diff --git a/DEPS b/DEPS index 939431a..a8ee76e 100644 --- a/DEPS +++ b/DEPS
@@ -241,7 +241,7 @@ # # CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-amd64-generic-chrome-skylab # CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-arm-generic-chrome-skylab - 'lacros_sdk_version': '15756.0.0', + 'lacros_sdk_version': '15763.0.0', # Generate location tag metadata to include in tests result data uploaded # to ResultDB. This isn't needed on some configs and the tool that generates @@ -306,11 +306,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'src_internal_revision': '8ca742cefe79b6c919d7f9a13a41e050a5ef62d1', + 'src_internal_revision': '40aab3e1c4517d57070812a86d5538d5809895a4', # 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': '59943f4e92b9728e8bac10903e195c8b9a037365', + 'skia_revision': '555cfc8d95c667b7d797914599f75124070b914c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -318,7 +318,7 @@ # 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': 'f431641a948660f5e1709aa7cd89b16ccf93f1de', + 'angle_revision': 'c603a4f199affd54b338ec1db405e01775c9c57e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -385,7 +385,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling chromium_variations # and whatever else without interference from each other. - 'chromium_variations_revision': '8460157bc5ad13094b0e93276c7387b47932195d', + 'chromium_variations_revision': 'ba4353a41f7f9074baa98a77f39e6be03bd26368', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. @@ -501,7 +501,7 @@ # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. - 'libcxx_revision': 'c51c9efb6c5a83e0e25c1e30864449d2beadd7a8', + 'libcxx_revision': '9d119c1f4a097b7d27210874f4eba3fc91a83a4e', # GN CIPD package version. 'gn_version': 'git_revision:a2e2717ea670249a34b0de4b3e54f268d320bdfa', @@ -825,12 +825,12 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '80915fa76a95b7fb3ba6db65df700a789109350f', + '401e3e3bf126ea139d5680c5a16e9e0fe51cd0c6', 'condition': 'checkout_android and checkout_src_internal', }, 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + '7854b9d90b9fb1e57c50e6f039bc44fa587a9eca', + 'url': Var('chromium_git') + '/website.git' + '@' + '324a451ec11c32fdfc9e57facb78dba9e1be4cce', }, 'src/ios/third_party/earl_grey2/src': { @@ -1162,7 +1162,7 @@ # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '0ab00d0ab4c48eb09ff9a359365c55528ef2bbb5', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '2569b035e6b1b0e6106a918833d8c53b70fd35db', 'condition': 'checkout_chromeos', }, @@ -1183,7 +1183,7 @@ # For Linux and Chromium OS. 'src/third_party/cros_system_api': { - 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'e5f61ee71226157479ebc9f10f5184af1c1b6ce6', + 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '84b44fd2f0decdc029779c1d12c0ed70a10c511e', 'condition': 'checkout_linux or checkout_chromeos', }, @@ -1197,7 +1197,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '74a6ca92bba677fc87328637bf573deb5944ac91', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '35696080284a2d59a8972ca27b509ebc1edc08ef', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1531,7 +1531,7 @@ }, 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + 'c35f3e9e3512d0012180ad8de8834d8813a80b73', + Var('chromium_git') + '/webm/libvpx.git' + '@' + '96b64eaac5adbac59e43e34d87af3ba0fb06bca6', 'src/third_party/libwebm/source': Var('chromium_git') + '/webm/libwebm.git' + '@' + 'e4fbea0c9751ae8aa86629b197a28d8276a2b0da', @@ -1663,7 +1663,7 @@ Var('pdfium_git') + '/pdfium.git' + '@' + Var('pdfium_revision'), 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '9b78d80da79be8d58590a2c686d66748161a77ff', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'b20333c6f8b603fc3bf842a272126d83403f201f', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '8ef97ff3b7332e38e61b347a2fbed425a4617151', @@ -1845,10 +1845,10 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'f4bf599a8b575df685c31d9c4729a70a04e377ed', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '6493b876ade082dc4e4d883691e8900d5b42f01c', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '3f04968bcc3bacf13aabf3c631a9459ffaddf262', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'cea1c0b9a91be940ec801ab84a7ca3b52e9fc930', + Var('webrtc_git') + '/src.git' + '@' + '9183fcdc5311f6b6236597ff725831686a34b8fa', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -1971,7 +1971,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': '0Pbp6aR5MNSOor-TyUr9HiQN6CEFRjxTD6LID3TZM6QC', + 'version': '_4_v2hcNrFaJAqsdEXUMKjlolHDyeBP34W5XglB6fdwC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -1982,7 +1982,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': '3As5TxenU3QWcTt0v-ps4C9SOGC8pOlLFCq5lCtnZNMC', + 'version': 'Ey5sw3T5RTqruQa6vb0qpa7FNew36roQ0d5L8JeOtbwC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -3995,7 +3995,7 @@ 'src/components/optimization_guide/internal': { 'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' + - 'b5dce536acaa9d9fedc1ea98b42586100f0e11c7', + '774f92f791e117e4cd26fa92d159d1d93fc4cfb6', 'condition': 'checkout_src_internal', }, @@ -4055,7 +4055,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - 'ee8bfecb9125511f41a7f526b5d1cd83157622f1', + '4bc68c8a54b6e0b2778a9779b5270fdaef88a30e', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index c7980532f..dea9873 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -989,7 +989,9 @@ r'services/network/web_transport\.cc', r'chrome/browser/ip_protection/.*', # Not an error in third_party folders. - _THIRD_PARTY_EXCEPT_BLINK + _THIRD_PARTY_EXCEPT_BLINK, + # //base/numerics can't use base or absl. + r'base/numerics/.*' ], ), BanRule( @@ -1212,7 +1214,12 @@ 'standard C++ casting when pointers are involved.', ), True, - [_THIRD_PARTY_EXCEPT_BLINK], # Don't warn in third_party folders. + [ + # Don't warn in third_party folders. + _THIRD_PARTY_EXCEPT_BLINK, + # //base/numerics can't use base or absl. + r'base/numerics/.*' + ], ), BanRule( r'/\bstd::(c8rtomb|mbrtoc8)\b', @@ -1798,6 +1805,17 @@ '^content/shell/browser/shell_content_browser_client.cc' ) ), + BanRule( + pattern = r'/absl::(optional|nullopt|make_optional|in_place|in_place_t)', + explanation = ( + 'Don\'t use `absl::optional`. Use `std::optional`.', + ), + # TODO(b/40288126): Enforce after completing the rewrite. + treat_as_error = False, + excluded_paths = [ + _THIRD_PARTY_EXCEPT_BLINK, + ] + ), ) _BANNED_MOJOM_PATTERNS : Sequence[BanRule] = (
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn index 198142ef..c720e4d 100644 --- a/android_webview/test/BUILD.gn +++ b/android_webview/test/BUILD.gn
@@ -98,6 +98,7 @@ "--browser-apk", "@WrappedPath(apks/SystemWebViewShell.apk)", ] + data = [ "//third_party/blink/web_tests/platform/webview/" ] data_deps = [ "//android_webview:system_webview_apk", "//android_webview/tools/system_webview_shell:system_webview_shell_layout_test_apk",
diff --git a/ash/accelerators/modifier_key_combo_recorder.cc b/ash/accelerators/modifier_key_combo_recorder.cc index 41bb2ed8..dc6f2ce 100644 --- a/ash/accelerators/modifier_key_combo_recorder.cc +++ b/ash/accelerators/modifier_key_combo_recorder.cc
@@ -68,7 +68,7 @@ uint32_t CalculateHash(AcceleratorKeyInputType key_type, uint32_t modifier_flags) { static_assert(sizeof(AcceleratorKeyInputType) <= sizeof(uint16_t)); - static_assert(static_cast<uint32_t>(ModifierFlag::kMaxValue) <= + static_assert(static_cast<uint32_t>(ModifierFlag::kMaxValue) < (sizeof(uint16_t) * 8)); return (modifier_flags << (sizeof(uint16_t) * 8)) + static_cast<uint16_t>(key_type); @@ -179,10 +179,15 @@ const uint32_t modifier_flags = GenerateModifierFlagsFromKeyEvent(key_event); const uint32_t hash = CalculateHash(type, modifier_flags); - // Do not emit the metric if its only an alpha or digit key pressed. + // True if Shift is the only modifier key present on the event. + const bool only_shift_present = + modifier_flags == GetModifierFlagFromModifier(Modifier::kShift); + + // Do not emit the metric if its only an alpha or digit key pressed (with or + // without Shift held). if ((type == AcceleratorKeyInputType::kAlpha || type == AcceleratorKeyInputType::kDigit) && - modifier_flags == 0) { + (modifier_flags == 0 || only_shift_present)) { return; }
diff --git a/ash/accelerators/modifier_key_combo_recorder_unittest.cc b/ash/accelerators/modifier_key_combo_recorder_unittest.cc index 8b1716c3c7..c55bc96 100644 --- a/ash/accelerators/modifier_key_combo_recorder_unittest.cc +++ b/ash/accelerators/modifier_key_combo_recorder_unittest.cc
@@ -113,6 +113,52 @@ "ChromeOS.Inputs.ModifierKeyCombo.Internal", expected_hash, 1); } +TEST_F(ModifierKeyComboRecorderTest, AlphaOrDigitKeysWithShift) { + ui::KeyboardDevice keyboard(1, ui::INPUT_DEVICE_INTERNAL, "Keyboard"); + ui::DeviceDataManagerTestApi().SetKeyboardDevices({keyboard}); + + ui::KeyboardCapability* keyboard_capability = + Shell::Get()->keyboard_capability(); + ui::KeyboardCapability::KeyboardInfo keyboard_info; + keyboard_info.device_type = + ui::KeyboardCapability::DeviceType::kDeviceInternalKeyboard; + keyboard_capability->DisableKeyboardInfoTrimmingForTesting(); + keyboard_capability->SetKeyboardInfoForTesting(keyboard, + std::move(keyboard_info)); + + ui::KeyEvent shift_c_event(ui::ET_KEY_PRESSED, ui::VKEY_C, ui::EF_SHIFT_DOWN); + shift_c_event.set_source_device_id(keyboard.id); + modifier_key_combo_recorder_->OnPrerewriteKeyInputEvent(shift_c_event); + // No metric should be recorded if the input was an alpha key + shift. + histogram_tester_->ExpectTotalCount( + "ChromeOS.Inputs.ModifierKeyCombo.Internal", 0); + + ui::KeyEvent shift_nine_event(ui::ET_KEY_PRESSED, ui::VKEY_9, + ui::EF_SHIFT_DOWN); + shift_nine_event.set_source_device_id(keyboard.id); + modifier_key_combo_recorder_->OnPrerewriteKeyInputEvent(shift_nine_event); + // No metric should be recorded if the input was a digit key + shift. + histogram_tester_->ExpectTotalCount( + "ChromeOS.Inputs.ModifierKeyCombo.Internal", 0); + + ui::KeyEvent ctrl_shift_c_event(ui::ET_KEY_PRESSED, ui::VKEY_C, + ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); + ctrl_shift_c_event.set_source_device_id(keyboard.id); + modifier_key_combo_recorder_->OnPrerewriteKeyInputEvent(ctrl_shift_c_event); + // ShiftLeft and ControlLeft are the default locations for these modifiers. + const uint32_t modifier_flag = + 1 << static_cast<uint32_t>(ModifierFlag::kShiftLeft) | + 1 << static_cast<uint32_t>(ModifierFlag::kControlLeft); + const uint32_t expected_hash = + static_cast<uint32_t>(AcceleratorKeyInputType::kAlpha) + + (modifier_flag << 16); + // Metric should be recorded if shift and another modifier are held. + histogram_tester_->ExpectTotalCount( + "ChromeOS.Inputs.ModifierKeyCombo.Internal", 1); + histogram_tester_->ExpectBucketCount( + "ChromeOS.Inputs.ModifierKeyCombo.Internal", expected_hash, 1); +} + class ModifierKeyComboRecorderParameterizedTest : public ModifierKeyComboRecorderTest, public testing::WithParamInterface<std::tuple<ui::KeyEvent, uint32_t>> {};
diff --git a/ash/game_dashboard/game_dashboard_main_menu_view.cc b/ash/game_dashboard/game_dashboard_main_menu_view.cc index bb5c380..d8cfe1ad 100644 --- a/ash/game_dashboard/game_dashboard_main_menu_view.cc +++ b/ash/game_dashboard/game_dashboard_main_menu_view.cc
@@ -70,8 +70,6 @@ constexpr int kCenterPadding = 8; // Main Menu fixed width. constexpr int kMainMenuFixedWidth = 416; -// Background radius. -constexpr float kBackgroundRadius = 12; // Corner radius for the detail row container. constexpr float kDetailRowCornerRadius = 16.0f; constexpr gfx::RoundedCornersF kGCDetailRowCorners = @@ -387,7 +385,6 @@ SetBorder(views::CreateRoundedRectBorder( /*thickness=*/1, kBubbleCornerRadius, cros_tokens::kCrosSysSystemHighlight1)); - set_shadow(views::BubbleBorder::Shadow::DIALOG_SHADOW); set_corner_radius(kBubbleCornerRadius); set_close_on_deactivate(true); set_internal_name("GameDashboardMainMenuView"); @@ -400,7 +397,8 @@ SetButtons(ui::DIALOG_BUTTON_NONE); SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kVertical, - gfx::Insets::VH(kPaddingHeight, kPaddingWidth), kCenterPadding)); + gfx::Insets::VH(kPaddingHeight, kPaddingWidth), + /*between_child_spacing=*/16)); AddShortcutTilesRow(); AddFeatureDetailsRows(); @@ -639,23 +637,26 @@ } void GameDashboardMainMenuView::AddUtilityClusterRow() { - views::BoxLayoutView* container = - AddChildView(std::make_unique<views::BoxLayoutView>()); - container->SetOrientation(views::BoxLayout::Orientation::kHorizontal); - container->SetBetweenChildSpacing(kCenterPadding); + auto* container = AddChildView(std::make_unique<views::View>()); + auto* layout = container->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kHorizontal, + /*inside_border_insets=*/gfx::Insets(), + /*between_child_spacing=*/16)); auto* feedback_button = - container->AddChildView(std::make_unique<views::LabelButton>( + container->AddChildView(std::make_unique<ash::PillButton>( base::BindRepeating( &GameDashboardMainMenuView::OnFeedbackButtonPressed, base::Unretained(this)), l10n_util::GetStringUTF16( IDS_ASH_GAME_DASHBOARD_SEND_FEEDBACK_TITLE))); - feedback_button->SetBackground(views::CreateThemedRoundedRectBackground( - cros_tokens::kCrosSysSystemOnBase, kBackgroundRadius)); feedback_button->SetID(VIEW_ID_GD_FEEDBACK_BUTTON); - feedback_button->SetImageLabelSpacing(kCenterPadding); - feedback_button->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT); + + // `feedback_button` should be left aligned. Help button and setting button + // should be right aligned. So add an empty view to fill the empty space. + auto* empty_view = container->AddChildView(std::make_unique<views::View>()); + layout->SetFlexForView(empty_view, /*flex=*/1); + container->AddChildView(CreateIconButton( base::BindRepeating(&GameDashboardMainMenuView::OnHelpButtonPressed, base::Unretained(this)),
diff --git a/ash/system/notification_center/message_view_factory.cc b/ash/system/notification_center/message_view_factory.cc index 858b986..d3606f0 100644 --- a/ash/system/notification_center/message_view_factory.cc +++ b/ash/system/notification_center/message_view_factory.cc
@@ -9,6 +9,7 @@ #include "ash/constants/ash_features.h" #include "ash/system/notification_center/views/ash_notification_view.h" +#include "ash/system/notification_center/views/conversation_notification_view.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "build/chromeos_buildflags.h" @@ -49,6 +50,8 @@ break; case message_center::NOTIFICATION_TYPE_CUSTOM: return GetCustomNotificationView(notification, shown_in_popup); + case message_center::NOTIFICATION_TYPE_CONVERSATION: + return std::make_unique<ConversationNotificationView>(notification); default: // If the caller asks for an unrecognized kind of view (entirely possible // if an application is running on an older version of this code that
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc index eef661a..69eb29a 100644 --- a/ash/wm/overview/overview_grid.cc +++ b/ash/wm/overview/overview_grid.cc
@@ -1820,9 +1820,12 @@ // Get the bounds of the item if there is a snapped window or a window // about to be snapped. If the height is less than that of the header, there // is nothing from the original window to be shown and nothing to be clipped. + // Floated windows doesn't need this special handling (see b/323136574). + auto* window = item->GetWindow(); + const bool is_floated = WindowState::Get(window)->IsFloated(); std::optional<gfx::RectF> split_view_bounds = GetSplitviewBoundsMaintainingAspectRatio(); - if (!split_view_bounds || + if (is_floated || !split_view_bounds || split_view_bounds->height() < kWindowMiniViewHeaderHeight) { item->set_unclipped_size(std::nullopt); return width; @@ -1832,10 +1835,10 @@ // split view bounds aspect ratio, and vertical clipping otherwise. const float aspect_ratio = target_size.width() / - (target_size.height() - - item->GetWindow()->GetProperty(aura::client::kTopViewInset)); + (target_size.height() - window->GetProperty(aura::client::kTopViewInset)); const float target_aspect_ratio = - split_view_bounds->width() / split_view_bounds->height(); + static_cast<float>(split_view_bounds->width()) / + split_view_bounds->height(); const bool clip_horizontally = aspect_ratio > target_aspect_ratio; const int window_height = height - kWindowMiniViewHeaderHeight; gfx::Size unclipped_size; @@ -1851,8 +1854,9 @@ // Find the width so that it matches height and matches the aspect ratio of // |split_view_bounds|. - width = split_view_bounds->width() * window_height / - split_view_bounds->height(); + // TODO(sammiequon): Check to see if we can unify this with the `width` + // calculation in the above branch where we do the clamp and the max. + width = target_aspect_ratio * window_height; // The unclipped height is the height which matches |width| but keeps the // aspect ratio of |target_bounds|. Clipping takes the overview header into // account, so add that back in.
diff --git a/ash/wm/overview/overview_item_base.h b/ash/wm/overview/overview_item_base.h index 45551b5..36db5eb 100644 --- a/ash/wm/overview/overview_item_base.h +++ b/ash/wm/overview/overview_item_base.h
@@ -315,6 +315,10 @@ return cannot_snap_widget_.get(); } + const std::optional<gfx::Size>& unclipped_size_for_testing() const { + return unclipped_size_; + } + protected: // Returns the widget init params needed to create the `item_widget_`. views::Widget::InitParams CreateOverviewItemWidgetParams(
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc index 05f4da03..9bc39010b 100644 --- a/ash/wm/overview/overview_session_unittest.cc +++ b/ash/wm/overview/overview_session_unittest.cc
@@ -48,6 +48,7 @@ #include "ash/wm/desks/legacy_desk_bar_view.h" #include "ash/wm/desks/templates/saved_desk_save_desk_button.h" #include "ash/wm/desks/templates/saved_desk_util.h" +#include "ash/wm/float/float_controller.h" #include "ash/wm/gestures/back_gesture/back_gesture_event_handler.h" #include "ash/wm/gestures/wm_gesture_handler.h" #include "ash/wm/mru_window_tracker.h" @@ -6944,6 +6945,31 @@ EXPECT_FALSE(GetOverviewController()->InOverviewSession()); } +// Regression test for http://b/323136574, where a floated window should not +// have an unclipped size when it's in a partial overview session. +TEST_F(SplitViewOverviewSessionTest, FloatedWindowsHaveNoUnclippedSize) { + std::unique_ptr<aura::Window> window1 = CreateAppWindow(); + std::unique_ptr<aura::Window> window2 = CreateAppWindow(); + + // Float `window1` and then snap `window2`. A partial overview session should + // start. + Shell::Get()->float_controller()->ToggleFloat(window1.get()); + EXPECT_TRUE(WindowState::Get(window1.get())->IsFloated()); + + const WindowSnapWMEvent event( + WM_EVENT_CYCLE_SNAP_SECONDARY, + WindowSnapActionSource::kKeyboardShortcutToSnap); + auto* window2_state = WindowState::Get(window2.get()); + window2_state->OnWMEvent(&event); + EXPECT_TRUE(window2_state->IsSnapped()); + + ASSERT_TRUE(GetOverviewController()->InOverviewSession()); + auto* window1_item = GetOverviewItemForWindow(window1.get()); + ASSERT_TRUE(window1_item); + + EXPECT_FALSE(window1_item->unclipped_size_for_testing()); +} + // Verify the correct behavior when dragging windows in overview mode. TEST_F(SplitViewOverviewSessionTest, OverviewDragControllerBehavior) { ui::GestureConfiguration* gesture_config =
diff --git a/ash/wm/window_restore/pine_contents_view.cc b/ash/wm/window_restore/pine_contents_view.cc index 59e113b..b9b5d2e 100644 --- a/ash/wm/window_restore/pine_contents_view.cc +++ b/ash/wm/window_restore/pine_contents_view.cc
@@ -64,7 +64,8 @@ constexpr int kOverflowMinThreshold = kMaxItems - 1; constexpr int kOverflowMaxElements = 7; constexpr int kOverflowMaxThreshold = kOverflowMaxElements - 1; -constexpr int kOverflowTablePadding = 2; +constexpr int kOverflowTriangleElements = 6; +constexpr int kOverflowIconSpacing = 2; constexpr int kOverflowTableSize = 20; constexpr int kOverflowBackgroundRounding = 20; constexpr int kOverflowCountBackgroundRounding = 9; @@ -206,6 +207,8 @@ // An alternative to `PineItemView` when there are more than four windows in // `apps` and the remaining information needs to be condensed. +// TODO(hewer): Fix the styling to make the background smaller than the +// contents. class PineItemsOverflowView : public views::BoxLayoutView { public: METADATA_HEADER(PineItemsOverflowView); @@ -213,8 +216,6 @@ explicit PineItemsOverflowView(const PineContentsView::AppsData& apps) { const int elements = static_cast<int>(apps.size()); CHECK_GE(elements, kOverflowMinElements); - // TODO(http://b/322361588): Remove after the 3-window case is added. - CHECK_NE(elements, 3); // TODO(hewer): Fix margins so the icons and text are aligned with // `PineItemView` elements. @@ -222,86 +223,92 @@ SetCrossAxisAlignment(views::BoxLayout::CrossAxisAlignment::kCenter); SetOrientation(views::BoxLayout::Orientation::kHorizontal); - // TODO(hewer): Fix the styling to make the background smaller than the - // contents. - views::Builder<views::TableLayoutView> table_builder; - table_builder - .SetBackground(views::CreateRoundedRectBackground( - SK_ColorLTGRAY, kOverflowBackgroundRounding)) - .AddColumn( - views::LayoutAlignment::kCenter, views::LayoutAlignment::kCenter, - views::TableLayout::kFixedSize, - views::TableLayout::ColumnSize::kFixed, kOverflowTableSize, 0) - .AddPaddingColumn(views::TableLayout::kFixedSize, kOverflowTablePadding) - .AddColumn( - views::LayoutAlignment::kCenter, views::LayoutAlignment::kCenter, - views::TableLayout::kFixedSize, - views::TableLayout::ColumnSize::kFixed, kOverflowTableSize, 0); - if (elements >= kOverflowMaxElements) { - // Create a 2x2 table view to display the icons for 4 or more windows, or - // the count of the remaining windows, rather than a single icon. - table_builder - .AddRows(1, views::TableLayout::kFixedSize, kOverflowTableSize) - .AddPaddingRow(views::TableLayout::kFixedSize, kOverflowTablePadding) - .AddRows(1, views::TableLayout::kFixedSize, kOverflowTableSize); - } else if (elements == kOverflowMinElements) { - // Create a 1x2 table view to display the icons for 2 windows, centered - // vertically. - table_builder - .AddPaddingRow(views::TableLayout::kFixedSize, - kOverflowTwoWindowPadding) - .AddRows(1, views::TableLayout::kFixedSize, kOverflowTableSize) - .AddPaddingRow(views::TableLayout::kFixedSize, - kOverflowTwoWindowPadding); - } - views::TableLayoutView* table_layout_view = - AddChildView(std::move(table_builder).Build()); - // TODO(sammiequon): Handle case where the app is not ready or installed. auto* delegate = Shell::Get()->saved_desk_delegate(); - // Add the overflow apps to the table. - // TODO(http://b/322361588): Handle case where there are 3 overflow windows. - for (int i = kOverflowMinThreshold; i < elements; ++i) { - // If there are 5 or more overflow windows, save the last spot in the - // table to count the remaining windows. - if (elements > kOverflowMaxElements && i >= kOverflowMaxThreshold) { - views::Label* count_label; - table_layout_view->AddChildView( - views::Builder<views::Label>() - .CopyAddressTo(&count_label) - // TODO(hewer): Cut off the maximum number of digits to display. - .SetText(base::FormatNumber(elements - kOverflowMaxThreshold)) - .SetPreferredSize(kOverflowCountPreferredSize) - .SetEnabledColor(cros_tokens::kCrosSysOnPrimaryContainer) - .SetBackground(views::CreateThemedRoundedRectBackground( - cros_tokens::kCrosSysPrimaryContainer, - kOverflowCountBackgroundRounding)) + // TODO(http://b/324318784): Clean up "table" usage in comments when + // BoxLayout is implemented. + // If we have three overflow elements (six windows total), we need to make a + // special view to handle the triangular shape. Otherwise, we will have some + // form of a table view with one or two rows. + if (elements == kOverflowTriangleElements) { + // Create a triangular container, and pass the child views so we can fill + // them with icons later. + views::BoxLayoutView* top_row_view = nullptr; + views::BoxLayoutView* bottom_row_view = nullptr; + AddChildView(CreateBaseTriangleView(&top_row_view, &bottom_row_view)); + CHECK(top_row_view); + CHECK(bottom_row_view); + + // Add the overflow apps to the table. + for (int i = kOverflowMinThreshold; i < elements; ++i) { + // Add the image view to the table (the top view has already been + // added). + views::BoxLayoutView* row_view = + i == kOverflowMinThreshold ? top_row_view : bottom_row_view; + views::ImageView* image_view = row_view->AddChildView( + views::Builder<views::ImageView>() + .SetImageSize(kOverflowIconPreferredSize) + .SetPreferredSize(kOverflowIconPreferredSize) .Build()); - TypographyProvider::Get()->StyleLabel(TypographyToken::kCrosLabel2, - *count_label); - break; + + // Insert `image_view` into a map so it can be retrieved in a callback. + image_view_map_[i] = image_view; + + // The callback may be called synchronously. + const auto& [app_id, favicons] = apps[i]; + delegate->GetIconForAppId( + app_id, kAppIdImageSize, + base::BindOnce(&PineItemsOverflowView::SetIconForIndex, + weak_ptr_factory_.GetWeakPtr(), i)); } + } else { + views::TableLayoutView* table_layout_view = + AddChildView(CreateBaseTableView(elements)); - const auto& [app_id, favicons] = apps[i]; + // Add the overflow apps to the table. + for (int i = kOverflowMinThreshold; i < elements; ++i) { + // If there are 5 or more overflow windows, save the last spot in the + // table to count the remaining windows. + if (elements > kOverflowMaxElements && i >= kOverflowMaxThreshold) { + views::Label* count_label; + table_layout_view->AddChildView( + views::Builder<views::Label>() + .CopyAddressTo(&count_label) + // TODO(hewer): Cut off the maximum number of digits to + // display. + .SetText(base::FormatNumber(elements - kOverflowMaxThreshold)) + .SetPreferredSize(kOverflowCountPreferredSize) + .SetEnabledColor(cros_tokens::kCrosSysOnPrimaryContainer) + .SetBackground(views::CreateThemedRoundedRectBackground( + cros_tokens::kCrosSysPrimaryContainer, + kOverflowCountBackgroundRounding)) + .Build()); + TypographyProvider::Get()->StyleLabel(TypographyToken::kCrosLabel2, + *count_label); + break; + } - // Add the icon to the table. - views::ImageView* image_view = table_layout_view->AddChildView( - views::Builder<views::ImageView>() - .SetImageSize(kOverflowIconPreferredSize) - .SetPreferredSize(kOverflowIconPreferredSize) - .Build()); + // Add the image view to the table. + views::ImageView* image_view = table_layout_view->AddChildView( + views::Builder<views::ImageView>() + .SetImageSize(kOverflowIconPreferredSize) + .SetPreferredSize(kOverflowIconPreferredSize) + .Build()); - // Insert `image_view` into a map so it can be retrieved in a callback. - image_view_map_[i] = image_view; + // Insert `image_view` into a map so it can be retrieved in a callback. + image_view_map_[i] = image_view; - // The callback may be called synchronously. - delegate->GetIconForAppId( - app_id, kAppIdImageSize, - base::BindOnce(&PineItemsOverflowView::SetIconForIndex, - weak_ptr_factory_.GetWeakPtr(), i)); + // The callback may be called synchronously. + const auto& [app_id, favicons] = apps[i]; + delegate->GetIconForAppId( + app_id, kAppIdImageSize, + base::BindOnce(&PineItemsOverflowView::SetIconForIndex, + weak_ptr_factory_.GetWeakPtr(), i)); + } } + // Add a text label displaying the count of the remaining windows. views::Label* remaining_windows_label; AddChildView(views::Builder<views::Label>() .CopyAddressTo(&remaining_windows_label) @@ -328,6 +335,76 @@ } private: + // TODO(http://b/324318784): Unify the CreateBase*View() functions to both use + // BoxLayoutView rather than TableLayoutView. + // Creates a triangular view to populate with window favicons (one on the + // top, two on the bottom). + std::unique_ptr<views::BoxLayoutView> CreateBaseTriangleView( + views::BoxLayoutView** top_row_view, + views::BoxLayoutView** bottom_row_view) { + return views::Builder<views::BoxLayoutView>() + .SetBackground(views::CreateRoundedRectBackground( + SK_ColorLTGRAY, kOverflowBackgroundRounding)) + .SetOrientation(views::BoxLayout::Orientation::kVertical) + .SetCrossAxisAlignment(views::BoxLayout::CrossAxisAlignment::kCenter) + .AddChildren( + views::Builder<views::BoxLayoutView>() + .CopyAddressTo(top_row_view) + .SetOrientation(views::BoxLayout::Orientation::kHorizontal) + .SetMainAxisAlignment( + views::BoxLayout::MainAxisAlignment::kCenter) + .SetCrossAxisAlignment( + views::BoxLayout::CrossAxisAlignment::kCenter) + .SetBetweenChildSpacing(kOverflowIconSpacing), + views::Builder<views::BoxLayoutView>() + .CopyAddressTo(bottom_row_view) + .SetOrientation(views::BoxLayout::Orientation::kHorizontal) + .SetMainAxisAlignment( + views::BoxLayout::MainAxisAlignment::kCenter) + .SetCrossAxisAlignment( + views::BoxLayout::CrossAxisAlignment::kCenter) + .SetBetweenChildSpacing(kOverflowIconSpacing)) + .Build(); + } + + // Creates either a one-row or two-row table view to populate with window + // favicons. + std::unique_ptr<views::TableLayoutView> CreateBaseTableView( + const int elements) { + views::Builder<views::TableLayoutView> table_builder; + table_builder + .SetBackground(views::CreateRoundedRectBackground( + SK_ColorLTGRAY, kOverflowBackgroundRounding)) + .AddColumn( + views::LayoutAlignment::kCenter, views::LayoutAlignment::kCenter, + views::TableLayout::kFixedSize, + views::TableLayout::ColumnSize::kFixed, kOverflowTableSize, 0) + .AddPaddingColumn(views::TableLayout::kFixedSize, kOverflowIconSpacing) + .AddColumn( + views::LayoutAlignment::kCenter, views::LayoutAlignment::kCenter, + views::TableLayout::kFixedSize, + views::TableLayout::ColumnSize::kFixed, kOverflowTableSize, 0); + + if (elements >= kOverflowMaxElements) { + // Create a 2x2 table view to display the icons for 4 or more windows, + // or the count of the remaining windows, rather than a single icon. + table_builder + .AddRows(1, views::TableLayout::kFixedSize, kOverflowTableSize) + .AddPaddingRow(views::TableLayout::kFixedSize, kOverflowIconSpacing) + .AddRows(1, views::TableLayout::kFixedSize, kOverflowTableSize); + } else if (elements == kOverflowMinElements) { + // Create a 1x2 table view to display the icons for 2 windows, centered + // vertically. + table_builder + .AddPaddingRow(views::TableLayout::kFixedSize, + kOverflowTwoWindowPadding) + .AddRows(1, views::TableLayout::kFixedSize, kOverflowTableSize) + .AddPaddingRow(views::TableLayout::kFixedSize, + kOverflowTwoWindowPadding); + } + return std::move(table_builder).Build(); + } + base::flat_map<int, views::ImageView*> image_view_map_; base::WeakPtrFactory<PineItemsOverflowView> weak_ptr_factory_{this}; }; @@ -335,9 +412,9 @@ BEGIN_METADATA(PineItemsOverflowView, views::BoxLayoutView) END_METADATA -// The right side contents (in LTR) of the `PineContentsView`. It is a vertical -// list of `PineItemView`, with each view representing an app. Shows a maximum -// of `kMaxItems` items. +// The right side contents (in LTR) of the `PineContentsView`. It is a +// vertical list of `PineItemView`, with each view representing an app. Shows +// a maximum of `kMaxItems` items. class PineItemsContainerView : public views::BoxLayoutView { public: METADATA_HEADER(PineItemsContainerView); @@ -369,8 +446,8 @@ } std::string title; - // `cache` might be null in a test environment. In that case, we will use - // an empty title. + // `cache` might be null in a test environment. In that case, we will + // use an empty title. if (cache) { cache->ForOneApp(app_id, [&title](const apps::AppUpdate& update) { title = update.Name(); @@ -479,6 +556,8 @@ {"odknhmnlageboeamepcngndbggdpaobj", {}}, // Settings {"fkiggjmkendpmbegkagpmagjepfkpmeb", {}}, // Files {"oabkinaljpjeilageghcdlnekhphhphl", {}}, // Calculator + {"mgndgikekgjfcpckkfioiadnlibdjbkf", // Chrome + {"https://www.google.com/maps/"}}, }; PineItemsContainerView* container_view = AddChildView( std::make_unique<PineItemsContainerView>(kTestingAppsData));
diff --git a/base/BUILD.gn b/base/BUILD.gn index ced73d45..6cd10b8 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -287,7 +287,6 @@ "containers/lru_cache.h", "containers/map_util.h", "containers/small_map.h", - "containers/span.h", "containers/stack.h", "containers/unique_ptr_adapters.h", "containers/util.h", @@ -3529,6 +3528,7 @@ ":path_service_unittest", ":sanitizer_buildflags", "//base/allocator:buildflags", + "//base/numerics:unittests", "//base/test:native_library_test_utils", "//base/test:proto_test_support", "//base/test:run_all_unittests",
diff --git a/base/android/callback_android.cc b/base/android/callback_android.cc index 9e748ae..b33acbb 100644 --- a/base/android/callback_android.cc +++ b/base/android/callback_android.cc
@@ -10,6 +10,7 @@ #include "base/android/scoped_java_ref.h" #include "base/base_jni/Callback_jni.h" #include "base/time/time.h" +#include "base/types/optional_ref.h" namespace base { namespace android { @@ -44,6 +45,20 @@ Java_Helper_onObjectResultFromNative(env, callback, java_string); } +void RunOptionalStringCallbackAndroid( + const JavaRef<jobject>& callback, + base::optional_ref<const std::string> optional_string_arg) { + JNIEnv* env = AttachCurrentThread(); + if (optional_string_arg.has_value()) { + Java_Helper_onOptionalStringResultFromNative( + env, callback, true, + ConvertUTF8ToJavaString(env, optional_string_arg.value())); + } else { + Java_Helper_onOptionalStringResultFromNative( + env, callback, false, ConvertUTF8ToJavaString(env, std::string())); + } +} + void RunByteArrayCallbackAndroid(const JavaRef<jobject>& callback, const std::vector<uint8_t>& arg) { JNIEnv* env = AttachCurrentThread();
diff --git a/base/android/callback_android.h b/base/android/callback_android.h index fa2420c..1165d0f5 100644 --- a/base/android/callback_android.h +++ b/base/android/callback_android.h
@@ -12,6 +12,7 @@ #include "base/android/scoped_java_ref.h" #include "base/base_export.h" #include "base/time/time.h" +#include "base/types/optional_ref.h" // Provides helper utility methods that run the given callback with the // specified argument. @@ -36,6 +37,10 @@ void BASE_EXPORT RunStringCallbackAndroid(const JavaRef<jobject>& callback, const std::string& arg); +void BASE_EXPORT RunOptionalStringCallbackAndroid( + const JavaRef<jobject>& callback, + base::optional_ref<const std::string> optional_string_arg); + void BASE_EXPORT RunByteArrayCallbackAndroid(const JavaRef<jobject>& callback, const std::vector<uint8_t>& arg);
diff --git a/base/android/java/src/org/chromium/base/Callback.java b/base/android/java/src/org/chromium/base/Callback.java index 4a9fa41..8a8bbce 100644 --- a/base/android/java/src/org/chromium/base/Callback.java +++ b/base/android/java/src/org/chromium/base/Callback.java
@@ -8,6 +8,8 @@ import org.jni_zero.CalledByNative; +import java.util.Optional; + /** * A simple single-argument callback to handle the result of a computation. * @@ -55,6 +57,13 @@ @SuppressWarnings("unchecked") @CalledByNative("Helper") + static void onOptionalStringResultFromNative( + Callback<Optional<String>> callback, boolean hasValue, String result) { + callback.onResult(hasValue ? Optional.of(result) : Optional.empty()); + } + + @SuppressWarnings("unchecked") + @CalledByNative("Helper") static void onBooleanResultFromNative(Callback callback, boolean result) { callback.onResult(Boolean.valueOf(result)); }
diff --git a/base/android/proguard/chromium_code.flags b/base/android/proguard/chromium_code.flags index 865f6ef7..6393108 100644 --- a/base/android/proguard/chromium_code.flags +++ b/base/android/proguard/chromium_code.flags
@@ -4,18 +4,9 @@ # Contains flags that can be safely shared with Cronet, and thus would be # appropriate for third-party apps to include. -# -# IMPORTANT: MAKE SURE ALL RULES IN THIS FILE ARE ADEQUATELY SCOPED TO ONLY -# AFFECT CHROMIUM CODE (typically that means the rule should have a restriction -# on something under `org.chromium`). These rules are shipped in Cronet which is -# a library used by a variety of downstream apps. ProGuard operates at the app -# level, not the library level. It doesn't automatically scope rules shipped -# in libraries. In other words: when downstream apps run ProGuard, these rules -# will be applied to their entire app. It is our responsibility to ensure the -# rules we ship in this way don't end up affecting code that is not ours. # Allow unused native methods to be removed, but prevent renaming on those that are kept. --keepclasseswithmembernames,includedescriptorclasses,allowaccessmodification class !cr_allowunused,org.chromium.base.library_loader.LinkerJni { +-keepclasseswithmembernames,includedescriptorclasses,allowaccessmodification class !cr_allowunused,** { native <methods>; }
diff --git a/base/big_endian.cc b/base/big_endian.cc index fe5ff2c..2dd7cfb 100644 --- a/base/big_endian.cc +++ b/base/big_endian.cc
@@ -6,6 +6,7 @@ #include <string.h> +#include "base/numerics/byte_conversions.h" #include "base/numerics/checked_math.h" #include "base/strings/string_piece.h" @@ -26,82 +27,98 @@ : ptr_(buf.data()), end_(buf.data() + buf.size()) {} bool BigEndianReader::Skip(size_t len) { - if (len > remaining()) + if (len > remaining()) { return false; + } ptr_ += len; return true; } bool BigEndianReader::ReadBytes(void* out, size_t len) { - if (len > remaining()) + if (len > remaining()) { return false; + } memcpy(out, ptr_, len); ptr_ += len; return true; } bool BigEndianReader::ReadPiece(base::StringPiece* out, size_t len) { - if (len > remaining()) + if (len > remaining()) { return false; + } *out = base::StringPiece(reinterpret_cast<const char*>(ptr_), len); ptr_ += len; return true; } bool BigEndianReader::ReadSpan(base::span<const uint8_t>* out, size_t len) { - if (len > remaining()) + if (len > remaining()) { return false; + } *out = base::make_span(ptr_, len); ptr_ += len; return true; } -template<typename T> -bool BigEndianReader::Read(T* value) { - if (sizeof(T) > remaining()) - return false; - ReadBigEndian<T>(ptr_, value); - ptr_ += sizeof(T); - return true; -} - bool BigEndianReader::ReadU8(uint8_t* value) { - return Read(value); + std::optional<span<const uint8_t, 1u>> bytes = ReadFixedSpan<1u>(); + if (!bytes.has_value()) { + return false; + } + *value = numerics::U8FromBigEndian(*bytes); + return true; } bool BigEndianReader::ReadU16(uint16_t* value) { - return Read(value); -} - -bool BigEndianReader::ReadU32(uint32_t* value) { - return Read(value); -} - -bool BigEndianReader::ReadU64(uint64_t* value) { - return Read(value); -} - -template <typename T> -bool BigEndianReader::ReadLengthPrefixed(base::StringPiece* out) { - T t_len; - if (!Read(&t_len)) - return false; - size_t len = strict_cast<size_t>(t_len); - const uint8_t* original_ptr = ptr_; - if (!Skip(len)) { - ptr_ -= sizeof(T); + std::optional<span<const uint8_t, 2u>> bytes = ReadFixedSpan<2u>(); + if (!bytes.has_value()) { return false; } - *out = base::StringPiece(reinterpret_cast<const char*>(original_ptr), len); + *value = numerics::U16FromBigEndian(*bytes); return true; } -bool BigEndianReader::ReadU8LengthPrefixed(base::StringPiece* out) { - return ReadLengthPrefixed<uint8_t>(out); +bool BigEndianReader::ReadU32(uint32_t* value) { + std::optional<span<const uint8_t, 4u>> bytes = ReadFixedSpan<4u>(); + if (!bytes.has_value()) { + return false; + } + *value = numerics::U32FromBigEndian(*bytes); + return true; } -bool BigEndianReader::ReadU16LengthPrefixed(base::StringPiece* out) { - return ReadLengthPrefixed<uint16_t>(out); +bool BigEndianReader::ReadU64(uint64_t* value) { + std::optional<span<const uint8_t, 8u>> bytes = ReadFixedSpan<8u>(); + if (!bytes.has_value()) { + return false; + } + *value = numerics::U64FromBigEndian(*bytes); + return true; +} + +bool BigEndianReader::ReadU8LengthPrefixed(std::string_view* out) { + uint8_t len; + if (!ReadU8(&len)) { + return false; + } + const bool ok = ReadPiece(out, len); + if (!ok) { + ptr_ -= 1u; // Undo the ReadU8. + } + return ok; +} + +bool BigEndianReader::ReadU16LengthPrefixed(std::string_view* out) { + uint16_t len; + if (!ReadU16(&len)) { + return false; + } + const bool ok = ReadPiece(out, len); + if (!ok) { + ptr_ -= 2u; // Undo the ReadU16. + } + return ok; } BigEndianWriter::BigEndianWriter(char* buf, size_t len) @@ -111,24 +128,27 @@ } bool BigEndianWriter::Skip(size_t len) { - if (len > remaining()) + if (len > remaining()) { return false; + } ptr_ += len; return true; } bool BigEndianWriter::WriteBytes(const void* buf, size_t len) { - if (len > remaining()) + if (len > remaining()) { return false; + } memcpy(ptr_, buf, len); ptr_ += len; return true; } -template<typename T> +template <typename T> bool BigEndianWriter::Write(T value) { - if (sizeof(T) > remaining()) + if (sizeof(T) > remaining()) { return false; + } WriteBigEndian<T>(ptr_, value); ptr_ += sizeof(T); return true;
diff --git a/base/big_endian.h b/base/big_endian.h index 37e794738..98edea5 100644 --- a/base/big_endian.h +++ b/base/big_endian.h
@@ -57,19 +57,22 @@ // NOTE(szym): glibc dns-canon.c use ntohs(*(uint16_t*)ptr) which is // potentially unaligned. // This would cause SIGBUS on ARMv5 or earlier and ARMv6-M. +// +// DEPRECATED: Use base::numerics::*FromBeBytes to convert big-endian byte +// encoding to primitives. template <typename T> inline void ReadBigEndian(const uint8_t buf[], T* out) { static_assert(std::is_integral_v<T>, "T has to be an integral type."); // Make an unsigned version of the output type to make shift possible // without UB. - typename std::make_unsigned<T>::type raw; + std::make_unsigned_t<T> raw; memcpy(&raw, buf, sizeof(T)); *out = static_cast<T>(internal::ByteSwapIfLittleEndian(raw)); } // Write an integer (signed or unsigned) |val| to |buf| in Big Endian order. // Note: this loop is unrolled with -O1 and above. -template<typename T> +template <typename T> inline void WriteBigEndian(char buf[], T val) { static_assert(std::is_integral_v<T>, "T has to be an integral type."); const auto unsigned_val = @@ -107,6 +110,19 @@ bool ReadPiece(base::StringPiece* out, size_t len); bool ReadSpan(base::span<const uint8_t>* out, size_t len); + // Reads `N` bytes and returns them as a span, or returns nullopt if there are + // not `N` bytes remaining in the buffer. + template <size_t N> + std::optional<span<const uint8_t, N>> ReadFixedSpan() { + std::optional<span<const uint8_t, N>> out; + if (remaining() < N) { + return out; + } + out.emplace(ptr_, N); + ptr_ += N; + return out; + } + bool ReadU8(uint8_t* value); bool ReadU16(uint16_t* value); bool ReadU32(uint32_t* value); @@ -127,12 +143,6 @@ bool ReadU16LengthPrefixed(base::StringPiece* out); private: - // Hidden to promote type safety. - template<typename T> - bool Read(T* v); - template <typename T> - bool ReadLengthPrefixed(base::StringPiece* out); - const uint8_t* ptr_; const uint8_t* end_; }; @@ -155,7 +165,7 @@ private: // Hidden to promote type safety. - template<typename T> + template <typename T> bool Write(T v); raw_ptr<char, DanglingUntriaged | AllowPtrArithmetic> ptr_;
diff --git a/base/memory/weak_ptr.h b/base/memory/weak_ptr.h index 4211c91..17f9ca6 100644 --- a/base/memory/weak_ptr.h +++ b/base/memory/weak_ptr.h
@@ -84,7 +84,13 @@ #include "base/memory/safe_ref_traits.h" #include "base/sequence_checker.h" #include "base/synchronization/atomic_flag.h" -#include "base/types/pass_key.h" + +namespace performance_manager { +class FrameNodeImpl; +class PageNodeImpl; +class ProcessNodeImpl; +class WorkerNodeImpl; +} // namespace performance_manager namespace base { @@ -371,6 +377,25 @@ }; } // namespace internal +namespace subtle { + +// Restricts access to WeakPtrFactory::BindToCurrentSequence() to authorized +// callers. +class BASE_EXPORT BindWeakPtrFactoryPassKey { + private: + // Avoid =default to disallow creation by uniform initialization. + BindWeakPtrFactoryPassKey() {} + + friend class BindWeakPtrFactoryForTesting; + friend class performance_manager::FrameNodeImpl; + friend class performance_manager::PageNodeImpl; + friend class performance_manager::ProcessNodeImpl; + friend class performance_manager::WorkerNodeImpl; + friend class sequence_manager::internal::TaskQueueImpl; +}; + +} // namespace subtle + // A class may be composed of a WeakPtrFactory and thereby // control how it exposes weak pointers to itself. This is helpful if you only // need weak pointers within the implementation of a class. This class is also @@ -433,11 +458,10 @@ return weak_reference_owner_.HasRefs(); } - // Rebind the factory to the current sequence. This allows creating a task - // queue and associated weak pointers on a different thread from the one they - // are used on. - void BindToCurrentSequence( - PassKey<sequence_manager::internal::TaskQueueImpl>) { + // Rebind the factory to the current sequence. This allows creating an object + // and associated weak pointers on a different thread from the one they are + // used on. + void BindToCurrentSequence(subtle::BindWeakPtrFactoryPassKey) { weak_reference_owner_.BindToCurrentSequence(); } };
diff --git a/base/memory/weak_ptr_nocompile.nc b/base/memory/weak_ptr_nocompile.nc index 02aebc03..1659369 100644 --- a/base/memory/weak_ptr_nocompile.nc +++ b/base/memory/weak_ptr_nocompile.nc
@@ -112,4 +112,11 @@ } } +void UnauthorizedBindToCurrentSequenceDisallowed() { + Unrelated unrelated; + WeakPtrFactory<Unrelated> factory(&unrelated); + factory.BindToCurrentSequence( + subtle::BindWeakPtrFactoryPassKey()); // expected-error {{calling a private constructor of class 'base::subtle::BindWeakPtrFactoryPassKey'}} +} + } // namespace base
diff --git a/base/memory/weak_ptr_unittest.cc b/base/memory/weak_ptr_unittest.cc index b8906cf8..02a4477 100644 --- a/base/memory/weak_ptr_unittest.cc +++ b/base/memory/weak_ptr_unittest.cc
@@ -18,6 +18,19 @@ #include "testing/gtest/include/gtest/gtest.h" namespace base { + +namespace subtle { + +class BindWeakPtrFactoryForTesting { + public: + template <typename T> + static void BindToCurrentSequence(WeakPtrFactory<T>& factory) { + factory.BindToCurrentSequence(BindWeakPtrFactoryPassKey()); + } +}; + +} // namespace subtle + namespace { WeakPtr<int> PassThru(WeakPtr<int> ptr) { @@ -156,6 +169,15 @@ return result; } + void BindToCurrentSequence(TargetWithFactory* target_with_factory) { + WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + task_runner()->PostTask( + FROM_HERE, base::BindOnce(&BackgroundThread::DoBindToCurrentSequence, + target_with_factory, &completion)); + completion.Wait(); + } + protected: static void DoCreateArrowFromArrow(Arrow** arrow, const Arrow* other, @@ -208,6 +230,13 @@ delete object; completion->Signal(); } + + static void DoBindToCurrentSequence(TargetWithFactory* target_with_factory, + WaitableEvent* completion) { + subtle::BindWeakPtrFactoryForTesting::BindToCurrentSequence( + target_with_factory->factory); + completion->Signal(); + } }; } // namespace @@ -771,6 +800,27 @@ EXPECT_EQ(test_struct.member, 1); } +TEST(WeakPtrDeathTest, BindToCurrentSequence) { + BackgroundThread background; + background.Start(); + + TargetWithFactory target_with_factory; + Arrow arrow{ + .target = target_with_factory.factory.GetWeakPtr(), + }; + + // WeakPtr can be accessed on main thread. + EXPECT_TRUE(arrow.target.get()); + + background.BindToCurrentSequence(&target_with_factory); + + // Now WeakPtr can be accessed on background thread. + EXPECT_TRUE(background.DeRef(&arrow)); + + // WeakPtr can no longer be accessed on main thread. + EXPECT_DCHECK_DEATH(arrow.target.get()); +} + TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) { // The default style "fast" does not support multi-threaded tests // (introduces deadlock on Linux).
diff --git a/base/numerics/BUILD.gn b/base/numerics/BUILD.gn index e6f2215..b7d8f308 100644 --- a/base/numerics/BUILD.gn +++ b/base/numerics/BUILD.gn
@@ -1,4 +1,4 @@ -# Copyright 2017 The Chromium Authors +# Copyright 2024 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -9,6 +9,7 @@ source_set("base_numerics") { visibility = [ "//base/*" ] sources = [ + "basic_ops_impl.h", "checked_math_impl.h", "clamped_math_impl.h", "safe_conversions_arm_impl.h", @@ -18,6 +19,7 @@ "safe_math_shared_impl.h", ] public = [ + "byte_conversions.h", "checked_math.h", "clamped_math.h", "math_constants.h", @@ -28,3 +30,13 @@ "wrapping_math.h", ] } + +source_set("unittests") { + testonly = true + visibility = [ "//base/*" ] + sources = [ "byte_conversions_unittest.cc" ] + deps = [ + "//base/numerics:base_numerics", + "//testing/gtest", + ] +}
diff --git a/base/numerics/basic_ops_impl.h b/base/numerics/basic_ops_impl.h new file mode 100644 index 0000000..e56e12c --- /dev/null +++ b/base/numerics/basic_ops_impl.h
@@ -0,0 +1,110 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_NUMERICS_BASIC_OPS_IMPL_H_ +#define BASE_NUMERICS_BASIC_OPS_IMPL_H_ + +#include <bit> +#include <cstdint> +#include <cstring> +#include <span> +#include <type_traits> + +namespace base::numerics::internal { + +// The correct type to perform math operations on given values of type `T`. This +// may be a larger type than `T` to avoid promotion to `int` which involves sign +// conversion! +template <class T> + requires(std::is_integral_v<T>) +using MathType = std::conditional_t< + sizeof(T) >= sizeof(int), + T, + std::conditional_t<std::is_signed_v<T>, int, unsigned int>>; + +// Reverses the byte order of the integer. +template <class T> + requires(std::is_unsigned_v<T> && std::is_integral_v<T>) +inline constexpr T SwapBytes(T value) { + // MSVC intrinsics are not constexpr, so we provide our own constexpr + // implementation. We provide it unconditionally so we can test it on all + // platforms for correctness. + if (std::is_constant_evaluated()) { + if constexpr (sizeof(T) == 1u) { + return value; + } else if constexpr (sizeof(T) == 2u) { + MathType<T> a = (MathType<T>(value) >> 0) & MathType<T>{0xff}; + MathType<T> b = (MathType<T>(value) >> 8) & MathType<T>{0xff}; + return static_cast<T>((a << 8) | (b << 0)); + } else if constexpr (sizeof(T) == 4u) { + T a = (value >> 0) & T{0xff}; + T b = (value >> 8) & T{0xff}; + T c = (value >> 16) & T{0xff}; + T d = (value >> 24) & T{0xff}; + return (a << 24) | (b << 16) | (c << 8) | (d << 0); + } else { + static_assert(sizeof(T) == 8u); + T a = (value >> 0) & T{0xff}; + T b = (value >> 8) & T{0xff}; + T c = (value >> 16) & T{0xff}; + T d = (value >> 24) & T{0xff}; + T e = (value >> 32) & T{0xff}; + T f = (value >> 40) & T{0xff}; + T g = (value >> 48) & T{0xff}; + T h = (value >> 56) & T{0xff}; + return (a << 56) | (b << 48) | (c << 40) | (d << 32) | // + (e << 24) | (f << 16) | (g << 8) | (h << 0); + } + } + +#if _MSC_VER + if constexpr (sizeof(T) == 1u) { + return value; + } else if constexpr (sizeof(T) == sizeof(unsigned short)) { + using U = unsigned short; + return _byteswap_ushort(U{value}); + } else if constexpr (sizeof(T) == sizeof(unsigned long)) { + using U = unsigned long; + return _byteswap_ulong(U{value}); + } else { + static_assert(sizeof(T) == 8u); + return _byteswap_uint64(value); + } +#else + if constexpr (sizeof(T) == 1u) { + return value; + } else if constexpr (sizeof(T) == 2u) { + return __builtin_bswap16(uint16_t{value}); + } else if constexpr (sizeof(T) == 4u) { + return __builtin_bswap32(value); + } else { + static_assert(sizeof(T) == 8u); + return __builtin_bswap64(value); + } +#endif +} + +// Converts from a byte array to an integer. +template <class T> + requires(std::is_unsigned_v<T> && std::is_integral_v<T>) +inline constexpr T FromLittleEndian(std::span<const uint8_t, sizeof(T)> bytes) { + T val; + if (std::is_constant_evaluated()) { + val = T{0}; + for (size_t i = 0u; i < sizeof(T); i += 1u) { + // SAFETY: `i < sizeof(T)` (the number of bytes in T), so `(8 * i)` is + // less than the number of bits in T. + val |= MathType<T>(bytes[i]) << (8u * i); + } + } else { + // SAFETY: `bytes` has sizeof(T) bytes, and `val` is of type `T` so has + // sizeof(T) bytes, and the two can not alias as `val` is a stack variable. + memcpy(&val, bytes.data(), sizeof(T)); + } + return val; +} + +} // namespace base::numerics::internal + +#endif // BASE_NUMERICS_BASIC_OPS_IMPL_H_
diff --git a/base/numerics/byte_conversions.h b/base/numerics/byte_conversions.h new file mode 100644 index 0000000..a4bf09c5 --- /dev/null +++ b/base/numerics/byte_conversions.h
@@ -0,0 +1,242 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_NUMERICS_BYTE_CONVERSIONS_H_ +#define BASE_NUMERICS_BYTE_CONVERSIONS_H_ + +#include <bit> +#include <cstdint> +#include <cstring> +#include <span> +#include <type_traits> + +#include "base/numerics/basic_ops_impl.h" + +namespace base::numerics { + +// Returns a value with all bytes in |x| swapped, i.e. reverses the endianness. +// TODO(pkasting): Once C++23 is available, replace with std::byteswap. +template <class T> + requires(std::is_unsigned_v<T> && std::is_integral_v<T>) +inline constexpr T ByteSwap(T value) { + return numerics::internal::SwapBytes(value); +} + +// Returns a uint8_t with the value in `bytes` interpreted as the native endian +// encoding of the integer for the machine. +// +// This is suitable for decoding integers that were always kept in native +// encoding, such as when stored in shared-memory (or through IPC) as a byte +// buffer. Prefer an explicit little endian when storing and reading data from +// storage, and explicit big endian for network order. +// +// Note that since a single byte can have only one ordering, this just copies +// the byte out of the span. This provides a consistent function for the +// operation nonetheless. +inline constexpr uint8_t U8FromNativeEndian( + std::span<const uint8_t, 1u> bytes) { + return bytes[0]; +} +// Returns a uint16_t with the value in `bytes` interpreted as the native endian +// encoding of the integer for the machine. +// +// This is suitable for decoding integers that were always kept in native +// encoding, such as when stored in shared-memory (or through IPC) as a byte +// buffer. Prefer an explicit little endian when storing and reading data from +// storage, and explicit big endian for network order. +inline constexpr uint16_t U16FromNativeEndian( + std::span<const uint8_t, 2u> bytes) { + return internal::FromLittleEndian<uint16_t>(bytes); +} +// Returns a uint32_t with the value in `bytes` interpreted as the native endian +// encoding of the integer for the machine. +// +// This is suitable for decoding integers that were always kept in native +// encoding, such as when stored in shared-memory (or through IPC) as a byte +// buffer. Prefer an explicit little endian when storing and reading data from +// storage, and explicit big endian for network order. +inline constexpr uint32_t U32FromNativeEndian( + std::span<const uint8_t, 4u> bytes) { + return internal::FromLittleEndian<uint32_t>(bytes); +} +// Returns a uint64_t with the value in `bytes` interpreted as the native endian +// encoding of the integer for the machine. +// +// This is suitable for decoding integers that were always kept in native +// encoding, such as when stored in shared-memory (or through IPC) as a byte +// buffer. Prefer an explicit little endian when storing and reading data from +// storage, and explicit big endian for network order. +inline constexpr uint64_t U64FromNativeEndian( + std::span<const uint8_t, 8u> bytes) { + return internal::FromLittleEndian<uint64_t>(bytes); +} +// Returns a float with the value in `bytes` interpreted as the native endian +// encoding of the number for the machine. +// +// This is suitable for decoding numbers that were always kept in native +// encoding, such as when stored in shared-memory (or through IPC) as a byte +// buffer. Prefer an explicit little endian when storing and reading data from +// storage, and explicit big endian for network order. +inline constexpr float FloatFromNativeEndian( + std::span<const uint8_t, 4u> bytes) { + return std::bit_cast<float>(U32FromNativeEndian(bytes)); +} +// Returns a double with the value in `bytes` interpreted as the native endian +// encoding of the number for the machine. +// +// This is suitable for decoding numbers that were always kept in native +// encoding, such as when stored in shared-memory (or through IPC) as a byte +// buffer. Prefer an explicit little endian when storing and reading data from +// storage, and explicit big endian for network order. +inline constexpr double DoubleFromNativeEndian( + std::span<const uint8_t, 8u> bytes) { + return std::bit_cast<double>(U64FromNativeEndian(bytes)); +} + +// Returns a uint8_t with the value in `bytes` interpreted as a little-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in little endian, +// which is a good practice with storing and reading data from storage. Use +// the native-endian versions when working with values that were always in +// memory, such as when stored in shared-memory (or through IPC) as a byte +// buffer. +// +// Note that since a single byte can have only one ordering, this just copies +// the byte out of the span. This provides a consistent function for the +// operation nonetheless. +inline constexpr uint8_t U8FromLittleEndian( + std::span<const uint8_t, 1u> bytes) { + return bytes[0]; +} +// Returns a uint16_t with the value in `bytes` interpreted as a little-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in little endian, +// which is a good practice with storing and reading data from storage. Use +// the native-endian versions when working with values that were always in +// memory, such as when stored in shared-memory (or through IPC) as a byte +// buffer. +inline constexpr uint16_t U16FromLittleEndian( + std::span<const uint8_t, 2u> bytes) { + return internal::FromLittleEndian<uint16_t>(bytes); +} +// Returns a uint32_t with the value in `bytes` interpreted as a little-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in little endian, +// which is a good practice with storing and reading data from storage. Use +// the native-endian versions when working with values that were always in +// memory, such as when stored in shared-memory (or through IPC) as a byte +// buffer. +inline constexpr uint32_t U32FromLittleEndian( + std::span<const uint8_t, 4u> bytes) { + return internal::FromLittleEndian<uint32_t>(bytes); +} +// Returns a uint64_t with the value in `bytes` interpreted as a little-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in little endian, +// which is a good practice with storing and reading data from storage. Use +// the native-endian versions when working with values that were always in +// memory, such as when stored in shared-memory (or through IPC) as a byte +// buffer. +inline constexpr uint64_t U64FromLittleEndian( + std::span<const uint8_t, 8u> bytes) { + return internal::FromLittleEndian<uint64_t>(bytes); +} +// Returns a float with the value in `bytes` interpreted as a little-endian +// encoding of the integer. +// +// This is suitable for decoding numbers encoded explicitly in little endian, +// which is a good practice with storing and reading data from storage. Use +// the native-endian versions when working with values that were always in +// memory, such as when stored in shared-memory (or through IPC) as a byte +// buffer. +inline constexpr float FloatFromLittleEndian( + std::span<const uint8_t, 4u> bytes) { + return std::bit_cast<float>(U32FromLittleEndian(bytes)); +} +// Returns a double with the value in `bytes` interpreted as a little-endian +// encoding of the integer. +// +// This is suitable for decoding numbers encoded explicitly in little endian, +// which is a good practice with storing and reading data from storage. Use +// the native-endian versions when working with values that were always in +// memory, such as when stored in shared-memory (or through IPC) as a byte +// buffer. +inline constexpr double DoubleFromLittleEndian( + std::span<const uint8_t, 8u> bytes) { + return std::bit_cast<double>(U64FromLittleEndian(bytes)); +} + +// Returns a uint8_t with the value in `bytes` interpreted as a big-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in big endian, such +// as for network order. Use the native-endian versions when working with values +// that were always in memory, such as when stored in shared-memory (or through +// IPC) as a byte buffer. +// +// Note that since a single byte can have only one ordering, this just copies +// the byte out of the span. This provides a consistent function for the +// operation nonetheless. +inline constexpr uint8_t U8FromBigEndian(std::span<const uint8_t, 1u> bytes) { + return bytes[0]; +} +// Returns a uint16_t with the value in `bytes` interpreted as a big-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in big endian, such +// as for network order. Use the native-endian versions when working with values +// that were always in memory, such as when stored in shared-memory (or through +// IPC) as a byte buffer. +inline constexpr uint16_t U16FromBigEndian(std::span<const uint8_t, 2u> bytes) { + return ByteSwap(internal::FromLittleEndian<uint16_t>(bytes)); +} +// Returns a uint32_t with the value in `bytes` interpreted as a big-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in big endian, such +// as for network order. Use the native-endian versions when working with values +// that were always in memory, such as when stored in shared-memory (or through +// IPC) as a byte buffer. +inline constexpr uint32_t U32FromBigEndian(std::span<const uint8_t, 4u> bytes) { + return ByteSwap(internal::FromLittleEndian<uint32_t>(bytes)); +} +// Returns a uint64_t with the value in `bytes` interpreted as a big-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in big endian, such +// as for network order. Use the native-endian versions when working with values +// that were always in memory, such as when stored in shared-memory (or through +// IPC) as a byte buffer. +inline constexpr uint64_t U64FromBigEndian(std::span<const uint8_t, 8u> bytes) { + return ByteSwap(internal::FromLittleEndian<uint64_t>(bytes)); +} +// Returns a float with the value in `bytes` interpreted as a big-endian +// encoding of the integer. +// +// This is suitable for decoding numbers encoded explicitly in big endian, such +// as for network order. Use the native-endian versions when working with values +// that were always in memory, such as when stored in shared-memory (or through +// IPC) as a byte buffer. +inline constexpr float FloatFromBigEndian(std::span<const uint8_t, 4u> bytes) { + return std::bit_cast<float>(U32FromBigEndian(bytes)); +} +// Returns a double with the value in `bytes` interpreted as a big-endian +// encoding of the integer. +// +// This is suitable for decoding numbers encoded explicitly in big endian, such +// as for network order. Use the native-endian versions when working with values +// that were always in memory, such as when stored in shared-memory (or through +// IPC) as a byte buffer. +inline constexpr double DoubleFromBigEndian( + std::span<const uint8_t, 8u> bytes) { + return std::bit_cast<double>(U64FromBigEndian(bytes)); +} + +} // namespace base::numerics + +#endif // BASE_NUMERICS_BYTE_CONVERSIONS_H_
diff --git a/base/numerics/byte_conversions_unittest.cc b/base/numerics/byte_conversions_unittest.cc new file mode 100644 index 0000000..7fb924c8 --- /dev/null +++ b/base/numerics/byte_conversions_unittest.cc
@@ -0,0 +1,184 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/numerics/byte_conversions.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base::numerics { + +TEST(NumericsTest, FromNativeEndian) { + // The implementation of FromNativeEndian and FromLittleEndian assumes the + // native endian is little. If support of big endian is desired, compile-time + // branches will need to be added to the implementation, and the test results + // will differ there (they would match FromBigEndian in this test). + static_assert(std::endian::native == std::endian::little); + { + constexpr uint8_t bytes[] = {0x12u}; + EXPECT_EQ(U8FromNativeEndian(bytes), 0x12u); + static_assert(std::same_as<uint8_t, decltype(U8FromNativeEndian(bytes))>); + static_assert(U8FromNativeEndian(bytes) == 0x12u); + } + { + constexpr uint8_t bytes[] = {0x12u, 0x34u}; + EXPECT_EQ(U16FromNativeEndian(bytes), 0x34'12u); + static_assert(std::same_as<uint16_t, decltype(U16FromNativeEndian(bytes))>); + static_assert(U16FromNativeEndian(bytes) == 0x34'12u); + } + { + constexpr uint8_t bytes[] = {0x12u, 0x34u, 0x56u, 0x78u}; + EXPECT_EQ(U32FromNativeEndian(bytes), 0x78'56'34'12u); + static_assert(std::same_as<uint32_t, decltype(U32FromNativeEndian(bytes))>); + static_assert(U32FromNativeEndian(bytes) == 0x78'56'34'12u); + } + { + constexpr uint8_t bytes[] = {0x12u, 0x34u, 0x56u, 0x78u, + 0x90u, 0x12u, 0x34u, 0x56u}; + EXPECT_EQ(U64FromNativeEndian(bytes), 0x56'34'12'90'78'56'34'12u); + static_assert(std::same_as<uint64_t, decltype(U64FromNativeEndian(bytes))>); + static_assert(U64FromNativeEndian(bytes) == 0x56'34'12'90'78'56'34'12u); + } + + { + constexpr uint8_t bytes[] = {0x12u, 0x34u, 0x56u, 0x78u}; + EXPECT_EQ(FloatFromNativeEndian(bytes), 1.73782443614e+34f); + EXPECT_EQ(std::bit_cast<uint32_t>(FloatFromNativeEndian(bytes)), + 0x78'56'34'12u); + static_assert(std::same_as<float, decltype(FloatFromNativeEndian(bytes))>); + static_assert(FloatFromNativeEndian(bytes) == 1.73782443614e+34f); + static_assert(std::bit_cast<uint32_t>(FloatFromNativeEndian(bytes)) == + 0x78'56'34'12u); + } + + { + constexpr uint8_t bytes[] = {0x12u, 0x34u, 0x56u, 0x78u, + 0x90u, 0x12u, 0x34u, 0x56u}; + EXPECT_EQ(DoubleFromNativeEndian(bytes), + 1.84145159269283616391989849435e107); + EXPECT_EQ(std::bit_cast<uint64_t>(DoubleFromNativeEndian(bytes)), + 0x56'34'12'90'78'56'34'12u); + static_assert( + std::same_as<double, decltype(DoubleFromNativeEndian(bytes))>); + static_assert(DoubleFromNativeEndian(bytes) == + 1.84145159269283616391989849435e107); + static_assert(std::bit_cast<uint64_t>(DoubleFromNativeEndian(bytes)) == + 0x56'34'12'90'78'56'34'12u); + } +} + +TEST(NumericsTest, FromLittleEndian) { + // The implementation of FromNativeEndian and FromLittleEndian assumes the + // native endian is little. If support of big endian is desired, compile-time + // branches will need to be added to the implementation, and the test results + // will differ there (they would match FromBigEndian in this test). + static_assert(std::endian::native == std::endian::little); + { + constexpr uint8_t bytes[] = {0x12u}; + EXPECT_EQ(U8FromLittleEndian(bytes), 0x12u); + static_assert(std::same_as<uint8_t, decltype(U8FromLittleEndian(bytes))>); + static_assert(U8FromLittleEndian(bytes) == 0x12u); + } + { + constexpr uint8_t bytes[] = {0x12u, 0x34u}; + EXPECT_EQ(U16FromLittleEndian(bytes), 0x34'12u); + static_assert(std::same_as<uint16_t, decltype(U16FromLittleEndian(bytes))>); + static_assert(U16FromLittleEndian(bytes) == 0x34'12u); + } + { + constexpr uint8_t bytes[] = {0x12u, 0x34u, 0x56u, 0x78u}; + EXPECT_EQ(U32FromLittleEndian(bytes), 0x78'56'34'12u); + static_assert(std::same_as<uint32_t, decltype(U32FromLittleEndian(bytes))>); + static_assert(U32FromLittleEndian(bytes) == 0x78'56'34'12u); + } + { + constexpr uint8_t bytes[] = {0x12u, 0x34u, 0x56u, 0x78u, + 0x90u, 0x12u, 0x34u, 0x56u}; + EXPECT_EQ(U64FromLittleEndian(bytes), 0x56'34'12'90'78'56'34'12u); + static_assert(std::same_as<uint64_t, decltype(U64FromLittleEndian(bytes))>); + static_assert(U64FromLittleEndian(bytes) == 0x56'34'12'90'78'56'34'12u); + } + + { + constexpr uint8_t bytes[] = {0x12u, 0x34u, 0x56u, 0x78u}; + EXPECT_EQ(FloatFromLittleEndian(bytes), 1.73782443614e+34f); + EXPECT_EQ(std::bit_cast<uint32_t>(FloatFromLittleEndian(bytes)), + 0x78'56'34'12u); + static_assert(std::same_as<float, decltype(FloatFromLittleEndian(bytes))>); + static_assert(FloatFromLittleEndian(bytes) == 1.73782443614e+34f); + static_assert(std::bit_cast<uint32_t>(FloatFromLittleEndian(bytes)) == + 0x78'56'34'12u); + } + + { + constexpr uint8_t bytes[] = {0x12u, 0x34u, 0x56u, 0x78u, + 0x90u, 0x12u, 0x34u, 0x56u}; + EXPECT_EQ(DoubleFromLittleEndian(bytes), + 1.84145159269283616391989849435e107); + EXPECT_EQ(std::bit_cast<uint64_t>(DoubleFromLittleEndian(bytes)), + 0x56'34'12'90'78'56'34'12u); + static_assert( + std::same_as<double, decltype(DoubleFromLittleEndian(bytes))>); + static_assert(DoubleFromLittleEndian(bytes) == + 1.84145159269283616391989849435e107); + static_assert(std::bit_cast<uint64_t>(DoubleFromLittleEndian(bytes)) == + 0x56'34'12'90'78'56'34'12u); + } +} + +TEST(NumericsTest, FromBigEndian) { + // The implementation of FromNativeEndian and FromLittleEndian assumes the + // native endian is little. If support of big endian is desired, compile-time + // branches will need to be added to the implementation, and the test results + // will differ there (they would match FromLittleEndian in this test). + static_assert(std::endian::native == std::endian::little); + { + constexpr uint8_t bytes[] = {0x12u}; + EXPECT_EQ(U8FromBigEndian(bytes), 0x12u); + static_assert(U8FromBigEndian(bytes) == 0x12u); + static_assert(std::same_as<uint8_t, decltype(U8FromBigEndian(bytes))>); + } + { + constexpr uint8_t bytes[] = {0x12u, 0x34u}; + EXPECT_EQ(U16FromBigEndian(bytes), 0x12'34u); + static_assert(U16FromBigEndian(bytes) == 0x12'34u); + static_assert(std::same_as<uint16_t, decltype(U16FromBigEndian(bytes))>); + } + { + constexpr uint8_t bytes[] = {0x12u, 0x34u, 0x56u, 0x78u}; + EXPECT_EQ(U32FromBigEndian(bytes), 0x12'34'56'78u); + static_assert(U32FromBigEndian(bytes) == 0x12'34'56'78u); + static_assert(std::same_as<uint32_t, decltype(U32FromBigEndian(bytes))>); + } + { + constexpr uint8_t bytes[] = {0x12u, 0x34u, 0x56u, 0x78u, + 0x90u, 0x12u, 0x34u, 0x56u}; + EXPECT_EQ(U64FromBigEndian(bytes), 0x12'34'56'78'90'12'34'56u); + static_assert(U64FromBigEndian(bytes) == 0x12'34'56'78'90'12'34'56u); + static_assert(std::same_as<uint64_t, decltype(U64FromBigEndian(bytes))>); + } + + { + constexpr uint8_t bytes[] = {0x12u, 0x34u, 0x56u, 0x78u}; + EXPECT_EQ(FloatFromBigEndian(bytes), 5.6904566139e-28f); + EXPECT_EQ(std::bit_cast<uint32_t>(FloatFromBigEndian(bytes)), + 0x12'34'56'78u); + static_assert(std::same_as<float, decltype(FloatFromBigEndian(bytes))>); + static_assert(FloatFromBigEndian(bytes) == 5.6904566139e-28f); + static_assert(std::bit_cast<uint32_t>(FloatFromBigEndian(bytes)) == + 0x12'34'56'78u); + } + { + constexpr uint8_t bytes[] = {0x12u, 0x34u, 0x56u, 0x78u, + 0x90u, 0x12u, 0x34u, 0x56u}; + EXPECT_EQ(DoubleFromBigEndian(bytes), 5.62634909901491201382066931077e-221); + EXPECT_EQ(std::bit_cast<uint64_t>(DoubleFromBigEndian(bytes)), + 0x12'34'56'78'90'12'34'56u); + static_assert(std::same_as<double, decltype(DoubleFromBigEndian(bytes))>); + static_assert(DoubleFromBigEndian(bytes) == + 5.62634909901491201382066931077e-221); + static_assert(std::bit_cast<uint64_t>(DoubleFromBigEndian(bytes)) == + 0x12'34'56'78'90'12'34'56u); + } +} + +} // namespace base::numerics
diff --git a/base/process/process_unittest.cc b/base/process/process_unittest.cc index 4e18fc3..9341abc1 100644 --- a/base/process/process_unittest.cc +++ b/base/process/process_unittest.cc
@@ -6,6 +6,7 @@ #include <memory> #include <string> +#include <string_view> #include <utility> #include "base/at_exit.h" @@ -78,10 +79,10 @@ return std::string(); } - std::vector<base::StringPiece> lines = SplitStringPiece( + std::vector<std::string_view> lines = SplitStringPiece( proc, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); for (const auto& line : lines) { - std::vector<base::StringPiece> fields = SplitStringPiece( + std::vector<std::string_view> fields = SplitStringPiece( line, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); if (fields.size() != 3U) { continue;
diff --git a/base/sys_byteorder.h b/base/sys_byteorder.h index 5aa8980..70c88a05 100644 --- a/base/sys_byteorder.h +++ b/base/sys_byteorder.h
@@ -13,112 +13,80 @@ #include <stdint.h> +#include "base/numerics/byte_conversions.h" #include "build/build_config.h" #if defined(COMPILER_MSVC) #include <stdlib.h> #endif -#if defined(COMPILER_MSVC) && !defined(__clang__) -// TODO(pkasting): See -// https://developercommunity.visualstudio.com/t/Mark-some-built-in-functions-as-constexp/362558 -// https://developercommunity.visualstudio.com/t/constexpr-byte-swapping-optimization/983963 -#define BASE_BYTESWAPS_CONSTEXPR -#else -#define BASE_BYTESWAPS_CONSTEXPR constexpr -#endif - namespace base { // Returns a value with all bytes in |x| swapped, i.e. reverses the endianness. -// TODO(pkasting): Once C++23 is available, replace with std::byteswap. -inline BASE_BYTESWAPS_CONSTEXPR uint16_t ByteSwap(uint16_t x) { -#if defined(COMPILER_MSVC) && !defined(__clang__) - return _byteswap_ushort(x); -#else - return __builtin_bswap16(x); -#endif +// TODO(danakj): Replace with base::numerics::byteswap(). +inline constexpr uint16_t ByteSwap(uint16_t x) { + // Forward to templated function in //base/numerics. + return numerics::ByteSwap(x); } -inline BASE_BYTESWAPS_CONSTEXPR uint32_t ByteSwap(uint32_t x) { -#if defined(COMPILER_MSVC) && !defined(__clang__) - return _byteswap_ulong(x); -#else - return __builtin_bswap32(x); -#endif +inline constexpr uint32_t ByteSwap(uint32_t x) { + // Forward to templated function in //base/numerics. + return numerics::ByteSwap(x); } -inline BASE_BYTESWAPS_CONSTEXPR uint64_t ByteSwap(uint64_t x) { - // Per build/build_config.h, clang masquerades as MSVC on Windows. If we are - // actually using clang, we can rely on the builtin. - // - // This matters in practice, because on x86(_64), this is a single "bswap" - // instruction. MSVC correctly replaces the call with an inlined bswap at /O2 - // as of 2021, but clang as we use it in Chromium doesn't, keeping a function - // call for a single instruction. -#if defined(COMPILER_MSVC) && !defined(__clang__) - return _byteswap_uint64(x); -#else - return __builtin_bswap64(x); -#endif +inline constexpr uint64_t ByteSwap(uint64_t x) { + // Forward to templated function in //base/numerics. + return numerics::ByteSwap(x); } -inline BASE_BYTESWAPS_CONSTEXPR uintptr_t ByteSwapUintPtrT(uintptr_t x) { - // We do it this way because some build configurations are ILP32 even when - // defined(ARCH_CPU_64_BITS). Unfortunately, we can't use sizeof in #ifs. But, - // because these conditionals are constexprs, the irrelevant branches will - // likely be optimized away, so this construction should not result in code - // bloat. - static_assert(sizeof(uintptr_t) == 4 || sizeof(uintptr_t) == 8, - "Unsupported uintptr_t size"); - if (sizeof(uintptr_t) == 4) - return ByteSwap(static_cast<uint32_t>(x)); - return ByteSwap(static_cast<uint64_t>(x)); +inline constexpr uintptr_t ByteSwapUintPtrT(uintptr_t x) { + // Forward to templated function in //base/numerics. + return numerics::ByteSwap(x); } // Converts the bytes in |x| from host order (endianness) to little endian, and // returns the result. -inline BASE_BYTESWAPS_CONSTEXPR uint16_t ByteSwapToLE16(uint16_t x) { +inline constexpr uint16_t ByteSwapToLE16(uint16_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) return x; #else - return ByteSwap(x); + return numerics::ByteSwap(x); #endif } -inline BASE_BYTESWAPS_CONSTEXPR uint32_t ByteSwapToLE32(uint32_t x) { +inline constexpr uint32_t ByteSwapToLE32(uint32_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) return x; #else - return ByteSwap(x); + return numerics::ByteSwap(x); #endif } -inline BASE_BYTESWAPS_CONSTEXPR uint64_t ByteSwapToLE64(uint64_t x) { +inline constexpr uint64_t ByteSwapToLE64(uint64_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) return x; #else - return ByteSwap(x); + return numerics::ByteSwap(x); #endif } // Converts the bytes in |x| from network to host order (endianness), and // returns the result. -inline BASE_BYTESWAPS_CONSTEXPR uint16_t NetToHost16(uint16_t x) { +inline constexpr uint16_t NetToHost16(uint16_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) - return ByteSwap(x); + return numerics::ByteSwap(x); #else return x; #endif } -inline BASE_BYTESWAPS_CONSTEXPR uint32_t NetToHost32(uint32_t x) { +inline constexpr uint32_t NetToHost32(uint32_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) - return ByteSwap(x); + return numerics::ByteSwap(x); #else return x; #endif } -inline BASE_BYTESWAPS_CONSTEXPR uint64_t NetToHost64(uint64_t x) { +inline constexpr uint64_t NetToHost64(uint64_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) - return ByteSwap(x); + return numerics::ByteSwap(x); #else return x; #endif @@ -126,23 +94,23 @@ // Converts the bytes in |x| from host to network order (endianness), and // returns the result. -inline BASE_BYTESWAPS_CONSTEXPR uint16_t HostToNet16(uint16_t x) { +inline constexpr uint16_t HostToNet16(uint16_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) - return ByteSwap(x); + return numerics::ByteSwap(x); #else return x; #endif } -inline BASE_BYTESWAPS_CONSTEXPR uint32_t HostToNet32(uint32_t x) { +inline constexpr uint32_t HostToNet32(uint32_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) - return ByteSwap(x); + return numerics::ByteSwap(x); #else return x; #endif } -inline BASE_BYTESWAPS_CONSTEXPR uint64_t HostToNet64(uint64_t x) { +inline constexpr uint64_t HostToNet64(uint64_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) - return ByteSwap(x); + return numerics::ByteSwap(x); #else return x; #endif @@ -150,6 +118,6 @@ } // namespace base -#undef BASE_BYTESWAPS_CONSTEXPR +#undef constexpr #endif // BASE_SYS_BYTEORDER_H_
diff --git a/base/task/sequence_manager/task_queue_impl.cc b/base/task/sequence_manager/task_queue_impl.cc index d4cd6559..8a97b0d 100644 --- a/base/task/sequence_manager/task_queue_impl.cc +++ b/base/task/sequence_manager/task_queue_impl.cc
@@ -35,7 +35,6 @@ #include "base/threading/thread_restrictions.h" #include "base/time/time.h" #include "base/trace_event/base_tracing.h" -#include "base/types/pass_key.h" #include "build/build_config.h" #include "third_party/abseil-cpp/absl/container/inlined_vector.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -1588,7 +1587,8 @@ } void TaskQueueImpl::CompleteInitializationOnBoundThread() { - voter_weak_ptr_factory_.BindToCurrentSequence(PassKey<TaskQueueImpl>()); + voter_weak_ptr_factory_.BindToCurrentSequence( + subtle::BindWeakPtrFactoryPassKey()); } TaskQueue::QueuePriority TaskQueueImpl::DefaultPriority() const {
diff --git a/base/tracing/protos/chrome_track_event.proto b/base/tracing/protos/chrome_track_event.proto index 602102e..4601270 100644 --- a/base/tracing/protos/chrome_track_event.proto +++ b/base/tracing/protos/chrome_track_event.proto
@@ -1386,6 +1386,14 @@ STEP_BUFFER_SWAP_POST_SUBMIT = 12; STEP_FINISH_BUFFER_SWAP = 13; STEP_SWAP_BUFFERS_ACK = 14; + + // Frame submission stages when Exo (Wayland server implementation in Ash + // browser process) is involved. Wayland clients (such as Lacros or ARC++) + // submit visual contents via Wayland surface commits, with which Exo + // constructs compositor frames and forwards to Ash Viz. + STEP_EXO_CONSTRUCT_COMPOSITOR_FRAME = 15; + STEP_EXO_SUBMIT_COMPOSITOR_FRAME = 16; + STEP_EXO_DISCARD_COMPOSITOR_FRAME = 17; } enum FrameSkippedReason { SKIPPED_REASON_UNKNOWN = 0;
diff --git a/base/win/win_util.cc b/base/win/win_util.cc index 71e8995..25cc9b48 100644 --- a/base/win/win_util.cc +++ b/base/win/win_util.cc
@@ -778,28 +778,6 @@ return current_session_id != glass_session_id; } -#if !defined(OFFICIAL_BUILD) -bool IsAppVerifierEnabled(const std::wstring& process_name) { - RegKey key; - - // Look for GlobalFlag in the IFEO\chrome.exe key. If it is present then - // Application Verifier or gflags.exe are configured. Most GlobalFlag - // settings are experimentally determined to be incompatible with renderer - // code integrity and a safe set is not known so any GlobalFlag entry is - // assumed to mean that Application Verifier (or pageheap) are enabled. - // The settings are propagated to both 64-bit WOW6432Node versions of the - // registry on 64-bit Windows, so only one check is needed. - return key.Open( - HKEY_LOCAL_MACHINE, - (L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File " - L"Execution Options\\" + - process_name) - .c_str(), - KEY_READ | KEY_WOW64_64KEY) == ERROR_SUCCESS && - key.HasValue(L"GlobalFlag"); -} -#endif // !defined(OFFICIAL_BUILD) - bool IsAppVerifierLoaded() { return GetModuleHandleA(kApplicationVerifierDllName); }
diff --git a/base/win/win_util.h b/base/win/win_util.h index 1276f27e..032fc0e 100644 --- a/base/win/win_util.h +++ b/base/win/win_util.h
@@ -228,13 +228,6 @@ // Returns true if current session is a remote session. BASE_EXPORT bool IsCurrentSessionRemote(); -#if !defined(OFFICIAL_BUILD) -// IsAppVerifierEnabled() indicates whether a newly created process will get -// Application Verifier or pageheap injected into it. Only available in -// unofficial builds to prevent abuse. -BASE_EXPORT bool IsAppVerifierEnabled(const std::wstring& process_name); -#endif // !defined(OFFICIAL_BUILD) - // IsAppVerifierLoaded() indicates whether Application Verifier is *already* // loaded into the current process. BASE_EXPORT bool IsAppVerifierLoaded();
diff --git a/build/config/clang/BUILD.gn b/build/config/clang/BUILD.gn index ba00640..afa34d9 100644 --- a/build/config/clang/BUILD.gn +++ b/build/config/clang/BUILD.gn
@@ -31,11 +31,11 @@ "-Xclang", "check-stack-allocated", - # TODO(danakj): Enable this after clang update. - #"-Xclang", - #"-plugin-arg-find-bad-constructs", - #"-Xclang", - #"check-allow-auto-typedefs", + # TODO(danakj): Delete this and the option from the plugin. + "-Xclang", + "-plugin-arg-find-bad-constructs", + "-Xclang", + "check-allow-auto-typedefs", "-Xclang", "-plugin-arg-find-bad-constructs",
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 72084265..a109df4 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -1894,6 +1894,7 @@ cflags += [ "-Wno-error=unknown-warning-option", "-Wno-error=unused-command-line-argument", + "-Wno-error=unknown-pragmas", ] } }
diff --git a/build/extract_partition.py b/build/extract_partition.py index 5e4f5cb04..5b8267a3 100755 --- a/build/extract_partition.py +++ b/build/extract_partition.py
@@ -6,7 +6,6 @@ import argparse import hashlib -import math import os import struct import subprocess @@ -70,20 +69,14 @@ with tempfile.TemporaryDirectory() as tempdir: temp_elf = os.path.join(tempdir, 'obj_without_id.so') - temp_elf2 = os.path.join(tempdir, 'obj_with_id_unaligned.so') old_build_id_file = os.path.join(tempdir, 'old_build_id') new_build_id_file = os.path.join(tempdir, 'new_build_id') - # Dump out build-id section and remove original build-id section from - # ELF file. + # Dump out build-id section. subprocess.check_call([ objcopy, '--extract-partition', partition, - # Note: Not using '--update-section' here as it is not supported - # by llvm-objcopy. - '--remove-section', - build_id_section, '--dump-section', '{}={}'.format(build_id_section, old_build_id_file), input_elf, @@ -113,24 +106,12 @@ with open(new_build_id_file, 'wb') as f: f.write(prefix + _ComputeNewBuildId(build_id, output_elf)) - # Write back the new build-id section. + # Update the build-id section. subprocess.check_call([ objcopy, - '--add-section', + '--update-section', '{}={}'.format(build_id_section, new_build_id_file), temp_elf, - temp_elf2, - ]) - subprocess.check_call([ - objcopy, - # Add alloc section flag, or else the section will be removed by - # objcopy --strip-all when generating unstripped lib file. - '--set-section-flags', - '{}={}'.format(build_id_section, 'alloc'), - # Set the section alignment to 4 bytes - '--set-section-alignment', - '{}={}'.format(build_id_section, '4'), - temp_elf2, output_elf, ])
diff --git a/build_overrides/build.gni b/build_overrides/build.gni index 619e86da..16767dc 100644 --- a/build_overrides/build.gni +++ b/build_overrides/build.gni
@@ -40,7 +40,7 @@ # TODO(crbug/1006541): Switch to perfetto's client library on all platforms. use_perfetto_client_library = (is_linux || is_android || (use_blink && is_ios) || is_win || - is_chromeos) && !is_castos + is_chromeos || is_mac) && !is_castos # Limits the defined //third_party/android_deps targets to only "buildCompile" # and "buildCompileNoDeps" targets. This is useful for third-party
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni index 88fcca8a..798353c7 100644 --- a/buildtools/deps_revisions.gni +++ b/buildtools/deps_revisions.gni
@@ -5,5 +5,5 @@ declare_args() { # Used to cause full rebuilds on libc++ rolls. This should be kept in sync # with the libcxx_revision vars in //DEPS. - libcxx_revision = "c51c9efb6c5a83e0e25c1e30864449d2beadd7a8" + libcxx_revision = "9d119c1f4a097b7d27210874f4eba3fc91a83a4e" }
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 3e98c4b..9552f34a 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -344,6 +344,7 @@ "//chrome/browser/commerce/price_tracking/proto:proto_java", "//chrome/browser/commerce/subscriptions/android:subscriptions_java", "//chrome/browser/consent_auditor/android:java", + "//chrome/browser/content_extraction/android:java", "//chrome/browser/contextmenu:java", "//chrome/browser/creator/android:java", "//chrome/browser/data_sharing:factory_java", @@ -3728,6 +3729,7 @@ "java/src/org/chromium/chrome/browser/webapps/WebApkInstallService.java", "java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java", "java/src/org/chromium/chrome/browser/webapps/WebApkPostShareTargetNavigator.java", + "java/src/org/chromium/chrome/browser/webapps/WebApkSyncService.java", "java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java", "java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java", "java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 35c019a..ffb1e2c5 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -1208,6 +1208,7 @@ "java/src/org/chromium/chrome/browser/webapps/WebApkServiceClient.java", "java/src/org/chromium/chrome/browser/webapps/WebApkShareTargetUtil.java", "java/src/org/chromium/chrome/browser/webapps/WebApkSplashNetworkErrorObserver.java", + "java/src/org/chromium/chrome/browser/webapps/WebApkSyncService.java", "java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java", "java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java", "java/src/org/chromium/chrome/browser/webapps/WebApkUpdateReportAbuseDialog.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index 307fc3c..5f74dce 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -371,6 +371,7 @@ "junit/src/org/chromium/chrome/browser/webapps/WebApkInstallNotificationTest.java", "junit/src/org/chromium/chrome/browser/webapps/WebApkIntentDataProviderFactoryTest.java", "junit/src/org/chromium/chrome/browser/webapps/WebApkShareTargetUtilTest.java", + "junit/src/org/chromium/chrome/browser/webapps/WebApkSyncServiceTest.java", "junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java", "junit/src/org/chromium/chrome/browser/webapps/WebappAuthenticatorTest.java", "junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java",
diff --git a/chrome/android/expectations/monochrome_64_32_public_bundle.proguard_flags.expected b/chrome/android/expectations/monochrome_64_32_public_bundle.proguard_flags.expected index 9dd7bc28..d5fe85b 100644 --- a/chrome/android/expectations/monochrome_64_32_public_bundle.proguard_flags.expected +++ b/chrome/android/expectations/monochrome_64_32_public_bundle.proguard_flags.expected
@@ -213,18 +213,9 @@ # Contains flags that can be safely shared with Cronet, and thus would be # appropriate for third-party apps to include. -# -# IMPORTANT: MAKE SURE ALL RULES IN THIS FILE ARE ADEQUATELY SCOPED TO ONLY -# AFFECT CHROMIUM CODE (typically that means the rule should have a restriction -# on something under `org.chromium`). These rules are shipped in Cronet which is -# a library used by a variety of downstream apps. ProGuard operates at the app -# level, not the library level. It doesn't automatically scope rules shipped -# in libraries. In other words: when downstream apps run ProGuard, these rules -# will be applied to their entire app. It is our responsibility to ensure the -# rules we ship in this way don't end up affecting code that is not ours. # Allow unused native methods to be removed, but prevent renaming on those that are kept. --keepclasseswithmembernames,includedescriptorclasses,allowaccessmodification class !cr_allowunused,org.chromium.base.library_loader.LinkerJni { +-keepclasseswithmembernames,includedescriptorclasses,allowaccessmodification class !cr_allowunused,** { native <methods>; } @@ -464,11 +455,6 @@ @org.jni_zero.CalledByNativeUnchecked <methods>; } -# Allow unused native methods to be removed, but prevent renaming on those that are kept. --keepclasseswithmembernames,includedescriptorclasses,allowaccessmodification class org.jni_zero.*,J.N,J.*_N { - native <methods>; -} - # File: ../../chrome/android/features/start_surface/proguard.flags # Copyright 2019 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be
diff --git a/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected b/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected index 354c3da6..0a721db 100644 --- a/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected +++ b/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected
@@ -213,18 +213,9 @@ # Contains flags that can be safely shared with Cronet, and thus would be # appropriate for third-party apps to include. -# -# IMPORTANT: MAKE SURE ALL RULES IN THIS FILE ARE ADEQUATELY SCOPED TO ONLY -# AFFECT CHROMIUM CODE (typically that means the rule should have a restriction -# on something under `org.chromium`). These rules are shipped in Cronet which is -# a library used by a variety of downstream apps. ProGuard operates at the app -# level, not the library level. It doesn't automatically scope rules shipped -# in libraries. In other words: when downstream apps run ProGuard, these rules -# will be applied to their entire app. It is our responsibility to ensure the -# rules we ship in this way don't end up affecting code that is not ours. # Allow unused native methods to be removed, but prevent renaming on those that are kept. --keepclasseswithmembernames,includedescriptorclasses,allowaccessmodification class !cr_allowunused,org.chromium.base.library_loader.LinkerJni { +-keepclasseswithmembernames,includedescriptorclasses,allowaccessmodification class !cr_allowunused,** { native <methods>; } @@ -464,11 +455,6 @@ @org.jni_zero.CalledByNativeUnchecked <methods>; } -# Allow unused native methods to be removed, but prevent renaming on those that are kept. --keepclasseswithmembernames,includedescriptorclasses,allowaccessmodification class org.jni_zero.*,J.N,J.*_N { - native <methods>; -} - # File: ../../chrome/android/features/start_surface/proguard.flags # Copyright 2019 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDragSource.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDragSource.java index 3d1ddf7..7ffdf92 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDragSource.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabDragSource.java
@@ -163,7 +163,7 @@ if (!TabUiFeatureUtilities.isTabDragEnabled() || DragDropGlobalState.hasValue()) { return false; } - // Do not allow move for last tab when partner homepage enabled. + // Do not allow move for last tab when homepage enabled and is set to a custom url. if (MultiWindowUtils.getInstance().hasAtMostOneTabWithHomepageEnabled(mTabModelSelector)) { return false; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java index 29c3a59..3f45855 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java
@@ -41,7 +41,7 @@ import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.app.tabmodel.TabWindowManagerSingleton; import org.chromium.chrome.browser.flags.ChromeFeatureList; -import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations; +import org.chromium.chrome.browser.homepage.HomepageManager; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.ChromeSharedPreferences; import org.chromium.chrome.browser.tab.Tab; @@ -215,7 +215,7 @@ // Not supported on automotive devices. if (BuildInfo.getInstance().isAutomotive) return false; - // Do not allow move for last tab when partner homepage enabled. + // Do not allow move for last tab when homepage enabled and is set to a custom url. if (hasAtMostOneTabWithHomepageEnabled(tabModelSelector)) { return false; } @@ -228,14 +228,18 @@ } /** - * @param tabModelSelector Used to pull total tab count. Returns whether last tab with partner - * homepage enabled. + * @param tabModelSelector Used to pull total tab count. + * @return whether it is last tab with homepage enabled and set to an custom url. */ public boolean hasAtMostOneTabWithHomepageEnabled(TabModelSelector tabModelSelector) { boolean hasAtMostOneTab = tabModelSelector.getTotalTabCount() <= 1; - boolean partnerHomepageEnabled = - PartnerBrowserCustomizations.getInstance().isHomepageProviderAvailableAndEnabled(); - return hasAtMostOneTab && partnerHomepageEnabled; + + // Chrome app is set to close with zero tabs when homepage is enabled and set to a custom + // url other than the NTP. We should not allow dragging the last tab or display 'Move to + // other window' in this scenario as the source window might be closed before drag n drop + // completes properly and thus cause other complications. + boolean shouldAppCloseWithZeroTabs = HomepageManager.shouldCloseAppWithZeroTabs(); + return hasAtMostOneTab && shouldAppCloseWithZeroTabs; } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivityCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivityCoordinator.java index ef4af709..c910d518 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivityCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivityCoordinator.java
@@ -23,8 +23,8 @@ import javax.inject.Inject; /** - * Coordinator for the WebAPK activity component. - * Add methods here if other components need to communicate with the WebAPK activity component. + * Coordinator for the WebAPK activity component. Add methods here if other components need to + * communicate with the WebAPK activity component. */ @ActivityScope public class WebApkActivityCoordinator implements DestroyObserver { @@ -64,6 +64,7 @@ assert storage != null; storage.incrementLaunchCount(); + WebApkSyncService.onWebApkUsed(mIntentDataProvider); mWebApkUpdateManager.get().updateIfNeeded(storage, mIntentDataProvider); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkSyncService.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkSyncService.java new file mode 100644 index 0000000..a6e05a0 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkSyncService.java
@@ -0,0 +1,87 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.webapps; + +import android.text.TextUtils; + +import org.jni_zero.JNINamespace; +import org.jni_zero.NativeMethods; + +import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider; +import org.chromium.chrome.browser.browserservices.intents.WebappIcon; +import org.chromium.chrome.browser.browserservices.intents.WebappInfo; +import org.chromium.components.sync.protocol.WebApkIconInfo; +import org.chromium.components.sync.protocol.WebApkSpecifics; + +/** Static class to update WebAPK data to sync. */ +@JNINamespace("webapk") +public class WebApkSyncService { + static void onWebApkUsed(BrowserServicesIntentDataProvider intendDataProvider) { + WebApkSpecifics specifics = getWebApkSpecifics(WebappInfo.create(intendDataProvider)); + if (specifics != null) { + WebApkSyncServiceJni.get().onWebApkUsed(specifics.toByteArray()); + } + } + + static WebApkSpecifics getWebApkSpecifics(WebappInfo webApkInfo) { + if (webApkInfo == null || !webApkInfo.isForWebApk()) { + return null; + } + + WebApkSpecifics.Builder webApkSpecificsBuilder = WebApkSpecifics.newBuilder(); + + if (TextUtils.isEmpty(webApkInfo.manifestId())) { + return null; + } + webApkSpecificsBuilder.setManifestId(webApkInfo.manifestId()); + + if (!TextUtils.isEmpty(webApkInfo.manifestStartUrl())) { + webApkSpecificsBuilder.setStartUrl(webApkInfo.manifestStartUrl()); + } + + if (!TextUtils.isEmpty(webApkInfo.name())) { + webApkSpecificsBuilder.setName(webApkInfo.name()); + } else if (!TextUtils.isEmpty(webApkInfo.shortName())) { + webApkSpecificsBuilder.setName(webApkInfo.shortName()); + } + + if (webApkInfo.hasValidToolbarColor()) { + webApkSpecificsBuilder.setThemeColor((int) webApkInfo.toolbarColor()); + } + + if (!TextUtils.isEmpty(webApkInfo.scopeUrl())) { + webApkSpecificsBuilder.setScope(webApkInfo.scopeUrl()); + } + + if (webApkInfo.shellApkVersion() < WebappIcon.ICON_WITH_URL_AND_HASH_SHELL_VERSION) { + for (String iconUrl : webApkInfo.iconUrlToMurmur2HashMap().keySet()) { + if (!TextUtils.isEmpty(iconUrl)) { + webApkSpecificsBuilder.addIconInfos( + WebApkIconInfo.newBuilder().setUrl(iconUrl).build()); + } + } + } else { + String iconUrl = webApkInfo.icon().iconUrl(); + if (!TextUtils.isEmpty(iconUrl)) { + WebApkIconInfo iconInfo = + WebApkIconInfo.newBuilder() + .setUrl(iconUrl) + .setPurpose( + webApkInfo.isIconAdaptive() + ? WebApkIconInfo.Purpose.MASKABLE + : WebApkIconInfo.Purpose.ANY) + .build(); + webApkSpecificsBuilder.addIconInfos(iconInfo); + } + } + + return webApkSpecificsBuilder.build(); + } + + @NativeMethods + interface Natives { + void onWebApkUsed(byte[] webApkSpecifics); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java index 4fec066..47574b4d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java
@@ -37,7 +37,6 @@ import org.chromium.chrome.browser.browserservices.intents.WebApkShareTarget; import org.chromium.chrome.browser.browserservices.intents.WebappInfo; import org.chromium.chrome.browser.browserservices.metrics.WebApkUmaRecorder; -import org.chromium.chrome.browser.browserservices.metrics.WebApkUmaRecorder.UpdateRequestQueued; import org.chromium.chrome.browser.dependency_injection.ActivityScope; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; @@ -535,7 +534,7 @@ mStorage, WebApkInstallResult.FAILURE, /* relaxUpdates= */ false); return; } - scheduleUpdate(); + scheduleUpdate(info.shellApkVersion()); }; String updateRequestPath = mStorage.createAndSetUpdateRequestFilePath(info); encodeIconsInBackground( @@ -565,8 +564,8 @@ /** Schedules update for when WebAPK is not running. */ @VisibleForTesting - protected void scheduleUpdate() { - WebApkUmaRecorder.recordUpdateRequestQueued(UpdateRequestQueued.TWICE); + protected void scheduleUpdate(int shellApkVersion) { + WebApkUmaRecorder.recordQueuedUpdateShellVersion(shellApkVersion); TaskInfo updateTask; if (mStorage.shouldForceUpdate()) { // Start an update task ASAP for forced updates.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java index c55f541c..ce984d2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java
@@ -283,34 +283,11 @@ } WebappInfo webApkInfo = WebApkDataProvider.getPartialWebappInfo(scope); - if (webApkInfo == null) { + WebApkSpecifics webApkSpecifics = WebApkSyncService.getWebApkSpecifics(webApkInfo); + if (webApkSpecifics == null) { continue; } - - WebApkSpecifics.Builder webApkSpecificsBuilder = WebApkSpecifics.newBuilder(); - if (webApkInfo.manifestId() != null) { - webApkSpecificsBuilder.setManifestId(webApkInfo.manifestId()); - } - if (webApkInfo.manifestStartUrl() != null) { - webApkSpecificsBuilder.setStartUrl(webApkInfo.manifestStartUrl()); - } - if (webApkInfo.name() != null) { - webApkSpecificsBuilder.setName(webApkInfo.name()); - } - if ((webApkInfo.name() == null || webApkInfo.name().equals("")) - && webApkInfo.shortName() != null) { - webApkSpecificsBuilder.setName(webApkInfo.shortName()); - } - if (webApkInfo.hasValidToolbarColor()) { - webApkSpecificsBuilder.setThemeColor((int) webApkInfo.toolbarColor()); - } - if (webApkInfo.scopeUrl() != null) { - webApkSpecificsBuilder.setScope(webApkInfo.scopeUrl()); - } - - // TODO(hartmanng): support icons and last used timestamp - - webApkSpecificsList.add(webApkSpecificsBuilder.build()); + webApkSpecificsList.add(WebApkSyncService.getWebApkSpecifics(webApkInfo)); } return webApkSpecificsList; }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragmentTest.java index c98e3119..c2d4b2b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragmentTest.java
@@ -235,6 +235,7 @@ @Test @MediumTest @Restriction(DeviceRestriction.RESTRICTION_TYPE_NON_AUTO) + @DisableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_CVC_STORAGE}) public void testTwoCreditCards_displaysTwoServerCards() throws Exception { mAutofillTestHelper.addServerCreditCard(SAMPLE_CARD_VISA); mAutofillTestHelper.addServerCreditCard(SAMPLE_CARD_MASTERCARD); @@ -248,6 +249,21 @@ @Test @MediumTest + @Restriction(DeviceRestriction.RESTRICTION_TYPE_NON_AUTO) + @EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_CVC_STORAGE}) + public void testTwoCreditCards_displaysTwoServerCards_cvcStorageEnabled() throws Exception { + mAutofillTestHelper.addServerCreditCard(SAMPLE_CARD_VISA); + mAutofillTestHelper.addServerCreditCard(SAMPLE_CARD_MASTERCARD); + + SettingsActivity activity = mSettingsActivityTestRule.startSettingsActivity(); + + // Verify that the preferences on the initial screen map to Save and Fill toggle + Mandatory + // Reauth toggle + CVC storage toggle + 2 Cards + Add Card button + Payment Apps. + Assert.assertEquals(7, getPreferenceScreen(activity).getPreferenceCount()); + } + + @Test + @MediumTest @Restriction(DeviceRestriction.RESTRICTION_TYPE_AUTO) public void testTwoCreditCards_displaysTwoServerCards_mandatoryReauthNotShownOnAutomotive() throws Exception { @@ -447,7 +463,8 @@ @Test @MediumTest - @DisableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_PAYMENTS_MANDATORY_REAUTH}) + @DisableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_PAYMENTS_MANDATORY_REAUTH, + ChromeFeatureList.AUTOFILL_ENABLE_CVC_STORAGE}) public void testMandatoryReauthToggle_notShownWhenFeatureDisabled() throws Exception { SettingsActivity activity = mSettingsActivityTestRule.startSettingsActivity(); @@ -458,6 +475,18 @@ @Test @MediumTest + @DisableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_PAYMENTS_MANDATORY_REAUTH}) + @EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_CVC_STORAGE}) + public void testMandatoryReauthToggle_notShownWhenFeatureDisabled_cvcStorageEnabled() throws Exception { + SettingsActivity activity = mSettingsActivityTestRule.startSettingsActivity(); + + // Verify that the preferences on the initial screen map are Save and + // Fill toggle + CVC storage toggle + Add Card button + Payment Apps. + Assert.assertEquals(4, getPreferenceScreen(activity).getPreferenceCount()); + } + + @Test + @MediumTest // Use the policy to simulate AutofillCreditCard is disabled. @Policies.Add({@Policies.Item(key = "AutofillCreditCardEnabled", string = "false")}) @Restriction(DeviceRestriction.RESTRICTION_TYPE_NON_AUTO) @@ -508,6 +537,7 @@ @Test @MediumTest @Restriction(DeviceRestriction.RESTRICTION_TYPE_NON_AUTO) + @DisableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_CVC_STORAGE}) public void testMandatoryReauthToggle_displayToggle() throws Exception { // Simulate the pref was enabled previously, to ensure the toggle value is set // correspondingly. @@ -538,6 +568,37 @@ @Test @MediumTest @Restriction(DeviceRestriction.RESTRICTION_TYPE_NON_AUTO) + @EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_CVC_STORAGE}) + public void testMandatoryReauthToggle_displayToggle_cvcStorageEnabled() throws Exception { + // Simulate the pref was enabled previously, to ensure the toggle value is set + // correspondingly. + TestThreadUtils.runOnUiThreadBlocking( + () -> { + getPrefService() + .setBoolean(Pref.AUTOFILL_PAYMENT_METHODS_MANDATORY_REAUTH, true); + }); + // Simulate the user can authenticate with biometric or screen lock. + when(mReauthenticatorMock.canUseAuthenticationWithBiometricOrScreenLock()).thenReturn(true); + + SettingsActivity activity = mSettingsActivityTestRule.startSettingsActivity(); + + // Verify that the preference on the initial screen map is only Save and Fill toggle + + // Mandatory Reauth toggle + CVC storage toggle + Add Card button + Payment Apps. + Assert.assertEquals(5, getPreferenceScreen(activity).getPreferenceCount()); + ChromeSwitchPreference mandatoryReauthPreference = + (ChromeSwitchPreference) getPreferenceScreen(activity).getPreference(1); + Assert.assertEquals( + mandatoryReauthPreference.getTitle(), + activity.getString( + R.string + .autofill_settings_page_enable_payment_method_mandatory_reauth_label)); + Assert.assertTrue(mandatoryReauthPreference.isChecked()); + Assert.assertTrue(mandatoryReauthPreference.isEnabled()); + } + + @Test + @MediumTest + @Restriction(DeviceRestriction.RESTRICTION_TYPE_NON_AUTO) public void testMandatoryReauthToggle_switchValueOnClicked() throws Exception { var optInHistogram = HistogramWatcher.newBuilder()
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataTest.java index e6be3ee..15aac90 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataTest.java
@@ -43,7 +43,10 @@ /** Integration tests for browsing data deletion. */ @RunWith(ChromeJUnit4ClassRunner.class) -@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +@CommandLineFlags.Add({ + ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, + ChromeSwitches.SKIP_LOCAL_UPM_GMS_CORE_VERSION_CHECK_FOR_TESTING, +}) @Batch(Batch.PER_CLASS) public class BrowsingDataTest { private static final String TEST_FILE = "/content/test/data/browsing_data/site_data.html";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateIntegrationTest.java index 6bf51a79..d4a9ef76 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateIntegrationTest.java
@@ -26,11 +26,11 @@ import org.junit.runner.RunWith; import org.chromium.base.ContextUtils; -import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.HistogramWatcher; import org.chromium.base.test.util.PackageManagerWrapper; import org.chromium.chrome.browser.flags.ActivityType; import org.chromium.chrome.browser.flags.ChromeSwitches; @@ -176,15 +176,7 @@ }); } - private void waitForHistogram(String name, int count) { - CriteriaHelper.pollUiThread( - () -> { - return RecordHistogram.getHistogramTotalCountForTesting(name) >= count; - }, - "waitForHistogram timeout", - 10000, - 200); - } + private void waitForHistogram() {} private WebApkProto.WebApk parseRequestProto(String path) throws Exception { FileInputStream requestFile = new FileInputStream(path); @@ -199,13 +191,16 @@ @Feature({"Webapps"}) public void testStoreUpdateRequestToFile() throws Exception { String pageUrl = mTestServer.getURL(WEBAPK_START_URL); + HistogramWatcher histogramWatcher = + HistogramWatcher.newSingleRecordWatcher( + "WebApk.Update.ShellVersion", SHELL_APK_VERSION); WebappActivity activity = mActivityTestRule.startWebApkActivity(pageUrl); assertEquals(ActivityType.WEB_APK, activity.getActivityType()); assertEquals(pageUrl, activity.getIntentDataProvider().getUrlToLoad()); waitForDialog(); - waitForHistogram("WebApk.Update.RequestQueued", 1); + histogramWatcher.pollInstrumentationThreadUntilSatisfied(); WebappDataStorage storage = WebappRegistry.getInstance()
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java index 2f37ed0..ef82621 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
@@ -248,7 +248,7 @@ } @Override - protected void scheduleUpdate() { + protected void scheduleUpdate(int shellVersion) { if (mCompleteCallback != null) mCompleteCallback.notifyCalled(); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java index 9b8009e3..5fa9eff 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java
@@ -27,17 +27,20 @@ import org.robolectric.annotation.Implements; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.homepage.HomepageManager; +import org.chromium.chrome.browser.multiwindow.MultiWindowUtilsUnitTest.ShadowHomepageManager; import org.chromium.chrome.browser.multiwindow.MultiWindowUtilsUnitTest.ShadowMultiInstanceManagerApi31; -import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.test.AutomotiveContextWrapperTestRule; +import org.chromium.components.embedder_support.util.UrlConstants; +import org.chromium.url.GURL; /** Unit tests for {@link MultiWindowUtils}. */ @RunWith(BaseRobolectricTestRunner.class) @Config( manifest = Config.NONE, - shadows = {ShadowMultiInstanceManagerApi31.class}) + shadows = {ShadowMultiInstanceManagerApi31.class, ShadowHomepageManager.class}) public class MultiWindowUtilsUnitTest { /** Shadows {@link MultiInstanceManagerApi31} class for testing. */ @Implements(MultiInstanceManagerApi31.class) @@ -65,6 +68,28 @@ } } + /** Shadow for {@link HomepageManager}. */ + @Implements(HomepageManager.class) + public static class ShadowHomepageManager { + static GURL sHomepageGurl; + static boolean sIsHomepageEnabled; + + @Implementation + public static boolean isHomepageEnabled() { + return sIsHomepageEnabled; + } + + @Implementation + public static GURL getHomepageGurl() { + return sHomepageGurl; + } + + public static void reset() { + sIsHomepageEnabled = false; + sHomepageGurl = NTP_GURL; + } + } + @Rule public AutomotiveContextWrapperTestRule mAutomotiveContextWrapperTestRule = new AutomotiveContextWrapperTestRule(); @@ -78,6 +103,8 @@ private static final String URL_1 = "url1"; private static final String URL_2 = "url2"; private static final String URL_3 = "url3"; + private static final GURL NTP_GURL = new GURL(UrlConstants.NTP_URL); + private static final GURL TEST_GURL = new GURL("https://youtube.com/"); private MultiWindowUtils mUtils; private boolean mIsInMultiWindowMode; @@ -135,11 +162,15 @@ return super.isOpenInOtherWindowSupported(activity); } }; + ShadowHomepageManager.sIsHomepageEnabled = true; + ShadowHomepageManager.sHomepageGurl = NTP_GURL; } @After public void tearDown() { ShadowMultiInstanceManagerApi31.reset(); + ShadowHomepageManager.reset(); + mOverrideOpenInNewWindowSupported = false; } @Test @@ -215,27 +246,32 @@ } @Test - public void testIsMoveOtherWindowSupported_HasOneTabWithPartnerHomePageDisabled_ReturnsTrue() { - PartnerBrowserCustomizations partnerBrowserCustomizations = - mock(PartnerBrowserCustomizations.class); - when(partnerBrowserCustomizations.isHomepageProviderAvailableAndEnabled()) - .thenReturn(false); - PartnerBrowserCustomizations.setInstanceForTesting(partnerBrowserCustomizations); + public void testIsMoveOtherWindowSupported_HasOneTabWithHomePageDisabled_ReturnsTrue() { + ShadowHomepageManager.sIsHomepageEnabled = false; when(mTabModelSelector.getTotalTabCount()).thenReturn(1); - assertFalse( - "Should return true when called for last tab with no partner customization.", + mOverrideOpenInNewWindowSupported = true; + assertTrue( + "Should return true when called for last tab with homepage disabled.", mUtils.isMoveToOtherWindowSupported(null, mTabModelSelector)); } @Test - public void testIsMoveOtherWindowSupported_HasOneTabWithPartnerHomePage_ReturnsFalse() { - PartnerBrowserCustomizations partnerBrowserCustomizations = - mock(PartnerBrowserCustomizations.class); - when(partnerBrowserCustomizations.isHomepageProviderAvailableAndEnabled()).thenReturn(true); - PartnerBrowserCustomizations.setInstanceForTesting(partnerBrowserCustomizations); + public void testIsMoveOtherWindowSupported_HasOneTabWithHomePageEnabledAsNtp_ReturnsTrue() { + mOverrideOpenInNewWindowSupported = true; + when(mTabModelSelector.getTotalTabCount()).thenReturn(1); + assertTrue( + "Should return true when called for last tab with homepage enabled as NTP.", + mUtils.isMoveToOtherWindowSupported(null, mTabModelSelector)); + } + + @Test + public void + testIsMoveOtherWindowSupported_HasOneTabWithHomePageEnabledAsCustomUrl_ReturnsFalse() { + ShadowHomepageManager.sHomepageGurl = TEST_GURL; + ShadowHomepageManager.sIsHomepageEnabled = true; when(mTabModelSelector.getTotalTabCount()).thenReturn(1); assertFalse( - "Should return false when called for last tab with partner customization.", + "Should return false when called for last tab with homepage set as a custom url.", mUtils.isMoveToOtherWindowSupported(null, mTabModelSelector)); } @@ -249,23 +285,26 @@ } @Test - public void testHasAtMostOneTabWithHomepageEnabled_ReturnsTrue() { - PartnerBrowserCustomizations partnerBrowserCustomizations = - mock(PartnerBrowserCustomizations.class); - when(partnerBrowserCustomizations.isHomepageProviderAvailableAndEnabled()).thenReturn(true); - PartnerBrowserCustomizations.setInstanceForTesting(partnerBrowserCustomizations); + public void testHasAtMostOneTabWithHomepageEnabledAsCustomUrl_ReturnsTrue() { + ShadowHomepageManager.sHomepageGurl = TEST_GURL; when(mTabModelSelector.getTotalTabCount()).thenReturn(1); assertTrue( - "Should return true for last tab with partner homepage.", + "Should return true for last tab with homepage set to a custom url.", mUtils.hasAtMostOneTabWithHomepageEnabled(mTabModelSelector)); } @Test - public void testHasAtMostOneTabWithHomepageEnabled_WithMoreThanOneTab_ReturnsFalse() { - PartnerBrowserCustomizations partnerBrowserCustomizations = - mock(PartnerBrowserCustomizations.class); - when(partnerBrowserCustomizations.isHomepageProviderAvailableAndEnabled()).thenReturn(true); - PartnerBrowserCustomizations.setInstanceForTesting(partnerBrowserCustomizations); + public void testHasAtMostOneTabWithHomepageEnabledAsNtp_ReturnsFalse() { + when(mTabModelSelector.getTotalTabCount()).thenReturn(1); + assertFalse( + "Should return true for last tab with homepage as NTP.", + mUtils.hasAtMostOneTabWithHomepageEnabled(mTabModelSelector)); + } + + @Test + public void + testHasAtMostOneTabWithHomepageEnabledAsCustomUrl_WithMoreThanOneTab_ReturnsFalse() { + ShadowHomepageManager.sHomepageGurl = TEST_GURL; when(mTabModelSelector.getTotalTabCount()).thenReturn(2); assertFalse( "Should return false for multiple tabs.", @@ -273,12 +312,8 @@ } @Test - public void testHasAtMostOneTabWithHomepageEnabled_WithHomepageDisabled_ReturnsFalse() { - PartnerBrowserCustomizations partnerBrowserCustomizations = - mock(PartnerBrowserCustomizations.class); - when(partnerBrowserCustomizations.isHomepageProviderAvailableAndEnabled()) - .thenReturn(false); - PartnerBrowserCustomizations.setInstanceForTesting(partnerBrowserCustomizations); + public void testHasAtMostOneTabWith_WithHomepageDisabled_ReturnsFalse() { + ShadowHomepageManager.sIsHomepageEnabled = false; when(mTabModelSelector.getTotalTabCount()).thenReturn(1); assertFalse( "Should return false for homepage disabled.",
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkSyncServiceTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkSyncServiceTest.java new file mode 100644 index 0000000..6ecf86f --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkSyncServiceTest.java
@@ -0,0 +1,181 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.webapps; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.when; + +import android.content.res.Resources; +import android.graphics.Color; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.android.XmlResourceParserImpl; +import org.robolectric.annotation.Config; +import org.w3c.dom.Document; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider; +import org.chromium.chrome.browser.browserservices.intents.WebappIcon; +import org.chromium.chrome.browser.browserservices.intents.WebappInfo; +import org.chromium.chrome.test.util.browser.webapps.WebApkIntentDataProviderBuilder; +import org.chromium.components.sync.protocol.WebApkSpecifics; + +import java.io.ByteArrayInputStream; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +/** Tests the WebApkSyncService class */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class WebApkSyncServiceTest { + private static final String START_URL = "https://example.com/start"; + private static final String MANIFEST_ID = "https://example.com/id"; + private static final String PACKAGE_NAME = "org.chromium.webapk"; + private static final String SCOPE = "https://example.com/"; + private static final String NAME = "My App"; + private static final String SHORT_NAME = "app"; + private static final long TOOLBAR_COLOR = Color.WHITE; + private static final int PRIMARY_ICON_ID = 12; + private static final String ICON_URL = "https://example.com/icon.png"; + private static final String ICON_MURMUR2_HASH = "5"; + private static final String ICON_URL2 = "https://example.com/icon2.png"; + + @Mock private Resources mMockResources; + + private String mPrimaryIconXmlContents; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + private XmlResourceParserImpl getMockXmlResourceParserImpl() { + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + DocumentBuilder documentBuilder = factory.newDocumentBuilder(); + Document document = + documentBuilder.parse( + new ByteArrayInputStream(mPrimaryIconXmlContents.getBytes())); + + return new XmlResourceParserImpl(document, "file", PACKAGE_NAME, PACKAGE_NAME, null); + } catch (Exception e) { + return null; + } + } + + @Test + public void testGetWebApkSyncSpecifics() { + BrowserServicesIntentDataProvider intentDataProvider = + new WebApkIntentDataProviderBuilder(PACKAGE_NAME, START_URL) + .setWebApkManifestId(MANIFEST_ID) + .setName(NAME) + .setShortName(SHORT_NAME) + .setToolbarColor(TOOLBAR_COLOR) + .setScope(SCOPE) + .build(); + + WebappInfo webApkInfo = WebappInfo.create(intentDataProvider); + WebApkSpecifics webApkSpecifics = WebApkSyncService.getWebApkSpecifics(webApkInfo); + + assertEquals(MANIFEST_ID, webApkSpecifics.getManifestId()); + assertEquals(START_URL, webApkSpecifics.getStartUrl()); + assertEquals(SCOPE, webApkSpecifics.getScope()); + + assertTrue(webApkSpecifics.hasName()); + assertEquals(NAME, webApkSpecifics.getName()); + + assertTrue(webApkSpecifics.hasThemeColor()); + assertEquals(TOOLBAR_COLOR, webApkSpecifics.getThemeColor()); + + assertEquals(0, webApkSpecifics.getIconInfosCount()); + } + + @Test + public void testGetSyncSpecificsWithEmptyValues() { + BrowserServicesIntentDataProvider intentDataProvider = + new WebApkIntentDataProviderBuilder(PACKAGE_NAME, START_URL) + .setWebApkManifestId(MANIFEST_ID) + .setShortName(SHORT_NAME) + .build(); + + WebappInfo webApkInfo = WebappInfo.create(intentDataProvider); + WebApkSpecifics webApkSpecifics = WebApkSyncService.getWebApkSpecifics(webApkInfo); + + assertEquals(MANIFEST_ID, webApkSpecifics.getManifestId()); + assertEquals(START_URL, webApkSpecifics.getStartUrl()); + assertEquals(SCOPE, webApkSpecifics.getScope()); + + assertTrue(webApkSpecifics.hasName()); + assertEquals(SHORT_NAME, webApkSpecifics.getName()); + + assertEquals(0, webApkSpecifics.getThemeColor()); + assertEquals(0, webApkSpecifics.getIconInfosCount()); + } + + @Test + public void testGetIconInfo() throws Exception { + mPrimaryIconXmlContents = + String.format( + "<bitmap xmlns:android='http://schemas.android.com/apk/res/android'" + + " android:src='@mipmap/app_icon_xxhdpi'" + + " iconUrl='%s'" + + " iconHash='%s'" + + "/>", + ICON_URL, ICON_MURMUR2_HASH); + when(mMockResources.getXml(anyInt())).thenReturn(getMockXmlResourceParserImpl()); + + WebappIcon testIcon = + new WebappIcon( + PACKAGE_NAME, + PRIMARY_ICON_ID, + mMockResources, + WebappIcon.ICON_WITH_URL_AND_HASH_SHELL_VERSION); + BrowserServicesIntentDataProvider intentDataProvider = + new WebApkIntentDataProviderBuilder(PACKAGE_NAME, START_URL) + .setWebApkManifestId(MANIFEST_ID) + .setPrimaryIcon(testIcon) + .setShellApkVersion(WebappIcon.ICON_WITH_URL_AND_HASH_SHELL_VERSION) + .build(); + + WebappInfo webApkInfo = WebappInfo.create(intentDataProvider); + WebApkSpecifics webApkSpecifics = WebApkSyncService.getWebApkSpecifics(webApkInfo); + + assertEquals(1, webApkSpecifics.getIconInfosCount()); + assertEquals(ICON_URL, webApkSpecifics.getIconInfos(0).getUrl()); + } + + @Test + public void testGetIconsFallback() throws Exception { + WebappIcon testIcon = new WebappIcon(); + Map<String, String> iconUrlAndIconMurmur2HashMap = new HashMap<String, String>(); + iconUrlAndIconMurmur2HashMap.put(ICON_URL, ICON_MURMUR2_HASH); + iconUrlAndIconMurmur2HashMap.put(ICON_URL2, ICON_MURMUR2_HASH); + BrowserServicesIntentDataProvider intentDataProvider = + new WebApkIntentDataProviderBuilder(PACKAGE_NAME, START_URL) + .setWebApkManifestId(MANIFEST_ID) + .setPrimaryIcon(testIcon) + .setIconUrlToMurmur2HashMap(iconUrlAndIconMurmur2HashMap) + .build(); + + WebappInfo webApkInfo = WebappInfo.create(intentDataProvider); + WebApkSpecifics webApkSpecifics = WebApkSyncService.getWebApkSpecifics(webApkInfo); + + assertEquals(2, webApkSpecifics.getIconInfosCount()); + assertEquals(ICON_URL, webApkSpecifics.getIconInfos(0).getUrl()); + assertEquals(ICON_URL2, webApkSpecifics.getIconInfos(1).getUrl()); + } +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java index 255311c2..0911a5f6 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java
@@ -862,6 +862,7 @@ .build(); expectedIntentDataProviders.put(testScope2, intentDataProvider2); + // This one will not be returned because it has no manifest id. BrowserServicesIntentDataProvider intentDataProvider3 = new WebApkIntentDataProviderBuilder(testPackageName3, testStartUrl3) .setWebApkManifestId(testManifestId3) @@ -897,7 +898,7 @@ List<WebApkSpecifics> webApkSpecificsList = webApkRegistry.getWebApkSpecificsImpl(setWebappInfoForTesting); - assertEquals(3, webApkSpecificsList.size()); + assertEquals(2, webApkSpecificsList.size()); Set<String> visitedScopes = new HashSet<String>(); for (WebApkSpecifics webApkSpecifics : webApkSpecificsList) { @@ -932,7 +933,7 @@ visitedScopes.add(webApkSpecifics.getScope()); } - assertEquals(3, visitedScopes.size()); + assertEquals(2, visitedScopes.size()); } private Set<String> addWebappsToRegistry(String... webapps) {
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h index e0c34db0..84a96603 100644 --- a/chrome/app/chrome_command_ids.h +++ b/chrome/app/chrome_command_ids.h
@@ -247,7 +247,6 @@ #define IDC_CLOSE_SIGN_IN_PROMO 40258 #define IDC_SHOW_FULL_URLS 40259 #define IDC_CARET_BROWSING_TOGGLE 40260 -#define IDC_TOGGLE_QUICK_COMMANDS 40261 #define IDC_CHROME_TIPS 40263 #define IDC_CHROME_WHATS_NEW 40264
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 96deb45..6e9b5f7 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -707,7 +707,7 @@ </message> <message name="IDS_CONTENT_CONTEXT_SAVEVIDEOFRAMEAS" desc="The name of the Save Video Frame As command in the content area context menu"> - Sa&ve video frame as... + Save video &frame as... </message> <message name="IDS_CONTENT_CONTEXT_SAVEVIDEOAS" desc="The name of the Save Video As command in the content area context menu"> Sa&ve video as... @@ -716,10 +716,10 @@ C&opy video address </message> <message name="IDS_CONTENT_CONTEXT_COPYVIDEOFRAME" desc="The name of the Copy Video Frame command in the content area context menu"> - C&opy video frame + Cop&y video frame </message> <message name="IDS_CONTENT_CONTEXT_SEARCHFORVIDEOFRAME" desc="In Title Case: The name of the Lens Search command in the content area context menu"> - Search video frame with <ph name="VISUAL_SEARCH_PROVIDER">$1<ex>Google Lens</ex></ph> + &Search video frame with <ph name="VISUAL_SEARCH_PROVIDER">$1<ex>Google Lens</ex></ph> </message> <message name="IDS_CONTENT_CONTEXT_OPENVIDEONEWTAB" desc="The name of the Open Video in New Tab command in the content area context menu"> &Open video in new tab @@ -985,7 +985,7 @@ </message> <message name="IDS_CONTENT_CONTEXT_SAVEVIDEOFRAMEAS" desc="In Title Case: The name of the Save Video Frame As command in the content area context menu"> - Sa&ve Video Frame As... + Save Video &Frame As... </message> <message name="IDS_CONTENT_CONTEXT_SAVEVIDEOAS" desc="In Title Case: The name of the Save Video As command in the content area context menu"> Sa&ve Video As... @@ -994,10 +994,10 @@ C&opy Video Address </message> <message name="IDS_CONTENT_CONTEXT_COPYVIDEOFRAME" desc="The name of the Copy Video Frame command in the content area context menu"> - C&opy Video Frame + Cop&y Video Frame </message> <message name="IDS_CONTENT_CONTEXT_SEARCHFORVIDEOFRAME" desc="In Title Case: The name of the Lens Search command in the content area context menu"> - Search Video Frame with <ph name="VISUAL_SEARCH_PROVIDER">$1<ex>Google Lens</ex></ph> + &Search Video Frame with <ph name="VISUAL_SEARCH_PROVIDER">$1<ex>Google Lens</ex></ph> </message> <message name="IDS_CONTENT_CONTEXT_OPENVIDEONEWTAB" desc="In Title Case: The name of the Open Video in New Tab command in the content area context menu"> &Open Video in New Tab @@ -1290,9 +1290,6 @@ <message name="IDS_MOVE_TAB_TO_NEW_WINDOW" desc="The text label of the Move Tab to Window menu item."> Move tab to new window </message> - <message name="IDS_TOGGLE_QUICK_COMMANDS" desc="The text label of the Toggle Quick Commands menu item"> - Quick commands - </message> <message name="IDS_SEARCH_TABS" desc="The text label of the Search Tabs... menu item"> Search tabs... </message> @@ -1433,9 +1430,6 @@ <message name="IDS_MOVE_TAB_TO_NEW_WINDOW" desc="In Title Case: The text label of the Move Tab to New Window menu item."> Move Tab to New Window </message> - <message name="IDS_TOGGLE_QUICK_COMMANDS" desc="In Title Case:The text label of the Toggle Quick Commands menu item"> - Quick Commands - </message> <message name="IDS_SEARCH_TABS" desc="In Title Case:The text label of the Search Tabs... menu item"> Search Tabs... </message> @@ -8415,6 +8409,9 @@ <message name="IDS_ACCNAME_SEARCH_SUGG" desc="The accessible name for the search suggestion tile in the NTP Journeys Module."> Search for <ph name="QUERY_CLUSTER_NAME">$1<ex>Office Chairs</ex></ph> </message> + <message name="IDS_NTP_MODULES_TAB_RESUMPTION_DISMISS_BUTTON" desc="A label for the dismiss button in the dropdown."> + No longer interested + </message> <message name="IDS_NTP_TAB_RESUMPTION_TITLE" desc="Name of the tab resumption module in sentence case shown in various UIs."> Tabs from other devices </message> @@ -8424,6 +8421,9 @@ <ph name="BREAK"><br></ph> You can manage settings from the card menu or see more options in Customize Chrome. </message> + <message name="IDS_NTP_MODULES_TAB_RESUMPTION_SENTENCE" desc="Name of the tabs in the Tab Resumption module in sentence case shown in various UIs."> + Tabs + </message> <!-- Extensions NTP Middle Slot Promo --> <message name="IDS_EXTENSIONS_PROMO_PERFORMANCE"> @@ -13685,22 +13685,22 @@ Control and reprogramming of MIDI devices blocked </message> <message name="IDS_ALLOWED_MIDI_SYSEX_MESSAGE" desc="Info bubble message and location bar icon tooltip text shown when a site has been allowed to use MIDI system exclusive messages."> - This site can control and reprogram your MIDI devices (SysEx). + This site can control and reprogram your MIDI devices </message> <message name="IDS_ALLOWED_MIDI_SYSEX_BLOCK" desc="Radio button to block access to use MIDI system exclusive messages."> - Always block <ph name="HOST">$1<ex>example.com</ex></ph> from controlling and reprogramming your MIDI devices. + Always block <ph name="HOST">$1<ex>example.com</ex></ph> from controlling and reprogramming your MIDI devices </message> <message name="IDS_ALLOWED_MIDI_SYSEX_NO_ACTION" desc="Radio button to keep allowing access to use MIDI system exclusive messages."> - Continue allowing this site to control and reprogram your MIDI devices. + Continue allowing this site to control and reprogram your MIDI devices </message> <message name="IDS_BLOCKED_MIDI_SYSEX_MESSAGE" desc="Info bubble message and location bar icon tooltip text shown when a site has been denied access to use MIDI system exclusive messages."> - This site has been blocked from controlling and reprogramming your MIDI devices (SysEx). + This site has been blocked from controlling and reprogramming your MIDI devices </message> <message name="IDS_BLOCKED_MIDI_SYSEX_UNBLOCK" desc="Radio button choice to unblock a site from using MIDI system exclusive messages."> - Always allow <ph name="HOST">$1<ex>mail.google.com</ex></ph> to control and reprogram your MIDI devices. + Always allow <ph name="HOST">$1<ex>mail.google.com</ex></ph> to control and reprogram your MIDI devices </message> <message name="IDS_BLOCKED_MIDI_SYSEX_NO_ACTION" desc="Radio button choice to continue blocking a site from using MIDI system exclusive messages."> - Continue blocking this site from controlling and reprogramming your MIDI devices. + Continue blocking this site from controlling and reprogramming your MIDI devices </message> <!-- Media Stream --> @@ -16116,18 +16116,6 @@ desc="Label of the text field used to enter the new window name."> Window name </message> - <message name="IDS_QUICK_COMMANDS_LABEL" - desc="Label to identify the Quick Commands feature in Task Manager"> - Quick Commands - </message> - <message name="IDS_QUICK_COMMANDS_PLACEHOLDER" - desc="Placeholder text for the Quick Commands text input"> - Enter a keyword like "tabs" or "windows" to find an action - </message> - <message name="IDS_QUICK_COMMANDS_NO_RESULTS" - desc="Shown when there are no results in Quick Commands"> - No commands found - </message> <!-- ChromeLabs bubble --> <message name="IDS_CHROMELABS_RELAUNCH_BUTTON_LABEL"
diff --git a/chrome/app/generated_resources_grd/IDS_ALLOWED_MIDI_SYSEX_BLOCK.png.sha1 b/chrome/app/generated_resources_grd/IDS_ALLOWED_MIDI_SYSEX_BLOCK.png.sha1 index 8b203ce..3e78031 100644 --- a/chrome/app/generated_resources_grd/IDS_ALLOWED_MIDI_SYSEX_BLOCK.png.sha1 +++ b/chrome/app/generated_resources_grd/IDS_ALLOWED_MIDI_SYSEX_BLOCK.png.sha1
@@ -1 +1 @@ -ea3ce3c4ce561aa46d50b311c32b0686d19485e3 \ No newline at end of file +113b2ddcb17ef5f4fc02a7916c9b9ad4589b5f3d \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ALLOWED_MIDI_SYSEX_MESSAGE.png.sha1 b/chrome/app/generated_resources_grd/IDS_ALLOWED_MIDI_SYSEX_MESSAGE.png.sha1 index 8b203ce..3e78031 100644 --- a/chrome/app/generated_resources_grd/IDS_ALLOWED_MIDI_SYSEX_MESSAGE.png.sha1 +++ b/chrome/app/generated_resources_grd/IDS_ALLOWED_MIDI_SYSEX_MESSAGE.png.sha1
@@ -1 +1 @@ -ea3ce3c4ce561aa46d50b311c32b0686d19485e3 \ No newline at end of file +113b2ddcb17ef5f4fc02a7916c9b9ad4589b5f3d \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ALLOWED_MIDI_SYSEX_NO_ACTION.png.sha1 b/chrome/app/generated_resources_grd/IDS_ALLOWED_MIDI_SYSEX_NO_ACTION.png.sha1 index 8b203ce..3e78031 100644 --- a/chrome/app/generated_resources_grd/IDS_ALLOWED_MIDI_SYSEX_NO_ACTION.png.sha1 +++ b/chrome/app/generated_resources_grd/IDS_ALLOWED_MIDI_SYSEX_NO_ACTION.png.sha1
@@ -1 +1 @@ -ea3ce3c4ce561aa46d50b311c32b0686d19485e3 \ No newline at end of file +113b2ddcb17ef5f4fc02a7916c9b9ad4589b5f3d \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_BLOCKED_MIDI_SYSEX_MESSAGE.png.sha1 b/chrome/app/generated_resources_grd/IDS_BLOCKED_MIDI_SYSEX_MESSAGE.png.sha1 index 2de32d24..3792ad9 100644 --- a/chrome/app/generated_resources_grd/IDS_BLOCKED_MIDI_SYSEX_MESSAGE.png.sha1 +++ b/chrome/app/generated_resources_grd/IDS_BLOCKED_MIDI_SYSEX_MESSAGE.png.sha1
@@ -1 +1 @@ -e52333a05f50195cc322ee656e33081324c6785a \ No newline at end of file +22183840296ec599f539876ad56516384671e298 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_BLOCKED_MIDI_SYSEX_NO_ACTION.png.sha1 b/chrome/app/generated_resources_grd/IDS_BLOCKED_MIDI_SYSEX_NO_ACTION.png.sha1 index 2de32d24..3792ad9 100644 --- a/chrome/app/generated_resources_grd/IDS_BLOCKED_MIDI_SYSEX_NO_ACTION.png.sha1 +++ b/chrome/app/generated_resources_grd/IDS_BLOCKED_MIDI_SYSEX_NO_ACTION.png.sha1
@@ -1 +1 @@ -e52333a05f50195cc322ee656e33081324c6785a \ No newline at end of file +22183840296ec599f539876ad56516384671e298 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_BLOCKED_MIDI_SYSEX_UNBLOCK.png.sha1 b/chrome/app/generated_resources_grd/IDS_BLOCKED_MIDI_SYSEX_UNBLOCK.png.sha1 index 2de32d24..3792ad9 100644 --- a/chrome/app/generated_resources_grd/IDS_BLOCKED_MIDI_SYSEX_UNBLOCK.png.sha1 +++ b/chrome/app/generated_resources_grd/IDS_BLOCKED_MIDI_SYSEX_UNBLOCK.png.sha1
@@ -1 +1 @@ -e52333a05f50195cc322ee656e33081324c6785a \ No newline at end of file +22183840296ec599f539876ad56516384671e298 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_MODULES_TAB_RESUMPTION_DISMISS_BUTTON.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_MODULES_TAB_RESUMPTION_DISMISS_BUTTON.png.sha1 new file mode 100644 index 0000000..eb5d196 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_NTP_MODULES_TAB_RESUMPTION_DISMISS_BUTTON.png.sha1
@@ -0,0 +1 @@ +1c3b657dcbcf95a058bd8742026e19bd3213d2f2 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_MODULES_TAB_RESUMPTION_SENTENCE.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_MODULES_TAB_RESUMPTION_SENTENCE.png.sha1 new file mode 100644 index 0000000..0b660b3 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_NTP_MODULES_TAB_RESUMPTION_SENTENCE.png.sha1
@@ -0,0 +1 @@ +4fceb425f89301f31f411d6e38cf226857a0ab35 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_QUICK_COMMANDS_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_QUICK_COMMANDS_LABEL.png.sha1 deleted file mode 100644 index 6bfa2fc..0000000 --- a/chrome/app/generated_resources_grd/IDS_QUICK_COMMANDS_LABEL.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -e305501bbd68e9722c49b0da2128b9abc4c56f30 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_QUICK_COMMANDS_NO_RESULTS.png.sha1 b/chrome/app/generated_resources_grd/IDS_QUICK_COMMANDS_NO_RESULTS.png.sha1 deleted file mode 100644 index fd544a5..0000000 --- a/chrome/app/generated_resources_grd/IDS_QUICK_COMMANDS_NO_RESULTS.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -185849eea17493d7cad20948a2f24afb927bf31e \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_QUICK_COMMANDS_PLACEHOLDER.png.sha1 b/chrome/app/generated_resources_grd/IDS_QUICK_COMMANDS_PLACEHOLDER.png.sha1 deleted file mode 100644 index 527942ba..0000000 --- a/chrome/app/generated_resources_grd/IDS_QUICK_COMMANDS_PLACEHOLDER.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -d35ab5350649d7d682cd092c813acc9ab361163a \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TOGGLE_QUICK_COMMANDS.png.sha1 b/chrome/app/generated_resources_grd/IDS_TOGGLE_QUICK_COMMANDS.png.sha1 deleted file mode 100644 index e2edf8a..0000000 --- a/chrome/app/generated_resources_grd/IDS_TOGGLE_QUICK_COMMANDS.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -fad73dc15316d3dfad90ebc691577fb7cb76944e \ No newline at end of file
diff --git a/chrome/app/profiles_strings.grdp b/chrome/app/profiles_strings.grdp index beffac0a..e14871d0 100644 --- a/chrome/app/profiles_strings.grdp +++ b/chrome/app/profiles_strings.grdp
@@ -141,6 +141,9 @@ Hide Accounts </message> </if> + <message name="IDS_PROFILES_MANAGED_BY" desc="Label shown under the avatar in the avatar menu bubble view stating that the account is managed."> + managed by <ph name="VALUE">$1<ex>1</ex></ph> + </message> <message name="IDS_PROFILES_MANAGE_PROFILES_BUTTON_TOOLTIP" desc="Button in the avatar menu bubble view for launching the profile picker."> Manage profiles </message>
diff --git a/chrome/app/profiles_strings_grdp/IDS_PROFILES_MANAGED_BY.png.sha1 b/chrome/app/profiles_strings_grdp/IDS_PROFILES_MANAGED_BY.png.sha1 new file mode 100644 index 0000000..9e6b7d9 --- /dev/null +++ b/chrome/app/profiles_strings_grdp/IDS_PROFILES_MANAGED_BY.png.sha1
@@ -0,0 +1 @@ +49a7bae21961528be6faf5a0384c0971424a5dd8 \ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 3050b33..9fc4073 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -1215,8 +1215,11 @@ <message name="IDS_SETTINGS_LANGUAGES_EXPAND_ACCESSIBILITY_LABEL" desc="Label for the button that toggles showing the language options. Only visible by screen reader software."> Show language options </message> - <message name="IDS_SETTINGS_LANGUAGES_PREFERRED_LANGUAGES_DESC" desc="Explanatory message about the list of preferred languages."> - Websites will show content in your preferred languages, when possible + <message name="IDS_SETTINGS_LANGUAGES_PREFERRED_LANGUAGES_HEADER" desc="Header of the explanatory message about the list of preferred languages."> + Websites in your languages + </message> + <message name="IDS_SETTINGS_LANGUAGES_PREFERRED_LANGUAGES_DESC" desc="Description text of the explanatory message about the list of preferred languages."> + Let websites know the languages you speak. They'll show content in those languages, when possible. </message> <message name="IDS_SETTINGS_LANGUAGES_OFFER_TO_ENABLE_TRANSLATE" desc="The label of the check-box that enables the prompt to translate a page."> Use Google Translate @@ -2802,19 +2805,19 @@ Not allowed to use your microphone </message> <message name="IDS_SETTINGS_SITE_SETTINGS_MIDI_DESCRIPTION" desc="Description of the MIDI devices content setting."> - Sites usually use MIDI devices for features for creating and editing music + Sites usually ask to control and reprogram MIDI devices to create music, edit music, or update device firmware </message> <message name="IDS_SETTINGS_SITE_SETTINGS_MIDI_ALLOWED" desc="Label for the enabled option of the MIDI devices content setting."> - Sites can ask to use your MIDI devices + Sites can ask to control and reprogram your MIDI devices </message> <message name="IDS_SETTINGS_SITE_SETTINGS_MIDI_BLOCKED" desc="Label for the disabled option of the MIDI devices content setting."> - Don't allow sites to use your MIDI devices + Don't allow sites to control and reprogram your MIDI devices </message> <message name="IDS_SETTINGS_SITE_SETTINGS_MIDI_ALLOWED_EXCEPTIONS" desc="Label for the allowed exceptions site list of the MIDI devices content setting."> - Allowed to use your MIDI devices + Allowed to control and reprogram your MIDI devices </message> <message name="IDS_SETTINGS_SITE_SETTINGS_MIDI_BLOCKED_EXCEPTIONS" desc="Label for the blocked exceptions site list of the MIDI devices content setting."> - Not allowed to use your MIDI devices + Not allowed to control and reprogram your MIDI devices </message> <message name="IDS_SETTINGS_SITE_SETTINGS_MOTION_SENSORS_DESCRIPTION" desc="Description of the motion sensors content setting."> Sites usually use your device's motion sensors for features like virtual reality or fitness tracking
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_LANGUAGES_PREFERRED_LANGUAGES_DESC.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_LANGUAGES_PREFERRED_LANGUAGES_DESC.png.sha1 index 5b6c75e..5f26c5e 100644 --- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_LANGUAGES_PREFERRED_LANGUAGES_DESC.png.sha1 +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_LANGUAGES_PREFERRED_LANGUAGES_DESC.png.sha1
@@ -1 +1 @@ -98ffb44cda9e1e09e6f5a94faca77a641d7cdf09 \ No newline at end of file +f85924c7fd33ed50c114feccc123a4b7f113ec05 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_LANGUAGES_PREFERRED_LANGUAGES_HEADER.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_LANGUAGES_PREFERRED_LANGUAGES_HEADER.png.sha1 new file mode 100644 index 0000000..5f26c5e --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_LANGUAGES_PREFERRED_LANGUAGES_HEADER.png.sha1
@@ -0,0 +1 @@ +f85924c7fd33ed50c114feccc123a4b7f113ec05 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_ALLOWED.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_ALLOWED.png.sha1 index 8a2179f..2db4c67 100644 --- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_ALLOWED.png.sha1 +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_ALLOWED.png.sha1
@@ -1 +1 @@ -15c343df6aa67ab938ec6de37c3db9e847c9ce46 \ No newline at end of file +a9e3eaf9dde5812b4779bd786b9fd51542af02c9 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_ALLOWED_EXCEPTIONS.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_ALLOWED_EXCEPTIONS.png.sha1 index 8a2179f..2db4c67 100644 --- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_ALLOWED_EXCEPTIONS.png.sha1 +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_ALLOWED_EXCEPTIONS.png.sha1
@@ -1 +1 @@ -15c343df6aa67ab938ec6de37c3db9e847c9ce46 \ No newline at end of file +a9e3eaf9dde5812b4779bd786b9fd51542af02c9 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_BLOCKED.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_BLOCKED.png.sha1 index 8a2179f..2db4c67 100644 --- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_BLOCKED.png.sha1 +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_BLOCKED.png.sha1
@@ -1 +1 @@ -15c343df6aa67ab938ec6de37c3db9e847c9ce46 \ No newline at end of file +a9e3eaf9dde5812b4779bd786b9fd51542af02c9 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_BLOCKED_EXCEPTIONS.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_BLOCKED_EXCEPTIONS.png.sha1 index 8a2179f..2db4c67 100644 --- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_BLOCKED_EXCEPTIONS.png.sha1 +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_BLOCKED_EXCEPTIONS.png.sha1
@@ -1 +1 @@ -15c343df6aa67ab938ec6de37c3db9e847c9ce46 \ No newline at end of file +a9e3eaf9dde5812b4779bd786b9fd51542af02c9 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_DESCRIPTION.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_DESCRIPTION.png.sha1 index 8a2179f..2db4c67 100644 --- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_DESCRIPTION.png.sha1 +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_MIDI_DESCRIPTION.png.sha1
@@ -1 +1 @@ -15c343df6aa67ab938ec6de37c3db9e847c9ce46 \ No newline at end of file +a9e3eaf9dde5812b4779bd786b9fd51542af02c9 \ No newline at end of file
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn index 2bbf4044..d7f22a5 100644 --- a/chrome/app/vector_icons/BUILD.gn +++ b/chrome/app/vector_icons/BUILD.gn
@@ -171,7 +171,6 @@ "privacy_tip.icon", "qr_code_chrome_refresh.icon", "qrcode_generator.icon", - "quick_commands.icon", "read_anything_letter_spacing.icon", "read_anything_letter_spacing_standard.icon", "read_anything_letter_spacing_very_wide.icon",
diff --git a/chrome/app/vector_icons/quick_commands.icon b/chrome/app/vector_icons/quick_commands.icon deleted file mode 100644 index 591dbeec..0000000 --- a/chrome/app/vector_icons/quick_commands.icon +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -CANVAS_DIMENSIONS, 16, -MOVE_TO, 1.6f, 14.04f, -R_V_LINE_TO, -1.64f, -R_H_LINE_TO, 12.8f, -R_V_LINE_TO, 1.64f, -CLOSE, -MOVE_TO, 12.8f, 11.2f, -V_LINE_TO, 2.4f, -R_H_LINE_TO, 1.09f, -R_V_LINE_TO, 8.8f, -CLOSE, -R_MOVE_TO, -10.23f, 0, -R_LINE_TO, 3.51f, -8.8f, -R_H_LINE_TO, 1.98f, -R_LINE_TO, 3.46f, 8.8f, -H_LINE_TO, 9.49f, -R_LINE_TO, -0.75f, -2.11f, -H_LINE_TO, 5.29f, -R_LINE_TO, -0.77f, 2.11f, -CLOSE, -R_MOVE_TO, 3.2f, -3.53f, -R_H_LINE_TO, 2.47f, -LINE_TO, 7.04f, 4.27f, -H_LINE_TO, 6.98f, -CLOSE \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index e2033c2..fb5527ec 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1798,6 +1798,10 @@ "tpcd/metadata/updater_service.h", "tpcd/metadata/updater_service_factory.cc", "tpcd/metadata/updater_service_factory.h", + "tpcd/support/top_level_trial_service.cc", + "tpcd/support/top_level_trial_service.h", + "tpcd/support/top_level_trial_service_factory.cc", + "tpcd/support/top_level_trial_service_factory.h", "tpcd/support/tpcd_support_service.cc", "tpcd/support/tpcd_support_service.h", "tpcd/support/tpcd_support_service_factory.cc", @@ -3030,6 +3034,7 @@ "commerce/android/shopping_service_factory_android.cc", "commerce/price_tracking/android/price_tracking_notification_bridge.cc", "commerce/price_tracking/android/price_tracking_notification_bridge.h", + "content_extraction/android/inner_text_bridge.cc", "content_settings/request_desktop_site_web_contents_observer_android.cc", "content_settings/request_desktop_site_web_contents_observer_android.h", "data_sharing/android/data_sharing_service_factory_android.cc", @@ -3431,6 +3436,7 @@ "//chrome/browser/commerce/merchant_viewer:merchant_viewer_data_manager", "//chrome/browser/commerce/merchant_viewer/android:jni_headers", "//chrome/browser/consent_auditor/android:jni_headers", + "//chrome/browser/content_extraction/android:jni_headers", "//chrome/browser/device_reauth/android:jni_headers", "//chrome/browser/download/internal/android", "//chrome/browser/feed/android:jni_headers",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 841242f7..1efb92a 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -302,7 +302,6 @@ #if BUILDFLAG(IS_MAC) #include "chrome/browser/ui/browser_dialogs.h" -#include "chrome/browser/ui/cocoa/screentime/screentime_features.h" #endif // BUILDFLAG(IS_MAC) #if BUILDFLAG(ENABLE_EXTENSIONS) @@ -8001,12 +8000,6 @@ FEATURE_VALUE_TYPE(ash::features::kExoSurroundingTextOffset)}, #endif // BUILDFLAG(IS_CHROMEOS_ASH) -#if BUILDFLAG(IS_MAC) - {"screentime", flag_descriptions::kScreenTimeName, - flag_descriptions::kScreenTimeDescription, kOsMac, - FEATURE_VALUE_TYPE(screentime::kScreenTime)}, -#endif - {"enable-heavy-ad-intervention", flag_descriptions::kHeavyAdInterventionName, flag_descriptions::kHeavyAdInterventionDescription, kOsAll, @@ -8459,13 +8452,6 @@ FEATURE_VALUE_TYPE(messages::kMessagesForAndroidStackingAnimation)}, #endif -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \ - BUILDFLAG(IS_FUCHSIA) - {"quick-commands", flag_descriptions::kQuickCommandsName, - flag_descriptions::kQuickCommandsDescription, kOsDesktop, - FEATURE_VALUE_TYPE(features::kQuickCommands)}, -#endif - #if BUILDFLAG(IS_ANDROID) {"quick-delete-for-android", flag_descriptions::kQuickDeleteForAndroidName, flag_descriptions::kQuickDeleteForAndroidDescription, kOsAndroid,
diff --git a/chrome/browser/android/browserservices/metrics/java/src/org/chromium/chrome/browser/browserservices/metrics/WebApkUmaRecorder.java b/chrome/browser/android/browserservices/metrics/java/src/org/chromium/chrome/browser/browserservices/metrics/WebApkUmaRecorder.java index ea75122..d9451c23 100644 --- a/chrome/browser/android/browserservices/metrics/java/src/org/chromium/chrome/browser/browserservices/metrics/WebApkUmaRecorder.java +++ b/chrome/browser/android/browserservices/metrics/java/src/org/chromium/chrome/browser/browserservices/metrics/WebApkUmaRecorder.java
@@ -38,17 +38,6 @@ } // This enum is used to back UMA histograms, and should therefore be treated as append-only. - // The queued request times shouldn't exceed three. - @IntDef({UpdateRequestQueued.ONCE, UpdateRequestQueued.TWICE, UpdateRequestQueued.THREE_TIMES}) - @Retention(RetentionPolicy.SOURCE) - public @interface UpdateRequestQueued { - int ONCE = 0; - int TWICE = 1; - int THREE_TIMES = 2; - int NUM_ENTRIES = 3; - } - - // This enum is used to back UMA histograms, and should therefore be treated as append-only. @IntDef({ GooglePlayInstallResult.SUCCESS, GooglePlayInstallResult.FAILED_NO_DELEGATE, @@ -90,17 +79,10 @@ int NUM_ENTRIES = 16; } - // This enum is used to back UMA histograms, and should therefore be treated as append-only. - @IntDef({WebApkUserTheme.LIGHT_THEME, WebApkUserTheme.DARK_THEME, WebApkUserTheme.NUM_ENTRIES}) - public @interface WebApkUserTheme { - int LIGHT_THEME = 0; - int DARK_THEME = 1; - int NUM_ENTRIES = 2; - } - public static final String HISTOGRAM_UPDATE_REQUEST_SENT = "WebApk.Update.RequestSent"; - public static final String HISTOGRAM_UPDATE_REQUEST_QUEUED = "WebApk.Update.RequestQueued"; + public static final String HISTOGRAM_UPDATE_REQUEST_SHELL_VERSION = + "WebApk.Update.ShellVersion"; private static final String HISTOGRAM_LAUNCH_TO_SPLASHSCREEN_VISIBLE = "WebApk.Startup.Cold.ShellLaunchToSplashscreenVisible"; @@ -126,11 +108,12 @@ /** * Records the times that an update request has been queued once, twice and three times before * sending to WebAPK server. + * * @param times representing the times that an update has been queued. */ - public static void recordUpdateRequestQueued(@UpdateRequestQueued int times) { - RecordHistogram.recordEnumeratedHistogram( - HISTOGRAM_UPDATE_REQUEST_QUEUED, times, UpdateRequestQueued.NUM_ENTRIES); + public static void recordQueuedUpdateShellVersion(int shellApkVersion) { + RecordHistogram.recordSparseHistogram( + HISTOGRAM_UPDATE_REQUEST_SHELL_VERSION, shellApkVersion); } /**
diff --git a/chrome/browser/android/webapk/webapk_sync_service.cc b/chrome/browser/android/webapk/webapk_sync_service.cc index f799d02..f1a2cd28 100644 --- a/chrome/browser/android/webapk/webapk_sync_service.cc +++ b/chrome/browser/android/webapk/webapk_sync_service.cc
@@ -4,8 +4,22 @@ #include "chrome/browser/android/webapk/webapk_sync_service.h" +#include <jni.h> + +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "base/android/scoped_java_ref.h" +#include "base/feature_list.h" #include "base/functional/callback_helpers.h" +#include "base/logging.h" +#include "chrome/android/chrome_jni_headers/WebApkSyncService_jni.h" #include "chrome/browser/android/webapk/webapk_sync_service_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "components/sync/base/features.h" + +using base::android::JavaParamRef; +using base::android::JavaRef; namespace webapk { @@ -39,4 +53,35 @@ return sync_bridge_->GetModelTypeControllerDelegate(); } +void WebApkSyncService::OnWebApkUsed( + std::unique_ptr<sync_pb::WebApkSpecifics> app_specifics) { + sync_bridge_->OnWebApkUsed(std::move(app_specifics)); +} + +// static +static void JNI_WebApkSyncService_OnWebApkUsed( + JNIEnv* env, + const JavaParamRef<jbyteArray>& java_webapk_specifics) { + if (!base::FeatureList::IsEnabled(syncer::kWebApkBackupAndRestoreBackend)) { + return; + } + + Profile* profile = ProfileManager::GetLastUsedProfile(); + if (profile == nullptr) { + return; + } + + std::string specifics_bytes; + base::android::JavaByteArrayToString(env, java_webapk_specifics, + &specifics_bytes); + + std::unique_ptr<sync_pb::WebApkSpecifics> specifics = + std::make_unique<sync_pb::WebApkSpecifics>(); + if (!specifics->ParseFromString(specifics_bytes)) { + LOG(ERROR) << "failed to parse WebApkSpecifics proto"; + return; + } + WebApkSyncService::GetForProfile(profile)->OnWebApkUsed(std::move(specifics)); +} + } // namespace webapk
diff --git a/chrome/browser/android/webapk/webapk_sync_service.h b/chrome/browser/android/webapk/webapk_sync_service.h index fb63ebf..48bf152 100644 --- a/chrome/browser/android/webapk/webapk_sync_service.h +++ b/chrome/browser/android/webapk/webapk_sync_service.h
@@ -30,6 +30,8 @@ base::WeakPtr<syncer::ModelTypeControllerDelegate> GetModelTypeControllerDelegate(); + void OnWebApkUsed(std::unique_ptr<sync_pb::WebApkSpecifics> app_specifics); + private: std::unique_ptr<AbstractWebApkDatabaseFactory> database_factory_; std::unique_ptr<WebApkSyncBridge> sync_bridge_;
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn index 0f07a311..7e0201b 100644 --- a/chrome/browser/ash/BUILD.gn +++ b/chrome/browser/ash/BUILD.gn
@@ -2147,8 +2147,6 @@ "login/users/chrome_user_manager_util.h", "login/users/default_user_image/default_user_images.cc", "login/users/default_user_image/default_user_images.h", - "login/users/multi_profile_user_controller.cc", - "login/users/multi_profile_user_controller.h", "login/users/scoped_test_user_manager.cc", "login/users/scoped_test_user_manager.h", "login/users/test_users.cc", @@ -5689,7 +5687,7 @@ "login/user_online_signin_notifier_unittest.cc", "login/users/avatar/user_image_loader_unittest.cc", "login/users/default_user_image/default_user_images_unittest.cc", - "login/users/multi_profile_user_controller_unittest.cc", + "login/users/multi_user_sign_in_policy_controller_unittest.cc", "login/users/user_manager_unittest.cc", "login/version_updater/update_time_estimator_unittest.cc", "login/version_updater/version_updater_unittest.cc",
diff --git a/chrome/browser/ash/crosapi/test_controller_ash.cc b/chrome/browser/ash/crosapi/test_controller_ash.cc index 52ddd681..9cf78a0 100644 --- a/chrome/browser/ash/crosapi/test_controller_ash.cc +++ b/chrome/browser/ash/crosapi/test_controller_ash.cc
@@ -13,6 +13,8 @@ #include "ash/constants/ash_pref_names.h" #include "ash/public/cpp/shelf_item_delegate.h" #include "ash/public/cpp/shelf_model.h" +#include "ash/public/cpp/shelf_test_api.h" +#include "ash/public/cpp/split_view_test_api.h" #include "ash/public/cpp/system/toast_manager.h" #include "ash/public/cpp/tablet_mode.h" #include "ash/public/cpp/window_properties.h" @@ -66,6 +68,7 @@ #include "content/public/browser/tts_utterance.h" #include "crypto/sha2.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" +#include "mojo/public/cpp/bindings/type_converter.h" #include "printing/buildflags/buildflags.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" @@ -92,6 +95,20 @@ #include "chrome/browser/ash/printing/test_cups_print_job_manager.h" #endif // BUILDFLAG(USE_CUPS) +namespace mojo { +// static +ash::SnapPosition +TypeConverter<ash::SnapPosition, crosapi::mojom::SnapPosition>::Convert( + crosapi::mojom::SnapPosition position) { + switch (position) { + case crosapi::mojom::SnapPosition::kPrimary: + return ash::SnapPosition::kPrimary; + case crosapi::mojom::SnapPosition::kSecondary: + return ash::SnapPosition::kSecondary; + } +} +} // namespace mojo + namespace crosapi { namespace { @@ -962,6 +979,20 @@ ash_utterance_event_delegates_.erase(utterance_id); } +void TestControllerAsh::SnapWindow(const std::string& window_id, + mojom::SnapPosition position, + SnapWindowCallback callback) { + aura::Window* window = GetShellSurfaceWindow(window_id); + CHECK(window); + ash::SplitViewTestApi().SnapWindow( + window, mojo::ConvertTo<ash::SnapPosition>(position)); + std::move(callback).Run(); +} + +void TestControllerAsh::IsShelfVisible(IsShelfVisibleCallback callback) { + std::move(callback).Run(ash::ShelfTestApi().IsVisible()); +} + // This class waits for overview mode to either enter or exit and fires a // callback. This class will fire the callback at most once. class TestControllerAsh::OverviewWaiter : public ash::OverviewObserver {
diff --git a/chrome/browser/ash/crosapi/test_controller_ash.h b/chrome/browser/ash/crosapi/test_controller_ash.h index 29f5318a..50e4a151 100644 --- a/chrome/browser/ash/crosapi/test_controller_ash.h +++ b/chrome/browser/ash/crosapi/test_controller_ash.h
@@ -11,6 +11,7 @@ #include <string> #include <vector> +#include "ash/wm/splitview/split_view_types.h" #include "base/one_shot_event.h" #include "chrome/browser/ash/crosapi/crosapi_ash.h" #include "chromeos/crosapi/mojom/test_controller.mojom.h" @@ -19,6 +20,13 @@ #include "mojo/public/cpp/bindings/remote.h" #include "ui/base/models/simple_menu_model.h" +namespace mojo { +template <> +struct TypeConverter<ash::SnapPosition, crosapi::mojom::SnapPosition> { + static ash::SnapPosition Convert(crosapi::mojom::SnapPosition position); +}; +} // namespace mojo + namespace crosapi { // This class is the ash-chrome implementation of the TestController interface. @@ -145,6 +153,12 @@ void IsToastShown(const std::string& toast_id, IsToastShownCallback callback) override; + void SnapWindow(const std::string& window_id, + mojom::SnapPosition position, + SnapWindowCallback callback) override; + + void IsShelfVisible(IsShelfVisibleCallback callback) override; + mojo::Remote<mojom::StandaloneBrowserTestController>& GetStandaloneBrowserTestController() { DCHECK(standalone_browser_test_controller_.is_bound());
diff --git a/chrome/browser/ash/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/ash/extensions/autotest_private/autotest_private_api.cc index aeef0645..c918310 100644 --- a/chrome/browser/ash/extensions/autotest_private/autotest_private_api.cc +++ b/chrome/browser/ash/extensions/autotest_private/autotest_private_api.cc
@@ -325,6 +325,8 @@ return "progress"; case message_center::NOTIFICATION_TYPE_CUSTOM: return "custom"; + case message_center::NOTIFICATION_TYPE_CONVERSATION: + return "conversation"; } return "unknown"; }
diff --git a/chrome/browser/ash/login/screens/user_creation_screen.cc b/chrome/browser/ash/login/screens/user_creation_screen.cc index 6838a64..1c520e8d 100644 --- a/chrome/browser/ash/login/screens/user_creation_screen.cc +++ b/chrome/browser/ash/login/screens/user_creation_screen.cc
@@ -171,13 +171,6 @@ return false; } -void UserCreationScreen::SetDefaultStep() { - if (!view_) { - return; - } - view_->SetDefaultStep(); -} - void UserCreationScreen::UpdateState(NetworkError::ErrorReason reason) { NetworkStateInformer::State state = network_state_informer_->state(); if (state != NetworkStateInformer::ONLINE ||
diff --git a/chrome/browser/ash/login/screens/user_creation_screen.h b/chrome/browser/ash/login/screens/user_creation_screen.h index f1b6abe..8dc6fd50 100644 --- a/chrome/browser/ash/login/screens/user_creation_screen.h +++ b/chrome/browser/ash/login/screens/user_creation_screen.h
@@ -64,7 +64,6 @@ UserCreationScreenExitTestDelegate* test_delegate); void SetChildSetupStep(); - void SetDefaultStep(); private: // BaseScreen:
diff --git a/chrome/browser/ash/login/screens/user_creation_screen_browsertest.cc b/chrome/browser/ash/login/screens/user_creation_screen_browsertest.cc index 175df7d..4c2f022 100644 --- a/chrome/browser/ash/login/screens/user_creation_screen_browsertest.cc +++ b/chrome/browser/ash/login/screens/user_creation_screen_browsertest.cc
@@ -292,18 +292,6 @@ test::OobeJS().TapOnPath(kEnrollTriageNextButton); WaitForScreenExit(); EXPECT_EQ(screen_result_.value(), UserCreationScreen::Result::SIGNIN_TRIAGE); - - OobeScreenWaiter(GaiaView::kScreenId).Wait(); - test::OobeJS() - .CreateVisibilityWaiter( - true, {"gaia-signin", "signin-frame-dialog", "signin-back-button"}) - ->Wait(); - - test::OobeJS().ClickOnPath( - {"gaia-signin", "signin-frame-dialog", "signin-back-button"}); - - OobeScreenWaiter(UserCreationView::kScreenId).Wait(); - test::OobeJS().ExpectVisiblePath(kUserCreationEnrollTriageDialog); } // Verify that enroll-device in the enorll triage step in user creation @@ -316,14 +304,6 @@ WaitForScreenExit(); EXPECT_EQ(screen_result_.value(), UserCreationScreen::Result::ENTERPRISE_ENROLL_TRIAGE); - - OobeScreenWaiter(EnrollmentScreenView::kScreenId).Wait(); - - LoginDisplayHost::default_host()->HandleAccelerator( - LoginAcceleratorAction::kCancelScreenAction); - - OobeScreenWaiter(UserCreationView::kScreenId).Wait(); - test::OobeJS().ExpectVisiblePath(kUserCreationDialog); } // Verify that back button display create step in the child setup step
diff --git a/chrome/browser/ash/login/screens/user_selection_screen.cc b/chrome/browser/ash/login/screens/user_selection_screen.cc index 9fd6d40..34aadd8d 100644 --- a/chrome/browser/ash/login/screens/user_selection_screen.cc +++ b/chrome/browser/ash/login/screens/user_selection_screen.cc
@@ -39,7 +39,6 @@ #include "chrome/browser/ash/login/ui/views/user_board_view.h" #include "chrome/browser/ash/login/users/chrome_user_manager.h" #include "chrome/browser/ash/login/users/default_user_image/default_user_images.h" -#include "chrome/browser/ash/login/users/multi_profile_user_controller.h" #include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/ash/system/system_clock.h" @@ -61,6 +60,7 @@ #include "components/signin/public/identity_manager/account_managed_status_finder.h" #include "components/user_manager/known_user.h" #include "components/user_manager/multi_user/multi_user_sign_in_policy.h" +#include "components/user_manager/multi_user/multi_user_sign_in_policy_controller.h" #include "components/user_manager/user_manager.h" #include "components/user_manager/user_type.h" #include "content/public/browser/device_service.h" @@ -192,8 +192,8 @@ std::tuple<bool, user_manager::MultiUserSignInPolicy> GetMultiUserSignInPolicy( const user_manager::User* user) { const std::string& user_id = user->GetAccountId().GetUserEmail(); - MultiProfileUserController* controller = - ChromeUserManager::Get()->GetMultiProfileUserController(); + user_manager::MultiUserSignInPolicyController* controller = + ChromeUserManager::Get()->GetMultiUserSignInPolicyController(); return { controller->IsUserAllowedInSession(user_id), controller->GetCachedValue(user_id),
diff --git a/chrome/browser/ash/login/ui/user_adding_screen_browsertest.cc b/chrome/browser/ash/login/ui/user_adding_screen_browsertest.cc index 5d4fd780..f8a4d78 100644 --- a/chrome/browser/ash/login/ui/user_adding_screen_browsertest.cc +++ b/chrome/browser/ash/login/ui/user_adding_screen_browsertest.cc
@@ -19,13 +19,13 @@ #include "chrome/browser/ash/login/test/user_adding_screen_utils.h" #include "chrome/browser/ash/login/ui/login_display_host.h" #include "chrome/browser/ash/login/ui/user_adding_screen.h" -#include "chrome/browser/ash/login/users/multi_profile_user_controller.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/prefs/pref_service.h" #include "components/session_manager/core/session_manager.h" +#include "components/user_manager/multi_user/multi_user_sign_in_policy.h" #include "components/user_manager/user_manager.h" #include "components/user_manager/user_manager_pref_names.h" #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc index a106431..11a4e77 100644 --- a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc +++ b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc
@@ -48,7 +48,6 @@ #include "chrome/browser/ash/login/users/affiliation.h" #include "chrome/browser/ash/login/users/chrome_user_manager_util.h" #include "chrome/browser/ash/login/users/default_user_image/default_user_images.h" -#include "chrome/browser/ash/login/users/multi_profile_user_controller.h" #include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h" #include "chrome/browser/ash/policy/core/device_local_account.h" #include "chrome/browser/ash/policy/external_data/handlers/crostini_ansible_playbook_external_data_handler.h" @@ -101,6 +100,8 @@ #include "components/proxy_config/proxy_prefs.h" #include "components/session_manager/core/session_manager.h" #include "components/user_manager/known_user.h" +#include "components/user_manager/multi_user/multi_user_sign_in_policy.h" +#include "components/user_manager/multi_user/multi_user_sign_in_policy_controller.h" #include "components/user_manager/user.h" #include "components/user_manager/user_image/user_image.h" #include "components/user_manager/user_manager.h" @@ -120,10 +121,13 @@ // TODO(b/278643115) Remove the using when moved. namespace prefs { +using user_manager::prefs::kMultiProfileNeverShowIntro; using user_manager::prefs::kMultiProfileUserBehaviorPref; +using user_manager::prefs::kMultiProfileWarningShowDismissed; using user_manager::prefs::kRegularUsersPref; } // namespace prefs using user_manager::MultiUserSignInPolicy; +using user_manager::MultiUserSignInPolicyController; using user_manager::ParseMultiUserSignInPolicyPref; namespace { @@ -278,7 +282,7 @@ registry->RegisterListPref(kDeviceLocalAccountsWithSavedData); registry->RegisterStringPref(kDeviceLocalAccountPendingDataRemoval, std::string()); - MultiProfileUserController::RegisterPrefs(registry); + MultiUserSignInPolicyController::RegisterPrefs(registry); SessionLengthLimiter::RegisterPrefs(registry); enterprise_user_session_metrics::RegisterPrefs(registry); @@ -287,7 +291,18 @@ // static void ChromeUserManagerImpl::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - MultiProfileUserController::RegisterProfilePrefs(registry); + // TODO(b/278643115): Move to components/user_manager. Currently, + // using user_prefs::PrefRegistrySyncable in components/user_manager + // will cause circular dependency. + registry->RegisterStringPref(prefs::kMultiProfileUserBehaviorPref, + std::string(MultiUserSignInPolicyToPrefValue( + MultiUserSignInPolicy::kUnrestricted))); + registry->RegisterBooleanPref( + prefs::kMultiProfileNeverShowIntro, false, + user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF); + registry->RegisterBooleanPref( + prefs::kMultiProfileWarningShowDismissed, false, + user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF); } // static @@ -302,7 +317,7 @@ : nullptr), cros_settings_(CrosSettings::Get()), device_local_account_policy_service_(nullptr), - multi_profile_user_controller_(GetLocalState(), this), + multi_user_sign_in_policy_controller_(GetLocalState(), this), mount_performer_(std::make_unique<MountPerformer>()) { UpdateNumberOfUsers(); @@ -443,14 +458,14 @@ device_local_account_policy_service_->RemoveObserver(this); } - multi_profile_user_controller_.Shutdown(); + multi_user_sign_in_policy_controller_.Shutdown(); cloud_external_data_policy_handlers_.clear(); session_observation_.Reset(); } -MultiProfileUserController* -ChromeUserManagerImpl::GetMultiProfileUserController() { - return &multi_profile_user_controller_; +MultiUserSignInPolicyController* +ChromeUserManagerImpl::GetMultiUserSignInPolicyController() { + return &multi_user_sign_in_policy_controller_; } user_manager::UserList ChromeUserManagerImpl::GetUsersAllowedForMultiProfile() @@ -462,7 +477,7 @@ } // No user is allowed if the primary user policy forbids it. - if (multi_profile_user_controller_.GetPrimaryUserPolicy() == + if (multi_user_sign_in_policy_controller_.GetPrimaryUserPolicy() == MultiUserSignInPolicy::kNotAllowed) { return {}; } @@ -583,7 +598,7 @@ auto* user = user_manager::UserManager::Get()->FindUserAndModify(account_id); CHECK(user); - multi_profile_user_controller_.StartObserving(user); + multi_user_sign_in_policy_controller_.StartObserving(user); } } system::UpdateSystemTimezone(profile); @@ -904,7 +919,8 @@ : account_id.GetUserEmail()); } - multi_profile_user_controller_.RemoveCachedValues(account_id.GetUserEmail()); + multi_user_sign_in_policy_controller_.RemoveCachedValues( + account_id.GetUserEmail()); ChromeUserManager::RemoveNonCryptohomeData(account_id); }
diff --git a/chrome/browser/ash/login/users/chrome_user_manager_impl.h b/chrome/browser/ash/login/users/chrome_user_manager_impl.h index bdc8d40e..6dcaa0c3 100644 --- a/chrome/browser/ash/login/users/chrome_user_manager_impl.h +++ b/chrome/browser/ash/login/users/chrome_user_manager_impl.h
@@ -18,7 +18,6 @@ #include "base/synchronization/lock.h" #include "chrome/browser/ash/login/users/affiliation.h" #include "chrome/browser/ash/login/users/chrome_user_manager.h" -#include "chrome/browser/ash/login/users/multi_profile_user_controller.h" #include "chrome/browser/ash/policy/core/device_local_account.h" #include "chrome/browser/ash/policy/core/device_local_account_policy_service.h" #include "chrome/browser/ash/policy/handlers/minimum_version_policy_handler.h" @@ -31,6 +30,7 @@ #include "components/account_id/account_id.h" #include "components/session_manager/core/session_manager.h" #include "components/session_manager/core/session_manager_observer.h" +#include "components/user_manager/multi_user/multi_user_sign_in_policy_controller.h" #include "components/user_manager/user.h" class PrefRegistrySimple; @@ -45,7 +45,6 @@ namespace ash { -class MultiProfileUserController; class SessionLengthLimiter; // Chrome specific implementation of the UserManager. @@ -71,7 +70,8 @@ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); // UserManagerInterface implementation: - MultiProfileUserController* GetMultiProfileUserController() override; + user_manager::MultiUserSignInPolicyController* + GetMultiUserSignInPolicyController() override; // UserManager implementation: void Shutdown() override; @@ -230,7 +230,8 @@ base::CallbackListSubscription ephemeral_users_enabled_subscription_; base::CallbackListSubscription local_accounts_subscription_; - MultiProfileUserController multi_profile_user_controller_; + user_manager::MultiUserSignInPolicyController + multi_user_sign_in_policy_controller_; std::vector<std::unique_ptr<policy::CloudExternalDataPolicyHandler>> cloud_external_data_policy_handlers_;
diff --git a/chrome/browser/ash/login/users/fake_chrome_user_manager.cc b/chrome/browser/ash/login/users/fake_chrome_user_manager.cc index c59b383f..4b7bc24 100644 --- a/chrome/browser/ash/login/users/fake_chrome_user_manager.cc +++ b/chrome/browser/ash/login/users/fake_chrome_user_manager.cc
@@ -24,6 +24,7 @@ #include "chromeos/ash/components/login/login_state/login_state.h" #include "components/user_manager/fake_user_manager.h" #include "components/user_manager/known_user.h" +#include "components/user_manager/multi_user/multi_user_sign_in_policy_controller.h" #include "components/user_manager/user.h" #include "components/user_manager/user_image/user_image.h" #include "components/user_manager/user_names.h" @@ -199,9 +200,9 @@ SimulateUserProfileLoad(account_id); } -MultiProfileUserController* -FakeChromeUserManager::GetMultiProfileUserController() { - return multi_profile_user_controller_; +user_manager::MultiUserSignInPolicyController* +FakeChromeUserManager::GetMultiUserSignInPolicyController() { + return multi_user_sign_in_policy_controller_; } void FakeChromeUserManager::SwitchActiveUser(const AccountId& account_id) {
diff --git a/chrome/browser/ash/login/users/fake_chrome_user_manager.h b/chrome/browser/ash/login/users/fake_chrome_user_manager.h index 9b5b50f..bd2e4fb 100644 --- a/chrome/browser/ash/login/users/fake_chrome_user_manager.h +++ b/chrome/browser/ash/login/users/fake_chrome_user_manager.h
@@ -144,7 +144,8 @@ using UserManagerBase::SetOwnerId; // UserManagerInterface override. - MultiProfileUserController* GetMultiProfileUserController() override; + user_manager::MultiUserSignInPolicyController* + GetMultiUserSignInPolicyController() override; // ChromeUserManager override. void SetUserAffiliation( @@ -158,9 +159,9 @@ fake_ephemeral_mode_config_ = std::move(ephemeral_mode_config); } - void set_multi_profile_user_controller( - MultiProfileUserController* controller) { - multi_profile_user_controller_ = controller; + void set_multi_user_sign_in_policy_controller( + user_manager::MultiUserSignInPolicyController* controller) { + multi_user_sign_in_policy_controller_ = controller; } void set_current_user_ephemeral(bool user_ephemeral) { @@ -194,7 +195,8 @@ bool current_user_ephemeral_ = false; bool current_user_child_ = false; - raw_ptr<MultiProfileUserController> multi_profile_user_controller_ = nullptr; + raw_ptr<user_manager::MultiUserSignInPolicyController> + multi_user_sign_in_policy_controller_ = nullptr; // If set this is the active user. If empty, the first created user is the // active user.
diff --git a/chrome/browser/ash/login/users/multi_profile_user_controller.h b/chrome/browser/ash/login/users/multi_profile_user_controller.h deleted file mode 100644 index 44a2207..0000000 --- a/chrome/browser/ash/login/users/multi_profile_user_controller.h +++ /dev/null
@@ -1,90 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_ASH_LOGIN_USERS_MULTI_PROFILE_USER_CONTROLLER_H_ -#define CHROME_BROWSER_ASH_LOGIN_USERS_MULTI_PROFILE_USER_CONTROLLER_H_ - -#include <memory> -#include <string> -#include <string_view> -#include <vector> - -#include "base/memory/raw_ptr.h" -#include "components/user_manager/multi_user/multi_user_sign_in_policy.h" - -class PrefChangeRegistrar; -class PrefRegistrySimple; -class PrefService; - -namespace user_manager { -class User; -class UserManager; -} - -namespace user_prefs { -class PrefRegistrySyncable; -} - -namespace ash { - -// MultiProfileUserController decides whether a user is allowed to be in a -// multi-profiles session. It caches the multi-profile user behavior pref backed -// by user policy into local state so that the value is available before the -// user login and checks if the meaning of the value is respected. -class MultiProfileUserController { - public: - MultiProfileUserController(PrefService* local_state, - user_manager::UserManager* user_manager); - - MultiProfileUserController(const MultiProfileUserController&) = delete; - MultiProfileUserController& operator=(const MultiProfileUserController&) = - delete; - - ~MultiProfileUserController(); - - static void RegisterPrefs(PrefRegistrySimple* registry); - static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); - - // Stops to work. - void Shutdown(); - - // Returns the cached policy value for `user_email`. - user_manager::MultiUserSignInPolicy GetCachedValue( - std::string_view user_email) const; - - // Returns the primary user's policy. If there's no primary user, - // returns std::nullopt. - std::optional<user_manager::MultiUserSignInPolicy> GetPrimaryUserPolicy() - const; - - // Returns true if user allowed to be in the current session. - bool IsUserAllowedInSession(const std::string& user_email) const; - - // Starts to observe the multiprofile user behavior pref of the given user. - void StartObserving(user_manager::User* user); - - // Removes the cached values for the given user. - void RemoveCachedValues(std::string_view user_email); - - private: - friend class MultiProfileUserControllerTest; - - // Sets the cached policy value. - void SetCachedValue(std::string_view user_email, - user_manager::MultiUserSignInPolicy policy); - - // Checks if all users are allowed in the current session. - void CheckSessionUsers(); - - // Invoked when user behavior pref value changes. - void OnUserPrefChanged(user_manager::User* user); - - raw_ptr<PrefService, DanglingUntriaged> local_state_; - raw_ptr<user_manager::UserManager> user_manager_; - std::vector<std::unique_ptr<PrefChangeRegistrar>> pref_watchers_; -}; - -} // namespace ash - -#endif // CHROME_BROWSER_ASH_LOGIN_USERS_MULTI_PROFILE_USER_CONTROLLER_H_
diff --git a/chrome/browser/ash/login/users/multi_profile_user_controller_unittest.cc b/chrome/browser/ash/login/users/multi_user_sign_in_policy_controller_unittest.cc similarity index 87% rename from chrome/browser/ash/login/users/multi_profile_user_controller_unittest.cc rename to chrome/browser/ash/login/users/multi_user_sign_in_policy_controller_unittest.cc index d4cf485..88c2d74 100644 --- a/chrome/browser/ash/login/users/multi_profile_user_controller_unittest.cc +++ b/chrome/browser/ash/login/users/multi_user_sign_in_policy_controller_unittest.cc
@@ -2,7 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ash/login/users/multi_profile_user_controller.h" +#include "components/user_manager/multi_user/multi_user_sign_in_policy_controller.h" + +// TODO(b/278643115): Move to components/user_manager/multi_user +// once we remove the dependency to chrome/* #include <stddef.h> @@ -39,16 +42,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -namespace ash { - -// TODO(b/278643115) Remove the using when moved. -namespace prefs { -using user_manager::prefs::kCachedMultiProfileUserBehavior; -using user_manager::prefs::kMultiProfileUserBehaviorPref; -} // namespace prefs -using user_manager::MultiUserSignInPolicy; -using user_manager::MultiUserSignInPolicyToPrefValue; -using user_manager::ParseMultiUserSignInPolicyPref; +namespace user_manager { namespace { @@ -114,34 +108,34 @@ Profile::FromBrowserContext(context)); } -class MockUserManagerObserver : public user_manager::UserManager::Observer { +class MockUserManagerObserver : public UserManager::Observer { public: MOCK_METHOD(void, OnUserNotAllowed, (const std::string&), (override)); }; } // namespace -class MultiProfileUserControllerTest : public testing::Test { +class MultiUserSignInPolicyControllerTest : public testing::Test { public: - MultiProfileUserControllerTest() + MultiUserSignInPolicyControllerTest() : fake_user_manager_(std::make_unique<ash::FakeChromeUserManager>()) { for (size_t i = 0; i < std::size(kUsers); ++i) { test_users_.push_back(AccountId::FromUserEmail(kUsers[i])); } } - MultiProfileUserControllerTest(const MultiProfileUserControllerTest&) = - delete; - MultiProfileUserControllerTest& operator=( - const MultiProfileUserControllerTest&) = delete; + MultiUserSignInPolicyControllerTest( + const MultiUserSignInPolicyControllerTest&) = delete; + MultiUserSignInPolicyControllerTest& operator=( + const MultiUserSignInPolicyControllerTest&) = delete; - ~MultiProfileUserControllerTest() override {} + ~MultiUserSignInPolicyControllerTest() override {} void SetUp() override { profile_manager_ = std::make_unique<TestingProfileManager>( TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager_->SetUp()); - controller_ = std::make_unique<MultiProfileUserController>( + controller_ = std::make_unique<MultiUserSignInPolicyController>( TestingBrowserProcess::GetGlobal()->local_state(), fake_user_manager_.Get()); @@ -202,16 +196,16 @@ controller_->SetCachedValue(test_users_[user_index].GetUserEmail(), policy); } - MultiProfileUserController* controller() { return controller_.get(); } + MultiUserSignInPolicyController* controller() { return controller_.get(); } TestingProfile* profile(int index) { return user_profiles_[index]; } content::BrowserTaskEnvironment task_environment_; - user_manager::TypedScopedUserManager<ash::FakeChromeUserManager> + TypedScopedUserManager<ash::FakeChromeUserManager> fake_user_manager_; std::unique_ptr<TestingProfileManager> profile_manager_; - std::unique_ptr<MultiProfileUserController> controller_; + std::unique_ptr<MultiUserSignInPolicyController> controller_; std::vector<raw_ptr<TestingProfile, VectorExperimental>> user_profiles_; @@ -219,7 +213,7 @@ }; // Tests that everyone is allowed before a session starts. -TEST_F(MultiProfileUserControllerTest, AllAllowedBeforeLogin) { +TEST_F(MultiUserSignInPolicyControllerTest, AllAllowedBeforeLogin) { constexpr MultiUserSignInPolicy kTestCases[] = { MultiUserSignInPolicy::kUnrestricted, MultiUserSignInPolicy::kPrimaryOnly, @@ -235,7 +229,7 @@ } // Tests that invalid cache value would become the default "unrestricted". -TEST_F(MultiProfileUserControllerTest, InvalidCacheBecomesDefault) { +TEST_F(MultiUserSignInPolicyControllerTest, InvalidCacheBecomesDefault) { { constexpr char kBad[] = "some invalid value"; ScopedDictPrefUpdate update( @@ -247,7 +241,7 @@ } // Tests that cached behavior value changes with user pref after login. -TEST_F(MultiProfileUserControllerTest, CachedBehaviorUpdate) { +TEST_F(MultiUserSignInPolicyControllerTest, CachedBehaviorUpdate) { LoginUser(0); constexpr MultiUserSignInPolicy kTestCases[] = { @@ -264,10 +258,10 @@ // Tests that compromised cache value would be fixed and pref value is checked // upon login. -TEST_F(MultiProfileUserControllerTest, CompromisedCacheFixedOnLogin) { +TEST_F(MultiUserSignInPolicyControllerTest, CompromisedCacheFixedOnLogin) { MockUserManagerObserver mock_observer; - base::ScopedObservation<user_manager::UserManager, - user_manager::UserManager::Observer> + base::ScopedObservation<UserManager, + UserManager::Observer> observation(&mock_observer); observation.Observe(fake_user_manager_.Get()); @@ -292,7 +286,7 @@ } // Tests cases before the second user login. -TEST_F(MultiProfileUserControllerTest, IsSecondaryAllowed) { +TEST_F(MultiUserSignInPolicyControllerTest, IsSecondaryAllowed) { LoginUser(0); for (size_t i = 0; i < std::size(kBehaviorTestCases); ++i) { @@ -308,10 +302,10 @@ } // Tests user behavior changes within a two-user session. -TEST_F(MultiProfileUserControllerTest, PrimaryBehaviorChange) { +TEST_F(MultiUserSignInPolicyControllerTest, PrimaryBehaviorChange) { MockUserManagerObserver mock_observer; - base::ScopedObservation<user_manager::UserManager, - user_manager::UserManager::Observer> + base::ScopedObservation<UserManager, + UserManager::Observer> observation(&mock_observer); observation.Observe(fake_user_manager_.Get()); EXPECT_CALL(mock_observer, OnUserNotAllowed(testing::_)) @@ -338,7 +332,7 @@ } } -TEST_F(MultiProfileUserControllerTest, +TEST_F(MultiUserSignInPolicyControllerTest, UsedPolicyCertificatesAllowedForPrimary) { // Verifies that any user can sign-in as the primary user, regardless of the // tainted state. @@ -354,7 +348,7 @@ controller()->IsUserAllowedInSession(test_users_[1].GetUserEmail())); } -TEST_F(MultiProfileUserControllerTest, +TEST_F(MultiUserSignInPolicyControllerTest, UsedPolicyCertificatesAllowedForSecondary) { // Verifies that if a regular user is signed-in then other regular users can // be added, including users that have used policy-provided trust anchors. @@ -377,7 +371,7 @@ controller()->IsUserAllowedInSession(test_users_[0].GetUserEmail())); } -TEST_F(MultiProfileUserControllerTest, +TEST_F(MultiUserSignInPolicyControllerTest, SecondaryAllowedWhenPrimaryUsedPolicyCertificates) { // Verifies that if a tainted user is signed-in then other users can still be // added. @@ -404,7 +398,7 @@ base::RunLoop().RunUntilIdle(); } -TEST_F(MultiProfileUserControllerTest, +TEST_F(MultiUserSignInPolicyControllerTest, PolicyCertificatesInMemoryDisallowsSecondaries) { // Verifies that if a user is signed-in and has policy certificates installed // then other users can still be added. @@ -437,4 +431,4 @@ base::RunLoop().RunUntilIdle(); } -} // namespace ash +} // namespace user_manager
diff --git a/chrome/browser/ash/login/users/user_manager_interface.h b/chrome/browser/ash/login/users/user_manager_interface.h index 4f18cbb2..420e629 100644 --- a/chrome/browser/ash/login/users/user_manager_interface.h +++ b/chrome/browser/ash/login/users/user_manager_interface.h
@@ -5,9 +5,12 @@ #ifndef CHROME_BROWSER_ASH_LOGIN_USERS_USER_MANAGER_INTERFACE_H_ #define CHROME_BROWSER_ASH_LOGIN_USERS_USER_MANAGER_INTERFACE_H_ +namespace user_manager { +class MultiUserSignInPolicyController; +} // namespace user_manager + namespace ash { -class MultiProfileUserController; // ChromeOS specific add-ons interface for the UserManager. class UserManagerInterface { @@ -19,7 +22,8 @@ virtual ~UserManagerInterface() = default; - virtual MultiProfileUserController* GetMultiProfileUserController() = 0; + virtual user_manager::MultiUserSignInPolicyController* + GetMultiUserSignInPolicyController() = 0; }; } // namespace ash
diff --git a/chrome/browser/ash/login/wizard_controller.cc b/chrome/browser/ash/login/wizard_controller.cc index 5be880e..75f29426 100644 --- a/chrome/browser/ash/login/wizard_controller.cc +++ b/chrome/browser/ash/login/wizard_controller.cc
@@ -2111,9 +2111,6 @@ PerformOOBECompletedActions( OobeMetricsHelper::CompletedPreLoginOobeFlowType::kAutoEnrollment); DCHECK(!prescribed_enrollment_config_.is_forced()); - // set the userCreationScreen with the default step creation and - // pre-select 'For personal use'. - GetScreen<UserCreationScreen>()->SetDefaultStep(); ShowLoginScreen(); break; case EnrollmentScreen::Result::TPM_ERROR:
diff --git a/chrome/browser/ash/printing/cups_printers_manager.cc b/chrome/browser/ash/printing/cups_printers_manager.cc index 0152261c..01c2bac 100644 --- a/chrome/browser/ash/printing/cups_printers_manager.cc +++ b/chrome/browser/ash/printing/cups_printers_manager.cc
@@ -47,7 +47,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" -#include "chromeos/ash/components/dbus/debug_daemon/debug_daemon_client.h" +#include "chromeos/ash/components/dbus/printscanmgr/printscanmgr_client.h" #include "chromeos/printing/cups_printer_status.h" #include "chromeos/printing/printing_constants.h" #include "chromeos/printing/uri.h" @@ -113,8 +113,14 @@ using ::chromeos::PrinterClass; using ::printing::PrinterQueryResult; -void OnRemovedPrinter(bool success) { - if (success) { +void OnRemovedPrinter( + std::optional<printscanmgr::CupsRemovePrinterResponse> response) { + if (!response) { + PRINTER_LOG(DEBUG) << "No response to remove printer request."; + return; + } + + if (response->result()) { PRINTER_LOG(DEBUG) << "Printer removal succeeded."; } else { PRINTER_LOG(DEBUG) << "Printer removal failed."; @@ -424,8 +430,10 @@ // Uninstall printer if installed completely. if (installed_printer_fingerprints_.erase(printer_id)) { // The printer was present in `installed_printer_fingerprints_`. - DebugDaemonClient::Get()->CupsRemovePrinter( - printer_id, base::BindOnce(&OnRemovedPrinter), base::DoNothing()); + printscanmgr::CupsRemovePrinterRequest request; + request.set_name(printer_id); + PrintscanmgrClient::Get()->CupsRemovePrinter( + request, base::BindOnce(&OnRemovedPrinter), base::DoNothing()); return; }
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc index 9bfdf526..8036cf0f 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -11,6 +11,7 @@ #include <utility> #include <vector> +#include "base/command_line.h" #include "base/containers/contains.h" #include "base/containers/flat_set.h" #include "base/files/file_util.h" @@ -82,6 +83,7 @@ #include "chrome/common/chrome_constants.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 "chrome/test/base/fake_profile_manager.h" #include "chrome/test/base/scoped_testing_local_state.h" @@ -191,7 +193,6 @@ #include "chrome/browser/android/customtabs/chrome_origin_verifier.h" #include "chrome/browser/android/search_permissions/search_permissions_service.h" #include "chrome/browser/android/webapps/webapp_registry.h" -#include "chrome/browser/password_manager/android/password_manager_android_util.h" #include "components/feed/buildflags.h" #else #include "content/public/browser/host_zoom_map.h" @@ -3939,11 +3940,14 @@ public: ChromeBrowsingDataRemoverDelegateWithAccountPasswordsTest() { #if BUILDFLAG(IS_ANDROID) - // Using the account store on Android also requires UPM support for local - // passwords. + // Using the account store on Android requires enabling the flag for UPM + // support of local passwords. Skip the Gms version check, otherwise the + // flag won't do anything in bots that have outdated GmsCore. feature_list_.InitAndEnableFeature( password_manager::features:: kUnifiedPasswordManagerLocalPasswordsAndroidNoMigration); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kSkipLocalUpmGmsCoreVersionCheckForTesting); #endif } };
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index e1b5650..aa5bd0d 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -4723,13 +4723,6 @@ break; } -#if !defined(OFFICIAL_BUILD) - // Disable renderer code integrity when Application Verifier or pageheap are - // enabled for chrome.exe to avoid renderer crashes. https://crbug.com/1004989 - if (base::win::IsAppVerifierEnabled(chrome::kBrowserProcessExecutableName)) - enforce_code_integrity = false; -#endif // !defined(OFFICIAL_BUILD) - if (!enforce_code_integrity) return true;
diff --git a/chrome/browser/chromeos/tablet_mode/DEPS b/chrome/browser/chromeos/tablet_mode/DEPS index 69dd4768e..bf2717d 100644 --- a/chrome/browser/chromeos/tablet_mode/DEPS +++ b/chrome/browser/chromeos/tablet_mode/DEPS
@@ -2,7 +2,4 @@ "chrome_content_browser_client_tablet_mode_part_browsertest\.cc": [ "+chrome/browser/ash/system_web_apps/system_web_app_manager.h", ], - "tablet_mode_page_behavior_browsertest.cc": [ - "+ash/public/cpp/test/shell_test_api.h", - ], }
diff --git a/chrome/browser/chromeos/tablet_mode/tablet_mode_page_behavior_browsertest.cc b/chrome/browser/chromeos/tablet_mode/tablet_mode_page_behavior_browsertest.cc index 7a5c918d..125ea6a 100644 --- a/chrome/browser/chromeos/tablet_mode/tablet_mode_page_behavior_browsertest.cc +++ b/chrome/browser/chromeos/tablet_mode/tablet_mode_page_behavior_browsertest.cc
@@ -2,62 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/command_line.h" -#include "base/functional/callback_forward.h" -#include "base/run_loop.h" -#include "base/test/scoped_feature_list.h" #include "chrome/browser/browser_features.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/chromeos/test_util.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/url_constants.h" #include "chrome/common/webui_url_constants.h" -#include "chrome/test/base/in_process_browser_test.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "third_party/blink/public/common/web_preferences/web_preferences.h" -#include "ui/display/screen.h" - -#if BUILDFLAG(IS_CHROMEOS_ASH) -#include "ash/constants/ash_switches.h" -#include "ash/public/cpp/test/shell_test_api.h" -#elif BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chromeos/crosapi/mojom/test_controller.mojom.h" -#include "chromeos/lacros/lacros_service.h" -#include "ui/display/display_observer.h" -#endif namespace { -#if BUILDFLAG(IS_CHROMEOS_LACROS) -// Runs the specified callback when a change to tablet state is detected. -class TabletModeWatcher : public display::DisplayObserver { - public: - explicit TabletModeWatcher(base::RepeatingClosure cb, - display::TabletState current_tablet_state) - : cb_(cb), current_tablet_state_(current_tablet_state) {} - void OnDisplayTabletStateChanged(display::TabletState state) override { - // Skip if the notified TabletState is same as the current state. - // This required since it may notify the current tablet state when the - // observer is added (e.g. WaylandScreen::AddObserver()). In such cases, we - // need to ignore the initial notification so that we can only catch - // meeningful notifications for testing. - if (current_tablet_state_ == state) - return; - - cb_.Run(); - } - - private: - base::RepeatingClosure cb_; - display::TabletState current_tablet_state_; -}; -#endif - -class TabletModePageBehaviorTest : public InProcessBrowserTest { +class TabletModePageBehaviorTest : public ChromeOSBrowserUITest { public: TabletModePageBehaviorTest() = default; @@ -74,46 +35,6 @@ InProcessBrowserTest::SetUp(); } - void SetUpDefaultCommandLine(base::CommandLine* command_line) override { - InProcessBrowserTest::SetUpDefaultCommandLine(command_line); - -#if BUILDFLAG(IS_CHROMEOS_ASH) - command_line->AppendSwitch(ash::switches::kAshEnableTabletMode); -#endif - } - - void TearDownOnMainThread() override { - if (InTabletMode()) { - SetTabletMode(false); - } - InProcessBrowserTest::TearDownOnMainThread(); - } - - void SetTabletMode(bool enable) { - DCHECK(InTabletMode() != enable); -#if BUILDFLAG(IS_CHROMEOS_ASH) - ash::ShellTestApi().SetTabletModeEnabledForTest(enable); -#elif BUILDFLAG(IS_CHROMEOS_LACROS) - base::RunLoop run_loop; - TabletModeWatcher watcher(run_loop.QuitClosure(), - display::Screen::GetScreen()->GetTabletState()); - display::Screen::GetScreen()->AddObserver(&watcher); - auto& test_controller = chromeos::LacrosService::Get() - ->GetRemote<crosapi::mojom::TestController>(); - if (enable) { - test_controller->EnterTabletMode(base::DoNothing()); - } else { - test_controller->ExitTabletMode(base::DoNothing()); - } - run_loop.Run(); - display::Screen::GetScreen()->RemoveObserver(&watcher); -#endif - } - - bool InTabletMode() const { - return display::Screen::GetScreen()->InTabletMode(); - } - content::WebContents* GetActiveWebContents(Browser* browser) const { return browser->tab_strip_model()->GetActiveWebContents(); } @@ -161,8 +82,7 @@ // Now enable tablet mode, and expect that the same page's web prefs get // updated. - SetTabletMode(true); - ASSERT_TRUE(InTabletMode()); + EnterTabletMode(); ValidateWebPrefs(web_contents, true /* tablet_mode_enabled */); // Any newly added pages should have the correct tablet mode prefs. @@ -172,8 +92,7 @@ ValidateWebPrefs(web_contents_2, true /* tablet_mode_enabled */); // Disable tablet mode and expect both pages's prefs are updated. - SetTabletMode(false); - ASSERT_FALSE(InTabletMode()); + ExitTabletMode(); ValidateWebPrefs(web_contents, false /* tablet_mode_enabled */); ValidateWebPrefs(web_contents_2, false /* tablet_mode_enabled */); } @@ -189,8 +108,7 @@ // Now enable tablet mode, and expect that this internal page's web prefs // remain unaffected as if tablet mode is off. - SetTabletMode(true); - ASSERT_TRUE(InTabletMode()); + EnterTabletMode(); ValidateWebPrefs(web_contents, false /* tablet_mode_enabled */); } @@ -211,8 +129,7 @@ // Now enable tablet mode, and expect that the page's web prefs of this hosted // app remain unaffected as if tablet mode is off. - SetTabletMode(true); - ASSERT_TRUE(InTabletMode()); + EnterTabletMode(); ValidateWebPrefs(web_contents, false /* tablet_mode_enabled */); } @@ -226,8 +143,7 @@ chrome::kChromeUINewTabPageURL); // Mobile-style Blink prefs should be applied to the NTP in tablet mode. - SetTabletMode(true); - ASSERT_TRUE(InTabletMode()); + EnterTabletMode(); ValidateWebPrefs(web_contents, true /* tablet_mode_enabled */); }
diff --git a/chrome/browser/compose/chrome_compose_client_unittest.cc b/chrome/browser/compose/chrome_compose_client_unittest.cc index 7e289d1..46c27647 100644 --- a/chrome/browser/compose/chrome_compose_client_unittest.cc +++ b/chrome/browser/compose/chrome_compose_client_unittest.cc
@@ -153,7 +153,8 @@ scoped_feature_list_.InitWithFeatures( {compose::features::kEnableCompose, - optimization_guide::features::kOptimizationGuideModelExecution}, + optimization_guide::features::kOptimizationGuideModelExecution, + compose::features::kComposeTextOutputAnimation}, {}); // Needed for feature params to reset. compose::ResetConfigForTesting(); @@ -726,6 +727,45 @@ histogram_tester.ExpectTotalCount(compose::kComposeRequestDurationError, 0); } +TEST_F(ChromeComposeClientTest, TestComposeNoResultAnimation) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + {optimization_guide::features::kOptimizationGuideOnDeviceModel}, + {compose::features::kComposeTextOutputAnimation}); + base::HistogramTester histogram_tester; + + const std::string input = "a user typed this"; + optimization_guide::proto::ComposeRequest context_request; + *context_request.mutable_page_metadata() = ComposePageMetadata(); + base::test::TestFuture< + optimization_guide:: + OptimizationGuideModelExecutionResultStreamingCallback> + saved_callback; + EXPECT_CALL(session(), AddContext(EqualsProto(context_request))); + EXPECT_CALL(session(), ExecuteModel(EqualsProto(ComposeRequest(input)), _)) + .WillOnce(testing::WithArg<1>(testing::Invoke( + [&](optimization_guide:: + OptimizationGuideModelExecutionResultStreamingCallback + callback) { saved_callback.SetValue(callback); }))); + ShowDialogAndBindMojo(); + + EXPECT_CALL(compose_dialog(), PartialResponseReceived(_)).Times(0); + EXPECT_CALL(compose_dialog(), ResponseReceived(_)).Times(1); + + page_handler()->Compose(input, false); + + // Send a partial response. + saved_callback.Get().Run(OptimizationGuideStreamingResult( + ComposeResponse(true, "Cucu"), /*is_complete=*/false, + /*provided_by_on_device=*/true)); + + // Then send the full response. + saved_callback.Get().Run(OptimizationGuideStreamingResult( + ComposeResponse(true, "Cucumbers"), /*is_complete=*/true, + /*provided_by_on_device=*/true)); + FlushMojo(); +} + TEST_F(ChromeComposeClientTest, TestComposeSessionIgnoresPreviousResponse) { base::test::ScopedFeatureList scoped_feature_list( optimization_guide::features::kOptimizationGuideOnDeviceModel);
diff --git a/chrome/browser/compose/compose_session.cc b/chrome/browser/compose/compose_session.cc index 186f690..857e40f 100644 --- a/chrome/browser/compose/compose_session.cc +++ b/chrome/browser/compose/compose_session.cc
@@ -455,6 +455,10 @@ optimization_guide::StreamingResponse result) { CHECK(base::FeatureList::IsEnabled( optimization_guide::features::kOptimizationGuideOnDeviceModel)); + if (!base::FeatureList::IsEnabled( + compose::features::kComposeTextOutputAnimation)) { + return; + } if (!dialog_remote_.is_bound()) { return; }
diff --git a/chrome/browser/content_extraction/android/BUILD.gn b/chrome/browser/content_extraction/android/BUILD.gn new file mode 100644 index 0000000..1880711 --- /dev/null +++ b/chrome/browser/content_extraction/android/BUILD.gn
@@ -0,0 +1,20 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") +import("//third_party/jni_zero/jni_zero.gni") + +android_library("java") { + srcjar_deps = [ ":jni_headers" ] + sources = [ "java/src/org/chromium/chrome/browser/content_extraction/InnerTextBridge.java" ] + deps = [ + "//base:base_java", + "//content/public/android:content_full_java", + "//third_party/jni_zero:jni_zero_java", + ] +} + +generate_jni("jni_headers") { + sources = [ "java/src/org/chromium/chrome/browser/content_extraction/InnerTextBridge.java" ] +}
diff --git a/chrome/browser/content_extraction/android/inner_text_bridge.cc b/chrome/browser/content_extraction/android/inner_text_bridge.cc new file mode 100644 index 0000000..fcf4521 --- /dev/null +++ b/chrome/browser/content_extraction/android/inner_text_bridge.cc
@@ -0,0 +1,51 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/android/callback_android.h" +#include "base/functional/callback_forward.h" +#include "base/types/optional_ref.h" +#include "chrome/browser/content_extraction/android/jni_headers/InnerTextBridge_jni.h" +#include "chrome/browser/content_extraction/inner_text.h" +#include "content/public/browser/render_frame_host.h" + +using ::base::android::JavaParamRef; + +namespace { +void OnGotInnerText( + base::OnceCallback<void(const base::optional_ref<const std::string>)> + optional_string_callback, + std::unique_ptr<content_extraction::InnerTextResult> inner_text) { + if (!optional_string_callback) { + return; + } + + if (!inner_text) { + std::move(optional_string_callback).Run(base::optional_ref<std::string>()); + } else { + std::move(optional_string_callback).Run(inner_text->inner_text); + } +} +} // namespace + +void JNI_InnerTextBridge_GetInnerText( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jrender_frame_host, + const JavaParamRef<jobject>& jcallback) { + CHECK(jcallback); + auto* render_frame_host = + content::RenderFrameHost::FromJavaRenderFrameHost(jrender_frame_host); + if (!render_frame_host) { + base::android::RunOptionalStringCallbackAndroid( + jcallback, base::optional_ref<std::string>()); + return; + } + + auto callback = + base::BindOnce(&base::android::RunOptionalStringCallbackAndroid, + base::android::ScopedJavaGlobalRef<jobject>(jcallback)); + + content_extraction::GetInnerText( + *render_frame_host, std::nullopt, + base::BindOnce(&OnGotInnerText, std::move(callback))); +}
diff --git a/chrome/browser/content_extraction/android/java/src/org/chromium/chrome/browser/content_extraction/InnerTextBridge.java b/chrome/browser/content_extraction/android/java/src/org/chromium/chrome/browser/content_extraction/InnerTextBridge.java new file mode 100644 index 0000000..17214d35c --- /dev/null +++ b/chrome/browser/content_extraction/android/java/src/org/chromium/chrome/browser/content_extraction/InnerTextBridge.java
@@ -0,0 +1,25 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.content_extraction; + +import org.jni_zero.NativeMethods; + +import org.chromium.base.Callback; +import org.chromium.content_public.browser.RenderFrameHost; + +import java.util.Optional; + +public class InnerTextBridge { + public static void getInnerText( + RenderFrameHost webContents, Callback<Optional<String>> innerTextCallback) { + InnerTextBridgeJni.get().getInnerText(webContents, innerTextCallback); + } + + @NativeMethods + interface Natives { + void getInnerText( + RenderFrameHost webContents, Callback<Optional<String>> innerTextCallback); + } +}
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc index efc22ad..0cbce46 100644 --- a/chrome/browser/download/download_browsertest.cc +++ b/chrome/browser/download/download_browsertest.cc
@@ -155,6 +155,7 @@ #include "third_party/blink/public/common/switches.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/page_transition_types.h" +#include "ui/base/ui_base_features.h" #include "ui/gfx/geometry/point_conversions.h" #if !BUILDFLAG(IS_CHROMEOS) @@ -4701,6 +4702,12 @@ } IN_PROC_BROWSER_TEST_F(DownloadTest, FeedbackServiceDiscardDownload) { +#if BUILDFLAG(IS_MAC) + // TODO (crbug/1523751): Test fails when ChromeRefresh2023 flags are enabled. + if (features::IsChromeRefresh2023()) { + GTEST_SKIP(); + } +#endif safe_browsing::FileTypePoliciesTestOverlay scoped_dangerous = safe_browsing::ScopedMarkAllFilesDangerousForTesting();
diff --git a/chrome/browser/enterprise/data_controls/rules_service.cc b/chrome/browser/enterprise/data_controls/rules_service.cc index 7c309847..03644dd 100644 --- a/chrome/browser/enterprise/data_controls/rules_service.cc +++ b/chrome/browser/enterprise/data_controls/rules_service.cc
@@ -10,6 +10,25 @@ namespace data_controls { +namespace { + +template <typename ActionSourceOrDestination> +ActionSourceOrDestination ExtractPasteActionContext( + const content::ClipboardEndpoint& endpoint) { + ActionSourceOrDestination action; + if (endpoint.data_transfer_endpoint() && + endpoint.data_transfer_endpoint()->IsUrlType()) { + action.url = *endpoint.data_transfer_endpoint()->GetURL(); + } + if (endpoint.browser_context()) { + action.incognito = Profile::FromBrowserContext(endpoint.browser_context()) + ->IsIncognitoProfile(); + } + return action; +} + +} // namespace + // --------------------------- // RulesService implementation // --------------------------- @@ -31,26 +50,12 @@ const content::ClipboardEndpoint& source, const content::ClipboardEndpoint& destination, const content::ClipboardMetadata& metadata) const { - ActionContext context; - if (source.data_transfer_endpoint() && - source.data_transfer_endpoint()->IsUrlType()) { - context.source.url = *source.data_transfer_endpoint()->GetURL(); - } - if (source.browser_context()) { - context.source.incognito = - Profile::FromBrowserContext(source.browser_context()) - ->IsIncognitoProfile(); - } - if (destination.data_transfer_endpoint() && - destination.data_transfer_endpoint()->IsUrlType()) { - context.destination.url = *destination.data_transfer_endpoint()->GetURL(); - } - if (destination.browser_context()) { - context.destination.incognito = - Profile::FromBrowserContext(destination.browser_context()) - ->IsIncognitoProfile(); - } - return rules_manager_.GetVerdict(Rule::Restriction::kClipboard, context); + return rules_manager_.GetVerdict( + Rule::Restriction::kClipboard, + { + .source = GetAsActionSource(source), + .destination = GetAsActionDestination(destination), + }); } Verdict RulesService::GetCopyRestrictedBySourceVerdict( @@ -67,6 +72,20 @@ .destination = {.os_clipboard = true}}); } +ActionSource RulesService::GetAsActionSource( + const content::ClipboardEndpoint& endpoint) const { + if (!endpoint.browser_context()) { + return {.os_clipboard = true}; + } + + return ExtractPasteActionContext<ActionSource>(endpoint); +} + +ActionDestination RulesService::GetAsActionDestination( + const content::ClipboardEndpoint& endpoint) const { + return ExtractPasteActionContext<ActionDestination>(endpoint); +} + // ---------------------------------- // RulesServiceFactory implementation // ----------------------------------
diff --git a/chrome/browser/enterprise/data_controls/rules_service.h b/chrome/browser/enterprise/data_controls/rules_service.h index 6ff8910..d9236f9 100644 --- a/chrome/browser/enterprise/data_controls/rules_service.h +++ b/chrome/browser/enterprise/data_controls/rules_service.h
@@ -49,6 +49,12 @@ explicit RulesService(content::BrowserContext* browser_context); private: + // Helpers to convert action-specific types to rule-specific types. + ActionSource GetAsActionSource( + const content::ClipboardEndpoint& endpoint) const; + ActionDestination GetAsActionDestination( + const content::ClipboardEndpoint& endpoint) const; + // `profile_` and `rules_manager_` are initialized with the browser_context // passed in the constructor. const raw_ptr<Profile> profile_ = nullptr;
diff --git a/chrome/browser/enterprise/data_controls/rules_service_unittest.cc b/chrome/browser/enterprise/data_controls/rules_service_unittest.cc index 46b80c70..a9825adb 100644 --- a/chrome/browser/enterprise/data_controls/rules_service_unittest.cc +++ b/chrome/browser/enterprise/data_controls/rules_service_unittest.cc
@@ -39,6 +39,14 @@ Profile* incognito_profile() { return incognito_profile_; } + content::WebContents* web_contents() { + if (!web_contents_) { + content::WebContents::CreateParams params(profile_); + web_contents_ = content::WebContents::Create(params); + } + return web_contents_.get(); + } + content::WebContents* incognito_web_contents() { if (!incognito_web_contents_) { content::WebContents::CreateParams params(incognito_profile_); @@ -49,8 +57,13 @@ const GURL google_url() const { return GURL("https://google.com"); } - content::ClipboardEndpoint google_url_endpoint() const { - return content::ClipboardEndpoint(ui::DataTransferEndpoint(google_url())); + content::ClipboardEndpoint google_url_endpoint() { + return content::ClipboardEndpoint( + ui::DataTransferEndpoint(google_url()), + base::BindLambdaForTesting([this]() -> content::BrowserContext* { + return static_cast<content::BrowserContext*>(profile()); + }), + *web_contents()->GetPrimaryMainFrame()); } content::ClipboardEndpoint empty_endpoint() const { @@ -96,6 +109,7 @@ TestingProfileManager profile_manager_; raw_ptr<TestingProfile> profile_; raw_ptr<Profile> incognito_profile_; + std::unique_ptr<content::WebContents> web_contents_; std::unique_ptr<content::WebContents> incognito_web_contents_; }; @@ -832,4 +846,216 @@ } } +TEST_F(DataControlsRulesServiceTest, OSClipboardSource) { + { + SetDataControls(profile()->GetPrefs(), {R"({ + "sources": { + "os_clipboard": true + }, + "restrictions": [ + {"class": "CLIPBOARD", "level": "BLOCK"} + ] + })"}); + ExpectBlockVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetPasteVerdict( + /*source*/ empty_endpoint(), + /*destination*/ google_url_endpoint(), + /*metadata*/ {})); + ExpectNoVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetPasteVerdict( + /*source*/ google_url_endpoint(), + /*destination*/ empty_endpoint(), + /*metadata*/ {})); + ExpectNoVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetCopyToOSClipboardVerdict( + /*source*/ google_url())); + ExpectNoVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetCopyRestrictedBySourceVerdict( + /*source*/ google_url())); + } + + { + SetDataControls(profile()->GetPrefs(), {R"({ + "sources": { + "os_clipboard": true + }, + "restrictions": [ + {"class": "CLIPBOARD", "level": "WARN"} + ] + })"}); + ExpectWarnVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetPasteVerdict( + /*source*/ empty_endpoint(), + /*destination*/ google_url_endpoint(), + /*metadata*/ {})); + ExpectNoVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetPasteVerdict( + /*source*/ google_url_endpoint(), + /*destination*/ empty_endpoint(), + /*metadata*/ {})); + ExpectNoVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetCopyToOSClipboardVerdict( + /*source*/ google_url())); + ExpectNoVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetCopyRestrictedBySourceVerdict( + /*source*/ google_url())); + } + + { + // When multiple rules are triggered, "ALLOW" should have precedence over + // any other value. + SetDataControls(profile()->GetPrefs(), { + R"({ + "sources": { + "os_clipboard": true + }, + "restrictions": [ + {"class": "CLIPBOARD", "level": "ALLOW"} + ] + })", + R"({ + "sources": { + "os_clipboard": true + }, + "restrictions": [ + {"class": "CLIPBOARD", "level": "WARN"} + ] + })"}); + ExpectAllowVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetPasteVerdict( + /*source*/ empty_endpoint(), + /*destination*/ google_url_endpoint(), + /*metadata*/ {})); + ExpectNoVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetPasteVerdict( + /*source*/ google_url_endpoint(), + /*destination*/ empty_endpoint(), + /*metadata*/ {})); + ExpectNoVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetCopyToOSClipboardVerdict( + /*source*/ google_url())); + ExpectNoVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetCopyRestrictedBySourceVerdict( + /*source*/ google_url())); + } +} + +TEST_F(DataControlsRulesServiceTest, NonOSClipboardSource) { + { + SetDataControls(profile()->GetPrefs(), {R"({ + "sources": { + "os_clipboard": false + }, + "restrictions": [ + {"class": "CLIPBOARD", "level": "BLOCK"} + ] + })"}); + ExpectNoVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetPasteVerdict( + /*source*/ empty_endpoint(), + /*destination*/ google_url_endpoint(), + /*metadata*/ {})); + ExpectBlockVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetPasteVerdict( + /*source*/ google_url_endpoint(), + /*destination*/ empty_endpoint(), + /*metadata*/ {})); + ExpectBlockVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetCopyToOSClipboardVerdict( + /*source*/ google_url())); + ExpectBlockVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetCopyRestrictedBySourceVerdict( + /*source*/ google_url())); + } + + { + SetDataControls(profile()->GetPrefs(), {R"({ + "sources": { + "os_clipboard": false + }, + "restrictions": [ + {"class": "CLIPBOARD", "level": "WARN"} + ] + })"}); + ExpectNoVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetPasteVerdict( + /*source*/ empty_endpoint(), + /*destination*/ google_url_endpoint(), + /*metadata*/ {})); + ExpectWarnVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetPasteVerdict( + /*source*/ google_url_endpoint(), + /*destination*/ empty_endpoint(), + /*metadata*/ {})); + ExpectWarnVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetCopyToOSClipboardVerdict( + /*source*/ google_url())); + ExpectWarnVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetCopyRestrictedBySourceVerdict( + /*source*/ google_url())); + } + + { + // When multiple rules are triggered, "ALLOW" should have precedence over + // any other value. + SetDataControls(profile()->GetPrefs(), { + R"({ + "sources": { + "os_clipboard": false + }, + "restrictions": [ + {"class": "CLIPBOARD", "level": "ALLOW"} + ] + })", + R"({ + "sources": { + "os_clipboard": false + }, + "restrictions": [ + {"class": "CLIPBOARD", "level": "WARN"} + ] + })"}); + ExpectNoVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetPasteVerdict( + /*source*/ empty_endpoint(), + /*destination*/ google_url_endpoint(), + /*metadata*/ {})); + ExpectAllowVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetPasteVerdict( + /*source*/ google_url_endpoint(), + /*destination*/ empty_endpoint(), + /*metadata*/ {})); + ExpectAllowVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetCopyToOSClipboardVerdict( + /*source*/ google_url())); + ExpectAllowVerdict(RulesServiceFactory::GetInstance() + ->GetForBrowserContext(profile()) + ->GetCopyRestrictedBySourceVerdict( + /*source*/ google_url())); + } +} + } // namespace data_controls
diff --git a/chrome/browser/extensions/api/cookies/cookies_helpers.cc b/chrome/browser/extensions/api/cookies/cookies_helpers.cc index 1b8fba82..e3119d4 100644 --- a/chrome/browser/extensions/api/cookies/cookies_helpers.cc +++ b/chrome/browser/extensions/api/cookies/cookies_helpers.cc
@@ -208,7 +208,8 @@ const net::CanonicalCookie& cookie = cookie_with_access_result.cookie; AppendCookieToVectorIfMatchAndHasHostPermission( cookie, details, extension, match_vector, - net::CookiePartitionKeyCollection()); + CookiePartitionKeyCollectionFromApiPartitionKey( + details->partition_key)); } }
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc index 9f6ce65e..a2f413c 100644 --- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc +++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc
@@ -406,8 +406,7 @@ const int lid = 0; manager->OnPeerConnectionAdded(frame_id, lid, pid, /*url=*/std::string(), - /*rtc_configuration=*/std::string(), - /*constraints=*/std::string()); + /*rtc_configuration=*/std::string()); if (!session_id.empty()) { manager->OnPeerConnectionSessionIdSet(frame_id, lid, session_id);
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 48865a0..415d7424 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -497,7 +497,7 @@ { "name": "audio-hfp-offload", "owners": [ "johnylin@chromium.org", "jrwu@chromium.org", "chromeos-audio@google.com" ], - "expiry_milestone": 122 + "expiry_milestone": 130 }, { "name": "audio-hfp-swb", @@ -6096,8 +6096,8 @@ }, { "name": "omnibox-rich-autocompletion", - "owners": [ "manukh@chromium.org", "chrome-omnibox-team@google.com" ], - "expiry_milestone": 115 + "owners": [ "manukh@chromium.org", "christianxu@chromium.org", "chrome-omnibox-team@google.com" ], + "expiry_milestone": 130 }, { "name": "omnibox-rich-autocompletion-promising",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 0bf2fefb..a50fe282 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -7707,15 +7707,6 @@ #endif // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \ - BUILDFLAG(IS_FUCHSIA) -const char kQuickCommandsName[] = "Quick Commands"; -const char kQuickCommandsDescription[] = - "Enable a text interface to browser features. Invoke with Ctrl-Space."; - -#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || - // BUILDFLAG(IS_FUCHSIA) - -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \ BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_CHROMEOS) const char kFollowingFeedSidepanelName[] = "Following feed in the sidepanel"; const char kFollowingFeedSidepanelDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 6380119..390e9b23 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -4438,14 +4438,6 @@ extern const char kZeroCopyVideoCaptureDescription[]; #endif // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \ - BUILDFLAG(IS_FUCHSIA) -extern const char kQuickCommandsName[]; -extern const char kQuickCommandsDescription[]; - -#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || - // defined (OS_FUCHSIA) - #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC) extern const char kWebShareName[]; extern const char kWebShareDescription[];
diff --git a/chrome/browser/lacros/app_mode/kiosk_session_service_lacros.cc b/chrome/browser/lacros/app_mode/kiosk_session_service_lacros.cc index 2eb1c79..ec286ec 100644 --- a/chrome/browser/lacros/app_mode/kiosk_session_service_lacros.cc +++ b/chrome/browser/lacros/app_mode/kiosk_session_service_lacros.cc
@@ -94,12 +94,16 @@ if (IsWebKioskSession()) { new_browser_observer_ = std::make_unique<NewBrowserObserver>(base::BindRepeating( - [](KioskSessionServiceLacros* kiosk_service, Browser* browser) { + [](base::WeakPtr<KioskSessionServiceLacros> kiosk_service, + Browser* browser) { + if (!kiosk_service) { + return; + } kiosk_service->KioskSessionServiceLacros::InitWebKioskSession( CHECK_DEREF(browser)); kiosk_service->new_browser_observer_.reset(); }, - weak_factory_.GetWeakPtr().get())); + weak_factory_.GetWeakPtr())); } } @@ -134,7 +138,7 @@ } } -void KioskSessionServiceLacros::SetInstallUrl(const GURL install_url) { +void KioskSessionServiceLacros::SetInstallUrl(const GURL& install_url) { // `SetInstallUrl` should be called once, but if it is called second time, // the url should be the same. CHECK(install_url_.is_empty() || install_url_ == install_url)
diff --git a/chrome/browser/lacros/app_mode/kiosk_session_service_lacros.h b/chrome/browser/lacros/app_mode/kiosk_session_service_lacros.h index ab6d1c8..be0564a7 100644 --- a/chrome/browser/lacros/app_mode/kiosk_session_service_lacros.h +++ b/chrome/browser/lacros/app_mode/kiosk_session_service_lacros.h
@@ -54,7 +54,7 @@ // Initialize the current Chrome Kiosk session with the `app_id`. void InitChromeKioskSession(Profile* profile, const std::string& app_id); - void SetInstallUrl(const GURL install_url); + void SetInstallUrl(const GURL& install_url); // Get install URL for Web Kiosk session. const GURL& GetInstallURL() const { return install_url_; }
diff --git a/chrome/browser/lacros/overview_lacros_browsertest.cc b/chrome/browser/lacros/overview_lacros_browsertest.cc index f0913c7..afef7e76 100644 --- a/chrome/browser/lacros/overview_lacros_browsertest.cc +++ b/chrome/browser/lacros/overview_lacros_browsertest.cc
@@ -7,47 +7,20 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/chromeos/test_util.h" #include "chrome/browser/ui/lacros/window_utility.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chromeos/crosapi/mojom/test_controller.mojom-test-utils.h" -#include "chromeos/lacros/lacros_service.h" #include "content/public/test/browser_test.h" #include "ui/aura/window.h" -namespace { - -// If ash does not contain the relevant test controller functionality, then -// there's nothing to do for this test. -bool IsServiceAvailable() { - if (chromeos::LacrosService::Get() - ->GetInterfaceVersion<crosapi::mojom::TestController>() < - static_cast<int>(crosapi::mojom::TestController::MethodMinVersions:: - kEnterOverviewModeMinVersion)) { - LOG(WARNING) << "Unsupported ash version."; - return false; - } - return true; -} - -} // namespace - -using OverviewBrowserTest = InProcessBrowserTest; +using OverviewBrowserTest = ChromeOSBrowserUITest; // We enter overview mode with a single window. When we close the window, // overview mode automatically exits. Check that there's no crash. -// TODO(https://crbug.com/1157314): This test is not safe to run in parallel -// with other lacros tests as overview mode applies to all processes. +// This test is not safe to run in parallel with other lacros tests as overview +// mode applies to all processes. IN_PROC_BROWSER_TEST_F(OverviewBrowserTest, NoCrashWithSingleWindow) { - if (!IsServiceAvailable()) - return; - - // Enter overview mode. - auto& test_controller = chromeos::LacrosService::Get() - ->GetRemote<crosapi::mojom::TestController>(); - base::RunLoop run_loop; - test_controller->EnterOverviewMode(run_loop.QuitClosure()); - run_loop.Run(); + EnterOverviewMode(); // Close the window by closing all tabs and wait for it to stop existing in // ash. @@ -59,25 +32,16 @@ // We enter overview mode with 2 windows. We delete 1 window during overview // mode. Then we exit overview mode. -// TODO(https://crbug.com/1157314): This test is not safe to run in parallel -// with other lacros tests as overview mode applies to all processes. +// This test is not safe to run in parallel with other lacros tests as overview +// mode applies to all processes. IN_PROC_BROWSER_TEST_F(OverviewBrowserTest, NoCrashTwoWindows) { - if (!IsServiceAvailable()) - return; - // Create an incognito window and make it visible. Browser* incognito_browser = Browser::Create(Browser::CreateParams( browser()->profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true), true)); AddBlankTabAndShow(incognito_browser); - // Enter overview mode. - auto& test_controller = chromeos::LacrosService::Get() - ->GetRemote<crosapi::mojom::TestController>(); - base::test::TestFuture<void> future; - test_controller->EnterOverviewMode(future.GetCallback()); - EXPECT_TRUE(future.Wait()); - future.Clear(); + EnterOverviewMode(); // Close the incognito window by closing all tabs and wait for it to stop // existing in ash. @@ -86,7 +50,5 @@ incognito_browser->tab_strip_model()->CloseAllTabs(); ASSERT_TRUE(browser_test_util::WaitForWindowDestruction(incognito_id)); - // Exit overview mode. - test_controller->ExitOverviewMode(future.GetCallback()); - EXPECT_TRUE(future.Wait()); + ExitOverviewMode(); }
diff --git a/chrome/browser/media/router/providers/cast/cast_media_route_provider.cc b/chrome/browser/media/router/providers/cast/cast_media_route_provider.cc index b9d03f6..7c9c33f 100644 --- a/chrome/browser/media/router/providers/cast/cast_media_route_provider.cc +++ b/chrome/browser/media/router/providers/cast/cast_media_route_provider.cc
@@ -362,7 +362,6 @@ mojom::MediaRouteProviderId::CAST, source_id, GetRemotePlaybackMediaSourceCompatibleSinks(media_source, sinks), GetOrigins(source_id)); - LOG(ERROR) << "sent sink updates"; } } // namespace media_router
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager.cc b/chrome/browser/media/webrtc/webrtc_event_log_manager.cc index dd81177e..4bba444 100644 --- a/chrome/browser/media/webrtc/webrtc_event_log_manager.cc +++ b/chrome/browser/media/webrtc/webrtc_event_log_manager.cc
@@ -236,8 +236,7 @@ int lid, base::ProcessId pid, const std::string& url, - const std::string& rtc_configuration, - const std::string& constraints) { + const std::string& rtc_configuration) { OnPeerConnectionAdded(frame_id, lid, base::NullCallback()); }
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager.h b/chrome/browser/media/webrtc/webrtc_event_log_manager.h index 56aeb2c..7585dd5 100644 --- a/chrome/browser/media/webrtc/webrtc_event_log_manager.h +++ b/chrome/browser/media/webrtc/webrtc_event_log_manager.h
@@ -114,8 +114,7 @@ int lid, base::ProcessId pid, const std::string& url, - const std::string& rtc_configuration, - const std::string& constraints) override; + const std::string& rtc_configuration) override; void OnPeerConnectionRemoved(content::GlobalRenderFrameHostId frame_id, int lid) override; void OnPeerConnectionUpdated(content::GlobalRenderFrameHostId frame_id,
diff --git a/chrome/browser/metrics/variations/chrome_variations_service_client.cc b/chrome/browser/metrics/variations/chrome_variations_service_client.cc index fa08d98f..c07d7b9 100644 --- a/chrome/browser/metrics/variations/chrome_variations_service_client.cc +++ b/chrome/browser/metrics/variations/chrome_variations_service_client.cc
@@ -91,8 +91,8 @@ // branded Lacros build, see crbug.com/1474764. if (!g_browser_process->browser_policy_connector()->GetDeviceSettings()) { CHECK_IS_TEST(); // IN-TEST - CHECK(chromeos::BrowserParamsProxy:: - IsCrosapiDisabledForTesting()); // IN-TEST + CHECK(chromeos::BrowserParamsProxy::Get() + ->IsCrosapiDisabledForTesting()); // IN-TEST return false; }
diff --git a/chrome/browser/nearby_sharing/metrics/attachment_metric_logger.cc b/chrome/browser/nearby_sharing/metrics/attachment_metric_logger.cc index fc18fdf..73fe632 100644 --- a/chrome/browser/nearby_sharing/metrics/attachment_metric_logger.cc +++ b/chrome/browser/nearby_sharing/metrics/attachment_metric_logger.cc
@@ -4,8 +4,11 @@ #include "chrome/browser/nearby_sharing/metrics/attachment_metric_logger.h" +#include <utility> + #include "chrome/browser/nearby_sharing/metrics/metric_common.h" #include "components/metrics/structured/structured_events.h" +#include "components/metrics/structured/structured_metrics_client.h" namespace nearby::share::metrics { @@ -25,25 +28,25 @@ // captured in the overall share metrics logged elsewhere. for (auto attachment : share_target.file_attachments) { - ::metrics::structured::events::v2::nearby_share::FileAttachment() - .SetIsReceiving(share_target.is_incoming) - .SetPlatform(static_cast<int>(platform)) - .SetDeviceRelationship(static_cast<int>(relationship)) - .SetFileType(static_cast<int>(attachment.type())) - .SetResult(static_cast<int>(result)) - .SetSize(attachment.size()) - .Record(); + ::metrics::structured::StructuredMetricsClient::Record(std::move( + ::metrics::structured::events::v2::nearby_share::FileAttachment() + .SetIsReceiving(share_target.is_incoming) + .SetPlatform(static_cast<int>(platform)) + .SetDeviceRelationship(static_cast<int>(relationship)) + .SetFileType(static_cast<int>(attachment.type())) + .SetResult(static_cast<int>(result)) + .SetSize(attachment.size()))); } for (auto attachment : share_target.text_attachments) { - ::metrics::structured::events::v2::nearby_share::TextAttachment() - .SetIsReceiving(share_target.is_incoming) - .SetPlatform(static_cast<int>(platform)) - .SetDeviceRelationship(static_cast<int>(relationship)) - .SetTextType(static_cast<int>(attachment.type())) - .SetResult(static_cast<int>(result)) - .SetSize(attachment.size()) - .Record(); + ::metrics::structured::StructuredMetricsClient::Record(std::move( + ::metrics::structured::events::v2::nearby_share::TextAttachment() + .SetIsReceiving(share_target.is_incoming) + .SetPlatform(static_cast<int>(platform)) + .SetDeviceRelationship(static_cast<int>(relationship)) + .SetTextType(static_cast<int>(attachment.type())) + .SetResult(static_cast<int>(result)) + .SetSize(attachment.size()))); } }
diff --git a/chrome/browser/nearby_sharing/metrics/discovery_metric_logger.cc b/chrome/browser/nearby_sharing/metrics/discovery_metric_logger.cc index 557c593a8..26eb54b 100644 --- a/chrome/browser/nearby_sharing/metrics/discovery_metric_logger.cc +++ b/chrome/browser/nearby_sharing/metrics/discovery_metric_logger.cc
@@ -4,9 +4,11 @@ #include "chrome/browser/nearby_sharing/metrics/discovery_metric_logger.h" +#include <utility> + #include "chrome/browser/nearby_sharing/metrics/metric_common.h" #include "components/metrics/structured/structured_events.h" -#include "components/metrics/structured/structured_metrics_features.h" +#include "components/metrics/structured/structured_metrics_client.h" namespace nearby::share::metrics { @@ -34,11 +36,11 @@ auto platform = GetPlatform(share_target); auto relationship = GetDeviceRelationship(share_target); - ::metrics::structured::events::v2::nearby_share::Discovery() - .SetPlatform(static_cast<int>(platform)) - .SetDeviceRelationship(static_cast<int>(relationship)) - .SetTimeToDiscovery(delta.InMilliseconds()) - .Record(); + ::metrics::structured::StructuredMetricsClient::Record( + std::move(::metrics::structured::events::v2::nearby_share::Discovery() + .SetPlatform(static_cast<int>(platform)) + .SetDeviceRelationship(static_cast<int>(relationship)) + .SetTimeToDiscovery(delta.InMilliseconds()))); } } // namespace nearby::share::metrics
diff --git a/chrome/browser/nearby_sharing/metrics/nearby_share_metric_logger.cc b/chrome/browser/nearby_sharing/metrics/nearby_share_metric_logger.cc index 9900172f..c534f30 100644 --- a/chrome/browser/nearby_sharing/metrics/nearby_share_metric_logger.cc +++ b/chrome/browser/nearby_sharing/metrics/nearby_share_metric_logger.cc
@@ -4,11 +4,13 @@ #include "chrome/browser/nearby_sharing/metrics/nearby_share_metric_logger.h" +#include <utility> + #include "base/time/time.h" #include "chrome/browser/nearby_sharing/metrics/metric_common.h" #include "chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom-shared.h" #include "components/metrics/structured/structured_events.h" -#include "components/metrics/structured/structured_metrics_features.h" +#include "components/metrics/structured/structured_metrics_client.h" namespace nearby::share::metrics { @@ -156,7 +158,7 @@ metric.SetTimeToTransferComplete(complete_time.InMilliseconds()); // Emit the metric. - metric.Record(); + ::metrics::structured::StructuredMetricsClient::Record(std::move(metric)); } void NearbyShareMetricLogger::OnBandwidthUpgrade(
diff --git a/chrome/browser/nearby_sharing/metrics/throughput_metric_logger.cc b/chrome/browser/nearby_sharing/metrics/throughput_metric_logger.cc index 0289f1adb..9995a35f 100644 --- a/chrome/browser/nearby_sharing/metrics/throughput_metric_logger.cc +++ b/chrome/browser/nearby_sharing/metrics/throughput_metric_logger.cc
@@ -4,9 +4,12 @@ #include "chrome/browser/nearby_sharing/metrics/throughput_metric_logger.h" +#include <utility> + #include "chrome/browser/nearby_sharing/metrics/metric_common.h" #include "chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom-shared.h" #include "components/metrics/structured/structured_events.h" +#include "components/metrics/structured/structured_metrics_client.h" namespace nearby::share::metrics { @@ -75,16 +78,16 @@ long transferred_bytes = (percentage_complete / 100) * transfer_size; long update_bytes = (percentage_delta / 100) * transfer_size; - ::metrics::structured::events::v2::nearby_share::Throughput() - .SetIsReceiving(share_target.is_incoming) - .SetPlatform(static_cast<int>(platform)) - .SetDeviceRelationship(static_cast<int>(relationship)) - .SetMedium(static_cast<int>(medium)) - .SetTotalTransferBytes(transfer_size) - .SetTransferredBytes(transferred_bytes) - .SetUpdateBytes(update_bytes) - .SetUpdateMillis(update_delta.InMilliseconds()) - .Record(); + ::metrics::structured::StructuredMetricsClient::Record( + std::move(::metrics::structured::events::v2::nearby_share::Throughput() + .SetIsReceiving(share_target.is_incoming) + .SetPlatform(static_cast<int>(platform)) + .SetDeviceRelationship(static_cast<int>(relationship)) + .SetMedium(static_cast<int>(medium)) + .SetTotalTransferBytes(transfer_size) + .SetTransferredBytes(transferred_bytes) + .SetUpdateBytes(update_bytes) + .SetUpdateMillis(update_delta.InMilliseconds()))); } void ThroughputMetricLogger::OnTransferCompleted(
diff --git a/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption.mojom b/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption.mojom index 1464441..04520a8 100644 --- a/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption.mojom +++ b/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption.mojom
@@ -9,4 +9,10 @@ interface PageHandler { // Queries for tabs. GetTabs() => (array<history.mojom.Tab> tabs); + + // Dismisses module until new tabs are found. + DismissModule(array<url.mojom.Url> urls); + + // Restores the module immediately. + RestoreModule(); };
diff --git a/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.cc b/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.cc index 8bf9bce..c776bb96 100644 --- a/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.cc +++ b/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.cc
@@ -46,6 +46,8 @@ namespace { // Maximum number of sessions we're going to display on the NTP const size_t kMaxSessionsToShow = 10; +// Name of preference to track list of dismissed tabs. +const char kDismissedTabsPrefName[] = "NewTabPage.TabResumption.DismissedTabs"; std::u16string FormatRelativeTime(const base::Time& time) { // Return a time like "1 hour ago", "2 days ago", etc. @@ -193,8 +195,19 @@ } } - for (auto i : scored_tab_indices) { - scored_tabs.push_back(std::move(tabs[i])); + bool new_url_found = false; + for (auto index : scored_tab_indices) { + if (IsNewURL(tabs[index]->url)) { + new_url_found = true; + } + scored_tabs.push_back(std::move(tabs[index])); + } + + // Bail if module is still dismissed. + if (profile_->GetPrefs()->GetList(kDismissedTabsPrefName).size() > 0 && + !new_url_found) { + std::move(callback).Run(std::vector<history::mojom::TabPtr>()); + return; } std::sort(scored_tabs.begin(), scored_tabs.end(), CompareTabsByTime); @@ -239,6 +252,12 @@ } // static +void TabResumptionPageHandler::RegisterProfilePrefs( + PrefRegistrySimple* registry) { + registry->RegisterListPref(kDismissedTabsPrefName, base::Value::List()); +} + +// static sync_sessions::OpenTabsUIDelegate* TabResumptionPageHandler::GetOpenTabsUIDelegate() { sync_sessions::SessionSyncService* service = @@ -278,3 +297,28 @@ } return tabs_mojom; } + +void TabResumptionPageHandler::DismissModule(const std::vector<GURL>& urls) { + base::Value::List url_list; + for (const auto& url : urls) { + url_list.Append(url.spec()); + } + profile_->GetPrefs()->SetList(kDismissedTabsPrefName, std::move(url_list)); +} + +void TabResumptionPageHandler::RestoreModule() { + profile_->GetPrefs()->SetList(kDismissedTabsPrefName, base::Value::List()); +} + +bool TabResumptionPageHandler::IsNewURL(GURL url) { + const base::Value::List& cached_urls = + profile_->GetPrefs()->GetList(kDismissedTabsPrefName); + auto it = std::find_if(cached_urls.begin(), cached_urls.end(), + [url](const base::Value& cached_url) { + return cached_url.GetString() == url.spec(); + }); + if (it == cached_urls.end()) { + return true; + } + return false; +}
diff --git a/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.h b/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.h index 9f2a3ba..831474e5 100644 --- a/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.h +++ b/chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.h
@@ -17,6 +17,7 @@ #include "chrome/browser/history/profile_based_browsing_history_driver.h" #include "chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption.mojom.h" #include "components/history/core/browser/history_types.h" +#include "components/prefs/pref_registry_simple.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -47,6 +48,8 @@ // tab_resumption::mojom::PageHandler: void GetTabs(GetTabsCallback callback) override; + static void RegisterProfilePrefs(PrefRegistrySimple* registry); + sync_sessions::OpenTabsUIDelegate* GetOpenTabsUIDelegate(); std::vector<history::mojom::TabPtr> GetForeignTabs(); @@ -63,7 +66,13 @@ GetTabsCallback callback, const std::vector<history::AnnotatedVisit> annotated_visits); + void DismissModule(const std::vector<GURL>& urls) override; + void RestoreModule() override; + private: + // Method to determine if a url is in the list of previously dismissed urls. + bool IsNewURL(GURL url); + // The task tracker for the HistoryService callbacks. base::CancelableTaskTracker task_tracker_;
diff --git a/chrome/browser/notifications/notification_platform_bridge_lacros.cc b/chrome/browser/notifications/notification_platform_bridge_lacros.cc index e258782..94d94636 100644 --- a/chrome/browser/notifications/notification_platform_bridge_lacros.cc +++ b/chrome/browser/notifications/notification_platform_bridge_lacros.cc
@@ -42,6 +42,10 @@ // TYPE_CUSTOM exists only within ash. NOTREACHED(); return crosapi::mojom::NotificationType::kSimple; + case message_center::NOTIFICATION_TYPE_CONVERSATION: + // TYPE_CONVERSATION is not currently supported for Lacros. + NOTREACHED(); + return crosapi::mojom::NotificationType::kSimple; } }
diff --git a/chrome/browser/password_manager/android/BUILD.gn b/chrome/browser/password_manager/android/BUILD.gn index bf4b1d97..1a1750d8 100644 --- a/chrome/browser/password_manager/android/BUILD.gn +++ b/chrome/browser/password_manager/android/BUILD.gn
@@ -464,6 +464,7 @@ ] deps = [ + "//chrome/common:non_code_constants", "//components/autofill/core/common", "//components/browser_sync", "//components/password_manager/core/browser",
diff --git a/chrome/browser/password_manager/android/password_manager_android_util.cc b/chrome/browser/password_manager/android/password_manager_android_util.cc index 58cad50..256ad73 100644 --- a/chrome/browser/password_manager/android/password_manager_android_util.cc +++ b/chrome/browser/password_manager/android/password_manager_android_util.cc
@@ -13,6 +13,7 @@ #include "base/notreached.h" #include "base/strings/string_number_conversions.h" #include "chrome/browser/password_manager/android/password_manager_eviction_util.h" +#include "chrome/common/chrome_switches.h" #include "components/browser_sync/sync_to_signin_migration.h" #include "components/password_manager/core/browser/features/password_features.h" #include "components/password_manager/core/browser/password_manager_constants.h" @@ -70,15 +71,22 @@ LocalUpmUserType GetLocalUpmUserType(PrefService* pref_service, const base::FilePath& login_db_directory) { - std::string gms_version_str = - base::android::BuildInfo::GetInstance()->gms_version_code(); int gms_version = 0; - // `gms_version_str` must be converted to int for comparison, because it can + // gms_version_code() must be converted to int for comparison, because it can // have legacy values "3(...)" and those evaluate > "2023(...)". - if (!base::StringToInt(gms_version_str, &gms_version) || - gms_version < - password_manager::features::kUPMLocalPasswordsMinGmsVersionCode - .Get()) { + // Compare with a constant before comparing with + // kUPMLocalPasswordsMinGmsVersionCode, as the latter will enroll the user + // into the experiment. + bool has_min_gms_version = + base::StringToInt( + base::android::BuildInfo::GetInstance()->gms_version_code(), + &gms_version) && + gms_version >= 240212000 && + gms_version >= + password_manager::features::kUPMLocalPasswordsMinGmsVersionCode.Get(); + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSkipLocalUpmGmsCoreVersionCheckForTesting) && + !has_min_gms_version) { return LocalUpmUserType::kNotEligible; }
diff --git a/chrome/browser/password_manager/android/password_manager_android_util.h b/chrome/browser/password_manager/android/password_manager_android_util.h index db523b2..dccebf9 100644 --- a/chrome/browser/password_manager/android/password_manager_android_util.h +++ b/chrome/browser/password_manager/android/password_manager_android_util.h
@@ -19,6 +19,8 @@ // Called on startup to update the value of UsesSplitStoresAndUPMForLocal(), // based on feature flags, minimum GmsCore version and other criteria. +// If switches::kSkipLocalUpmGmsCoreVersionCheckForTesting is added to the +// command-line, the GmsCore version check will be skipped. void SetUsesSplitStoresAndUPMForLocal(PrefService* pref_service, const base::FilePath& login_db_directory);
diff --git a/chrome/browser/password_manager/android/password_manager_android_util_unittest.cc b/chrome/browser/password_manager/android/password_manager_android_util_unittest.cc index dc9109f5..e46cb8b4 100644 --- a/chrome/browser/password_manager/android/password_manager_android_util_unittest.cc +++ b/chrome/browser/password_manager/android/password_manager_android_util_unittest.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" #include "chrome/browser/sync/sync_service_factory.h" #include "chrome/browser/trusted_vault/trusted_vault_service_factory.h" +#include "chrome/common/chrome_switches.h" #include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" @@ -195,6 +196,10 @@ UsesSplitStoresAndUPMForLocalTest() { base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( syncer::kSyncDeferredStartupTimeoutSeconds, "0"); + // Skip the Gms version check, otherwise enabling UPM flags in individual + // tests won't actually do anything in bots with outdated GmsCore. + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kSkipLocalUpmGmsCoreVersionCheckForTesting); } // Can be invoked more than once, calling DestroyProfile() in-between. @@ -595,6 +600,8 @@ kUnifiedPasswordManagerLocalPasswordsAndroidNoMigration, {{password_manager::features::kUPMLocalPasswordsMinGmsVersionCode.name, base::ToString(std::numeric_limits<int>::max())}}); + base::CommandLine::ForCurrentProcess()->RemoveSwitch( + switches::kSkipLocalUpmGmsCoreVersionCheckForTesting); fake_server::FakeServerHttpPostProvider::DisableNetwork(); CreateProfile(); ASSERT_TRUE(
diff --git a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc index fc518fec..2596125e 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
@@ -95,7 +95,7 @@ #include "chrome/browser/password_manager/account_password_store_factory.h" #include "chrome/browser/password_manager/android/password_accessory_controller_impl.h" #include "chrome/browser/password_manager/android/password_generation_controller.h" -#include "chrome/browser/password_manager/android/password_manager_android_util.h" +#include "chrome/common/chrome_switches.h" #endif // BUILDFLAG(IS_ANDROID) using autofill::CalculateFormSignature; @@ -1430,13 +1430,16 @@ class ChromePasswordManagerClientWithAccountStoreAndroidTest : public ChromePasswordManagerClientAndroidTest { void SetUp() override { - // Using the account store on Android also requires UPM support for local - // passwords. + // Using the account store on Android requires enabling the flag for UPM + // support of local passwords. Skip the Gms version check, otherwise the + // flag won't do anything in bots that have outdated GmsCore. feature_list_.InitWithFeatures( {password_manager::features:: kUnifiedPasswordManagerLocalPasswordsAndroidNoMigration, password_manager::features::kSharedPasswordNotificationUI}, {}); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kSkipLocalUpmGmsCoreVersionCheckForTesting); ChromePasswordManagerClientAndroidTest::SetUp();
diff --git a/chrome/browser/pdf/pdf_extension_js_test.cc b/chrome/browser/pdf/pdf_extension_js_test.cc index bc2d688e..8e7c2f9 100644 --- a/chrome/browser/pdf/pdf_extension_js_test.cc +++ b/chrome/browser/pdf/pdf_extension_js_test.cc
@@ -33,7 +33,6 @@ #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/scoped_time_zone.h" -#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" #include "extensions/test/result_catcher.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "pdf/buildflags.h" @@ -95,15 +94,13 @@ GURL url(embedded_test_server()->GetURL("/pdf/" + pdf_filename)); - // It should be good enough to just navigate to the URL. But loading up the - // BrowserPluginGuest seems to happen asynchronously as there was flakiness - // being seen due to the BrowserPluginGuest not being available yet (see - // crbug.com/498077). So instead use LoadPdf() which ensures that the PDF is + // Use `LoadPdfInNewTab()` or `LoadPdf()`, which ensures that the PDF is // loaded before continuing. - extensions::MimeHandlerViewGuest* guest = - new_tab ? LoadPdfInNewTabGetMimeHandlerView(url) - : LoadPdfGetMimeHandlerView(url); - ASSERT_TRUE(guest); + ASSERT_TRUE(new_tab ? LoadPdfInNewTab(url) : LoadPdf(url)); + content::RenderFrameHost* extension_host = + pdf_extension_test_util::GetOnlyPdfExtensionHost( + GetActiveWebContents()); + ASSERT_TRUE(extension_host); constexpr char kModuleLoaderTemplate[] = R"(var s = document.createElement('script'); @@ -115,7 +112,7 @@ document.body.appendChild(s);)"; bool result = content::ExecJs( - guest->GetGuestMainFrame(), + extension_host, base::StringPrintf(kModuleLoaderTemplate, chrome::kChromeUIWebUITestHost, filename.c_str())); @@ -138,215 +135,100 @@ }; IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Basic) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("basic_test.js", "test.pdf"); EXPECT_EQ(1, CountPDFProcesses()); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, BasicPlugin) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("basic_plugin_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, PluginController) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("plugin_controller_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Viewport) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("viewport_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ViewportScroller) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("viewport_scroller_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Layout3) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("layout_test.js", "test-layout3.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Layout4) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("layout_test.js", "test-layout4.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Bookmark) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("bookmarks_test.js", "test-bookmarks-with-zoom.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Navigator) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("navigator_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ParamsParser) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("params_parser_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ZoomManager) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("zoom_manager_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, GestureDetector) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("gesture_detector_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, SwipeDetector) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("swipe_detector_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, TouchHandling) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("touch_handling_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Elements) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("material_elements_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, DownloadControls) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("download_controls_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Title) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("title_test.js", "test-title.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, WhitespaceTitle) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("whitespace_title_test.js", "test-whitespace-title.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, PageChange) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("page_change_test.js", "test-bookmarks.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ScrollWithFormFieldFocusedTest) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("scroll_with_form_field_focused_test.js", "test-bookmarks.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Metrics) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("metrics_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ViewerPasswordDialog) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("viewer_password_dialog_test.js", "encrypted.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ArrayBufferAllocator) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - // Run several times to see if there are issues with unloading. RunTestsInJsModule("beep_test.js", "array_buffer.pdf"); RunTestsInJsModule("beep_test.js", "array_buffer.pdf"); @@ -354,66 +236,36 @@ } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ViewerToolbar) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("viewer_toolbar_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ViewerPdfSidenav) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("viewer_pdf_sidenav_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ViewerThumbnailBar) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("viewer_thumbnail_bar_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ViewerThumbnail) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("viewer_thumbnail_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ViewerAttachmentBar) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("viewer_attachment_bar_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ViewerAttachment) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("viewer_attachment_test.js", "test.pdf"); @@ -431,11 +283,6 @@ } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ViewerPropertiesDialog) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - // The properties dialog formats some values based on locale. base::test::ScopedRestoreICUDefaultLocale scoped_locale{"en_US"}; // This will apply to the new processes spawned within RunTestsInJsModule(), @@ -445,11 +292,6 @@ } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, PostMessageProxy) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("post_message_proxy_test.js", "test.pdf"); @@ -457,11 +299,6 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Printing) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("printing_icon_test.js", "test.pdf"); } #endif // BUILDFLAG(IS_CHROMEOS_ASH) @@ -480,22 +317,12 @@ } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, AnnotationsToolbar) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("annotations_toolbar_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ViewerToolbarDropdown) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("viewer_toolbar_dropdown_test.js", "test.pdf"); @@ -506,11 +333,6 @@ // TODO(crbug.com/1444895): Re-enable it when integrating PDF OCR with // Select-to-Speak. IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, DISABLED_PdfOcrToolbar) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("pdf_ocr_toolbar_test.js", "test.pdf"); @@ -535,11 +357,6 @@ }; IN_PROC_BROWSER_TEST_P(PDFExtensionContentSettingJSTest, Beep) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("beep_test.js", "test-beep.pdf"); } @@ -591,11 +408,6 @@ } IN_PROC_BROWSER_TEST_P(PDFExtensionContentSettingJSTest, BeepCsp) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - // The script-source * directive in the mock headers file should // allow the JavaScript to execute the beep(). RunTestsInJsModule("beep_test.js", "test-beep-csp.pdf"); @@ -624,11 +436,6 @@ // Regression test for https://crbug.com/1239148. IN_PROC_BROWSER_TEST_P(PDFExtensionWebUICodeCacheJSTest, Basic) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunTestsInJsModule("basic_test.js", "test.pdf"); } @@ -658,33 +465,18 @@ // Test navigating to a PDF in the scope of a service worker with no fetch event // handler. IN_PROC_BROWSER_TEST_P(PDFExtensionServiceWorkerJSTest, NoFetchHandler) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunServiceWorkerTest("empty.js"); } // Test navigating to a PDF when a service worker intercepts the request and // then falls back to network by not calling FetchEvent.respondWith(). IN_PROC_BROWSER_TEST_P(PDFExtensionServiceWorkerJSTest, NetworkFallback) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunServiceWorkerTest("network_fallback_worker.js"); } // Test navigating to a PDF when a service worker intercepts the request and // provides a response. IN_PROC_BROWSER_TEST_P(PDFExtensionServiceWorkerJSTest, Interception) { - // TODO(crbug.com/1445746): Remove this once the test passes for OOPIF PDF. - if (UseOopif()) { - GTEST_SKIP(); - } - RunServiceWorkerTest("respond_with_fetch_worker.js"); }
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 690f748..8e10086 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -281,6 +281,7 @@ #include "chrome/browser/new_tab_page/modules/photos/photos_service.h" #include "chrome/browser/new_tab_page/modules/recipes/recipes_service.h" #include "chrome/browser/new_tab_page/modules/safe_browsing/safe_browsing_handler.h" +#include "chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.h" #include "chrome/browser/new_tab_page/promos/promo_service.h" #include "chrome/browser/policy/developer_tools_policy_handler.h" #include "chrome/browser/search/background/ntp_custom_background_service.h" @@ -1865,6 +1866,7 @@ send_tab_to_self::RegisterProfilePrefs(registry); signin::RegisterProfilePrefs(registry); StartupBrowserCreator::RegisterProfilePrefs(registry); + TabResumptionPageHandler::RegisterProfilePrefs(registry); tab_organization_prefs::RegisterProfilePrefs(registry); tab_search_prefs::RegisterProfilePrefs(registry); ThemeColorPickerHandler::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc index 4dd3da39..023a6d5 100644 --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -181,6 +181,7 @@ #include "chrome/browser/tpcd/experiment/eligibility_service_factory.h" #include "chrome/browser/tpcd/heuristics/opener_heuristic_service_factory.h" #include "chrome/browser/tpcd/metadata/updater_service_factory.h" +#include "chrome/browser/tpcd/support/top_level_trial_service_factory.h" #include "chrome/browser/tpcd/support/tpcd_support_service_factory.h" #include "chrome/browser/translate/translate_model_service_factory.h" #include "chrome/browser/translate/translate_ranker_factory.h" @@ -405,10 +406,6 @@ #include "chrome/browser/permissions/prediction_model_handler_provider_factory.h" #endif -#if BUILDFLAG(IS_MAC) -#include "chrome/browser/ui/cocoa/screentime/history_bridge_factory.h" -#include "chrome/browser/ui/cocoa/screentime/screentime_features.h" -#endif #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \ BUILDFLAG(IS_CHROMEOS_ASH) @@ -1119,11 +1116,6 @@ screen_ai::PdfOcrControllerFactory::GetInstance(); screen_ai::ScreenAIServiceRouterFactory::EnsureFactoryBuilt(); #endif -#if BUILDFLAG(IS_MAC) - if (screentime::IsScreenTimeEnabled()) { - screentime::HistoryBridgeFactory::GetInstance(); - } -#endif SCTReportingServiceFactory::GetInstance(); search_engines::SearchEngineChoiceServiceFactory::GetInstance(); #if BUILDFLAG(IS_ANDROID) @@ -1224,6 +1216,7 @@ tpcd::experiment::EligibilityServiceFactory::GetInstance(); tpcd::metadata::UpdaterServiceFactory::GetInstance(); tpcd::trial::TpcdTrialServiceFactory::GetInstance(); + tpcd::trial::TopLevelTrialServiceFactory::GetInstance(); #if !BUILDFLAG(IS_ANDROID) TrackingProtectionNoticeFactory::GetInstance(); #endif
diff --git a/chrome/browser/profiles/keep_alive/profile_keep_alive_types.cc b/chrome/browser/profiles/keep_alive/profile_keep_alive_types.cc index 85002bc..5d27308c 100644 --- a/chrome/browser/profiles/keep_alive/profile_keep_alive_types.cc +++ b/chrome/browser/profiles/keep_alive/profile_keep_alive_types.cc
@@ -57,8 +57,6 @@ return out << "kCrxInstaller"; case ProfileKeepAliveOrigin::kProfilePickerView: return out << "kProfilePickerView"; - case ProfileKeepAliveOrigin::kCommanderFrontend: - return out << "kCommanderFrontend"; case ProfileKeepAliveOrigin::kDiceWebSigninInterceptionBubble: return out << "kDiceWebSigninInterceptionBubble"; case ProfileKeepAliveOrigin::kHistoryMenuBridge:
diff --git a/chrome/browser/profiles/keep_alive/profile_keep_alive_types.h b/chrome/browser/profiles/keep_alive/profile_keep_alive_types.h index 25c496f..a774342 100644 --- a/chrome/browser/profiles/keep_alive/profile_keep_alive_types.h +++ b/chrome/browser/profiles/keep_alive/profile_keep_alive_types.h
@@ -115,9 +115,8 @@ // Profile, but may be a different one in Lacros. kProfilePickerView = 25, - // The frontend view for Commander exists (even if it's not visible). It - // renders to a WebUI, so we can't just destroy it whenever we want. - kCommanderFrontend = 26, + // DEPRECATED + // kCommanderFrontend = 26, // UI bubble that may outlive the Browser, especially on Mac. kDiceWebSigninInterceptionBubble = 27,
diff --git a/chrome/browser/profiles/profile_attributes_entry.cc b/chrome/browser/profiles/profile_attributes_entry.cc index a612123..a2c759b 100644 --- a/chrome/browser/profiles/profile_attributes_entry.cc +++ b/chrome/browser/profiles/profile_attributes_entry.cc
@@ -57,6 +57,7 @@ const char kHostedDomain[] = "hosted_domain"; const char kProfileManagementEnrollmentToken[] = "profile_management_enrollment_token"; +const char kDasherlessManagement[] = "dasherless_management"; const char kProfileManagementOidcAuthToken[] = "profile_management_oidc_auth_token"; const char kProfileManagementOidcIdToken[] = "profile_management_oidc_id_token"; @@ -480,6 +481,10 @@ return GetBool(prefs::kSignedInWithCredentialProvider); } +bool ProfileAttributesEntry::IsDasherlessManagement() const { + return GetBool(kDasherlessManagement); +} + size_t ProfileAttributesEntry::GetAvatarIconIndex() const { std::string icon_url = GetString(kAvatarIconKey); size_t icon_index = 0; @@ -674,6 +679,10 @@ SetBool(prefs::kSignedInWithCredentialProvider, value); } +void ProfileAttributesEntry::SetDasherlessManagement(bool value) { + SetBool(kDasherlessManagement, value); +} + void ProfileAttributesEntry::LockForceSigninProfile(bool is_lock) { DCHECK(signin_util::IsForceSigninEnabled()); if (SetBool(kForceSigninProfileLockedKey, is_lock)) {
diff --git a/chrome/browser/profiles/profile_attributes_entry.h b/chrome/browser/profiles/profile_attributes_entry.h index fc70c77..3d620b4f 100644 --- a/chrome/browser/profiles/profile_attributes_entry.h +++ b/chrome/browser/profiles/profile_attributes_entry.h
@@ -138,6 +138,9 @@ bool IsUsingDefaultAvatar() const; // Indicates that profile was signed in through native OS credential provider. bool IsSignedInWithCredentialProvider() const; + // Returns true if the profile is managed by a third party identity that is + // not sync-ed to Google (i.e dasher-based). + bool IsDasherlessManagement() const; // Returns the index of the default icon used by the profile. size_t GetAvatarIconIndex() const; // Returns the colors specified by the profile theme, or default colors if no @@ -193,6 +196,7 @@ void SetLastDownloadedGAIAPictureUrlWithSize( const std::string& image_url_with_size); void SetSignedInWithCredentialProvider(bool value); + void SetDasherlessManagement(bool value); // Only non-omitted profiles can be set as non-ephemeral. It's the // responsibility of the caller to make sure that the entry is set as // non-ephemeral only if prefs::kForceEphemeralProfiles is false.
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 2933117..9c8a845 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -101,6 +101,7 @@ #include "chrome/browser/ssl/stateful_ssl_host_state_delegate_factory.h" #include "chrome/browser/startup_data.h" #include "chrome/browser/storage/storage_notification_service_factory.h" +#include "chrome/browser/tpcd/support/top_level_trial_service_factory.h" #include "chrome/browser/tpcd/support/tpcd_support_service_factory.h" #include "chrome/browser/transition_manager/full_browser_transition_manager.h" #include "chrome/browser/ui/startup/startup_browser_creator.h" @@ -876,9 +877,11 @@ // as it depends on the default StoragePartition being initialized. GetOriginTrialsControllerDelegate(); - // The TpcdTrialService must be created with the profile, but after the - // initialization of the OriginTrialsControllerDelegate, as it depends on it. + // The TpcdTrialService and TopLevelTrialService must be created with the + // profile, but after the initialization of the + // OriginTrialsControllerDelegate, as it depends on it. tpcd::trial::TpcdTrialServiceFactory::GetForProfile(this); + tpcd::trial::TopLevelTrialServiceFactory::GetForProfile(this); } base::FilePath ProfileImpl::last_selected_directory() {
diff --git a/chrome/browser/readaloud/android/java/res/layout/readaloud_mini_player_layout.xml b/chrome/browser/readaloud/android/java/res/layout/readaloud_mini_player_layout.xml index 3530f379..4504d3dc0 100644 --- a/chrome/browser/readaloud/android/java/res/layout/readaloud_mini_player_layout.xml +++ b/chrome/browser/readaloud/android/java/res/layout/readaloud_mini_player_layout.xml
@@ -14,7 +14,7 @@ android:layout_height="wrap_content" android:layout_gravity="start|bottom" android:orientation="vertical" - android:animateLayoutChanges="true" + android:alpha="0" android:visibility="gone"> <!-- Shadow --> @@ -36,8 +36,7 @@ android:id="@+id/mini_player_container" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingHorizontal="16dp" - android:alpha="0"> + android:paddingHorizontal="16dp"> <!-- Buffering/unknown layout. --> <LinearLayout @@ -190,7 +189,6 @@ android:progress="0" android:progressTint="@macro/default_icon_color" android:progressTintMode="src_atop" - android:visibility="gone" - android:alpha="0"/> + android:visibility="gone"/> </FrameLayout> </org.chromium.chrome.browser.readaloud.player.mini.MiniPlayerLayout> \ No newline at end of file
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayout.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayout.java index 0980529..5eff6f8 100644 --- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayout.java +++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayout.java
@@ -28,8 +28,6 @@ import androidx.annotation.ColorInt; -import com.google.android.material.animation.ChildrenAlphaProperty; - import org.chromium.chrome.browser.readaloud.player.Colors; import org.chromium.chrome.browser.readaloud.player.InteractionHandler; import org.chromium.chrome.browser.readaloud.player.R; @@ -146,6 +144,7 @@ return; } mFinalOpacity = endValue; + setAlpha(startValue); Runnable onFinished = endValue == 1f ? mMediator::onFullOpacityReached : mMediator::onZeroOpacityReached; @@ -153,9 +152,7 @@ if (mEnableAnimations) { // TODO: handle case where existing animation is incomplete and needs to be reversed destroyAnimator(); - mAnimator = - ObjectAnimator.ofFloat( - mBackdrop, ChildrenAlphaProperty.CHILDREN_ALPHA, endValue); + mAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, endValue); mAnimator.setDuration(FADE_DURATION_MS); mAnimator.setInterpolator(FADE_INTERPOLATOR); mAnimator.addListener( @@ -168,8 +165,7 @@ }); mAnimator.start(); } else { - mContents.setAlpha(endValue); - mProgressBar.setAlpha(endValue); + setAlpha(endValue); onFinished.run(); } }
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayoutUnitTest.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayoutUnitTest.java index 845aa721..da449e4 100644 --- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayoutUnitTest.java +++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerLayoutUnitTest.java
@@ -188,21 +188,19 @@ @Test public void testFadeInWithoutAnimation() { - View container = mLayout.findViewById(R.id.mini_player_container); - assertEquals(0f, container.getAlpha(), /* delta= */ 0f); + assertEquals(0f, mLayout.getAlpha(), /* delta= */ 0f); mLayout.enableAnimations(false); mLayout.changeOpacity(0f, 1f); assertNull(mLayout.getAnimatorForTesting()); - assertEquals(1f, container.getAlpha(), /* delta= */ 0f); + assertEquals(1f, mLayout.getAlpha(), /* delta= */ 0f); verify(mMediator).onFullOpacityReached(); } @Test public void testFadeInWithAnimation() { - View container = mLayout.findViewById(R.id.mini_player_container); - assertEquals(0f, container.getAlpha(), /* delta= */ 0f); + assertEquals(0f, mLayout.getAlpha(), /* delta= */ 0f); mLayout.enableAnimations(true); mLayout.changeOpacity(0f, 1f); @@ -212,7 +210,7 @@ assertEquals(300L, animator.getDuration()); animator.end(); - assertEquals(1f, container.getAlpha(), /* delta= */ 0f); + assertEquals(1f, mLayout.getAlpha(), /* delta= */ 0f); verify(mMediator).onFullOpacityReached(); } @@ -223,14 +221,13 @@ mLayout.changeOpacity(0f, 1f); // Ensure we're starting with full opacity. - View container = mLayout.findViewById(R.id.mini_player_container); - assertEquals(1f, container.getAlpha(), /* delta= */ 0f); + assertEquals(1f, mLayout.getAlpha(), /* delta= */ 0f); // Fade out. mLayout.changeOpacity(1f, 0f); assertNull(mLayout.getAnimatorForTesting()); - assertEquals(0f, container.getAlpha(), /* delta= */ 0f); + assertEquals(0f, mLayout.getAlpha(), /* delta= */ 0f); verify(mMediator).onZeroOpacityReached(); } @@ -241,8 +238,7 @@ mLayout.changeOpacity(0f, 1f); // Ensure we're starting with full opacity. - View container = mLayout.findViewById(R.id.mini_player_container); - assertEquals(1f, container.getAlpha(), /* delta= */ 0f); + assertEquals(1f, mLayout.getAlpha(), /* delta= */ 0f); // Fade out. mLayout.enableAnimations(true); @@ -253,7 +249,7 @@ assertEquals(300L, animator.getDuration()); animator.end(); - assertEquals(0f, container.getAlpha(), /* delta= */ 0f); + assertEquals(0f, mLayout.getAlpha(), /* delta= */ 0f); verify(mMediator).onZeroOpacityReached(); }
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediator.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediator.java index 6b62cda..a31b998 100644 --- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediator.java +++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediator.java
@@ -19,17 +19,14 @@ * Mediator class responsible for controlling Read Aloud mini player. * * <p>The show animation has the following steps: - * - * <li>Set player visibility from GONE to INVISIBLE to cause it to layout, getting its height. Make - * the compositor scene layer visible. + * <li>Set player visibility from GONE to VISIBLE to cause it to layout, getting its height, but + * leave it transparent. Make the compositor scene layer visible. * <li>Grow bottom controls to cause web contents to shrink and make room for the player. The scene * layer pretends to be the real player and slides up smoothly with the changing bottom controls * min height. - * <li>When the resize is done, make the player VISIBLE with transparent contents. - * <li>Fade in the contents. + * <li>When the resize is done, fade in the contents. * - * <p>The hide animation is the reverse of the show animation: - * + * <p>The hide animation is the reverse of the show animation: * <li>Fade out the player contents. * <li>Make the scene layer visible and set the player visibility to GONE. * <li>Shrink the bottom controls and move the scene layer down along with the changing bottom @@ -130,8 +127,8 @@ // Grow immediately if height is already known. growBottomControls(); } - // Set player visibility from GONE to INVISIBLE so that it has a height. - mModel.set(Properties.ANDROID_VIEW_VISIBILITY, View.INVISIBLE); + // Set player visibility from GONE to VISIBLE so that it has a height. + mModel.set(Properties.ANDROID_VIEW_VISIBILITY, View.VISIBLE); } /** @@ -151,7 +148,6 @@ // (2) Finished growing, start fading in. private void onBottomControlsGrown() { // Step two: fade in if transition is animated, or jump to full opacity otherwise. - mModel.set(Properties.ANDROID_VIEW_VISIBILITY, View.VISIBLE); mModel.set(Properties.CONTENTS_OPAQUE, true); }
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediatorUnitTest.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediatorUnitTest.java index 7e42f00..fa093d2 100644 --- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediatorUnitTest.java +++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediatorUnitTest.java
@@ -83,7 +83,7 @@ assertFalse(mModel.get(Properties.ANIMATE_VISIBILITY_CHANGES)); assertTrue(mModel.get(Properties.COMPOSITED_VIEW_VISIBLE)); assertEquals(VisibilityState.SHOWING, mMediator.getVisibility()); - assertEquals(View.INVISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); + assertEquals(View.VISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); // Simulate the layout reporting its height. mMediator.onHeightKnown(HEIGHT_PX); @@ -95,8 +95,7 @@ // Simulate the bottom controls being resized instantly. onControlsOffsetChanged(0, HEIGHT_PX, false); - // Layout should become visible. - assertEquals(View.VISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); + // Layout should become opaque. assertTrue(mModel.get(Properties.CONTENTS_OPAQUE)); // Simulate the layout calling back after setting opacity. @@ -113,7 +112,7 @@ assertTrue(mModel.get(Properties.ANIMATE_VISIBILITY_CHANGES)); assertTrue(mModel.get(Properties.COMPOSITED_VIEW_VISIBLE)); assertEquals(VisibilityState.SHOWING, mMediator.getVisibility()); - assertEquals(View.INVISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); + assertEquals(View.VISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); // Simulate the layout reporting its height. mMediator.onHeightKnown(HEIGHT_PX); @@ -129,13 +128,12 @@ onControlsOffsetChanged(-HEIGHT_PX / 3, 2 * HEIGHT_PX / 3, true); // Make sure the next step doesn't start until resizing finishes. - assertEquals(View.INVISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); + assertFalse(mModel.get(Properties.CONTENTS_OPAQUE)); // Browser controls reach their final height. onControlsOffsetChanged(0, HEIGHT_PX, true); - // Layout should become visible. - assertEquals(View.VISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); + // Layout should become opaque. assertTrue(mModel.get(Properties.CONTENTS_OPAQUE)); // Simulate the layout calling back after fading in. @@ -166,7 +164,7 @@ assertTrue(mModel.get(Properties.ANIMATE_VISIBILITY_CHANGES)); assertTrue(mModel.get(Properties.COMPOSITED_VIEW_VISIBLE)); assertEquals(VisibilityState.SHOWING, mMediator.getVisibility()); - assertEquals(View.INVISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); + assertEquals(View.VISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); // Simulate the layout reporting its height. mMediator.onHeightKnown(HEIGHT_PX); @@ -182,8 +180,7 @@ // will fade in the view; ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); - // Layout should become visible. - assertEquals(View.VISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); + // Layout should become opaque. assertTrue(mModel.get(Properties.CONTENTS_OPAQUE)); // Simulate the layout calling back after fading in. @@ -200,7 +197,7 @@ assertTrue(mModel.get(Properties.ANIMATE_VISIBILITY_CHANGES)); assertTrue(mModel.get(Properties.COMPOSITED_VIEW_VISIBLE)); assertEquals(VisibilityState.SHOWING, mMediator.getVisibility()); - assertEquals(View.INVISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); + assertEquals(View.VISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); // Simulate the layout reporting its height. mMediator.onHeightKnown(HEIGHT_PX); @@ -213,12 +210,13 @@ // Simulate the bottom controls being resized with an animation onBottomControlsHeightChanged(HEIGHT_PX, HEIGHT_PX); - onControlsOffsetChanged(-HEIGHT_PX, 0, true); + onControlsOffsetChanged(-HEIGHT_PX, HEIGHT_PX, true); + assertTrue(mModel.get(Properties.CONTENTS_OPAQUE)); ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); - // The delayed runnable should do nothing, lLayout should stay invisible - assertEquals(View.INVISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); + // The delayed runnable should do nothing, contents should stay opaque + assertTrue(mModel.get(Properties.CONTENTS_OPAQUE)); } @Test @@ -389,6 +387,7 @@ mMediator.show(/* animate= */ true); mMediator.onHeightKnown(HEIGHT_PX); + assertEquals(View.VISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); // Bottom controls resize should take previous height into account. verify(mBrowserControlsSizer).setBottomControlsHeight(eq(totalHeight), eq(HEIGHT_PX)); @@ -397,9 +396,7 @@ onControlsOffsetChanged(-HEIGHT_PX, 0, true); onControlsOffsetChanged(-2 * HEIGHT_PX / 3, HEIGHT_PX / 3, true); onControlsOffsetChanged(-HEIGHT_PX / 3, 2 * HEIGHT_PX / 3, true); - assertEquals(View.INVISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); onControlsOffsetChanged(0, HEIGHT_PX, true); - assertEquals(View.VISIBLE, mModel.get(Properties.ANDROID_VIEW_VISIBILITY)); assertTrue(mModel.get(Properties.CONTENTS_OPAQUE)); }
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index ea195355..21e0632 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -26,7 +26,6 @@ "access_code_cast:resources", "app_service_internals:resources", "bookmarks:resources", - "commander:resources", "commerce:resources", "downloads:resources", "feed:resources",
diff --git a/chrome/browser/resources/ash/settings/internet_page/internet_detail_subpage.html b/chrome/browser/resources/ash/settings/internet_page/internet_detail_subpage.html index be11495f..7ccaf67 100644 --- a/chrome/browser/resources/ash/settings/internet_page/internet_detail_subpage.html +++ b/chrome/browser/resources/ash/settings/internet_page/internet_detail_subpage.html
@@ -45,15 +45,8 @@ margin-inline-start: var(--cr-controlled-by-spacing); } - .signin-button { - margin-inline-end: 8px; - padding: 8px 16px 8px 8px; - } - - .signin-icon { - background-color: var(--text-color); - margin-inline-end: 4px; - margin-inline-start: 0; + #signinButton > iron-icon { + margin-inline-end: 0; } #mac-address-container { @@ -95,11 +88,11 @@ </cr-policy-indicator> </template> </div> - <cr-button class="signin-button" id="signinButton" on-click="onSigninClick_" + <cr-button id="signinButton" on-click="onSigninClick_" hidden$="[[!showSignin_(managedProperties_)]]" disabled="[[disableSignin_(managedProperties_, disabled_)]]"> - <div class="signin-icon cr-icon icon-external"></div> - $i18n{networkButtonSignin} + <iron-icon icon="cr:open-in-new" slot="prefix-icon"></iron-icon> + $i18n{networkButtonSignin} </cr-button> <cr-button id="forgetButton" on-click="onForgetClick_" hidden$="[[!showForget_(managedProperties_)]]"
diff --git a/chrome/browser/resources/chromeos/add_supervision/add_supervision_ui.ts b/chrome/browser/resources/chromeos/add_supervision/add_supervision_ui.ts index 7e0916e..82b604d 100644 --- a/chrome/browser/resources/chromeos/add_supervision/add_supervision_ui.ts +++ b/chrome/browser/resources/chromeos/add_supervision/add_supervision_ui.ts
@@ -41,15 +41,15 @@ /** Returns true if the URL references an HTTP request to localhost. */ export function isLocalHostForTesting(url: URL): boolean { - return url.protocol == 'http:' && url.hostname == '127.0.0.1'; + return url.protocol === 'http:' && url.hostname === '127.0.0.1'; } /** Returns true if the URL references one of the allowed hosts. */ function isAllowedHost(url: URL): boolean { - return url.protocol == 'https:' && + return url.protocol === 'https:' && ALLOWED_HOSTS.some( (allowedHost) => - url.host == allowedHost || url.host.endsWith('.' + allowedHost)); + url.host === allowedHost || url.host.endsWith('.' + allowedHost)); } /** Returns true if the request should be allowed. */
diff --git a/chrome/browser/resources/chromeos/emulator/battery_settings.js b/chrome/browser/resources/chromeos/emulator/battery_settings.js index ae11cdf0..c7fdb01e 100644 --- a/chrome/browser/resources/chromeos/emulator/battery_settings.js +++ b/chrome/browser/resources/chromeos/emulator/battery_settings.js
@@ -221,11 +221,11 @@ }, isBatteryPresent() { - return this.batteryState != 'Not Present'; + return this.batteryState !== 'Not Present'; }, isDualRole(source) { - return source.type == 'DualRoleUSB'; + return source.type === 'DualRoleUSB'; }, /** @@ -234,11 +234,11 @@ * @private */ cssClassForSetAsSource_(source) { - return source.id == this.selectedPowerSourceId ? '' : 'action-button'; + return source.id === this.selectedPowerSourceId ? '' : 'action-button'; }, canAmpsChange(type) { - return type == 'USB'; + return type === 'USB'; }, canBecomeSource(source, selectedId, powerSourceOptionsChange) { @@ -246,7 +246,7 @@ return false; } return !this.powerSourceOptions.some(function(source) { - return source.connected && source.type == 'DedicatedCharger'; + return source.connected && source.type === 'DedicatedCharger'; }); }, });
diff --git a/chrome/browser/resources/chromeos/emulator/bluetooth_settings.js b/chrome/browser/resources/chromeos/emulator/bluetooth_settings.js index b2d49415..d3e7f87 100644 --- a/chrome/browser/resources/chromeos/emulator/bluetooth_settings.js +++ b/chrome/browser/resources/chromeos/emulator/bluetooth_settings.js
@@ -235,7 +235,7 @@ const addressRegex = RegExp('^([\\da-fA-F]{2}:){5}[\\da-fA-F]{2}$'); if (addressRegex.test(val)) { for (let i = 0; i < this.predefinedDevices.length; ++i) { - if (this.predefinedDevices[i].address == val) { + if (this.predefinedDevices[i].address === val) { exists = true; break; } @@ -243,7 +243,7 @@ if (!exists) { for (let i = 0; i < this.devices.length; ++i) { - if (this.devices[i].address == val && i != this.currentEditIndex) { + if (this.devices[i].address === val && i !== this.currentEditIndex) { exists = true; break; } @@ -271,7 +271,7 @@ let exists = false; for (let i = 0; i < this.predefinedDevices.length; ++i) { - if (this.predefinedDevices[i].path == val) { + if (this.predefinedDevices[i].path === val) { exists = true; break; } @@ -279,7 +279,7 @@ if (!exists) { for (let i = 0; i < this.devices.length; ++i) { - if (this.devices[i].path == val && i != this.currentEditIndex) { + if (this.devices[i].path === val && i !== this.currentEditIndex) { exists = true; break; } @@ -302,7 +302,7 @@ * @return {boolean} Whether the PIN/passkey input field should be shown. */ showAuthToken(pairMethod) { - return !!pairMethod && pairMethod != 'None'; + return !!pairMethod && pairMethod !== 'None'; }, /** @@ -334,7 +334,7 @@ /** @type {!Array<!BluetoothDevice>} */ const deviceList = []; for (let i = 0; i < devices.length; ++i) { - if (this.devicePaths[devices[i].path] != undefined) { + if (this.devicePaths[devices[i].path] !== undefined) { continue; } @@ -359,7 +359,7 @@ devicePairedFromTray_(path) { const obj = this.devicePaths[path]; - if (obj == undefined) { + if (obj === undefined) { return; } @@ -378,7 +378,7 @@ pairDevice(event) { const index = event.model.index; const predefined = - /** @type {boolean} */ (event.target.dataset.predefined == 'true'); + /** @type {boolean} */ (event.target.dataset.predefined === 'true'); const device = predefined ? this.predefinedDevices[index] : this.devices[index]; @@ -411,7 +411,7 @@ pairFailed_(path) { const obj = this.devicePaths[path]; - if (obj == undefined) { + if (obj === undefined) { return; } @@ -428,7 +428,7 @@ discoverDevice(event) { const index = event.model.index; const predefined = - /** @type {boolean} */ (event.target.dataset.predefined == 'true'); + /** @type {boolean} */ (event.target.dataset.predefined === 'true'); const device = predefined ? this.predefinedDevices[index] : this.devices[index]; @@ -463,7 +463,7 @@ * @private */ addBluetoothDevice_(device) { - if (this.devicePaths[device.path] != undefined) { + if (this.devicePaths[device.path] !== undefined) { const obj = this.devicePaths[device.path]; let devicePath = (obj.predefined ? 'predefinedDevices.' : 'devices.'); devicePath += obj.index.toString(); @@ -487,7 +487,7 @@ * of the item which the target is contained in. */ copyDevice(event) { - const predefined = (event.target.dataset.predefined == 'true'); + const predefined = (event.target.dataset.predefined === 'true'); const index = event.model.index; const copyDevice = predefined ? this.predefinedDevices[index] : this.devices[index]; @@ -545,7 +545,7 @@ * @private */ deviceRemovedFromMainAdapter_(path) { - if (this.devicePaths[path] == undefined) { + if (this.devicePaths[path] === undefined) { return; } @@ -564,7 +564,7 @@ */ getTextForDeviceClass(classValue) { for (let i = 0; i < this.deviceClassOptions.length; ++i) { - if (this.deviceClassOptions[i].value == classValue) { + if (this.deviceClassOptions[i].value === classValue) { return this.deviceClassOptions[i].text; } } @@ -578,7 +578,7 @@ */ getValueForDeviceClass(classText) { for (let i = 0; i < this.deviceClassOptions.length; ++i) { - if (this.deviceClassOptions[i].text == classText) { + if (this.deviceClassOptions[i].text === classText) { return this.deviceClassOptions[i].value; } }
diff --git a/chrome/browser/resources/chromeos/enterprise_reporting/reporting_history.ts b/chrome/browser/resources/chromeos/enterprise_reporting/reporting_history.ts index 5a58713f..d244f3a 100644 --- a/chrome/browser/resources/chromeos/enterprise_reporting/reporting_history.ts +++ b/chrome/browser/resources/chromeos/enterprise_reporting/reporting_history.ts
@@ -82,7 +82,7 @@ onFilterChange() { const currentSelection: string = this.$.erpTableFilter.value; - if (this.selectedOption != currentSelection) { + if (this.selectedOption !== currentSelection) { this.selectedOption = currentSelection; this.updateErpTable(); } @@ -100,7 +100,7 @@ // For the erp-parameters column we need to extract the information from // the bullet lists, for all the other columns we just append the // innerHTML directly. - if (currentCol.className == 'erp-parameters') { + if (currentCol.className === 'erp-parameters') { currentCol.querySelectorAll('li').forEach(el => { value += el.innerText + ' - '; }); @@ -178,10 +178,10 @@ } // If there are events we filter them by the type of event. const filteredEvents = this.currentHistory.events.filter( - (event: ErpHistoryEvent) => event.call == this.selectedOption || - this.selectedOption == ReportingHistoryElement.allEvents || - (this.selectedOption == ReportingHistoryElement.allButUploads && - event.call != 'Upload')); + (event: ErpHistoryEvent) => event.call === this.selectedOption || + this.selectedOption === ReportingHistoryElement.allEvents || + (this.selectedOption === ReportingHistoryElement.allButUploads && + event.call !== 'Upload')); // If there are no events after filtering, present the placeholder. if (filteredEvents.length === 0) {
diff --git a/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.ts b/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.ts index 4bb35c4..11e49111 100644 --- a/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.ts +++ b/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.ts
@@ -283,7 +283,7 @@ // If the network was or is active, request an update. if (this.managedProperties_.connectionState != ConnectionStateType.kNotConnected || - networks.find(network => network.guid == this.guid)) { + networks.find(network => network.guid === this.guid)) { this.getNetworkDetails_(); } } @@ -293,7 +293,7 @@ if (!this.guid || !this.managedProperties_) { return; } - if (network.guid == this.guid) { + if (network.guid === this.guid) { this.getNetworkDetails_(); } } @@ -330,7 +330,7 @@ const type = this.managedProperties_.type; this.networkConfig_.getDeviceStateList().then(response => { const devices = response.result; - this.deviceState_ = devices.find(device => device.type == type) || null; + this.deviceState_ = devices.find(device => device.type === type) || null; if (!this.deviceState_) { // If the device type associated with the current network has been // removed (e.g., due to unplugging a Cellular dongle), the details @@ -432,7 +432,7 @@ } private isRemembered_(managedProperties: ManagedProperties): boolean { - return managedProperties.source != OncSource.kNone; + return managedProperties.source !== OncSource.kNone; } private isRememberedOrConnected_(managedProperties: ManagedProperties): @@ -443,7 +443,7 @@ private shouldShowApnList_(managedProperties: ManagedProperties): boolean { return !this.isApnRevampEnabled_ && - managedProperties.type == NetworkType.kCellular; + managedProperties.type === NetworkType.kCellular; } private shouldShowApnSection_(managedProperties: ManagedProperties): boolean { @@ -467,21 +467,21 @@ } private showCellularSim_(managedProperties: ManagedProperties): boolean { - return managedProperties.type == NetworkType.kCellular && - managedProperties.typeProperties.cellular!.family != 'CDMA'; + return managedProperties.type === NetworkType.kCellular && + managedProperties.typeProperties.cellular!.family !== 'CDMA'; } private showCellularChooseNetwork_(managedProperties: ManagedProperties): boolean { - return managedProperties.type == NetworkType.kCellular && + return managedProperties.type === NetworkType.kCellular && managedProperties.typeProperties.cellular!.supportNetworkScan; } private showForget_(managedProperties: ManagedProperties): boolean { - if (!managedProperties || managedProperties.type != NetworkType.kWiFi) { + if (!managedProperties || managedProperties.type !== NetworkType.kWiFi) { return false; } - return managedProperties.source != OncSource.kNone && + return managedProperties.source !== OncSource.kNone && !this.isPolicySource(managedProperties.source); } @@ -542,8 +542,8 @@ return false; } return managedProperties.connectable && - managedProperties.type != NetworkType.kEthernet && - managedProperties.connectionState == ConnectionStateType.kNotConnected; + managedProperties.type !== NetworkType.kEthernet && + managedProperties.connectionState === ConnectionStateType.kNotConnected; } private showDisconnect_(managedProperties: (ManagedProperties|undefined)): @@ -551,8 +551,8 @@ if (!managedProperties) { return false; } - return managedProperties.type != NetworkType.kEthernet && - managedProperties.connectionState != ConnectionStateType.kNotConnected; + return managedProperties.type !== NetworkType.kEthernet && + managedProperties.connectionState !== ConnectionStateType.kNotConnected; } private shouldShowProxyPolicyIndicator_(managedProperties: ManagedProperties): @@ -677,7 +677,7 @@ private getInfoFields_(): string[] { const fields: string[] = []; const type = this.managedProperties_.type; - if (type == NetworkType.kCellular) { + if (type === NetworkType.kCellular) { fields.push( 'cellular.activationState', 'cellular.servingOperator.name', 'cellular.networkTechnology'); @@ -685,10 +685,10 @@ if (OncMojo.isRestrictedConnectivity(this.managedProperties_.portalState)) { fields.push('portalState'); } - // Two separate checks for type == kCellular because the order of the array + // Two separate checks for type === kCellular because the order of the array // dictates the order the fields appear on the UI. We want portalState to // show after the earlier Cellular fields but before these later fields. - if (type == NetworkType.kCellular) { + if (type === NetworkType.kCellular) { fields.push( 'cellular.homeProvider.name', 'cellular.homeProvider.country', 'cellular.firmwareRevision', 'cellular.hardwareRevision',
diff --git a/chrome/browser/resources/chromeos/login/BUILD.gn b/chrome/browser/resources/chromeos/login/BUILD.gn index 2b7af9a..0df41f7 100644 --- a/chrome/browser/resources/chromeos/login/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/BUILD.gn
@@ -222,10 +222,6 @@ ] } -js_library("i18n_setup") { - deps = [ "//ash/webui/common/resources:load_time_data.m" ] -} - js_library("cr_ui") { sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/cr_ui.js" ] deps = [
diff --git a/chrome/browser/resources/chromeos/login/i18n_setup.js b/chrome/browser/resources/chromeos/login/i18n_setup.ts similarity index 99% rename from chrome/browser/resources/chromeos/login/i18n_setup.js rename to chrome/browser/resources/chromeos/login/i18n_setup.ts index 924310a4..df1a6e4 100644 --- a/chrome/browser/resources/chromeos/login/i18n_setup.js +++ b/chrome/browser/resources/chromeos/login/i18n_setup.ts
@@ -4,4 +4,4 @@ import './strings.m.js'; -export {loadTimeData} from '//resources/ash/common/load_time_data.m.js'; \ No newline at end of file +export {loadTimeData} from '//resources/ash/common/load_time_data.m.js';
diff --git a/chrome/browser/resources/chromeos/login/login.gni b/chrome/browser/resources/chromeos/login/login.gni index 82674ce..6601d0f 100644 --- a/chrome/browser/resources/chromeos/login/login.gni +++ b/chrome/browser/resources/chromeos/login/login.gni
@@ -19,15 +19,15 @@ "cr_ui.js", "display_manager.js", "install_oobe_error_store.js", - "i18n_setup.js", + "i18n_setup.ts", "lazy_load_screens.js", "login_ui_tools.js", "multi_tap_detector.js", "oobe.js", "oobe_trace.js", "oobe_trace_start.js", - "priority_screens_common_flow.js", - "priority_screens_oobe_flow.js", + "priority_screens_common_flow.ts", + "priority_screens_oobe_flow.ts", "screens.ts", ]
diff --git a/chrome/browser/resources/chromeos/login/priority_screens_common_flow.js b/chrome/browser/resources/chromeos/login/priority_screens_common_flow.js deleted file mode 100644 index ce278eb..0000000 --- a/chrome/browser/resources/chromeos/login/priority_screens_common_flow.js +++ /dev/null
@@ -1,8 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import './screens/common/user_creation.js'; - -export const priorityCommonScreenList = - [{tag: 'user-creation-element', id: 'user-creation'}];
diff --git a/chrome/browser/resources/chromeos/login/priority_screens_common_flow.ts b/chrome/browser/resources/chromeos/login/priority_screens_common_flow.ts new file mode 100644 index 0000000..5edfbe7 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/priority_screens_common_flow.ts
@@ -0,0 +1,17 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import './screens/common/user_creation.js'; + +//TODO(b/324392321) Move type definition to oobe_types after its TS migration +export interface OobeScreen { + tag: string; + id: string; + condition?: string; + extra_classes?: string[]; +} +export interface ScreensList extends Array<OobeScreen>{} + +export const priorityCommonScreenList: ScreensList = + [{tag: 'user-creation-element', id: 'user-creation'}];
diff --git a/chrome/browser/resources/chromeos/login/priority_screens_oobe_flow.js b/chrome/browser/resources/chromeos/login/priority_screens_oobe_flow.js deleted file mode 100644 index 934facb..0000000 --- a/chrome/browser/resources/chromeos/login/priority_screens_oobe_flow.js +++ /dev/null
@@ -1,9 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import './screens/oobe/welcome.js'; - -export const priorityOobeScreenList = [ - {tag: 'oobe-welcome-element', id: 'connect'}, -];
diff --git a/chrome/browser/resources/chromeos/login/priority_screens_oobe_flow.ts b/chrome/browser/resources/chromeos/login/priority_screens_oobe_flow.ts new file mode 100644 index 0000000..3007d16b --- /dev/null +++ b/chrome/browser/resources/chromeos/login/priority_screens_oobe_flow.ts
@@ -0,0 +1,18 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import './screens/oobe/welcome.js'; + +//TODO(b/324392321) Move type definition to oobe_types after its TS migration +export interface OobeScreen { + tag: string; + id: string; + condition?: string; + extra_classes?: string[]; +} +export interface ScreensList extends Array<OobeScreen>{} + +export const priorityOobeScreenList: ScreensList = [ + {tag: 'oobe-welcome-element', id: 'connect'}, +];
diff --git a/chrome/browser/resources/chromeos/login/screens.ts b/chrome/browser/resources/chromeos/login/screens.ts index fea28da0..64c280c0 100644 --- a/chrome/browser/resources/chromeos/login/screens.ts +++ b/chrome/browser/resources/chromeos/login/screens.ts
@@ -82,12 +82,14 @@ import './screens/oobe/packaged_license.js'; import './screens/oobe/update.js'; -export type ScreensList = Array<{ - tag: string, - id: string, - condition?: string, - extra_classes?: string[], -}>; +//TODO(b/324392321) Move type definition to oobe_types after its TS migration +export interface OobeScreen { + tag: string; + id: string; + condition?: string; + extra_classes?: string[]; +} +export interface ScreensList extends Array<OobeScreen>{} /** * List of screens that are used for both `oobe` and `login` flows.
diff --git a/chrome/browser/resources/chromeos/login/screens/common/user_creation.ts b/chrome/browser/resources/chromeos/login/screens/common/user_creation.ts index 216e97e..9811b678 100644 --- a/chrome/browser/resources/chromeos/login/screens/common/user_creation.ts +++ b/chrome/browser/resources/chromeos/login/screens/common/user_creation.ts
@@ -194,7 +194,6 @@ 'setIsBackButtonVisible', 'setTriageStep', 'setChildSetupStep', - 'setDefaultStep', ]; } @@ -209,6 +208,7 @@ onBeforeShow(): void { if (this.isOobeSoftwareUpdateEnabled_) { this.restoreOobeUIState(); + this.selectedUserType = ''; if (!loadTimeData.getBoolean('isOobeFlow')) { this.titleKey_ = 'userCreationAddPersonUpdatedTitle'; this.subtitleKey_ = 'userCreationAddPersonUpdatedSubtitle'; @@ -216,6 +216,8 @@ this.titleKey_ = 'userCreationUpdatedTitle'; this.subtitleKey_ = 'userCreationUpdatedSubtitle'; } + this.selectedEnrollTriageMethod = ''; + this.selectedChildSetupMethod = ''; return; } @@ -230,14 +232,6 @@ } } - setDefaultStep(): void { - Oobe.getInstance().setOobeUIState(OOBE_UI_STATE.USER_CREATION); - this.setUIStep(UserCreationUIState.CREATE); - this.selectedUserType = UserCreationUserType.SELF; - this.selectedEnrollTriageMethod = ''; - this.selectedChildSetupMethod = ''; - } - override ready(): void { super.ready(); this.initializeLoginScreen('UserCreationScreen');
diff --git a/chrome/browser/resources/chromeos/notification_tester/notification_tester.js b/chrome/browser/resources/chromeos/notification_tester/notification_tester.js index 4e47620..44da95d8 100644 --- a/chrome/browser/resources/chromeos/notification_tester/notification_tester.js +++ b/chrome/browser/resources/chromeos/notification_tester/notification_tester.js
@@ -252,9 +252,9 @@ // Show / hide dom elements when this.notifMetadata.notificationType changes notificationTypeChanged_(notificationType) { this.showMultiOptions = - (notificationType == NotificationType.NOTIFICATION_TYPE_MULTIPLE); + (notificationType === NotificationType.NOTIFICATION_TYPE_MULTIPLE); this.showProgressOptions = - (notificationType == NotificationType.NOTIFICATION_TYPE_PROGRESS); + (notificationType === NotificationType.NOTIFICATION_TYPE_PROGRESS); this.showTypeSpecificDesc = !(this.showMultiOptions || this.showProgressOptions); } @@ -263,9 +263,9 @@ // notifier as a string. notifierTypeChanged_(notifierType) { // notifierType is guaranteed to be 'System' or 'Web'. - this.isSystemNotification = notifierType == 'System'; - this.isWebNotification = notifierType == 'Web'; - if (notifierType == 'System') { + this.isSystemNotification = notifierType === 'System'; + this.isWebNotification = notifierType === 'Web'; + if (notifierType === 'System') { this.notifMetadata.notifierType = NotifierType.SYSTEM_COMPONENT; return; }
diff --git a/chrome/browser/resources/chromeos/notification_tester/select_custom.js b/chrome/browser/resources/chromeos/notification_tester/select_custom.js index fa46de5d..21cc321 100644 --- a/chrome/browser/resources/chromeos/notification_tester/select_custom.js +++ b/chrome/browser/resources/chromeos/notification_tester/select_custom.js
@@ -45,7 +45,7 @@ // <select> element. onSelectChange(event) { const customInput = this.shadowRoot.querySelector('.hidden-input'); - this.customSelected = event.target.value == 'custom'; + this.customSelected = event.target.value === 'custom'; customInput.hidden = !this.customSelected; this.formItemStyle = this.customSelected ? 'form-item-custom' : 'form-item'; if (this.customSelected) {
diff --git a/chrome/browser/resources/chromeos/parent_access/parent_access_ui.ts b/chrome/browser/resources/chromeos/parent_access/parent_access_ui.ts index 887deea..375550d4 100644 --- a/chrome/browser/resources/chromeos/parent_access/parent_access_ui.ts +++ b/chrome/browser/resources/chromeos/parent_access/parent_access_ui.ts
@@ -90,7 +90,7 @@ // Otherwise, all requests should be https and in the ALLOWED_HOSTS list. const requestIsHttps = requestUrl.protocol === 'https:'; const requestIsInAllowedHosts = ALLOWED_HOSTS.some( - (allowedHost) => requestUrl.host == allowedHost || + (allowedHost) => requestUrl.host === allowedHost || requestUrl.host.endsWith(allowedHost)); return requestIsHttps && requestIsInAllowedHosts; @@ -118,7 +118,7 @@ const eventOriginFilter = parsedWebviewUrl.origin; const oauthFetchResult = await this.parentAccessUiHandler.getOauthToken(); - if (oauthFetchResult.status != GetOauthTokenStatus.kSuccess) { + if (oauthFetchResult.status !== GetOauthTokenStatus.kSuccess) { throw new Error('OAuth token was not successfully fetched.'); }
diff --git a/chrome/browser/resources/commander/BUILD.gn b/chrome/browser/resources/commander/BUILD.gn deleted file mode 100644 index e83d64b..0000000 --- a/chrome/browser/resources/commander/BUILD.gn +++ /dev/null
@@ -1,28 +0,0 @@ -# Copyright 2020 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//ui/webui/resources/tools/build_webui.gni") - -build_webui("build") { - grd_prefix = "commander" - static_files = [ "commander.html" ] - web_component_files = [ - "app.ts", - "option.ts", - ] - non_web_component_files = [ - "browser_proxy.ts", - "types.ts", - ] - - icons_html_files = [ "icons.html" ] - - ts_composite = true - ts_definitions = [ "//tools/typescript/definitions/chrome_send.d.ts" ] - ts_deps = [ - "//third_party/polymer/v3_0:library", - "//ui/webui/resources/cr_elements:build_ts", - "//ui/webui/resources/js:build_ts", - ] -}
diff --git a/chrome/browser/resources/commander/OWNERS b/chrome/browser/resources/commander/OWNERS deleted file mode 100644 index d7b99b6..0000000 --- a/chrome/browser/resources/commander/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -file://chrome/browser/ui/commander/OWNERS
diff --git a/chrome/browser/resources/commander/app.html b/chrome/browser/resources/commander/app.html deleted file mode 100644 index fd65186..0000000 --- a/chrome/browser/resources/commander/app.html +++ /dev/null
@@ -1,108 +0,0 @@ -<style> - :host { - background-color: #fff; - font-size: 13px; - overflow: hidden; - } - - input { - background-color: transparent; - border: 0; - box-sizing: border-box; - height: 100%; - margin:0; - padding: 1em 1em 1em 0; - width: 100%; - } - - input:focus { - outline: none; - } - - #inputRow { - align-items: center; - box-sizing: border-box; - display: flex; - height: 48px; - width: 100%; - } - - #noResults { - border-top: 1px solid var(--google-grey-300); - box-sizing: border-box; - font-weight: bold; - height: 48px; - padding: 1em; - width: 100%; - } - - .chip { - background-color: var(--google-blue-50); - border-radius: 100px; - box-sizing: border-box; - color: var(--google-blue-700); - display: inline-block; - height: 32px; - margin-inline-start: 12px; - padding: 8px; - text-align: center; - white-space: nowrap; - } - - commander-option:first-child { - border-top: 1px solid var(--google-grey-300); - } - - ::-webkit-scrollbar { - display: none; - } - - iron-icon { - margin-inline-start: 1em; - margin-top: 0.5em; - --iron-icon-fill-color: var(--google-grey-600); - } - - @media (prefers-color-scheme: dark) { - :host { - background-color: var(--google-grey-900); - color: #fff; - } - - .chip { - background-color: var(--google-blue-700); - color: var(--google-blue-50); - } - - input::placeholder { - color: var(--google-grey-500); - } - - iron-icon { - --iron-icon-fill-color: var(--google-grey-500); - } - } -</style> -<div id="inputRow" aria-owns="options" - aria-expanded="[[computeExpanded_(options_)]]" role="combobox" > - <iron-icon icon="commander-icons:chrome"></iron-icon> - <template is="dom-if" if="[[computeShowChip_(promptText_)]]"> - <div class="chip">[[promptText_]]</div> - </template> - <input id="input" type="text" on-input="onInput_" - on-keydown="onKeydown_" aria-autocomplete="list" aria-controls="options" - placeholder="$i18n{placeholder}"></input> -</div> -<div id="options" role="listbox"> -<template is="dom-repeat" on-dom-change="onDomChange_" items="[[options_]]"> - <commander-option - aria-selected="[[computeAriaSelected_(index, focusedIndex_)]]" - role="option" id="[[getOptionId_(index)]]" - class$="[[getOptionClass_(index, focusedIndex_)]]" - model="[[item]]" on-click="onOptionClick_"></commander-option> -</template> -<template is="dom-if" if="[[showNoResults_]]" - on-dom-change="onDomChange_"> - <div id="noResults">$i18n{noResults}</div> -</template> -</div>
diff --git a/chrome/browser/resources/commander/app.ts b/chrome/browser/resources/commander/app.ts deleted file mode 100644 index 9e1ce30..0000000 --- a/chrome/browser/resources/commander/app.ts +++ /dev/null
@@ -1,202 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -import './icons.html.js'; -import './option.js'; -import 'chrome://resources/cr_elements/icons.html.js'; -import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; -import 'chrome://resources/cr_elements/cr_shared_vars.css.js'; - -import {addWebUiListener} from 'chrome://resources/js/cr.js'; -import type {DomRepeatEvent} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {Debouncer, enqueueDebouncer, microTask, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -import {getTemplate} from './app.html.js'; -import type {BrowserProxy} from './browser_proxy.js'; -import {BrowserProxyImpl} from './browser_proxy.js'; -import type {Option, ViewModel} from './types.js'; -import {Action} from './types.js'; - -export interface CommanderAppElement { - $: { - input: HTMLInputElement, - inputRow: HTMLElement, - }; -} - - -export class CommanderAppElement extends PolymerElement { - static get is() { - return 'commander-app'; - } - - static get template() { - return getTemplate(); - } - - static get properties() { - return { - options_: Array, - focusedIndex_: { - type: Number, - notify: true, - observer: 'onFocusedIndexChanged_', - }, - promptText_: String, - resultSetId_: Number, - }; - } - - private options_: Option[]; - private focusedIndex_: number; - private promptText_: string|null; - private browserProxy_: BrowserProxy; - private resultSetId_: number|null; - private savedInput_: string; - private showNoResults_: boolean; - private debouncer_: Debouncer|null; - - constructor() { - super(); - this.browserProxy_ = BrowserProxyImpl.getInstance(); - } - - override ready() { - super.ready(); - addWebUiListener('view-model-updated', this.onViewModelUpdated_.bind(this)); - addWebUiListener('initialize', this.initialize_.bind(this)); - this.initialize_(); - } - - /** - * Resets the UI for a new session. - */ - private initialize_() { - this.options_ = []; - this.$.input.value = ''; - this.$.input.focus(); - this.focusedIndex_ = -1; - this.resultSetId_ = null; - this.promptText_ = null; - this.savedInput_ = ''; - this.showNoResults_ = false; - } - - private onKeydown_(e: KeyboardEvent) { - if (e.key === 'Escape') { - this.browserProxy_.dismiss(); - return; - } - if (e.key === 'ArrowUp') { - e.preventDefault(); - this.focusedIndex_ = (this.focusedIndex_ + this.options_.length - 1) % - this.options_.length; - } else if (e.key === 'ArrowDown') { - e.preventDefault(); - this.focusedIndex_ = (this.focusedIndex_ + 1) % this.options_.length; - } else if (e.key === 'Enter') { - if (this.focusedIndex_ >= 0 && - this.focusedIndex_ < this.options_.length) { - this.notifySelectedAtIndex_(this.focusedIndex_); - } - } else if ( - this.promptText_ && e.key === 'Backspace' && - this.$.input.value === '') { - this.browserProxy_.promptCancelled(); - this.promptText_ = null; - this.$.input.value = this.savedInput_; - e.preventDefault(); - this.onInput_(); - } - } - - private onInput_() { - this.browserProxy_.textChanged(this.$.input.value); - } - - private onViewModelUpdated_(viewModel: ViewModel) { - if (viewModel.action === Action.DISPLAY_RESULTS) { - this.options_ = viewModel.options || []; - this.resultSetId_ = viewModel.resultSetId; - this.showNoResults_ = this.resultSetId_ != null && - this.$.input.value !== '' && this.options_.length === 0; - if (this.options_.length > 0) { - this.focusedIndex_ = 0; - } - } else if (viewModel.action === Action.PROMPT) { - this.showNoResults_ = false; - this.options_ = []; - this.resultSetId_ = viewModel.resultSetId; - this.promptText_ = viewModel.promptText || null; - this.savedInput_ = this.$.input.value; - this.$.input.value = ''; - this.onInput_(); - } - } - - private onDomChange_() { - this.debouncer_ = Debouncer.debounce(this.debouncer_, microTask, () => { - this.browserProxy_.heightChanged(document.body.offsetHeight); - }); - enqueueDebouncer(this.debouncer_); - } - - /** - * Called when a result option is clicked via mouse. - */ - private onOptionClick_(e: DomRepeatEvent<Option>) { - this.notifySelectedAtIndex_(e.model.index); - } - - /** - * Used to set `aria-activedescendant` when the focused option changes. - */ - private onFocusedIndexChanged_() { - if (this.focusedIndex_ === -1) { - this.$.inputRow.removeAttribute('aria-activedescendant'); - } else { - this.$.inputRow.setAttribute( - 'aria-activedescendant', this.getOptionId_(this.focusedIndex_)); - } - } - - /** - * Informs the browser that the option at |index| was selected. - */ - private notifySelectedAtIndex_(index: number) { - if (this.resultSetId_ !== null) { - this.browserProxy_.optionSelected(index, this.resultSetId_); - } - } - - private getOptionClass_(index: number): string { - return index === this.focusedIndex_ ? 'focused' : ''; - } - - /** - * An id is required for aria-activedescendant - */ - private getOptionId_(index: number): string { - return 'option-' + index; - } - - private computeShowChip_(): boolean { - return this.promptText_ !== null; - } - - private computeExpanded_(): string { - return this.options_.length > 0 ? 'true' : 'false'; - } - - private computeAriaSelected_(index: number): string { - return index === this.focusedIndex_ ? 'true' : 'false'; - } -} - -declare global { - interface HTMLElementTagNameMap { - 'commander-app': CommanderAppElement; - } -} - -customElements.define(CommanderAppElement.is, CommanderAppElement);
diff --git a/chrome/browser/resources/commander/browser_proxy.ts b/chrome/browser/resources/commander/browser_proxy.ts deleted file mode 100644 index 155cbf2..0000000 --- a/chrome/browser/resources/commander/browser_proxy.ts +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -export interface BrowserProxy { - textChanged(newText: string): void; - optionSelected(index: number, resultSetId: number): void; - heightChanged(newHeight: number): void; - dismiss(): void; - promptCancelled(): void; -} - -export class BrowserProxyImpl implements BrowserProxy { - /** - * Notifies the backend that user input has changed. - * @param newText The current contents of the user input field. - */ - textChanged(newText: string) { - chrome.send('textChanged', [newText]); - } - - /** - * Notifies the backend that the option at |index| in result set - * |resultSetId| was selected. - * @param index The index of the selected option. - * @param resultSetId The result set this option was presented in. - */ - optionSelected(index: number, resultSetId: number) { - chrome.send('optionSelected', [index, resultSetId]); - } - - /** - * Notifies the views layer that the inherent height of the UI has changed - * so that the window can grow or shrink. - * @param newHeight The current height of the element. - */ - heightChanged(newHeight: number) { - chrome.send('heightChanged', [newHeight]); - } - - /** - * Notifies the backend that the user wants to dismiss the UI. - */ - dismiss() { - chrome.send('dismiss'); - } - - /** - * Notifies the backend that the user has cancelled entering a composite - * command. - */ - promptCancelled() { - chrome.send('compositeCommandCancelled'); - } - - static getInstance(): BrowserProxy { - return instance || (instance = new BrowserProxyImpl()); - } - - static setInstance(obj: BrowserProxy) { - instance = obj; - } -} - -let instance: BrowserProxy|null = null;
diff --git a/chrome/browser/resources/commander/commander.html b/chrome/browser/resources/commander/commander.html deleted file mode 100644 index fc74fe780..0000000 --- a/chrome/browser/resources/commander/commander.html +++ /dev/null
@@ -1,18 +0,0 @@ -<!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}"> -<head> - <meta charset="utf-8"> - <meta name="color-scheme" content="light dark"> - <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> - <style> - body { - margin: 0; - } - </style> - <title>$i18n{pageTitle}</title> -</head> -<body> - <commander-app></commander-app> - <script type="module" src="app.js"></script> -</body> -</html>
diff --git a/chrome/browser/resources/commander/icons.html b/chrome/browser/resources/commander/icons.html deleted file mode 100644 index 1ae21db..0000000 --- a/chrome/browser/resources/commander/icons.html +++ /dev/null
@@ -1,7 +0,0 @@ -<iron-iconset-svg name="commander-icons" size="24"> - <svg> - <defs> - <g id="chrome"><path d="M11.3532,5a4.4966,4.4966,0,0,1,.5434,5.25l.0005,0L8.5912,15.9759A7.9982,7.9982,0,0,0,15.4163,5Z"></path><path d="M3.7249,6.5952A4.501,4.501,0,0,1,8,3.5h6.6144A7.9976,7.9976,0,0,0,1.6949,3.0792Z"></path><path d="M8.9206,12.4054A4.503,4.503,0,0,1,4.1034,10.25l0,0L.7948,4.52A8.0022,8.0022,0,0,0,6.8905,15.9217Z"></path><circle cx="8" cy="8" r="3"></circle></g> - </defs> - </svg> -</iron-iconset-svg>
diff --git a/chrome/browser/resources/commander/option.html b/chrome/browser/resources/commander/option.html deleted file mode 100644 index 1b293a5..0000000 --- a/chrome/browser/resources/commander/option.html +++ /dev/null
@@ -1,90 +0,0 @@ -<style> - :host { - align-items: center; - box-sizing: border-box; - color: var(--google-grey-900); - cursor: default; - display: flex; - height: 48px; - padding: 1em; - width: 100%; - } - - - :host(:hover) { - background-color: var(--google-grey-200); - } - - :host(.focused) { - background-color: var(--google-grey-200); - } - - :host(.focused) #focus-indicator { - display: block; - } - - .annotation { - color: var(--google-grey-700); - margin-inline-start: auto; - } - - .title { - overflow: hidden; - text-overflow: ellipsis; - } - - .title-piece { - white-space: pre; - } - - .match { - font-weight: 600; - } - - #focus-indicator { - background-color: var(--google-blue-600); - border-radius: 3px; - display: none; - height: 48px; - margin-inline-start: -16px; /*-1 * (host padding + width / 2)*/ - position: absolute; - width: 6px; - } - - @media (prefers-color-scheme: dark) { - :host { - color: #fff; - } - :host(:hover) { - /* Google Grey 911 according to the mock. */ - background-color: rgb(53, 54, 58); - } - - :host(.focused) { - background-color: rgba(var(--google-grey-900-rgb), 6%); - } - - .annotation { - color: var(--google-grey-500); - } - - iron-icon { - --iron-icon-fill-color: var(--google-grey-500); - } - - #focus-indicator { - background-color: var(--google-blue-300); - } - - } -</style> -<div id="focus-indicator"></div> -<span class="title"> -<template is="dom-repeat" - items="[[computeMatchSpans_(model.title, model.matchedRanges)]]" - as="span"> - <span class$="title-piece - [[getClassForMatch_(span.isMatch)]]">[[span.text]]</span> -</template> -</span> -<span class="annotation">[[model.annotation]]</span>
diff --git a/chrome/browser/resources/commander/option.ts b/chrome/browser/resources/commander/option.ts deleted file mode 100644 index 65fc036..0000000 --- a/chrome/browser/resources/commander/option.ts +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -import './icons.html.js'; -import 'chrome://resources/cr_elements/cr_shared_vars.css.js'; - -import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -import {getTemplate} from './option.html.js'; -import type {Option} from './types.js'; - -/** - * Represents a substring of the option title, annotated with whether it's part - * of a match or not. - */ -export interface MatchSpan { - text: string; - isMatch: boolean; -} - -export class CommanderOptionElement extends PolymerElement { - static get is() { - return 'commander-option'; - } - - static get template() { - return getTemplate(); - } - - static get properties() { - return { - model: Object, - }; - } - - model: Option; - - /** - * Splits this.model.title into a list of substrings, each marked with - * whether they should be displayed as a match or not. - */ - private computeMatchSpans_(): MatchSpan[] { - const result: MatchSpan[] = []; - let firstNonmatch = 0; - for (const r of this.model.matchedRanges) { - const [start, end] = r; - if (start !== 0) { - result.push({ - text: this.model.title.substring(firstNonmatch, start), - isMatch: false, - }); - } - result.push( - {text: this.model.title.substring(start, end), isMatch: true}); - firstNonmatch = end; - } - if (firstNonmatch < this.model.title.length) { - result.push( - {text: this.model.title.substring(firstNonmatch), isMatch: false}); - } - return result; - } - - private getClassForMatch_(isMatch: boolean): string { - return isMatch ? 'match' : ''; - } -} - -declare global { - interface HTMLElementTagNameMap { - 'commander-option': CommanderOptionElement; - } -} - -customElements.define(CommanderOptionElement.is, CommanderOptionElement);
diff --git a/chrome/browser/resources/commander/types.ts b/chrome/browser/resources/commander/types.ts deleted file mode 100644 index 70c4530c..0000000 --- a/chrome/browser/resources/commander/types.ts +++ /dev/null
@@ -1,50 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -/** - * The type of entity a given command represents. Must stay in sync with - * commander::CommandItem::Entity. - */ -export enum Entity { - COMMAND = 0, - BOOKMARK = 1, - TAB = 2, - WINDOW = 3, - GROUP = 4, -} - -/** - * The action that should be taken when the view model is received by the view. - * Must stay in sync with commander::CommanderViewModel::Action. "CLOSE" is - * included for completeness, but should be handled before the view model - * reaches the WebUI layer. - */ -export enum Action { - DISPLAY_RESULTS = 0, - CLOSE = 1, - PROMPT = 2, -} - -// TODO(lgrey): Convert Option and ViewModel from class to type when tests -// are in TypeScript. -/** - * View model for a result option. - * Corresponds to commander::CommandItemViewModel. - */ -export class Option { - title: string; - annotation?: string; - entity: Entity; - matchedRanges: number[][]; -} - -/** - * View model for a result set. - * Corresponds to commander::CommanderViewModel. - */ -export class ViewModel { - action: Action; - resultSetId: number; - options?: Option[]; - promptText?: string; -}
diff --git a/chrome/browser/resources/new_tab_page/modules/v2/tab_resumption/module.html b/chrome/browser/resources/new_tab_page/modules/v2/tab_resumption/module.html index 3511ed4..9e4543b 100644 --- a/chrome/browser/resources/new_tab_page/modules/v2/tab_resumption/module.html +++ b/chrome/browser/resources/new_tab_page/modules/v2/tab_resumption/module.html
@@ -125,6 +125,7 @@ 'modulesMoreActions', 'modulesDriveSentence')]]" on-disable-button-click="onDisableButtonClick_" + on-dismiss-button-click="onDismissButtonClick_" on-info-button-click="onInfoButtonClick_" on-menu-button-click="onMenuButtonClick_"> </ntp-module-header-v2>
diff --git a/chrome/browser/resources/new_tab_page/modules/v2/tab_resumption/module.ts b/chrome/browser/resources/new_tab_page/modules/v2/tab_resumption/module.ts index c3e5584..66b53ae 100644 --- a/chrome/browser/resources/new_tab_page/modules/v2/tab_resumption/module.ts +++ b/chrome/browser/resources/new_tab_page/modules/v2/tab_resumption/module.ts
@@ -53,6 +53,11 @@ return [ [ { + action: 'dismiss', + icon: 'modules:thumb_down', + text: this.i18n('modulesTabResumptionDismissButton'), + }, + { action: 'disable', icon: 'modules:block', text: this.i18nRecursive( @@ -109,6 +114,22 @@ }, Number(e.model.item.relativeTime.microseconds / 1000n)); } + + private onDismissButtonClick_() { + const urls = this.tabs.map((tab: Tab) => tab.url); + TabResumptionProxyImpl.getInstance().handler.dismissModule(urls); + this.dispatchEvent(new CustomEvent('dismiss-module-instance', { + bubbles: true, + composed: true, + detail: { + message: loadTimeData.getStringF( + 'dismissModuleToastMessage', + loadTimeData.getString('modulesTabResumptionSentence')), + restoreCallback: () => + TabResumptionProxyImpl.getInstance().handler.restoreModule(), + }, + })); + } } customElements.define(
diff --git a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html index 2fa3a88..56d9e5a54 100644 --- a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html +++ b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html
@@ -130,7 +130,8 @@ <div id="destinationDropdown" on-keydown="onKeyDown_" tabindex="0" on-blur="onBlur_" on-click="onClick_" role="button" aria-haspopup="true" aria-label="$i18n{destinationLabel} [[value.displayName]]" - aria-description$="[[getAriaDescription_(destinationStatusText)]]"> + aria-description$="[[getAriaDescription_(destinationStatusText)]]" + aria-expanded="[[opened_]]" aria-setsize$="[[dropdownLength_]]"> <div id="destination-display-container"> <div id="destination-icon-box"> <iron-icon icon="[[destinationIcon]]"></iron-icon> @@ -152,7 +153,8 @@ class$="list-item [[getHighlightedClass_(item.key, highlightedIndex_)]]" aria-description$="[[getPrinterStatusErrorString_( - item.printerStatusReason)]]"> + item.printerStatusReason)]]" + aria-posinset$="[[getPrinterPosinset_(index)]]"> <iron-icon icon="[[getPrinterStatusIcon_( item.printerStatusReason, item.isEnterprisePrinter, isDarkModeActive_)]]"> @@ -163,6 +165,7 @@ <button on-click="onSelect_" tabindex="-1" value="[[pdfDestinationKey]]" hidden$="[[pdfPrinterDisabled]]" on-blur="onBlur_" role="menuitem" aria-setsize$="[[dropdownLength_]]" + aria-posinset$="[[pdfPosinset]]" class$="list-item [[getHighlightedClass_(pdfDestinationKey, highlightedIndex_)]]"> $i18n{printToPDF} @@ -170,19 +173,21 @@ <button on-click="onSelect_" tabindex="-1" on-blur="onBlur_" value="[[driveDestinationKey]]" hidden$="[[!driveDestinationKey]]" role="menuitem" aria-setsize$="[[dropdownLength_]]" + aria-posinset$="[[drivePosinset]]" class$="list-item [[getHighlightedClass_(driveDestinationKey, highlightedIndex_)]]"> $i18n{printToGoogleDrive} </button> <button on-click="onSelect_" tabindex="-1" value="noDestinations" hidden$="[[!noDestinations]]" on-blur="onBlur_" role="menuitem" - aria-setsize$="[[dropdownLength_]]" + aria-setsize$="[[dropdownLength_]]" aria-posinset$="1" class$="list-item [[getHighlightedClass_('noDestinations', highlightedIndex_)]]"> $i18n{noDestinationsMessage} </button> <button on-click="onSelect_" tabindex="-1" value="seeMore" aria-label="$i18n{seeMoreDestinationsLabel}" on-blur="onBlur_" + aria-posinset$="[[seeMorePosinset]]" role="menuitem" aria-setsize$="[[dropdownLength_]]" class$="list-item [[getHighlightedClass_('seeMore', highlightedIndex_)]]">
diff --git a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.ts b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.ts index 02f6bdf6..ecc4585 100644 --- a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.ts +++ b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.ts
@@ -85,9 +85,21 @@ }, destinationStatusText: String, + + pdfPosinset: Number, + + drivePosinset: Number, + + seeMorePosinset: Number, }; } + static get observers() { + return [ + 'updateAriaPosinset(itemList, pdfPrinterDisabled, driveDestinationKey)', + ]; + } + value: Destination; itemList: Destination[]; destinationIcon: string; @@ -100,6 +112,9 @@ private isDarkModeActive_: boolean; private highlightedIndex_: number; private dropdownLength_: number; + private pdfPosinset: number; + private drivePosinset: number; + private seeMorePosinset: number; private opened_: boolean = false; private dropdownRefitPending_: boolean = false; @@ -350,6 +365,24 @@ return getPrinterStatusIcon( printerStatusReason, isEnterprisePrinter, this.isDarkModeActive_); } + + private getPrinterPosinset_(index: number): number { + return index + 1; + } + + /** + * Set the ARIA position in the dropdown based on the visible items. + */ + private updateAriaPosinset(): void { + let currentPosition = this.itemList ? this.itemList.length + 1 : 1; + if (!this.pdfPrinterDisabled) { + this.pdfPosinset = currentPosition++; + } + if (this.driveDestinationKey) { + this.drivePosinset = currentPosition++; + } + this.seeMorePosinset = currentPosition++; + } } declare global {
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.html b/chrome/browser/resources/settings/basic_page/basic_page.html index 206d0ec..73e48012 100644 --- a/chrome/browser/resources/settings/basic_page/basic_page.html +++ b/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -77,7 +77,7 @@ </settings-section> </template> <template is="dom-if" - if="[[showPerformancePage_(pageVisibility.performance)]]" + if="[[showPage_(pageVisibility.performance)]]" restamp> <settings-section page-title="$i18n{memoryPageTitle}" <if expr="_google_chrome"> @@ -88,10 +88,6 @@ <settings-performance-page prefs="{{prefs}}"> </settings-performance-page> </settings-section> - </template> - <template is="dom-if" - if="[[showBatteryPage_(pageVisibility.performance)]]" - restamp> <settings-section page-title="$i18n{batteryPageTitle}" section="battery" nest-under-section="performance" <if expr="_google_chrome"> @@ -102,10 +98,6 @@ <settings-battery-page prefs="{{prefs}}"> </settings-battery-page> </settings-section> - </template> - <template is="dom-if" - if="[[showSpeedPage_(pageVisibility.performance)]]" - restamp> <settings-section page-title="$i18n{speedPageTitle}" section="speed" nest-under-section="performance" <if expr="_google_chrome">
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.ts b/chrome/browser/resources/settings/basic_page/basic_page.ts index 0b10f913..915b0c44 100644 --- a/chrome/browser/resources/settings/basic_page/basic_page.ts +++ b/chrome/browser/resources/settings/basic_page/basic_page.ts
@@ -337,18 +337,6 @@ return this.showPage_(visibility); } - private showPerformancePage_(visibility?: boolean): boolean { - return this.showPage_(visibility); - } - - private showBatteryPage_(visibility?: boolean): boolean { - return this.showPage_(visibility); - } - - private showSpeedPage_(visibility?: boolean): boolean { - return this.showPage_(visibility); - } - private showSafetyCheckPage_(visibility?: boolean): boolean { return !loadTimeData.getBoolean('enableSafetyHub') && this.showPage_(visibility);
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.html b/chrome/browser/resources/settings/languages_page/languages_page.html index 4dce4495..914a31ee 100644 --- a/chrome/browser/resources/settings/languages_page/languages_page.html +++ b/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -25,6 +25,11 @@ display: none; } + #languagesSectionHeader { + padding-bottom: 12px; + padding-top: 12px; + } + <if expr="is_win"> .explain-selected { color: var(--google-green-700); @@ -57,9 +62,10 @@ </style> <div id="languagesSection"> <div class="cr-row continuation"> - <h2 class="flex"> - $i18n{preferredLanguagesDesc} - </h2> + <div id="languagesSectionHeader" class="flex"> + <div>$i18n{preferredLanguagesHeader}</div> + <div class="secondary">$i18n{preferredLanguagesDesc}</div> + </div> <cr-button id="addLanguages" class="header-aligned-button" disabled="[[!canEnableSomeSupportedLanguage_(languages)]]" on-click="onAddLanguagesClick_">
diff --git a/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.html b/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.html index 2d0e3ca..d86a830 100644 --- a/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.html +++ b/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.html
@@ -4,14 +4,14 @@ margin-bottom: var(--cr-section-vertical-padding); } </style> - <template is="dom-if" if="[[!is3pcdRedesignEnabled_]]"> + <template is="dom-if" if="[[!isCookiesUiV2_]]"> <settings-toggle-button id="toggle" class="hr" label="$i18n{doNotTrack}" pref="{{prefs.enable_do_not_track}}" on-settings-boolean-control-change="onToggleChange_" no-set-pref> </settings-toggle-button> </template> - <template is="dom-if" if="[[is3pcdRedesignEnabled_]]"> + <template is="dom-if" if="[[isCookiesUiV2_]]"> <settings-toggle-button id="toggle" class="toggle" label="$i18n{doNotTrack}" pref="{{prefs.enable_do_not_track}}"
diff --git a/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.ts b/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.ts index 720b2f45..1325774 100644 --- a/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.ts +++ b/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.ts
@@ -46,17 +46,18 @@ value: false, }, - is3pcdRedesignEnabled_: { + isCookiesUiV2_: { type: Boolean, value: () => - loadTimeData.getBoolean('is3pcdCookieSettingsRedesignEnabled'), + (loadTimeData.getBoolean('isCookieSettingsUiAlignmentEnabled') || + loadTimeData.getBoolean('is3pcdCookieSettingsRedesignEnabled')), }, }; } prefs: {enable_do_not_track: chrome.settingsPrivate.PrefObject}; private showDialog_: boolean; - private is3pcdRedesignEnabled_: boolean; + private isCookiesUiV2_: boolean; private onDomChange_() { if (this.showDialog_) {
diff --git a/chrome/browser/resources/side_panel/read_anything/voice_selection_menu.ts b/chrome/browser/resources/side_panel/read_anything/voice_selection_menu.ts index 60aab41..ab09ec4 100644 --- a/chrome/browser/resources/side_panel/read_anything/voice_selection_menu.ts +++ b/chrome/browser/resources/side_panel/read_anything/voice_selection_menu.ts
@@ -37,6 +37,7 @@ // If Read Aloud is in the paused state. This is set from the parent element // via one way data binding. private readonly paused: boolean; + private readonly availableVoices: SpeechSynthesisVoice[]; private voicePlayingWhenMenuOpened_: boolean = false;
diff --git a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc index 8a6c6e55..f005cd7 100644 --- a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc +++ b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc
@@ -89,7 +89,8 @@ return false; } -bool ChromeEnterpriseRealTimeUrlLookupService::CanCheckSubresourceURL() const { +bool ChromeEnterpriseRealTimeUrlLookupService:: + CanIncludeSubframeUrlInReferrerChain() const { return false; } @@ -107,27 +108,22 @@ void ChromeEnterpriseRealTimeUrlLookupService::GetAccessToken( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner) { token_fetcher_->Start(base::BindOnce( &ChromeEnterpriseRealTimeUrlLookupService::OnGetAccessToken, - weak_factory_.GetWeakPtr(), url, last_committed_url, is_mainframe, - std::move(response_callback), std::move(callback_task_runner), - base::TimeTicks::Now())); + weak_factory_.GetWeakPtr(), url, std::move(response_callback), + std::move(callback_task_runner), base::TimeTicks::Now())); } void ChromeEnterpriseRealTimeUrlLookupService::OnGetAccessToken( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, base::TimeTicks get_token_start_time, const std::string& access_token) { - SendRequest(url, last_committed_url, is_mainframe, access_token, - std::move(response_callback), std::move(callback_task_runner), + SendRequest(url, access_token, std::move(response_callback), + std::move(callback_task_runner), /* is_sampled_report */ false); }
diff --git a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h index 1d520e5b..12752c6 100644 --- a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h +++ b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h
@@ -55,7 +55,7 @@ // RealTimeUrlLookupServiceBase: bool CanPerformFullURLLookup() const override; - bool CanCheckSubresourceURL() const override; + bool CanIncludeSubframeUrlInReferrerChain() const override; bool CanCheckSafeBrowsingDb() const override; bool CanCheckSafeBrowsingHighConfidenceAllowlist() const override; bool CanSendRTSampleRequest() const override; @@ -71,16 +71,12 @@ bool CanSendPageLoadToken() const override; void GetAccessToken( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override; // Called when the access token is obtained from |token_fetcher_|. void OnGetAccessToken( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, base::TimeTicks get_token_start_time,
diff --git a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_unittest.cc b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_unittest.cc index f6644ac9..12dde47 100644 --- a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_unittest.cc +++ b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_unittest.cc
@@ -225,8 +225,6 @@ std::unique_ptr<TestingProfile> test_profile_; syncer::TestSyncService test_sync_service_; std::unique_ptr<MockReferrerChainProvider> referrer_chain_provider_; - GURL last_committed_url_ = GURL("http://lastcommitted.test"); - bool is_mainframe_ = true; }; TEST_F(ChromeEnterpriseRealTimeUrlLookupServiceTest, @@ -241,8 +239,7 @@ base::MockCallback<network::TestURLLoaderFactory::Interceptor> request_callback; base::MockCallback<RTLookupResponseCallback> response_callback; - enterprise_rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + enterprise_rt_service()->StartLookup(url, response_callback.Get(), content::GetIOThreadTaskRunner({})); test_url_loader_factory_.SetInterceptor(request_callback.Get()); @@ -268,8 +265,7 @@ Return(ReferrerChainProvider::SUCCESS))); base::MockCallback<RTLookupResponseCallback> response_callback; - enterprise_rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + enterprise_rt_service()->StartLookup(url, response_callback.Get(), content::GetIOThreadTaskRunner({})); EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ true,
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc index 179f345..5cc50c3 100644 --- a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc +++ b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include <utility> +#include "base/command_line.h" #include "base/functional/bind.h" #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" @@ -65,8 +66,8 @@ #if BUILDFLAG(IS_ANDROID) #include "chrome/browser/password_manager/android/mock_password_checkup_launcher_helper.h" -#include "chrome/browser/password_manager/android/password_manager_android_util.h" #include "chrome/browser/sync/sync_service_factory.h" +#include "chrome/common/chrome_switches.h" #include "components/sync/test/test_sync_service.h" #endif @@ -1603,16 +1604,21 @@ class ChromePasswordProtectionServiceWithAccountPasswordStoreTest : public ChromePasswordProtectionServiceTest { public: - ChromePasswordProtectionServiceWithAccountPasswordStoreTest() = default; + ChromePasswordProtectionServiceWithAccountPasswordStoreTest() { +#if BUILDFLAG(IS_ANDROID) + // Using the account store on Android requires enabling the flag for UPM + // support of local passwords. Skip the Gms version check, otherwise the + // flag won't do anything in bots that have outdated GmsCore. + feature_list_.InitAndEnableFeature( + password_manager::features:: + kUnifiedPasswordManagerLocalPasswordsAndroidNoMigration); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kSkipLocalUpmGmsCoreVersionCheckForTesting); +#endif + } private: -#if BUILDFLAG(IS_ANDROID) - // Using the account store on Android also requires UPM support for local - // passwords. - base::test::ScopedFeatureList feature_list_{ - password_manager::features:: - kUnifiedPasswordManagerLocalPasswordsAndroidNoMigration}; -#endif + base::test::ScopedFeatureList feature_list_; }; TEST_F(ChromePasswordProtectionServiceWithAccountPasswordStoreTest, @@ -1689,9 +1695,14 @@ : public PasswordCheckupWithPhishGuardTest { public: void SetUp() override { + // Splitting the stores requires enabling the flag for UPM support of local + // passwords. Skip the Gms version check, otherwise the flag won't do + // anything in bots that have outdated GmsCore. feature_list_.InitAndEnableFeature( password_manager::features:: kUnifiedPasswordManagerLocalPasswordsAndroidNoMigration); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kSkipLocalUpmGmsCoreVersionCheckForTesting); PasswordCheckupWithPhishGuardTest::SetUp(); } };
diff --git a/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.cc b/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.cc index f45c339..8e86aac 100644 --- a/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.cc +++ b/chrome/browser/safe_browsing/telemetry/android/android_telemetry_service.cc
@@ -92,15 +92,15 @@ coordinator->RemoveObserver(this); } -void AndroidTelemetryService::OnDownloadCreated( - download::DownloadItem* item) { +void AndroidTelemetryService::OnDownloadCreated(download::DownloadItem* item) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); download::SimpleDownloadManagerCoordinator* coordinator = SimpleDownloadManagerCoordinatorFactory::GetForKey( profile_->GetProfileKey()); - if (!coordinator->has_all_history_downloads()) + if (!coordinator->has_all_history_downloads()) { return; + } item->AddObserver(this); } @@ -168,28 +168,31 @@ content::WebContents* web_contents, content::RenderFrameHost* rfh, ClientSafeBrowsingReportRequest* report) { - if (!SafeBrowsingNavigationObserverManager::IsEnabledAndReady( - profile_->GetPrefs(), g_browser_process->safe_browsing_service())) { + SafeBrowsingNavigationObserverManager* observer_manager = + web_contents + ? SafeBrowsingNavigationObserverManagerFactory::GetForBrowserContext( + web_contents->GetBrowserContext()) + : nullptr; + + if (!web_contents) { + RecordApkDownloadTelemetryIncompleteReason( + ApkDownloadTelemetryIncompleteReason::MISSING_WEB_CONTENTS); + return; + } else if (!SafeBrowsingNavigationObserverManager::IsEnabledAndReady( + profile_->GetPrefs(), + g_browser_process->safe_browsing_service()) || + !observer_manager) { RecordApkDownloadTelemetryIncompleteReason( ApkDownloadTelemetryIncompleteReason::SB_NAVIGATION_MANAGER_NOT_READY); return; } RecordApkDownloadTelemetryIncompleteReason( - web_contents - ? ApkDownloadTelemetryIncompleteReason::COMPLETE - : ApkDownloadTelemetryIncompleteReason::MISSING_WEB_CONTENTS); - SafeBrowsingNavigationObserverManager* observer_manager = - web_contents - ? SafeBrowsingNavigationObserverManagerFactory::GetForBrowserContext( - web_contents->GetBrowserContext()) - : nullptr; + ApkDownloadTelemetryIncompleteReason::COMPLETE); SafeBrowsingNavigationObserverManager::AttributionResult result = - observer_manager - ? observer_manager->IdentifyReferrerChainByRenderFrameHost( - rfh, kAndroidTelemetryUserGestureLimit, - report->mutable_referrer_chain()) - : SafeBrowsingNavigationObserverManager::NAVIGATION_EVENT_NOT_FOUND; + observer_manager->IdentifyReferrerChainByRenderFrameHost( + rfh, kAndroidTelemetryUserGestureLimit, + report->mutable_referrer_chain()); size_t referrer_chain_length = report->referrer_chain().size(); UMA_HISTOGRAM_COUNTS_100( @@ -205,10 +208,8 @@ CountOfRecentNavigationsToAppend( profile_, profile_->GetPrefs(), result) : 0u; - if (observer_manager) { - observer_manager->AppendRecentNavigations(recent_navigations_to_collect, - report->mutable_referrer_chain()); - } + observer_manager->AppendRecentNavigations(recent_navigations_to_collect, + report->mutable_referrer_chain()); } std::unique_ptr<ClientSafeBrowsingReportRequest> @@ -227,8 +228,9 @@ content::DownloadItemUtils::GetWebContents(item); content::RenderFrameHost* rfh = content::DownloadItemUtils::GetRenderFrameHost(item); - if (!rfh && web_contents) + if (!rfh && web_contents) { rfh = web_contents->GetPrimaryMainFrame(); + } FillReferrerChain(web_contents, rfh, report.get());
diff --git a/chrome/browser/tabpersistence/android/java/src/org/chromium/chrome/browser/tabpersistence/FlatBufferTabStateSerializer.java b/chrome/browser/tabpersistence/android/java/src/org/chromium/chrome/browser/tabpersistence/FlatBufferTabStateSerializer.java index 5effb259..8d8ec32 100644 --- a/chrome/browser/tabpersistence/android/java/src/org/chromium/chrome/browser/tabpersistence/FlatBufferTabStateSerializer.java +++ b/chrome/browser/tabpersistence/android/java/src/org/chromium/chrome/browser/tabpersistence/FlatBufferTabStateSerializer.java
@@ -117,11 +117,13 @@ state.timestampMillis = tabStateFlatBuffer.timestampMillis(); state.lastNavigationCommittedTimestampMillis = tabStateFlatBuffer.lastNavigationCommittedTimestampMillis(); - Token tabGroupId = - new Token( - tabStateFlatBuffer.tabGroupId().high(), - tabStateFlatBuffer.tabGroupId().low()); - state.tabGroupId = tabGroupId.isZero() ? null : tabGroupId; + + Token tabGroupId = null; + var flatBufferTabGroupId = tabStateFlatBuffer.tabGroupId(); + if (flatBufferTabGroupId != null) { + tabGroupId = new Token(flatBufferTabGroupId.high(), flatBufferTabGroupId.low()); + } + state.tabGroupId = (tabGroupId == null || tabGroupId.isZero()) ? null : tabGroupId; state.userAgent = getTabUserAgentTypeFromFlatBuffer(tabStateFlatBuffer.userAgent()); state.tabLaunchTypeAtCreation = getLaunchTypeFromFlatBuffer(tabStateFlatBuffer.launchTypeAtCreation());
diff --git a/chrome/browser/tpcd/support/top_level_trial_service.cc b/chrome/browser/tpcd/support/top_level_trial_service.cc new file mode 100644 index 0000000..70c1d97 --- /dev/null +++ b/chrome/browser/tpcd/support/top_level_trial_service.cc
@@ -0,0 +1,152 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/tpcd/support/top_level_trial_service.h" + +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/document_user_data.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/origin_trials_controller_delegate.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/storage_partition.h" +#include "net/base/features.h" +#include "services/network/public/mojom/cookie_manager.mojom.h" + +namespace tpcd::trial { +namespace { + +const char kTrialName[] = "TopLevelTpcd"; +} // namespace + +TopLevelTrialService::TopLevelTrialService( + content::BrowserContext* browser_context) + : browser_context_(browser_context) { + ot_controller_ = browser_context->GetOriginTrialsControllerDelegate(); + if (ot_controller_) { + ot_controller_->AddObserver(this); + } +} + +TopLevelTrialService::~TopLevelTrialService() = default; + +void TopLevelTrialService::Shutdown() { + if (ot_controller_) { + ot_controller_->RemoveObserver(this); + } + + ot_controller_ = nullptr; + browser_context_ = nullptr; +} + +void TopLevelTrialService::UpdateTopLevelTrialSettingsForTesting( + const url::Origin& origin, + bool match_subdomains, + bool enabled) { + UpdateTopLevelTrialSettings(origin, match_subdomains, enabled); +} + +void TopLevelTrialService::UpdateTopLevelTrialSettings( + const url::Origin& origin, + bool includes_subdomains, + bool enabled) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + HostContentSettingsMap* settings_map = + HostContentSettingsMapFactory::GetForProfile(browser_context_); + CHECK(settings_map); + + const GURL origin_as_url = origin.GetURL(); + + // Check for an existing `TOP_LEVEL_TPCD_TRIAL` setting that allows origin. + content_settings::SettingInfo existing_setting_info; + bool setting_exists = + (settings_map->GetContentSetting( + origin_as_url, origin_as_url, + ContentSettingsType::TOP_LEVEL_TPCD_TRIAL, + &existing_setting_info) == CONTENT_SETTING_ALLOW) && + (existing_setting_info.primary_pattern.HasDomainWildcard() == + includes_subdomains) && + !existing_setting_info.primary_pattern.MatchesAllHosts(); + + // If the trial status matches existing settings, there is no need to + // update `settings_map`. + if (enabled == setting_exists) { + return; + } + + ContentSettingsPattern primary_setting_pattern; + ContentSettingsPattern secondary_setting_pattern = + ContentSettingsPattern::Wildcard(); + if (includes_subdomains) { + primary_setting_pattern = ContentSettingsPattern::FromURL(origin_as_url); + } else { + // In this case, the combination of `primary_setting_pattern` and + // `secondary_setting_pattern` is equivalent to + // `ContentSettingsType::TOP_LEVEL_TPCD_TRIAL`'s default scope + // (`TOP_ORIGIN_ONLY_SCOPE`). + primary_setting_pattern = + ContentSettingsPattern::FromURLNoWildcard(origin_as_url); + } + + if (enabled) { + settings_map->SetContentSettingCustomScope( + primary_setting_pattern, secondary_setting_pattern, + ContentSettingsType::TOP_LEVEL_TPCD_TRIAL, CONTENT_SETTING_ALLOW); + } else { + CHECK(setting_exists); + + // Remove settings for expired/unused pairs to avoid memory bloat. + auto matches_pair = + [&](const ContentSettingPatternSource& setting) -> bool { + return (setting.primary_pattern == + existing_setting_info.primary_pattern) && + (setting.secondary_pattern == + existing_setting_info.secondary_pattern); + }; + + settings_map->ClearSettingsForOneTypeWithPredicate( + ContentSettingsType::TOP_LEVEL_TPCD_TRIAL, matches_pair); + } + + ContentSettingsForOneType trial_settings = + settings_map->GetSettingsForOneType( + ContentSettingsType::TOP_LEVEL_TPCD_TRIAL); + + browser_context_->GetDefaultStoragePartition() + ->GetCookieManagerForBrowserProcess() + ->SetContentSettings(ContentSettingsType::TOP_LEVEL_TPCD_TRIAL, + std::move(trial_settings), base::NullCallback()); +} + +void TopLevelTrialService::ClearTopLevelTrialSettings() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + HostContentSettingsMap* settings_map = + HostContentSettingsMapFactory::GetForProfile(browser_context_); + CHECK(settings_map); + + settings_map->ClearSettingsForOneType( + ContentSettingsType::TOP_LEVEL_TPCD_TRIAL); +} + +void TopLevelTrialService::OnStatusChanged(const url::Origin& origin, + const std::string& partition_site, + bool includes_subdomains, + bool enabled) { + // TopLevelTpcd is a first-party trial, so the |partition_site| can be ignored + // (and should always be same-site with the |origin| anyway). + UpdateTopLevelTrialSettings(origin, includes_subdomains, enabled); +} + +void TopLevelTrialService::OnPersistedTokensCleared() { + ClearTopLevelTrialSettings(); +} + +std::string TopLevelTrialService::trial_name() { + return kTrialName; +} + +} // namespace tpcd::trial
diff --git a/chrome/browser/tpcd/support/top_level_trial_service.h b/chrome/browser/tpcd/support/top_level_trial_service.h new file mode 100644 index 0000000..3167648 --- /dev/null +++ b/chrome/browser/tpcd/support/top_level_trial_service.h
@@ -0,0 +1,59 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_TPCD_SUPPORT_TOP_LEVEL_TRIAL_SERVICE_H_ +#define CHROME_BROWSER_TPCD_SUPPORT_TOP_LEVEL_TRIAL_SERVICE_H_ + +#include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/keyed_service/core/keyed_service.h" +#include "content/public/browser/origin_trials_controller_delegate.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" + +namespace tpcd::trial { + +// A profile-keyed service that maintains TPCD_TRIAL content settings based on +// the state of the associated origin trial for a given +// `origin`-`partition_site` pair. +class TopLevelTrialService + : public content::OriginTrialsControllerDelegate::Observer, + public KeyedService { + public: + explicit TopLevelTrialService(content::BrowserContext* browser_context); + ~TopLevelTrialService() override; + TopLevelTrialService(const TopLevelTrialService&) = delete; + TopLevelTrialService& operator=(const TopLevelTrialService&) = delete; + + // KeyedService overrides: + void Shutdown() override; + + void UpdateTopLevelTrialSettingsForTesting(const url::Origin& origin, + bool match_subdomains, + bool enabled); + + private: + // Updates `ContentSettingsForOneType::TOP_LEVEL_TPCD_TRIAL` to reflect + // the status of the trial for `origin`. If `match_subdomains` is true, + // a custom scope is used for the content setting to match all subdomains of + // `origin`. + void UpdateTopLevelTrialSettings(const url::Origin& origin, + bool match_subdomains, + bool enabled); + void ClearTopLevelTrialSettings(); + + // content::OriginTrialsControllerDelegate::Observer overrides: + void OnStatusChanged(const url::Origin& origin, + const std::string& partition_site, + bool match_subdomains, + bool enabled) override; + void OnPersistedTokensCleared() override; + std::string trial_name() override; + + raw_ptr<content::OriginTrialsControllerDelegate> ot_controller_; + raw_ptr<content::BrowserContext> browser_context_; +}; + +} // namespace tpcd::trial + +#endif // CHROME_BROWSER_TPCD_SUPPORT_TOP_LEVEL_TRIAL_SERVICE_H_
diff --git a/chrome/browser/tpcd/support/top_level_trial_service_browsertest.cc b/chrome/browser/tpcd/support/top_level_trial_service_browsertest.cc new file mode 100644 index 0000000..ddb111d --- /dev/null +++ b/chrome/browser/tpcd/support/top_level_trial_service_browsertest.cc
@@ -0,0 +1,422 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/strings/strcat.h" +#include "base/test/bind.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/content_settings/cookie_settings_factory.h" +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/test/base/chrome_test_utils.h" +#include "components/content_settings/core/browser/content_settings_observer.h" +#include "components/content_settings/core/browser/cookie_settings.h" +#include "components/content_settings/core/common/content_settings.h" +#include "components/content_settings/core/common/content_settings_pattern.h" +#include "components/content_settings/core/common/content_settings_types.h" +#include "components/content_settings/core/common/features.h" +#include "components/content_settings/core/common/pref_names.h" +#include "components/network_session_configurator/common/network_switches.h" +#include "components/prefs/pref_service.h" +#include "components/privacy_sandbox/tracking_protection_prefs.h" +#include "components/user_prefs/user_prefs.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/common/content_features.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/url_loader_interceptor.h" +#include "net/base/features.h" +#include "net/cookies/cookie_util.h" +#include "net/dns/mock_host_resolver.h" +#include "net/test/embedded_test_server/embedded_test_server.h" + +using content::URLLoaderInterceptor; +using content::WebContents; + +namespace tpcd::trial { +namespace { + +const char kTestTokenPublicKey[] = + "dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA=,fMS4mpO6buLQ/QMd+zJmxzty/" + "VQ6B1EUZqoCU04zoRU="; + +const char kTrialEnabledDomain[] = "example.test"; +const char kTrialEnabledSubdomain[] = "sub.example.test"; + +// Origin Trials token for `kTrialEnabledSite` generated with: +// tools/origin_trials/generate_token.py https://example.test TopLevelTpcd +// --expire-days 5000 +const char kTopLevelTrialToken[] = + "A5sGfiy3qkhJES3yFHkBd7i0jX8rC+" + "pCA2M0tAhfmetOLkvOVTAR2589eHxZHbdv3QgX7BtANaw3A+" + "A3NvgAtwIAAABXeyJvcmlnaW4iOiAiaHR0cHM6Ly9leGFtcGxlLnRlc3Q6NDQzIiwgImZlYXR1" + "cmUiOiAiVG9wTGV2ZWxUcGNkIiwgImV4cGlyeSI6IDIxMzkzMjU5MjZ9"; + +// Origin Trials token for `kTrialEnabledSite` (and all its subdomains) +// generated with: +// tools/origin_trials/generate_token.py https://example.test TopLevelTpcd +// --is-subdomain --expire-days 5000 +const char kTopLevelTrialSubdomainMatchingToken[] = + "A5+BZIDRMyQWn2lWBHXWd3egEk2WqNdtEuzEbDZV0qXwYM8nKiqlHNYjGrfXuFgmUQ+" + "j0wpk0EBVJC51I3K0gQkAAABseyJvcmlnaW4iOiAiaHR0cHM6Ly9leGFtcGxlLnRlc3Q6NDQzI" + "iwgImZlYXR1cmUiOiAiVG9wTGV2ZWxUcGNkIiwgImV4cGlyeSI6IDIxMzkzMzg0NjcsICJpc1N" + "1YmRvbWFpbiI6IHRydWV9"; + +// Origin Trials token for `kTrialEnabledSiteSubdomain` generated with: +// tools/origin_trials/generate_token.py https://sub.example.test TopLevelTpcd +// --expire-days 5000 +const char kSubdomainTopLevelTrialToken[] = + "A7CJlPHXa8yQc2lJRvM/" + "mq4Oi5+" + "SJHbT4nnUmWiYKeuguuMkTd6y8DHBRAdEgvLXPajr9Qm2cMe4f5qzovm07QwAAABbeyJvcmlna" + "W4iOiAiaHR0cHM6Ly9zdWIuZXhhbXBsZS50ZXN0OjQ0MyIsICJmZWF0dXJlIjogIlRvcExldmV" + "sVHBjZCIsICJleHBpcnkiOiAyMTM5MzM4NTY5fQ=="; + +// Origin Trials token for `kTrialEnabledSiteSubdomain` (and all its subdomains) +// generated with: +// tools/origin_trials/generate_token.py https://sub.example.test TopLevelTpcd +// --is-subdomain --expire-days 5000 +const char kSubdomainTopLevelTrialSubdomainMatchingToken[] = + "Ayuwtl4l9AC0MUBPlPDMZ3on5Db2hTQtFJdRM4fC1Bj03JLXWKNoe9bg4m5CslS5wFG9WQQsKu" + "q/" + "IbnFBxzGXwMAAABweyJvcmlnaW4iOiAiaHR0cHM6Ly9zdWIuZXhhbXBsZS50ZXN0OjQ0MyIsIC" + "JmZWF0dXJlIjogIlRvcExldmVsVHBjZCIsICJleHBpcnkiOiAyMTM5MzM4NTIzLCAiaXNTdWJk" + "b21haW4iOiB0cnVlfQ=="; + +class ContentSettingChangeObserver : public content_settings::Observer { + public: + explicit ContentSettingChangeObserver( + content::BrowserContext* browser_context, + const GURL request_url, + const GURL partition_url, + ContentSettingsType setting_type) + : browser_context_(browser_context), + request_url_(request_url), + partition_url_(partition_url), + setting_type_(setting_type) { + HostContentSettingsMapFactory::GetForProfile(browser_context_) + ->AddObserver(this); + } + + ~ContentSettingChangeObserver() override { + HostContentSettingsMapFactory::GetForProfile(browser_context_) + ->RemoveObserver(this); + } + void Wait() { run_loop_.Run(); } + + private: + // content_settings::Observer overrides: + void OnContentSettingChanged( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsTypeSet content_type_set) override { + if (content_type_set.Contains(setting_type_) && + primary_pattern.Matches(request_url_) && + secondary_pattern.Matches(partition_url_)) { + run_loop_.Quit(); + } + } + + raw_ptr<content::BrowserContext> browser_context_; + base::RunLoop run_loop_; + GURL request_url_; + GURL partition_url_; + ContentSettingsType setting_type_; +}; + +} // namespace + +class TopLevelTpcdTrialBrowserTest : public PlatformBrowserTest { + public: + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitchASCII("origin-trial-public-key", + kTestTokenPublicKey); + command_line->AppendSwitch(switches::kIgnoreCertificateErrors); + } + + void SetUp() override { + features_.InitWithFeaturesAndParameters( + {{::features::kPersistentOriginTrials, {}}, + {net::features::kTopLevelTpcdTrialSettings, {}}, + {content_settings::features::kTrackingProtection3pcd, {}}}, + {}); + + PlatformBrowserTest::SetUp(); + } + + void SetUpOnMainThread() override { + ASSERT_TRUE(embedded_test_server()->Start()); + host_resolver()->AddRule("*", "127.0.0.1"); + + https_server_ = std::make_unique<net::EmbeddedTestServer>( + net::EmbeddedTestServer::TYPE_HTTPS); + https_server_->SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES); + https_server_->AddDefaultHandlers( + base::FilePath(FILE_PATH_LITERAL("chrome/test/data/"))); + ASSERT_TRUE(https_server_->Start()); + + // We use a URLLoaderInterceptor, rather than the EmbeddedTestServer, since + // the origin trial token in the response is associated with a fixed + // origin, whereas EmbeddedTestServer serves content on a random port. + url_loader_interceptor_ = + std::make_unique<URLLoaderInterceptor>(base::BindLambdaForTesting( + [this](URLLoaderInterceptor::RequestParams* params) { + return OnRequest(params); + })); + + GetPrefs()->SetBoolean(prefs::kTrackingProtection3pcdEnabled, true); + } + + void TearDownOnMainThread() override { + https_server_.reset(); + url_loader_interceptor_.reset(); + PlatformBrowserTest::TearDownOnMainThread(); + } + + protected: + content::WebContents* GetActiveWebContents() { + return chrome_test_utils::GetActiveWebContents(this); + } + + Profile* GetProfile() { + return Profile::FromBrowserContext( + GetActiveWebContents()->GetBrowserContext()); + } + + PrefService* GetPrefs() { + return user_prefs::UserPrefs::Get( + GetActiveWebContents()->GetBrowserContext()); + } + + // Most other cookie-related content settings compare their primary patterns' + // against embedded/requesting sites and their secondary patterns' + // against top-level sites. This convenience function helps avoid confusion + // since |TOP_LEVEL_TPCD_TRIAL| content settings only use a primary pattern + // which is compared against top-level sites. + ContentSettingChangeObserver CreateTopLevelTrialSettingsObserver(GURL url) { + return ContentSettingChangeObserver( + GetProfile(), url, GURL(), ContentSettingsType::TOP_LEVEL_TPCD_TRIAL); + } + + bool OnRequest(content::URLLoaderInterceptor::RequestParams* params) { + std::string path = params->url_request.url.path().substr(1); + std::string host = params->url_request.url.host(); + std::string query = params->url_request.url.query(); + + if (host != kTrialEnabledDomain && host != kTrialEnabledSubdomain) { + return false; + } + + std::string headers = + "HTTP/1.1 200 OK\n" + "Content-type: text/html\n"; + std::string body = ""; + + std::string token = ""; + if (host == kTrialEnabledDomain) { + if (query == "subdomain_matching_token") { + token = kTopLevelTrialSubdomainMatchingToken; + } else if (query != "no_token") { + token = kTopLevelTrialToken; + } + } + + if (host == kTrialEnabledSubdomain) { + if (query == "etld_plus_1_token") { + token = kTopLevelTrialSubdomainMatchingToken; + } else if (query == "subdomain_matching_token") { + token = kSubdomainTopLevelTrialSubdomainMatchingToken; + } else if (query != "no_token") { + token = kSubdomainTopLevelTrialToken; + } + } + + if (path.find("meta_tag") == 0) { + body = + "<html>\n" + "<head>\n" + "<meta http-equiv='origin-trial' " + "content='" + + token + + "'>\n" + "</head>\n" + "<body></body>\n" + "</html>\n"; + } else { + base::StrAppend(&headers, {"Origin-Trial: ", token, "\n"}); + } + + content::URLLoaderInterceptor::WriteResponse(headers, body, + params->client.get()); + return true; + } + + base::test::ScopedFeatureList features_; + std::unique_ptr<net::EmbeddedTestServer> https_server_; + std::unique_ptr<URLLoaderInterceptor> url_loader_interceptor_; + const GURL kTrialEnabledSite{base::StrCat({"https://", kTrialEnabledDomain})}; + const GURL kTrialEnabledSiteSubdomain{ + base::StrCat({"https://", kTrialEnabledSubdomain})}; +}; + +IN_PROC_BROWSER_TEST_F(TopLevelTpcdTrialBrowserTest, EnabledAfterHttpResponse) { + content::WebContents* web_contents = GetActiveWebContents(); + + // Verify third-party cookie access isn't permitted under |kTrialEnabledSite|. + content_settings::CookieSettings* settings = + CookieSettingsFactory::GetForProfile(GetProfile()).get(); + EXPECT_EQ(settings->GetCookieSetting(GURL(), kTrialEnabledSite, {}, nullptr), + CONTENT_SETTING_BLOCK); + + // Navigate to a |kTrialEnabledSite| page that returns its origin trial token + // in the HTTP response headers. + { + ContentSettingChangeObserver setting_observer = + CreateTopLevelTrialSettingsObserver(kTrialEnabledSite); + ASSERT_TRUE(content::NavigateToURL(web_contents, kTrialEnabledSite)); + setting_observer.Wait(); + } + + // Check that third-party cookie access is now permitted under + // |kTrialEnabledSite|. + EXPECT_EQ(settings->GetCookieSetting(GURL(), kTrialEnabledSite, {}, nullptr), + CONTENT_SETTING_ALLOW); + + // Verify that a subsequent load of a |kTrialEnabledSite| page + // without the token removes the |TOP_LEVEL_TPCD_TRIAL| content setting for + // it. + { + GURL enabled_site_no_token = GURL(kTrialEnabledSite.spec() + "?no_token"); + ContentSettingChangeObserver setting_observer = + CreateTopLevelTrialSettingsObserver(enabled_site_no_token); + ASSERT_TRUE(content::NavigateToURL(web_contents, enabled_site_no_token)); + setting_observer.Wait(); + } + + // Verify third-party cookie access is no longer permitted under + // |kTrialEnabledSite|. + EXPECT_EQ(settings->GetCookieSetting(GURL(), kTrialEnabledSite, {}, nullptr), + CONTENT_SETTING_BLOCK); +} + +IN_PROC_BROWSER_TEST_F(TopLevelTpcdTrialBrowserTest, + EnabledAfterHttpResponseWithEtldSubdomainMatchingToken) { + content::WebContents* web_contents = GetActiveWebContents(); + + // Verify third-party cookie access isn't permitted under |kTrialEnabledSite| + // or |kTrialEnabledSiteSubdomain|. + content_settings::CookieSettings* settings = + CookieSettingsFactory::GetForProfile(GetProfile()).get(); + EXPECT_EQ(settings->GetCookieSetting(GURL(), kTrialEnabledSite, {}, nullptr), + CONTENT_SETTING_BLOCK); + EXPECT_EQ(settings->GetCookieSetting(GURL(), kTrialEnabledSiteSubdomain, {}, + nullptr), + CONTENT_SETTING_BLOCK); + + // Navigate to a |kTrialEnabledSiteSubdomain| page that returns the subdomain + // matching origin trial token for it's eTLD+1 (|kTrialEnabledSite|) in the + // HTTP response headers. + { + GURL url = GURL(kTrialEnabledSiteSubdomain.spec() + "?etld_plus_1_token"); + ContentSettingChangeObserver setting_observer = + CreateTopLevelTrialSettingsObserver(url); + ASSERT_TRUE(content::NavigateToURL(web_contents, url)); + setting_observer.Wait(); + } + + // Check that third-party cookie access is now permitted under + // |kTrialEnabledSite| and |kTrialEnabledSiteSubdomain|. + EXPECT_EQ(settings->GetCookieSetting(GURL(), kTrialEnabledSiteSubdomain, {}, + nullptr), + CONTENT_SETTING_ALLOW); + EXPECT_EQ(settings->GetCookieSetting(GURL(), kTrialEnabledSite, {}, nullptr), + CONTENT_SETTING_ALLOW); + + // Verify that a subsequent load of a page from |kTrialEnabledSiteSubdomain|'s + // eTLD+1 (|kTrialEnabledSite|) without the token removes the + // |TOP_LEVEL_TPCD_TRIAL| content setting for them. + { + GURL enabled_site_no_token = GURL(kTrialEnabledSite.spec() + "?no_token"); + ContentSettingChangeObserver setting_observer = + CreateTopLevelTrialSettingsObserver(enabled_site_no_token); + ASSERT_TRUE(content::NavigateToURL(web_contents, enabled_site_no_token)); + setting_observer.Wait(); + } + + // Verify third-party cookie access is no longer permitted under + // |kTrialEnabledSite| or |kTrialEnabledSiteSubdomain|. + EXPECT_EQ(settings->GetCookieSetting(GURL(), kTrialEnabledSiteSubdomain, {}, + nullptr), + CONTENT_SETTING_BLOCK); + EXPECT_EQ(settings->GetCookieSetting(GURL(), kTrialEnabledSite, {}, nullptr), + CONTENT_SETTING_BLOCK); +} + +IN_PROC_BROWSER_TEST_F(TopLevelTpcdTrialBrowserTest, EnabledUsingMetaTag) { + content::WebContents* web_contents = GetActiveWebContents(); + + // Navigate to a |kTrialEnabledSite| page where its origin trial token is in a + // meta tag in the head of the document. + { + GURL url = GURL(kTrialEnabledSite.spec() + "meta_tag"); + + ContentSettingChangeObserver setting_observer = + CreateTopLevelTrialSettingsObserver(url); + ASSERT_TRUE(content::NavigateToURL(web_contents, url)); + setting_observer.Wait(); + } + + // Check that third-party cookie access is now permitted under + // |kTrialEnabledSite|. + content_settings::CookieSettings* settings = + CookieSettingsFactory::GetForProfile(GetProfile()).get(); + EXPECT_EQ(settings->GetCookieSetting(GURL(), kTrialEnabledSite, {}, nullptr), + CONTENT_SETTING_ALLOW); + EXPECT_EQ(settings->GetThirdPartyCookieAllowMechanism( + GURL(), kTrialEnabledSite, {}, nullptr), + content_settings::CookieSettingsBase:: + ThirdPartyCookieAllowMechanism::kAllowByTopLevel3PCD); +} + +IN_PROC_BROWSER_TEST_F(TopLevelTpcdTrialBrowserTest, + EnabledUsingMetaTagWithEtldSubdomainMatchingToken) { + content::WebContents* web_contents = GetActiveWebContents(); + + // Navigate to a |kTrialEnabledSiteSubdomain| page where the subdomain + // matching origin trial token for it's eTLD+1 (|kTrialEnabledSite|) is in a + // meta tag in the head of the document. + { + GURL url = + GURL(kTrialEnabledSiteSubdomain.spec() + "meta_tag?etld_plus_1_token"); + ContentSettingChangeObserver setting_observer = + CreateTopLevelTrialSettingsObserver(url); + ASSERT_TRUE(content::NavigateToURL(web_contents, url)); + setting_observer.Wait(); + } + + // Verify that third-party cookie access is now permitted under + // |kTrialEnabledSite| and |kTrialEnabledSiteSubdomain|. + content_settings::CookieSettings* settings = + CookieSettingsFactory::GetForProfile(GetProfile()).get(); + + EXPECT_EQ(settings->GetCookieSetting(GURL(), kTrialEnabledSiteSubdomain, {}, + nullptr), + CONTENT_SETTING_ALLOW); + EXPECT_EQ(settings->GetCookieSetting(GURL(), kTrialEnabledSite, {}, nullptr), + CONTENT_SETTING_ALLOW); + + EXPECT_EQ(settings->GetThirdPartyCookieAllowMechanism( + GURL(), kTrialEnabledSiteSubdomain, {}, nullptr), + content_settings::CookieSettingsBase:: + ThirdPartyCookieAllowMechanism::kAllowByTopLevel3PCD); + EXPECT_EQ(settings->GetThirdPartyCookieAllowMechanism( + GURL(), kTrialEnabledSite, {}, nullptr), + content_settings::CookieSettingsBase:: + ThirdPartyCookieAllowMechanism::kAllowByTopLevel3PCD); +} + +} // namespace tpcd::trial
diff --git a/chrome/browser/tpcd/support/top_level_trial_service_factory.cc b/chrome/browser/tpcd/support/top_level_trial_service_factory.cc new file mode 100644 index 0000000..d62a1d9 --- /dev/null +++ b/chrome/browser/tpcd/support/top_level_trial_service_factory.cc
@@ -0,0 +1,63 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/tpcd/support/top_level_trial_service_factory.h" + +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" +#include "chrome/browser/origin_trials/origin_trials_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/tpcd/support/top_level_trial_service.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/common/content_features.h" +#include "net/base/features.h" + +namespace tpcd::trial { + +// static +TopLevelTrialServiceFactory* TopLevelTrialServiceFactory::GetInstance() { + static base::NoDestructor<TopLevelTrialServiceFactory> factory; + return factory.get(); +} + +// static +TopLevelTrialService* TopLevelTrialServiceFactory::GetForProfile( + Profile* profile) { + return static_cast<TopLevelTrialService*>( + GetInstance()->GetServiceForBrowserContext(profile, true)); +} + +// static +ProfileSelections TopLevelTrialServiceFactory::CreateProfileSelections() { + if (!base::FeatureList::IsEnabled( + net::features::kTopLevelTpcdTrialSettings) || + !base::FeatureList::IsEnabled(features::kPersistentOriginTrials)) { + return ProfileSelections::BuildNoProfilesSelected(); + } + + return ProfileSelections::Builder() + .WithRegular(ProfileSelection::kOriginalOnly) + .WithGuest(ProfileSelection::kOwnInstance) + // The Following will be completely unselected as users do not "browse" + // within this profiles. + .WithSystem(ProfileSelection::kNone) + .WithAshInternals(ProfileSelection::kNone) + .Build(); +} + +TopLevelTrialServiceFactory::TopLevelTrialServiceFactory() + : ProfileKeyedServiceFactory("TopLevelTrialService", + CreateProfileSelections()) { + DependsOn(OriginTrialsFactory::GetInstance()); + DependsOn(HostContentSettingsMapFactory::GetInstance()); +} + +TopLevelTrialServiceFactory::~TopLevelTrialServiceFactory() = default; + +KeyedService* TopLevelTrialServiceFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + return new TopLevelTrialService(context); +} + +} // namespace tpcd::trial
diff --git a/chrome/browser/tpcd/support/top_level_trial_service_factory.h b/chrome/browser/tpcd/support/top_level_trial_service_factory.h new file mode 100644 index 0000000..64069286 --- /dev/null +++ b/chrome/browser/tpcd/support/top_level_trial_service_factory.h
@@ -0,0 +1,44 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_TPCD_SUPPORT_TOP_LEVEL_TRIAL_SERVICE_FACTORY_H_ +#define CHROME_BROWSER_TPCD_SUPPORT_TOP_LEVEL_TRIAL_SERVICE_FACTORY_H_ + +#include "base/no_destructor.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" + +namespace content { +class BrowserContext; +} + +namespace tpcd::trial { +class TopLevelTrialService; + +class TopLevelTrialServiceFactory : public ProfileKeyedServiceFactory { + public: + static TopLevelTrialServiceFactory* GetInstance(); + static TopLevelTrialService* GetForProfile(Profile* profile); + static ProfileSelections CreateProfileSelections(); + + TopLevelTrialServiceFactory(const TopLevelTrialServiceFactory&) = delete; + TopLevelTrialServiceFactory& operator=(const TopLevelTrialServiceFactory&) = + delete; + TopLevelTrialServiceFactory(TopLevelTrialServiceFactory&&) = delete; + TopLevelTrialServiceFactory& operator=(TopLevelTrialServiceFactory&&) = + delete; + + private: + friend class base::NoDestructor<TopLevelTrialServiceFactory>; + + TopLevelTrialServiceFactory(); + ~TopLevelTrialServiceFactory() override; + + // BrowserContextKeyedServiceFactory: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; +}; + +} // namespace tpcd::trial + +#endif // CHROME_BROWSER_TPCD_SUPPORT_TOP_LEVEL_TRIAL_SERVICE_FACTORY_H_
diff --git a/chrome/browser/tpcd/support/tpcd_support_service.cc b/chrome/browser/tpcd/support/tpcd_support_service.cc index 97e2940..90f7b26bf 100644 --- a/chrome/browser/tpcd/support/tpcd_support_service.cc +++ b/chrome/browser/tpcd/support/tpcd_support_service.cc
@@ -14,8 +14,6 @@ #include "components/origin_trials/browser/origin_trials.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/navigation_handle.h" -#include "content/public/browser/render_frame_host.h" #include "content/public/browser/storage_partition.h" #include "services/network/public/mojom/cookie_manager.mojom.h" #include "url/gurl.h" @@ -30,7 +28,6 @@ TpcdTrialService::TpcdTrialService(content::BrowserContext* browser_context) : browser_context_(browser_context) { ot_controller_ = browser_context->GetOriginTrialsControllerDelegate(); - if (ot_controller_) { ot_controller_->AddObserver(this); }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 6436e06f..686a6ba 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -53,6 +53,8 @@ "autofill/autofill_popup_controller.h", "autofill/autofill_popup_controller_impl.cc", "autofill/autofill_popup_controller_impl.h", + "autofill/autofill_popup_hide_helper.cc", + "autofill/autofill_popup_hide_helper.h", "autofill/autofill_popup_view.h", "autofill/autofill_popup_view_delegate.h", "autofill/chrome_autofill_client.cc", @@ -511,6 +513,7 @@ "//components/embedder_support:browser_util", "//components/encrypted_messages:encrypted_message_proto", "//components/enterprise", + "//components/enterprise/buildflags:buildflags", "//components/error_page/content/browser", "//components/facilitated_payments/core/features", "//components/favicon/content", @@ -1123,28 +1126,6 @@ "chrome_web_modal_dialog_manager_delegate.h", "collected_cookies_infobar_delegate.cc", "collected_cookies_infobar_delegate.h", - "commander/bookmark_command_source.cc", - "commander/bookmark_command_source.h", - "commander/command_source.cc", - "commander/command_source.h", - "commander/commander.cc", - "commander/commander.h", - "commander/commander_backend.h", - "commander/commander_controller.cc", - "commander/commander_controller.h", - "commander/commander_frontend.h", - "commander/commander_view_model.cc", - "commander/commander_view_model.h", - "commander/entity_match.cc", - "commander/entity_match.h", - "commander/open_url_command_source.cc", - "commander/open_url_command_source.h", - "commander/simple_command_source.cc", - "commander/simple_command_source.h", - "commander/tab_command_source.cc", - "commander/tab_command_source.h", - "commander/window_command_source.cc", - "commander/window_command_source.h", "commerce/commerce_prompt.h", "confirm_bubble_model.cc", "confirm_bubble_model.h", @@ -1663,10 +1644,6 @@ "webui/chrome_content_browser_client_webui_part.h", "webui/chrome_web_contents_handler.cc", "webui/chrome_web_contents_handler.h", - "webui/commander/commander_handler.cc", - "webui/commander/commander_handler.h", - "webui/commander/commander_ui.cc", - "webui/commander/commander_ui.h", "webui/commerce/product_specifications_ui.cc", "webui/commerce/product_specifications_ui.h", "webui/commerce/shopping_insights_side_panel_ui.cc", @@ -2045,7 +2022,6 @@ "//chrome/browser/support_tool:support_tool_proto", "//chrome/browser/ui/color:color_headers", "//chrome/browser/ui/color:mixers", - "//chrome/browser/ui/commander:fuzzy_finder", "//chrome/browser/ui/webui/access_code_cast:mojo_bindings", "//chrome/browser/ui/webui/app_service_internals:mojo_bindings", "//chrome/browser/ui/webui/downloads:mojo_bindings", @@ -4452,24 +4428,6 @@ "cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm", "cocoa/scoped_menu_bar_lock.h", "cocoa/scoped_menu_bar_lock.mm", - "cocoa/screentime/fake_webpage_controller.h", - "cocoa/screentime/fake_webpage_controller.mm", - "cocoa/screentime/history_bridge.h", - "cocoa/screentime/history_bridge.mm", - "cocoa/screentime/history_bridge_factory.h", - "cocoa/screentime/history_bridge_factory.mm", - "cocoa/screentime/history_deleter.h", - "cocoa/screentime/history_deleter_impl.h", - "cocoa/screentime/history_deleter_impl.mm", - "cocoa/screentime/screentime_features.cc", - "cocoa/screentime/screentime_features.h", - "cocoa/screentime/screentime_policy.cc", - "cocoa/screentime/screentime_policy.h", - "cocoa/screentime/tab_helper.h", - "cocoa/screentime/tab_helper.mm", - "cocoa/screentime/webpage_controller.h", - "cocoa/screentime/webpage_controller_impl.h", - "cocoa/screentime/webpage_controller_impl.mm", "cocoa/share_menu_controller.h", "cocoa/share_menu_controller.mm", "cocoa/simple_message_box_cocoa.h", @@ -5170,8 +5128,6 @@ "views/chrome_web_dialog_view.h", "views/color_provider_browser_helper.cc", "views/color_provider_browser_helper.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/commerce/price_insights_icon_view.cc", @@ -6509,6 +6465,10 @@ } } + if (enterprise_watermark) { + deps += [ "//chrome/browser/enterprise/watermark:watermark_view_lib" ] + } + if (enable_lens_desktop_google_branded_features) { sources += [ "lens/lens_side_panel_helper.h",
diff --git a/chrome/browser/ui/actions/chrome_action_id.h b/chrome/browser/ui/actions/chrome_action_id.h index 379e379..77db85a 100644 --- a/chrome/browser/ui/actions/chrome_action_id.h +++ b/chrome/browser/ui/actions/chrome_action_id.h
@@ -203,7 +203,6 @@ E(kActionCloseSignInPromo, IDC_CLOSE_SIGN_IN_PROMO) \ E(kActionShowFullUrls, IDC_SHOW_FULL_URLS) \ E(kActionCaretBrowsingToggle, IDC_CARET_BROWSING_TOGGLE) \ - E(kActionToggleQuickCommands, IDC_TOGGLE_QUICK_COMMANDS) \ E(kActionChromeTips, IDC_CHROME_TIPS) \ E(kActionChromeWhatsNew, IDC_CHROME_WHATS_NEW) \ E(kActionPerformance, IDC_PERFORMANCE) \
diff --git a/chrome/browser/ui/ash/session_controller_client_impl.cc b/chrome/browser/ui/ash/session_controller_client_impl.cc index a9edff1..59aa219 100644 --- a/chrome/browser/ui/ash/session_controller_client_impl.cc +++ b/chrome/browser/ui/ash/session_controller_client_impl.cc
@@ -27,7 +27,6 @@ #include "chrome/browser/ash/login/lock/screen_locker.h" #include "chrome/browser/ash/login/ui/user_adding_screen.h" #include "chrome/browser/ash/login/users/chrome_user_manager.h" -#include "chrome/browser/ash/login/users/multi_profile_user_controller.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/ash/settings/device_settings_service.h" #include "chrome/browser/browser_process.h" @@ -49,6 +48,7 @@ #include "components/prefs/pref_service.h" #include "components/session_manager/core/session_manager.h" #include "components/supervised_user/core/browser/supervised_user_service.h" +#include "components/user_manager/multi_user/multi_user_sign_in_policy_controller.h" #include "components/user_manager/user_manager_pref_names.h" #include "components/user_manager/user_type.h" #include "content/public/browser/browser_context.h" @@ -443,7 +443,7 @@ return ash::AddUserSessionPolicy::ERROR_NO_ELIGIBLE_USERS; if (static_cast<ash::ChromeUserManager*>(user_manager) - ->GetMultiProfileUserController() + ->GetMultiUserSignInPolicyController() ->GetPrimaryUserPolicy() == user_manager::MultiUserSignInPolicy::kNotAllowed) { return ash::AddUserSessionPolicy::ERROR_NOT_ALLOWED_PRIMARY_USER;
diff --git a/chrome/browser/ui/ash/session_controller_client_impl_unittest.cc b/chrome/browser/ui/ash/session_controller_client_impl_unittest.cc index 98493c5..a5853cf 100644 --- a/chrome/browser/ui/ash/session_controller_client_impl_unittest.cc +++ b/chrome/browser/ui/ash/session_controller_client_impl_unittest.cc
@@ -19,7 +19,6 @@ #include "base/time/time.h" #include "chrome/browser/ash/crosapi/fake_browser_manager.h" #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" -#include "chrome/browser/ash/login/users/multi_profile_user_controller.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h" #include "chrome/browser/policy/networking/policy_cert_service.h" @@ -36,6 +35,7 @@ #include "components/prefs/pref_service.h" #include "components/session_manager/core/session_manager.h" #include "components/user_manager/multi_user/multi_user_sign_in_policy.h" +#include "components/user_manager/multi_user/multi_user_sign_in_policy_controller.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user_manager.h" #include "components/user_manager/user_manager_pref_names.h" @@ -118,9 +118,11 @@ // Initialize the UserManager singleton. user_manager_.Reset(std::make_unique<TestChromeUserManager>()); - controller_ = std::make_unique<ash::MultiProfileUserController>( - TestingBrowserProcess::GetGlobal()->local_state(), user_manager_.Get()); - user_manager_->set_multi_profile_user_controller(controller_.get()); + controller_ = + std::make_unique<user_manager::MultiUserSignInPolicyController>( + TestingBrowserProcess::GetGlobal()->local_state(), + user_manager_.Get()); + user_manager_->set_multi_user_sign_in_policy_controller(controller_.get()); // Initialize AssistantBrowserDelegate singleton. assistant_delegate_ = std::make_unique<AssistantBrowserDelegateImpl>(); @@ -152,7 +154,7 @@ base::RunLoop().RunUntilIdle(); assistant_delegate_.reset(); - user_manager_->set_multi_profile_user_controller(nullptr); + user_manager_->set_multi_user_sign_in_policy_controller(nullptr); controller_.reset(); user_manager_.Reset(); @@ -218,7 +220,7 @@ ash::SessionTerminationManager session_termination_manager_; content::BrowserTaskEnvironment task_environment_; user_manager::TypedScopedUserManager<TestChromeUserManager> user_manager_; - std::unique_ptr<ash::MultiProfileUserController> controller_; + std::unique_ptr<user_manager::MultiUserSignInPolicyController> controller_; std::unique_ptr<AssistantBrowserDelegateImpl> assistant_delegate_; std::unique_ptr<TestingProfileManager> profile_manager_; std::unique_ptr<crosapi::FakeBrowserManager> browser_manager_;
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc index 1fe7185f..9e355a98 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc +++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -143,49 +143,25 @@ CHECK(picture_in_picture_window_manager); picture_in_picture_window_observation_.Observe( picture_in_picture_window_manager); -#if !BUILDFLAG(IS_ANDROID) - // There may not always be a ZoomController, e.g., in tests. - if (auto* zoom_controller = - zoom::ZoomController::FromWebContents(web_contents)) { - zoom_observation_.Observe(zoom_controller); - } -#endif + // The hide helper is destroyed on hide, so it cannot outlive the popup + // controller. + // TODO(b/320632147): Move this into show and remove the call to + // `CreatePopupHideHelper()` from tests. + CreatePopupHideHelper(web_contents, + base::BindRepeating(&AutofillPopupControllerImpl::Hide, + base::Unretained(this))); } AutofillPopupControllerImpl::~AutofillPopupControllerImpl() = default; -void AutofillPopupControllerImpl::WebContentsDestroyed() { - Hide(PopupHidingReason::kTabGone); +void AutofillPopupControllerImpl::CreatePopupHideHelper( + content::WebContents* web_contents, + AutofillPopupHideHelper::HidingCallback hiding_callback) { + popup_hide_helper_ = std::make_unique<AutofillPopupHideHelper>( + web_contents, AutofillPopupHideHelper::HidingParams{}, + std::move(hiding_callback)); } -void AutofillPopupControllerImpl::OnWebContentsLostFocus( - content::RenderWidgetHost* render_widget_host) { - Hide(PopupHidingReason::kFocusChanged); -} - -void AutofillPopupControllerImpl::PrimaryMainFrameWasResized( - bool width_changed) { -#if BUILDFLAG(IS_ANDROID) - // Ignore virtual keyboard showing and hiding a strip of suggestions. - if (!width_changed) { - return; - } -#endif - Hide(PopupHidingReason::kWidgetChanged); -} - -#if !BUILDFLAG(IS_ANDROID) -void AutofillPopupControllerImpl::OnZoomControllerDestroyed( - zoom::ZoomController* source) { - zoom_observation_.Reset(); -} - -void AutofillPopupControllerImpl::OnZoomChanged( - const zoom::ZoomController::ZoomChangedEventData& data) { - Hide(PopupHidingReason::kContentAreaMoved); -} -#endif // !BUILDFLAG(IS_ANDROID) - void AutofillPopupControllerImpl::RenderFrameDeleted( content::RenderFrameHost* rfh) { // If the popup menu has been triggered from within an iframe and that frame @@ -207,13 +183,6 @@ } } -void AutofillPopupControllerImpl::OnVisibilityChanged( - content::Visibility visibility) { - if (visibility == content::Visibility::HIDDEN) { - Hide(PopupHidingReason::kTabGone); - } -} - void AutofillPopupControllerImpl::OnBeforeTextFieldDidChange( AutofillManager& manager, FormGlobalId form, @@ -386,6 +355,7 @@ } key_press_observer_.Reset(); autofill_managers_observation_.Reset(); + popup_hide_helper_.reset(); AutofillMetrics::LogAutofillPopupHidingReason(reason); HideViewAndDie(); }
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h index 5c0fe0bd..f86d75d8 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h +++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
@@ -15,6 +15,7 @@ #include "base/time/time.h" #include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h" #include "chrome/browser/ui/autofill/autofill_popup_controller.h" +#include "chrome/browser/ui/autofill/autofill_popup_hide_helper.h" #include "chrome/browser/ui/autofill/next_idle_time_ticks.h" #include "chrome/browser/ui/autofill/popup_controller_common.h" #include "components/autofill/content/browser/scoped_autofill_managers_observation.h" @@ -76,9 +77,6 @@ class AutofillPopupControllerImpl : public AutofillPopupController, public content::WebContentsObserver, -#if !BUILDFLAG(IS_ANDROID) - public zoom::ZoomObserver, -#endif // !BUILDFLAG(IS_ANDROID) public AutofillManager::Observer, public PictureInPictureWindowManager::Observer, public ExpandablePopupParentControllerImpl { @@ -185,6 +183,10 @@ std::optional<base::WeakPtr<ExpandablePopupParentControllerImpl>> parent); ~AutofillPopupControllerImpl() override; + void CreatePopupHideHelper( + content::WebContents* web_contents, + AutofillPopupHideHelper::HidingCallback hiding_callback); + gfx::NativeView container_view() const override; content::WebContents* GetWebContents() const override; const gfx::RectF& element_bounds() const override; @@ -214,21 +216,9 @@ private: // content::WebContentsObserver: - void WebContentsDestroyed() override; - void OnWebContentsLostFocus( - content::RenderWidgetHost* render_widget_host) override; - void PrimaryMainFrameWasResized(bool width_changed) override; void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; void DidFinishNavigation( content::NavigationHandle* navigation_handle) override; - void OnVisibilityChanged(content::Visibility visibility) override; - -#if !BUILDFLAG(IS_ANDROID) - // ZoomObserver: - void OnZoomControllerDestroyed(zoom::ZoomController* source) override; - void OnZoomChanged( - const zoom::ZoomController::ZoomChangedEventData& data) override; -#endif // AutofillManager::Observer: void OnBeforeTextFieldDidChange(AutofillManager& manager, @@ -298,11 +288,6 @@ // the machine that would normally cause the popup to be hidden. bool keep_popup_open_for_testing_ = false; -#if !BUILDFLAG(IS_ANDROID) - base::ScopedObservation<zoom::ZoomController, zoom::ZoomObserver> - zoom_observation_{this}; -#endif - // Observer needed to check autofill popup overlap with picture-in-picture // window. It is guaranteed that there can only be one // PictureInPictureWindowManager per Chrome instance, therefore, it is also @@ -333,6 +318,9 @@ // The open sub-popup controller if any, `nullptr` otherwise. base::WeakPtr<AutofillPopupControllerImpl> sub_popup_controller_; + // This is a helper which detects events that should hide the popup. + std::unique_ptr<AutofillPopupHideHelper> popup_hide_helper_; + // AutofillPopupControllerImpl deletes itself. To simplify memory management, // we delete the object asynchronously. base::WeakPtrFactory<AutofillPopupControllerImpl>
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc index b6a7fa6..da6c3428 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc +++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc
@@ -197,7 +197,15 @@ element_bounds, base::i18n::UNKNOWN_DIRECTION, std::move(show_pwd_migration_warning_callback), - parent) {} + parent) { + // This is done in order to set the callback to + // `TestAutofillPopupController::Hide` (which is mocked below). Otherwise, + // it would be set to `AutofillPopupController::Hide()`, which is not + // mocked. + CreatePopupHideHelper( + web_contents, base::BindRepeating(&TestAutofillPopupController::Hide, + base::Unretained(this))); + } ~TestAutofillPopupController() override = default; // Making protected functions public for testing @@ -1632,9 +1640,11 @@ // Triggered by OnZoomChanged(). EXPECT_CALL(client().popup_controller(manager()), Hide(PopupHidingReason::kContentAreaMoved)); - // Triggered by PrimaryMainFrameWasResized(). + // Override the default ON_CALL behavior to do nothing to avoid destroying the + // hide helper. We want to test ZoomObserver events explicitly. EXPECT_CALL(client().popup_controller(manager()), - Hide(PopupHidingReason::kWidgetChanged)); + Hide(PopupHidingReason::kWidgetChanged)) + .WillOnce(Return()); auto* zoom_controller = zoom::ZoomController::FromWebContents(web_contents()); zoom_controller->SetZoomLevel(zoom_controller->GetZoomLevel() + 1.0); // Verify and clear before TearDown() closes the popup.
diff --git a/chrome/browser/ui/autofill/autofill_popup_hide_helper.cc b/chrome/browser/ui/autofill/autofill_popup_hide_helper.cc new file mode 100644 index 0000000..12e1394 --- /dev/null +++ b/chrome/browser/ui/autofill/autofill_popup_hide_helper.cc
@@ -0,0 +1,70 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/autofill/autofill_popup_hide_helper.h" + +#include "components/autofill/core/browser/ui/popup_hiding_reasons.h" +#include "content/public/browser/render_widget_host.h" +#include "content/public/browser/visibility.h" +#include "content/public/browser/web_contents.h" + +namespace autofill { + +AutofillPopupHideHelper::AutofillPopupHideHelper( + content::WebContents* web_contents, + HidingParams hiding_params, + HidingCallback hiding_callback) + : content::WebContentsObserver(web_contents), + hiding_params_(hiding_params) { + hiding_callback_ = std::move(hiding_callback); +#if !BUILDFLAG(IS_ANDROID) + // There may not always be a ZoomController, e.g., in tests. + if (auto* zoom_controller = + zoom::ZoomController::FromWebContents(web_contents)) { + zoom_observation_.Observe(zoom_controller); + } +#endif // !BUILDFLAG(IS_ANDROID) +} + +AutofillPopupHideHelper::~AutofillPopupHideHelper() = default; + +void AutofillPopupHideHelper::WebContentsDestroyed() { + hiding_callback_.Run(PopupHidingReason::kTabGone); +} + +void AutofillPopupHideHelper::OnWebContentsLostFocus( + content::RenderWidgetHost* render_widget_host) { + hiding_callback_.Run(PopupHidingReason::kFocusChanged); +} + +void AutofillPopupHideHelper::PrimaryMainFrameWasResized(bool width_changed) { + if constexpr (BUILDFLAG(IS_ANDROID)) { + // Ignore virtual keyboard showing and hiding a strip of suggestions. + if (!width_changed) { + return; + } + } + hiding_callback_.Run(PopupHidingReason::kWidgetChanged); +} + +void AutofillPopupHideHelper::OnVisibilityChanged( + content::Visibility visibility) { + if (visibility == content::Visibility::HIDDEN) { + hiding_callback_.Run(PopupHidingReason::kTabGone); + } +} + +#if !BUILDFLAG(IS_ANDROID) +void AutofillPopupHideHelper::OnZoomControllerDestroyed( + zoom::ZoomController* source) { + zoom_observation_.Reset(); +} + +void AutofillPopupHideHelper::OnZoomChanged( + const zoom::ZoomController::ZoomChangedEventData& data) { + hiding_callback_.Run(PopupHidingReason::kContentAreaMoved); +} +#endif // !BUILDFLAG(IS_ANDROID) + +} // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_popup_hide_helper.h b/chrome/browser/ui/autofill/autofill_popup_hide_helper.h new file mode 100644 index 0000000..5e288ef --- /dev/null +++ b/chrome/browser/ui/autofill/autofill_popup_hide_helper.h
@@ -0,0 +1,81 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_HIDE_HELPER_H_ +#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_HIDE_HELPER_H_ + +#include "base/functional/bind.h" +#include "base/scoped_observation.h" +#include "content/public/browser/web_contents_observer.h" +#if !BUILDFLAG(IS_ANDROID) +#include "components/zoom/zoom_observer.h" +#endif // BUILDFLAG(IS_ANDROID) + +namespace content { +class RenderWidgetHost; +enum class Visibility; +class WebContents; +} // namespace content + +namespace autofill { + +enum class PopupHidingReason; + +// AutofillPopupHideHelper is a class which detects events that should hide an +// Autofill Popup or any class that should have the same hiding behavior. The +// popup passes a `HidingCallback` in the constructor of the hiding helper, +// which will be called when a hiding event occurs. Note that some hiding events +// cannot be observed by this class because they are specific to the renderer, +// to suggestions, etc. +class AutofillPopupHideHelper : public content::WebContentsObserver +#if !BUILDFLAG(IS_ANDROID) + , + public zoom::ZoomObserver +#endif // !BUILDFLAG(IS_ANDROID) +{ + public: + // This is a `RepeatingCallback` because multiple hiding events can occur at + // the same time. + using HidingCallback = base::RepeatingCallback<void(PopupHidingReason)>; + + // This struct configures what type of events the helper should call the + // `hiding_callback_`. + struct HidingParams { + // TODO(b/320632147): Add parameters. + }; + + AutofillPopupHideHelper(content::WebContents* web_contents, + HidingParams hiding_params, + HidingCallback hiding_callback); + AutofillPopupHideHelper(const AutofillPopupHideHelper&) = delete; + AutofillPopupHideHelper& operator=(const AutofillPopupHideHelper&) = delete; + ~AutofillPopupHideHelper() override; + + private: + // content::WebContentsObserver: + void WebContentsDestroyed() override; + void OnWebContentsLostFocus( + content::RenderWidgetHost* render_widget_host) override; + void PrimaryMainFrameWasResized(bool width_changed) override; + void OnVisibilityChanged(content::Visibility visibility) override; + +#if !BUILDFLAG(IS_ANDROID) + // ZoomObserver: + void OnZoomControllerDestroyed(zoom::ZoomController* source) override; + void OnZoomChanged( + const zoom::ZoomController::ZoomChangedEventData& data) override; +#endif + + HidingCallback hiding_callback_; + HidingParams hiding_params_; + +#if !BUILDFLAG(IS_ANDROID) + base::ScopedObservation<zoom::ZoomController, zoom::ZoomObserver> + zoom_observation_{this}; +#endif +}; + +} // namespace autofill + +#endif // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_HIDE_HELPER_H_
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index 5664d44..b1a42ad 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc
@@ -40,7 +40,6 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/chrome_pages.h" -#include "chrome/browser/ui/commander/commander.h" #include "chrome/browser/ui/managed_ui.h" #include "chrome/browser/ui/page_info/page_info_dialog.h" #include "chrome/browser/ui/passwords/ui_utils.h" @@ -959,9 +958,6 @@ case IDC_SHOW_BETA_FORUM: ShowBetaForum(browser_); break; - case IDC_TOGGLE_QUICK_COMMANDS: - ToggleCommander(browser_); - break; case IDC_DISTILL_PAGE: ToggleDistilledView(browser_); break; @@ -1337,8 +1333,6 @@ IDC_SHOW_SAVE_LOCAL_CARD_SIGN_IN_PROMO_IF_APPLICABLE, true); command_updater_.UpdateCommandEnabled(IDC_CLOSE_SIGN_IN_PROMO, true); command_updater_.UpdateCommandEnabled(IDC_CARET_BROWSING_TOGGLE, true); - command_updater_.UpdateCommandEnabled(IDC_TOGGLE_QUICK_COMMANDS, - commander::IsEnabled()); // Navigation commands command_updater_.UpdateCommandEnabled( IDC_HOME, normal_window || browser_->is_type_app() ||
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index 65c2e5a..55c3a7e 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc
@@ -72,7 +72,6 @@ #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/chrome_pages.h" -#include "chrome/browser/ui/commander/commander.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/find_bar/find_bar.h" @@ -2132,10 +2131,6 @@ } #endif -void ToggleCommander(Browser* browser) { - commander::Commander::Get()->ToggleForBrowser(browser); -} - #if !defined(TOOLKIT_VIEWS) std::optional<int> GetKeyboardFocusedTabIndex(const Browser* browser) { return std::nullopt;
diff --git a/chrome/browser/ui/browser_commands.h b/chrome/browser/ui/browser_commands.h index 18a23b7..c4aff62 100644 --- a/chrome/browser/ui/browser_commands.h +++ b/chrome/browser/ui/browser_commands.h
@@ -254,7 +254,6 @@ #if BUILDFLAG(IS_CHROMEOS) void ToggleMultitaskMenu(Browser* browser); #endif -void ToggleCommander(Browser* browser); void ExecuteUIDebugCommand(int id, const Browser* browser); std::optional<int> GetKeyboardFocusedTabIndex(const Browser* browser);
diff --git a/chrome/browser/ui/chromeos/DEPS b/chrome/browser/ui/chromeos/DEPS new file mode 100644 index 0000000..3355c59 --- /dev/null +++ b/chrome/browser/ui/chromeos/DEPS
@@ -0,0 +1,6 @@ +specific_include_rules = { + "test_util\.cc": [ + "+ash", + "+chrome/browser/ui/views", + ], +}
diff --git a/chrome/browser/ui/chromeos/test_util.cc b/chrome/browser/ui/chromeos/test_util.cc new file mode 100644 index 0000000..51ab1a5 --- /dev/null +++ b/chrome/browser/ui/chromeos/test_util.cc
@@ -0,0 +1,303 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/chromeos/test_util.h" + +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/chromeos/window_pin_util.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" +#include "chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/frame/immersive_mode_controller.h" +#include "chrome/browser/ui/views/frame/immersive_mode_tester.h" +#include "chrome/test/base/ui_test_utils.h" +#include "chromeos/ui/base/window_properties.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_delegate.h" +#include "third_party/blink/public/mojom/frame/fullscreen.mojom.h" +#include "ui/aura/window.h" +#include "ui/display/screen.h" +#include "ui/views/test/widget_test.h" +#include "ui/views/widget/widget.h" + +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "ash/constants/ash_switches.h" +#include "ash/public/cpp/shelf_test_api.h" +#include "ash/public/cpp/split_view_test_api.h" +#include "ash/shell.h" +#include "ash/wm/overview/overview_controller.h" +#include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h" +#include "chrome/browser/ash/crosapi/test_controller_ash.h" +#else // BUILDFLAG(IS_CHROMEOS_LACROS) +#include "base/functional/callback_helpers.h" +#include "base/run_loop.h" +#include "base/test/run_until.h" +#include "chrome/browser/ui/lacros/window_properties.h" +#include "chrome/browser/ui/lacros/window_utility.h" +#include "chromeos/crosapi/mojom/test_controller.mojom-test-utils.h" +#include "chromeos/lacros/lacros_service.h" +#include "ui/display/display_observer.h" +#endif + +namespace { +#if BUILDFLAG(IS_CHROMEOS_LACROS) + +bool IsCrosApiSupported(uint32_t min_version) { + return chromeos::LacrosService::Get() + ->GetInterfaceVersion<crosapi::mojom::TestController>() >= + static_cast<int>(min_version); +} + +chromeos::WindowStateType WindowStateTypeFromSnapPosition( + crosapi::mojom::SnapPosition position) { + switch (position) { + case crosapi::mojom::SnapPosition::kPrimary: + return chromeos::WindowStateType::kPrimarySnapped; + case crosapi::mojom::SnapPosition::kSecondary: + return chromeos::WindowStateType::kSecondarySnapped; + } +} + +// Runs the specified callback when a change to tablet state is detected. +// TODO(b/323790202): Make this more robust. +class TabletModeWatcher : public display::DisplayObserver { + public: + explicit TabletModeWatcher(base::RepeatingClosure cb, + display::TabletState current_tablet_state) + : cb_(cb), current_tablet_state_(current_tablet_state) {} + void OnDisplayTabletStateChanged(display::TabletState state) override { + // Skip if the notified TabletState is same as the current state. + // This required since it may notify the current tablet state when the + // observer is added (e.g. WaylandScreen::AddObserver()). In such cases, we + // need to ignore the initial notification so that we can only catch + // meaningful notifications for testing. + if (current_tablet_state_ == state) { + return; + } + + cb_.Run(); + } + + private: + base::RepeatingClosure cb_; + display::TabletState current_tablet_state_; +}; + +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) +} // namespace + +void ChromeOSBrowserUITest::SetUpDefaultCommandLine( + base::CommandLine* command_line) { + InProcessBrowserTest::SetUpDefaultCommandLine(command_line); +#if BUILDFLAG(IS_CHROMEOS_ASH) + command_line->AppendSwitch(ash::switches::kAshEnableTabletMode); +#endif +} + +void ChromeOSBrowserUITest::TearDownOnMainThread() { + if (InTabletMode()) { + ExitTabletMode(); + } + InProcessBrowserTest::TearDownOnMainThread(); +} + +bool ChromeOSBrowserUITest::InTabletMode() { + return display::Screen::GetScreen()->InTabletMode(); +} + +void ChromeOSBrowserUITest::EnterTabletMode() { + SetTabletMode(true); +} + +void ChromeOSBrowserUITest::ExitTabletMode() { + SetTabletMode(false); +} + +void ChromeOSBrowserUITest::SetTabletMode(bool enable) { + CHECK_NE(InTabletMode(), enable); +#if BUILDFLAG(IS_CHROMEOS_ASH) + if (enable) { + ash::TabletModeControllerTestApi().EnterTabletMode(); + } else { + ash::TabletModeControllerTestApi().LeaveTabletMode(); + } +#elif BUILDFLAG(IS_CHROMEOS_LACROS) + base::RunLoop run_loop; + TabletModeWatcher watcher(run_loop.QuitClosure(), + display::Screen::GetScreen()->GetTabletState()); + display::Screen::GetScreen()->AddObserver(&watcher); + auto& test_controller = chromeos::LacrosService::Get() + ->GetRemote<crosapi::mojom::TestController>(); + auto waiter = + crosapi::mojom::TestControllerAsyncWaiter(test_controller.get()); + if (enable) { + waiter.EnterTabletMode(); + } else { + waiter.ExitTabletMode(); + } + run_loop.Run(); + display::Screen::GetScreen()->RemoveObserver(&watcher); +#endif + CHECK_EQ(InTabletMode(), enable); +} + +void ChromeOSBrowserUITest::EnterOverviewMode() { + SetOverviewMode(true); +} + +void ChromeOSBrowserUITest::ExitOverviewMode() { + SetOverviewMode(false); +} + +void ChromeOSBrowserUITest::SetOverviewMode(bool enable) { +#if BUILDFLAG(IS_CHROMEOS_ASH) + if (enable) { + ash::Shell::Get()->overview_controller()->StartOverview( + ash::OverviewStartAction::kTests); + } else { + ash::Shell::Get()->overview_controller()->EndOverview( + ash::OverviewEndAction::kTests); + } +#elif BUILDFLAG(IS_CHROMEOS_LACROS) + auto& test_controller = chromeos::LacrosService::Get() + ->GetRemote<crosapi::mojom::TestController>(); + auto waiter = + crosapi::mojom::TestControllerAsyncWaiter(test_controller.get()); + if (enable) { + waiter.EnterOverviewMode(); + } else { + waiter.ExitOverviewMode(); + } +#endif +} + +bool ChromeOSBrowserUITest::IsSnapWindowSupported() { +#if BUILDFLAG(IS_CHROMEOS_ASH) + return true; +#else + return IsCrosApiSupported( + crosapi::mojom::TestController::MethodMinVersions::kSnapWindowMinVersion); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) +} + +void ChromeOSBrowserUITest::SnapWindow(aura::Window* window, + crosapi::mojom::SnapPosition position) { + CHECK(IsSnapWindowSupported()); +#if BUILDFLAG(IS_CHROMEOS_ASH) + ash::SplitViewTestApi().SnapWindow( + window, mojo::ConvertTo<ash::SnapPosition>(position)); +#else // BUILDFLAG(IS_CHROMEOS_LACROS) + auto& test_controller = chromeos::LacrosService::Get() + ->GetRemote<crosapi::mojom::TestController>(); + crosapi::mojom::TestControllerAsyncWaiter(test_controller.get()) + .SnapWindow(lacros_window_utility::GetRootWindowUniqueId(window), + position); + auto expected_state = WindowStateTypeFromSnapPosition(position); + ASSERT_TRUE(base::test::RunUntil([&]() { + return window->GetProperty(chromeos::kWindowStateTypeKey) == expected_state; + })); +#endif +} + +void ChromeOSBrowserUITest::PinWindow(aura::Window* window, bool trusted) { + ::PinWindow(window, trusted); +#if BUILDFLAG(IS_CHROMEOS_LACROS) + auto expected_type = trusted ? chromeos::WindowPinType::kTrustedPinned + : chromeos::WindowPinType::kPinned; + ASSERT_TRUE(base::test::RunUntil([&]() { + return window->GetProperty(lacros::kWindowPinTypeKey) == expected_type; + })); +#endif +} + +bool ChromeOSBrowserUITest::IsIsShelfVisibleSupported() { +#if BUILDFLAG(IS_CHROMEOS_ASH) + return true; +#else // BUILDFLAG(IS_CHROMEOS_LACROS) + return IsCrosApiSupported(crosapi::mojom::TestController::MethodMinVersions:: + kIsShelfVisibleMinVersion); +#endif +} + +bool ChromeOSBrowserUITest::IsShelfVisible() { + CHECK(IsIsShelfVisibleSupported()); +#if BUILDFLAG(IS_CHROMEOS_ASH) + return ash::ShelfTestApi().IsVisible(); +#else // BUILDFLAG(IS_CHROMEOS_LACROS) + auto& test_controller = chromeos::LacrosService::Get() + ->GetRemote<crosapi::mojom::TestController>(); + return crosapi::mojom::TestControllerAsyncWaiter(test_controller.get()) + .IsShelfVisible(); +#endif +} + +void ChromeOSBrowserUITest::DeactivateWidget(views::Widget* widget) { +#if BUILDFLAG(IS_CHROMEOS_LACROS) + views::test::WidgetActivationWaiter waiter(widget, false); +#endif + widget->Deactivate(); +#if BUILDFLAG(IS_CHROMEOS_LACROS) + waiter.Wait(); +#endif +} + +void ChromeOSBrowserUITest::EnterImmersiveFullscreenMode(Browser* browser) { + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); + ASSERT_FALSE(browser_view->IsFullscreen()); + + ImmersiveModeController* immersive_mode_controller = + browser_view->immersive_mode_controller(); + ASSERT_FALSE(immersive_mode_controller->IsEnabled()); + + ui_test_utils::ToggleFullscreenModeAndWait(browser); + // TODO(crbug.com/1501757): Simplify waiting once the two states are merged. + ImmersiveModeTester(browser).WaitForFullscreenToEnter(); + ASSERT_TRUE(immersive_mode_controller->IsEnabled()); + ASSERT_TRUE(browser_view->IsFullscreen()); +} + +void ChromeOSBrowserUITest::ExitImmersiveFullscreenMode(Browser* browser) { + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); + ASSERT_TRUE(browser_view->IsFullscreen()); + + ImmersiveModeController* immersive_mode_controller = + browser_view->immersive_mode_controller(); + ASSERT_TRUE(immersive_mode_controller->IsEnabled()); + + ui_test_utils::ToggleFullscreenModeAndWait(browser); + // TODO(crbug.com/1501757): Simplify waiting once the two states are merged. + ImmersiveModeTester(browser).WaitForFullscreenToExit(); + ASSERT_FALSE(immersive_mode_controller->IsEnabled()); + ASSERT_FALSE(browser_view->IsFullscreen()); +} + +void ChromeOSBrowserUITest::EnterTabFullscreenMode( + Browser* browser, + content::WebContents* web_contents) { + ui_test_utils::FullscreenWaiter waiter(browser, {.tab_fullscreen = true}); + static_cast<content::WebContentsDelegate*>(browser) + ->EnterFullscreenModeForTab(web_contents->GetPrimaryMainFrame(), {}); + waiter.Wait(); +} + +void ChromeOSBrowserUITest::ExitTabFullscreenMode( + Browser* browser, + content::WebContents* web_contents) { + ui_test_utils::FullscreenWaiter waiter(browser, {.tab_fullscreen = false}); + browser->exclusive_access_manager() + ->fullscreen_controller() + ->ExitFullscreenModeForTab(web_contents); + waiter.Wait(); +} + +BrowserNonClientFrameViewChromeOS* ChromeOSBrowserUITest::GetFrameViewChromeOS( + BrowserView* browser_view) { + // We know we're using ChromeOS, so static cast. + auto* frame_view = static_cast<BrowserNonClientFrameViewChromeOS*>( + browser_view->GetWidget()->non_client_view()->frame_view()); + DCHECK(frame_view); + return frame_view; +}
diff --git a/chrome/browser/ui/chromeos/test_util.h b/chrome/browser/ui/chromeos/test_util.h new file mode 100644 index 0000000..ff86547 --- /dev/null +++ b/chrome/browser/ui/chromeos/test_util.h
@@ -0,0 +1,92 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_CHROMEOS_TEST_UTIL_H_ +#define CHROME_BROWSER_UI_CHROMEOS_TEST_UTIL_H_ + +#include "base/test/test_future.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chromeos/crosapi/mojom/test_controller.mojom.h" +#include "chromeos/ui/base/window_state_type.h" +#include "ui/aura/window.h" +#include "ui/aura/window_observer.h" + +class Browser; +class BrowserNonClientFrameViewChromeOS; +class BrowserView; + +namespace views { +class Widget; +} + +// This class is meant primarily for writing UI-centric ChromeOS browser tests +// that work for both Ash and Lacros(*), and in the latter case do so by using +// crosapi's TestController behind the scenes to perform system-level UI actions +// such as toggling tablet mode. +// +// (*) Typically, these tests are built into the `browser_tests` target for Ash, +// and into the `lacros_chrome_browsertests` target for Lacros. +class ChromeOSBrowserUITest : public InProcessBrowserTest { + public: + ChromeOSBrowserUITest() = default; + ChromeOSBrowserUITest(const ChromeOSBrowserUITest&) = delete; + ChromeOSBrowserUITest& operator=(const ChromeOSBrowserUITest&) = delete; + ~ChromeOSBrowserUITest() override = default; + + // InProcessBrowserTest: + void SetUpDefaultCommandLine(base::CommandLine* command_line) override; + void TearDownOnMainThread() override; + + // Checks whether the ChromeOS UI is currently in tablet mode (as opposed to + // clamshell mode). + static bool InTabletMode(); + + // Makes the ChromeOS UI enter/exit tablet mode. + void EnterTabletMode(); + void ExitTabletMode(); + + // Makes the ChromeOS UI enter/exit overview mode. + static void EnterOverviewMode(); + static void ExitOverviewMode(); + + // Checks whether the `SnapWindow` method can be called. + static bool IsSnapWindowSupported(); + + // Snaps the given window to the given part of the screen + static void SnapWindow(aura::Window* window, + crosapi::mojom::SnapPosition position); + + // Pins the given window. This is also known as locked fullscreen mode. + static void PinWindow(aura::Window* window, bool trusted); + + // Checks whether the `IsShelfVisible` method can be called. + static bool IsIsShelfVisibleSupported(); + + // Checks whether the ChromeOS UI currently shows the shelf (on the primary + // display). + static bool IsShelfVisible(); + + // Deactivates the given widget. + static void DeactivateWidget(views::Widget* widget); + + // Enters/exits immersive fullscreen mode for the given browser. + static void EnterImmersiveFullscreenMode(Browser* browser); + static void ExitImmersiveFullscreenMode(Browser* browser); + + // Enters/exits fullscreen mode in th tab associated with the given contents. + static void EnterTabFullscreenMode(Browser* browser, + content::WebContents* web_contents); + static void ExitTabFullscreenMode(Browser* browser, + content::WebContents* web_contents); + + // Returns the non-client frame view for `browser_view`. + static BrowserNonClientFrameViewChromeOS* GetFrameViewChromeOS( + BrowserView* browser_view); + + private: + void SetTabletMode(bool enabled); + static void SetOverviewMode(bool enabled); +}; + +#endif // CHROME_BROWSER_UI_CHROMEOS_TEST_UTIL_H_
diff --git a/chrome/browser/ui/cocoa/accelerators_cocoa.mm b/chrome/browser/ui/cocoa/accelerators_cocoa.mm index 243f90e6..ae8ca2f 100644 --- a/chrome/browser/ui/cocoa/accelerators_cocoa.mm +++ b/chrome/browser/ui/cocoa/accelerators_cocoa.mm
@@ -15,7 +15,6 @@ #include "base/memory/singleton.h" #include "build/branding_buildflags.h" #include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/ui/commander/commander.h" #include "printing/buildflags/buildflags.h" #import "ui/base/accelerators/platform_accelerator_cocoa.h" #import "ui/events/cocoa/cocoa_event_utils.h" @@ -139,13 +138,6 @@ std::make_pair(IDC_FULLSCREEN, enterFullscreenAccelerator())); DCHECK(result.second); - if (commander::IsEnabled()) { - result = accelerators_.insert( - std::make_pair(IDC_TOGGLE_QUICK_COMMANDS, - ui::Accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN))); - DCHECK(result.second); - } - if (!base::i18n::IsRTL()) return;
diff --git a/chrome/browser/ui/cocoa/main_menu_builder.mm b/chrome/browser/ui/cocoa/main_menu_builder.mm index f452616..2a5365a 100644 --- a/chrome/browser/ui/cocoa/main_menu_builder.mm +++ b/chrome/browser/ui/cocoa/main_menu_builder.mm
@@ -10,7 +10,6 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/ui/cocoa/accelerators_cocoa.h" #include "chrome/browser/ui/cocoa/history_menu_bridge.h" -#include "chrome/browser/ui/commander/commander.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/common/chrome_features.h" #include "chrome/grit/branded_strings.h" @@ -315,9 +314,6 @@ Item(IDS_DISTILL_PAGE) .command_id(IDC_DISTILL_PAGE) .remove_if(!dom_distiller::IsDomDistillerEnabled()), - Item(IDS_TOGGLE_QUICK_COMMANDS) - .command_id(IDC_TOGGLE_QUICK_COMMANDS) - .remove_if(!commander::IsEnabled()), Item().is_separator(), Item(IDS_DEVELOPER_MENU_MAC) .tag(IDC_DEVELOPER_MENU)
diff --git a/chrome/browser/ui/cocoa/screentime/README.md b/chrome/browser/ui/cocoa/screentime/README.md deleted file mode 100644 index 884e0ffc..0000000 --- a/chrome/browser/ui/cocoa/screentime/README.md +++ /dev/null
@@ -1,34 +0,0 @@ -# Screen Time - -This directory contains the integration between Chromium and the macOS -ScreenTime system, which is a digital wellbeing tool allowing users to restrict -their own use of apps and websites by category. ScreenTime was introduced in -macOS 11, but we only support it for macOS 12.1+ due to an -[issue with input handling](https://crbug.com/1202440). - -The ScreenTime system API is documented [on -apple.com](https://developer.apple.com/documentation/screentime?language=objc). -The most pertinent class is `STWebpageController`, which is an -`NSViewController` subclass. Clients of ScreenTime construct a single -`STWebpageController` per tab and splice its corresponding NSView into their -view tree in such a way that it covers the web contents. The NSView becomes -opaque when screen time for that tab or website has been used up. - -The public interface to ScreenTime within Chromium is the -`screentime::TabHelper` class, which is a -[TabHelper](../../../../../docs/tab_helpers.md) that binds an -STWebpageController to a WebContents. - -There is also a key private class, called `screentime::HistoryBridge`, which -connects a -[HistoryService](../../../../../components/history/core/browser/history_service.h) -to the ScreenTime history deletion controller. HistoryBridge is a profile-keyed -service, so one exists for each Profile. - -## Testing - -So that tests can avoid depending on the real ScreenTime system, -`STWebpageController` is wrapped by a C++ class called -`screentime::WebpageController`, which has a testing fake called -`screentime::FakeWebpageController`, and `STWebHistory` is wrapped by a C++ -class called `screentime::HistoryDeleter`.
diff --git a/chrome/browser/ui/cocoa/screentime/fake_webpage_controller.h b/chrome/browser/ui/cocoa/screentime/fake_webpage_controller.h deleted file mode 100644 index 2d648c7a..0000000 --- a/chrome/browser/ui/cocoa/screentime/fake_webpage_controller.h +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_SCREENTIME_FAKE_WEBPAGE_CONTROLLER_H_ -#define CHROME_BROWSER_UI_COCOA_SCREENTIME_FAKE_WEBPAGE_CONTROLLER_H_ - -#include <vector> - -#include "chrome/browser/ui/cocoa/screentime/webpage_controller.h" - -namespace screentime { - -// An implementation of WebpageController that is not backed by the real -// ScreenTime framework. This is used for testing and development on pre-11.0 -// devices that don't have the real ScreenTime API available. -// -// FakeWebpageController implements the following behavior: -// 1. The ScreenTime "shield" view is a flat blue layer -// 2. Every navigation causes it to toggle blocking / not blocking state -// -// Further testing hooks may be added to this class in future. -class FakeWebpageController : public WebpageController { - public: - FakeWebpageController(const BlockedChangedCallback& callback); - ~FakeWebpageController() override; - - NSView* GetView() override; - void PageURLChangedTo(const GURL& url) override; - - const std::vector<GURL>& visited_urls_for_testing() const { - return visited_urls_; - } - - private: - bool enabled_ = false; - NSView* __strong view_; - BlockedChangedCallback blocked_changed_callback_; - - // For unit tests: - std::vector<GURL> visited_urls_; -}; - -} // namespace screentime - -#endif // CHROME_BROWSER_UI_COCOA_SCREENTIME_FAKE_WEBPAGE_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/screentime/fake_webpage_controller.mm b/chrome/browser/ui/cocoa/screentime/fake_webpage_controller.mm deleted file mode 100644 index e1746e1..0000000 --- a/chrome/browser/ui/cocoa/screentime/fake_webpage_controller.mm +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/cocoa/screentime/fake_webpage_controller.h" - -#import <Cocoa/Cocoa.h> - -namespace { - -NSView* MakeView(bool enabled) { - NSView* view = [[NSView alloc] init]; - view.wantsLayer = YES; - view.layer.backgroundColor = NSColor.blueColor.CGColor; - view.hidden = !enabled; - return view; -} - -} // namespace - -namespace screentime { - -FakeWebpageController::FakeWebpageController( - const BlockedChangedCallback& blocked_changed_callback) - : view_(MakeView(enabled_)), - blocked_changed_callback_(blocked_changed_callback) {} -FakeWebpageController::~FakeWebpageController() = default; - -NSView* FakeWebpageController::GetView() { - return view_; -} - -void FakeWebpageController::PageURLChangedTo(const GURL& url) { - visited_urls_.push_back(url); - - enabled_ = !enabled_; - [view_ setHidden:!enabled_]; - blocked_changed_callback_.Run(enabled_); -} - -} // namespace screentime
diff --git a/chrome/browser/ui/cocoa/screentime/history_bridge.h b/chrome/browser/ui/cocoa/screentime/history_bridge.h deleted file mode 100644 index 74c5f43..0000000 --- a/chrome/browser/ui/cocoa/screentime/history_bridge.h +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_SCREENTIME_HISTORY_BRIDGE_H_ -#define CHROME_BROWSER_UI_COCOA_SCREENTIME_HISTORY_BRIDGE_H_ - -#include "base/scoped_observation.h" -#include "components/history/core/browser/history_service.h" -#include "components/history/core/browser/history_service_observer.h" -#include "components/keyed_service/core/keyed_service.h" - -namespace screentime { - -class HistoryDeleter; - -// A HistoryBridge connects a HistoryService to a HistoryDeleter, which wraps -// the system ScreenTime backend. HistoryBridge is responsible for observing -// deletions of part or all of the history in a HistoryService and deleting the -// corresponding history from ScreenTime. It passes these to the provided -// HistoryDeleter, which proxies to the system API (when in production use) or -// to a test fake. -class HistoryBridge : public KeyedService, - public history::HistoryServiceObserver { - public: - HistoryBridge(history::HistoryService* history_service, - std::unique_ptr<HistoryDeleter> deleter); - HistoryBridge(const HistoryBridge& other) = delete; - HistoryBridge& operator=(const HistoryBridge& other) = delete; - ~HistoryBridge() override; - - // history::HistoryServiceObserver: - void OnURLsDeleted(history::HistoryService* history_service, - const history::DeletionInfo& deletion_info) override; - void HistoryServiceBeingDeleted( - history::HistoryService* history_service) override; - - private: - std::unique_ptr<HistoryDeleter> deleter_; - base::ScopedObservation<history::HistoryService, - history::HistoryServiceObserver> - history_service_observer_{this}; -}; - -} // namespace screentime - -#endif // CHROME_BROWSER_UI_COCOA_SCREENTIME_HISTORY_BRIDGE_H_
diff --git a/chrome/browser/ui/cocoa/screentime/history_bridge.mm b/chrome/browser/ui/cocoa/screentime/history_bridge.mm deleted file mode 100644 index 7c9cfc2..0000000 --- a/chrome/browser/ui/cocoa/screentime/history_bridge.mm +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/cocoa/screentime/history_bridge.h" - -#import <ScreenTime/ScreenTime.h> - -#include "base/apple/foundation_util.h" -#include "base/strings/sys_string_conversions.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/cocoa/screentime/history_deleter.h" -#include "chrome/browser/ui/cocoa/screentime/screentime_policy.h" - -namespace screentime { - -HistoryBridge::HistoryBridge(history::HistoryService* service, - std::unique_ptr<HistoryDeleter> deleter) - : deleter_(std::move(deleter)) { - history_service_observer_.Observe(service); -} -HistoryBridge::~HistoryBridge() = default; - -void HistoryBridge::OnURLsDeleted(history::HistoryService* service, - const history::DeletionInfo& deletion_info) { - if (deletion_info.IsAllHistory()) { - deleter_->DeleteAllHistory(); - } else if (deletion_info.time_range().IsValid()) { - if (deletion_info.restrict_urls().has_value()) { - // Awkward: the ScreenTime API has no way to express "delete history for - // this URL within this time range", only "delete all history for this - // URL" and "delete all history within this time range". Here, we err on - // side of deleting the specific URLs for all time, rather than deleting - // all URLs within the given time. - for (const auto& url : *deletion_info.restrict_urls()) - deleter_->DeleteHistoryForURL(url); - } else { - deleter_->DeleteHistoryDuringInterval( - std::make_pair(deletion_info.time_range().begin(), - deletion_info.time_range().end())); - } - } else { - // If the time range isn't valid at all, this is a URL delete, which has no - // time bounds. - for (const auto& row : deletion_info.deleted_rows()) - deleter_->DeleteHistoryForURL(URLForReporting(row.url())); - } -} - -void HistoryBridge::HistoryServiceBeingDeleted( - history::HistoryService* history_service) { - DCHECK(history_service_observer_.IsObservingSource(history_service)); - history_service_observer_.Reset(); -} - -} // namespace screentime
diff --git a/chrome/browser/ui/cocoa/screentime/history_bridge_factory.h b/chrome/browser/ui/cocoa/screentime/history_bridge_factory.h deleted file mode 100644 index cf2cd8a..0000000 --- a/chrome/browser/ui/cocoa/screentime/history_bridge_factory.h +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_SCREENTIME_HISTORY_BRIDGE_FACTORY_H_ -#define CHROME_BROWSER_UI_COCOA_SCREENTIME_HISTORY_BRIDGE_FACTORY_H_ - -#include "chrome/browser/profiles/profile_keyed_service_factory.h" - -namespace screentime { - -// A BrowserContextKeyedServiceFactory that is responsible for creating a -// HistoryBridge instance for each loaded Profile. The HistoryBridge instance is -// created when the Profile is initially created, so there's no explicit -// creation step. -class HistoryBridgeFactory : public ProfileKeyedServiceFactory { - public: - HistoryBridgeFactory(); - ~HistoryBridgeFactory() override; - - HistoryBridgeFactory(const HistoryBridgeFactory&) = delete; - HistoryBridgeFactory& operator=(const HistoryBridgeFactory&) = delete; - - static HistoryBridgeFactory* GetInstance(); - static bool IsEnabled(); - - // BrowserContextKeyedServiceFactory: - std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext( - content::BrowserContext* context) const override; - bool ServiceIsCreatedWithBrowserContext() const override; - bool ServiceIsNULLWhileTesting() const override; -}; - -} // namespace screentime - -#endif // CHROME_BROWSER_UI_COCOA_SCREENTIME_HISTORY_BRIDGE_FACTORY_H_
diff --git a/chrome/browser/ui/cocoa/screentime/history_bridge_factory.mm b/chrome/browser/ui/cocoa/screentime/history_bridge_factory.mm deleted file mode 100644 index a2cefb3..0000000 --- a/chrome/browser/ui/cocoa/screentime/history_bridge_factory.mm +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/cocoa/screentime/history_bridge_factory.h" - -#include "base/no_destructor.h" -#include "chrome/browser/history/history_service_factory.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/cocoa/screentime/history_bridge.h" -#include "chrome/browser/ui/cocoa/screentime/history_deleter_impl.h" -#include "chrome/browser/ui/cocoa/screentime/screentime_features.h" - -namespace screentime { - -// static -HistoryBridgeFactory* HistoryBridgeFactory::GetInstance() { - static base::NoDestructor<HistoryBridgeFactory> factory; - return factory.get(); -} - -HistoryBridgeFactory::HistoryBridgeFactory() - : ProfileKeyedServiceFactory("screentime::HistoryBridge") {} -HistoryBridgeFactory::~HistoryBridgeFactory() = default; - -// static -bool HistoryBridgeFactory::IsEnabled() { - return base::FeatureList::IsEnabled(kScreenTime); -} - -std::unique_ptr<KeyedService> -HistoryBridgeFactory::BuildServiceInstanceForBrowserContext( - content::BrowserContext* context) const { - auto* profile = Profile::FromBrowserContext(context); - auto* service = HistoryServiceFactory::GetForProfile( - profile, ServiceAccessType::IMPLICIT_ACCESS); - - auto deleter = HistoryDeleterImpl::Create(); - - return std::make_unique<HistoryBridge>(service, std::move(deleter)); -} - -bool HistoryBridgeFactory::ServiceIsCreatedWithBrowserContext() const { - return true; -} - -bool HistoryBridgeFactory::ServiceIsNULLWhileTesting() const { - // Never create a HistoryBridge for a test context. They will always end up - // backed by a real HistoryDeleterImpl, which will try to talk to the system - // ScreenTime service, which will either make the test very slow or introduce - // flake. Tests need to explicitly opt into having real ScreenTime when they - // want it. - return true; -} - -} // namespace screentime
diff --git a/chrome/browser/ui/cocoa/screentime/history_bridge_unittest.cc b/chrome/browser/ui/cocoa/screentime/history_bridge_unittest.cc deleted file mode 100644 index f7fe25a..0000000 --- a/chrome/browser/ui/cocoa/screentime/history_bridge_unittest.cc +++ /dev/null
@@ -1,149 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/cocoa/screentime/history_bridge.h" - -#include "base/files/scoped_temp_dir.h" -#include "base/memory/raw_ptr.h" -#include "base/run_loop.h" -#include "base/task/cancelable_task_tracker.h" -#include "base/test/scoped_feature_list.h" -#include "chrome/browser/ui/cocoa/screentime/history_deleter.h" -#include "components/history/core/browser/history_database_params.h" -#include "components/history/core/browser/history_service.h" -#include "components/version_info/channel.h" -#include "content/public/test/browser_task_environment.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace screentime { - -namespace { - -class TestHistoryDeleter : public HistoryDeleter { - public: - ~TestHistoryDeleter() override {} - - bool deleted_all() const { return deleted_all_; } - std::optional<TimeInterval> deleted_interval() const { - return deleted_interval_; - } - const std::set<GURL>& deleted_urls() const { return deleted_urls_; } - - void WaitForDelete() { wait_loop_.Run(); } - - // HistoryDeleter: - void DeleteAllHistory() override { - deleted_all_ = true; - wait_loop_.Quit(); - } - void DeleteHistoryDuringInterval(const TimeInterval& interval) override { - deleted_interval_ = interval; - wait_loop_.Quit(); - } - void DeleteHistoryForURL(const GURL& url) override { - deleted_urls_.insert(url); - wait_loop_.Quit(); - } - - private: - bool deleted_all_ = false; - std::optional<TimeInterval> deleted_interval_ = std::nullopt; - std::set<GURL> deleted_urls_; - base::RunLoop wait_loop_; -}; - -} // namespace - -class HistoryBridgeTest : public ::testing::Test { - public: - HistoryBridgeTest() { - service_ = std::make_unique<history::HistoryService>(); - auto deleter = std::make_unique<TestHistoryDeleter>(); - deleter_ = deleter.get(); - bridge_ = - std::make_unique<HistoryBridge>(service_.get(), std::move(deleter)); - - CHECK(history_dir_.CreateUniqueTempDir()); - service_->Init(history::HistoryDatabaseParams( - history_dir_.GetPath(), 0, 0, version_info::Channel::UNKNOWN)); - service_->SetOnBackendDestroyTask(history_teardown_loop_.QuitClosure()); - } - - void TearDown() override { - service()->Shutdown(); - history_teardown_loop_.Run(); - } - - history::HistoryService* service() { return service_.get(); } - TestHistoryDeleter* deleter() { return deleter_; } - - void AddPage(const GURL& url, base::Time time = base::Time::Now()) { - service()->AddPage(url, time, history::VisitSource::SOURCE_BROWSED); - } - - void DeleteHistoryBetween(base::Time start, base::Time end) { - base::CancelableTaskTracker tracker; - base::RunLoop loop; - service()->ExpireHistoryBetween({}, history::kNoAppIdFilter, start, end, - true, loop.QuitClosure(), &tracker); - loop.Run(); - } - - void DeleteHistoryForURL(const GURL& url) { service()->DeleteURLs({url}); } - - void DeleteAllHistory() { DeleteHistoryBetween(base::Time(), base::Time()); } - - private: - content::BrowserTaskEnvironment task_environment_; - base::ScopedTempDir history_dir_; - std::unique_ptr<history::HistoryService> service_; - raw_ptr<TestHistoryDeleter, DanglingUntriaged> deleter_; - std::unique_ptr<HistoryBridge> bridge_; - base::RunLoop history_teardown_loop_; -}; - -TEST_F(HistoryBridgeTest, DeleteAll) { - AddPage(GURL("https://www.chromium.org/")); - AddPage(GURL("https://test.chromium.org/")); - - DeleteAllHistory(); - deleter()->WaitForDelete(); - EXPECT_TRUE(deleter()->deleted_all()); -} - -TEST_F(HistoryBridgeTest, DeleteURLs) { - const GURL kTestUrlA("https://www.chromium.org/"); - const base::Time now = base::Time::Now(); - AddPage(kTestUrlA, now - base::Seconds(2)); - AddPage(GURL("https://test.chromium.org/"), now - base::Seconds(1)); - - service()->DeleteURLs({kTestUrlA}); - deleter()->WaitForDelete(); - EXPECT_FALSE(deleter()->deleted_all()); - EXPECT_EQ(deleter()->deleted_urls(), std::set<GURL>{kTestUrlA}); -} - -TEST_F(HistoryBridgeTest, DeleteTimeInterval) { - const base::Time now = base::Time::Now(); - AddPage(GURL("https://www.chromium.org/a"), now - base::Seconds(2)); - AddPage(GURL("https://www.chromium.org/b"), now - base::Seconds(1)); - - DeleteHistoryBetween(now - base::Seconds(3), now); - deleter()->WaitForDelete(); - EXPECT_FALSE(deleter()->deleted_all()); - EXPECT_EQ(deleter()->deleted_interval()->first, now - base::Seconds(3)); - EXPECT_EQ(deleter()->deleted_interval()->second, now); -} - -TEST_F(HistoryBridgeTest, OnlyOriginsAreDeleted) { - const GURL kTestURL("https://www.chromium.org/abc"); - const GURL kStrippedTestURL("https://www.chromium.org/"); - AddPage(kTestURL); - DeleteHistoryForURL(kTestURL); - deleter()->WaitForDelete(); - EXPECT_EQ(deleter()->deleted_urls().size(), 1U); - EXPECT_EQ(deleter()->deleted_urls().count(kStrippedTestURL), 1U); -} - -} // namespace screentime
diff --git a/chrome/browser/ui/cocoa/screentime/history_deleter.h b/chrome/browser/ui/cocoa/screentime/history_deleter.h deleted file mode 100644 index 905638c7..0000000 --- a/chrome/browser/ui/cocoa/screentime/history_deleter.h +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_SCREENTIME_HISTORY_DELETER_H_ -#define CHROME_BROWSER_UI_COCOA_SCREENTIME_HISTORY_DELETER_H_ - -#include <utility> - -#include "base/time/time.h" - -class GURL; - -namespace screentime { - -// The HistoryDeleter interface wraps the actual implementation of deleting -// items from the system ScreenTime history store, so the interface here exactly -// mirrors the ScreenTime STWebHistory interface: -// https://developer.apple.com/documentation/screentime/stwebhistory -class HistoryDeleter { - public: - using TimeInterval = std::pair<base::Time, base::Time>; - - virtual ~HistoryDeleter() = default; - - virtual void DeleteAllHistory() = 0; - virtual void DeleteHistoryDuringInterval(const TimeInterval& interval) = 0; - virtual void DeleteHistoryForURL(const GURL& url) = 0; -}; - -} // namespace screentime - -#endif // CHROME_BROWSER_UI_COCOA_SCREENTIME_HISTORY_DELETER_H_
diff --git a/chrome/browser/ui/cocoa/screentime/history_deleter_impl.h b/chrome/browser/ui/cocoa/screentime/history_deleter_impl.h deleted file mode 100644 index fe5b6e3..0000000 --- a/chrome/browser/ui/cocoa/screentime/history_deleter_impl.h +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_SCREENTIME_HISTORY_DELETER_IMPL_H_ -#define CHROME_BROWSER_UI_COCOA_SCREENTIME_HISTORY_DELETER_IMPL_H_ - -#include "chrome/browser/ui/cocoa/screentime/history_deleter.h" - -#include <memory> - -@class STWebHistory; - -namespace screentime { - -// Implementation of HistoryDeleter that mutates the actual system history -// store. -class HistoryDeleterImpl : public HistoryDeleter { - public: - ~HistoryDeleterImpl() override; - - // The constructor is private so that the actual construction of this object - // can be guarded by availability checks inside this class rather than in - // callers. This method may return nullptr if called on a system where - // ScreenTime is not available! - static std::unique_ptr<HistoryDeleterImpl> Create(); - - void DeleteAllHistory() override; - void DeleteHistoryDuringInterval(const TimeInterval& interval) override; - void DeleteHistoryForURL(const GURL& url) override; - - private: - HistoryDeleterImpl(); - - STWebHistory* __strong platform_deleter_; -}; - -} // namespace screentime - -#endif // CHROME_BROWSER_UI_COCOA_SCREENTIME_HISTORY_DELETER_IMPL_H_
diff --git a/chrome/browser/ui/cocoa/screentime/history_deleter_impl.mm b/chrome/browser/ui/cocoa/screentime/history_deleter_impl.mm deleted file mode 100644 index 987b89e..0000000 --- a/chrome/browser/ui/cocoa/screentime/history_deleter_impl.mm +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/cocoa/screentime/history_deleter_impl.h" - -#import <ScreenTime/ScreenTime.h> - -#include "base/apple/foundation_util.h" -#include "base/memory/ptr_util.h" -#include "base/notreached.h" -#include "base/strings/sys_string_conversions.h" -#include "net/base/apple/url_conversions.h" - -namespace screentime { - -HistoryDeleterImpl::~HistoryDeleterImpl() = default; - -std::unique_ptr<HistoryDeleterImpl> HistoryDeleterImpl::Create() { - if (@available(macOS 12.1, *)) - return base::WrapUnique(new HistoryDeleterImpl); - return nullptr; -} - -void HistoryDeleterImpl::DeleteAllHistory() { - if (@available(macOS 12.1, *)) { - [platform_deleter_ deleteAllHistory]; - } else { - NOTIMPLEMENTED(); - } -} - -void HistoryDeleterImpl::DeleteHistoryDuringInterval( - const TimeInterval& interval) { - if (@available(macOS 12.1, *)) { - NSDateInterval* nsinterval = - [[NSDateInterval alloc] initWithStartDate:interval.first.ToNSDate() - endDate:interval.second.ToNSDate()]; - [platform_deleter_ deleteHistoryDuringInterval:nsinterval]; - } else { - NOTIMPLEMENTED(); - } -} - -void HistoryDeleterImpl::DeleteHistoryForURL(const GURL& url) { - if (@available(macOS 12.1, *)) { - [platform_deleter_ deleteHistoryForURL:net::NSURLWithGURL(url)]; - } else { - NOTIMPLEMENTED(); - } -} - -HistoryDeleterImpl::HistoryDeleterImpl() { - if (@available(macOS 12.1, *)) { - NSError* error = nil; - NSString* bundle_id = base::SysUTF8ToNSString(base::apple::BaseBundleID()); - platform_deleter_ = [[STWebHistory alloc] initWithBundleIdentifier:bundle_id - error:&error]; - DCHECK(!error); - } else { - NOTIMPLEMENTED(); - } -} - -} // namespace screentime
diff --git a/chrome/browser/ui/cocoa/screentime/screentime_features.cc b/chrome/browser/ui/cocoa/screentime/screentime_features.cc deleted file mode 100644 index 2d3f027..0000000 --- a/chrome/browser/ui/cocoa/screentime/screentime_features.cc +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/cocoa/screentime/screentime_features.h" - -#include <Availability.h> - -namespace screentime { - -BASE_FEATURE(kScreenTime, "ScreenTime", base::FEATURE_DISABLED_BY_DEFAULT); - -bool IsScreenTimeEnabled() { - if (__builtin_available(macOS 12.1, *)) { - return base::FeatureList::IsEnabled(kScreenTime); - } - return false; -} - -} // namespace screentime
diff --git a/chrome/browser/ui/cocoa/screentime/screentime_features.h b/chrome/browser/ui/cocoa/screentime/screentime_features.h deleted file mode 100644 index 3c365fb60..0000000 --- a/chrome/browser/ui/cocoa/screentime/screentime_features.h +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_SCREENTIME_SCREENTIME_FEATURES_H_ -#define CHROME_BROWSER_UI_COCOA_SCREENTIME_SCREENTIME_FEATURES_H_ - -#include "base/feature_list.h" - -namespace screentime { - -BASE_DECLARE_FEATURE(kScreenTime); - -bool IsScreenTimeEnabled(); - -} // namespace screentime - -#endif // CHROME_BROWSER_UI_COCOA_SCREENTIME_SCREENTIME_FEATURES_H_
diff --git a/chrome/browser/ui/cocoa/screentime/screentime_policy.cc b/chrome/browser/ui/cocoa/screentime/screentime_policy.cc deleted file mode 100644 index 8e272e2..0000000 --- a/chrome/browser/ui/cocoa/screentime/screentime_policy.cc +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/cocoa/screentime/screentime_policy.h" - -#include "url/origin.h" - -namespace screentime { - -GURL URLForReporting(const GURL& url) { - // Strip the username, password, path, and query components: - // https://crbug.com/1188351. - return url::Origin::Create(url).GetURL(); -} - -} // namespace screentime
diff --git a/chrome/browser/ui/cocoa/screentime/screentime_policy.h b/chrome/browser/ui/cocoa/screentime/screentime_policy.h deleted file mode 100644 index cecb9765..0000000 --- a/chrome/browser/ui/cocoa/screentime/screentime_policy.h +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_SCREENTIME_SCREENTIME_POLICY_H_ -#define CHROME_BROWSER_UI_COCOA_SCREENTIME_SCREENTIME_POLICY_H_ - -#include "url/gurl.h" - -// Functions in this file encapsulate policy decisions about how to interact -// with and which data to supply to Screen Time. -namespace screentime { - -// Return a url based on `url` to be passed to Screen Time when reporting (or -// clearing) page visits. All URLs passed to Screen Time are filtered through -// this function. -GURL URLForReporting(const GURL& url); - -} // namespace screentime - -#endif // CHROME_BROWSER_UI_COCOA_SCREENTIME_SCREENTIME_POLICY_H_
diff --git a/chrome/browser/ui/cocoa/screentime/screentime_tab_helper_unittest.mm b/chrome/browser/ui/cocoa/screentime/screentime_tab_helper_unittest.mm deleted file mode 100644 index 13a22c7..0000000 --- a/chrome/browser/ui/cocoa/screentime/screentime_tab_helper_unittest.mm +++ /dev/null
@@ -1,97 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/cocoa/screentime/tab_helper.h" - -#include "base/test/scoped_feature_list.h" -#include "chrome/browser/media/router/media_router_feature.h" -#include "chrome/browser/ui/cocoa/screentime/fake_webpage_controller.h" -#include "chrome/browser/ui/cocoa/screentime/screentime_features.h" -#include "chrome/browser/ui/cocoa/screentime/tab_helper.h" -#include "chrome/test/base/testing_profile.h" -#include "content/public/test/browser_task_environment.h" -#include "content/public/test/test_renderer_host.h" -#include "content/public/test/web_contents_tester.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace screentime { - -class ScreentimeTabHelperTest : public ::testing::Test { - public: - ScreentimeTabHelperTest() = default; - ~ScreentimeTabHelperTest() override = default; - - void SetUp() override { - ::testing::Test::SetUp(); - - TabHelper::UseFakeWebpageControllerForTesting(); - // `kMediaRouter` is disabled because it has unmet dependencies and is - // unrelated to this unit test. - features_.InitWithFeatures(/*enabled=*/{kScreenTime}, - /*disabled=*/{media_router::kMediaRouter}); - profile_ = std::make_unique<TestingProfile>(); - } - - TestingProfile* profile() const { return profile_.get(); } - - private: - base::test::ScopedFeatureList features_; - content::BrowserTaskEnvironment task_environment_; - content::RenderViewHostTestEnabler rvh_test_enabler_; - std::unique_ptr<TestingProfile> profile_; -}; - -TEST_F(ScreentimeTabHelperTest, NeverUsedInIncognito) { - if (@available(macOS 12.1, *)) { - auto* otr_profile = profile()->GetOffTheRecordProfile( - Profile::OTRProfileID::PrimaryID(), /*create_if_needed=*/true); - - EXPECT_TRUE(TabHelper::IsScreentimeEnabledForProfile(profile())); - EXPECT_FALSE(TabHelper::IsScreentimeEnabledForProfile(otr_profile)); - } else { - GTEST_SKIP() << "ScreenTime is only enabled on macOS 12.1 and higher"; - } -} - -TEST_F(ScreentimeTabHelperTest, OnlyOriginsAreReported) { - auto contents = - content::WebContentsTester::CreateTestWebContents(profile(), nullptr); - auto helper = std::make_unique<TabHelper>(contents.get()); - - FakeWebpageController* controller = static_cast<FakeWebpageController*>( - helper->page_controller_for_testing()); - - auto* tester = content::WebContentsTester::For(contents.get()); - tester->NavigateAndCommit(GURL("https://www.chromium.org/abc")); - tester->NavigateAndCommit(GURL("https://test.chromium.org/def")); - - EXPECT_EQ(controller->visited_urls_for_testing()[0], - GURL("https://www.chromium.org/")); - EXPECT_EQ(controller->visited_urls_for_testing()[1], - GURL("https://test.chromium.org/")); -} - -TEST_F(ScreentimeTabHelperTest, OnlyHttpHttpsSchemesReported) { - auto contents = - content::WebContentsTester::CreateTestWebContents(profile(), nullptr); - auto helper = std::make_unique<TabHelper>(contents.get()); - - FakeWebpageController* controller = static_cast<FakeWebpageController*>( - helper->page_controller_for_testing()); - - auto* tester = content::WebContentsTester::For(contents.get()); - tester->NavigateAndCommit(GURL("https://www.chromium.org/abc")); - tester->NavigateAndCommit(GURL("http://test.chromium.org/def")); - tester->NavigateAndCommit(GURL("chrome://version")); - tester->NavigateAndCommit(GURL("mailto:hello@example.com")); - - EXPECT_EQ(controller->visited_urls_for_testing().size(), 2u); - - EXPECT_EQ(controller->visited_urls_for_testing()[0], - GURL("https://www.chromium.org/")); - EXPECT_EQ(controller->visited_urls_for_testing()[1], - GURL("http://test.chromium.org/")); -} - -} // namespace screentime
diff --git a/chrome/browser/ui/cocoa/screentime/tab_helper.h b/chrome/browser/ui/cocoa/screentime/tab_helper.h deleted file mode 100644 index 5c06fa8..0000000 --- a/chrome/browser/ui/cocoa/screentime/tab_helper.h +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_SCREENTIME_TAB_HELPER_H_ -#define CHROME_BROWSER_UI_COCOA_SCREENTIME_TAB_HELPER_H_ - -#include <memory> - -#include "content/public/browser/web_contents_observer.h" -#include "content/public/browser/web_contents_user_data.h" - -class Profile; - -namespace content { -class WebContents; -} - -namespace screentime { - -class WebpageController; - -// A TabHelper connects a content::WebContents to a WebpageController, -// passing state updates from the WebContents to the WebpageController and -// from the WebpageController to the WebContents or other parts of the browser. -class TabHelper : public content::WebContentsObserver, - public content::WebContentsUserData<TabHelper> { - public: - static void UseFakeWebpageControllerForTesting(); - static bool IsScreentimeEnabledForProfile(Profile* profile); - - TabHelper(content::WebContents* contents); - ~TabHelper() override; - - // WebContentsObserver: - void PrimaryPageChanged(content::Page& handle) override; - - WebpageController* page_controller_for_testing() const { - return page_controller_.get(); - } - - private: - friend class content::WebContentsUserData<TabHelper>; - - std::unique_ptr<WebpageController> MakeWebpageController(); - - void OnBlockedChanged(bool blocked); - - WEB_CONTENTS_USER_DATA_KEY_DECL(); - - std::unique_ptr<WebpageController> page_controller_; -}; - -} // namespace screentime - -#endif // CHROME_BROWSER_UI_COCOA_SCREENTIME_TAB_HELPER_H_
diff --git a/chrome/browser/ui/cocoa/screentime/tab_helper.mm b/chrome/browser/ui/cocoa/screentime/tab_helper.mm deleted file mode 100644 index ee2e6093..0000000 --- a/chrome/browser/ui/cocoa/screentime/tab_helper.mm +++ /dev/null
@@ -1,94 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import <Cocoa/Cocoa.h> - -#include "base/command_line.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/cocoa/screentime/fake_webpage_controller.h" -#include "chrome/browser/ui/cocoa/screentime/screentime_features.h" -#include "chrome/browser/ui/cocoa/screentime/screentime_policy.h" -#include "chrome/browser/ui/cocoa/screentime/tab_helper.h" -#include "chrome/browser/ui/cocoa/screentime/webpage_controller.h" -#include "chrome/browser/ui/cocoa/screentime/webpage_controller_impl.h" -#include "content/public/browser/media_session.h" -#include "content/public/browser/web_contents.h" - -namespace screentime { - -namespace { -bool g_use_fake_webpage_controller = false; -} - -// static -void TabHelper::UseFakeWebpageControllerForTesting() { - g_use_fake_webpage_controller = true; -} - -// static -bool TabHelper::IsScreentimeEnabledForProfile(Profile* profile) { - if (profile->IsOffTheRecord()) { - return false; - } - return IsScreenTimeEnabled(); -} - -TabHelper::TabHelper(content::WebContents* contents) - : WebContentsObserver(contents), - content::WebContentsUserData<TabHelper>(*contents), - page_controller_(MakeWebpageController()) { - Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); - // Absolutely ensure that we never record a navigation for an OTR profile. - CHECK(!profile->IsOffTheRecord()); - - NSView* contents_view = contents->GetNativeView().GetNativeNSView(); - [contents_view addSubview:page_controller_->GetView()]; -} - -TabHelper::~TabHelper() = default; - -void TabHelper::PrimaryPageChanged(content::Page& page) { - content::RenderFrameHost& rfh = page.GetMainDocument(); - const GURL& url = rfh.GetLastCommittedURL(); - if (!url.SchemeIsHTTPOrHTTPS()) - return; - page_controller_->PageURLChangedTo(URLForReporting(url)); -} - -std::unique_ptr<WebpageController> TabHelper::MakeWebpageController() { - const bool use_fake = - g_use_fake_webpage_controller || - base::CommandLine::ForCurrentProcess()->HasSwitch("fake-screentime"); - - // The callback is owned by the WebpageController instance, which is in turn - // owned by this object, so it can't outlive us. - auto callback = - base::BindRepeating(&TabHelper::OnBlockedChanged, base::Unretained(this)); - std::unique_ptr<WebpageController> controller; - if (@available(macOS 12.1, *)) { - if (use_fake) { - controller = std::make_unique<FakeWebpageController>(callback); - } else { - controller = std::make_unique<WebpageControllerImpl>(callback); - } - } else { - DCHECK(use_fake); - controller = std::make_unique<FakeWebpageController>(callback); - } - return controller; -} - -void TabHelper::OnBlockedChanged(bool blocked) { - // TODO: Update occlusion state on the WebContents, and so on. - // Getting this behavior right will probably require some care. - auto* media_session = content::MediaSession::Get(web_contents()); - if (blocked) - media_session->Suspend(content::MediaSession::SuspendType::kSystem); - else - media_session->Resume(content::MediaSession::SuspendType::kSystem); -} - -WEB_CONTENTS_USER_DATA_KEY_IMPL(TabHelper); - -} // namespace screentime
diff --git a/chrome/browser/ui/cocoa/screentime/webpage_controller.h b/chrome/browser/ui/cocoa/screentime/webpage_controller.h deleted file mode 100644 index 9804a6e..0000000 --- a/chrome/browser/ui/cocoa/screentime/webpage_controller.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_SCREENTIME_WEBPAGE_CONTROLLER_H_ -#define CHROME_BROWSER_UI_COCOA_SCREENTIME_WEBPAGE_CONTROLLER_H_ - -#include "base/functional/callback.h" -#include "url/gurl.h" - -@class NSView; - -namespace screentime { - -// The interface for the per-page controller. This interface exists to allow for -// abstracting away the concrete STWebpageController class, which is only -// available on some platforms and ties into a systemwide API that makes unit -// testing difficult. As little logic as possible should happen in -// implementations of WebpageController. -class WebpageController { - public: - using BlockedChangedCallback = base::RepeatingCallback<void(bool)>; - - WebpageController() = default; - virtual ~WebpageController() = default; - - virtual NSView* GetView() = 0; - - // Called when the WebContents that this WebpageController is attached to - // changes its committed URL to |url|, to update ScreenTime's notion of the - // "page URL" (in Chrome parlance, the top-level frame URL). - virtual void PageURLChangedTo(const GURL& url) = 0; -}; - -} // namespace screentime - -#endif // CHROME_BROWSER_UI_COCOA_SCREENTIME_WEBPAGE_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/screentime/webpage_controller_impl.h b/chrome/browser/ui/cocoa/screentime/webpage_controller_impl.h deleted file mode 100644 index 1660fba..0000000 --- a/chrome/browser/ui/cocoa/screentime/webpage_controller_impl.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_SCREENTIME_WEBPAGE_CONTROLLER_IMPL_H_ -#define CHROME_BROWSER_UI_COCOA_SCREENTIME_WEBPAGE_CONTROLLER_IMPL_H_ - -#include <Foundation/Foundation.h> - -#include "chrome/browser/ui/cocoa/screentime/webpage_controller.h" - -@class BlockedObserver; -@class STWebpageController; - -namespace screentime { - -// This class wraps the STWebpageController screentime class, to allow for tests -// to use a fake controller. -class NS_AVAILABLE_MAC(11.0) WebpageControllerImpl : public WebpageController { - public: - WebpageControllerImpl(const BlockedChangedCallback& callback); - ~WebpageControllerImpl() override; - - NSView* GetView() override; - void PageURLChangedTo(const GURL& url) override; - - void OnBlockedChanged(bool blocked); - - private: - STWebpageController* __strong platform_controller_; - BlockedObserver* __strong blocked_observer_; - BlockedChangedCallback blocked_changed_callback_; -}; - -} // namespace screentime - -#endif // CHROME_BROWSER_UI_COCOA_SCREENTIME_WEBPAGE_CONTROLLER_IMPL_H_
diff --git a/chrome/browser/ui/cocoa/screentime/webpage_controller_impl.mm b/chrome/browser/ui/cocoa/screentime/webpage_controller_impl.mm deleted file mode 100644 index 8aa86903..0000000 --- a/chrome/browser/ui/cocoa/screentime/webpage_controller_impl.mm +++ /dev/null
@@ -1,79 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/cocoa/screentime/webpage_controller_impl.h" - -#include <ScreenTime/ScreenTime.h> - -#include "base/apple/foundation_util.h" -#include "base/memory/raw_ptr.h" -#include "base/strings/sys_string_conversions.h" -#include "net/base/apple/url_conversions.h" - -@interface BlockedObserver : NSObject -@end - -NS_AVAILABLE_MAC(11.0) -@implementation BlockedObserver { - raw_ptr<screentime::WebpageControllerImpl> _controller; - STWebpageController* __weak _nativeController; -} - -- (instancetype)initWithController: - (screentime::WebpageControllerImpl*)controller - nativeController:(STWebpageController*)nativeController { - if (self = [super init]) { - _controller = controller; - _nativeController = nativeController; - [_nativeController addObserver:self - forKeyPath:@"URLIsBlocked" - options:0 - context:nullptr]; - } - return self; -} - -- (void)dealloc { - [_nativeController removeObserver:self forKeyPath:@"URLIsBlocked"]; -} - -- (void)observeValueForKeyPath:(NSString*)forKeyPath - ofObject:(id)object - change:(NSDictionary*)change - context:(void*)context { - DCHECK([forKeyPath isEqualToString:@"URLIsBlocked"]); - _controller->OnBlockedChanged(_nativeController.URLIsBlocked); -} - -@end - -namespace screentime { - -WebpageControllerImpl::WebpageControllerImpl( - const BlockedChangedCallback& blocked_changed_callback) - : platform_controller_([[STWebpageController alloc] init]), - blocked_observer_([[BlockedObserver alloc] - initWithController:this - nativeController:platform_controller_]), - blocked_changed_callback_(blocked_changed_callback) { - NSError* error = nil; - NSString* bundle_id = base::SysUTF8ToNSString(base::apple::BaseBundleID()); - [platform_controller_ setBundleIdentifier:bundle_id error:&error]; -} - -WebpageControllerImpl::~WebpageControllerImpl() = default; - -NSView* WebpageControllerImpl::GetView() { - return [platform_controller_ view]; -} - -void WebpageControllerImpl::PageURLChangedTo(const GURL& url) { - [platform_controller_ setURL:net::NSURLWithGURL(url)]; -} - -void WebpageControllerImpl::OnBlockedChanged(bool blocked) { - blocked_changed_callback_.Run(blocked); -} - -} // namespace screentime
diff --git a/chrome/browser/ui/commander/BUILD.gn b/chrome/browser/ui/commander/BUILD.gn deleted file mode 100644 index aa1d197..0000000 --- a/chrome/browser/ui/commander/BUILD.gn +++ /dev/null
@@ -1,24 +0,0 @@ -import("//testing/libfuzzer/fuzzer_test.gni") - -source_set("fuzzy_finder") { - sources = [ - "fuzzy_finder.cc", - "fuzzy_finder.h", - ] - - configs += [ "//build/config/compiler:wexit_time_destructors" ] - - deps = [ - "//base:base", - "//base:i18n", - "//ui/gfx/range", - ] -} - -fuzzer_test("fuzzy_finder_fuzzer") { - sources = [ "fuzzy_finder_fuzzer.cc" ] - deps = [ - ":fuzzy_finder", - "//base:base", - ] -}
diff --git a/chrome/browser/ui/commander/OWNERS b/chrome/browser/ui/commander/OWNERS deleted file mode 100644 index 76d629d..0000000 --- a/chrome/browser/ui/commander/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -lgrey@chromium.org -ellyjones@chromium.org
diff --git a/chrome/browser/ui/commander/README.md b/chrome/browser/ui/commander/README.md deleted file mode 100644 index 9de252f..0000000 --- a/chrome/browser/ui/commander/README.md +++ /dev/null
@@ -1,60 +0,0 @@ -# Commander overview - -This directory contains the bulk of the Commander, a new UI surface that allows -users to access most Chromium functionality via a keyboard interface. - -## Components - -The three main components of the commander are: - -### Frontend - -The frontend is responsible for passing user input to the controller and -displaying the subsequent results, delivered in a `CommanderViewModel`. -The frontend conforms to the `CommanderFrontend` interface which currently -has a single production implementation: `CommanderFrontendViews`. The actual -interface is implemented in WebUI (see `chrome/browser/ui/webui/commander`). - -### Command Sources - -Command sources (`CommandSource`) are responsible for providing a list of -possible commands (`CommandItem`) for the user's current context, then -executing them if they are chosen. - -### Backend - -The backend is responsible for maintaining alist of command sources, passing -user input to them, and sorting and ranking the result. - -If a command requires more input (for example, choosing a window to move the -current tab to), the command source will provide a callback which can receive -user input and returns commands. The backend will then use this callback -as the sole source to complete the multi-step command. - -The backend conforms to the `CommanderBackend` interface and currently has a -single production implementation: `CommanderController`. - -## Relationships - -To sum up the relationships of the classes in this file: -`Commander` (a singleton) owns a `CommanderBackend` and a `CommanderFrontend`. -This class's `ToggleForBrowser()` method is the entirety of the Commander -interface as far as the rest of the browser is concerned. - -`ToggleForBrowser()` calls the method of the same name on the frontend. This -hides the UI if it is showing on a different browser, then hides or shows it on -the provided browser, depending on the current state. The frontend then sends -user input to the backend, which responds with a view model of possible -commands. - -When the backend receives a message indicating that the user has chosen an -option, the `CommandItem` is executed if it's "one-shot". Otherwise, it's -a composite command; the backend passes a prompt text to the frontend, which -updates the UI accordingly. The backend passes subsequent input to the provided -callback until the command is either completed or cancelled. Composite commands -can be nested to allow for multiple (for example: the user specifying two -windows to merge together). - -## Fuzzy finder -Most `CommandSource`s use `FuzzyFinder` to narrow down which commands to return. -For more information, see [the explainer](fuzzy_finder.md).
diff --git a/chrome/browser/ui/commander/bookmark_command_source.cc b/chrome/browser/ui/commander/bookmark_command_source.cc deleted file mode 100644 index 22adff5..0000000 --- a/chrome/browser/ui/commander/bookmark_command_source.cc +++ /dev/null
@@ -1,91 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/commander/bookmark_command_source.h" - -#include "base/i18n/case_conversion.h" -#include "base/logging.h" -#include "chrome/browser/bookmarks/bookmark_model_factory.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_tabstrip.h" -#include "chrome/browser/ui/commander/commander_backend.h" -#include "chrome/browser/ui/commander/commander_view_model.h" -#include "chrome/browser/ui/commander/fuzzy_finder.h" -#include "components/bookmarks/browser/bookmark_model.h" -#include "components/bookmarks/browser/url_and_title.h" - -namespace commander { - -namespace { - -std::unique_ptr<CommandItem> CreateOpenBookmarkItem( - const bookmarks::UrlAndTitle& bookmark, - Browser* browser) { - auto item = std::make_unique<CommandItem>(); - item->title = bookmark.title; - item->entity_type = CommandItem::Entity::kBookmark; - // base::Unretained is safe because commands are reset when a browser is - // closed. - item->command = base::BindOnce(&chrome::AddTabAt, base::Unretained(browser), - GURL(bookmark.url), -1, true, std::nullopt); - return item; -} - -CommandSource::CommandResults GetMatchingBookmarks( - Browser* browser, - const std::u16string& input) { - CommandSource::CommandResults results; - bookmarks::BookmarkModel* model = - BookmarkModelFactory::GetForBrowserContext(browser->profile()); - // This should have been checked already. - DCHECK(model && model->loaded()); - FuzzyFinder finder(input); - std::vector<gfx::Range> ranges; - for (bookmarks::UrlAndTitle& bookmark : model->GetUniqueUrls()) { - double score = finder.Find(bookmark.title, &ranges); - if (score > 0) { - auto item = CreateOpenBookmarkItem(bookmark, browser); - item->score = score; - item->matched_ranges = ranges; - results.push_back(std::move(item)); - } - } - return results; -} - -} // namespace - -BookmarkCommandSource::BookmarkCommandSource() = default; -BookmarkCommandSource::~BookmarkCommandSource() = default; - -CommandSource::CommandResults BookmarkCommandSource::GetCommands( - const std::u16string& input, - Browser* browser) const { - CommandSource::CommandResults results; - bookmarks::BookmarkModel* model = - BookmarkModelFactory::GetForBrowserContext(browser->profile()); - // Just no-op instead of waiting for the model to load, since this isn't - // a persistent UI surface and they can just try again. - if (!model || !model->loaded() || !model->HasBookmarks()) - return results; - - FuzzyFinder finder(input); - std::vector<gfx::Range> ranges; - // TODO(lgrey): Temporarily using an untranslated string since it's not - // yet clear which commands will ship. - std::u16string open_title = u"Open bookmark..."; - double score = finder.Find(open_title, &ranges); - if (score > 0) { - auto verb = std::make_unique<CommandItem>(open_title, score, ranges); - // base::Unretained is safe because commands are cleared on browser close. - verb->command = std::make_pair( - open_title, - base::BindRepeating(&GetMatchingBookmarks, base::Unretained(browser))); - results.push_back(std::move(verb)); - } - return results; -} - -} // namespace commander
diff --git a/chrome/browser/ui/commander/bookmark_command_source.h b/chrome/browser/ui/commander/bookmark_command_source.h deleted file mode 100644 index e2fb27a..0000000 --- a/chrome/browser/ui/commander/bookmark_command_source.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COMMANDER_BOOKMARK_COMMAND_SOURCE_H_ -#define CHROME_BROWSER_UI_COMMANDER_BOOKMARK_COMMAND_SOURCE_H_ - -#include "chrome/browser/ui/commander/command_source.h" - -namespace commander { - -// Provides an "Open Bookmark..." composite command which lets the user -// search for a bookmark to open. If the user has typed a minimum threshold -// of characters, this will also return matching individual bookmark commands -// directly. -class BookmarkCommandSource : public CommandSource { - public: - BookmarkCommandSource(); - ~BookmarkCommandSource() override; - - BookmarkCommandSource(const BookmarkCommandSource& other) = delete; - BookmarkCommandSource& operator=(const BookmarkCommandSource& other) = delete; - - // Command source overrides - CommandSource::CommandResults GetCommands(const std::u16string& input, - Browser* browser) const override; -}; - -} // namespace commander - -#endif // CHROME_BROWSER_UI_COMMANDER_BOOKMARK_COMMAND_SOURCE_H_
diff --git a/chrome/browser/ui/commander/command_source.cc b/chrome/browser/ui/commander/command_source.cc deleted file mode 100644 index 9c530a3..0000000 --- a/chrome/browser/ui/commander/command_source.cc +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/commander/command_source.h" - -namespace commander { - -CommandItem::CommandItem() = default; -CommandItem::CommandItem(const std::u16string& title, - double score, - const std::vector<gfx::Range>& ranges) - : title(title), score(score), matched_ranges(ranges) {} -CommandItem::~CommandItem() = default; -CommandItem::CommandItem(CommandItem&& other) = default; -CommandItem& CommandItem::operator=(CommandItem&& other) = default; - -CommandItem::Type CommandItem::GetType() { - if (absl::get_if<CompositeCommand>(&command)) - return kComposite; - return kOneShot; -} - -} // namespace commander
diff --git a/chrome/browser/ui/commander/command_source.h b/chrome/browser/ui/commander/command_source.h deleted file mode 100644 index 48e249f..0000000 --- a/chrome/browser/ui/commander/command_source.h +++ /dev/null
@@ -1,105 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COMMANDER_COMMAND_SOURCE_H_ -#define CHROME_BROWSER_UI_COMMANDER_COMMAND_SOURCE_H_ - -#include <memory> -#include <utility> -#include <vector> - -#include "base/functional/callback.h" -#include "third_party/abseil-cpp/absl/types/variant.h" -#include "ui/gfx/range/range.h" - -class Browser; - -namespace commander { - -struct CommandItem; - -// Provides and ranks available commands in response to user input. The -// intention is for every system available through the commander to -// provide its own source, which is responsible for tracking the state and -// context necessary to provide appropriate commands from that system. -class CommandSource { - public: - using CommandResults = std::vector<std::unique_ptr<CommandItem>>; - CommandSource() = default; - virtual ~CommandSource() = default; - - // Returns a list of scored commands to return for |input|, or an empty - // list if none are appropriate. The commands are not guaranteed to be in - // any particular order. |browser| is the browser the active commander - // is attached to. - virtual CommandResults GetCommands(const std::u16string& input, - Browser* browser) const = 0; -}; - -// Represents a single option that can be presented in the command palette. -struct CommandItem { - public: - enum Type { - // On selection, the command is invoked and the UI should close. - kOneShot, - // On selection, the user is prompted for further information. - kComposite, - }; - // What *the text* of this command represents. For example, in the composite - // command "Move Current Tab To Window", the user will be prompted to select - // a window by name. In that case, the original command will have Entity = - // kCommand, and the follow-up will have Entity kWindow. - // This is used in the UI to give different visual treatments to different - // entity types. - enum Entity { - kCommand, - kBookmark, - kTab, - kWindow, - kGroup, - }; - - using CompositeCommandProvider = - base::RepeatingCallback<CommandSource::CommandResults( - const std::u16string&)>; - using CompositeCommand = std::pair<std::u16string, CompositeCommandProvider>; - - CommandItem(); - CommandItem(const std::u16string& title, - double score, - const std::vector<gfx::Range>& ranges); - virtual ~CommandItem(); - - CommandItem(const CommandItem& other) = delete; - CommandItem& operator=(const CommandItem& other) = delete; - CommandItem(CommandItem&& other); - CommandItem& operator=(CommandItem&& other); - - Type GetType(); - // The title to display to the user. - std::u16string title; - // See Entity documentation above. - Entity entity_type = kCommand; - // Optional secondary text for the command. Typically used to display a - // hotkey. - std::u16string annotation; - // If this command is a one-shot, executes the command. If this command is - // composite, provides the prompt text sent to the user, and a - // CompositeCommandProvider to handle additional user input. - absl::variant<base::OnceClosure, CompositeCommand> command; - // How relevant the item is to user input. Expected range is (0,1], with 1 - // indicating a perfect match (in the absence of other criteria, this boils - // down to an exact string match). - double score; - // Ranges of indices in |item|'s title that correspond to user input. - // For example, given user input "comitmlt" and a command called "Command Item - // Match Result", this would result in {(0, 3), (8, 10), (13,14), (23,25)}, - // representing: - // [Com]mand [It]em [M]atch Resu[lt] - std::vector<gfx::Range> matched_ranges; -}; - -} // namespace commander - -#endif // CHROME_BROWSER_UI_COMMANDER_COMMAND_SOURCE_H_
diff --git a/chrome/browser/ui/commander/commander.cc b/chrome/browser/ui/commander/commander.cc deleted file mode 100644 index 2181671e..0000000 --- a/chrome/browser/ui/commander/commander.cc +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/commander/commander.h" - -#include "base/no_destructor.h" -#include "chrome/browser/ui/commander/commander_controller.h" -#include "chrome/browser/ui/commander/commander_frontend.h" -#include "chrome/browser/ui/ui_features.h" -#include "content/public/browser/browser_thread.h" - -namespace commander { - -bool IsEnabled() { - return base::FeatureList::IsEnabled(features::kQuickCommands); -} - -// static -Commander* Commander::Get() { - static base::NoDestructor<Commander> instance; - return instance.get(); -} - -Commander::Commander() = default; -Commander::~Commander() = default; - -void Commander::Initialize() { - DCHECK(IsEnabled()); - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(!backend_ && !frontend_); - backend_ = std::make_unique<CommanderController>(); - frontend_ = CommanderFrontend::Create(backend_.get()); -} - -void Commander::ToggleForBrowser(Browser* browser) { - DCHECK(IsEnabled()); - DCHECK(frontend_); - frontend_->ToggleForBrowser(browser); -} - -} // namespace commander
diff --git a/chrome/browser/ui/commander/commander.h b/chrome/browser/ui/commander/commander.h deleted file mode 100644 index 4bf9751..0000000 --- a/chrome/browser/ui/commander/commander.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COMMANDER_COMMANDER_H_ -#define CHROME_BROWSER_UI_COMMANDER_COMMANDER_H_ - -#include <memory> - -#include "base/no_destructor.h" - -class Browser; - -namespace commander { - -class CommanderBackend; -class CommanderFrontend; - -// Returns true if the commander UI should be made available. -bool IsEnabled(); - -// A singleton which initializes and owns the components of the commander -// system. This is the boundary between commander internals and the rest of the -// browser. -class Commander { - public: - static Commander* Get(); - - // Initialize internal components. Must be called before any calls to - // ToggleForBrowser(). - void Initialize(); - - // Toggles the UI. There are three possible cases: - // If the UI is not showing, it will be shown attached to `browser`'s window. - // If the UI is showing on `browser`, it will be hidden. - // If the UI is showing on a different browser, it will be hidden, and then - // shown attached to `browser`'s window. - void ToggleForBrowser(Browser* browser); - - Commander(const Commander& other) = delete; - Commander& operator=(const Commander& other) = delete; - - private: - friend base::NoDestructor<Commander>; - - Commander(); - ~Commander(); - std::unique_ptr<CommanderFrontend> frontend_; - std::unique_ptr<CommanderBackend> backend_; -}; - -} // namespace commander - -#endif // CHROME_BROWSER_UI_COMMANDER_COMMANDER_H_
diff --git a/chrome/browser/ui/commander/commander_backend.h b/chrome/browser/ui/commander/commander_backend.h deleted file mode 100644 index ed6d27e..0000000 --- a/chrome/browser/ui/commander/commander_backend.h +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COMMANDER_COMMANDER_BACKEND_H_ -#define CHROME_BROWSER_UI_COMMANDER_COMMANDER_BACKEND_H_ - -#include <string> - -#include "base/functional/callback.h" - -class Browser; - -namespace commander { - -struct CommanderViewModel; - -// An abstract interface for an object that responds to input from the UI layer -// and responds with a view model representing results or some action. -class CommanderBackend { - public: - using ViewModelUpdateCallback = - base::RepeatingCallback<void(CommanderViewModel view_model)>; - CommanderBackend() = default; - virtual ~CommanderBackend() = default; - - // Called when user input changes. |text| is the full contents of - // the textfield. |browser| is the browser the commander UI is currently - // attached to. - virtual void OnTextChanged(const std::u16string& text, Browser* browser) = 0; - // Called when the user has selected (clicked or pressed enter) the option at - // |command_index| from the result set identified by |result_set_id|. - // If |result_set_id| is stale due to race conditions, this is a no-op to - // ensure that we don't perform an action the user didn't intend. - virtual void OnCommandSelected(size_t command_index, int result_set_id) = 0; - // Called when the user has cancelled entering a composite command. This - // should have the effect of returning the backend to the state it was in - // previous to the composite command being selected. - virtual void OnCompositeCommandCancelled() {} - // Sets the callback to be used when a fresh view model is ready to be - // displayed. Invocations of the callback are not necessarily 1:1 or - // synchronous with user input, since some command sources may be async or - // provide incremental results. - virtual void SetUpdateCallback(ViewModelUpdateCallback callback) = 0; - // Called when the UI layer is closed. This is a hook to allow the backend - // to release any bound state. - virtual void Reset() {} -}; - -} // namespace commander - -#endif // CHROME_BROWSER_UI_COMMANDER_COMMANDER_BACKEND_H_
diff --git a/chrome/browser/ui/commander/commander_controller.cc b/chrome/browser/ui/commander/commander_controller.cc deleted file mode 100644 index b866b38b..0000000 --- a/chrome/browser/ui/commander/commander_controller.cc +++ /dev/null
@@ -1,130 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/commander/commander_controller.h" - -#include "base/memory/ptr_util.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/commander/bookmark_command_source.h" -#include "chrome/browser/ui/commander/command_source.h" -#include "chrome/browser/ui/commander/commander_view_model.h" -#include "chrome/browser/ui/commander/open_url_command_source.h" -#include "chrome/browser/ui/commander/simple_command_source.h" -#include "chrome/browser/ui/commander/tab_command_source.h" -#include "chrome/browser/ui/commander/window_command_source.h" -#include "third_party/abseil-cpp/absl/types/variant.h" - -namespace commander { - -namespace { - -size_t constexpr kMaxResults = 8; - -CommanderController::CommandSources CreateDefaultSources() { - CommanderController::CommandSources sources; - sources.push_back(std::make_unique<SimpleCommandSource>()); - sources.push_back(std::make_unique<OpenURLCommandSource>()); - sources.push_back(std::make_unique<BookmarkCommandSource>()); - sources.push_back(std::make_unique<WindowCommandSource>()); - sources.push_back(std::make_unique<TabCommandSource>()); - return sources; -} - -} // namespace - -CommanderController::CommanderController() - : CommanderController(CreateDefaultSources()) {} - -CommanderController::CommanderController(CommandSources sources) - : current_result_set_id_(0), sources_(std::move(sources)) {} - -CommanderController::~CommanderController() = default; - -void CommanderController::OnTextChanged(const std::u16string& text, - Browser* browser) { - std::vector<std::unique_ptr<CommandItem>> items; - if (composite_command_provider_) { - items = composite_command_provider_.Run(text); - } else { - for (auto& source : sources_) { - auto commands = source->GetCommands(text, browser); - items.insert(items.end(), std::make_move_iterator(commands.begin()), - std::make_move_iterator(commands.end())); - } - } - - // Sort descending by score, then alphabetically. - size_t max_elements = std::min(items.size(), kMaxResults); - std::partial_sort( - std::begin(items), std::begin(items) + max_elements, std::end(items), - [](const std::unique_ptr<CommandItem>& left, - const std::unique_ptr<CommandItem>& right) { - return (left->score == right->score) ? left->title < right->title - : left->score > right->score; - }); - if (items.size() > kMaxResults) - items.resize(kMaxResults); - current_items_ = std::move(items); - CommanderViewModel vm; - vm.result_set_id = ++current_result_set_id_; - vm.action = CommanderViewModel::Action::kDisplayResults; - for (auto& item : current_items_) { - vm.items.emplace_back(*item); - } - callback_.Run(vm); -} - -void CommanderController::OnCommandSelected(size_t command_index, - int result_set_id) { - if (command_index >= current_items_.size() || - result_set_id != current_result_set_id_) - return; - - CommandItem* item = current_items_[command_index].get(); - if (item->GetType() == CommandItem::Type::kOneShot) { - base::OnceClosure command = - std::move(absl::get<base::OnceClosure>(item->command)); - // Dismiss the view. - CommanderViewModel vm; - vm.result_set_id = ++current_result_set_id_; - vm.action = CommanderViewModel::Action::kClose; - callback_.Run(vm); - - std::move(command).Run(); - } else { - CommandItem::CompositeCommand command = - absl::get<CommandItem::CompositeCommand>(item->command); - composite_command_provider_ = command.second; - // Tell the view to requery. - CommanderViewModel vm; - vm.result_set_id = ++current_result_set_id_; - vm.action = CommanderViewModel::Action::kPrompt; - vm.prompt_text = command.first; - callback_.Run(vm); - } -} - -void CommanderController::OnCompositeCommandCancelled() { - DCHECK(composite_command_provider_); - composite_command_provider_.Reset(); -} - -void CommanderController::SetUpdateCallback(ViewModelUpdateCallback callback) { - callback_ = std::move(callback); -} - -void CommanderController::Reset() { - current_items_.clear(); - if (composite_command_provider_) - composite_command_provider_.Reset(); -} - -// static -std::unique_ptr<CommanderController> -CommanderController::CreateWithSourcesForTesting(CommandSources sources) { - auto* instance = new CommanderController(std::move(sources)); - return base::WrapUnique(instance); -} - -} // namespace commander
diff --git a/chrome/browser/ui/commander/commander_controller.h b/chrome/browser/ui/commander/commander_controller.h deleted file mode 100644 index 94813fce..0000000 --- a/chrome/browser/ui/commander/commander_controller.h +++ /dev/null
@@ -1,50 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COMMANDER_COMMANDER_CONTROLLER_H_ -#define CHROME_BROWSER_UI_COMMANDER_COMMANDER_CONTROLLER_H_ - -#include "chrome/browser/ui/commander/commander_backend.h" - -#include "chrome/browser/ui/commander/command_source.h" - -namespace commander { - -// The primary CommanderBackend, responsible for aggregating results for -// multiple command sources. If the user selects a composite command (one -// that requires additional user input), this object delegates the -// CommandBackend implementation to |delegate_|. -class CommanderController : public CommanderBackend { - public: - using CommandSources = std::vector<std::unique_ptr<CommandSource>>; - CommanderController(); - ~CommanderController() override; - - // Disallow copy and assign. - CommanderController(const CommanderController& other) = delete; - CommanderController& operator=(const CommanderController& other) = delete; - - // CommanderBackend overrides. - void OnTextChanged(const std::u16string& text, Browser* browser) override; - void OnCommandSelected(size_t command_index, int result_set_id) override; - void OnCompositeCommandCancelled() override; - void SetUpdateCallback(ViewModelUpdateCallback callback) override; - void Reset() override; - - static std::unique_ptr<CommanderController> CreateWithSourcesForTesting( - CommandSources sources); - - private: - explicit CommanderController(CommandSources sources); - - std::vector<std::unique_ptr<CommandItem>> current_items_; - int current_result_set_id_; - CommandSources sources_; - ViewModelUpdateCallback callback_; - CommandItem::CompositeCommandProvider composite_command_provider_; -}; - -} // namespace commander - -#endif // CHROME_BROWSER_UI_COMMANDER_COMMANDER_CONTROLLER_H_
diff --git a/chrome/browser/ui/commander/commander_controller_unittest.cc b/chrome/browser/ui/commander/commander_controller_unittest.cc deleted file mode 100644 index 56670060..0000000 --- a/chrome/browser/ui/commander/commander_controller_unittest.cc +++ /dev/null
@@ -1,599 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/commander/commander_controller.h" - -#include <string> -#include <tuple> - -#include "base/functional/callback.h" -#include "base/functional/callback_helpers.h" -#include "base/memory/raw_ptr.h" -#include "base/run_loop.h" -#include "base/test/bind.h" -#include "chrome/browser/ui/commander/command_source.h" -#include "chrome/browser/ui/commander/commander_view_model.h" -#include "chrome/test/base/browser_with_test_window_test.h" - -namespace commander { - -namespace { - -class TestCommandSource : public CommandSource { - public: - using GetCommandsHandler = - base::RepeatingCallback<CommandResults(const std::u16string&, - Browser* browser)>; - explicit TestCommandSource(GetCommandsHandler handler) - : handler_(std::move(handler)) {} - ~TestCommandSource() override = default; - - CommandResults GetCommands(const std::u16string& input, - Browser* browser) const override { - invocations_.push_back(input); - return handler_.Run(input, browser); - } - - const std::vector<std::u16string>& invocations() const { - return invocations_; - } - - private: - mutable std::vector<std::u16string> invocations_; - GetCommandsHandler handler_; -}; - -std::unique_ptr<TestCommandSource> CreateNoOpCommandSource() { - return std::make_unique<TestCommandSource>(base::BindRepeating( - [](const std::u16string&, - Browser* browser) -> CommandSource::CommandResults { return {}; })); -} - -std::unique_ptr<CommandItem> CreateNoOpCommandItem(const std::u16string& title, - double score) { - std::vector<gfx::Range> ranges{{0, static_cast<uint32_t>(title.size())}}; - auto item = std::make_unique<CommandItem>(title, score, ranges); - item->command = base::DoNothing(); - return item; -} - -TestCommandSource* AddSource( - std::vector<std::unique_ptr<CommandSource>>* sources, - std::unique_ptr<TestCommandSource> source) { - TestCommandSource* bare_ptr = source.get(); - sources->push_back(std::move(source)); - return bare_ptr; -} - -} // namespace - -class CommanderControllerTest : public BrowserWithTestWindowTest { - public: - void SetUp() override { - BrowserWithTestWindowTest::SetUp(); - expected_count_ = 0; - } - - void ExpectViewModelCallbackCalls(int expected_count) { - expected_count_ += expected_count; - } - void WaitForExpectedCallbacks() { - if (expected_count_ <= 0) - return; - if (!run_loop_.get() || !run_loop_->running()) { - run_loop_ = std::make_unique<base::RunLoop>(); - run_loop_->Run(); - } - } - void OnViewModelUpdated(CommanderViewModel view_model) { - received_view_models_.push_back(view_model); - if (expected_count_ > 0) { - expected_count_--; - if (run_loop_.get() && expected_count_ == 0) - run_loop_->Quit(); - } - } - - protected: - std::unique_ptr<base::RunLoop> run_loop_; - int expected_count_; - std::vector<CommanderViewModel> received_view_models_; -}; - -class ViewModelCallbackWaiter { - public: - explicit ViewModelCallbackWaiter(CommanderControllerTest* test, int count = 1) - : test_(test) { - test_->ExpectViewModelCallbackCalls(count); - } - - ~ViewModelCallbackWaiter() { test_->WaitForExpectedCallbacks(); } - - private: - raw_ptr<CommanderControllerTest> test_; -}; - -TEST_F(CommanderControllerTest, PassesInputToCommandSourcesOnTextChanged) { - std::vector<std::unique_ptr<CommandSource>> sources; - TestCommandSource* first = AddSource(&sources, CreateNoOpCommandSource()); - TestCommandSource* second = AddSource(&sources, CreateNoOpCommandSource()); - - auto controller = - CommanderController::CreateWithSourcesForTesting(std::move(sources)); - controller->SetUpdateCallback(base::BindRepeating( - &CommanderControllerTest::OnViewModelUpdated, base::Unretained(this))); - - EXPECT_EQ(first->invocations().size(), 0u); - EXPECT_EQ(second->invocations().size(), 0u); - - std::u16string input = u"foobar"; - controller->OnTextChanged(input, browser()); - - EXPECT_EQ(first->invocations().size(), 1u); - EXPECT_EQ(second->invocations().size(), 1u); - - EXPECT_EQ(first->invocations().back(), input); - EXPECT_EQ(second->invocations().back(), input); -} - -TEST_F(CommanderControllerTest, ResultSetIdsDifferAcrossCalls) { - std::vector<std::unique_ptr<CommandSource>> sources; - std::ignore = AddSource(&sources, CreateNoOpCommandSource()); - base::RunLoop run_loop; - auto controller = - CommanderController::CreateWithSourcesForTesting(std::move(sources)); - controller->SetUpdateCallback(base::BindRepeating( - &CommanderControllerTest::OnViewModelUpdated, base::Unretained(this))); - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"foobar", browser()); - } - // Assert since we're accessing an element. - ASSERT_EQ(received_view_models_.size(), 1u); - int first_id = received_view_models_.back().result_set_id; - - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"barfoo", browser()); - } - EXPECT_EQ(received_view_models_.size(), 2u); - EXPECT_NE(received_view_models_.back().result_set_id, first_id); -} - -TEST_F(CommanderControllerTest, ViewModelAggregatesResults) { - std::vector<std::unique_ptr<CommandSource>> sources; - auto first = std::make_unique<TestCommandSource>( - base::BindRepeating([](const std::u16string&, Browser* browser) { - CommandSource::CommandResults result; - result.push_back(CreateNoOpCommandItem(u"first", 100)); - return result; - })); - auto second = std::make_unique<TestCommandSource>( - base::BindRepeating([](const std::u16string&, Browser* browser) { - CommandSource::CommandResults result; - auto item = CreateNoOpCommandItem(u"second", 99); - item->annotation = u"2nd"; - item->entity_type = CommandItem::Entity::kBookmark; - result.push_back(std::move(item)); - return result; - })); - sources.push_back(std::move(first)); - sources.push_back(std::move(second)); - - auto controller = - CommanderController::CreateWithSourcesForTesting(std::move(sources)); - controller->SetUpdateCallback(base::BindRepeating( - &CommanderControllerTest::OnViewModelUpdated, base::Unretained(this))); - - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"foobar", browser()); - } - ASSERT_EQ(received_view_models_.size(), 1u); - CommanderViewModel model = received_view_models_.back(); - ASSERT_EQ(model.items.size(), 2u); - - EXPECT_EQ(model.items[0].title, u"first"); - EXPECT_EQ(model.items[0].annotation, std::u16string()); - EXPECT_EQ(model.items[0].entity_type, CommandItem::Entity::kCommand); - - EXPECT_EQ(model.items[1].title, u"second"); - EXPECT_EQ(model.items[1].annotation, u"2nd"); - EXPECT_EQ(model.items[1].entity_type, CommandItem::Entity::kBookmark); -} - -// TODO(lgrey): This will need to change when scoring gets more sophisticated -// than a simple sort. -TEST_F(CommanderControllerTest, ViewModelSortsResults) { - std::vector<std::unique_ptr<CommandSource>> sources; - auto first = std::make_unique<TestCommandSource>( - base::BindRepeating([](const std::u16string&, Browser* browser) { - CommandSource::CommandResults result; - result.push_back(CreateNoOpCommandItem(u"third", 98)); - result.push_back(CreateNoOpCommandItem(u"first", 100)); - result.push_back(CreateNoOpCommandItem(u"fourth", 90)); - - return result; - })); - auto second = std::make_unique<TestCommandSource>( - base::BindRepeating([](const std::u16string&, Browser* browser) { - CommandSource::CommandResults result; - result.push_back(CreateNoOpCommandItem(u"second", 99)); - result.push_back(CreateNoOpCommandItem(u"fifth", 1)); - return result; - })); - sources.push_back(std::move(first)); - sources.push_back(std::move(second)); - - auto controller = - CommanderController::CreateWithSourcesForTesting(std::move(sources)); - controller->SetUpdateCallback(base::BindRepeating( - &CommanderControllerTest::OnViewModelUpdated, base::Unretained(this))); - - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"foobar", browser()); - } - ASSERT_EQ(received_view_models_.size(), 1u); - CommanderViewModel model = received_view_models_.back(); - ASSERT_EQ(model.items.size(), 5u); - EXPECT_EQ(model.items[0].title, u"first"); - EXPECT_EQ(model.items[1].title, u"second"); - EXPECT_EQ(model.items[2].title, u"third"); - EXPECT_EQ(model.items[3].title, u"fourth"); - EXPECT_EQ(model.items[4].title, u"fifth"); -} - -TEST_F(CommanderControllerTest, ViewModelSortsSameScoreAlphabetically) { - std::vector<std::unique_ptr<CommandSource>> sources; - auto source = std::make_unique<TestCommandSource>( - base::BindRepeating([](const std::u16string&, Browser* browser) { - CommandSource::CommandResults result; - result.push_back(CreateNoOpCommandItem(u"clementine", 100)); - result.push_back(CreateNoOpCommandItem(u"apple", 100)); - result.push_back(CreateNoOpCommandItem(u"banana", 100)); - - return result; - })); - sources.push_back(std::move(source)); - auto controller = - CommanderController::CreateWithSourcesForTesting(std::move(sources)); - controller->SetUpdateCallback(base::BindRepeating( - &CommanderControllerTest::OnViewModelUpdated, base::Unretained(this))); - - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"foobar", browser()); - } - ASSERT_EQ(received_view_models_.size(), 1u); - CommanderViewModel model = received_view_models_.back(); - ASSERT_EQ(model.items.size(), 3u); - EXPECT_EQ(model.items[0].title, u"apple"); - EXPECT_EQ(model.items[1].title, u"banana"); - EXPECT_EQ(model.items[2].title, u"clementine"); -} - -TEST_F(CommanderControllerTest, ViewModelRetainsBoldRanges) { - std::vector<std::unique_ptr<CommandSource>> sources; - auto source = std::make_unique<TestCommandSource>( - base::BindRepeating([=](const std::u16string&, Browser* browser) { - auto first = CreateNoOpCommandItem(u"first", 100); - auto second = CreateNoOpCommandItem(u"second", 99); - first->matched_ranges.clear(); - first->matched_ranges.emplace_back(0, 2); - first->matched_ranges.emplace_back(4, 1); - second->matched_ranges.clear(); - second->matched_ranges.emplace_back(1, 4); - CommandSource::CommandResults result; - result.push_back(std::move(first)); - result.push_back(std::move(second)); - return result; - })); - sources.push_back(std::move(source)); - auto controller = - CommanderController::CreateWithSourcesForTesting(std::move(sources)); - controller->SetUpdateCallback(base::BindRepeating( - &CommanderControllerTest::OnViewModelUpdated, base::Unretained(this))); - - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"foobar", browser()); - } - ASSERT_EQ(received_view_models_.size(), 1u); - CommanderViewModel model = received_view_models_.back(); - // Ensure |first| is at index 0; - EXPECT_EQ(model.items[0].title, u"first"); - std::vector<gfx::Range> first_ranges = {gfx::Range(0, 2), gfx::Range(4, 1)}; - std::vector<gfx::Range> second_ranges = {gfx::Range(1, 4)}; - EXPECT_EQ(model.items[0].matched_ranges, first_ranges); - EXPECT_EQ(model.items[1].matched_ranges, second_ranges); -} - -TEST_F(CommanderControllerTest, OnCommandSelectedInvokesOneShotCommand) { - std::vector<std::unique_ptr<CommandSource>> sources; - bool first_called = false; - bool second_called = false; - auto source = std::make_unique<TestCommandSource>(base::BindRepeating( - [](bool* first_called_ptr, bool* second_called_ptr, const std::u16string&, - Browser* browser) { - auto first = CreateNoOpCommandItem(u"first", 100); - auto second = CreateNoOpCommandItem(u"second", 99); - first->command = base::BindOnce([](bool* called) { *called = true; }, - first_called_ptr); - second->command = base::BindOnce([](bool* called) { *called = true; }, - second_called_ptr); - CommandSource::CommandResults result; - result.push_back(std::move(first)); - result.push_back(std::move(second)); - return result; - }, - &first_called, &second_called)); - sources.push_back(std::move(source)); - auto controller = - CommanderController::CreateWithSourcesForTesting(std::move(sources)); - controller->SetUpdateCallback(base::BindRepeating( - &CommanderControllerTest::OnViewModelUpdated, base::Unretained(this))); - - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"foobar", browser()); - } - ASSERT_EQ(received_view_models_.size(), 1u); - CommanderViewModel model = received_view_models_.back(); - // Ensure |first| is at index 0; - EXPECT_EQ(model.items[0].title, u"first"); - - { - ViewModelCallbackWaiter waiter(this); - controller->OnCommandSelected(0, model.result_set_id); - } - EXPECT_TRUE(first_called); - EXPECT_FALSE(second_called); - EXPECT_EQ(received_view_models_.size(), 2u); - EXPECT_EQ(received_view_models_.back().action, - CommanderViewModel::Action::kClose); -} - -TEST_F(CommanderControllerTest, NoActionOnIncorrectResultId) { - std::vector<std::unique_ptr<CommandSource>> sources; - bool item_called = false; - auto source = std::make_unique<TestCommandSource>(base::BindRepeating( - [](bool* called_ptr, const std::u16string&, Browser* browser) { - auto item = CreateNoOpCommandItem(u"first", 100); - item->command = - base::BindOnce([](bool* called) { *called = true; }, called_ptr); - CommandSource::CommandResults result; - result.push_back(std::move(item)); - return result; - }, - &item_called)); - sources.push_back(std::move(source)); - auto controller = - CommanderController::CreateWithSourcesForTesting(std::move(sources)); - controller->SetUpdateCallback(base::BindRepeating( - &CommanderControllerTest::OnViewModelUpdated, base::Unretained(this))); - - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"foobar", browser()); - } - ASSERT_EQ(received_view_models_.size(), 1u); - CommanderViewModel model = received_view_models_.back(); - - controller->OnCommandSelected(0, model.result_set_id - 1); - - EXPECT_FALSE(item_called); -} - -TEST_F(CommanderControllerTest, NoActionOnOOBIndex) { - std::vector<std::unique_ptr<CommandSource>> sources; - bool item_called = false; - auto source = std::make_unique<TestCommandSource>(base::BindRepeating( - [](bool* called_ptr, const std::u16string&, Browser* browser) { - auto item = CreateNoOpCommandItem(u"first", 100); - item->command = - base::BindOnce([](bool* called) { *called = true; }, called_ptr); - CommandSource::CommandResults result; - result.push_back(std::move(item)); - return result; - }, - &item_called)); - sources.push_back(std::move(source)); - auto controller = - CommanderController::CreateWithSourcesForTesting(std::move(sources)); - controller->SetUpdateCallback(base::BindRepeating( - &CommanderControllerTest::OnViewModelUpdated, base::Unretained(this))); - - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"foobar", browser()); - } - ASSERT_EQ(received_view_models_.size(), 1u); - CommanderViewModel model = received_view_models_.back(); - controller->OnCommandSelected(1, model.result_set_id); - - EXPECT_FALSE(item_called); -} - -TEST_F(CommanderControllerTest, InvokingCompositeCommandSendsPrompt) { - std::vector<std::unique_ptr<CommandSource>> sources; - auto source = std::make_unique<TestCommandSource>( - base::BindRepeating([](const std::u16string&, Browser* browser) { - auto item = CreateNoOpCommandItem(u"first", 100); - CommandItem::CompositeCommandProvider noop = - base::BindRepeating([](const std::u16string&) { - return CommandSource::CommandResults(); - }); - item->command = std::make_pair(u"Do stuff", noop); - CommandSource::CommandResults result; - result.push_back(std::move(item)); - return result; - })); - sources.push_back(std::move(source)); - auto controller = - CommanderController::CreateWithSourcesForTesting(std::move(sources)); - controller->SetUpdateCallback(base::BindRepeating( - &CommanderControllerTest::OnViewModelUpdated, base::Unretained(this))); - - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"abracadabra", browser()); - } - ASSERT_EQ(received_view_models_.size(), 1u); - { - ViewModelCallbackWaiter waiter(this); - controller->OnCommandSelected(0, - received_view_models_.back().result_set_id); - } - EXPECT_EQ(received_view_models_.back().action, - CommanderViewModel::Action::kPrompt); - EXPECT_EQ(received_view_models_.back().prompt_text, u"Do stuff"); -} - -TEST_F(CommanderControllerTest, OnTextChangedPassedToCompositeCommandProvider) { - std::vector<std::unique_ptr<CommandSource>> sources; - std::u16string received_string; - auto source = std::make_unique<TestCommandSource>(base::BindRepeating( - [](std::u16string* passthrough_string, const std::u16string& string, - Browser* browser) { - auto item = CreateNoOpCommandItem(u"first", 100); - CommandItem::CompositeCommandProvider provider = base::BindRepeating( - [](std::u16string* out_string, const std::u16string& string) { - *out_string = string; - return CommandSource::CommandResults(); - }, - passthrough_string); - item->command = std::make_pair(u"Do stuff", provider); - CommandSource::CommandResults result; - result.push_back(std::move(item)); - return result; - }, - &received_string)); - sources.push_back(std::move(source)); - auto controller = - CommanderController::CreateWithSourcesForTesting(std::move(sources)); - controller->SetUpdateCallback(base::BindRepeating( - &CommanderControllerTest::OnViewModelUpdated, base::Unretained(this))); - - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"abracadabra", browser()); - } - ASSERT_EQ(received_view_models_.size(), 1u); - { - ViewModelCallbackWaiter waiter(this); - - controller->OnCommandSelected(0, - received_view_models_.back().result_set_id); - } - - controller->OnTextChanged(u"hocus pocus", browser()); - EXPECT_EQ(received_string, u"hocus pocus"); -} - -TEST_F(CommanderControllerTest, - CompositeProviderCommandsArePresentedAndExecuted) { - std::vector<std::unique_ptr<CommandSource>> sources; - auto source = std::make_unique<TestCommandSource>( - base::BindRepeating([](const std::u16string&, Browser* browser) { - auto outer = CreateNoOpCommandItem(u"outer", 100); - CommandItem::CompositeCommandProvider provider = - base::BindRepeating([](const std::u16string&) { - CommandSource::CommandResults results; - auto inner = CreateNoOpCommandItem(u"inner", 100); - inner->command = base::MakeExpectedRunClosure(FROM_HERE); - results.push_back(std::move(inner)); - return results; - }); - outer->command = std::make_pair(u"Do stuff", provider); - CommandSource::CommandResults result; - result.push_back(std::move(outer)); - return result; - })); - sources.push_back(std::move(source)); - auto controller = - CommanderController::CreateWithSourcesForTesting(std::move(sources)); - controller->SetUpdateCallback(base::BindRepeating( - &CommanderControllerTest::OnViewModelUpdated, base::Unretained(this))); - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"abracadabra", browser()); - } - - ASSERT_EQ(received_view_models_.size(), 1u); - // Select composite command. - { - ViewModelCallbackWaiter waiter(this); - controller->OnCommandSelected(0, - received_view_models_.back().result_set_id); - } - // Query again. Controller should pull results from the composite provider - // this time. - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"hocus pocus", browser()); - } - ASSERT_EQ(received_view_models_.size(), 3u); - EXPECT_EQ(received_view_models_.back().items[0].title, u"inner"); - - controller->OnCommandSelected(0, received_view_models_.back().result_set_id); - // Inner command is an ExpectedRunClosure, so we will fail here if it wasn't - // called, without needing to assert anything. -} - -TEST_F(CommanderControllerTest, OnCompositeCommandCancelledRemovesProvider) { - std::vector<std::unique_ptr<CommandSource>> sources; - TestCommandSource* source = AddSource( - &sources, - std::make_unique<TestCommandSource>( - base::BindRepeating([](const std::u16string&, Browser* browser) { - auto item = CreateNoOpCommandItem(u"first", 100); - CommandItem::CompositeCommandProvider noop = - base::BindRepeating([](const std::u16string&) { - return CommandSource::CommandResults(); - }); - item->command = std::make_pair(u"Do stuff", noop); - CommandSource::CommandResults result; - result.push_back(std::move(item)); - return result; - }))); - auto controller = - CommanderController::CreateWithSourcesForTesting(std::move(sources)); - controller->SetUpdateCallback(base::BindRepeating( - &CommanderControllerTest::OnViewModelUpdated, base::Unretained(this))); - - // Prime the sources so we can select an item. - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"abracadabra", browser()); - } - EXPECT_EQ(source->invocations().size(), 1u); - - // Selecting - { - ViewModelCallbackWaiter waiter(this); - controller->OnCommandSelected(0, - received_view_models_.back().result_set_id); - } - ASSERT_EQ(received_view_models_.size(), 2u); - EXPECT_EQ(received_view_models_.back().action, - CommanderViewModel::Action::kPrompt); - // This should go to the provider and not be seen by the source. - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"alakazam", browser()); - } - EXPECT_EQ(source->invocations().size(), 1u); - - controller->OnCompositeCommandCancelled(); - // Composite command was cancelled, so the source should see this one. - { - ViewModelCallbackWaiter waiter(this); - controller->OnTextChanged(u"hocus pocus", browser()); - } - EXPECT_EQ(source->invocations().size(), 2u); - EXPECT_EQ(source->invocations().back(), u"hocus pocus"); -} - -} // namespace commander
diff --git a/chrome/browser/ui/commander/commander_frontend.h b/chrome/browser/ui/commander/commander_frontend.h deleted file mode 100644 index 724a9e5d9..0000000 --- a/chrome/browser/ui/commander/commander_frontend.h +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COMMANDER_COMMANDER_FRONTEND_H_ -#define CHROME_BROWSER_UI_COMMANDER_COMMANDER_FRONTEND_H_ - -#include <memory> - -class Browser; - -namespace commander { - -class CommanderBackend; - -// Abstract interface for the commander UI. -class CommanderFrontend { - public: - CommanderFrontend() = default; - virtual ~CommanderFrontend() = default; - - // If the UI is currently showing for |browser|, hides it. - // If the UI is currently showing for a different browser, - // hides it, then shows it for |browser|. - // If the UI is not showing, shows it for |browser|. - virtual void ToggleForBrowser(Browser* browser) = 0; - // Show the UI, anchored to |browser|'s window. - virtual void Show(Browser* browser) = 0; - // Hide the UI, if showing. - virtual void Hide() = 0; - - static std::unique_ptr<CommanderFrontend> Create(CommanderBackend* backend); - - // Disallow copy and assign - CommanderFrontend(const CommanderFrontend& other) = delete; - CommanderFrontend& operator=(const CommanderFrontend& other) = delete; -}; - -} // namespace commander - -#endif // CHROME_BROWSER_UI_COMMANDER_COMMANDER_FRONTEND_H_
diff --git a/chrome/browser/ui/commander/commander_view_model.cc b/chrome/browser/ui/commander/commander_view_model.cc deleted file mode 100644 index 0b6af743..0000000 --- a/chrome/browser/ui/commander/commander_view_model.cc +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/commander/commander_view_model.h" - -namespace commander { - -CommandItemViewModel::CommandItemViewModel( - const std::u16string& title, - const std::vector<gfx::Range>& matched_ranges, - CommandItem::Entity entity_type, - const std::u16string& annotation) - : title(title), - matched_ranges(matched_ranges), - entity_type(entity_type), - annotation(annotation) {} - -CommandItemViewModel::CommandItemViewModel(const CommandItem& item) - : CommandItemViewModel(item.title, - item.matched_ranges, - item.entity_type, - item.annotation) {} -CommandItemViewModel::~CommandItemViewModel() = default; -CommandItemViewModel::CommandItemViewModel(const CommandItemViewModel& other) = - default; - -CommanderViewModel::CommanderViewModel() = default; -CommanderViewModel::~CommanderViewModel() = default; -CommanderViewModel::CommanderViewModel(const CommanderViewModel& other) = - default; - -} // namespace commander
diff --git a/chrome/browser/ui/commander/commander_view_model.h b/chrome/browser/ui/commander/commander_view_model.h deleted file mode 100644 index d27f079..0000000 --- a/chrome/browser/ui/commander/commander_view_model.h +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COMMANDER_COMMANDER_VIEW_MODEL_H_ -#define CHROME_BROWSER_UI_COMMANDER_COMMANDER_VIEW_MODEL_H_ - -#include <string> -#include <vector> - -#include "chrome/browser/ui/commander/command_source.h" -#include "ui/gfx/range/range.h" - -namespace commander { - -// A view model for a single command to be presented by the commander UI. -struct CommandItemViewModel { - public: - CommandItemViewModel( - const std::u16string& title, - const std::vector<gfx::Range>& matched_ranges, - CommandItem::Entity entity_type = CommandItem::Entity::kCommand, - const std::u16string& annotation = std::u16string()); - explicit CommandItemViewModel(const CommandItem& item); - ~CommandItemViewModel(); - CommandItemViewModel(const CommandItemViewModel& other); - // The displayed title of the command. - std::u16string title; - // The locations of spans in |title| that should be emphasised to - // indicate to the user why the command was surfaced for their input. - std::vector<gfx::Range> matched_ranges; - // See CommandItem::Entity documentation. - CommandItem::Entity entity_type; - // Optional secondary text for the command. Typically used to display a - // hotkey. - std::u16string annotation; -}; - -// A view model for a set of results to be presented by the commander UI. -struct CommanderViewModel { - // The action - enum Action { - // Display the items in |items|. - kDisplayResults, - // Close the UI. Typically sent after a command has been executed. - kClose, - // Clear the input and requery. Sent when the user has selected a command - // that needs further user input. - kPrompt, - }; - - public: - CommanderViewModel(); - ~CommanderViewModel(); - CommanderViewModel(const CommanderViewModel& other); - // An identifier for this result set. See discussion in - // commander_backend.h for more details. - int result_set_id; - // A pre-ranked list of items to display. Can be empty if there are - // no results, or `action` is not kDisplayResults. - std::vector<CommandItemViewModel> items; - // Prompt text to be shown when entering a composite command. Should only - // be populated if and only if `action` is kPrompt. - std::u16string prompt_text; - // The action the view should take in response to receiving this view model. - Action action; -}; - -} // namespace commander - -#endif // CHROME_BROWSER_UI_COMMANDER_COMMANDER_VIEW_MODEL_H_
diff --git a/chrome/browser/ui/commander/entity_match.cc b/chrome/browser/ui/commander/entity_match.cc deleted file mode 100644 index ac44181c..0000000 --- a/chrome/browser/ui/commander/entity_match.cc +++ /dev/null
@@ -1,185 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/commander/entity_match.h" - -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_list.h" -#include "chrome/browser/ui/commander/fuzzy_finder.h" -#include "chrome/browser/ui/tabs/tab_group.h" -#include "chrome/browser/ui/tabs/tab_group_model.h" -#include "chrome/browser/ui/tabs/tab_utils.h" -#include "components/sessions/content/session_tab_helper.h" - -namespace commander { - -namespace { -// TODO(lgrey): Just guessing for now! Not even sure if we need a max width, -// but right now, the code that does "<title> and x other tabs" wants a max. -double constexpr kMaxTitleWidth = 1000; - -} // namespace - -WindowMatch::WindowMatch(Browser* browser, - const std::u16string& title, - double score) - : browser(browser), title(title), score(score) {} -WindowMatch::~WindowMatch() = default; -WindowMatch::WindowMatch(WindowMatch&& other) = default; -WindowMatch& WindowMatch::operator=(WindowMatch&& other) = default; - -std::unique_ptr<CommandItem> WindowMatch::ToCommandItem() const { - auto item = std::make_unique<CommandItem>(title, score, matched_ranges); - item->entity_type = CommandItem::Entity::kWindow; - return item; -} - -GroupMatch::GroupMatch(tab_groups::TabGroupId group, - const std::u16string& title, - double score) - : group(group), title(title), score(score) {} -GroupMatch::~GroupMatch() = default; -GroupMatch::GroupMatch(GroupMatch&& other) = default; -GroupMatch& GroupMatch::operator=(GroupMatch&& other) = default; - -std::unique_ptr<CommandItem> GroupMatch::ToCommandItem() const { - auto item = std::make_unique<CommandItem>(title, score, matched_ranges); - item->entity_type = CommandItem::Entity::kGroup; - return item; -} - -TabMatch::TabMatch(int index, - int session_id, - const std::u16string& title, - double score) - : index(index), session_id(session_id), title(title), score(score) {} -TabMatch::~TabMatch() = default; -TabMatch::TabMatch(TabMatch&& other) = default; -TabMatch& TabMatch::operator=(TabMatch&& other) = default; - -std::unique_ptr<CommandItem> TabMatch::ToCommandItem() const { - auto item = std::make_unique<CommandItem>(title, score, matched_ranges); - item->entity_type = CommandItem::Entity::kTab; - return item; -} - -TabSearchOptions::TabSearchOptions() = default; -TabSearchOptions::~TabSearchOptions() = default; - -std::vector<TabMatch> TabsMatchingInput(const Browser* browser, - const std::u16string& input, - const TabSearchOptions& options) { - DCHECK(browser); - DCHECK(!(options.only_pinned && options.only_unpinned)); - DCHECK(!(options.only_audible && options.only_muted)); - DCHECK(!options.exclude_tab_group.has_value() || - options.exclude_tab_group != options.only_tab_group); - double ordering_score = 1.0; - std::vector<TabMatch> results; - FuzzyFinder finder(input); - std::vector<gfx::Range> ranges; - TabStripModel* tab_strip_model = browser->tab_strip_model(); - for (int i = 0; i < tab_strip_model->count(); ++i) { - if (tab_strip_model->IsTabPinned(i) ? options.only_unpinned - : options.only_pinned) { - continue; - } - content::WebContents* contents = tab_strip_model->GetWebContentsAt(i); - if (options.only_audible && !contents->IsCurrentlyAudible()) - continue; - if (options.only_muted && !contents->IsAudioMuted()) - continue; - auto group = tab_strip_model->GetTabGroupForTab(i); - if (options.only_tab_group.has_value() && options.only_tab_group != group) - continue; - if (options.exclude_tab_group.has_value() && - options.exclude_tab_group == group) - continue; - - auto title = contents->GetTitle(); - if (input.empty()) { - TabMatch match(i, sessions::SessionTabHelper::IdForTab(contents).id(), - title, ordering_score); - results.push_back(std::move(match)); - ordering_score *= .95; - } else { - double score = finder.Find(title, &ranges); - if (score > 0) { - TabMatch match(i, sessions::SessionTabHelper::IdForTab(contents).id(), - title, score); - match.matched_ranges = ranges; - results.push_back(std::move(match)); - } - } - } - return results; -} - -std::vector<WindowMatch> WindowsMatchingInput(const Browser* browser_to_exclude, - const std::u16string& input, - bool match_profile) { - std::vector<WindowMatch> results; - double mru_score = .95; - FuzzyFinder finder(input); - std::vector<gfx::Range> ranges; - for (Browser* browser : BrowserList::GetInstance()->OrderedByActivation()) { - if (browser == browser_to_exclude || !browser->is_type_normal()) - continue; - if (match_profile && browser->profile() != browser_to_exclude->profile()) - continue; - std::u16string title = browser->GetWindowTitleForMaxWidth(kMaxTitleWidth); - if (input.empty()) { - WindowMatch match(browser, title, mru_score); - results.push_back(std::move(match)); - mru_score *= .95; - } else { - double score = finder.Find(title, &ranges); - if (score > 0) { - WindowMatch match(browser, std::move(title), score); - match.matched_ranges = ranges; - results.push_back(std::move(match)); - } - } - } - return results; -} - -std::vector<GroupMatch> GroupsMatchingInput( - const Browser* browser, - const std::u16string& input, - std::optional<tab_groups::TabGroupId> group_to_exclude) { - DCHECK(browser); - std::vector<GroupMatch> results; - FuzzyFinder finder(input); - std::vector<gfx::Range> ranges; - TabGroupModel* model = browser->tab_strip_model()->group_model(); - if (!model) - return results; - // For empty input, use this to preserve TabGroupModel's ordering, which is - // arbitrary but still helpful to keep consistent across calls and surfaces. - double ordering_score = .95; - for (const tab_groups::TabGroupId& group_id : model->ListTabGroups()) { - if (group_to_exclude == group_id) - continue; - TabGroup* group = model->GetTabGroup(group_id); - const std::u16string& group_title = group->visual_data()->title(); - const std::u16string& title = - group_title.empty() ? group->GetContentString() : group_title; - if (input.empty()) { - GroupMatch match(group_id, title, ordering_score); - results.push_back(std::move(match)); - ordering_score *= .95; - } else { - double score = finder.Find(title, &ranges); - if (score > 0) { - GroupMatch match(group_id, title, score); - match.matched_ranges = ranges; - results.push_back(std::move(match)); - } - } - } - return results; -} - -} // namespace commander
diff --git a/chrome/browser/ui/commander/entity_match.h b/chrome/browser/ui/commander/entity_match.h deleted file mode 100644 index 86f3dfc..0000000 --- a/chrome/browser/ui/commander/entity_match.h +++ /dev/null
@@ -1,126 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COMMANDER_ENTITY_MATCH_H_ -#define CHROME_BROWSER_UI_COMMANDER_ENTITY_MATCH_H_ - -#include <memory> -#include <optional> -#include <string> -#include <vector> - -#include "base/memory/raw_ptr.h" -#include "chrome/browser/ui/commander/command_source.h" -#include "components/sessions/core/session_id.h" -#include "components/tab_groups/tab_group_id.h" -#include "ui/gfx/range/range.h" - -class Browser; - -namespace commander { - -// Intermediate result type for browser windows that are eligible to be -// presented to the user as an option for a particular command. -struct WindowMatch { - WindowMatch(Browser* browser, const std::u16string& title, double score); - ~WindowMatch(); - - WindowMatch(WindowMatch&& other); - WindowMatch& operator=(WindowMatch&& other); - - std::unique_ptr<CommandItem> ToCommandItem() const; - - raw_ptr<Browser> browser; - std::u16string title; - std::vector<gfx::Range> matched_ranges; - double score; -}; -// Intermediate result type for tab groups that are eligible to be -// presented to the user as an option for a particular command. -struct GroupMatch { - GroupMatch(tab_groups::TabGroupId group, - const std::u16string& title, - double score); - ~GroupMatch(); - - GroupMatch(GroupMatch&& other); - GroupMatch& operator=(GroupMatch&& other); - - std::unique_ptr<CommandItem> ToCommandItem() const; - - tab_groups::TabGroupId group; - std::u16string title; - std::vector<gfx::Range> matched_ranges; - double score; -}; - -// Intermediate result type for tabs that are eligible to be -// presented to the user as an option for a particular command. -struct TabMatch { - TabMatch(int index, - int session_id, - const std::u16string& title, - double score); - ~TabMatch(); - - TabMatch(TabMatch&& other); - TabMatch& operator=(TabMatch&& other); - - std::unique_ptr<CommandItem> ToCommandItem() const; - - // Index in tab strip. - int index; - // As obtained by sessions::SessionTabHelper::IdForTab. Used to ensure that - // the tab at `index` is the one we expect for destructive actions. - int session_id; - std::u16string title; - std::vector<gfx::Range> matched_ranges; - double score; -}; - -// Returns browser windows whose titles fuzzy match `input`. If input is empty, -// returns all eligible browser windows with score reflecting MRU order. -// `browser_to_exclude` is excluded from the list, as are all browser windows -// from a different profile unless `match_profile` is false. -std::vector<WindowMatch> WindowsMatchingInput(const Browser* browser_to_exclude, - const std::u16string& input, - bool match_profile = false); - -// Returns tab groups in `browser` whose titles fuzzy match `input`. If input is -// empty, returns all groups in an arbitrary order. If `group_to_exclude` is -// set, it is excluded from the list. -std::vector<GroupMatch> GroupsMatchingInput( - const Browser* browser, - const std::u16string& input, - std::optional<tab_groups::TabGroupId> group_to_exclude = std::nullopt); - -// Options for narrowing results from `TabsMatchingInput`. -struct TabSearchOptions { - TabSearchOptions(); - ~TabSearchOptions(); - // Return only pinned tabs. Mutually exclusive with `only_unpinned`. - bool only_pinned = false; - // Return only unpinned tabs. Mutually exclusive with `only_pinned`. - bool only_unpinned = false; - // Return only audible tabs. Mutually exclusive with `only_muted`. - bool only_audible = false; - // Return only muted tabs. Mutually exclusive with `only_audible`. - bool only_muted = false; - // Exclude tabs that belong to this group. Explicitly setting this to the - // same value as `only_tab_group` is invalid. - std::optional<tab_groups::TabGroupId> exclude_tab_group = std::nullopt; - // Exclude tabs that do not belong to this group. Explicitly setting this to - // the same value as `exclude_tab_group` is invalid. - std::optional<tab_groups::TabGroupId> only_tab_group = std::nullopt; -}; - -// Returns tabs in `browser` whose titles fuzzy match `input`. If input is -// empty, returns all groups in the order they appear in the tab strip. -std::vector<TabMatch> TabsMatchingInput(const Browser* browser, - const std::u16string& input, - const TabSearchOptions& options = {}); - -} // namespace commander - -#endif // CHROME_BROWSER_UI_COMMANDER_ENTITY_MATCH_H_
diff --git a/chrome/browser/ui/commander/entity_match_unittest.cc b/chrome/browser/ui/commander/entity_match_unittest.cc deleted file mode 100644 index ed1bf95..0000000 --- a/chrome/browser/ui/commander/entity_match_unittest.cc +++ /dev/null
@@ -1,293 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/commander/entity_match.h" - -#include "base/ranges/algorithm.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/ui/browser_list.h" -#include "chrome/browser/ui/commander/command_source.h" -#include "chrome/browser/ui/tabs/tab_group.h" -#include "chrome/browser/ui/tabs/tab_group_model.h" -#include "chrome/test/base/browser_with_test_window_test.h" -#include "chrome/test/base/test_browser_window.h" -#include "chrome/test/base/testing_profile.h" -#include "chrome/test/base/testing_profile_manager.h" -#include "components/tab_groups/tab_group_id.h" -#include "content/public/test/web_contents_tester.h" - -namespace commander { - -class CommanderEntityMatchTest : public BrowserWithTestWindowTest { - public: - void SetUp() override { - BrowserWithTestWindowTest::SetUp(); - BrowserList::GetInstance()->SetLastActive(browser()); - } - - // Creates and returns a browser with `title` as its user title. - // If `profile` is provided, it is used, otherwise uses the profile of this - // test's browser. - std::unique_ptr<Browser> CreateAndActivateBrowser( - const std::string& title, - Profile* browser_profile = nullptr) { - Browser::CreateParams params(browser_profile ? browser_profile : profile(), - true); - auto browser = CreateBrowserWithTestWindowForParams(params); - browser->SetWindowUserTitle(title); - BrowserList::GetInstance()->SetLastActive(browser.get()); - return browser; - } - - // Creates a tab per string in |titles|, then places each one in a group, - // titled with the corresponding string. - void CreateGroups(std::vector<std::u16string> titles) { - // Create the tabs first so they don't get autogrouped and make odd things - // happen. - for (size_t i = 0; i < titles.size(); ++i) - AddTab(browser(), GURL("chrome://newtab")); - TabStripModel* tab_strip_model = browser()->tab_strip_model(); - TabGroupModel* group_model = tab_strip_model->group_model(); - for (size_t i = 0; i < titles.size(); ++i) { - tab_groups::TabGroupId group = - tab_strip_model->AddToNewGroup({static_cast<int>(i)}); - tab_groups::TabGroupVisualData data( - titles.at(i), tab_groups::TabGroupColorId::kGrey, false); - group_model->GetTabGroup(group)->SetVisualData(data); - } - } - - void CreateTabs(std::vector<std::u16string> titles) { - for (const auto& title : titles) { - GURL url("chrome://newtab"); - AddTab(browser(), url); - NavigateAndCommitActiveTabWithTitle(browser(), url, title); - } - } -}; - -TEST_F(CommanderEntityMatchTest, WindowExcludesCurrentBrowser) { - std::string title("Title"); - browser()->SetWindowUserTitle(title); - auto other_browser = CreateAndActivateBrowser(title); - - auto matches = - WindowsMatchingInput(browser(), base::UTF8ToUTF16(title), false); - EXPECT_EQ(matches.size(), 1u); -} - -TEST_F(CommanderEntityMatchTest, WindowIncludesAllProfilesIfUnrestricted) { - std::string title("Title"); - - auto same_profile_browser = CreateAndActivateBrowser(title); - TestingProfile* other_profile = - profile_manager()->CreateTestingProfile("other"); - auto other_profile_browser = CreateAndActivateBrowser(title, other_profile); - - auto matches = - WindowsMatchingInput(browser(), base::UTF8ToUTF16(title), false); - EXPECT_EQ(matches.size(), 2u); -} - -TEST_F(CommanderEntityMatchTest, WindowOmitsNonmatchingProfilesIfRestricted) { - std::string title("Title"); - auto same_profile_browser = CreateAndActivateBrowser(title); - - TestingProfile* other_profile = - profile_manager()->CreateTestingProfile("other"); - auto other_profile_browser = CreateAndActivateBrowser(title, other_profile); - - auto matches = - WindowsMatchingInput(browser(), base::UTF8ToUTF16(title), true); - ASSERT_EQ(matches.size(), 1u); - EXPECT_EQ(matches.at(0).browser, same_profile_browser.get()); -} - -TEST_F(CommanderEntityMatchTest, WindowOnlyIncludesMatches) { - auto browser_with_match = CreateAndActivateBrowser("Orange juice"); - auto browser_without_match = CreateAndActivateBrowser("Aqua regia"); - - auto matches = WindowsMatchingInput(browser(), u"orange", true); - ASSERT_EQ(matches.size(), 1u); - EXPECT_EQ(matches.at(0).browser, browser_with_match.get()); -} - -TEST_F(CommanderEntityMatchTest, WindowRanksMatches) { - auto browser_best_match = CreateAndActivateBrowser("Orange juice"); - auto browser_good_match = - CreateAndActivateBrowser("Oracular Nouns Gesture Electrically"); - - auto matches = WindowsMatchingInput(browser(), u"orange", true); - ASSERT_EQ(matches.size(), 2u); - base::ranges::sort(matches, std::greater<>(), &WindowMatch::score); - EXPECT_EQ(matches.at(0).browser, browser_best_match.get()); -} - -TEST_F(CommanderEntityMatchTest, WindowMRUOrderWithNoInput) { - auto browser1 = CreateAndActivateBrowser("Beep"); - auto browser2 = CreateAndActivateBrowser("Boop"); - - // Browser 2 was activated last, so we expect it to be the top match. - auto matches = WindowsMatchingInput(browser(), u"", true); - ASSERT_EQ(matches.size(), 2u); - base::ranges::sort(matches, std::greater<>(), &WindowMatch::score); - EXPECT_EQ(matches.at(0).browser, browser2.get()); - - BrowserList::GetInstance()->SetLastActive(browser1.get()); - // Activating browser 1 should have brought it to the top. - matches = WindowsMatchingInput(browser(), u"", true); - ASSERT_EQ(matches.size(), 2u); - base::ranges::sort(matches, std::greater<>(), &WindowMatch::score); - EXPECT_EQ(matches.at(0).browser, browser1.get()); -} - -TEST_F(CommanderEntityMatchTest, GroupReturnsAllWithNoInput) { - CreateGroups({u"Foo", u"Bar", u"Baz"}); - - EXPECT_EQ(GroupsMatchingInput(browser(), u"").size(), 3u); -} - -TEST_F(CommanderEntityMatchTest, GroupExcludeWithNoInput) { - ASSERT_TRUE(browser()->tab_strip_model()->SupportsTabGroups()); - CreateGroups({u"Foo", u"Bar", u"Baz"}); - - auto second_group = browser()->tab_strip_model()->GetTabGroupForTab(1); - EXPECT_TRUE(second_group.has_value()); - EXPECT_EQ(GroupsMatchingInput(browser(), u"", second_group).size(), 2u); -} - -TEST_F(CommanderEntityMatchTest, GroupOnlyIncludesMatches) { - ASSERT_TRUE(browser()->tab_strip_model()->SupportsTabGroups()); - CreateGroups({u"Orange juice", u"Aqua Regia"}); - - auto matches = GroupsMatchingInput(browser(), u"Orange"); - ASSERT_EQ(matches.size(), 1u); - EXPECT_EQ(matches.at(0).title, u"Orange juice"); -} - -TEST_F(CommanderEntityMatchTest, GroupRanksMatches) { - ASSERT_TRUE(browser()->tab_strip_model()->SupportsTabGroups()); - CreateGroups({u"Oracular Nouns Gesture Electrically", u"Orange juice"}); - - auto matches = GroupsMatchingInput(browser(), u"orange"); - ASSERT_EQ(matches.size(), 2u); - base::ranges::sort(matches, std::greater<>(), &GroupMatch::score); - EXPECT_EQ(matches.at(0).title, u"Orange juice"); -} - -TEST_F(CommanderEntityMatchTest, GroupExcludeWithInput) { - ASSERT_TRUE(browser()->tab_strip_model()->SupportsTabGroups()); - CreateGroups({u"William of Orange", u"Orange juice"}); - - auto first_group = browser()->tab_strip_model()->GetTabGroupForTab(0); - auto matches = GroupsMatchingInput(browser(), u"orange", first_group); - ASSERT_EQ(matches.size(), 1u); - EXPECT_EQ(matches.at(0).title, u"Orange juice"); -} - -TEST_F(CommanderEntityMatchTest, TabReturnsAllWithNoInput) { - CreateTabs({u"A", u"B", u"C"}); - - EXPECT_EQ(TabsMatchingInput(browser(), u"").size(), 3u); -} - -TEST_F(CommanderEntityMatchTest, TabOnlyPinnedExcludesUnpinned) { - CreateTabs({u"A", u"B", u"C"}); - browser()->tab_strip_model()->SetTabPinned(1, true); - - TabSearchOptions options; - options.only_pinned = true; - auto matches = TabsMatchingInput(browser(), u"", options); - ASSERT_EQ(matches.size(), 1u); - EXPECT_EQ(matches.at(0).title, u"B"); -} - -TEST_F(CommanderEntityMatchTest, TabOnlyUnpinnedExcludesPinned) { - CreateTabs({u"A", u"B", u"C"}); - browser()->tab_strip_model()->SetTabPinned(1, true); - - TabSearchOptions options; - options.only_unpinned = true; - auto matches = TabsMatchingInput(browser(), u"", options); - ASSERT_EQ(matches.size(), 2u); - EXPECT_EQ(base::ranges::find(matches, u"B", &TabMatch::title), matches.end()); -} - -TEST_F(CommanderEntityMatchTest, TabExcludeTabGroupExcludes) { - ASSERT_TRUE(browser()->tab_strip_model()->SupportsTabGroups()); - CreateTabs({u"A", u"B", u"C"}); - browser()->tab_strip_model()->AddToNewGroup({1}); - browser()->tab_strip_model()->AddToNewGroup({2}); - auto first_group = browser()->tab_strip_model()->GetTabGroupForTab(1); - EXPECT_TRUE(first_group.has_value()); - - TabSearchOptions options; - options.exclude_tab_group = first_group; - auto matches = TabsMatchingInput(browser(), u"", options); - EXPECT_EQ(matches.size(), 2u); - EXPECT_EQ(base::ranges::find(matches, u"B", &TabMatch::title), matches.end()); -} - -TEST_F(CommanderEntityMatchTest, TabOnlyTabGroupExcludesOthers) { - ASSERT_TRUE(browser()->tab_strip_model()->SupportsTabGroups()); - CreateTabs({u"A", u"B", u"C"}); - browser()->tab_strip_model()->AddToNewGroup({1}); - browser()->tab_strip_model()->AddToNewGroup({2}); - auto first_group = browser()->tab_strip_model()->GetTabGroupForTab(1); - EXPECT_TRUE(first_group.has_value()); - - TabSearchOptions options; - options.only_tab_group = first_group; - auto matches = TabsMatchingInput(browser(), u"", options); - ASSERT_EQ(matches.size(), 1u); - EXPECT_EQ(matches.at(0).title, u"B"); -} - -TEST_F(CommanderEntityMatchTest, TabOnlyAudibleExcludesOthers) { - CreateTabs({u"A", u"B", u"C"}); - browser()->tab_strip_model()->InsertWebContentsAt( - 1, content::WebContentsTester::CreateTestWebContents(profile(), nullptr), - AddTabTypes::ADD_NONE); - content::WebContentsTester::For( - browser()->tab_strip_model()->GetWebContentsAt(1)) - ->SetIsCurrentlyAudible(true); - - TabSearchOptions options; - options.only_audible = true; - auto matches = TabsMatchingInput(browser(), u"", options); - ASSERT_EQ(matches.size(), 1u); - EXPECT_EQ(matches.at(0).index, 1); -} - -TEST_F(CommanderEntityMatchTest, TabOnlyMutedExcludesOthers) { - CreateTabs({u"A", u"B", u"C"}); - browser()->tab_strip_model()->GetWebContentsAt(1)->SetAudioMuted(true); - - TabSearchOptions options; - options.only_muted = true; - auto matches = TabsMatchingInput(browser(), u"", options); - ASSERT_EQ(matches.size(), 1u); - EXPECT_EQ(matches.at(0).index, 1); -} - -TEST_F(CommanderEntityMatchTest, TabOnlyIncludesMatches) { - CreateTabs({u"Orange juice", u"Aqua regia"}); - - auto matches = TabsMatchingInput(browser(), u"orange"); - ASSERT_EQ(matches.size(), 1u); - EXPECT_EQ(matches.at(0).title, u"Orange juice"); -} - -TEST_F(CommanderEntityMatchTest, TabOnlyRanksMatches) { - CreateTabs({u"Oracular Nouns Gesture Electrically", u"Orange juice"}); - - auto matches = TabsMatchingInput(browser(), u"range"); - ASSERT_EQ(matches.size(), 2u); - EXPECT_EQ(matches.at(0).title, u"Orange juice"); - - base::ranges::sort(matches, std::greater<>(), &TabMatch::score); - EXPECT_EQ(matches.at(0).title, u"Orange juice"); -} - -} // namespace commander
diff --git a/chrome/browser/ui/commander/fuzzy_finder.cc b/chrome/browser/ui/commander/fuzzy_finder.cc deleted file mode 100644 index 5166bb5..0000000 --- a/chrome/browser/ui/commander/fuzzy_finder.cc +++ /dev/null
@@ -1,445 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/commander/fuzzy_finder.h" - -#include "base/i18n/case_conversion.h" -#include "base/i18n/char_iterator.h" -#include "base/ranges/algorithm.h" -#include "base/strings/string_util.h" -#include "third_party/icu/source/common/unicode/uchar.h" -#include "third_party/icu/source/common/unicode/ustring.h" - -namespace { -// Used only for exact matches. -static const double kMaxScore = 1.0; -// When needle is a prefix of haystack. -static const double kPrefixScore = .99; -// When a heuristic determines that the match should score highly, -// but it is *not* an exact match or prefix. -static const double kVeryHighScore = .95; - -// Max haystack size in UTF-16 units for the dynamic programming algorithm. -// Haystacks longer than this are scored by ConsecutiveMatchWithGaps. -static constexpr size_t kMaxHaystack = 1024; -// Max needle size in UTF-16 units for the dynamic programming algorithm. -// Needles longer than this are scored by ConsecutiveMatchWithGaps -static constexpr size_t kMaxNeedle = 16; - -struct MatchRecord { - MatchRecord(int start, int end, int length, bool is_boundary, int gap_before) - : range(start, end), - length(length), - gap_before(gap_before), - is_boundary(is_boundary) {} - gfx::Range range; - // This can't be inferred from `range` since range is in code units for - // display, but `length` is in code points. - int length; - int gap_before; - bool is_boundary; -}; - -// Scores matches identified by ConsecutiveMatchWithGaps(). See that comment -// for details. -double ScoreForMatches(const std::vector<MatchRecord>& matches, - size_t needle_size, - size_t haystack_size) { - // |base_score| is the maximum per match, so total should not exceed 1.0. - const double base_score = 1.0 / needle_size; - const double gap_penalty = 1.0 / haystack_size; - static const double kRegularMultiplier = .5; - static const double kWordBoundaryMultiplier = .8; - static const double kInitialMultiplier = 1.0; - double score = 0; - - for (size_t i = 0; i < matches.size(); i++) { - MatchRecord match = matches[i]; - // The first character of the match is special; it gets a relative bonus - // if it is on a boundary. Otherwise, it is penalized by the distance - // between it and the previous match. - if (match.is_boundary) { - score += - base_score * (i == 0 ? kInitialMultiplier : kWordBoundaryMultiplier); - } else { - double penalty_multiplier = 1 - (gap_penalty * match.gap_before); - DCHECK_GT(penalty_multiplier, 0); - score += base_score * kRegularMultiplier * penalty_multiplier; - } - // ...then the rest of a contiguous match. - score += (match.length - 1) * base_score * kRegularMultiplier; - } - DCHECK(score <= 1.0); - return score; -} - -size_t LengthInCodePoints(const std::u16string& str) { - return u_countChar32(str.data(), str.size()); -} - -// Returns a positive score if every code point in |needle| is present in -// |haystack| in the same order. The match *need not* be contiguous. Matches in -// special positions are given extra weight, and noncontiguous matches are -// penalized based on the size of the gaps between. -// This is not guaranteed to return the best possible match; for example, given -// needle = "orange" and haystack = "William of Orange", this function will -// match as "William [o]f O[range]" rather than "William of [Orange]". It's main -// use is to filter nonmatches before a more comprehensive algorithm, and as a -// fallback for when the inputs are too high for a more comprehensive algorithm -// to be performant. -double ConsecutiveMatchWithGaps(const std::u16string& needle, - const std::u16string& haystack, - std::vector<gfx::Range>* matched_ranges) { - DCHECK(needle == base::i18n::FoldCase(needle)); - DCHECK(haystack == base::i18n::FoldCase(haystack)); - DCHECK(matched_ranges->empty()); - // Special case for prefix. - if (base::StartsWith(haystack, needle)) { - matched_ranges->emplace_back(0, needle.size()); - return kPrefixScore; - } - base::i18n::UTF16CharIterator n_iter(needle); - base::i18n::UTF16CharIterator h_iter(haystack); - - std::vector<MatchRecord> matches; - int gap_size_before_match = 0; - int match_began_on_boundary = true; - int match_start = -1; - int match_length = 0; - - // Find matching ranges. - while (!n_iter.end() && !h_iter.end()) { - if (n_iter.get() == h_iter.get()) { - // There's a match. - if (match_length == 0) { - // Match start. - match_start = h_iter.array_pos(); - match_began_on_boundary = - h_iter.start() || u_isUWhiteSpace(h_iter.PreviousCodePoint()); - } - ++match_length; - h_iter.Advance(); - n_iter.Advance(); - } else { - if (match_length > 0) { - DCHECK(match_start != -1); - match_length = 0; - matches.emplace_back(match_start, h_iter.array_pos(), match_length, - match_began_on_boundary, gap_size_before_match); - gap_size_before_match = 1; - match_start = -1; - } else { - gap_size_before_match++; - } - h_iter.Advance(); - } - } - if (!n_iter.end()) { - // Didn't match all of |needle|. - matched_ranges->clear(); - return 0; - } - if (match_length > 0) { - DCHECK(match_start != -1); - matches.emplace_back(match_start, h_iter.array_pos(), match_length, - match_began_on_boundary, gap_size_before_match); - } - for (const MatchRecord& match : matches) { - matched_ranges->push_back(match.range); - } - double score = ScoreForMatches(matches, LengthInCodePoints(needle), - LengthInCodePoints(haystack)); - score *= kPrefixScore; // Normalize so that a prefix always wins. - return score; -} -// Converts a list of indices in `positions` into contiguous ranges and fills -// `matched_ranges` with the result. -// For example: [0, 1, 4, 7, 8, 9] -> [{0, 2}, {4, 1}, {7, 3}]. -void ConvertPositionsToRanges(const std::vector<size_t>& positions, - std::vector<gfx::Range>* matched_ranges) { - size_t n = positions.size(); - DCHECK(n > 0); - size_t start = positions.front(); - size_t length = 1; - for (size_t i = 0; i < n - 1; ++i) { - if (positions.at(i) + 1 < positions.at(i + 1)) { - // Noncontiguous positions -> close out the range. - matched_ranges->emplace_back(start, start + length); - start = positions.at(i + 1); - length = 1; - } else { - ++length; - } - } - matched_ranges->emplace_back(start, start + length); -} - -// Returns the maximum score for the given matrix, then backtracks to fill in -// `matched_ranges`. See fuzzy_finder.md for extended discussion. -int ScoreForMatrix(const std::vector<int> score_matrix, - size_t width, - size_t height, - const std::vector<size_t> codepoint_to_offset, - std::vector<gfx::Range>* matched_ranges) { - // Find winning score and its index. - size_t max_index = 0; - int max_score = 0; - for (size_t i = 0; i < width; i++) { - int score = score_matrix[(height - 1) * width + i]; - if (score > max_score) { - max_score = score; - max_index = i; - } - } - - // Backtrack through the matrix to find matching positions. - std::vector<size_t> positions = {codepoint_to_offset[max_index]}; - size_t cur_i = max_index; - size_t cur_j = height - 1; - while (cur_j > 0) { - // Move diagonally... - --cur_i; - --cur_j; - // ...then scan left until the score stops increasing. - int current = score_matrix[cur_j * width + cur_i]; - int left = cur_i == 0 ? 0 : score_matrix[cur_j * width + cur_i - 1]; - while (current < left) { - cur_i -= 1; - if (cur_i == 0) - break; - current = left; - left = score_matrix[cur_j * width + cur_i - 1]; - } - positions.push_back(codepoint_to_offset[cur_i]); - } - - base::ranges::reverse(positions); - ConvertPositionsToRanges(positions, matched_ranges); - return max_score; -} - -} // namespace - -namespace commander { - -FuzzyFinder::FuzzyFinder(const std::u16string& needle) - : needle_(base::i18n::FoldCase(needle)) { - if (needle_.size() <= kMaxNeedle) { - score_matrix_.reserve(needle_.size() * kMaxHaystack); - consecutive_matrix_.reserve(needle_.size() * kMaxHaystack); - } -} - -FuzzyFinder::~FuzzyFinder() = default; - -double FuzzyFinder::Find(const std::u16string& haystack, - std::vector<gfx::Range>* matched_ranges) { - matched_ranges->clear(); - if (needle_.size() == 0) - return 0; - const std::u16string& folded = base::i18n::FoldCase(haystack); - size_t m = needle_.size(); - size_t n = folded.size(); - // Special case 0: M > N. We don't allow skipping anything in |needle|, so - // no match possible. - if (m > n) { - return 0; - } - // Special case 1: M == N. It must be either an exact match, - // or a non-match. - if (m == n) { - if (folded == needle_) { - matched_ranges->emplace_back(0, needle_.length()); - return kMaxScore; - } else { - return 0; - } - } - // Special case 2: needle is a prefix of haystack - if (base::StartsWith(folded, needle_)) { - matched_ranges->emplace_back(0, needle_.length()); - return kPrefixScore; - } - // Special case 3: M == 1. Scan through all matches, and return: - // no match -> - // 0 - // prefix match -> - // kPrefixScore (but should have been handled above) - // word boundary match (e.g. needle: j, haystack "Orange [J]uice") -> - // kVeryHighScore - // any other match -> - // Scored based on how far into haystack needle is found, normalized by - // haystack length. - if (m == 1) { - size_t substring_position = folded.find(needle_); - while (substring_position != std::string::npos) { - if (substring_position == 0) { - // Prefix match. - matched_ranges->emplace_back(0, 1); - return kPrefixScore; - } else { - wchar_t previous = folded.at(substring_position - 1); - if (base::IsUnicodeWhitespace(previous)) { - // Word boundary. Since we've eliminated prefix by now, this is as - // good as we're going to get, so we can return. - matched_ranges->clear(); - matched_ranges->emplace_back(substring_position, - substring_position + 1); - return kVeryHighScore; - // Internal match. If |matched_ranges| is already populated, we've - // seen another internal match previously, so ignore this one. - } else if (matched_ranges->empty()) { - matched_ranges->emplace_back(substring_position, - substring_position + 1); - } - } - substring_position = folded.find(needle_, substring_position + 1); - } - if (matched_ranges->empty()) { - return 0; - } else { - // First internal match. - DCHECK_EQ(matched_ranges->size(), 1u); - double position = static_cast<double>(matched_ranges->back().start()); - return std::min(1 - position / folded.length(), 0.01); - } - } - - // This has two purposes: - // 1. If there's no match here, we should bail instead of wasting time on the - // full O(mn) matching algorithm. - // 2. If m * n is too big, we will use this result instead of doing the full - // full O(mn) matching algorithm. - double score = ConsecutiveMatchWithGaps(needle_, folded, matched_ranges); - if (score == 0) { - matched_ranges->clear(); - return 0; - } else if (n > kMaxHaystack || m > kMaxNeedle) { - return score; - } - matched_ranges->clear(); - return MatrixMatch(needle_, folded, matched_ranges); -} - -double FuzzyFinder::MatrixMatch(const std::u16string& needle_string, - const std::u16string& haystack_string, - std::vector<gfx::Range>* matched_ranges) { - static constexpr int kMatchScore = 16; - static constexpr int kBoundaryBonus = 8; - static constexpr int kConsecutiveBonus = 4; - static constexpr int kInitialBonus = kBoundaryBonus * 2; - static constexpr int kGapStart = 3; - static constexpr int kGapExtension = 1; - - const size_t m = LengthInCodePoints(needle_string); - const size_t n = LengthInCodePoints(haystack_string); - - DCHECK_LE(m, kMaxNeedle); - DCHECK_LE(n, kMaxHaystack); - score_matrix_.assign(m * n, 0); - consecutive_matrix_.assign(m * n, 0); - word_boundaries_.assign(n, false); - codepoint_to_offset_.assign(n, 0); - - base::i18n::UTF16CharIterator needle(needle_string); - base::i18n::UTF16CharIterator haystack(haystack_string); - - // Fill in first row and word boundaries. - bool in_gap = false; - int32_t needle_code_point = needle.get(); - int32_t haystack_code_point; - word_boundaries_[0] = true; - while (!haystack.end()) { - haystack_code_point = haystack.get(); - size_t i = haystack.char_offset(); - codepoint_to_offset_[i] = haystack.array_pos(); - if (i < n - 1) - word_boundaries_[i + 1] = u_isUWhiteSpace(haystack_code_point); - int bonus = word_boundaries_[i] ? kInitialBonus : 0; - if (needle_code_point == haystack_code_point) { - consecutive_matrix_[i] = 1; - score_matrix_[i] = kMatchScore + bonus; - in_gap = false; - } else { - int penalty = in_gap ? kGapExtension : kGapStart; - int left_score = i > 0 ? score_matrix_[i - 1] : 0; - score_matrix_[i] = std::max(left_score - penalty, 0); - in_gap = true; - } - haystack.Advance(); - } - - while (!haystack.start()) - haystack.Rewind(); - needle.Advance(); - - // Fill in rows 1 through n -1: - while (!needle.end()) { - in_gap = false; - while (!haystack.end()) { - size_t j = needle.char_offset(); - size_t i = haystack.char_offset(); - size_t idx = i + (j * n); - if (i < j) { - // Since all of needle must match, by the time we've gotten to the nth - // character of needle, at least n - 1 characters of haystack have been - // consumed. - haystack.Advance(); - continue; - } - // If we choose `left_score`, we're either creating or extending a gap. - int left_score = i > 0 ? score_matrix_[idx - 1] : 0; - int penalty = in_gap ? kGapExtension : kGapStart; - left_score -= penalty; - // If we choose `diagonal_score`, we're extending a match. - int diagonal_score = 0; - int consecutive = 0; - if (needle.get() == haystack.get()) { - DCHECK_GT(j, 0u); - DCHECK_GE(i, j); - // DCHECKs above show that this index is valid. - size_t diagonal_index = idx - n - 1; - diagonal_score = score_matrix_[diagonal_index] + kMatchScore; - if (word_boundaries_[j]) { - diagonal_score += kBoundaryBonus; - // If we're giving a boundary bonus, it implies that this position - // is an "acronym" type match rather than a "consecutive string" - // type match, so reset consecutive to not double dip. - consecutive = 1; - } else { - consecutive = consecutive_matrix_[idx] + 1; - if (consecutive > 1) { - // Find the beginning of this consecutive run. - size_t run_start = i - consecutive; - diagonal_score += word_boundaries_[run_start] ? kBoundaryBonus - : kConsecutiveBonus; - } - } - } - in_gap = left_score > diagonal_score; - consecutive_matrix_[idx] = in_gap ? 0 : consecutive; - score_matrix_[idx] = std::max(0, std::max(left_score, diagonal_score)); - haystack.Advance(); - } - while (!haystack.start()) - haystack.Rewind(); - needle.Advance(); - } - - const int raw_score = - ScoreForMatrix(score_matrix_, n, m, codepoint_to_offset_, matched_ranges); - const int max_possible_score = - kInitialBonus + kMatchScore + (kBoundaryBonus + kMatchScore) * (m - 1); - // But that said, in most cases, good matches will score well below this, so - // let's saturate a little. - constexpr float kScoreBias = 0.25; - const double score = - kScoreBias + - (static_cast<double>(raw_score) / max_possible_score) * (1 - kScoreBias); - DCHECK_LE(score, 1.0); - // Make sure it scores below exact matches and prefixes. - return score * kVeryHighScore; -} - -} // namespace commander
diff --git a/chrome/browser/ui/commander/fuzzy_finder.h b/chrome/browser/ui/commander/fuzzy_finder.h deleted file mode 100644 index 86ba9d7..0000000 --- a/chrome/browser/ui/commander/fuzzy_finder.h +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COMMANDER_FUZZY_FINDER_H_ -#define CHROME_BROWSER_UI_COMMANDER_FUZZY_FINDER_H_ - -#include <string> -#include <vector> - -#include "ui/gfx/range/range.h" - -namespace commander { - -class FuzzyFinder { - public: - explicit FuzzyFinder(const std::u16string& needle); - ~FuzzyFinder(); - FuzzyFinder(const FuzzyFinder& other) = delete; - FuzzyFinder& operator=(const FuzzyFinder& other) = delete; - - // Returns a score from 0 to 1 based on how well |needle_| matches |haystack|. - // 0 means no match. |matched_ranges| will be filled with the ranges of - // |haystack| that match |needle| so they can be highlighted in the UI; see - // comment on commander::CommandItem |matched_ranges| for a worked example. - double Find(const std::u16string& haystack, - std::vector<gfx::Range>* matched_ranges); - - private: - // Implementation of the O(mn) matching algorithm. Only run if: - // - `needle` is smaller than `haystack` - // - `needle` is longer than a single character - // - `needle` is not an exact prefix of `haystack` - // - every code unit in `needle` is present in haystack, in the order that - // they appear in `needle`. - // - `needle` and `haystack` are not longer than some maximum size (subject to - // change but currently 16 for `needle` and `1024` for haystack). - // See fuzzy_finder.md for full details. - double MatrixMatch(const std::u16string& needle, - const std::u16string& haystack, - std::vector<gfx::Range>* matched_ranges); - // Case-folded input string. - std::u16string needle_; - // Scratch space for MatrixMatch(). - std::vector<int> score_matrix_; - std::vector<int> consecutive_matrix_; - std::vector<bool> word_boundaries_; - std::vector<size_t> codepoint_to_offset_; -}; - -} // namespace commander - -#endif // CHROME_BROWSER_UI_COMMANDER_FUZZY_FINDER_H_
diff --git a/chrome/browser/ui/commander/fuzzy_finder.md b/chrome/browser/ui/commander/fuzzy_finder.md deleted file mode 100644 index ebe7001..0000000 --- a/chrome/browser/ui/commander/fuzzy_finder.md +++ /dev/null
@@ -1,233 +0,0 @@ -# Commander Fuzzy Finder explainer - -Most [Commander](README.md) sources use `FuzzyFinder` to select which available -commands match user input. - -A `FuzzyFinder` instance is constructed with the user input, which we call the -_needle_. From then, callers call `Find()` with text to match, which we call -the _haystack_. `Find()` returns a score between 0.0 and 1.0 inclusive for -how well _needle_ matched _haystack_, and fills a provided out parameter, -`matched_ranges`, with the ranges of the characters of _haystack_ that match -_needle_. - -Calls to `Find()` proceed through up to three layers, the last of which is the -most interesting and covered in depth below. -1. First, we check for certain special cases (single character _needle_, equal -length _needle_ and _haystack_ etc.) If the call matches one of the special -cases, we can handle the case without doing much work and return here. -2. Then, we run a simple O(n) search (where _n_ is the length of -_haystack_) which we call "consecutive with gaps allowed". This checks that all -of _needle_ is present in _haystack_ (but, you guessed it, with gaps allowed!) -This served two purposes: providing a "good enough" result for large inputs, -and ensuring that all of _needle_ appears before spending the time running the -full algorithm. Most non-matches will return here. -3. A dynamic programming string search based on the command-line tool [fzf](https://github.com/junegunn/fzf/blob/master/src/algo/algo.go), -which is itself an adaptation of the [Smith-Waterman](https://en.wikipedia.org/wiki/Smith%E2%80%93Waterman_algorithm) ([original paper](https://dornsife.usc.edu/assets/sites/516/docs/papers/msw_papers/msw-042.pdf) very short, pretty readable) genetic sequence alignment -algorithm. This takes O(mn) time and space, so we only run this for _needles_ -and _haystacks_ under a certain size. - -## The matrix algorithm - - Aside: for simplicity, steps 1 and 2 above are performed in terms of UTF-16 - code units. The matrix algorithm, on the other hand, works in [code points](https://unicode.org/glossary/#code_point), which makes it more accurate for languages outside the [basic multilingual plane](https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane). - -This is easiest to present in a worked example, so let's use -`needle` = "nwi" -`haystack` = "winter new window" - -(this is an example where consecutive match with gaps would give us a bad -result: "wi\[n\]ter ne\[w\] w\[i\]ndow". - -With `m = len(needle) = 3` and `n = len(haystack) = 17`, we will need the -following for scratch space: - -#### A `n x m` score matrix: - -| | w | i | n | t | e | r | | n | e | w | | w | i | n | d | o | w | -|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| -| n | | | | | | | | | | | | | | | | | | -| w | | | | | | | | | | | | | | | | | | -| i | | | | | | | | | | | | | | | | | | - -where the cell at indices i,j means: the score for the substrings `needle[:j]` -and `haystack[:i]`. Scores in the score matrix are ints, because that's what -fzf used and they had good weights. We'll normalize at the end when reporting -the final score. - -The exact calculation of the score for a match is arbitrary and subject to -change so we won't get into it in detail here. We *will* get into detail about -how the scores of previously filled cells affect the scores of subsequent cells. - -#### A `n x m` "consecutive matrix" (not pictured, it looks exactly like the above when empty). - - The cell at i,j represents how many consecutive matched characters -of `needle` were found ending at this position. I guess formally, you could say: - -If `n` is the value of the consecutive matrix at i, j, then for `x` in -1 through `n`: `needle[i - x] == haystack[j - x]`. - -#### A length `n` word boundary array - -(Constructing this is straightforward, so here's the final version) - -| | w | i | n | t | e | r | | n | e | w | | w | i | n | d | o | w | -|-----------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| -| boundary? | T | F | F | F | F | F | F | T | F | F | F | T | F | F | F | F | F | - -This helps us track which bonuses for word boundaries, which are key for -matching acronyms. - -#### A codepoint to code unit map - -Since we're working in code points, we need this to generate matched ranges we -can use in the UI. For English and other BMP languages, this will be the -identity. - -### Step 1: Fill the first row - -First, we fill the first row of the score and consecutive matrices. This is -pretty straightforward. We iterate through `haystack`, and for each code unit: - -#### Match - -If it matches the first code unit in `needle`, set the corresponding cell -in the consecutive matrix to 1. Calculate a bonus for the match based on whether -it's on a word boundary (NB: this bonus is higher in the first row, since -presumably, the first character the user typed has very high salience). - -#### No match - -Otherwise, set the corresponding cell in the consecutive array to 0. As far as -the score, there's no points awarded for a match, but this might still be an -interesting position later based on how close it is to a previous match. - -Given that, for a non-match, we set the score of this cell, to the score of the -cell to our immediate left, minus a penalty based on how far the gap from an -actual match to the current cell is. If there's no cell to the left or if the -resulting score is negative, use 0 instead. - -After the first row is filled in, we have the score matrix: - -| | w | i | n | t | e | r | | n | e | w | | w | i | n | d | o | w | -|---|---|---|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----| -| n | 0 | 0 | 16 | 13 | 12 | 11 | 10 | 32 | 29 | 28 | 27 | 26 | 25 | 16 | 13 | 12 | 11 | -| w | | | | | | | | | | | | | | | | | | -| i | | | | | | | | | | | | | | | | | | - -and consecutive matrix: - -| | w | i | n | t | e | r | | n | e | w | | w | i | n | d | o | w | -|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| -| n | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | -| w | | | | | | | | | | | | | | | | | | -| i | | | | | | | | | | | | | | | | | | - - -### Step 2: Fill in the rest - -For the subsequent rows, each cell at i, j can represent: -- An extension of a gap. This is exactly the same as the non-match score for the -first row: the score of the cell to the left, minus a penalty. We call this the -`left_score`. -- A match (`needle[j] == haystack[i]`). For example, at `i == 11` and `j == 1`, -in our example, "w" matches. One way to look at this is that we had the prefixes - -_needle_ "n" -_haystack_ "winter new " - -and extended them both with "w". Given that, we score then match -(including bonuses) and add that to the score of the prefixes: the cell -at i - 1, j - 1. We call this `diagonal_score`. - -To recap: the left score means that we are extending a gap; that there's some -prefix of `haystack[:i]` that scores highly, and we're just piggybacking off of -it. We want to look at the left score even if we have a match, because there -could have been a previous match that was better. The diagonal score means that -we're extending the match; that this position should be bolded later when -we show _haystack_ to the user. Smith-Waterman also allowed for what I'll call -a "top score", which represents a gap in _needle_, but for our use cases, we -need all of _needle_ to match, so we're not interested. - -The final score of the cell is max(0, left_score, diagonal_score) - -If we choose the diagonal score, in *most cases* we fill the consecutive matrix -by incrementing the diagonal cell of the consecutive matrix (see source for -exceptions). If we choose the left score, then we don't consider this position -a match, so we're in a gap, and so the cell in the consecutive matrix is set to -1. - -Now our matrices are filled! - -Score: - -| | w | i | n | t | e | r | | n | e | w | | w | i | n | d | o | w | -|---|---|---|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----| -| n | 0 | 0 | 16 | 13 | 12 | 11 | 10 | 32 | 29 | 28 | 27 | 26 | 25 | 16 | 13 | 12 | 11 | -| w | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 45 | 42 | 51 | 48 | 47 | 46 | 45 | 44 | -| i | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 71 | 68 | 67 | 66 | 65 | - -and consecutive: - -| | w | i | n | t | e | r | | n | e | w | | w | i | n | d | o | w | -|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| -| n | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | -| w | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | -| i | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 0 | - -### Step 3: Backtrack - -Now that the score matrix is completely filled, we have a final score: the -highest score in the bottom row. If we just needed to rank, this would be -enough, but we also need to provide the positions of matches so that we can -highlight them for the user. For that, we need to backtrack through the matrix. - -To do that, we start at a known match. The final score fits the bill. - -| | w | i | n | t | e | r | | n | e | w | | w | i | n | d | o | w | -|---|---|---|----|----|----|----|----|----|----|----|----|----|--------|----|----|----|----| -| n | 0 | 0 | 16 | 13 | 12 | 11 | 10 | 32 | 29 | 28 | 27 | 26 | 25 | 16 | 13 | 12 | 11 | -| w | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 45 | 42 | 51 | 48 | 47 | 46 | 45 | 44 | -| i | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | >>71<< | 68 | 67 | 66 | 65 | - -Based on how we built the score matrix, we know that for a match, we moved down -diagonally, so now we move up diagonally - -| | w | i | n | t | e | r | | n | e | w | | w | i | n | d | o | w | -|---|---|---|----|----|----|----|----|----|----|----|----|--------|----|----|----|----|----| -| n | 0 | 0 | 16 | 13 | 12 | 11 | 10 | 32 | 29 | 28 | 27 | 26 | 25 | 16 | 13 | 12 | 11 | -| w | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 45 | 42 | >>51<< | 48 | 47 | 46 | 45 | 44 | -| i | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 71 | 68 | 67 | 66 | 65 | - -But this isn't necessarily the next position. If the score to the left is even -higher, *that* position is better. Practically, it means that we scan to the -left "edge", that is, scan left until the score to the left is no longer -higher than the current score. - -At this point, since we could not have gotten to the current position by -extending a gap (since to use the left score, the current cell's score would -need to have been less than the left cell's), it must have been by moving -diagonally and that means that we've reached this row's match. - -The first cell we look at in the second row is the right cell, but we do need -to do this in the top row: - -| | w | i | n | t | e | r | | n | e | w | | w | i | n | d | o | w | -|---|---|---|----|----|----|----|----|----|----|----|--------|----|----|----|----|----|----| -| n | 0 | 0 | 16 | 13 | 12 | 11 | 10 | 32 | 29 | 28 | >>27<< | 26 | 25 | 16 | 13 | 12 | 11 | -| w | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 45 | 42 | 51 | 48 | 47 | 46 | 45 | 44 | -| i | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 71 | 68 | 67 | 66 | 65 | -_not the right place, let's slide left_ - - -| | w | i | n | t | e | r | | n | e | w | | w | i | n | d | o | w | -|---|---|---|----|----|----|----|----|--------|----|----|----|----|----|----|----|----|----| -| n | 0 | 0 | 16 | 13 | 12 | 11 | 10 | >>32<< | 29 | 28 | 27 | 26 | 25 | 16 | 13 | 12 | 11 | -| w | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 45 | 42 | 51 | 48 | 47 | 46 | 45 | 44 | -| i | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 71 | 68 | 67 | 66 | 65 | -_going left doesn't increase the score, this is the place!_ - - - -We repeat this process all the way up and including the top row. Now we have all -of the positions. The rest (fixing up the positions into ranges, normalizing the -score, etc.) is just grunt work.
diff --git a/chrome/browser/ui/commander/fuzzy_finder_fuzzer.cc b/chrome/browser/ui/commander/fuzzy_finder_fuzzer.cc deleted file mode 100644 index f6250e74d..0000000 --- a/chrome/browser/ui/commander/fuzzy_finder_fuzzer.cc +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -#include <stddef.h> -#include <stdint.h> - -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/ui/commander/fuzzy_finder.h" - -#include <fuzzer/FuzzedDataProvider.h> - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - FuzzedDataProvider provider(data, size); - std::vector<gfx::Range> ranges; - std::u16string needle = - base::UTF8ToUTF16(provider.ConsumeRandomLengthString()); - std::u16string haystack = - base::UTF8ToUTF16(provider.ConsumeRandomLengthString()); - - commander::FuzzyFinder(needle).Find(haystack, &ranges); - return 0; -}
diff --git a/chrome/browser/ui/commander/fuzzy_finder_unittest.cc b/chrome/browser/ui/commander/fuzzy_finder_unittest.cc deleted file mode 100644 index 2e80f1cf9..0000000 --- a/chrome/browser/ui/commander/fuzzy_finder_unittest.cc +++ /dev/null
@@ -1,108 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/commander/fuzzy_finder.h" - -#include "base/i18n/case_conversion.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace commander { - -namespace { -// Convenience function to avoid visual noise from constructing FuzzyFinder -// objects in-test. -double FuzzyFind(const std::u16string& needle, - const std::u16string& haystack, - std::vector<gfx::Range>* matched_ranges) { - return FuzzyFinder(needle).Find(haystack, matched_ranges); -} -} // namespace - -TEST(CommanderFuzzyFinder, NonmatchIsZero) { - std::vector<gfx::Range> ranges; - EXPECT_EQ(0, FuzzyFind(u"orange", u"orangutan", &ranges)); - EXPECT_TRUE(ranges.empty()); - EXPECT_EQ(0, FuzzyFind(u"elephant", u"orangutan", &ranges)); - EXPECT_TRUE(ranges.empty()); -} - -TEST(CommanderFuzzyFinder, ExactMatchIsOne) { - std::vector<gfx::Range> ranges; - EXPECT_EQ(1, FuzzyFind(u"orange", u"orange", &ranges)); - EXPECT_EQ(ranges, std::vector<gfx::Range>({{0, 6}})); -} - -// This ensures coverage for a fast path. Successful match is -// tested in ExactMatchIsOne() above. -TEST(CommanderFuzzyFinder, NeedleHaystackSameLength) { - std::vector<gfx::Range> ranges; - EXPECT_EQ(0, FuzzyFind(u"ranges", u"orange", &ranges)); - EXPECT_TRUE(ranges.empty()); -} - -// This ensures coverage for a fast path (just making sure the path has -// coverage rather than ensuring the path is taken). -TEST(CommanderFuzzyFinder, SingleCharNeedle) { - std::vector<gfx::Range> ranges; - FuzzyFinder finder(u"o"); - - double prefix_score = finder.Find(u"orange", &ranges); - EXPECT_EQ(ranges, std::vector<gfx::Range>({{0, 1}})); - double internal_score = finder.Find(u"phone", &ranges); - EXPECT_EQ(ranges, std::vector<gfx::Range>({{2, 3}})); - double boundary_score = finder.Find(u"phone operator", &ranges); - EXPECT_EQ(ranges, std::vector<gfx::Range>({{6, 7}})); - - // Expected ordering: - // - Prefix should rank highest. - // - Word boundary matches that are not the prefix should rank next - // highest, even if there's an internal match earlier in the haystack. - // - Internal matches should rank lowest. - EXPECT_GT(prefix_score, boundary_score); - EXPECT_GT(boundary_score, internal_score); - - // ...and non-matches should have score = 0. - EXPECT_EQ(0, finder.Find(u"aquarium", &ranges)); - EXPECT_TRUE(ranges.empty()); -} - -TEST(CommanderFuzzyFinder, CaseInsensitive) { - std::vector<gfx::Range> ranges; - EXPECT_EQ(1, FuzzyFind(u"orange", u"Orange", &ranges)); - EXPECT_EQ(ranges, std::vector<gfx::Range>({{0, 6}})); -} - -TEST(CommanderFuzzyFinder, PrefixRanksHigherThanInternal) { - std::vector<gfx::Range> ranges; - FuzzyFinder finder(u"orange"); - double prefix_rank = finder.Find(u"Orange juice", &ranges); - double non_prefix_rank = finder.Find(u"William of Orange", &ranges); - - EXPECT_GT(prefix_rank, 0); - EXPECT_GT(non_prefix_rank, 0); - EXPECT_LT(prefix_rank, 1); - EXPECT_LT(non_prefix_rank, 1); - EXPECT_GT(prefix_rank, non_prefix_rank); -} - -TEST(CommanderFuzzyFinder, NeedleLongerThanHaystack) { - std::vector<gfx::Range> ranges; - EXPECT_EQ(0, FuzzyFind(u"orange juice", u"orange", &ranges)); - EXPECT_TRUE(ranges.empty()); -} - -TEST(CommanderFuzzyFinder, Noncontiguous) { - std::vector<gfx::Range> ranges; - EXPECT_GT(FuzzyFind(u"tuot", u"Tlön, Uqbar, Orbis Tertius", &ranges), 0); - EXPECT_EQ(ranges, - std::vector<gfx::Range>({{0, 1}, {6, 7}, {13, 14}, {19, 20}})); -} - -TEST(CommanderFuzzyFinder, EmptyStringDoesNotMatch) { - std::vector<gfx::Range> ranges; - EXPECT_EQ(0, FuzzyFind(u"", u"orange", &ranges)); - EXPECT_TRUE(ranges.empty()); -} - -} // namespace commander
diff --git a/chrome/browser/ui/commander/open_url_command_source.cc b/chrome/browser/ui/commander/open_url_command_source.cc deleted file mode 100644 index 9f5b017..0000000 --- a/chrome/browser/ui/commander/open_url_command_source.cc +++ /dev/null
@@ -1,68 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/commander/open_url_command_source.h" - -#include "base/i18n/case_conversion.h" -#include "base/strings/utf_string_conversions.h" -#include "build/branding_buildflags.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_tabstrip.h" -#include "chrome/browser/ui/commander/fuzzy_finder.h" -#include "chrome/grit/locale_settings.h" -#include "ui/base/l10n/l10n_util.h" - -namespace commander { - -namespace { - -std::vector<std::pair<std::u16string, GURL>> CreateTitleURLMap() { - return { -#if BUILDFLAG(GOOGLE_CHROME_BRANDING) - {u"Chrome Help", - GURL("https://support.google.com/chrome/?p=help&ctx=menu#topic=9796470")}, - // GSuite - {u"New Google Doc", GURL("https://docs.new")}, - {u"New Google Sheet", GURL("https://sheets.new")}, - {u"New Google Slides", GURL("https://slides.new")}, - {u"New Google Form", GURL("https://forms.new")}, - {u"New Google Meet", GURL("https://meet.new")}, - {u"Open Theme Store", - GURL(l10n_util::GetStringUTF8(IDS_THEMES_GALLERY_URL))}, - {u"Open Extension Store", - GURL(l10n_util::GetStringUTF8(IDS_WEBSTORE_URL))}, -#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) - }; -} - -} // namespace - -OpenURLCommandSource::OpenURLCommandSource() - : title_url_map_(CreateTitleURLMap()) {} -OpenURLCommandSource::~OpenURLCommandSource() = default; - -CommandSource::CommandResults OpenURLCommandSource::GetCommands( - const std::u16string& input, - Browser* browser) const { - - CommandSource::CommandResults results; - std::vector<gfx::Range> ranges; - FuzzyFinder finder(input); - for (const auto& command_spec : title_url_map_) { - std::u16string title = command_spec.first; - double score = finder.Find(title, &ranges); - if (score == 0) - continue; - - auto item = std::make_unique<CommandItem>(title, score, ranges); - // base::Unretained is safe because commands are reset when a browser is - // closed. - item->command = base::BindOnce(&chrome::AddTabAt, base::Unretained(browser), - command_spec.second, -1, true, std::nullopt); - results.push_back(std::move(item)); - } - return results; -} - -} // namespace commander
diff --git a/chrome/browser/ui/commander/open_url_command_source.h b/chrome/browser/ui/commander/open_url_command_source.h deleted file mode 100644 index d1a65152..0000000 --- a/chrome/browser/ui/commander/open_url_command_source.h +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COMMANDER_OPEN_URL_COMMAND_SOURCE_H_ -#define CHROME_BROWSER_UI_COMMANDER_OPEN_URL_COMMAND_SOURCE_H_ - -#include "chrome/browser/ui/commander/command_source.h" -#include "url/gurl.h" - -namespace commander { - -// A command source for basic commands that open a given URL in a new tab. -class OpenURLCommandSource : public CommandSource { - public: - OpenURLCommandSource(); - ~OpenURLCommandSource() override; - - // Disallow copy and assign. - OpenURLCommandSource(const OpenURLCommandSource& other) = delete; - OpenURLCommandSource& operator=(const OpenURLCommandSource& other) = delete; - - // CommandSource overrides - CommandSource::CommandResults GetCommands(const std::u16string& input, - Browser* browser) const override; - - private: - const std::vector<std::pair<std::u16string, GURL>> title_url_map_; -}; - -} // namespace commander - -#endif // CHROME_BROWSER_UI_COMMANDER_OPEN_URL_COMMAND_SOURCE_H_
diff --git a/chrome/browser/ui/commander/simple_command_source.cc b/chrome/browser/ui/commander/simple_command_source.cc deleted file mode 100644 index b668e405..0000000 --- a/chrome/browser/ui/commander/simple_command_source.cc +++ /dev/null
@@ -1,121 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/commander/simple_command_source.h" - -#include <string> -#include <vector> - -#include "base/functional/bind.h" -#include "base/i18n/case_conversion.h" -#include "base/no_destructor.h" -#include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/ui/accelerator_utils.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/commander/fuzzy_finder.h" -#include "chrome/grit/generated_resources.h" -#include "components/strings/grit/components_strings.h" -#include "ui/base/accelerators/accelerator.h" -#include "ui/base/l10n/l10n_util.h" - -namespace commander { - -SimpleCommandSource::SimpleCommandSource() { - weak_this_ = weak_ptr_factory_.GetWeakPtr(); -} -SimpleCommandSource::~SimpleCommandSource() = default; - -CommandSource::CommandResults SimpleCommandSource::GetCommands( - const std::u16string& input, - Browser* browser) const { - // TODO(lgrey): Temporarily using hardcoded English titles instead of - // translated strings so we can experiment without adding translation load. - // As implied, none of these strings are final, or necessarily expected to - // ship. - struct CommandEntry { - int id; - std::u16string title; - }; - static const base::NoDestructor<std::vector<CommandEntry>> kCommandMap({ - {IDC_FIND, l10n_util::GetStringUTF16(IDS_FIND)}, - {IDC_SAVE_PAGE, l10n_util::GetStringUTF16(IDS_SAVE_PAGE)}, - {IDC_PRINT, l10n_util::GetStringUTF16(IDS_PRINT)}, - {IDC_SHOW_HISTORY, u"Show history"}, - {IDC_RELOAD, u"Reload"}, - {IDC_NEW_TAB, u"Create new tab"}, - {IDC_RESTORE_TAB, u"Open recently closed tab"}, - {IDC_NEW_WINDOW, u"Create new window"}, - {IDC_NEW_INCOGNITO_WINDOW, u"Create new incognito window"}, - {IDC_BOOKMARK_THIS_TAB, u"Bookmark this tab"}, - {IDC_BOOKMARK_ALL_TABS, u"Bookmark all tabs"}, - {IDC_BACK, u"Back"}, - {IDC_FORWARD, u"Forward"}, - {IDC_ZOOM_PLUS, u"Zoom in"}, - {IDC_ZOOM_MINUS, u"Zoom out"}, - {IDC_ZOOM_NORMAL, u"Reset zoom"}, - {IDC_VIEW_SOURCE, u"View page source"}, - {IDC_EXIT, u"Quit"}, - {IDC_EMAIL_PAGE_LOCATION, u"Email page location"}, - {IDC_FOCUS_LOCATION, u"Focus location bar"}, - {IDC_FOCUS_TOOLBAR, u"Focus toolbar"}, - {IDC_OPEN_FILE, u"Open file"}, - {IDC_TASK_MANAGER, u"Show task manager"}, - {IDC_SHOW_BOOKMARK_MANAGER, u"Show bookmark manager"}, - {IDC_SHOW_DOWNLOADS, u"Show downloads"}, - {IDC_CLEAR_BROWSING_DATA, u"Clear browsing data"}, - {IDC_OPTIONS, u"Show settings"}, - {IDC_SHOW_AVATAR_MENU, u"Switch profile"}, - {IDC_DEV_TOOLS_TOGGLE, u"Toggle developer tools"}, - {IDC_MANAGE_EXTENSIONS, l10n_util::GetStringUTF16(IDS_MANAGE_EXTENSIONS)}, - {IDC_TAB_SEARCH, u"Search tabs..."}, - {IDC_SELECT_NEXT_TAB, u"Next tab"}, - {IDC_SELECT_PREVIOUS_TAB, u"Previous tab"}, - {IDC_MOVE_TAB_NEXT, u"Move tab forward"}, - {IDC_MOVE_TAB_PREVIOUS, u"Move tab backward"}, - {IDC_QRCODE_GENERATOR, u"Create QR code"}, - }); - - CommandSource::CommandResults results; - FuzzyFinder finder(input); - std::vector<gfx::Range> ranges; - for (const auto& command_spec : *kCommandMap) { - if (!chrome::IsCommandEnabled(browser, command_spec.id)) - continue; - std::u16string title = command_spec.title; - std::erase(title, '&'); - double score = finder.Find(title, &ranges); - if (score == 0) - continue; - - auto item = std::make_unique<CommandItem>(title, score, ranges); - ui::Accelerator accelerator; - ui::AcceleratorProvider* provider = - chrome::AcceleratorProviderForBrowser(browser); - if (provider->GetAcceleratorForCommandId(command_spec.id, &accelerator)) { - item->annotation = accelerator.GetShortcutText(); - } - - // base::Unretained is safe because the controller is reset when the - // browser it's attached to closes. - item->command = - base::BindOnce(&SimpleCommandSource::ExecuteCommand, weak_this_, - base::Unretained(browser), command_spec.id); - results.push_back(std::move(item)); - } - - return results; -} - -// Why this is necessary: -// chrome::ExecuteCommand has a third default argument |time_stamp| which -// makes it difficult to use with BindOnce. Pre-binding it at command creation -// is wrong since it defaults to base::TimeTicks::Now(); that means if pre-bound -// it would get the timestamp when the command was generated, rather than when -// it was invoked. -void SimpleCommandSource::ExecuteCommand(Browser* browser, int command_id) { - chrome::ExecuteCommand(browser, command_id); -} - -} // namespace commander
diff --git a/chrome/browser/ui/commander/simple_command_source.h b/chrome/browser/ui/commander/simple_command_source.h deleted file mode 100644 index 7c8a539..0000000 --- a/chrome/browser/ui/commander/simple_command_source.h +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COMMANDER_SIMPLE_COMMAND_SOURCE_H_ -#define CHROME_BROWSER_UI_COMMANDER_SIMPLE_COMMAND_SOURCE_H_ - -#include "chrome/browser/ui/commander/command_source.h" - -#include "base/memory/weak_ptr.h" - -namespace commander { - -// A command source which hosts simple one-shot browser commands, most of which -// are accessible by hotkey. This is an alternative surface to provide for -// hotkey discovery. -class SimpleCommandSource : public CommandSource { - public: - SimpleCommandSource(); - ~SimpleCommandSource() override; - - // Disallow copy and assign - SimpleCommandSource(const SimpleCommandSource& other) = delete; - SimpleCommandSource& operator=(const SimpleCommandSource& other) = delete; - - // Command source overrides - CommandSource::CommandResults GetCommands(const std::u16string& input, - Browser* browser) const override; - - private: - base::WeakPtr<SimpleCommandSource> weak_this_; - // Wrapper around chrome::ExecuteCommand. See implementation comment - // for details. - void ExecuteCommand(Browser* browser, int command_id); - base::WeakPtrFactory<SimpleCommandSource> weak_ptr_factory_{this}; -}; - -} // namespace commander - -#endif // CHROME_BROWSER_UI_COMMANDER_SIMPLE_COMMAND_SOURCE_H_
diff --git a/chrome/browser/ui/commander/tab_command_source.cc b/chrome/browser/ui/commander/tab_command_source.cc deleted file mode 100644 index 8fc74f2..0000000 --- a/chrome/browser/ui/commander/tab_command_source.cc +++ /dev/null
@@ -1,533 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/commander/tab_command_source.h" - -#include <numeric> -#include <string> - -#include "base/functional/bind.h" -#include "base/ranges/algorithm.h" -#include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/send_tab_to_self/send_tab_to_self_util.h" -#include "chrome/browser/ui/accelerator_utils.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/commander/entity_match.h" -#include "chrome/browser/ui/commander/fuzzy_finder.h" -#include "chrome/browser/ui/tabs/tab_enums.h" -#include "chrome/browser/ui/tabs/tab_group_model.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/grit/generated_resources.h" -#include "components/sessions/content/session_tab_helper.h" -#include "ui/base/accelerators/accelerator.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/models/list_selection_model.h" - -namespace commander { - -namespace { - -// TODO(lgrey): It *might* make to pull this out later into a CommandSource -// method or a free function in some common place. Not committing yet. -std::unique_ptr<CommandItem> ItemForTitle(const std::u16string& title, - FuzzyFinder& finder, - std::vector<gfx::Range>* ranges) { - double score = finder.Find(title, ranges); - if (score > 0) - return std::make_unique<CommandItem>(title, score, *ranges); - return nullptr; -} - -// Returns the tab group that the currently selected tabs can *not* be moved to. -// In practice, this is the tab group that *all* selected tabs belong to, if -// any. In the common special case of single selection, this will return that -// tab's group if it has one. -std::optional<tab_groups::TabGroupId> IneligibleGroupForSelected( - TabStripModel* tab_strip_model) { - std::optional<tab_groups::TabGroupId> excluded_group = std::nullopt; - for (int index : tab_strip_model->selection_model().selected_indices()) { - auto group = tab_strip_model->GetTabGroupForTab(index); - if (group.has_value()) { - if (!excluded_group.has_value()) { - excluded_group = group; - } else if (group != excluded_group) { - // More than one group in the selection, so don't exclude anything. - return std::nullopt; - } - } - } - return excluded_group; -} - -// Returns true only if `browser` is alive, and the contents at `index` match -// `tab_session_id`. -bool DoesTabAtIndexMatchSessionId(base::WeakPtr<Browser> browser, - int index, - int tab_session_id) { - if (!browser.get()) - return false; - if (browser->tab_strip_model()->count() <= index) - return false; - content::WebContents* contents = - browser->tab_strip_model()->GetWebContentsAt(index); - DCHECK(contents); - return sessions::SessionTabHelper::IdForTab(contents).id() == tab_session_id; -} - -// Commands: - -// TODO(lgrey): If this command ships, upstream these to TabStripModel -// (and get access to private methods for consistency). -bool CanCloseTabsToLeft(const TabStripModel* model) { - const ui::ListSelectionModel& selection = model->selection_model(); - if (selection.empty()) - return false; - int left_selected = *(selection.selected_indices().cbegin()); - for (int i = 0; i < left_selected; ++i) { - if (!model->IsTabPinned(i)) - return true; - } - return false; -} - -void CloseTabsToLeft(Browser* browser) { - TabStripModel* model = browser->tab_strip_model(); - const ui::ListSelectionModel& selection = model->selection_model(); - if (selection.empty()) - return; - int left_selected = *(selection.selected_indices().cbegin()); - for (int i = left_selected - 1; i >= 0; --i) { - model->CloseWebContentsAt(i, TabCloseTypes::CLOSE_CREATE_HISTORICAL_TAB | - TabCloseTypes::CLOSE_USER_GESTURE); - } -} - -bool HasUnpinnedTabs(const TabStripModel* model) { - return model->IndexOfFirstNonPinnedTab() < model->count(); -} - -bool HasPinnedTabs(const TabStripModel* model) { - return model->IndexOfFirstNonPinnedTab() > 0; -} - -void CloseUnpinnedTabs(Browser* browser) { - TabStripModel* model = browser->tab_strip_model(); - for (int i = model->count() - 1; i >= 0; --i) { - if (!model->IsTabPinned(i)) - model->CloseWebContentsAt(i, TabCloseTypes::CLOSE_CREATE_HISTORICAL_TAB | - TabCloseTypes::CLOSE_USER_GESTURE); - } -} - -bool CanMoveTabsToExistingWindow(const Browser* browser_to_exclude) { - const BrowserList* browser_list = BrowserList::GetInstance(); - return base::ranges::any_of( - *browser_list, [browser_to_exclude](Browser* browser) { - return browser != browser_to_exclude && browser->is_type_normal() && - browser->profile() == browser_to_exclude->profile(); - }); -} - -void MoveTabsToExistingWindow(base::WeakPtr<Browser> source, - base::WeakPtr<Browser> target) { - if (!source.get() || !target.get()) - return; - const ui::ListSelectionModel::SelectedIndices& sel = - source->tab_strip_model()->selection_model().selected_indices(); - chrome::MoveTabsToExistingWindow(source.get(), target.get(), - std::vector<int>(sel.begin(), sel.end())); -} - -bool CanAddAllToNewGroup(const TabStripModel* model) { - return model->group_model()->ListTabGroups().size() == 0; -} - -void AddAllToNewGroup(Browser* browser) { - std::vector<int> indices(browser->tab_strip_model()->count()); - std::iota(indices.begin(), indices.end(), 0); - browser->tab_strip_model()->AddToNewGroup(indices); -} - -void AddSelectedToNewGroup(Browser* browser) { - TabStripModel* model = browser->tab_strip_model(); - const ui::ListSelectionModel::SelectedIndices& sel = - model->selection_model().selected_indices(); - model->AddToNewGroup(std::vector<int>(sel.begin(), sel.end())); -} - -void MuteAllTabs(Browser* browser, bool exclude_active) { - TabStripModel* model = browser->tab_strip_model(); - for (int i = 0; i < model->count(); ++i) { - if (exclude_active && i == model->active_index()) - return; - content::WebContents* contents = model->GetWebContentsAt(i); - if (contents->IsCurrentlyAudible()) - contents->SetAudioMuted(true); - } -} - -// TODO(lgrey): Precalculate tab strip properties like "has audible tabs", "has -// pinned tabs" etc. in one iteration at search time. -bool HasAudibleTabs(const TabStripModel* model) { - for (int i = 0; i < model->count(); ++i) { - content::WebContents* contents = model->GetWebContentsAt(i); - if (contents->IsCurrentlyAudible()) - return true; - } - return false; -} - -bool HasMutedTabs(const TabStripModel* model) { - for (int i = 0; i < model->count(); ++i) { - content::WebContents* contents = model->GetWebContentsAt(i); - if (contents->IsAudioMuted()) - return true; - } - return false; -} - -void ScrollToTop(Browser* browser) { - browser->tab_strip_model()->GetActiveWebContents()->ScrollToTopOfDocument(); -} - -void ScrollToBottom(Browser* browser) { - browser->tab_strip_model() - ->GetActiveWebContents() - ->ScrollToBottomOfDocument(); -} - -// Multiphase commands: - -void MuteUnmuteTab(base::WeakPtr<Browser> browser, - int tab_index, - int tab_session_id, - bool mute) { - if (!DoesTabAtIndexMatchSessionId(browser, tab_index, tab_session_id)) - return; - browser->tab_strip_model()->GetWebContentsAt(tab_index)->SetAudioMuted(mute); -} - -std::unique_ptr<CommandItem> CreateMuteUnmuteTabItem(const TabMatch& match, - Browser* browser, - bool mute) { - auto item = match.ToCommandItem(); - item->command = base::BindOnce(&MuteUnmuteTab, browser->AsWeakPtr(), - match.index, match.session_id, mute); - return item; -} - -CommandSource::CommandResults MuteUnmuteTabItemsForTabsMatching( - Browser* browser, - bool mute, - const std::u16string& input) { - CommandSource::CommandResults results; - TabSearchOptions options; - if (mute) - options.only_audible = true; - else - options.only_muted = true; - for (auto& match : TabsMatchingInput(browser, input, options)) { - results.push_back(CreateMuteUnmuteTabItem(match, browser, mute)); - } - return results; -} - -void TogglePinTab(base::WeakPtr<Browser> browser, - int tab_index, - int tab_session_id, - bool pin) { - if (!DoesTabAtIndexMatchSessionId(browser, tab_index, tab_session_id)) - return; - browser->tab_strip_model()->SetTabPinned(tab_index, pin); -} - -std::unique_ptr<CommandItem> CreatePinTabItem(const TabMatch& match, - Browser* browser, - bool pin) { - auto item = match.ToCommandItem(); - item->command = base::BindOnce(&TogglePinTab, browser->AsWeakPtr(), - match.index, match.session_id, pin); - return item; -} - -CommandSource::CommandResults TogglePinTabCommandsForTabsMatching( - Browser* browser, - bool pin, - const std::u16string& input) { - CommandSource::CommandResults results; - TabSearchOptions options; - if (pin) - options.only_unpinned = true; - else - options.only_pinned = true; - for (auto& match : TabsMatchingInput(browser, input, options)) { - results.push_back(CreatePinTabItem(match, browser, pin)); - } - return results; -} - -std::unique_ptr<CommandItem> CreateMoveTabsToWindowItem( - Browser* source, - const WindowMatch& match) { - auto item = match.ToCommandItem(); - item->command = base::BindOnce(&MoveTabsToExistingWindow, source->AsWeakPtr(), - match.browser->AsWeakPtr()); - return item; -} - -CommandSource::CommandResults MoveTabsToWindowCommandsForWindowsMatching( - Browser* source, - const std::u16string& input) { - CommandSource::CommandResults results; - // Add "New Window", if appropriate. It should score highest with no input. - std::u16string new_window_title = l10n_util::GetStringUTF16(IDS_NEW_WINDOW); - std::erase(new_window_title, '&'); - std::unique_ptr<CommandItem> item; - if (input.empty()) { - item = std::make_unique<CommandItem>(new_window_title, .99, - std::vector<gfx::Range>()); - } else { - FuzzyFinder finder(input); - std::vector<gfx::Range> ranges; - item = ItemForTitle(new_window_title, finder, &ranges); - } - if (item) { - item->entity_type = CommandItem::Entity::kWindow; - item->command = base::BindOnce(&chrome::MoveActiveTabToNewWindow, - base::Unretained(source)); - results.push_back(std::move(item)); - } - for (auto& match : WindowsMatchingInput(source, input)) - results.push_back(CreateMoveTabsToWindowItem(source, match)); - return results; -} - -void AddTabsToGroup(base::WeakPtr<Browser> browser, - tab_groups::TabGroupId group) { - if (!browser.get()) - return; - const ui::ListSelectionModel::SelectedIndices& sel = - browser->tab_strip_model()->selection_model().selected_indices(); - browser->tab_strip_model()->AddToExistingGroup( - std::vector<int>(sel.begin(), sel.end()), group); -} - -CommandSource::CommandResults AddTabsToGroupCommandsForGroupsMatching( - Browser* browser, - const std::u16string& input) { - CommandSource::CommandResults results; - TabStripModel* tab_strip_model = browser->tab_strip_model(); - // Add "New Group", if appropriate. It should score highest with no input. - std::u16string new_group_title = - l10n_util::GetStringUTF16(IDS_TAB_CXMENU_SUBMENU_NEW_GROUP); - std::unique_ptr<CommandItem> item; - if (input.empty()) { - item = std::make_unique<CommandItem>(new_group_title, .99, - std::vector<gfx::Range>()); - } else { - FuzzyFinder finder(input); - std::vector<gfx::Range> ranges; - item = ItemForTitle(new_group_title, finder, &ranges); - } - if (item) { - item->entity_type = CommandItem::Entity::kGroup; - item->command = - base::BindOnce(&AddSelectedToNewGroup, base::Unretained(browser)); - results.push_back(std::move(item)); - } - for (auto& match : GroupsMatchingInput( - browser, input, IneligibleGroupForSelected(tab_strip_model))) { - auto command_item = match.ToCommandItem(); - command_item->command = - base::BindOnce(&AddTabsToGroup, browser->AsWeakPtr(), match.group); - results.push_back(std::move(command_item)); - } - return results; -} - -} // namespace - -TabCommandSource::TabCommandSource() = default; -TabCommandSource::~TabCommandSource() = default; - -CommandSource::CommandResults TabCommandSource::GetCommands( - const std::u16string& input, - Browser* browser) const { - CommandSource::CommandResults results; - FuzzyFinder finder(input); - std::vector<gfx::Range> ranges; - ui::AcceleratorProvider* provider = - chrome::AcceleratorProviderForBrowser(browser); - - TabStripModel* tab_strip_model = browser->tab_strip_model(); - // TODO(lgrey): Temporarily using hardcoded English titles instead of - // translated strings so we can experiment without adding translation load. - if (auto item = ItemForTitle(u"Close current tab", finder, &ranges)) { - item->command = - base::BindOnce(&chrome::CloseTab, base::Unretained(browser)); - ui::Accelerator accelerator; - if (provider->GetAcceleratorForCommandId(IDC_CLOSE_TAB, &accelerator)) - item->annotation = accelerator.GetShortcutText(); - results.push_back(std::move(item)); - } - if (chrome::CanCloseOtherTabs(browser)) { - if (auto item = ItemForTitle(u"Close other tabs", finder, &ranges)) { - item->command = - base::BindOnce(&chrome::CloseOtherTabs, base::Unretained(browser)); - results.push_back(std::move(item)); - } - } - if (chrome::CanCloseTabsToRight(browser)) { - if (auto item = ItemForTitle(u"Close tabs to the right", finder, &ranges)) { - item->command = - base::BindOnce(&chrome::CloseTabsToRight, base::Unretained(browser)); - results.push_back(std::move(item)); - } - } - - if (CanCloseTabsToLeft(tab_strip_model)) { - if (auto item = ItemForTitle(u"Close tabs to the left", finder, &ranges)) { - item->command = - base::BindOnce(&CloseTabsToLeft, base::Unretained(browser)); - results.push_back(std::move(item)); - } - } - - if (HasUnpinnedTabs(tab_strip_model)) { - if (auto item = ItemForTitle(u"Close unpinned tabs", finder, &ranges)) { - item->command = - base::BindOnce(&CloseUnpinnedTabs, base::Unretained(browser)); - results.push_back(std::move(item)); - } - } - - if (chrome::CanMoveActiveTabToNewWindow(browser)) { - if (auto item = - ItemForTitle(l10n_util::GetStringUTF16(IDS_MOVE_TAB_TO_NEW_WINDOW), - finder, &ranges)) { - item->command = base::BindOnce(chrome::MoveActiveTabToNewWindow, - base::Unretained(browser)); - results.push_back(std::move(item)); - } - } - - if (CanMoveTabsToExistingWindow(browser)) { - if (auto item = ItemForTitle(u"Move tabs to window...", finder, &ranges)) { - item->command = std::make_pair( - u"Move tabs to...", - base::BindRepeating(&MoveTabsToWindowCommandsForWindowsMatching, - base::Unretained(browser))); - results.push_back(std::move(item)); - } - } - - if (CanAddAllToNewGroup(tab_strip_model)) { - if (auto item = - ItemForTitle(u"Move all tabs to new group", finder, &ranges)) { - item->command = - base::BindOnce(&AddAllToNewGroup, base::Unretained(browser)); - results.push_back(std::move(item)); - } - } - - if (!tab_strip_model->WillContextMenuGroup(tab_strip_model->active_index())) { - if (auto item = ItemForTitle(u"Ungroup tab", finder, &ranges)) { - item->command = - base::BindOnce(&chrome::GroupTab, base::Unretained(browser)); - results.push_back(std::move(item)); - } - } - if (auto item = ItemForTitle(u"Add tab to group...", finder, &ranges)) { - item->command = std::make_pair( - u"Add to group...", - base::BindRepeating(&AddTabsToGroupCommandsForGroupsMatching, - base::Unretained(browser))); - results.push_back(std::move(item)); - } - if (auto item = ItemForTitle(u"Mute all tabs", finder, &ranges)) { - item->command = - base::BindOnce(&MuteAllTabs, base::Unretained(browser), false); - results.push_back(std::move(item)); - } - - if (auto item = ItemForTitle(u"Mute other tabs", finder, &ranges)) { - item->command = - base::BindOnce(&MuteAllTabs, base::Unretained(browser), false); - results.push_back(std::move(item)); - } - - if (HasAudibleTabs(tab_strip_model)) { - if (auto item = ItemForTitle(u"Mute tab...", finder, &ranges)) { - item->command = - std::make_pair(u"Mute tab...", - base::BindRepeating(&MuteUnmuteTabItemsForTabsMatching, - base::Unretained(browser), true)); - results.push_back(std::move(item)); - } - } - - if (HasMutedTabs(tab_strip_model)) { - if (auto item = ItemForTitle(u"Unmute tab...", finder, &ranges)) { - item->command = - std::make_pair(u"Unmute tab...", - base::BindRepeating(&MuteUnmuteTabItemsForTabsMatching, - base::Unretained(browser), false)); - results.push_back(std::move(item)); - } - } - - if (HasUnpinnedTabs(tab_strip_model)) { - if (auto item = ItemForTitle(u"Pin tab...", finder, &ranges)) { - item->command = std::make_pair( - u"Pin tab...", - base::BindRepeating(&TogglePinTabCommandsForTabsMatching, - base::Unretained(browser), true)); - results.push_back((std::move(item))); - } - } - - if (HasPinnedTabs(tab_strip_model)) { - if (auto item = ItemForTitle(u"Unpin tab...", finder, &ranges)) { - item->command = std::make_pair( - u"Unpin tab...", - base::BindRepeating(&TogglePinTabCommandsForTabsMatching, - base::Unretained(browser), false)); - results.push_back((std::move(item))); - } - } - - if (chrome::CanMoveActiveTabToReadLater(browser)) { - if (auto item = ItemForTitle(u"Add to Read Later", finder, &ranges)) { - item->command = - base::BindOnce(IgnoreResult(&chrome::MoveCurrentTabToReadLater), - base::Unretained(browser)); - results.push_back(std::move(item)); - } - } - - if (auto item = ItemForTitle(u"Scroll to top", finder, &ranges)) { - item->command = base::BindOnce(&ScrollToTop, base::Unretained(browser)); - results.push_back(std::move(item)); - } - - if (auto item = ItemForTitle(u"Scroll to bottom", finder, &ranges)) { - item->command = base::BindOnce(&ScrollToBottom, base::Unretained(browser)); - results.push_back(std::move(item)); - } - - if (send_tab_to_self::ShouldDisplayEntryPoint( - tab_strip_model->GetActiveWebContents())) { - if (auto item = ItemForTitle(u"Send tab to self...", finder, &ranges)) { - item->command = base::BindOnce(&chrome::SendTabToSelfFromPageAction, - base::Unretained(browser)); - results.push_back(std::move(item)); - } - } - - return results; -} - -} // namespace commander
diff --git a/chrome/browser/ui/commander/tab_command_source.h b/chrome/browser/ui/commander/tab_command_source.h deleted file mode 100644 index 56f648e..0000000 --- a/chrome/browser/ui/commander/tab_command_source.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COMMANDER_TAB_COMMAND_SOURCE_H_ -#define CHROME_BROWSER_UI_COMMANDER_TAB_COMMAND_SOURCE_H_ - -#include "chrome/browser/ui/commander/command_source.h" - -namespace commander { - -// Source for commands that manipulate tabs. -class TabCommandSource : public CommandSource { - public: - TabCommandSource(); - ~TabCommandSource() override; - - TabCommandSource(const TabCommandSource& other) = delete; - TabCommandSource& operator=(const TabCommandSource& other) = delete; - - // Command source overrides - CommandSource::CommandResults GetCommands(const std::u16string& input, - Browser* browser) const override; -}; -} // namespace commander - -#endif // CHROME_BROWSER_UI_COMMANDER_TAB_COMMAND_SOURCE_H_
diff --git a/chrome/browser/ui/commander/window_command_source.cc b/chrome/browser/ui/commander/window_command_source.cc deleted file mode 100644 index 25a1ae91..0000000 --- a/chrome/browser/ui/commander/window_command_source.cc +++ /dev/null
@@ -1,111 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/commander/window_command_source.h" - -#include <numeric> - -#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/commander/entity_match.h" -#include "chrome/browser/ui/commander/fuzzy_finder.h" - -namespace commander { - -namespace { - -// Activates `browser` if it's still present. -void SwitchToBrowser(base::WeakPtr<Browser> browser) { - if (browser.get()) - browser->window()->Show(); -} - -// Merges all tabs from `source` into `target`, if they are both present. -void MergeBrowsers(base::WeakPtr<Browser> source, - base::WeakPtr<Browser> target) { - if (!source.get() || !target.get()) - return; - size_t source_count = source->tab_strip_model()->count(); - std::vector<int> indices(source_count); - std::iota(indices.begin(), indices.end(), 0); - chrome::MoveTabsToExistingWindow(source.get(), target.get(), indices); -} - -// Returns browser windows whose titles fuzzy match `input`. If input is empty, -// returns all eligible browser windows with score reflecting MRU order. -// `browser_to_exclude` is excluded from the list, as are all browser windows -// from a different profile unless `match_profile` is false. - -std::unique_ptr<CommandItem> CreateSwitchWindowItem(const WindowMatch& match) { - auto item = match.ToCommandItem(); - item->command = base::BindOnce(&SwitchToBrowser, match.browser->AsWeakPtr()); - return item; -} - -std::unique_ptr<CommandItem> CreateMergeWindowItem(Browser* source, - const WindowMatch& target) { - auto item = target.ToCommandItem(); - item->command = base::BindOnce(&MergeBrowsers, source->AsWeakPtr(), - target.browser->AsWeakPtr()); - return item; -} - -CommandSource::CommandResults SwitchCommandsForWindowsMatching( - Browser* browser_to_exclude, - const std::u16string& input) { - CommandSource::CommandResults results; - for (auto& match : WindowsMatchingInput(browser_to_exclude, input)) - results.push_back(CreateSwitchWindowItem(match)); - return results; -} - -CommandSource::CommandResults MergeCommandsForWindowsMatching( - Browser* source_browser, - const std::u16string& input) { - CommandSource::CommandResults results; - for (auto& match : WindowsMatchingInput(source_browser, input, true)) - results.push_back(CreateMergeWindowItem(source_browser, match)); - return results; -} - -} // namespace - -WindowCommandSource::WindowCommandSource() = default; -WindowCommandSource::~WindowCommandSource() = default; - -CommandSource::CommandResults WindowCommandSource::GetCommands( - const std::u16string& input, - Browser* browser) const { - CommandSource::CommandResults results; - BrowserList* browser_list = BrowserList::GetInstance(); - if (browser_list->size() < 2) - return results; - FuzzyFinder finder(input); - std::vector<gfx::Range> ranges; - // TODO(lgrey): Temporarily using untranslated strings since it's not - // yet clear which commands will ship. - std::u16string open_title = u"Switch to window..."; - std::u16string merge_title = u"Merge current window into..."; - - double score = finder.Find(open_title, &ranges); - if (score > 0) { - auto verb = std::make_unique<CommandItem>(open_title, score, ranges); - verb->command = std::make_pair( - open_title, base::BindRepeating(&SwitchCommandsForWindowsMatching, - base::Unretained(browser))); - results.push_back(std::move(verb)); - } - score = finder.Find(merge_title, &ranges); - if (score > 0 && !browser->is_type_devtools()) { - auto verb = std::make_unique<CommandItem>(merge_title, score, ranges); - verb->command = std::make_pair( - merge_title, base::BindRepeating(&MergeCommandsForWindowsMatching, - base::Unretained(browser))); - results.push_back(std::move(verb)); - } - return results; -} -} // namespace commander
diff --git a/chrome/browser/ui/commander/window_command_source.h b/chrome/browser/ui/commander/window_command_source.h deleted file mode 100644 index af8621f..0000000 --- a/chrome/browser/ui/commander/window_command_source.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COMMANDER_WINDOW_COMMAND_SOURCE_H_ -#define CHROME_BROWSER_UI_COMMANDER_WINDOW_COMMAND_SOURCE_H_ - -#include "chrome/browser/ui/commander/command_source.h" - -namespace commander { - -// Command source for window-related commands. -class WindowCommandSource : public CommandSource { - public: - WindowCommandSource(); - ~WindowCommandSource() override; - - WindowCommandSource(const WindowCommandSource& other) = delete; - WindowCommandSource& operator=(const WindowCommandSource& other) = delete; - - // Command source overrides - CommandSource::CommandResults GetCommands(const std::u16string& input, - Browser* browser) const override; -}; -} // namespace commander - -#endif // CHROME_BROWSER_UI_COMMANDER_WINDOW_COMMAND_SOURCE_H_
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 b370456..b8fca41 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
@@ -350,9 +350,9 @@ ASSERT_FALSE(IsWindowFullscreenForTabOrPending()); } -// TODO(crbug.com/1230771) Flaky on Linux-ozone and Lacros +// TODO(crbug.com/1230771) Flaky on Linux-ozone, Lacros and MacOS. #if (BUILDFLAG(IS_LINUX) && BUILDFLAG(IS_OZONE)) || \ - BUILDFLAG(IS_CHROMEOS_LACROS) + BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_MAC) #define MAYBE_TabEntersPresentationModeFromWindowed \ DISABLED_TabEntersPresentationModeFromWindowed #else
diff --git a/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.cc b/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.cc index d71ee16..b3d507d 100644 --- a/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.cc +++ b/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.cc
@@ -8,6 +8,15 @@ #include "components/performance_manager/public/features.h" #include "content/public/browser/navigation_handle.h" +void TabResourceUsage::SetMemoryUsageInBytes(uint64_t memory_usage_bytes) { + memory_usage_bytes_ = memory_usage_bytes; + is_high_memory_usage_ = + memory_usage_bytes_ > + base::checked_cast<uint64_t>( + performance_manager::features:: + kMemoryUsageInHovercardsHighThresholdBytes.Get()); +} + WEB_CONTENTS_USER_DATA_KEY_IMPL(TabResourceUsageTabHelper); TabResourceUsageTabHelper::~TabResourceUsageTabHelper() = default; @@ -21,7 +30,7 @@ void TabResourceUsageTabHelper::PrimaryPageChanged(content::Page&) { // Reset memory usage count when we navigate to another site since the // memory usage reported will be outdated. - resource_usage_->set_memory_usage_in_bytes(0); + resource_usage_->SetMemoryUsageInBytes(0); } void TabResourceUsageTabHelper::DidFinishNavigation( @@ -41,7 +50,7 @@ void TabResourceUsageTabHelper::SetMemoryUsageInBytes( uint64_t memory_usage_bytes) { - resource_usage_->set_memory_usage_in_bytes(memory_usage_bytes); + resource_usage_->SetMemoryUsageInBytes(memory_usage_bytes); } scoped_refptr<const TabResourceUsage>
diff --git a/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h b/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h index b3ad596..b8b6813 100644 --- a/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h +++ b/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_TAB_RESOURCE_USAGE_TAB_HELPER_H_ #define CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_TAB_RESOURCE_USAGE_TAB_HELPER_H_ +#include "components/performance_manager/public/features.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" @@ -18,15 +19,16 @@ uint64_t memory_usage_in_bytes() const { return memory_usage_bytes_; } - void set_memory_usage_in_bytes(uint64_t memory_usage_bytes) { - memory_usage_bytes_ = memory_usage_bytes; - } + void SetMemoryUsageInBytes(uint64_t memory_usage_bytes); + + bool is_high_memory_usage() const { return is_high_memory_usage_; } private: friend class base::RefCounted<TabResourceUsage>; ~TabResourceUsage() = default; uint64_t memory_usage_bytes_ = 0; + bool is_high_memory_usage_ = false; }; // Per-tab class to keep track of current memory usage for each tab.
diff --git a/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper_unittest.cc b/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper_unittest.cc index 17c2aca..9da068b 100644 --- a/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper_unittest.cc +++ b/chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/performance_controls/tab_resource_usage_tab_helper.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "components/performance_manager/public/features.h" #include "url/gurl.h" namespace { @@ -36,3 +37,15 @@ NavigateAndCommit(GURL(kTestDomain)); EXPECT_EQ(tab_helper->GetMemoryUsageInBytes(), 0u); } + +// Correctly reports whether memory usage is high after memory usage is set. +TEST_F(TabResourceUsageTabHelperTest, HighMemoryUsage) { + auto* const tab_helper = InitializeTabHelper(); + uint64_t const high_memory_usage_threshold = static_cast<uint64_t>( + performance_manager::features::kMemoryUsageInHovercardsHighThresholdBytes + .Get()); + tab_helper->SetMemoryUsageInBytes(high_memory_usage_threshold); + EXPECT_FALSE(tab_helper->resource_usage()->is_high_memory_usage()); + tab_helper->SetMemoryUsageInBytes(high_memory_usage_threshold + 1); + EXPECT_TRUE(tab_helper->resource_usage()->is_high_memory_usage()); +}
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index dcd506b..1610c28 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -240,10 +240,6 @@ #include "chrome/browser/ui/shared_highlighting/shared_highlighting_promo.h" #endif -#if BUILDFLAG(IS_MAC) -#include "chrome/browser/ui/cocoa/screentime/tab_helper.h" -#endif - #if BUILDFLAG(IS_WIN) #include "chrome/browser/font_prewarmer_tab_helper.h" #endif @@ -652,12 +648,6 @@ } #endif -#if BUILDFLAG(IS_MAC) - if (screentime::TabHelper::IsScreentimeEnabledForProfile(profile)) { - screentime::TabHelper::CreateForWebContents(web_contents); - } -#endif - #if BUILDFLAG(IS_CHROMEOS_ASH) GoogleOneOfferIphTabHelper::CreateForWebContents(web_contents); ash::BootTimesRecorderTabHelper::MaybeCreateForWebContents(web_contents);
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc index bb41ecd..23eef8b 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.cc +++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -45,7 +45,6 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/commander/commander.h" #include "chrome/browser/ui/global_error/global_error.h" #include "chrome/browser/ui/global_error/global_error_service.h" #include "chrome/browser/ui/global_error/global_error_service_factory.h" @@ -700,9 +699,6 @@ AddItemWithStringId(IDC_CREATE_SHORTCUT, IDS_ADD_TO_OS_LAUNCH_SURFACE); } AddItemWithStringId(IDC_NAME_WINDOW, IDS_NAME_WINDOW); - if (commander::IsEnabled()) { - AddItemWithStringId(IDC_TOGGLE_QUICK_COMMANDS, IDS_TOGGLE_QUICK_COMMANDS); - } if (features::IsSidePanelPinningEnabled()) { AddItemWithStringId(IDC_SHOW_READING_MODE_SIDE_PANEL, @@ -760,7 +756,6 @@ } } SetCommandIcon(this, IDC_NAME_WINDOW, kNameWindowIcon); - SetCommandIcon(this, IDC_TOGGLE_QUICK_COMMANDS, kQuickCommandsIcon); SetCommandIcon(this, IDC_SHOW_READING_MODE_SIDE_PANEL, kMenuBookChromeRefreshIcon); SetCommandIcon(this, IDC_PERFORMANCE, kPerformanceIcon);
diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc index f4c71cb..1c0fd6fb 100644 --- a/chrome/browser/ui/ui_features.cc +++ b/chrome/browser/ui/ui_features.cc
@@ -98,11 +98,6 @@ base::FEATURE_ENABLED_BY_DEFAULT); #endif -// Enables the QuickCommands UI surface. See https://crbug.com/1014639 -BASE_FEATURE(kQuickCommands, - "QuickCommands", - base::FEATURE_DISABLED_BY_DEFAULT); - // Enable responsive toolbar. Toolbar buttons overflow to a chevron button when // the browser width is resized smaller than normal. BASE_FEATURE(kResponsiveToolbar,
diff --git a/chrome/browser/ui/ui_features.h b/chrome/browser/ui/ui_features.h index 90de44b6..ed44e667d 100644 --- a/chrome/browser/ui/ui_features.h +++ b/chrome/browser/ui/ui_features.h
@@ -60,8 +60,6 @@ BASE_DECLARE_FEATURE(kLightweightExtensionOverrideConfirmations); #endif -BASE_DECLARE_FEATURE(kQuickCommands); - BASE_DECLARE_FEATURE(kResponsiveToolbar); BASE_DECLARE_FEATURE(kScrollableTabStrip);
diff --git a/chrome/browser/ui/views/accelerator_table.cc b/chrome/browser/ui/views/accelerator_table.cc index 8e702ab..3689a5cd 100644 --- a/chrome/browser/ui/views/accelerator_table.cc +++ b/chrome/browser/ui/views/accelerator_table.cc
@@ -247,10 +247,6 @@ {ui::VKEY_OEM_MINUS, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_ZOOM_MINUS}, {ui::VKEY_OEM_PLUS, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_ZOOM_PLUS}, - // TODO(https://crbug.com/1016439): This is a temporary hotkey. Chrome OS - // uses this for switching IMEs, but since this feature is only exposed via - // command line flag at the moment, we'll exclude them entirely for now. - {ui::VKEY_SPACE, ui::EF_CONTROL_DOWN, IDC_TOGGLE_QUICK_COMMANDS}, #endif // !BUILDFLAG(IS_CHROMEOS) #endif // !BUILDFLAG(IS_MAC) #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) && \
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc index a4117dbc..81d3321 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
@@ -60,6 +60,7 @@ #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/ozone_buildflags.h" #include "ui/base/test/ui_controls.h" +#include "ui/base/ui_base_features.h" #include "ui/display/display_switches.h" #include "ui/events/keycodes/keyboard_codes.h" #include "ui/views/background.h" @@ -922,8 +923,16 @@ } }; +#if BUILDFLAG(IS_OZONE_WAYLAND) +// TODO (crbug/1523247): This test is failing under wayland when the +// ChromeRefresh2023 flags are set. This skips it +// until it can be fixed. +#define MAYBE_OpenMenuOnClickAndHold DISABLED_OpenMenuOnClickAndHold +#else +#define MAYBE_OpenMenuOnClickAndHold OpenMenuOnClickAndHold +#endif // If this flakes, disable and log details in http://crbug.com/523255. -VIEW_TEST(BookmarkBarViewTest6, OpenMenuOnClickAndHold) +VIEW_TEST(BookmarkBarViewTest6, MAYBE_OpenMenuOnClickAndHold) // Tests drag and drop to different menu. class BookmarkBarViewTest7 : public BookmarkBarViewDragTestBase { @@ -1872,6 +1881,11 @@ // TODO(https://crbug.com/1506808): Flaky on Windows. #if BUILDFLAG(IS_WIN) #define MAYBE_ContextMenuExitTest DISABLED_ContextMenuExitTest +#elif BUILDFLAG(IS_OZONE_WAYLAND) +// TODO (crbug/1523247): This test is failing under wayland when the +// ChromeRefresh2023 flags are set. This skips it +// until it can be fixed. +#define MAYBE_ContextMenuExitTest DISABLED_ContextMenuExitTest #else #define MAYBE_ContextMenuExitTest ContextMenuExitTest #endif
diff --git a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc index d3175d6..0aec2dc 100644 --- a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc +++ b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
@@ -11,7 +11,6 @@ #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/net/system_network_context_manager.h" -#include "chrome/browser/ui/commander/commander.h" #include "chrome/browser/ui/views/chrome_constrained_window_views_client.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/chrome_views_delegate.h" @@ -170,8 +169,6 @@ relaunch_notification_controller_ = std::make_unique<RelaunchNotificationController>( UpgradeDetector::GetInstance()); - if (commander::IsEnabled()) - commander::Commander::Get()->Initialize(); } void ChromeBrowserMainExtraPartsViews::PostMainMessageLoopRun() {
diff --git a/chrome/browser/ui/views/commander_frontend_views.cc b/chrome/browser/ui/views/commander_frontend_views.cc deleted file mode 100644 index e22977b1..0000000 --- a/chrome/browser/ui/views/commander_frontend_views.cc +++ /dev/null
@@ -1,309 +0,0 @@ -// Copyright 2020 The Chromium Authors -// 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/commander_frontend_views.h" - -#include <tuple> - -#include "base/functional/bind.h" -#include "base/functional/callback_helpers.h" -#include "base/memory/raw_ptr.h" -#include "base/memory/raw_ptr_exclusion.h" -#include "build/build_config.h" -#include "build/chromeos_buildflags.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/lifetime/termination_notification.h" -#include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h" -#include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/task_manager/web_contents_tags.h" -#include "chrome/browser/ui/browser_list.h" -#include "chrome/browser/ui/commander/commander_backend.h" -#include "chrome/browser/ui/commander/commander_view_model.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/frame/top_container_view.h" -#include "chrome/browser/ui/views/theme_copying_widget.h" -#include "chrome/browser/ui/webui/commander/commander_ui.h" -#include "chrome/common/webui_url_constants.h" -#include "chrome/grit/generated_resources.h" -#include "ui/base/metadata/metadata_header_macros.h" -#include "ui/base/metadata/metadata_impl_macros.h" -#include "ui/gfx/geometry/rounded_corners_f.h" -#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h" -#include "ui/views/controls/webview/webview.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -#if BUILDFLAG(IS_WIN) -#include "ui/views/widget/native_widget_aura.h" -#endif - -namespace { -constexpr gfx::Size kDefaultSize(512, 48); -constexpr int kTopContainerOverlapMargin = 12; -constexpr int kCornerRadius = 8; - -// -void AnchorToBrowser(gfx::Rect* bounds, Browser* browser) { - DCHECK(browser); - BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); - gfx::Rect top_container_bounds = - browser_view->top_container()->GetBoundsInScreen(); - - bounds->set_x(top_container_bounds.x() + - (top_container_bounds.width() - bounds->width()) / 2); - bounds->set_y(top_container_bounds.bottom() - kTopContainerOverlapMargin); -} - -} // namespace - -// Helper to dismiss the commander widget on focus loss. This exists since -// `CommanderFrontendViews` is also a widget observer (but for the parent -// widget); splitting the responsibilities avoids the potential for awkward -// misunderstandings. -class CommanderFocusLossWatcher : public views::WidgetObserver { - public: - CommanderFocusLossWatcher(commander::CommanderFrontend* frontend, - views::Widget* widget) - : frontend_(frontend) { - widget_observation_.Observe(widget); - } - ~CommanderFocusLossWatcher() override = default; - - // views::WidgetObserver - void OnWidgetActivationChanged(views::Widget* widget, bool active) override { - if (!active) - frontend_->Hide(); - } - - private: - raw_ptr<commander::CommanderFrontend> frontend_; // weak, owns us - base::ScopedObservation<views::Widget, views::WidgetObserver> - widget_observation_{this}; -}; - -// A small shim to handle passing keyboard events back up to the browser. -// Required for hotkeys to work. -class CommanderWebView : public views::WebView { - METADATA_HEADER(CommanderWebView, views::WebView) - - public: - explicit CommanderWebView(content::BrowserContext* context) - : views::WebView(context) {} - bool HandleKeyboardEvent( - content::WebContents* source, - const content::NativeWebKeyboardEvent& event) override { - CHECK(owner_); - return event_handler_.HandleKeyboardEvent(event, owner_->GetFocusManager()); - } - - bool HandleContextMenu(content::RenderFrameHost& render_frame_host, - const content::ContextMenuParams& params) override { - return true; - } - - void AddedToWidget() override { - views::WebView::AddedToWidget(); - holder()->SetCornerRadii(gfx::RoundedCornersF(kCornerRadius)); - } - - void SetOwner(views::View* owner) { - if (owner_ == owner) - return; - owner_ = owner; - OnPropertyChanged(&owner_, views::kPropertyEffectsNone); - } - views::View* GetOwner() const { return owner_; } - - private: - views::UnhandledKeyboardEventHandler event_handler_; - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #addr-of - RAW_PTR_EXCLUSION views::View* owner_ = nullptr; -}; - -BEGIN_METADATA(CommanderWebView) -ADD_PROPERTY_METADATA(views::View*, Owner) -END_METADATA - -CommanderFrontendViews::CommanderFrontendViews( - commander::CommanderBackend* backend) - : backend_(backend) { - backend_->SetUpdateCallback( - base::BindRepeating(&CommanderFrontendViews::OnViewModelUpdated, - weak_ptr_factory_.GetWeakPtr())); - subscription_ = browser_shutdown::AddAppTerminatingCallback(base::BindOnce( - &CommanderFrontendViews::OnAppTerminating, base::Unretained(this))); -} - -CommanderFrontendViews::~CommanderFrontendViews() { - backend_->SetUpdateCallback(base::DoNothing()); - if (widget_) - widget_->CloseNow(); -} -void CommanderFrontendViews::ToggleForBrowser(Browser* browser) { - DCHECK(browser); - // This ensures that quick commands are only available for normal browsers. - if (!browser->is_type_normal()) - return; - bool should_show = !browser_ || browser != browser_; - if (browser_) - Hide(); - if (should_show) - Show(browser); -} - -void CommanderFrontendViews::Show(Browser* browser) { - DCHECK(!is_showing()); - DCHECK_EQ(nullptr, web_view_.get()); - browser_ = browser; - BrowserList::AddObserver(this); - views::View* parent = BrowserView::GetBrowserViewForBrowser(browser_); - widget_delegate_ = std::make_unique<views::WidgetDelegate>(); - widget_delegate_->SetCanActivate(true); - views::Widget* parent_widget = parent->GetWidget(); - parent_widget->AddObserver(this); - widget_ = new ThemeCopyingWidget(parent_widget); - views::Widget::InitParams params( - views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - params.delegate = widget_delegate_.get(); - params.name = "Quick Commands"; - params.parent = parent->GetWidget()->GetNativeView(); - params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent; -// On Windows, this defaults to DesktopNativeWidgetAura, which has incorrect -// parenting behavior for this widget. -#if BUILDFLAG(IS_WIN) - params.native_widget = new views::NativeWidgetAura(widget_); -#endif - widget_->Init(std::move(params)); - focus_loss_watcher_ = - std::make_unique<CommanderFocusLossWatcher>(this, widget_); - - auto web_view = CreateWebView(browser->profile()); - web_view->SetOwner(parent); - web_view->SetSize(kDefaultSize); - CommanderUI* controller = static_cast<CommanderUI*>( - web_view->GetWebContents()->GetWebUI()->GetController()); - controller->handler()->PrepareToShow(this); - - web_view_ = widget_->SetContentsView(std::move(web_view)); - - gfx::Rect bounds; - bounds.set_size(kDefaultSize); - AnchorToBrowser(&bounds, browser_); - widget_->SetBounds(bounds); - - widget_->Show(); - - web_view_->RequestFocus(); - web_view_->GetWebContents()->Focus(); -} - -void CommanderFrontendViews::Hide() { - DCHECK(is_showing()); - - BrowserView::GetBrowserViewForBrowser(browser_)->GetWidget()->RemoveObserver( - this); - BrowserList::RemoveObserver(this); - backend_->Reset(); - browser_ = nullptr; - - widget_->GetRootView()->RemoveChildViewT(std::exchange(web_view_, nullptr)); - - focus_loss_watcher_.reset(); - widget_delegate_->SetOwnedByWidget(true); - std::ignore = widget_delegate_.release(); - widget_->Close(); - widget_ = nullptr; -} - -void CommanderFrontendViews::OnBrowserClosing(Browser* browser) { - if (browser_ == browser) - Hide(); -} - -void CommanderFrontendViews::OnAppTerminating() { - if (is_showing()) - Hide(); -} - -void CommanderFrontendViews::OnWidgetBoundsChanged( - views::Widget* widget, - const gfx::Rect& new_bounds) { - DCHECK(browser_); - DCHECK(is_showing()); - DCHECK(widget == - BrowserView::GetBrowserViewForBrowser(browser_)->GetWidget()); - gfx::Rect bounds = widget_->GetWindowBoundsInScreen(); - AnchorToBrowser(&bounds, browser_); - widget_->SetBounds(bounds); -} - -void CommanderFrontendViews::OnTextChanged(const std::u16string& text) { - DCHECK(is_showing()); - backend_->OnTextChanged(text, browser_); -} - -void CommanderFrontendViews::OnOptionSelected(size_t option_index, - int result_set_id) { - DCHECK(is_showing()); - backend_->OnCommandSelected(option_index, result_set_id); -} - -void CommanderFrontendViews::OnCompositeCommandCancelled() { - DCHECK(is_showing()); - backend_->OnCompositeCommandCancelled(); -} - -void CommanderFrontendViews::OnDismiss() { - Hide(); -} - -void CommanderFrontendViews::OnHeightChanged(int new_height) { - DCHECK(is_showing()); - gfx::Size size = kDefaultSize; - size.set_height(new_height); - widget_->SetSize(size); - web_view_->SetSize(size); -} - -void CommanderFrontendViews::OnHandlerEnabled(bool is_enabled) { - is_handler_enabled_ = is_enabled; -} - -void CommanderFrontendViews::OnViewModelUpdated( - commander::CommanderViewModel view_model) { - DCHECK(is_showing()); - if (view_model.action == commander::CommanderViewModel::Action::kClose) { - Hide(); - return; - } - if (!is_handler_enabled_) - // TODO(lgrey): Think through whether it makes sense to stash the view model - // and send it when the handler becomes available again. - return; - CommanderUI* controller = static_cast<CommanderUI*>( - web_view_->GetWebContents()->GetWebUI()->GetController()); - controller->handler()->ViewModelUpdated(std::move(view_model)); - // TODO(lgrey): Pass view model to WebUI. -} - -std::unique_ptr<CommanderWebView> CommanderFrontendViews::CreateWebView( - Profile* profile) { - DCHECK(profile); - auto web_view = std::make_unique<CommanderWebView>(profile); - web_view->set_allow_accelerators(true); - // Make the commander WebContents show up in the task manager. - content::WebContents* web_contents = web_view->GetWebContents(); - task_manager::WebContentsTags::CreateForToolContents( - web_contents, IDS_QUICK_COMMANDS_LABEL); - web_view->LoadInitialURL(GURL(chrome::kChromeUICommanderURL)); - return web_view; -} - -// static -std::unique_ptr<commander::CommanderFrontend> -commander::CommanderFrontend::Create(commander::CommanderBackend* backend) { - return std::make_unique<CommanderFrontendViews>(backend); -}
diff --git a/chrome/browser/ui/views/commander_frontend_views.h b/chrome/browser/ui/views/commander_frontend_views.h deleted file mode 100644 index fc0f3cc..0000000 --- a/chrome/browser/ui/views/commander_frontend_views.h +++ /dev/null
@@ -1,96 +0,0 @@ -// Copyright 2020 The Chromium Authors -// 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_COMMANDER_FRONTEND_VIEWS_H_ -#define CHROME_BROWSER_UI_VIEWS_COMMANDER_FRONTEND_VIEWS_H_ - -#include <memory> - -#include "base/callback_list.h" -#include "base/memory/raw_ptr.h" -#include "base/memory/weak_ptr.h" -#include "chrome/browser/ui/browser_list_observer.h" -#include "chrome/browser/ui/commander/commander_frontend.h" -#include "chrome/browser/ui/webui/commander/commander_handler.h" -#include "ui/views/widget/widget_observer.h" - -class CommanderFocusLossWatcher; -class CommanderWebView; -class Profile; - -namespace views { -class WidgetDelegate; -class Widget; -} // namespace views - -namespace commander { -class CommanderBackend; -struct CommanderViewModel; -} // namespace commander - -// Views implementation of commander::CommanderFrontend. The actual UI is WebUI; -// this class is responsible for setting up the infrastructure to host the -// WebUI in its own widget and mediating between the WebUI implementation and -// the controller. -class CommanderFrontendViews : public commander::CommanderFrontend, - public CommanderHandler::Delegate, - public BrowserListObserver, - public views::WidgetObserver { - public: - explicit CommanderFrontendViews(commander::CommanderBackend* backend); - ~CommanderFrontendViews() override; - - // commander::CommanderFrontend overrides - void ToggleForBrowser(Browser* browser) override; - void Show(Browser* browser) override; - void Hide() override; - - // CommanderHandler::Delegate overrides - void OnTextChanged(const std::u16string& text) override; - void OnOptionSelected(size_t option_index, int result_set_id) override; - void OnCompositeCommandCancelled() override; - void OnDismiss() override; - void OnHeightChanged(int new_height) override; - void OnHandlerEnabled(bool is_enabled) override; - - // BrowserListObserver overrides - void OnBrowserClosing(Browser* browser) override; - - // views::WidgetObserver overrides - void OnWidgetBoundsChanged(views::Widget* widget, - const gfx::Rect& new_bounds) override; - - private: - // Receives view model updates from |backend_|. - void OnViewModelUpdated(commander::CommanderViewModel view_model); - - // Creates a WebView to host the WebUI interface for |profile|. - std::unique_ptr<CommanderWebView> CreateWebView(Profile* profile); - - bool is_showing() { return widget_ != nullptr; } - - void OnAppTerminating(); - - // The controller. Must outlive this object. - raw_ptr<commander::CommanderBackend> backend_; - // The widget that contains |web_view_| - raw_ptr<views::Widget> widget_ = nullptr; - // |widget_|'s delegate - std::unique_ptr<views::WidgetDelegate> widget_delegate_; - // The WebView that hosts the WebUI instance. Populated when the view - // is showing and null otherwise. - raw_ptr<CommanderWebView> web_view_ = nullptr; - // The browser |widget_| is attached to. - raw_ptr<Browser> browser_ = nullptr; - // Whether the web UI interface is loaded and ready to accept view models. - bool is_handler_enabled_ = false; - // Sbuscription for observing app termination. - base::CallbackListSubscription subscription_; - // Helper to close the commander widget on deactivation. - std::unique_ptr<CommanderFocusLossWatcher> focus_loss_watcher_; - - base::WeakPtrFactory<CommanderFrontendViews> weak_ptr_factory_{this}; -}; - -#endif // CHROME_BROWSER_UI_VIEWS_COMMANDER_FRONTEND_VIEWS_H_
diff --git a/chrome/browser/ui/views/commander_frontend_views_browsertest.cc b/chrome/browser/ui/views/commander_frontend_views_browsertest.cc deleted file mode 100644 index 3f63a69..0000000 --- a/chrome/browser/ui/views/commander_frontend_views_browsertest.cc +++ /dev/null
@@ -1,281 +0,0 @@ -// Copyright 2020 The Chromium Authors -// 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/commander_frontend_views.h" - -#include <tuple> - -#include "base/memory/raw_ptr.h" -#include "chrome/browser/ui/commander/commander_backend.h" -#include "chrome/browser/ui/commander/commander_view_model.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "content/public/test/browser_test.h" -#include "ui/views/test/widget_test.h" -#include "ui/views/widget/any_widget_observer.h" -#include "ui/views/widget/widget.h" - -class CommanderFrontendViewsTest : public InProcessBrowserTest { - public: - // TODO(lgrey): This is copied over from CommanderControllerUnittest, with - // modifications. If we need it one more time, extract to a common file. - class TestBackend : public commander::CommanderBackend { - public: - void OnTextChanged(const std::u16string& text, Browser* browser) override { - text_changed_invocations_.push_back(text); - } - void OnCommandSelected(size_t command_index, int result_set_id) override { - command_selected_invocations_.push_back(command_index); - } - void OnCompositeCommandCancelled() override { - composite_command_cancelled_invocation_count_++; - } - void SetUpdateCallback(commander::CommanderBackend::ViewModelUpdateCallback - callback) override { - callback_ = std::move(callback); - } - void Reset() override { reset_invocation_count_++; } - - void CallCallback() { - commander::CommanderViewModel vm; - CallCallback(vm); - } - - void CallCallback(commander::CommanderViewModel vm) { callback_.Run(vm); } - - const std::vector<std::u16string> text_changed_invocations() { - return text_changed_invocations_; - } - const std::vector<size_t> command_selected_invocations() { - return command_selected_invocations_; - } - - int composite_command_cancelled_invocation_count() { - return composite_command_cancelled_invocation_count_; - } - int reset_invocation_count() { return reset_invocation_count_; } - - private: - commander::CommanderBackend::ViewModelUpdateCallback callback_; - std::vector<std::u16string> text_changed_invocations_; - std::vector<size_t> command_selected_invocations_; - int composite_command_cancelled_invocation_count_ = 0; - int reset_invocation_count_ = 0; - }; - - protected: - views::Widget* WaitForCommanderWidgetAttachedTo(Browser* browser) { - if (IsWidgetAttachedToBrowser(browser)) { - expected_browser_ = nullptr; - return active_widget_; - } - expected_browser_ = browser; - - run_loop_ = std::make_unique<base::RunLoop>(); - run_loop_->Run(); - EXPECT_TRUE(IsWidgetAttachedToBrowser(browser)); - return active_widget_; - } - void WaitForCommanderWidgetToClose() { - if (!active_widget_) - return; - run_loop_ = std::make_unique<base::RunLoop>(); - run_loop_->Run(); - EXPECT_TRUE(!active_widget_); - } - std::unique_ptr<TestBackend> backend_; - - private: - void SetUpOnMainThread() override { - backend_ = std::make_unique<TestBackend>(); - observer_ = std::make_unique<views::AnyWidgetObserver>( - views::test::AnyWidgetTestPasskey()); - // Unretained is safe since we own observer. - observer_->set_shown_callback(base::BindRepeating( - &CommanderFrontendViewsTest::OnWidgetShown, base::Unretained(this))); - observer_->set_closing_callback(base::BindRepeating( - &CommanderFrontendViewsTest::OnWidgetClosed, base::Unretained(this))); - } - - void TearDownOnMainThread() override { - observer_.reset(); - run_loop_.reset(); - backend_.reset(); - } - - void OnWidgetShown(views::Widget* widget) { - if (widget->GetName() == "Quick Commands") { - active_widget_ = widget; - if (IsWidgetAttachedToBrowser(expected_browser_)) { - expected_browser_ = nullptr; - if (run_loop_) - run_loop_->Quit(); - } - } - } - - void OnWidgetClosed(views::Widget* widget) { - if (widget == active_widget_) { - active_widget_ = nullptr; - if (run_loop_) - run_loop_->Quit(); - } - } - - bool IsWidgetAttachedToBrowser(const Browser* browser) { - if (!active_widget_ || !browser) - return false; - views::Widget* browser_widget = - BrowserView::GetBrowserViewForBrowser(browser)->GetWidget(); - return active_widget_->parent() == browser_widget; - } - - std::unique_ptr<views::AnyWidgetObserver> observer_; - raw_ptr<views::Widget> active_widget_ = nullptr; - raw_ptr<Browser> expected_browser_ = nullptr; - std::unique_ptr<base::RunLoop> run_loop_; -}; - -IN_PROC_BROWSER_TEST_F(CommanderFrontendViewsTest, ShowShowsWidget) { - auto frontend = std::make_unique<CommanderFrontendViews>(backend_.get()); - - frontend->Show(browser()); - EXPECT_TRUE(WaitForCommanderWidgetAttachedTo(browser())); - frontend->Hide(); -} - -IN_PROC_BROWSER_TEST_F(CommanderFrontendViewsTest, HideHidesWidget) { - auto frontend = std::make_unique<CommanderFrontendViews>(backend_.get()); - - frontend->Show(browser()); - EXPECT_TRUE(WaitForCommanderWidgetAttachedTo(browser())); - EXPECT_EQ(backend_->reset_invocation_count(), 0); - - frontend->Hide(); - WaitForCommanderWidgetToClose(); - EXPECT_EQ(backend_->reset_invocation_count(), 1); -} - -IN_PROC_BROWSER_TEST_F(CommanderFrontendViewsTest, DismissHidesWidget) { - auto frontend = std::make_unique<CommanderFrontendViews>(backend_.get()); - - frontend->Show(browser()); - EXPECT_TRUE(WaitForCommanderWidgetAttachedTo(browser())); - EXPECT_EQ(backend_->reset_invocation_count(), 0); - - frontend->OnDismiss(); - WaitForCommanderWidgetToClose(); - EXPECT_EQ(backend_->reset_invocation_count(), 1); -} - -IN_PROC_BROWSER_TEST_F(CommanderFrontendViewsTest, ViewModelCloseHidesWidget) { - auto frontend = std::make_unique<CommanderFrontendViews>(backend_.get()); - - frontend->Show(browser()); - EXPECT_TRUE(WaitForCommanderWidgetAttachedTo(browser())); - EXPECT_EQ(backend_->reset_invocation_count(), 0); - - commander::CommanderViewModel vm; - vm.action = commander::CommanderViewModel::Action::kClose; - backend_->CallCallback(vm); - WaitForCommanderWidgetToClose(); - EXPECT_EQ(backend_->reset_invocation_count(), 1); -} - -IN_PROC_BROWSER_TEST_F(CommanderFrontendViewsTest, ToggleShowsWidget) { - auto frontend = std::make_unique<CommanderFrontendViews>(backend_.get()); - - frontend->ToggleForBrowser(browser()); - EXPECT_TRUE(WaitForCommanderWidgetAttachedTo(browser())); - - frontend->Hide(); -} - -IN_PROC_BROWSER_TEST_F(CommanderFrontendViewsTest, ToggleHidesWidget) { - auto frontend = std::make_unique<CommanderFrontendViews>(backend_.get()); - - frontend->Show(browser()); - EXPECT_TRUE(WaitForCommanderWidgetAttachedTo(browser())); - - frontend->ToggleForBrowser(browser()); - WaitForCommanderWidgetToClose(); - EXPECT_EQ(backend_->reset_invocation_count(), 1); -} - -// Ensure that calling toggle twice in a row does the right thing. -IN_PROC_BROWSER_TEST_F(CommanderFrontendViewsTest, ToggleTogglesWidget) { - auto frontend = std::make_unique<CommanderFrontendViews>(backend_.get()); - - frontend->ToggleForBrowser(browser()); - EXPECT_TRUE(WaitForCommanderWidgetAttachedTo(browser())); - - frontend->ToggleForBrowser(browser()); - WaitForCommanderWidgetToClose(); - EXPECT_EQ(backend_->reset_invocation_count(), 1); -} - -IN_PROC_BROWSER_TEST_F(CommanderFrontendViewsTest, OnHeightChangedSizesWidget) { - auto frontend = std::make_unique<CommanderFrontendViews>(backend_.get()); - - frontend->Show(browser()); - views::Widget* commander_widget = WaitForCommanderWidgetAttachedTo(browser()); - - int old_height = commander_widget->GetRootView()->height(); - int new_height = 200; - // Ensure changing height isn't a no-op. - EXPECT_NE(old_height, new_height); - - frontend->OnHeightChanged(200); - EXPECT_EQ(new_height, commander_widget->GetRootView()->height()); - frontend->Hide(); -} - -IN_PROC_BROWSER_TEST_F(CommanderFrontendViewsTest, PassesOnOptionSelected) { - auto frontend = std::make_unique<CommanderFrontendViews>(backend_.get()); - - frontend->Show(browser()); - std::ignore = WaitForCommanderWidgetAttachedTo(browser()); - - frontend->OnOptionSelected(8, 13); - ASSERT_EQ(backend_->command_selected_invocations().size(), 1u); - EXPECT_EQ(backend_->command_selected_invocations().back(), 8u); - frontend->Hide(); -} - -IN_PROC_BROWSER_TEST_F(CommanderFrontendViewsTest, PassesOnTextChanged) { - auto frontend = std::make_unique<CommanderFrontendViews>(backend_.get()); - frontend->Show(browser()); - std::ignore = WaitForCommanderWidgetAttachedTo(browser()); - - const std::u16string input = u"orange"; - frontend->OnTextChanged(input); - ASSERT_EQ(backend_->text_changed_invocations().size(), 1u); - EXPECT_EQ(backend_->text_changed_invocations().back(), input); - frontend->Hide(); -} - -IN_PROC_BROWSER_TEST_F(CommanderFrontendViewsTest, - PassesOnCompositeCommandCancelled) { - auto frontend = std::make_unique<CommanderFrontendViews>(backend_.get()); - frontend->Show(browser()); - std::ignore = WaitForCommanderWidgetAttachedTo(browser()); - - EXPECT_EQ(backend_->composite_command_cancelled_invocation_count(), 0); - frontend->OnCompositeCommandCancelled(); - EXPECT_EQ(backend_->composite_command_cancelled_invocation_count(), 1); - frontend->Hide(); -} -IN_PROC_BROWSER_TEST_F(CommanderFrontendViewsTest, HidesOnFocusLoss) { - auto frontend = std::make_unique<CommanderFrontendViews>(backend_.get()); - - frontend->Show(browser()); - views::Widget* widget = WaitForCommanderWidgetAttachedTo(browser()); - EXPECT_TRUE(widget); - EXPECT_EQ(backend_->reset_invocation_count(), 0); - - // Activate the main browser window. - widget->parent()->Activate(); - WaitForCommanderWidgetToClose(); - EXPECT_EQ(backend_->reset_invocation_count(), 1); -}
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 56dfdb0..7745b85 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -187,6 +187,7 @@ #include "chromeos/components/mgs/managed_guest_session_utils.h" #include "components/autofill/core/common/autofill_payments_features.h" #include "components/content_settings/core/common/features.h" +#include "components/enterprise/buildflags/buildflags.h" #include "components/feature_engagement/public/event_constants.h" #include "components/feature_engagement/public/feature_constants.h" #include "components/feature_engagement/public/tracker.h" @@ -335,6 +336,10 @@ #include "chrome/browser/ui/views/frame/webui_tab_strip_container_view.h" #endif // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) +#if BUILDFLAG(ENTERPRISE_WATERMARK) +#include "chrome/browser/enterprise/watermark/watermark_view.h" +#endif // BUILDFLAG(ENTERPRISE_WATERMARK) + using base::UserMetricsAction; using content::NativeWebKeyboardEvent; using content::WebContents; @@ -917,8 +922,19 @@ contents_web_view_ = contents_container->AddChildView(std::move(contents_web_view)); contents_web_view_->set_is_primary_web_contents_for_window(true); + + views::View* watermark_view = nullptr; + +#if BUILDFLAG(ENTERPRISE_WATERMARK) + if (base::FeatureList::IsEnabled(features::kEnableWatermarkView)) { + watermark_view = contents_container->AddChildView( + std::make_unique<enterprise_watermark::WatermarkView>( + "Private! Confidential!")); + } +#endif // BUILDFLAG(ENTERPRISE_WATERMARK) + contents_container->SetLayoutManager(std::make_unique<ContentsLayoutManager>( - devtools_web_view_, contents_web_view_)); + devtools_web_view_, contents_web_view_, watermark_view)); toolbar_ = top_container_->AddChildView( std::make_unique<ToolbarView>(browser_.get(), this)); @@ -3633,9 +3649,7 @@ const uint64_t memory_used = tab_data.tab_resource_usage->memory_usage_in_bytes(); const bool is_high_memory_usage = - memory_used > static_cast<uint64_t>( - performance_manager::features:: - kMemoryUsageInHovercardsHighThresholdBytes.Get()); + tab_data.tab_resource_usage->is_high_memory_usage(); if (is_high_memory_usage || is_for_tab) { const int message_id = is_high_memory_usage ? IDS_TAB_AX_HIGH_MEMORY_USAGE : IDS_TAB_AX_MEMORY_USAGE;
diff --git a/chrome/browser/ui/views/frame/browser_view_unittest.cc b/chrome/browser/ui/views/frame/browser_view_unittest.cc index 3731391..47ddcbab 100644 --- a/chrome/browser/ui/views/frame/browser_view_unittest.cc +++ b/chrome/browser/ui/views/frame/browser_view_unittest.cc
@@ -478,7 +478,7 @@ TEST_P(BrowserViewTest, WindowTitleOmitsLowMemoryUsage) { scoped_refptr<TabResourceUsage> tab_resource_usage_ = base::MakeRefCounted<TabResourceUsage>(); - tab_resource_usage_->set_memory_usage_in_bytes(100); + tab_resource_usage_->SetMemoryUsageInBytes(100); TabRendererData memory_usage; memory_usage.tab_resource_usage = tab_resource_usage_; @@ -495,7 +495,7 @@ performance_manager::features:: kMemoryUsageInHovercardsHighThresholdBytes.Get()) + 1; - tab_resource_usage_->set_memory_usage_in_bytes(memory_used); + tab_resource_usage_->SetMemoryUsageInBytes(memory_used); // Expect that high memory usage is in the window title. EXPECT_TRUE(browser_view()->GetAccessibleWindowTitle().find(
diff --git a/chrome/browser/ui/views/frame/contents_layout_manager.cc b/chrome/browser/ui/views/frame/contents_layout_manager.cc index a5b75aa..196c80d 100644 --- a/chrome/browser/ui/views/frame/contents_layout_manager.cc +++ b/chrome/browser/ui/views/frame/contents_layout_manager.cc
@@ -7,13 +7,13 @@ #include "ui/views/view.h" ContentsLayoutManager::ContentsLayoutManager(views::View* devtools_view, - views::View* contents_view) + views::View* contents_view, + views::View* watermark_view) : devtools_view_(devtools_view), contents_view_(contents_view), - host_(nullptr) {} + watermark_view_(watermark_view) {} -ContentsLayoutManager::~ContentsLayoutManager() { -} +ContentsLayoutManager::~ContentsLayoutManager() = default; void ContentsLayoutManager::SetContentsResizingStrategy( const DevToolsContentsResizingStrategy& strategy) { @@ -42,6 +42,11 @@ // layout here. devtools_view_->SetBoundsRect(host_->GetMirroredRect(new_devtools_bounds)); contents_view_->SetBoundsRect(host_->GetMirroredRect(new_contents_bounds)); + + // Enterprise watermark view is always overlaid, even when empty. + if (watermark_view_) { + watermark_view_->SetBoundsRect(gfx::Rect(0, 0, width, height)); + } } gfx::Size ContentsLayoutManager::GetPreferredSize(
diff --git a/chrome/browser/ui/views/frame/contents_layout_manager.h b/chrome/browser/ui/views/frame/contents_layout_manager.h index 052dbe87..6236107 100644 --- a/chrome/browser/ui/views/frame/contents_layout_manager.h +++ b/chrome/browser/ui/views/frame/contents_layout_manager.h
@@ -12,7 +12,9 @@ // ContentsLayoutManager positions the WebContents and devtools WebContents. class ContentsLayoutManager : public views::LayoutManager { public: - ContentsLayoutManager(views::View* devtools_view, views::View* contents_view); + ContentsLayoutManager(views::View* devtools_view, + views::View* contents_view, + views::View* watermark_view = nullptr); ContentsLayoutManager(const ContentsLayoutManager&) = delete; ContentsLayoutManager& operator=(const ContentsLayoutManager&) = delete; @@ -31,8 +33,9 @@ private: raw_ptr<views::View> devtools_view_; raw_ptr<views::View> contents_view_; + raw_ptr<views::View> watermark_view_; - raw_ptr<views::View> host_; + raw_ptr<views::View> host_ = nullptr; DevToolsContentsResizingStrategy strategy_; };
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller.h b/chrome/browser/ui/views/frame/immersive_mode_controller.h index 204c25d..6331925 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller.h +++ b/chrome/browser/ui/views/frame/immersive_mode_controller.h
@@ -54,6 +54,9 @@ // Called when the immersive mode controller has been destroyed. virtual void OnImmersiveModeControllerDestroyed() {} + // Called when immersive mode is entered. + virtual void OnImmersiveFullscreenEntered() {} + // Called when immersive mode is exited. virtual void OnImmersiveFullscreenExited() {}
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc index 4c15ebc..2783b4d 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc
@@ -200,7 +200,11 @@ observer.OnImmersiveRevealEnded(); } -void ImmersiveModeControllerChromeos::OnImmersiveFullscreenEntered() {} +void ImmersiveModeControllerChromeos::OnImmersiveFullscreenEntered() { + for (Observer& observer : observers_) { + observer.OnImmersiveFullscreenEntered(); + } +} void ImmersiveModeControllerChromeos::OnImmersiveFullscreenExited() { browser_view_->contents_web_view()->holder()->SetHitTestTopInset(0);
diff --git a/chrome/browser/ui/views/frame/immersive_mode_tester.cc b/chrome/browser/ui/views/frame/immersive_mode_tester.cc index 17c7447..230c61a 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_tester.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_tester.cc
@@ -34,12 +34,23 @@ EXPECT_EQ(expected_index, browser_->tab_strip_model()->active_index()); } +void ImmersiveModeTester::WaitForFullscreenToEnter() { + if (!GetBrowserView()->immersive_mode_controller()->IsEnabled() || + !GetBrowserView()->IsFullscreen()) { + fullscreen_entering_loop_ = std::make_unique<base::RunLoop>(); + fullscreen_entering_loop_->Run(); + } + ASSERT_TRUE(GetBrowserView()->immersive_mode_controller()->IsEnabled()); + ASSERT_TRUE(GetBrowserView()->IsFullscreen()); +} + void ImmersiveModeTester::WaitForFullscreenToExit() { if (GetBrowserView()->immersive_mode_controller()->IsEnabled()) { - fullscreen_loop_ = std::make_unique<base::RunLoop>(); - fullscreen_loop_->Run(); + fullscreen_exiting_loop_ = std::make_unique<base::RunLoop>(); + fullscreen_exiting_loop_->Run(); } ASSERT_FALSE(GetBrowserView()->immersive_mode_controller()->IsEnabled()); + ASSERT_FALSE(GetBrowserView()->IsFullscreen()); } void ImmersiveModeTester::OnImmersiveRevealStarted() { @@ -64,7 +75,14 @@ scoped_observation_.Reset(); } +void ImmersiveModeTester::OnImmersiveFullscreenEntered() { + if (fullscreen_entering_loop_) { + fullscreen_entering_loop_->Quit(); + } +} + void ImmersiveModeTester::OnImmersiveFullscreenExited() { - if (fullscreen_loop_ && fullscreen_loop_->running()) - fullscreen_loop_->Quit(); + if (fullscreen_exiting_loop_) { + fullscreen_exiting_loop_->Quit(); + } }
diff --git a/chrome/browser/ui/views/frame/immersive_mode_tester.h b/chrome/browser/ui/views/frame/immersive_mode_tester.h index 7c11e7d4..439722a 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_tester.h +++ b/chrome/browser/ui/views/frame/immersive_mode_tester.h
@@ -76,6 +76,10 @@ // Verifies a reveal has happened and the expected tab is active. void VerifyTabIndexAfterReveal(int expected_index); + // Waits for the immersive fullscreen to start (or returns immediately if + // immersive fullscreen already started). + void WaitForFullscreenToEnter(); + // Waits for the immersive fullscreen to end (or returns immediately if // immersive fullscreen already ended). void WaitForFullscreenToExit(); @@ -84,6 +88,7 @@ void OnImmersiveRevealStarted() override; void OnImmersiveRevealEnded() override; void OnImmersiveModeControllerDestroyed() override; + void OnImmersiveFullscreenEntered() override; void OnImmersiveFullscreenExited() override; private: @@ -94,7 +99,8 @@ bool reveal_started_ = false; bool reveal_ended_ = false; std::unique_ptr<base::RunLoop> reveal_loop_; - std::unique_ptr<base::RunLoop> fullscreen_loop_; + std::unique_ptr<base::RunLoop> fullscreen_entering_loop_; + std::unique_ptr<base::RunLoop> fullscreen_exiting_loop_; }; #endif // CHROME_BROWSER_UI_VIEWS_FRAME_IMMERSIVE_MODE_TESTER_H_
diff --git a/chrome/browser/ui/views/frame/tab_strip_region_view_unittest.cc b/chrome/browser/ui/views/frame/tab_strip_region_view_unittest.cc index 98a471f..99a1118 100644 --- a/chrome/browser/ui/views/frame/tab_strip_region_view_unittest.cc +++ b/chrome/browser/ui/views/frame/tab_strip_region_view_unittest.cc
@@ -103,6 +103,10 @@ }; TEST_P(TabStripRegionViewTest, GrabHandleSpaceStaysVisible) { + // TODO (crbug/1520595): Skip for now due to test failing when CR2023 enabled. + if (features::IsChromeRefresh2023()) { + GTEST_SKIP(); + } const int kTabStripRegionViewWidth = 500; tab_strip_region_view_->SetBounds(0, 0, kTabStripRegionViewWidth, 20); @@ -118,6 +122,10 @@ } TEST_P(TabStripRegionViewTest, NewTabButtonStaysVisible) { + // TODO (crbug/1520595): Skip for now due to test failing when CR2023 enabled. + if (features::IsChromeRefresh2023()) { + GTEST_SKIP(); + } const int kTabStripRegionViewWidth = 500; tab_strip_region_view_->SetBounds(0, 0, kTabStripRegionViewWidth, 20); @@ -147,6 +155,10 @@ } TEST_P(TabStripRegionViewTest, NewTabButtonInkDrop) { + // TODO (crbug/1523257): Skip for now due to test failing when CR2023 enabled. + if (features::IsChromeRefresh2023()) { + GTEST_SKIP(); + } constexpr int kTabStripRegionViewWidth = 500; tab_strip_region_view_->SetBounds(0, 0, kTabStripRegionViewWidth, GetLayoutConstant(TAB_STRIP_HEIGHT));
diff --git a/chrome/browser/ui/views/media_router/cast_toolbar_button_unittest.cc b/chrome/browser/ui/views/media_router/cast_toolbar_button_unittest.cc index d0f7b20b..3387be2 100644 --- a/chrome/browser/ui/views/media_router/cast_toolbar_button_unittest.cc +++ b/chrome/browser/ui/views/media_router/cast_toolbar_button_unittest.cc
@@ -114,21 +114,12 @@ browser_.get(), media_router_, std::move(context_menu))); const ui::ColorProvider* color_provider = button_->GetColorProvider(); - idle_icon_ = gfx::Image(gfx::CreateVectorIcon( - vector_icons::kMediaRouterIdleIcon, - color_provider->GetColor(kColorToolbarButtonIcon))); idle_chrome_refresh_icon_ = gfx::Image(gfx::CreateVectorIcon( vector_icons::kMediaRouterIdleChromeRefreshIcon, color_provider->GetColor(kColorToolbarButtonIcon))); - warning_icon_ = gfx::Image(gfx::CreateVectorIcon( - vector_icons::kMediaRouterWarningIcon, - color_provider->GetColor(kColorMediaRouterIconWarning))); warning_chrome_refresh_icon_ = gfx::Image(gfx::CreateVectorIcon( vector_icons::kMediaRouterWarningChromeRefreshIcon, color_provider->GetColor(kColorToolbarButtonIcon))); - active_icon_ = gfx::Image(gfx::CreateVectorIcon( - vector_icons::kMediaRouterActiveIcon, - color_provider->GetColor(kColorMediaRouterIconActive))); active_chrome_refresh_icon_ = gfx::Image(gfx::CreateVectorIcon( vector_icons::kMediaRouterActiveChromeRefreshIcon, color_provider->GetColor(kColorMediaRouterIconActive))); @@ -161,11 +152,8 @@ raw_ptr<MockMediaRouter, DanglingUntriaged> media_router_ = nullptr; std::unique_ptr<MirroringMediaControllerHostImpl> mirroring_controller_host_; - gfx::Image idle_icon_; gfx::Image idle_chrome_refresh_icon_; - gfx::Image warning_icon_; gfx::Image warning_chrome_refresh_icon_; - gfx::Image active_icon_; gfx::Image active_chrome_refresh_icon_; gfx::Image paused_icon_; @@ -183,22 +171,6 @@ EXPECT_FALSE(button_->GetVisible()); } -TEST_F(CastToolbarButtonTest, UpdateIssues) { - button_->UpdateIcon(); - EXPECT_TRUE(gfx::test::AreImagesEqual(idle_icon_, GetIcon())); - - button_->OnIssue(Issue(IssueInfo( - "title notification", IssueInfo::Severity::NOTIFICATION, "sinkId1"))); - EXPECT_TRUE(gfx::test::AreImagesEqual(idle_icon_, GetIcon())); - - button_->OnIssue(Issue( - IssueInfo("title warning", IssueInfo::Severity::WARNING, "sinkId1"))); - EXPECT_TRUE(gfx::test::AreImagesEqual(warning_icon_, GetIcon())); - - button_->OnIssuesCleared(); - EXPECT_TRUE(gfx::test::AreImagesEqual(idle_icon_, GetIcon())); -} - TEST_F(CastToolbarButtonTest, UpdateIssuesChromeResfresh) { // Enable the proper features / prefs. base::test::ScopedFeatureList scoped_feature_list; @@ -220,22 +192,6 @@ EXPECT_TRUE(gfx::test::AreImagesEqual(idle_chrome_refresh_icon_, GetIcon())); } -TEST_F(CastToolbarButtonTest, UpdateRoutes) { - button_->UpdateIcon(); - EXPECT_TRUE(gfx::test::AreImagesEqual(idle_icon_, GetIcon())); - - button_->OnRoutesUpdated(local_display_route_list_); - EXPECT_TRUE(gfx::test::AreImagesEqual(active_icon_, GetIcon())); - - // The idle icon should be shown when we only have non-local and/or - // non-display routes. - button_->OnRoutesUpdated(non_local_display_route_list_); - EXPECT_TRUE(gfx::test::AreImagesEqual(idle_icon_, GetIcon())); - - button_->OnRoutesUpdated({}); - EXPECT_TRUE(gfx::test::AreImagesEqual(idle_icon_, GetIcon())); -} - TEST_F(CastToolbarButtonTest, UpdateRoutesChromeRefresh) { // Enable the proper features / prefs. base::test::ScopedFeatureList scoped_feature_list;
diff --git a/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc b/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc index 88ed7d5..120d32c 100644 --- a/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc +++ b/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc
@@ -15,6 +15,7 @@ #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/base/ozone_buildflags.h" #include "ui/compositor/layer_tree_owner.h" #include "ui/gfx/native_widget_types.h" #include "ui/views/controls/menu/menu_controller.h" @@ -511,7 +512,8 @@ // implemented in menu code) will consult the delegate before closing the view // after the drag. // TODO(pkasting): https://crbug.com/939621 Fails on Mac. -#if BUILDFLAG(IS_MAC) +// TODO(crbug/1523611): Test is failing under ChromeRefresh2023 on wayland. +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_OZONE_WAYLAND) #define MAYBE_MenuViewDragAndDropNestedDrag \ DISABLED_MenuViewDragAndDropNestedDrag #else
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_dialog_browsertest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_dialog_browsertest.cc index fcfeff0..3aca0110 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view_dialog_browsertest.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_dialog_browsertest.cc
@@ -467,8 +467,8 @@ // set. All permissions will show regardless of its factory default value. IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewDialogBrowserTest, InvokeUi_AllowAllPermissions) { - // Last updated in crrev.com/c/5053508. - set_baseline("5053508"); + // Last updated in crrev.com/c/5237718. + set_baseline("5237718"); ShowAndVerifyUi(); } @@ -476,8 +476,8 @@ // set. All permissions will show regardless of its factory default value. IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewDialogBrowserTest, InvokeUi_BlockAllPermissions) { - // Last updated in crrev.com/c/5053508. - set_baseline("5053508"); + // Last updated in crrev.com/c/5237718. + set_baseline("5237718"); ShowAndVerifyUi(); }
diff --git a/chrome/browser/ui/views/profiles/incognito_menu_view.cc b/chrome/browser/ui/views/profiles/incognito_menu_view.cc index 3e46e2ce..f67f417 100644 --- a/chrome/browser/ui/views/profiles/incognito_menu_view.cc +++ b/chrome/browser/ui/views/profiles/incognito_menu_view.cc
@@ -62,7 +62,7 @@ ? l10n_util::GetPluralStringFUTF16(IDS_INCOGNITO_WINDOW_COUNT_MESSAGE, incognito_window_count) : std::u16string(), - header_art_icon); + std::u16string(), header_art_icon); AddFeatureButton( l10n_util::GetStringUTF16(IDS_INCOGNITO_PROFILE_MENU_CLOSE_BUTTON_NEW),
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.cc b/chrome/browser/ui/views/profiles/profile_menu_view.cc index 7c719d6..6a5b156a 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view.cc +++ b/chrome/browser/ui/views/profiles/profile_menu_view.cc
@@ -41,6 +41,7 @@ #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/browser/ui/color/chrome_color_id.h" +#include "chrome/browser/ui/managed_ui.h" #include "chrome/browser/ui/passwords/ui_utils.h" #include "chrome/browser/ui/profiles/profile_colors_util.h" #include "chrome/browser/ui/profiles/profile_picker.h" @@ -513,10 +514,16 @@ IsSyncPaused(profile) ? l10n_util::GetStringUTF16(IDS_PROFILES_LOCAL_PROFILE_STATE) : base::UTF8ToUTF16(account_info.email); + auto account_manager = chrome::GetAccountManagerIdentity(profile); + management_label_ = + account_manager + ? l10n_util::GetStringFUTF16(IDS_PROFILES_MANAGED_BY, + base::UTF8ToUTF16(*account_manager)) + : std::u16string(); SetProfileIdentityInfo( profile_name, background_color, edit_button_params, ui::ImageModel::FromImage(account_info.account_image), menu_title_, - menu_subtitle_); + menu_subtitle_, management_label_); } else { if (switches::IsExplicitBrowserSigninUIOnDesktopEnabled( switches::ExplicitBrowserSigninPhase::kExperimental) && @@ -527,6 +534,7 @@ menu_title_ = l10n_util::GetStringUTF16(IDS_PROFILES_LOCAL_PROFILE_STATE); // The email may be empty. menu_subtitle_ = base::UTF8ToUTF16(account_info.email); + management_label_ = std::u16string(); SetProfileIdentityInfo( profile_name, background_color, edit_button_params, ui::ImageModel::FromImage( @@ -538,7 +546,7 @@ !account_info.IsEmpty() ? account_info.account_image : profile_attributes->GetAvatarIcon(kIdentityImageSize)), - menu_title_, menu_subtitle_); + menu_title_, menu_subtitle_, management_label_); } } @@ -547,6 +555,7 @@ menu_title_ = l10n_util::GetStringUTF16(IDS_GUEST_PROFILE_NAME); menu_subtitle_ = std::u16string(); + management_label_ = std::u16string(); if (guest_window_count > 1) { menu_subtitle_ = l10n_util::GetPluralStringFUTF16( IDS_GUEST_WINDOW_COUNT_MESSAGE, guest_window_count); @@ -558,7 +567,7 @@ /*profile_name=*/std::u16string(), /*background_color=*/SK_ColorTRANSPARENT, /*edit_button=*/std::nullopt, profiles::GetGuestAvatar(), menu_title_, - menu_subtitle_, header_art_icon); + menu_subtitle_, management_label_, header_art_icon); } void ProfileMenuView::BuildAutofillButtons() {
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.h b/chrome/browser/ui/views/profiles/profile_menu_view.h index 4ee6a4b..17a0008 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view.h +++ b/chrome/browser/ui/views/profiles/profile_menu_view.h
@@ -96,6 +96,7 @@ std::u16string menu_title_; std::u16string menu_subtitle_; + std::u16string management_label_; #if !BUILDFLAG(IS_CHROMEOS) // A profile switcher object needed if the user triggers opening other
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc index 1ea1910a..e1d7cbf 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc +++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -479,7 +479,8 @@ void BuildProfileTitleAndSubtitle(views::View* parent, const std::u16string& title, - const std::u16string& subtitle) { + const std::u16string& subtitle, + const std::u16string& management_label) { views::View* profile_titles_container = parent->AddChildView(std::make_unique<views::View>()); // Separate the titles from the avatar image by the default margin. @@ -504,6 +505,14 @@ features::IsChromeRefresh2023() ? views::style::STYLE_BODY_3 : views::style::STYLE_SECONDARY)); } + + if (base::FeatureList::IsEnabled(features::kEnterpriseProfileBadging) && + !management_label.empty()) { + profile_titles_container->AddChildView(std::make_unique<views::Label>( + management_label, views::style::CONTEXT_LABEL, + features::IsChromeRefresh2023() ? views::style::STYLE_BODY_5 + : views::style::STYLE_SECONDARY)); + } } } // namespace @@ -657,6 +666,7 @@ const ui::ImageModel& image_model, const std::u16string& title, const std::u16string& subtitle, + const std::u16string& management_label, const ui::ThemedVectorIcon& avatar_header_art) { constexpr int kBottomMargin = kDefaultMargin; @@ -732,7 +742,7 @@ std::move(heading_label), profile_background_color, std::move(avatar_image_view), std::move(edit_button), avatar_header_art); BuildProfileTitleAndSubtitle(/*parent=*/identity_info_container_, title, - subtitle); + subtitle, management_label); } void ProfileMenuViewBase::BuildSyncInfoWithCallToAction(
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.h b/chrome/browser/ui/views/profiles/profile_menu_view_base.h index 4112882..b0b73fd 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view_base.h +++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
@@ -113,6 +113,7 @@ const ui::ImageModel& image_model, const std::u16string& title, const std::u16string& subtitle = std::u16string(), + const std::u16string& management_label = std::u16string(), const ui::ThemedVectorIcon& avatar_header_art = ui::ThemedVectorIcon()); // Displays the sync info section as a rounded rectangle with text on top and // a button on the bottom. Clicking the button triggers |action|.
diff --git a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.cc b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.cc index 79f872c..ba1dbef0 100644 --- a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.cc +++ b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.cc
@@ -147,11 +147,13 @@ // comment of `QRImageGenerator::GenerateQRCode`). auto callback = base::BindOnce( &QRCodeGeneratorBubble::OnCodeGeneratorResponse, base::Unretained(this)); - if (qrcode_service_override_.is_null()) { - qrcode_service_->GenerateQRCode(std::move(request), std::move(callback)); - } else { - qrcode_service_override_.Run(std::move(request), std::move(callback)); + if (qrcode_error_override_.has_value()) { + auto response = qrcode_generator::mojom::GenerateQRCodeResponse::New(); + response->error_code = qrcode_error_override_.value(); + std::move(callback).Run(std::move(response)); + return; } + qrcode_service_->GenerateQRCode(std::move(request), std::move(callback)); } void QRCodeGeneratorBubble::OnCodeGeneratorResponse( @@ -350,7 +352,7 @@ // End controls row // Initialize Service - if (!qrcode_service_ && qrcode_service_override_.is_null()) { + if (!qrcode_service_) { qrcode_service_ = std::make_unique<qrcode_generator::QRImageGenerator>(); } } @@ -431,11 +433,9 @@ return final_image; } -void QRCodeGeneratorBubble::SetQRCodeServiceForTesting( - base::RepeatingCallback<void(mojom::GenerateQRCodeRequestPtr request, - QRImageGenerator::ResponseCallback callback)> - qrcode_service_override) { - qrcode_service_override_ = std::move(qrcode_service_override); +void QRCodeGeneratorBubble::SetQRCodeErrorForTesting( + std::optional<qrcode_generator::mojom::QRCodeGeneratorError> error) { + qrcode_error_override_ = error; } const SkBitmap QRCodeGeneratorBubble::GetBitmap() {
diff --git a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.h b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.h index c862ea73..66e5770 100644 --- a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.h +++ b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_VIEWS_QRCODE_GENERATOR_QRCODE_GENERATOR_BUBBLE_H_ #include <memory> +#include <optional> #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" @@ -74,10 +75,8 @@ views::Label* error_label_for_testing() { return bottom_error_label_; } views::LabelButton* download_button_for_testing() { return download_button_; } - void SetQRCodeServiceForTesting( - base::RepeatingCallback<void(mojom::GenerateQRCodeRequestPtr request, - QRImageGenerator::ResponseCallback callback)> - qrcode_service_override); + void SetQRCodeErrorForTesting( + std::optional<qrcode_generator::mojom::QRCodeGeneratorError> error); private: // Updates and formats QR code, text, and controls. @@ -131,18 +130,10 @@ // `QRImageGenerator` class. std::unique_ptr<QRImageGenerator> qrcode_service_; - // Unit tests can set `qr_code_service_override_` to intercept QR code - // requests and inject test-controlled QR code responses. - // - // Rationale for using a `RepeatingCallback` instead of implementing - // dependency injection using virtual methods: 1) `GenerateQRCode` will become - // a free function after shipping https://crbug.com/1431991, 2) in general - // `RepeatingCallback` is equivalent to a pure interface with a single method, - // (note that `RepeatingCallback` below has the same signature as - // `GenerateQRCode`). - base::RepeatingCallback<void(mojom::GenerateQRCodeRequestPtr request, - QRImageGenerator::ResponseCallback callback)> - qrcode_service_override_; + // Unit tests can set `qr_code_error_override_` to inject QR code + // generation errors. + std::optional<qrcode_generator::mojom::QRCodeGeneratorError> + qrcode_error_override_; // URL for which the QR code is being generated. // Used for validation.
diff --git a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble_unittest.cc b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble_unittest.cc index 3c0cf390..cb2a6a7a 100644 --- a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble_unittest.cc +++ b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_bubble_unittest.cc
@@ -72,43 +72,9 @@ image.bitmap()->getColor(kQuietZoneDip, kQuietZoneDip)); } -// Test-fake implementation of QRImageGenerator; the real implementation -// can't be used in these tests because it requires spawning a service process. -class FakeQRCodeGeneratorService { +class VisibilityChangedWaiter : public views::ViewObserver { public: - FakeQRCodeGeneratorService() = default; - - using GenerateQRCodeCallback = - base::OnceCallback<void(mojom::GenerateQRCodeResponsePtr)>; - void GenerateQRCode(mojom::GenerateQRCodeRequestPtr request, - GenerateQRCodeCallback callback) { - pending_callback_ = std::move(callback); - if (run_loop_) - run_loop_->Quit(); - } - - void WaitForRequest() { - if (HasPendingRequest()) - return; - run_loop_ = std::make_unique<base::RunLoop>(); - run_loop_->Run(); - } - - bool HasPendingRequest() const { return bool(pending_callback_); } - - void DeliverResponse(mojom::GenerateQRCodeResponsePtr response) { - CHECK(pending_callback_); - std::move(pending_callback_).Run(std::move(response)); - } - - private: - GenerateQRCodeCallback pending_callback_; - std::unique_ptr<base::RunLoop> run_loop_; -}; - -class ViewVisibilityWaiter : public views::ViewObserver { - public: - explicit ViewVisibilityWaiter(views::View* view) { + explicit VisibilityChangedWaiter(views::View* view) { observation_.Observe(view); } @@ -139,14 +105,6 @@ anchor_view_, web_contents_->GetWeakPtr(), base::DoNothing(), base::DoNothing(), GURL("https://www.chromium.org/a")); - // `base::Unretained` is okay, because `TearDown` will run before - // destruction of `fake_service_` and will `reset` the `bubble_widget_` - // which will destroy the `bubble` which will destroy/drop the callback we - // are setting for testing below. - bubble->SetQRCodeServiceForTesting( - base::BindRepeating(&FakeQRCodeGeneratorService::GenerateQRCode, - base::Unretained(&fake_service_))); - bubble_ = bubble.get(); bubble_widget_.reset( views::BubbleDialogDelegateView::CreateBubble(std::move(bubble))); @@ -193,8 +151,6 @@ error_label()->GetViewAccessibility().IsIgnored(); } - FakeQRCodeGeneratorService* service() { return &fake_service_; } - private: content::RenderViewHostTestEnabler rvh_test_enabler_; TestingProfile profile_; @@ -202,10 +158,8 @@ WidgetAutoclosePtr anchor_widget_; raw_ptr<views::View> anchor_view_; - raw_ptr<QRCodeGeneratorBubble, DanglingUntriaged> bubble_; WidgetAutoclosePtr bubble_widget_; - - FakeQRCodeGeneratorService fake_service_; + raw_ptr<QRCodeGeneratorBubble> bubble_; }; // This test is a bit fiddly because mojo imposes asynchronicity on both sender @@ -215,78 +169,56 @@ // responses have been delivered TEST_F(QRCodeGeneratorBubbleUITest, ImageShowsAfterErrorState) { bubble()->Show(); - EXPECT_TRUE(ImageShowing()); - service()->WaitForRequest(); - ASSERT_TRUE(service()->HasPendingRequest()); - auto error_response = mojom::GenerateQRCodeResponse::New(); - error_response->error_code = mojom::QRCodeGeneratorError::UNKNOWN_ERROR; - - EXPECT_TRUE(ImageShowing()); - + // The UI regenerates the QR code when the user types new text, so synthesize + // that, but inject an error. { - ViewVisibilityWaiter waiter(image()); - service()->DeliverResponse(std::move(error_response)); + VisibilityChangedWaiter waiter(image()); + bubble()->SetQRCodeErrorForTesting( + mojom::QRCodeGeneratorError::UNKNOWN_ERROR); + textfield()->InsertOrReplaceText(u"https://www.chromium.org/b"); waiter.Wait(); - EXPECT_FALSE(ImageShowing()); } // The UI regenerates the QR code when the user types new text, so synthesize - // that. - textfield()->InsertOrReplaceText(u"https://www.chromium.org/b"); - service()->WaitForRequest(); - - auto ok_response = mojom::GenerateQRCodeResponse::New(); - ok_response->error_code = mojom::QRCodeGeneratorError::NONE; - ok_response->bitmap.allocN32Pixels(16, 16); - ok_response->data_size = gfx::Size(16, 16); - + // that, but this time clear the injected error. { - ViewVisibilityWaiter waiter(image()); - service()->DeliverResponse(std::move(ok_response)); + VisibilityChangedWaiter waiter(image()); + bubble()->SetQRCodeErrorForTesting(std::nullopt); + textfield()->InsertOrReplaceText(u"https://www.chromium.org/b"); waiter.Wait(); - EXPECT_TRUE(ImageShowing()); } } TEST_F(QRCodeGeneratorBubbleUITest, PlaceholderImageShowsAfterTextFieldEmptied) { + // Expecting placeholder image when the text input is empty. + textfield()->SelectAll(false); + textfield()->DeleteRange(textfield()->GetSelectedRange()); bubble()->Show(); - EXPECT_TRUE(ImagePlaceholderShowing()); - service()->WaitForRequest(); - ASSERT_TRUE(service()->HasPendingRequest()); - auto error_response = mojom::GenerateQRCodeResponse::New(); - error_response->error_code = mojom::QRCodeGeneratorError::UNKNOWN_ERROR; - - EXPECT_TRUE(ImagePlaceholderShowing()); - + // Expecting image to be hidden after QR generation error. { - ViewVisibilityWaiter waiter(image()); - service()->DeliverResponse(std::move(error_response)); + VisibilityChangedWaiter waiter(image()); + bubble()->SetQRCodeErrorForTesting( + mojom::QRCodeGeneratorError::UNKNOWN_ERROR); + textfield()->InsertOrReplaceText(u"https://www.chromium.org/b"); waiter.Wait(); EXPECT_FALSE(ImageShowing()); } - auto ok_response = mojom::GenerateQRCodeResponse::New(); - ok_response->error_code = mojom::QRCodeGeneratorError::NONE; - ok_response->bitmap.allocN32Pixels(16, 16); - ok_response->bitmap.eraseColor(SK_ColorRED); - ok_response->data_size = gfx::Size(16, 16); - - // The UI regenerates the QR code when the user types new text, so synthesize - // that. - textfield()->InsertOrReplaceText(u"https://www.chromium.org/b"); - service()->WaitForRequest(); - + // Expecting image to be shown after QR generation success. { - ViewVisibilityWaiter waiter(image()); - service()->DeliverResponse(std::move(ok_response)); + VisibilityChangedWaiter waiter(image()); + bubble()->SetQRCodeErrorForTesting(std::nullopt); + // The UI regenerates the QR code when the user types new text, so + // synthesize that. + textfield()->InsertOrReplaceText(u"https://www.chromium.org/b"); waiter.Wait(); EXPECT_TRUE(ImageShowing()); @@ -294,48 +226,40 @@ EXPECT_TRUE(download_button()->GetEnabled()); } + // Expecting placeholder image after deleting the text input again. textfield()->SelectAll(false); textfield()->DeleteRange(textfield()->GetSelectedRange()); - EXPECT_TRUE(ImageShowing()); EXPECT_TRUE(ImagePlaceholderShowing()); EXPECT_FALSE(download_button()->GetEnabled()); } TEST_F(QRCodeGeneratorBubbleUITest, LabelHidesAfterErrorState) { + // Expecting placeholder image when the text input is empty. + textfield()->SelectAll(false); + textfield()->DeleteRange(textfield()->GetSelectedRange()); bubble()->Show(); - EXPECT_TRUE(ImagePlaceholderShowing()); EXPECT_TRUE(ErrorLabelHiddenAndA11yIgnored()); - service()->WaitForRequest(); - ASSERT_TRUE(service()->HasPendingRequest()); - auto error_response = mojom::GenerateQRCodeResponse::New(); - error_response->error_code = mojom::QRCodeGeneratorError::UNKNOWN_ERROR; - - EXPECT_TRUE(ImagePlaceholderShowing()); - + // Expecting image to be hidden after QR generation error. { - ViewVisibilityWaiter waiter(image()); - service()->DeliverResponse(std::move(error_response)); + VisibilityChangedWaiter waiter(image()); + bubble()->SetQRCodeErrorForTesting( + mojom::QRCodeGeneratorError::UNKNOWN_ERROR); + textfield()->InsertOrReplaceText(u"https://www.chromium.org/b"); waiter.Wait(); EXPECT_FALSE(ImageShowing()); } - auto too_long_response = mojom::GenerateQRCodeResponse::New(); - too_long_response->error_code = mojom::QRCodeGeneratorError::INPUT_TOO_LONG; - - // The UI regenerates the QR code when the user types new text, so synthesize - // that. - textfield()->InsertOrReplaceText(u"https://www.chromium.org/b"); - service()->WaitForRequest(); - + // Input-too-long should present a different UI from unknown errors. { - ViewVisibilityWaiter waiter(image()); - service()->DeliverResponse(std::move(too_long_response)); + VisibilityChangedWaiter waiter(image()); + bubble()->SetQRCodeErrorForTesting( + mojom::QRCodeGeneratorError::INPUT_TOO_LONG); + textfield()->InsertOrReplaceText(u"https://www.chromium.org/b"); waiter.Wait(); - EXPECT_TRUE(ImageShowing()); EXPECT_TRUE(ImagePlaceholderShowing()); EXPECT_TRUE(ErrorLabelShowing());
diff --git a/chrome/browser/ui/views/tabs/fade_footer_view.cc b/chrome/browser/ui/views/tabs/fade_footer_view.cc index 31a2fda..d2565ad8 100644 --- a/chrome/browser/ui/views/tabs/fade_footer_view.cc +++ b/chrome/browser/ui/views/tabs/fade_footer_view.cc
@@ -10,7 +10,6 @@ #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/views/tabs/alert_indicator_button.h" #include "chrome/grit/generated_resources.h" -#include "components/performance_manager/public/features.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/models/image_model.h" @@ -164,12 +163,8 @@ const std::u16string formatted_memory_usage = ui::FormatBytes(data.memory_usage_in_bytes); const std::u16string row_text = l10n_util::GetStringFUTF16( - data.memory_usage_in_bytes > - static_cast<uint64_t>( - performance_manager::features:: - kMemoryUsageInHovercardsHighThresholdBytes.Get()) - ? IDS_HOVERCARD_TAB_HIGH_MEMORY_USAGE - : IDS_HOVERCARD_TAB_MEMORY_USAGE, + data.is_high_memory_usage ? IDS_HOVERCARD_TAB_HIGH_MEMORY_USAGE + : IDS_HOVERCARD_TAB_MEMORY_USAGE, formatted_memory_usage); const ui::ImageModel icon_image_model = ui::ImageModel::FromVectorIcon(
diff --git a/chrome/browser/ui/views/tabs/fade_footer_view.h b/chrome/browser/ui/views/tabs/fade_footer_view.h index b427885..df1c23b 100644 --- a/chrome/browser/ui/views/tabs/fade_footer_view.h +++ b/chrome/browser/ui/views/tabs/fade_footer_view.h
@@ -22,6 +22,7 @@ }; struct PerformanceRowData { + bool is_high_memory_usage = false; uint64_t memory_usage_in_bytes = 0; };
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc index bae79056..fd5eaf55 100644 --- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc +++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
@@ -565,12 +565,17 @@ tab_data.tab_resource_usage ? tab_data.tab_resource_usage->memory_usage_in_bytes() : 0; + const bool is_high_memory_usage = + tab_data.tab_resource_usage + ? tab_data.tab_resource_usage->is_high_memory_usage() + : false; show_footer = show_footer || show_discard_status || tab_memory_usage_in_bytes > 0; footer_view_->SetAlertData({alert_state_, show_discard_status, tab_data.discarded_memory_savings_in_bytes}); - footer_view_->SetPerformanceData({tab_memory_usage_in_bytes}); + footer_view_->SetPerformanceData( + {is_high_memory_usage, tab_memory_usage_in_bytes}); } else { if (alert_state_ != old_alert_state) {
diff --git a/chrome/browser/ui/views/web_apps/isolated_web_apps/callback_delayer.cc b/chrome/browser/ui/views/web_apps/isolated_web_apps/callback_delayer.cc index 0b64f508..260c7c3 100644 --- a/chrome/browser/ui/views/web_apps/isolated_web_apps/callback_delayer.cc +++ b/chrome/browser/ui/views/web_apps/isolated_web_apps/callback_delayer.cc
@@ -65,7 +65,7 @@ stopwatch_->Start(); repeating_timer_.Start(FROM_HERE, base::Seconds(1) / kRefreshRateHz, base::BindRepeating(&CallbackDelayer::OnTimerTick, - base::Unretained(this))); + weak_ptr_factory_.GetWeakPtr())); } void CallbackDelayer::OnTimerTick() {
diff --git a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc index cd122c0..d925823 100644 --- a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc +++ b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
@@ -751,9 +751,12 @@ auto_reauthn_checkbox_->SetChecked(true); } - // Do not add disclosure text if this is a sign in. - if (account.login_state == Account::LoginState::kSignIn) + // Do not add disclosure text if this is a sign in or if we were requested + // to skip it. + if (account.login_state == Account::LoginState::kSignIn || + !idp_display_data.request_permission) { return row; + } // Add disclosure text. It requires a StyledLabel so that we can add the links // to the privacy policy and terms of service URLs.
diff --git a/chrome/browser/ui/views/webid/account_selection_bubble_view_unittest.cc b/chrome/browser/ui/views/webid/account_selection_bubble_view_unittest.cc index ee00b8e..1901cc9 100644 --- a/chrome/browser/ui/views/webid/account_selection_bubble_view_unittest.cc +++ b/chrome/browser/ui/views/webid/account_selection_bubble_view_unittest.cc
@@ -145,13 +145,14 @@ const content::IdentityProviderMetadata& idp_metadata, const std::string& terms_of_service_url, bool show_auto_reauthn_checkbox = false, - bool exclude_iframe = true) { + bool exclude_iframe = true, + bool request_permission = true) { CreateAccountSelectionBubble(/*exclude_title=*/false, exclude_iframe, show_auto_reauthn_checkbox); IdentityProviderDisplayData idp_data( kIdpETLDPlusOne, idp_metadata, CreateTestClientMetadata(terms_of_service_url), {account}, - /*request_permission=*/true, /*has_login_status_mismatch=*/false); + request_permission, /*has_login_status_mismatch=*/false); dialog_->ShowSingleAccountConfirmDialog( kTopFrameETLDPlusOne, exclude_iframe ? std::nullopt @@ -677,6 +678,38 @@ kAccountSuffix)); } +TEST_F(AccountSelectionBubbleViewTest, NewAccountWithoutRequestPermission) { + const std::string kAccountSuffix = "suffix"; + content::IdentityRequestAccount account = CreateTestIdentityRequestAccount( + kAccountSuffix, content::IdentityRequestAccount::LoginState::kSignUp); + CreateSingleAccountPicker( + /*show_back_button=*/false, account, content::IdentityProviderMetadata(), + /*terms_of_service_url=*/"", /*show_auto_reauthn_checkbox=*/false, + /*exclude_iframe=*/true, /*request_permission=*/false); + + std::vector<raw_ptr<views::View, VectorExperimental>> children = + dialog()->children(); + ASSERT_EQ(children.size(), 3u); + PerformHeaderChecks(children[0], kTitleSignIn, + /*expected_subtitle=*/std::nullopt, + /*expect_idp_brand_icon_in_header=*/true); + + views::View* single_account_chooser = children[2]; + std::vector<raw_ptr<views::View, VectorExperimental>> chooser_children = + single_account_chooser->children(); + ASSERT_EQ(chooser_children.size(), 2u); + views::View* single_account_row = chooser_children[0]; + + CheckAccountRow(single_account_row, kAccountSuffix); + + // Check the "Continue as" button. + views::MdTextButton* button = + static_cast<views::MdTextButton*>(chooser_children[1]); + EXPECT_EQ(button->GetText(), + base::UTF8ToUTF16("Continue as " + std::string(kGivenNameBase) + + kAccountSuffix)); +} + TEST_F(AccountSelectionBubbleViewTest, ContinueButtonWithProperBackgroundColor) { const std::string kAccountSuffix = "suffix";
diff --git a/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc b/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc index c684b4b3..50bc46b 100644 --- a/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc
@@ -51,10 +51,6 @@ #include "chromeos/ash/components/standalone_browser/feature_refs.h" #endif -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chromeos/startup/browser_params_proxy.h" -#endif - namespace web_app { WebAppControllerBrowserTest::WebAppControllerBrowserTest() @@ -275,7 +271,7 @@ test::LogDebugInfoToConsole(profile_manager->GetLoadedProfiles(), log_time); } #if BUILDFLAG(IS_CHROMEOS_LACROS) - if (!chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { + if (IsCrosapiEnabled()) { // Make sure all ash browser UI are closed before the test tears down. CloseAllAshBrowserWindows(); } @@ -292,7 +288,7 @@ void WebAppControllerBrowserTest::SetUpOnMainThread() { #if BUILDFLAG(IS_CHROMEOS_LACROS) - if (!chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { + if (IsCrosapiEnabled()) { CHECK(IsWebAppsCrosapiEnabled()); } #endif
diff --git a/chrome/browser/ui/webui/ash/login/signin_userlist_unittest.cc b/chrome/browser/ui/webui/ash/login/signin_userlist_unittest.cc index b64a15af..5920e7f7 100644 --- a/chrome/browser/ui/webui/ash/login/signin_userlist_unittest.cc +++ b/chrome/browser/ui/webui/ash/login/signin_userlist_unittest.cc
@@ -12,12 +12,12 @@ #include "base/strings/string_number_conversions.h" #include "chrome/browser/ash/login/screens/user_selection_screen.h" #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" -#include "chrome/browser/ash/login/users/multi_profile_user_controller.h" #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" #include "chromeos/ash/components/proximity_auth/screenlock_bridge.h" #include "components/account_id/account_id.h" +#include "components/user_manager/multi_user/multi_user_sign_in_policy_controller.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user.h" #include "content/public/test/browser_task_environment.h" @@ -54,9 +54,12 @@ profile_manager_ = std::make_unique<TestingProfileManager>( TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager_->SetUp()); - controller_ = std::make_unique<MultiProfileUserController>( - TestingBrowserProcess::GetGlobal()->local_state(), fake_user_manager_); - fake_user_manager_->set_multi_profile_user_controller(controller_.get()); + controller_ = + std::make_unique<user_manager::MultiUserSignInPolicyController>( + TestingBrowserProcess::GetGlobal()->local_state(), + fake_user_manager_); + fake_user_manager_->set_multi_user_sign_in_policy_controller( + controller_.get()); for (size_t i = 0; i < std::size(kUsersPublic); ++i) fake_user_manager_->AddPublicAccountUser( @@ -74,7 +77,7 @@ } void TearDown() override { - fake_user_manager_->set_multi_profile_user_controller(nullptr); + fake_user_manager_->set_multi_user_sign_in_policy_controller(nullptr); controller_.reset(); profile_manager_.reset(); testing::Test::TearDown(); @@ -89,7 +92,7 @@ user_manager::ScopedUserManager user_manager_enabler_; std::unique_ptr<TestingProfileManager> profile_manager_; std::map<std::string, proximity_auth::mojom::AuthType> user_auth_type_map; - std::unique_ptr<MultiProfileUserController> controller_; + std::unique_ptr<user_manager::MultiUserSignInPolicyController> controller_; }; TEST_F(SigninPrepareUserListTest, AlwaysKeepOwnerInList) {
diff --git a/chrome/browser/ui/webui/ash/login/user_creation_screen_handler.cc b/chrome/browser/ui/webui/ash/login/user_creation_screen_handler.cc index 8cd62b2..4d89734 100644 --- a/chrome/browser/ui/webui/ash/login/user_creation_screen_handler.cc +++ b/chrome/browser/ui/webui/ash/login/user_creation_screen_handler.cc
@@ -102,10 +102,6 @@ ShowInWebUI(); } -void UserCreationScreenHandler::SetDefaultStep() { - CallExternalAPI("setDefaultStep"); -} - void UserCreationScreenHandler::SetTriageStep() { CallExternalAPI("setTriageStep"); }
diff --git a/chrome/browser/ui/webui/ash/login/user_creation_screen_handler.h b/chrome/browser/ui/webui/ash/login/user_creation_screen_handler.h index 5d07eef..4ceb6d2 100644 --- a/chrome/browser/ui/webui/ash/login/user_creation_screen_handler.h +++ b/chrome/browser/ui/webui/ash/login/user_creation_screen_handler.h
@@ -27,7 +27,6 @@ virtual void SetIsBackButtonVisible(bool value) = 0; virtual void SetTriageStep() = 0; virtual void SetChildSetupStep() = 0; - virtual void SetDefaultStep() = 0; }; class UserCreationScreenHandler : public UserCreationView, @@ -48,7 +47,6 @@ void SetIsBackButtonVisible(bool value) override; void SetTriageStep() override; void SetChildSetupStep() override; - void SetDefaultStep() override; // BaseScreenHandler: void DeclareLocalizedValues(
diff --git a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc index d4564556..d598e0b 100644 --- a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc +++ b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc
@@ -299,7 +299,6 @@ "chrome://bookmarks", "chrome://bookmarks-side-panel.top-chrome", "chrome://chrome-urls", - "chrome://commander", "chrome://components", "chrome://connection-help", "chrome://connection-monitoring-detected",
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index bb85866f..58ba4c2c 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -134,7 +134,6 @@ #include "chrome/browser/ui/webui/access_code_cast/access_code_cast_ui.h" #include "chrome/browser/ui/webui/app_service_internals/app_service_internals_ui.h" #include "chrome/browser/ui/webui/bookmarks/bookmarks_ui.h" -#include "chrome/browser/ui/webui/commander/commander_ui.h" #include "chrome/browser/ui/webui/commerce/shopping_insights_side_panel_ui.h" #include "chrome/browser/ui/webui/devtools/devtools_ui.h" #include "chrome/browser/ui/webui/downloads/downloads_ui.h" @@ -536,8 +535,6 @@ if (url.host_piece() == password_manager::kChromeUIPasswordManagerHost) { return &NewWebUI<PasswordManagerUI>; } - if (url.host_piece() == chrome::kChromeUICommanderHost) - return &NewWebUI<CommanderUI>; // Identity API is not available on Android. if (url.host_piece() == chrome::kChromeUIIdentityInternalsHost) return &NewWebUI<IdentityInternalsUI>;
diff --git a/chrome/browser/ui/webui/commander/OWNERS b/chrome/browser/ui/webui/commander/OWNERS deleted file mode 100644 index d7b99b6..0000000 --- a/chrome/browser/ui/webui/commander/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -file://chrome/browser/ui/commander/OWNERS
diff --git a/chrome/browser/ui/webui/commander/commander_handler.cc b/chrome/browser/ui/webui/commander/commander_handler.cc deleted file mode 100644 index cd62a2b0..0000000 --- a/chrome/browser/ui/webui/commander/commander_handler.cc +++ /dev/null
@@ -1,146 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/webui/commander/commander_handler.h" - -#include <string> -#include <utility> - -#include "base/functional/bind.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/ui/commander/commander_view_model.h" - -namespace { -// Message handler keys. -constexpr char kTextChangedMessage[] = "textChanged"; -constexpr char kOptionSelectedMessage[] = "optionSelected"; -constexpr char kDismissMessage[] = "dismiss"; -constexpr char kHeightChangedMessage[] = "heightChanged"; -constexpr char kCompositeCommandCancelledMessage[] = - "compositeCommandCancelled"; -// WebUI event keys. -constexpr char kViewModelUpdatedEvent[] = "view-model-updated"; -constexpr char kInitializeEvent[] = "initialize"; -// View model dictionary keys -constexpr char kActionKey[] = "action"; -constexpr char kResultSetIdKey[] = "resultSetId"; -constexpr char kTitleKey[] = "title"; -constexpr char kEntityKey[] = "entity"; -constexpr char kAnnotationKey[] = "annotation"; -constexpr char kMatchedRangesKey[] = "matchedRanges"; -constexpr char kOptionsKey[] = "options"; -constexpr char kPromptTextKey[] = "promptText"; -} // namespace - -CommanderHandler::CommanderHandler() = default; -CommanderHandler::~CommanderHandler() = default; - -void CommanderHandler::RegisterMessages() { - web_ui()->RegisterMessageCallback( - kTextChangedMessage, - base::BindRepeating(&CommanderHandler::HandleTextChanged, - base::Unretained(this))); - web_ui()->RegisterMessageCallback( - kOptionSelectedMessage, - base::BindRepeating(&CommanderHandler::HandleOptionSelected, - base::Unretained(this))); - web_ui()->RegisterMessageCallback( - kCompositeCommandCancelledMessage, - base::BindRepeating(&CommanderHandler::HandleCompositeCommandCancelled, - base::Unretained(this))); - web_ui()->RegisterMessageCallback( - kDismissMessage, base::BindRepeating(&CommanderHandler::HandleDismiss, - base::Unretained(this))); - web_ui()->RegisterMessageCallback( - kHeightChangedMessage, - base::BindRepeating(&CommanderHandler::HandleHeightChanged, - base::Unretained(this))); -} - -void CommanderHandler::OnJavascriptDisallowed() { - if (delegate_) - delegate_->OnHandlerEnabled(false); -} - -void CommanderHandler::OnJavascriptAllowed() { - if (delegate_) - delegate_->OnHandlerEnabled(true); -} - -void CommanderHandler::HandleTextChanged(const base::Value::List& args) { - AllowJavascript(); - CHECK_EQ(1u, args.size()); - std::string text = args[0].GetString(); - if (delegate_) - delegate_->OnTextChanged(base::UTF8ToUTF16(text)); -} - -void CommanderHandler::HandleOptionSelected(const base::Value::List& args) { - AllowJavascript(); - CHECK_EQ(2u, args.size()); - int index = args[0].GetInt(); - int result_set_id = args[1].GetInt(); - if (delegate_) - delegate_->OnOptionSelected(index, result_set_id); -} - -void CommanderHandler::HandleCompositeCommandCancelled( - const base::Value::List& args) { - if (!delegate_) - return; - AllowJavascript(); - delegate_->OnCompositeCommandCancelled(); -} - -void CommanderHandler::HandleDismiss(const base::Value::List& args) { - if (delegate_) - delegate_->OnDismiss(); -} - -void CommanderHandler::HandleHeightChanged(const base::Value::List& args) { - CHECK_EQ(1u, args.size()); - int new_height = args[0].GetInt(); - if (delegate_) - delegate_->OnHeightChanged(new_height); -} - -void CommanderHandler::ViewModelUpdated( - commander::CommanderViewModel view_model) { - base::Value::Dict vm; - vm.Set(kActionKey, view_model.action); - vm.Set(kResultSetIdKey, view_model.result_set_id); - if (view_model.action == - commander::CommanderViewModel::Action::kDisplayResults) { - base::Value::List option_list; - for (commander::CommandItemViewModel& item : view_model.items) { - base::Value::Dict option; - option.Set(kTitleKey, item.title); - option.Set(kEntityKey, item.entity_type); - if (!item.annotation.empty()) - option.Set(kAnnotationKey, item.annotation); - base::Value::List ranges; - for (const gfx::Range& range : item.matched_ranges) { - base::Value::List range_value; - range_value.Append(static_cast<int>(range.start())); - range_value.Append(static_cast<int>(range.end())); - ranges.Append(std::move(range_value)); - } - option.Set(kMatchedRangesKey, std::move(ranges)); - option_list.Append(std::move(option)); - } - vm.Set(kOptionsKey, std::move(option_list)); - } else { - // kDismiss is handled higher in the stack. - DCHECK_EQ(view_model.action, - commander::CommanderViewModel::Action::kPrompt); - vm.Set(kPromptTextKey, view_model.prompt_text); - } - FireWebUIListener(kViewModelUpdatedEvent, vm); -} - -void CommanderHandler::PrepareToShow(Delegate* delegate) { - delegate_ = delegate; - if (IsJavascriptAllowed()) - FireWebUIListener(kInitializeEvent); -}
diff --git a/chrome/browser/ui/webui/commander/commander_handler.h b/chrome/browser/ui/webui/commander/commander_handler.h deleted file mode 100644 index e78e49e..0000000 --- a/chrome/browser/ui/webui/commander/commander_handler.h +++ /dev/null
@@ -1,78 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_WEBUI_COMMANDER_COMMANDER_HANDLER_H_ -#define CHROME_BROWSER_UI_WEBUI_COMMANDER_COMMANDER_HANDLER_H_ - -#include "base/memory/raw_ptr.h" -#include "chrome/browser/ui/commander/commander_view_model.h" -#include "content/public/browser/web_ui.h" -#include "content/public/browser/web_ui_message_handler.h" - -// Handles serializing and unserializing communication between the commander -// backend and WebUI interface. -class CommanderHandler : public content::WebUIMessageHandler { - public: - // The delegate allows CommanderHandler to send messages up to the - // browser-side commander system. - class Delegate { - public: - // Called when the text is changed in the WebUI interface. - virtual void OnTextChanged(const std::u16string& text) = 0; - // Called when an option is selected (clicked or enter pressed) in the WebUI - // interface. - virtual void OnOptionSelected(size_t option_index, int result_set_id) = 0; - // Called when the user has cancelled entering a composite command. - virtual void OnCompositeCommandCancelled() = 0; - // Called when the WebUI interface wants to dismiss the UI. - virtual void OnDismiss() = 0; - // Called when the WebUI interface's content height has changed. - virtual void OnHeightChanged(int new_height) = 0; - // Called when the web interface's availability changes (for example, if - // the renderer crashes, this should be called with false). - virtual void OnHandlerEnabled(bool is_enabled) = 0; - }; - CommanderHandler(); - ~CommanderHandler() override; - - // Called when a new view model should be displayed. - void ViewModelUpdated(commander::CommanderViewModel view_model); - - // Called to reinitialize the UI (clear input, remove results, etc.) and - // attach the delegate. - void PrepareToShow(Delegate* delegate); - - // WebUIMessageHandler overrides. - void RegisterMessages() override; - void OnJavascriptAllowed() override; - void OnJavascriptDisallowed() override; - - private: - // WebUI message handlers - - // Handles text changes in the primary textfield. Expects a single string - // argument. - void HandleTextChanged(const base::Value::List& args); - - // Handles the user selecting one of the available command options. - // Expects two numeric argument representing the index of the chosen command, - // and the result set id of the active view model (see documentation in - // commander::CommanderViewModel). - void HandleOptionSelected(const base::Value::List& args); - - // Handles the user cancelling a composite command. No arguments expected. - void HandleCompositeCommandCancelled(const base::Value::List& args); - - // Handles the user pressing "Escape", or otherwise indicating they would - // like to dismiss the UI. No arguments expected. - void HandleDismiss(const base::Value::List& args); - - // Handles the display height of the UI changing. Expects one numeric argument - // representing the new height. - void HandleHeightChanged(const base::Value::List& args); - - raw_ptr<Delegate> delegate_ = nullptr; -}; - -#endif // CHROME_BROWSER_UI_WEBUI_COMMANDER_COMMANDER_HANDLER_H_
diff --git a/chrome/browser/ui/webui/commander/commander_ui.cc b/chrome/browser/ui/webui/commander/commander_ui.cc deleted file mode 100644 index b83d2ca..0000000 --- a/chrome/browser/ui/webui/commander/commander_ui.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/webui/commander/commander_ui.h" - -#include <memory> - -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/commander/commander_handler.h" -#include "chrome/browser/ui/webui/webui_util.h" -#include "chrome/common/webui_url_constants.h" -#include "chrome/grit/browser_resources.h" -#include "chrome/grit/commander_resources.h" -#include "chrome/grit/commander_resources_map.h" -#include "chrome/grit/generated_resources.h" -#include "content/public/browser/web_ui_data_source.h" - -CommanderUI::CommanderUI(content::WebUI* web_ui) - : content::WebUIController(web_ui) { - auto handler = std::make_unique<CommanderHandler>(); - handler_ = handler.get(); - web_ui->AddMessageHandler(std::move(handler)); - - content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd( - Profile::FromWebUI(web_ui), chrome::kChromeUICommanderHost); - static constexpr webui::LocalizedString kLocalizedStrings[] = { - {"placeholder", IDS_QUICK_COMMANDS_PLACEHOLDER}, - {"noResults", IDS_QUICK_COMMANDS_NO_RESULTS}, - {"pageTitle", IDS_QUICK_COMMANDS_LABEL}, - }; - for (const auto& str : kLocalizedStrings) - webui::AddLocalizedString(source, str.name, str.id); - webui::SetupWebUIDataSource( - source, base::make_span(kCommanderResources, kCommanderResourcesSize), - IDR_COMMANDER_COMMANDER_HTML); -} - -CommanderUI::~CommanderUI() = default;
diff --git a/chrome/browser/ui/webui/commander/commander_ui.h b/chrome/browser/ui/webui/commander/commander_ui.h deleted file mode 100644 index 958193f..0000000 --- a/chrome/browser/ui/webui/commander/commander_ui.h +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_WEBUI_COMMANDER_COMMANDER_UI_H_ -#define CHROME_BROWSER_UI_WEBUI_COMMANDER_COMMANDER_UI_H_ - -#include "base/memory/raw_ptr.h" -#include "content/public/browser/web_ui_controller.h" - -class CommanderHandler; - -// Entry point for the Commander WebUI interface. -class CommanderUI : public content::WebUIController { - public: - explicit CommanderUI(content::WebUI* web_ui); - ~CommanderUI() override; - - // Disallow copy and assign - CommanderUI(const CommanderUI& other) = delete; - CommanderUI& operator=(const CommanderUI& other) = delete; - - CommanderHandler* handler() { return handler_; } - - private: - raw_ptr<CommanderHandler> handler_; -}; - -#endif // CHROME_BROWSER_UI_WEBUI_COMMANDER_COMMANDER_UI_H_
diff --git a/chrome/browser/ui/webui/commander/commander_ui_browsertest.cc b/chrome/browser/ui/webui/commander/commander_ui_browsertest.cc deleted file mode 100644 index df402377..0000000 --- a/chrome/browser/ui/webui/commander/commander_ui_browsertest.cc +++ /dev/null
@@ -1,206 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/webui/commander/commander_ui.h" - -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/commander/commander_view_model.h" -#include "chrome/browser/ui/webui/commander/commander_handler.h" -#include "chrome/common/chrome_isolated_world_ids.h" -#include "chrome/common/webui_url_constants.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "content/public/browser/navigation_controller.h" -#include "content/public/test/browser_test.h" -#include "content/public/test/browser_test_utils.h" -#include "content/public/test/test_web_ui.h" - -namespace { - -class TestCommanderHandler : public CommanderHandler { - public: - explicit TestCommanderHandler(content::WebUI* web_ui) { set_web_ui(web_ui); } -}; - -} // namespace - -// This actually tests the whole WebUI communication layer as a unit: -// CommanderUI and CommanderHandler. -class CommanderUITest : public InProcessBrowserTest, - public CommanderHandler::Delegate { - public: - void SetUpOnMainThread() override { - contents_ = content::WebContents::Create( - content::WebContents::CreateParams(browser()->profile())); - contents_->GetController().LoadURL( - GURL(chrome::kChromeUICommanderURL), content::Referrer(), - ui::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string()); - CommanderUI* controller = - static_cast<CommanderUI*>(contents_->GetWebUI()->GetController()); - controller->handler()->PrepareToShow(this); - - ASSERT_TRUE(content::WaitForLoadStop(contents_.get())); - EXPECT_EQ(contents_->GetLastCommittedURL().host(), - chrome::kChromeUICommanderHost); - } - void TearDownOnMainThread() override { - contents_.reset(); - dismiss_invocation_count_ = 0; - text_changed_invocations_.clear(); - option_selected_invocations_.clear(); - height_changed_invocations_.clear(); - } - - protected: - void ExecuteJS(std::string js) { - ASSERT_TRUE(content::ExecJs(contents_.get(), js)); - } - // CommanderHandler::Delegate implementation. - void OnTextChanged(const std::u16string& text) override { - text_changed_invocations_.push_back(text); - } - void OnOptionSelected(size_t option_index, int result_set_id) override { - option_selected_invocations_.emplace_back(option_index, result_set_id); - } - - void OnCompositeCommandCancelled() override { - composite_command_cancelled_invocation_count_++; - } - - void OnDismiss() override { dismiss_invocation_count_++; } - - void OnHeightChanged(int new_height) override { - height_changed_invocations_.emplace_back(new_height); - } - void OnHandlerEnabled(bool enabled) override {} - - const std::vector<std::u16string> text_changed_invocations() { - return text_changed_invocations_; - } - const std::vector<std::pair<size_t, int>> option_selected_invocations() { - return option_selected_invocations_; - } - const std::vector<int> height_changed_invocations() { - return height_changed_invocations_; - } - - int composite_command_cancelled_invocation_count() { - return composite_command_cancelled_invocation_count_; - } - int dismiss_invocation_count() { return dismiss_invocation_count_; } - - private: - std::unique_ptr<content::WebContents> contents_; - int dismiss_invocation_count_ = 0; - int composite_command_cancelled_invocation_count_ = 0; - std::vector<std::u16string> text_changed_invocations_; - std::vector<std::pair<size_t, int>> option_selected_invocations_; - std::vector<int> height_changed_invocations_; -}; - -IN_PROC_BROWSER_TEST_F(CommanderUITest, Dismiss) { - EXPECT_EQ(dismiss_invocation_count(), 0); - ExecuteJS("chrome.send('dismiss')"); - EXPECT_EQ(dismiss_invocation_count(), 1); -} - -IN_PROC_BROWSER_TEST_F(CommanderUITest, HeightChanged) { - size_t calls = height_changed_invocations().size(); - ExecuteJS("chrome.send('heightChanged', [42])"); - ASSERT_EQ(height_changed_invocations().size(), calls + 1); - ASSERT_EQ(height_changed_invocations().back(), 42); -} - -IN_PROC_BROWSER_TEST_F(CommanderUITest, TextChanged) { - EXPECT_EQ(text_changed_invocations().size(), 0u); - ExecuteJS("chrome.send('textChanged', ['orange'])"); - ASSERT_EQ(text_changed_invocations().size(), 1u); - ASSERT_EQ(text_changed_invocations().back(), u"orange"); -} - -IN_PROC_BROWSER_TEST_F(CommanderUITest, OptionSelected) { - EXPECT_EQ(option_selected_invocations().size(), 0u); - ExecuteJS("chrome.send('optionSelected', [13, 586])"); - ASSERT_EQ(option_selected_invocations().size(), 1u); - std::pair<size_t, int> expected({13, 586}); - ASSERT_EQ(option_selected_invocations().back(), expected); -} - -IN_PROC_BROWSER_TEST_F(CommanderUITest, CompositeCommandCancelled) { - EXPECT_EQ(composite_command_cancelled_invocation_count(), 0); - ExecuteJS("chrome.send('compositeCommandCancelled')"); - EXPECT_EQ(composite_command_cancelled_invocation_count(), 1); -} - -TEST(CommanderHandlerTest, DisplayResultsViewModelPassed) { - content::TestWebUI test_web_ui; - auto handler = std::make_unique<TestCommanderHandler>(&test_web_ui); - - commander::CommanderViewModel vm; - vm.action = commander::CommanderViewModel::Action::kDisplayResults; - std::u16string item_title = u"Test item"; - std::vector<gfx::Range> item_ranges = {gfx::Range(0, 4)}; - vm.items.emplace_back(item_title, item_ranges); - vm.result_set_id = 42; - - handler->AllowJavascriptForTesting(); - handler->ViewModelUpdated(std::move(vm)); - const content::TestWebUI::CallData& call_data = - *test_web_ui.call_data().back(); - EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name()); - EXPECT_EQ("view-model-updated", call_data.arg1()->GetString()); - - const base::Value::Dict& arg = call_data.arg2()->GetDict(); - EXPECT_EQ( - "Test item", - arg.Find("options")->GetList()[0].GetDict().Find("title")->GetString()); - EXPECT_EQ(0, arg.Find("options") - ->GetList()[0] - .GetDict() - .Find("matchedRanges") - ->GetList()[0] - .GetList()[0] - .GetInt()); - EXPECT_EQ(4, arg.Find("options") - ->GetList()[0] - .GetDict() - .Find("matchedRanges") - ->GetList()[0] - .GetList()[1] - .GetInt()); - EXPECT_EQ(42, arg.Find("resultSetId")->GetInt()); -} - -TEST(CommanderHandlerTest, PromptViewModelPassed) { - content::TestWebUI test_web_ui; - auto handler = std::make_unique<TestCommanderHandler>(&test_web_ui); - - commander::CommanderViewModel vm; - vm.action = commander::CommanderViewModel::Action::kPrompt; - vm.result_set_id = 42; - vm.prompt_text = u"Select fruit"; - - handler->AllowJavascriptForTesting(); - handler->ViewModelUpdated(std::move(vm)); - const content::TestWebUI::CallData& call_data = - *test_web_ui.call_data().back(); - EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name()); - EXPECT_EQ("view-model-updated", call_data.arg1()->GetString()); - - const base::Value::Dict& arg = call_data.arg2()->GetDict(); - EXPECT_EQ("Select fruit", arg.Find("promptText")->GetString()); - EXPECT_EQ(42, arg.Find("resultSetId")->GetInt()); -} - -TEST(CommanderHandlerTest, Initialize) { - content::TestWebUI test_web_ui; - auto handler = std::make_unique<TestCommanderHandler>(&test_web_ui); - handler->AllowJavascriptForTesting(); - handler->PrepareToShow(nullptr); - const content::TestWebUI::CallData& call_data = - *test_web_ui.call_data().back(); - EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name()); - EXPECT_EQ("initialize", call_data.arg1()->GetString()); -}
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc index e1c366c..29f5386 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
@@ -548,8 +548,11 @@ {"modulesJourneysCartTileLabelDefault", IDS_NTP_MODULES_QUEST_CART_TILE_LABEL_DEFAULT}, {"modulesMoreActions", IDS_NTP_MODULES_MORE_ACTIONS}, + {"modulesTabResumptionDismissButton", + IDS_NTP_MODULES_TAB_RESUMPTION_DISMISS_BUTTON}, {"modulesTabResumptionTitle", IDS_NTP_TAB_RESUMPTION_TITLE}, {"modulesTabResumptionInfo", IDS_NTP_MODULES_TAB_RESUMPTION_INFO}, + {"modulesTabResumptionSentence", IDS_NTP_MODULES_TAB_RESUMPTION_SENTENCE}, // Middle slot promo. {"undoDismissPromoButtonToast", IDS_NTP_UNDO_DISMISS_PROMO_BUTTON_TOAST},
diff --git a/chrome/browser/ui/webui/password_manager/promo_cards_handler.h b/chrome/browser/ui/webui/password_manager/promo_cards_handler.h index d31fba1..a7e84eb 100644 --- a/chrome/browser/ui/webui/password_manager/promo_cards_handler.h +++ b/chrome/browser/ui/webui/password_manager/promo_cards_handler.h
@@ -9,6 +9,7 @@ #include <vector> #include "base/memory/raw_ptr.h" +#include "base/types/pass_key.h" #include "base/values.h" #include "content/public/browser/web_ui_message_handler.h" #include "ui/gfx/image/image.h"
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index 3444445..67c923d 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -837,6 +837,8 @@ {"searchLanguages", IDS_SETTINGS_LANGUAGE_SEARCH}, {"languagesExpandA11yLabel", IDS_SETTINGS_LANGUAGES_EXPAND_ACCESSIBILITY_LABEL}, + {"preferredLanguagesHeader", + IDS_SETTINGS_LANGUAGES_PREFERRED_LANGUAGES_HEADER}, {"preferredLanguagesDesc", IDS_SETTINGS_LANGUAGES_PREFERRED_LANGUAGES_DESC}, {"moveToTop", IDS_SETTINGS_LANGUAGES_LANGUAGES_LIST_MOVE_TO_TOP},
diff --git a/chrome/browser/ui/webui/webui_util.cc b/chrome/browser/ui/webui/webui_util.cc index 9e0acc0..90babb9 100644 --- a/chrome/browser/ui/webui/webui_util.cc +++ b/chrome/browser/ui/webui/webui_util.cc
@@ -6,9 +6,12 @@ #include <string> +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "content/public/browser/web_ui_data_source.h" +#include "content/public/common/url_constants.h" #include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/ui_base_features.h" @@ -38,9 +41,14 @@ namespace webui { void SetJSModuleDefaults(content::WebUIDataSource* source) { + std::string scheme = + base::StartsWith(source->GetSource(), content::kChromeUIUntrustedScheme) + ? content::kChromeUIUntrustedScheme + : content::kChromeUIScheme; source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::ScriptSrc, - "script-src chrome://resources chrome://webui-test 'self';"); + base::StringPrintf("script-src %s://resources %s://webui-test 'self';", + scheme.c_str(), scheme.c_str())); source->UseStringsJs(); source->EnableReplaceI18nInJS();
diff --git a/chrome/browser/web_applications/app_service/lacros_browser_shortcuts_controller.cc b/chrome/browser/web_applications/app_service/lacros_browser_shortcuts_controller.cc index 3b3fc4d..4d3a6419 100644 --- a/chrome/browser/web_applications/app_service/lacros_browser_shortcuts_controller.cc +++ b/chrome/browser/web_applications/app_service/lacros_browser_shortcuts_controller.cc
@@ -145,7 +145,7 @@ if (service->GetInterfaceVersion<crosapi::mojom::AppShortcutPublisher>() < int{crosapi::mojom::AppShortcutPublisher::MethodMinVersions:: kRegisterAppShortcutControllerMinVersion} && - !chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { + !chromeos::BrowserParamsProxy::Get()->IsCrosapiDisabledForTesting()) { LOG(WARNING) << "Ash AppShortcutPublisher version " << service->GetInterfaceVersion<crosapi::mojom::AppShortcutPublisher>() @@ -184,7 +184,7 @@ if (service->GetInterfaceVersion<crosapi::mojom::AppShortcutPublisher>() < int{crosapi::mojom::AppShortcutPublisher::MethodMinVersions:: kPublishShortcutsMinVersion} && - !chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { + !chromeos::BrowserParamsProxy::Get()->IsCrosapiDisabledForTesting()) { LOG(WARNING) << "Ash AppShortcutPublisher version " << service->GetInterfaceVersion<crosapi::mojom::AppShortcutPublisher>() @@ -289,7 +289,7 @@ if (service->GetInterfaceVersion<crosapi::mojom::AppShortcutPublisher>() < int{crosapi::mojom::AppShortcutPublisher::MethodMinVersions:: kShortcutRemovedMinVersion} && - !chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { + !chromeos::BrowserParamsProxy::Get()->IsCrosapiDisabledForTesting()) { LOG(WARNING) << "Ash AppShortcutPublisher version " << service->GetInterfaceVersion<crosapi::mojom::AppShortcutPublisher>()
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index b15358c..30c8086 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1707400503-560572c1c183ea46f06eeebd8fb1b53e61875da3.profdata +chrome-mac-arm-main-1707407462-a8f6c39779c9e1e90c62d57f89007850a6892eca.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni index 72dcc7e..ade7406 100644 --- a/chrome/chrome_paks.gni +++ b/chrome/chrome_paks.gni
@@ -151,7 +151,6 @@ "$root_gen_dir/chrome/access_code_cast_resources.pak", "$root_gen_dir/chrome/app_service_internals_resources.pak", "$root_gen_dir/chrome/bookmarks_resources.pak", - "$root_gen_dir/chrome/commander_resources.pak", "$root_gen_dir/chrome/commerce_resources.pak", "$root_gen_dir/chrome/component_extension_resources.pak", "$root_gen_dir/chrome/dev_ui_resources.pak",
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 356739e..b486e37 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -556,6 +556,13 @@ // possible) for testing purposes. const char kSimulateIdleTimeout[] = "simulate-idle-timeout"; +// Causes password_manager_android_util::SetUsesSplitStoresAndUPMForLocal() to +// ignore the min GmsCore version requirement. +// TODO(crbug.com/324370397): Remove once min GmsCore version running on the +// bots is above the checked value. +const char kSkipLocalUpmGmsCoreVersionCheckForTesting[] = + "skip-local-upm-gms-core-version-check-for-testing"; + // Specifies the maximum SSL/TLS version ("tls1.2" or "tls1.3"). const char kSSLVersionMax[] = "ssl-version-max";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 96ce222..c1e853e 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -173,6 +173,7 @@ extern const char kSimulateOutdatedNoAU[]; extern const char kSimulateUpgrade[]; extern const char kSimulateIdleTimeout[]; +extern const char kSkipLocalUpmGmsCoreVersionCheckForTesting[]; extern const char kSSLVersionMax[]; extern const char kSSLVersionMin[]; extern const char kSSLVersionTLSv12[];
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 7e21515..4fa070dc 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -579,8 +579,6 @@ #endif #if !BUILDFLAG(IS_ANDROID) -const char kChromeUICommanderHost[] = "commander"; -const char kChromeUICommanderURL[] = "chrome://commander"; const char kChromeUITabSearchHost[] = "tab-search.top-chrome"; const char kChromeUITabSearchURL[] = "chrome://tab-search.top-chrome/"; #endif
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index c98dccc6..45e4d66 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -502,8 +502,6 @@ #endif #if !BUILDFLAG(IS_ANDROID) -extern const char kChromeUICommanderHost[]; -extern const char kChromeUICommanderURL[]; extern const char kChromeUITabSearchHost[]; extern const char kChromeUITabSearchURL[]; #endif
diff --git a/chrome/installer/linux/debian/update_dist_package_versions.py b/chrome/installer/linux/debian/update_dist_package_versions.py index c8d4f72d..a6f1102 100755 --- a/chrome/installer/linux/debian/update_dist_package_versions.py +++ b/chrome/installer/linux/debian/update_dist_package_versions.py
@@ -22,144 +22,161 @@ SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) SUPPORTED_DEBIAN_RELEASES = { - 'Debian 10 (Buster)': 'buster', + "Debian 10 (Buster)": "buster", # TODO: bullseye-updates does not have a .gz file. # 'Debian 11 (Bullseye)': 'bullseye', } SUPPORTED_UBUNTU_RELEASES = { - 'Ubuntu 18.04 (Bionic)': 'bionic', - 'Ubuntu 20.04 (Focal)': 'focal', + "Ubuntu 18.04 (Bionic)": "bionic", + "Ubuntu 20.04 (Focal)": "focal", } -PACKAGE_FILTER = set([ - "libatspi2.0-0", - "libasound2", - "libatk1.0-0", - "libatk-bridge2.0-0", - "libc6", - "libcairo2", - "libcups2", - "libdbus-1-3", - "libdrm2", - "libexpat1", - "libgbm1", - "libgcc1", - "libglib2.0-0", - "libnspr4", - "libnss3", - "libpango-1.0-0", - "libpangocairo-1.0-0", - "libstdc++6", - "libuuid1", - "libx11-6", - "libx11-xcb1", - "libxcb1", - "libxcb-dri3-0", - "libxcomposite1", - "libxcursor1", - "libxdamage1", - "libxext6", - "libxfixes3", - "libxi6", - "libxkbcommon0", - "libxrandr2", - "libxrender1", - "libxshmfence1", - "libxss1", - "libxtst6", -]) +PACKAGE_FILTER = set( + [ + "libatspi2.0-0", + "libasound2", + "libatk1.0-0", + "libatk-bridge2.0-0", + "libc6", + "libcairo2", + "libcups2", + "libdbus-1-3", + "libdrm2", + "libexpat1", + "libgbm1", + "libgcc1", + "libglib2.0-0", + "libnspr4", + "libnss3", + "libpango-1.0-0", + "libpangocairo-1.0-0", + "libstdc++6", + "libuuid1", + "libx11-6", + "libx11-xcb1", + "libxcb1", + "libxcb-dri3-0", + "libxcomposite1", + "libxcursor1", + "libxdamage1", + "libxext6", + "libxfixes3", + "libxi6", + "libxkbcommon0", + "libxrandr2", + "libxrender1", + "libxshmfence1", + "libxss1", + "libxtst6", + ] +) + def create_temp_file_from_data(data): - file = tempfile.NamedTemporaryFile() - file.write(data) - file.flush() - return file + file = tempfile.NamedTemporaryFile() + file.write(data) + file.flush() + return file -if sys.platform != 'linux2': - print >> sys.stderr, "Only supported on Linux." - sys.exit(1) + +if sys.platform != "linux2": + print >> sys.stderr, "Only supported on Linux." + sys.exit(1) deb_sources = {} for release in SUPPORTED_DEBIAN_RELEASES: - codename = SUPPORTED_DEBIAN_RELEASES[release] - deb_sources[release] = [ - { - "base_url": url, - "packages": [ "main/binary-amd64/Packages.gz" ] - } for url in [ - "http://ftp.us.debian.org/debian/dists/%s" % codename, - "http://ftp.us.debian.org/debian/dists/%s-updates" % codename, - "http://security.debian.org/dists/%s/updates" % codename, - ] - ] + codename = SUPPORTED_DEBIAN_RELEASES[release] + deb_sources[release] = [ + {"base_url": url, "packages": ["main/binary-amd64/Packages.gz"]} + for url in [ + "http://ftp.us.debian.org/debian/dists/%s" % codename, + "http://ftp.us.debian.org/debian/dists/%s-updates" % codename, + "http://security.debian.org/dists/%s/updates" % codename, + ] + ] for release in SUPPORTED_UBUNTU_RELEASES: - codename = SUPPORTED_UBUNTU_RELEASES[release] - repos = ['main', 'universe'] - deb_sources[release] = [ - { - "base_url": url, - "packages": [ - "%s/binary-amd64/Packages.gz" % repo for repo in repos - ], - } for url in [ - "http://us.archive.ubuntu.com/ubuntu/dists/%s" % codename, - "http://us.archive.ubuntu.com/ubuntu/dists/%s-updates" % codename, - "http://security.ubuntu.com/ubuntu/dists/%s-security" % codename, - ] - ] + codename = SUPPORTED_UBUNTU_RELEASES[release] + repos = ["main", "universe"] + deb_sources[release] = [ + { + "base_url": url, + "packages": ["%s/binary-amd64/Packages.gz" % repo for repo in repos], + } + for url in [ + "http://us.archive.ubuntu.com/ubuntu/dists/%s" % codename, + "http://us.archive.ubuntu.com/ubuntu/dists/%s-updates" % codename, + "http://security.ubuntu.com/ubuntu/dists/%s-security" % codename, + ] + ] distro_package_versions = {} -package_regex = re.compile('^Package: (.*)$') -version_regex = re.compile('^Version: (.*)$') +package_regex = re.compile("^Package: (.*)$") +version_regex = re.compile("^Version: (.*)$") for distro in deb_sources: - package_versions = {} - for source in deb_sources[distro]: - base_url = source["base_url"] - release = urllib2.urlopen("%s/Release" % base_url).read() - release_gpg = urllib2.urlopen("%s/Release.gpg" % base_url).read() - keyring = os.path.join(SCRIPT_DIR, 'repo_signing_keys.gpg') - release_file = create_temp_file_from_data(release) - release_gpg_file = create_temp_file_from_data(release_gpg) - subprocess.check_output(['gpgv', '--quiet', '--keyring', keyring, - release_gpg_file.name, release_file.name]) - for packages_gz in source["packages"]: - gz_data = urllib2.urlopen("%s/%s" % (base_url, packages_gz)).read() + package_versions = {} + for source in deb_sources[distro]: + base_url = source["base_url"] + release = urllib2.urlopen("%s/Release" % base_url).read() + release_gpg = urllib2.urlopen("%s/Release.gpg" % base_url).read() + keyring = os.path.join(SCRIPT_DIR, "repo_signing_keys.gpg") + release_file = create_temp_file_from_data(release) + release_gpg_file = create_temp_file_from_data(release_gpg) + subprocess.check_output( + [ + "gpgv", + "--quiet", + "--keyring", + keyring, + release_gpg_file.name, + release_file.name, + ] + ) + for packages_gz in source["packages"]: + gz_data = urllib2.urlopen("%s/%s" % (base_url, packages_gz)).read() - sha = hashlib.sha256() - sha.update(gz_data) - digest = binascii.hexlify(sha.digest()) - matches = [line for line in release.split('\n') - if digest in line and packages_gz in line] - assert len(matches) == 1 + sha = hashlib.sha256() + sha.update(gz_data) + digest = binascii.hexlify(sha.digest()) + matches = [ + line + for line in release.split("\n") + if digest in line and packages_gz in line + ] + assert len(matches) == 1 - zipped_file = cStringIO.StringIO() - zipped_file.write(gz_data) - zipped_file.seek(0) - contents = gzip.GzipFile(fileobj=zipped_file, mode='rb').read() - package = '' - for line in contents.split('\n'): - if line.startswith('Package: '): - match = re.search(package_regex, line) - package = match.group(1) - elif line.startswith('Version: '): - match = re.search(version_regex, line) - version = match.group(1) - if package in PACKAGE_FILTER: - package_versions[package] = version - distro_package_versions[distro] = package_versions + zipped_file = cStringIO.StringIO() + zipped_file.write(gz_data) + zipped_file.seek(0) + contents = gzip.GzipFile(fileobj=zipped_file, mode="rb").read() + package = "" + for line in contents.split("\n"): + if line.startswith("Package: "): + match = re.search(package_regex, line) + package = match.group(1) + elif line.startswith("Version: "): + match = re.search(version_regex, line) + version = match.group(1) + if package in PACKAGE_FILTER: + package_versions[package] = version + distro_package_versions[distro] = package_versions missing_any_package = False for distro in distro_package_versions: - missing_packages = PACKAGE_FILTER.difference(distro_package_versions[distro]) - if missing_packages: - missing_any_package = True - print >> sys.stderr, "Packages are not avilable on %s: %s" % ( - distro, ', '.join(missing_packages)) + missing_packages = PACKAGE_FILTER.difference(distro_package_versions[distro]) + if missing_packages: + missing_any_package = True + print >> sys.stderr, "Packages are not avilable on %s: %s" % ( + distro, + ", ".join(missing_packages), + ) if missing_any_package: - sys.exit(1) + sys.exit(1) -with open(os.path.join(SCRIPT_DIR, 'dist_package_versions.json'), 'w') as f: - f.write(json.dumps(distro_package_versions, sort_keys=True, indent=4, - separators=(',', ': '))) - f.write('\n') +with open(os.path.join(SCRIPT_DIR, "dist_package_versions.json"), "w") as f: + f.write( + json.dumps( + distro_package_versions, sort_keys=True, indent=4, separators=(",", ": ") + ) + ) + f.write("\n")
diff --git a/chrome/installer/linux/rpm/update_package_provides.py b/chrome/installer/linux/rpm/update_package_provides.py index 2d30d96..cdce118 100755 --- a/chrome/installer/linux/rpm/update_package_provides.py +++ b/chrome/installer/linux/rpm/update_package_provides.py
@@ -4,15 +4,17 @@ # found in the LICENSE file. import binascii -import cStringIO import gzip import hashlib import json import os import sys -import urllib2 import xml.etree.ElementTree +import cStringIO +import urllib2 + + LIBRARY_FILTER = set([ "ld-linux-x86-64.so", "libX11-xcb.so", @@ -63,8 +65,8 @@ "rtld(GNU_HASH)", ]) -SUPPORTED_FEDORA_RELEASES = ['32', '33', '34'] -SUPPORTED_OPENSUSE_LEAP_RELEASES = ['15.2', '15.3'] +SUPPORTED_FEDORA_RELEASES = ["32", "33", "34"] +SUPPORTED_OPENSUSE_LEAP_RELEASES = ["15.2", "15.3"] COMMON_NS = "http://linux.duke.edu/metadata/common" RPM_NS = "http://linux.duke.edu/metadata/rpm" @@ -72,80 +74,90 @@ rpm_sources = {} for version in SUPPORTED_FEDORA_RELEASES: - rpm_sources['Fedora ' + version] = [ - "https://download.fedoraproject.org/pub/fedora/linux/releases/%s/Everything/x86_64/os/" % version, - # 'updates' must appear after 'releases' since its entries - # overwrite the originals. - "https://download.fedoraproject.org/pub/fedora/linux/updates/%s/Everything/x86_64/" % version, - ] + rpm_sources["Fedora " + version] = [ + "https://download.fedoraproject.org/pub/fedora/linux/releases/%s/Everything/x86_64/os/" + % version, + # 'updates' must appear after 'releases' since its entries + # overwrite the originals. + "https://download.fedoraproject.org/pub/fedora/linux/updates/%s/Everything/x86_64/" + % version, + ] for version in SUPPORTED_OPENSUSE_LEAP_RELEASES: - rpm_sources['openSUSE Leap ' + version] = [ - "https://download.opensuse.org/distribution/leap/%s/repo/oss/" % version, - # 'update' must appear after 'distribution' since its entries - # overwrite the originals. - "https://download.opensuse.org/update/leap/%s/oss/" % version, - ] + rpm_sources["openSUSE Leap " + version] = [ + "https://download.opensuse.org/distribution/leap/%s/repo/oss/" % + version, + # 'update' must appear after 'distribution' since its entries + # overwrite the originals. + "https://download.opensuse.org/update/leap/%s/oss/" % version, + ] provides = {} missing_any_library = False for distro in rpm_sources: - distro_provides = {} - provided_prefixes = set() - for source in rpm_sources[distro]: - # |source| may redirect to a real download mirror. However, these - # mirrors may be out-of-sync with each other. Follow the redirect - # to ensure the file-references from the metadata file are valid. - source = urllib2.urlopen(source).geturl() + distro_provides = {} + provided_prefixes = set() + for source in rpm_sources[distro]: + # |source| may redirect to a real download mirror. However, these + # mirrors may be out-of-sync with each other. Follow the redirect + # to ensure the file-references from the metadata file are valid. + source = urllib2.urlopen(source).geturl() - response = urllib2.urlopen(source + "repodata/repomd.xml") - repomd = xml.etree.ElementTree.fromstring(response.read()) - primary = source + repomd.find("./{%s}data[@type='primary']/{%s}location" % - (REPO_NS, REPO_NS)).attrib['href'] - expected_checksum = repomd.find( - "./{%s}data[@type='primary']/{%s}checksum[@type='sha256']" % - (REPO_NS, REPO_NS)).text + response = urllib2.urlopen(source + "repodata/repomd.xml") + repomd = xml.etree.ElementTree.fromstring(response.read()) + primary = (source + + repomd.find("./{%s}data[@type='primary']/{%s}location" % + (REPO_NS, REPO_NS)).attrib["href"]) + expected_checksum = repomd.find( + "./{%s}data[@type='primary']/{%s}checksum[@type='sha256']" % + (REPO_NS, REPO_NS)).text - response = urllib2.urlopen(primary) - gz_data = response.read() + response = urllib2.urlopen(primary) + gz_data = response.read() - sha = hashlib.sha256() - sha.update(gz_data) - actual_checksum = binascii.hexlify(sha.digest()) - assert expected_checksum == actual_checksum + sha = hashlib.sha256() + sha.update(gz_data) + actual_checksum = binascii.hexlify(sha.digest()) + assert expected_checksum == actual_checksum - zipped_file = cStringIO.StringIO() - zipped_file.write(gz_data) - zipped_file.seek(0) - contents = gzip.GzipFile(fileobj=zipped_file, mode='rb').read() - metadata = xml.etree.ElementTree.fromstring(contents) - for package in metadata.findall('./{%s}package' % COMMON_NS): - if package.find('./{%s}arch' % COMMON_NS).text != 'x86_64': - continue - package_name = package.find('./{%s}name' % COMMON_NS).text - package_provides = [] - for entry in package.findall('./{%s}format/{%s}provides/{%s}entry' % - (COMMON_NS, RPM_NS, RPM_NS)): - name = entry.attrib['name'] - for prefix in LIBRARY_FILTER: - if name.startswith(prefix): - package_provides.append(name) - provided_prefixes.add(prefix) - distro_provides[package_name] = package_provides - provides[distro] = sorted(list(set( - [package_provides for package in distro_provides - for package_provides in distro_provides[package]]))) + zipped_file = cStringIO.StringIO() + zipped_file.write(gz_data) + zipped_file.seek(0) + contents = gzip.GzipFile(fileobj=zipped_file, mode="rb").read() + metadata = xml.etree.ElementTree.fromstring(contents) + for package in metadata.findall("./{%s}package" % COMMON_NS): + if package.find("./{%s}arch" % COMMON_NS).text != "x86_64": + continue + package_name = package.find("./{%s}name" % COMMON_NS).text + package_provides = [] + for entry in package.findall( + "./{%s}format/{%s}provides/{%s}entry" % + (COMMON_NS, RPM_NS, RPM_NS)): + name = entry.attrib["name"] + for prefix in LIBRARY_FILTER: + if name.startswith(prefix): + package_provides.append(name) + provided_prefixes.add(prefix) + distro_provides[package_name] = package_provides + provides[distro] = sorted( + list( + set([ + package_provides for package in distro_provides + for package_provides in distro_provides[package] + ]))) - missing_libraries = LIBRARY_FILTER.difference(provided_prefixes) - if missing_libraries: - missing_any_library = True - print >> sys.stderr, "Libraries are not avilable on %s: %s" % ( - distro, ', '.join(missing_libraries)) + missing_libraries = LIBRARY_FILTER.difference(provided_prefixes) + if missing_libraries: + missing_any_library = True + print >> sys.stderr, "Libraries are not avilable on %s: %s" % ( + distro, + ", ".join(missing_libraries), + ) if missing_any_library: - sys.exit(1) + sys.exit(1) script_dir = os.path.dirname(os.path.realpath(__file__)) -with open(os.path.join(script_dir, 'dist_package_provides.json'), 'w') as f: - f.write(json.dumps(provides, sort_keys=True, indent=4, - separators=(',', ': '))) - f.write('\n') +with open(os.path.join(script_dir, "dist_package_provides.json"), "w") as f: + f.write( + json.dumps(provides, sort_keys=True, indent=4, separators=(",", ": "))) + f.write("\n")
diff --git a/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc index 9b895dd..8cd3f79 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc +++ b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc
@@ -2427,6 +2427,93 @@ EXPECT_EQ((int)next_node_ids.size(), 0); } +TEST_F(ReadAnythingAppControllerTest, GetCurrentText_IncludesListMarkers) { + // Simulate breaking up the brackets across a link. + std::string marker_html_tag = "::marker"; + std::u16string bullet1 = u"1."; + std::u16string sentence1 = u"Realize numbers are ignored in Read Aloud. "; + std::u16string bullet2 = u"2."; + std::u16string sentence2 = u"Fix it."; + ui::AXTreeUpdate update; + ui::AXTreeID id_1 = ui::AXTreeID::CreateNewAXTreeID(); + SetUpdateTreeID(&update, id_1); + + ui::AXNodeData list_marker1; + list_marker1.id = 2; + list_marker1.role = ax::mojom::Role::kListMarker; + list_marker1.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag, + marker_html_tag); + list_marker1.SetName(bullet1); + list_marker1.SetNameFrom(ax::mojom::NameFrom::kContents); + + ui::AXNodeData static_text1; + static_text1.id = 3; + static_text1.role = ax::mojom::Role::kStaticText; + static_text1.SetNameChecked(sentence1); + + ui::AXNodeData list_marker2; + list_marker2.id = 4; + list_marker2.role = ax::mojom::Role::kListMarker; + list_marker2.AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag, + marker_html_tag); + list_marker2.SetName(bullet2); + list_marker2.SetNameFrom(ax::mojom::NameFrom::kContents); + + ui::AXNodeData static_text2; + static_text2.id = 12; + static_text2.role = ax::mojom::Role::kStaticText; + static_text2.SetNameChecked(sentence2); + + ui::AXNodeData root; + root.id = 10; + root.child_ids = {list_marker1.id, static_text1.id, list_marker2.id, + static_text2.id}; + update.root_id = root.id; + + update.nodes = {root, list_marker1, static_text1, list_marker2, static_text2}; + OnActiveAXTreeIDChanged(id_1); + AccessibilityEventReceived({update}); + OnAXTreeDistilled(id_1, {root.id, list_marker1.id, static_text1.id, + list_marker2.id, static_text2.id}); + InitAXPosition(list_marker1.id); + + std::vector<ui::AXNodeID> next_node_ids = GetCurrentText(); + EXPECT_EQ((int)next_node_ids.size(), 1); + + // The first segment was returned correctly. + EXPECT_EQ(next_node_ids[0], list_marker1.id); + EXPECT_EQ(GetCurrentTextStartIndex(next_node_ids[0]), 0); + EXPECT_EQ(GetCurrentTextEndIndex(next_node_ids[0]), (int)bullet1.length()); + + // Move to the next segment. + next_node_ids = MoveToNextGranularityAndGetText(); + EXPECT_EQ((int)next_node_ids.size(), 1); + + EXPECT_EQ(next_node_ids[0], static_text1.id); + EXPECT_EQ(GetCurrentTextStartIndex(next_node_ids[0]), 0); + EXPECT_EQ(GetCurrentTextEndIndex(next_node_ids[0]), (int)sentence1.length()); + + // Move to the next segment. + next_node_ids = MoveToNextGranularityAndGetText(); + EXPECT_EQ((int)next_node_ids.size(), 1); + + EXPECT_EQ(next_node_ids[0], list_marker2.id); + EXPECT_EQ(GetCurrentTextStartIndex(next_node_ids[0]), 0); + EXPECT_EQ(GetCurrentTextEndIndex(next_node_ids[0]), (int)bullet2.length()); + + // Move to the next segment. + next_node_ids = MoveToNextGranularityAndGetText(); + EXPECT_EQ((int)next_node_ids.size(), 1); + + EXPECT_EQ(next_node_ids[0], static_text2.id); + EXPECT_EQ(GetCurrentTextStartIndex(next_node_ids[0]), 0); + EXPECT_EQ(GetCurrentTextEndIndex(next_node_ids[0]), (int)sentence2.length()); + + // Nodes are empty at the end of the new tree. + next_node_ids = MoveToNextGranularityAndGetText(); + EXPECT_EQ((int)next_node_ids.size(), 0); +} + TEST_F(ReadAnythingAppControllerTest, GetCurrentText_SentenceSplitAcrossParagraphs) { std::u16string header_text = u"Header Text";
diff --git a/chrome/renderer/accessibility/read_anything_app_model.cc b/chrome/renderer/accessibility/read_anything_app_model.cc index d714f20..9ec57aae 100644 --- a/chrome/renderer/accessibility/read_anything_app_model.cc +++ b/chrome/renderer/accessibility/read_anything_app_model.cc
@@ -1426,9 +1426,20 @@ bool ReadAnythingAppModel::IsTextForReadAnything( ui::AXNodeID ax_node_id) const { - // TODO(crbug.com/1474951): Can this be updated to IsText() instead? - return (GetHtmlTag(ax_node_id).length() == 0); + // ListMarkers will have an HTML tag of "::marker," so they won't be + // considered text when checking for the length of the html tag. However, in + // order to read out loud ordered bullets, nodes that have the kListMarker + // role should be included. + // Note: This technically will include unordered list markers like bullets, + // but these won't be spoken because they will be filtered by the TTS engine. + ui::AXNode* node = GetAXNode(ax_node_id); + bool is_list_marker = node->GetRole() == ax::mojom::Role::kListMarker; + + // TODO(crbug.com/1474951): Can this be updated to IsText() instead of + // checking the length of the html tag? + return (GetHtmlTag(ax_node_id).length() == 0) || is_list_marker; } + bool ReadAnythingAppModel::IsOpeningPunctuation(char c) { return (c == '(' || c == '{' || c == '[' || c == '<'); }
diff --git a/chrome/services/qrcode_generator/public/cpp/qrcode_generator_service.cc b/chrome/services/qrcode_generator/public/cpp/qrcode_generator_service.cc index ab37bd5..0e25c96 100644 --- a/chrome/services/qrcode_generator/public/cpp/qrcode_generator_service.cc +++ b/chrome/services/qrcode_generator/public/cpp/qrcode_generator_service.cc
@@ -37,22 +37,8 @@ base::BindOnce(&MeasureDurationAndForwardToOriginalCallback, base::TimeTicks::Now(), std::move(callback)); - // Using a WeakPtr below meets the following requirement from the doc comment: - // "The `callback` will not be run if `this` generator is destroyed first". - ResponseCallback weak_callback = - base::BindOnce(&QRImageGenerator::ForwardResponse, - weak_ptr_factory_.GetWeakPtr(), std::move(timed_callback)); - - // Execute either a mojo call or an in-process C++ call depending on whether - // the "RustyQrCodeGenerator" feature has been enabled. QRCodeGeneratorServiceImpl().GenerateQRCode(std::move(request), - std::move(weak_callback)); -} - -void QRImageGenerator::ForwardResponse( - ResponseCallback original_callback, - mojom::GenerateQRCodeResponsePtr response) { - std::move(original_callback).Run(std::move(response)); + std::move(timed_callback)); } } // namespace qrcode_generator
diff --git a/chrome/services/qrcode_generator/public/cpp/qrcode_generator_service.h b/chrome/services/qrcode_generator/public/cpp/qrcode_generator_service.h index f785d67..ff5c63fa 100644 --- a/chrome/services/qrcode_generator/public/cpp/qrcode_generator_service.h +++ b/chrome/services/qrcode_generator/public/cpp/qrcode_generator_service.h
@@ -6,21 +6,13 @@ #define CHROME_SERVICES_QRCODE_GENERATOR_PUBLIC_CPP_QRCODE_GENERATOR_SERVICE_H_ #include "base/functional/callback.h" -#include "base/memory/weak_ptr.h" #include "chrome/services/qrcode_generator/public/mojom/qrcode_generator.mojom.h" namespace qrcode_generator { class QRImageGenerator { public: - // Launches a new instance of the `mojom::QRCodeGeneratorService` in an - // isolated, sandboxed process. The lifetime of the process is tied to that of - // the constructed `QRImageGenerator`. - // - // May be called from any thread. (Note that mojo requires that `Generate` is - // called on the same thread.) QRImageGenerator(); - ~QRImageGenerator(); QRImageGenerator(const QRImageGenerator&) = delete; @@ -28,19 +20,11 @@ QRImageGenerator& operator=(const QRImageGenerator&) = delete; QRImageGenerator& operator=(const QRImageGenerator&&) = delete; - // Generates a QR code. - // - // The `callback` will not be run if `this` generator is destroyed first. + // Generates a QR code. `callback` will be invoked synchronously. using ResponseCallback = base::OnceCallback<void(mojom::GenerateQRCodeResponsePtr)>; void GenerateQRCode(mojom::GenerateQRCodeRequestPtr request, ResponseCallback callback); - - private: - void ForwardResponse(ResponseCallback original_callback, - mojom::GenerateQRCodeResponsePtr response); - - base::WeakPtrFactory<QRImageGenerator> weak_ptr_factory_{this}; }; } // namespace qrcode_generator
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 10af43f..6089ef0 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -721,6 +721,8 @@ "../browser/certificate_provider/test_certificate_provider_extension.h", "../browser/extensions/policy_test_utils.cc", "../browser/extensions/policy_test_utils.h", + "../browser/ui/chromeos/test_util.cc", + "../browser/ui/chromeos/test_util.h", "../browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.cc", "../browser/ui/views/frame/browser_non_client_frame_view_chromeos_test_utils.h", "../browser/ui/views/frame/immersive_mode_tester.cc", @@ -2318,6 +2320,7 @@ "../browser/tpcd/heuristics/opener_heuristic_browsertest.cc", "../browser/tpcd/metadata/devtools_observer_browsertest.cc", "../browser/tpcd/metadata/updater_service_browsertest.cc", + "../browser/tpcd/support/top_level_trial_service_browsertest.cc", "../browser/tpcd/support/tpcd_support_browsertest.cc", # TODO(b/246519185) - Py3 incompatible, decide if to keep test. @@ -2765,7 +2768,6 @@ "../browser/ui/webui/chrome_url_data_manager_browsertest.cc", "../browser/ui/webui/chrome_web_ui_controller_factory_browsertest.cc", "../browser/ui/webui/chrome_webui_navigation_browsertest.cc", - "../browser/ui/webui/commander/commander_ui_browsertest.cc", "../browser/ui/webui/commerce/shopping_ui_handler_delegate_browsertest.cc", "../browser/ui/webui/constrained_web_dialog_ui_browsertest.cc", "../browser/ui/webui/extensions/extension_settings_browsertest.cc", @@ -6660,7 +6662,6 @@ "//chrome/browser/tpcd/heuristics:unit_tests", "//chrome/browser/ui:test_support", "//chrome/browser/ui/color:color_headers", - "//chrome/browser/ui/commander:fuzzy_finder", "//chrome/browser/updates/announcement_notification:unit_tests", "//chrome/browser/web_share_target:unit_tests", "//chrome/common:test_support", @@ -7156,8 +7157,6 @@ "../browser/ui/cocoa/profiles/profile_menu_controller_unittest.mm", "../browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_unittest.mm", "../browser/ui/cocoa/scoped_menu_bar_lock_unittest.mm", - "../browser/ui/cocoa/screentime/history_bridge_unittest.cc", - "../browser/ui/cocoa/screentime/screentime_tab_helper_unittest.mm", "../browser/ui/cocoa/status_icons/status_icon_mac_unittest.mm", "../browser/ui/cocoa/tab_menu_bridge_unittest.mm", "../browser/ui/cocoa/test/run_loop_testing_unittest.mm", @@ -7713,9 +7712,6 @@ "../browser/ui/color/chrome_color_provider_utils_unittest.cc", "../browser/ui/color/material_new_tab_page_color_mixer_unittest.cc", "../browser/ui/color/new_tab_page_color_mixer_unittest.cc", - "../browser/ui/commander/commander_controller_unittest.cc", - "../browser/ui/commander/entity_match_unittest.cc", - "../browser/ui/commander/fuzzy_finder_unittest.cc", "../browser/ui/commerce/commerce_ui_tab_helper_unittest.cc", "../browser/ui/commerce/price_tracking_page_action_controller_unittest.cc", "../browser/ui/content_settings/content_setting_bubble_model_unittest.cc", @@ -10460,7 +10456,6 @@ ":lacros_test_support_ui", "//chromeos/lacros", "//chromeos/lacros:test_support", - "//chromeos/startup:startup", "//components/account_manager_core", "//components/account_manager_core:test_support", ] @@ -10940,7 +10935,6 @@ "../browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_interactive_uitest.cc", "../browser/ui/views/browser_accelerator_interactive_uitest.cc", "../browser/ui/views/certificate_selector_browsertest.cc", - "../browser/ui/views/commander_frontend_views_browsertest.cc", "../browser/ui/views/commerce/price_insights_icon_view_interactive_uitest.cc", "../browser/ui/views/commerce/price_tracking_email_dialog_view_interactive_uitest.cc", "../browser/ui/views/commerce/price_tracking_icon_view_interactive_uitest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/WebApkIntentDataProviderBuilder.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/WebApkIntentDataProviderBuilder.java index edfbf361..ac1075e 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/WebApkIntentDataProviderBuilder.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/WebApkIntentDataProviderBuilder.java
@@ -10,6 +10,7 @@ import org.chromium.base.TimeUtils; import org.chromium.blink.mojom.DisplayMode; import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider; +import org.chromium.chrome.browser.browserservices.intents.WebappIcon; import org.chromium.chrome.browser.webapps.WebApkIntentDataProviderFactory; import org.chromium.components.webapps.ShortcutSource; import org.chromium.components.webapps.WebApkDistributor; @@ -18,6 +19,7 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.Map; /** Builder class for WebAPK {@link BrowserServicesIntentDataProvider} objects. */ public class WebApkIntentDataProviderBuilder { @@ -30,7 +32,10 @@ private String mManifestId; private String mName; private String mShortName; + private WebappIcon mPrimaryIcon; + private Map<String, String> mIconUrlToMurmur2HashMap = new HashMap<String, String>(); private long mToolbarColor; + private int mShellApkVersion = 1; public WebApkIntentDataProviderBuilder(String webApkPackageName, String url) { mWebApkPackageName = webApkPackageName; @@ -77,11 +82,19 @@ return this; } - private String manifestId() { - if (mManifestId == null) { - return mUrl; - } - return mManifestId; + public WebApkIntentDataProviderBuilder setPrimaryIcon(WebappIcon icon) { + mPrimaryIcon = icon; + return this; + } + + public WebApkIntentDataProviderBuilder setIconUrlToMurmur2HashMap(Map<String, String> hashmap) { + mIconUrlToMurmur2HashMap = hashmap; + return this; + } + + public WebApkIntentDataProviderBuilder setShellApkVersion(int shellApkVersion) { + mShellApkVersion = shellApkVersion; + return this; } /** Builds {@link BrowserServicesIntentDataProvider} object using options that have been set. */ @@ -90,7 +103,7 @@ new Intent(), mUrl, mScope, - null, + mPrimaryIcon, null, mName, mShortName, @@ -105,13 +118,13 @@ /* isPrimaryIconMaskable= */ false, /* isSplashIconMaskable= */ false, mWebApkPackageName, - /* shellApkVersion= */ 1, + mShellApkVersion, mManifestUrl, mUrl, - manifestId(), + mManifestId, /* appKey= */ null, WebApkDistributor.BROWSER, - /* iconUrlToMurmur2HashMap= */ new HashMap<String, String>(), + mIconUrlToMurmur2HashMap, null, /* forceNavigation= */ false, /* isSplashProvidedByWebApk= */ false,
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc index 32212a34..7fa234cb 100644 --- a/chrome/test/base/in_process_browser_test.cc +++ b/chrome/test/base/in_process_browser_test.cc
@@ -161,7 +161,6 @@ #include "chromeos/crosapi/mojom/crosapi.mojom.h" #include "chromeos/crosapi/mojom/test_controller.mojom-test-utils.h" #include "chromeos/lacros/lacros_service.h" -#include "chromeos/startup/browser_params_proxy.h" #include "components/account_manager_core/chromeos/account_manager.h" #include "components/account_manager_core/chromeos/account_manager_facade_factory.h" // nogncheck #include "components/account_manager_core/chromeos/fake_account_manager_ui.h" // nogncheck @@ -292,14 +291,18 @@ // Try to find a better name. bool WaitForWindowCreation(Browser* browser) { #if BUILDFLAG(IS_CHROMEOS_LACROS) - if (!chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { - CHECK(IsTestControllerAvailable()); + // TODO(crbug.com/1508245): Get rid of the IsTestControllerAvailable condition + // by making it always true (when crosapi is enabled). Moreover, propagate the + // WaitForWindowCreation return value. This requires fixing some tests that + // improperly override init params. + if (InProcessBrowserTest::IsCrosapiEnabled() && IsTestControllerAvailable()) { // Wait for window creation to complete in Ash in order to avoid // wayland-crosapi race conditions in subsequent test steps. aura::Window* window = browser->window()->GetNativeWindow(); std::string id = lacros_window_utility::GetRootWindowUniqueId(window->GetRootWindow()); - return browser_test_util::WaitForWindowCreation(id); + std::ignore = browser_test_util::WaitForWindowCreation(id); + return true; } #endif return true; @@ -352,6 +355,12 @@ MaybeGetAshAccountManagerUIForTests()); } +bool InProcessBrowserTest::IsCrosapiEnabled() { + return !base::CommandLine::ForCurrentProcess() + ->GetSwitchValuePath("lacros-mojo-socket-for-testing") + .empty(); +} + base::Version InProcessBrowserTest::GetAshChromeVersion() { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); base::FilePath ash_chrome_path = @@ -925,8 +934,7 @@ content::NetworkConnectionChangeSimulator network_change_simulator; network_change_simulator.InitializeChromeosConnectionType(); - if (!chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { - CHECK(IsTestControllerAvailable()); + if (IsCrosapiEnabled() && IsTestControllerAvailable()) { // There should NOT be any open ash browser window UI at this point. VerifyNoAshBrowserWindowOpenRightNow(); } @@ -1002,8 +1010,7 @@ CHECK(BrowserList::GetInstance()->empty()); #if BUILDFLAG(IS_CHROMEOS_LACROS) - if (!chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) { - CHECK(IsTestControllerAvailable()); + if (IsCrosapiEnabled() && IsTestControllerAvailable()) { // At this point, there should NOT be any ash browser UIs(e.g. SWA, etc) // open; otherwise, the tests running after the current one could be // polluted if the tests are running against the shared Ash (by default). @@ -1072,10 +1079,10 @@ const std::vector<std::string>& additional_cmdline_switches, const std::string& bug_number_and_reason) { DCHECK(!bug_number_and_reason.empty()); - CHECK(!chromeos::BrowserParamsProxy::IsCrosapiDisabledForTesting()) + base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); + CHECK(IsCrosapiEnabled()) << "You can only start unique ash chrome when crosapi is enabled. " << "It should not be necessary otherwise."; - base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); base::FilePath ash_dir_holder = cmdline->GetSwitchValuePath("unique-ash-dir"); CHECK(!ash_dir_holder.empty()); CHECK(unique_ash_user_data_dir_.CreateUniqueTempDirUnderPath(ash_dir_holder));
diff --git a/chrome/test/base/in_process_browser_test.h b/chrome/test/base/in_process_browser_test.h index 1e524c7c..e2a7a8d 100644 --- a/chrome/test/base/in_process_browser_test.h +++ b/chrome/test/base/in_process_browser_test.h
@@ -240,6 +240,9 @@ const std::string& bug_number_and_reason); #endif + // Returns true if crosapi is enabled for the test. + static bool IsCrosapiEnabled(); + protected: // Closes the given browser and waits for it to release all its resources. void CloseBrowserSynchronously(Browser* browser);
diff --git a/chrome/test/base/run_all_unittests.cc b/chrome/test/base/run_all_unittests.cc index 0ffedec..0c6e47b 100644 --- a/chrome/test/base/run_all_unittests.cc +++ b/chrome/test/base/run_all_unittests.cc
@@ -57,6 +57,10 @@ int main(int argc, char** argv) { base::PlatformThread::SetName("MainThread"); +#if BUILDFLAG(IS_CHROMEOS_LACROS) + chromeos::ScopedDisableCrosapiForTesting disable_crosapi; +#endif + content::UnitTestTestSuite test_suite( new ChromeUnitTestSuite(argc, argv), base::BindRepeating(CreateContentClients));
diff --git a/chrome/test/data/extensions/api_test/cookies/api/background.js b/chrome/test/data/extensions/api_test/cookies/api/background.js index 897c36e..a80568f 100644 --- a/chrome/test/data/extensions/api_test/cookies/api/background.js +++ b/chrome/test/data/extensions/api_test/cookies/api/background.js
@@ -47,68 +47,75 @@ }; var TEST_PARTITIONED_COOKIE = { - url: TEST_PARTITION_KEY, + url: TEST_URL4, name: 'PARTITIONEDCOOKIE', value: 'partitioned_cookie_val', expirationDate: TEST_EXPIRATION_DATE, secure: true, httpOnly: true, + path: '/', partitionKey: {topLevelSite: TEST_PARTITION_KEY} }; var TEST_PARTITIONED_COOKIE_SAME_KEY = { - url: TEST_PARTITION_KEY, + url: TEST_URL4, name: 'PARTITIONEDCOOKIE_SAME_KEY', value: 'partitioned_cookie_same_key', expirationDate: TEST_EXPIRATION_DATE, secure: true, httpOnly: true, + path: '/', partitionKey: {topLevelSite: TEST_PARTITION_KEY} }; var TEST_PARTITIONED_COOKIE_DIFFERENT_KEY = { - url: TEST_PARTITION_KEY, + url: TEST_URL4, name: 'PARTITIONED_COOKIE_DIFFERENT_KEY', value: 'partitioned_cookie_different_key', expirationDate: TEST_EXPIRATION_DATE, secure: true, httpOnly: true, + path: '/', partitionKey: {topLevelSite: TEST_URL5} }; var TEST_PARTITIONED_COOKIE_BASIC_COOKIE_NAME = { - url: TEST_PARTITION_KEY, + url: TEST_URL4, name: TEST_BASIC_COOKIE.name, value: 'TEST_PARTITIONED_COOKIE_BASIC_COOKIE_NAME', expirationDate: TEST_EXPIRATION_DATE, secure: true, httpOnly: true, + path: '/', partitionKey: {topLevelSite: TEST_PARTITION_KEY} }; var TEST_PARTITIONED_INVALID_PARTITION_KEY = { - url: TEST_PARTITION_KEY, + url: TEST_URL4, name: 'TEST_PARTITIONED_INVALID_PARTITION_KEY', value: 'TEST_PARTITIONED_INVALID_PARTITION_KEY', expirationDate: TEST_EXPIRATION_DATE, secure: true, httpOnly: true, + path: '/', partitionKey: {topLevelSite: 'TEST_PARTITIONED_INVALID_PARTITION_KEY'} }; var TEST_PARTITIONED_COOKIE_SECURE_FALSE = { - url: TEST_PARTITION_KEY, + url: TEST_URL, name: 'SECURE_FALSE', value: 'partitioned_cookie_val', expirationDate: TEST_EXPIRATION_DATE, secure: false, httpOnly: true, + path: '/', partitionKey: {topLevelSite: TEST_PARTITION_KEY} }; var TEST_PARTITIONED_COOKIE_OPAQUE_TOP_LEVEL_SITE = { - url: TEST_PARTITION_KEY, + url: TEST_URL4, name: 'OPAQUE_TOP_LEVEL_SITE', value: 'partitioned_cookie_val', expirationDate: TEST_EXPIRATION_DATE, secure: false, httpOnly: true, + path: '/', partitionKey: {topLevelSite: TEST_OPAQUE_URL} }; @@ -140,17 +147,17 @@ chrome.cookies.remove({url: TEST_URL, name: 'D'}); chrome.cookies.remove({url: TEST_ODD_URL, name: 'abcd'}); chrome.cookies.remove({ - url: TEST_PARTITIONED_COOKIE.url, + url: TEST_URL4, name: TEST_PARTITIONED_COOKIE.name, partitionKey: {topLevelSite: TEST_PARTITION_KEY} }); chrome.cookies.remove({ - url: TEST_PARTITIONED_COOKIE_SAME_KEY.url, + url: TEST_URL4, name: TEST_PARTITIONED_COOKIE_SAME_KEY.name, partitionKey: {topLevelSite: TEST_PARTITION_KEY} }); chrome.cookies.remove({ - url: TEST_PARTITIONED_COOKIE_DIFFERENT_KEY.url, + url: TEST_URL4, name: TEST_PARTITIONED_COOKIE_DIFFERENT_KEY.name, partitionKey: { topLevelSite: @@ -158,7 +165,7 @@ } }); chrome.cookies.remove({ - url: TEST_PARTITIONED_COOKIE_BASIC_COOKIE_NAME.url, + url: TEST_URL4, name: TEST_PARTITIONED_COOKIE_BASIC_COOKIE_NAME.name, partitionKey: { topLevelSite: @@ -166,9 +173,9 @@ } }); chrome.cookies.remove({ - url: TEST_PARTITIONED_COOKIE_DIFFERENT_KEY.url, + url: TEST_URL4, name: TEST_PARTITIONED_COOKIE_DIFFERENT_KEY.name, - partitionKey: TEST_PARTITIONED_COOKIE.partitionKey + partitionKey: TEST_PARTITIONED_COOKIE_DIFFERENT_KEY.partitionKey }); } var pass = chrome.test.callbackPass; @@ -333,7 +340,7 @@ chrome.test.assertEq(TEST_PARTITIONED_COOKIE.name, cookie.name); chrome.test.assertEq( TEST_PARTITIONED_COOKIE.value, cookie.value); - chrome.test.assertEq(TEST_DOMAIN, cookie.domain); + chrome.test.assertEq(TEST_HOST, cookie.domain); chrome.test.assertEq(true, cookie.hostOnly); chrome.test.assertEq('/', cookie.path); chrome.test.assertEq(true, cookie.secure); @@ -432,6 +439,21 @@ chrome.test.assertEq( TEST_PARTITIONED_COOKIE.name, cookies[0].name); })); + // Try supplying a URL, which causes implementation to take + // a different code path. + chrome.cookies.getAll( + { + url: TEST_PARTITIONED_COOKIE.url, + partitionKey: { + topLevelSite: + TEST_PARTITIONED_COOKIE.partitionKey.topLevelSite + } + }, + pass(function(cookies) { + chrome.test.assertEq(1, cookies.length); + chrome.test.assertEq( + TEST_PARTITIONED_COOKIE.name, cookies[0].name); + })); // Set another cookie with the same partition key as previous cookie // return both cookies by passing the common partition key. chrome.cookies.set(TEST_PARTITIONED_COOKIE_SAME_KEY); @@ -449,6 +471,23 @@ chrome.test.assertEq( TEST_PARTITIONED_COOKIE_SAME_KEY.name, cookies[1].name); })); + // Try supplying a URL, which causes implementation to take + // a different code path. + chrome.cookies.getAll( + { + url: TEST_PARTITIONED_COOKIE.url, + partitionKey: { + topLevelSite: + TEST_PARTITIONED_COOKIE.partitionKey.topLevelSite + } + }, + pass(function(cookies) { + chrome.test.assertEq(2, cookies.length); + chrome.test.assertEq( + TEST_PARTITIONED_COOKIE.name, cookies[0].name); + chrome.test.assertEq( + TEST_PARTITIONED_COOKIE_SAME_KEY.name, cookies[1].name); + })); // Set cookie with a different partition key than the previous // cookies. Ensure that only cookies with the original partition key // are returned. @@ -467,9 +506,26 @@ chrome.test.assertEq( TEST_PARTITIONED_COOKIE_SAME_KEY.name, cookies[1].name); })); + // Try supplying a URL, which causes implementation to take + // a different code path. + chrome.cookies.getAll( + { + url: TEST_PARTITIONED_COOKIE.url, + partitionKey: { + topLevelSite: + TEST_PARTITIONED_COOKIE.partitionKey.topLevelSite + } + }, + pass(function(cookies) { + chrome.test.assertEq(2, cookies.length); + chrome.test.assertEq( + TEST_PARTITIONED_COOKIE.name, cookies[0].name); + chrome.test.assertEq( + TEST_PARTITIONED_COOKIE_SAME_KEY.name, cookies[1].name); + })); // Set another unpartitioned cookie and check that only the previous // cookies with the common partition key are returned. - chrome.cookies.set(TEST_BASIC_COOKIE); + chrome.cookies.set(TEST_SECURE_COOKIE); chrome.cookies.getAll( { partitionKey: { @@ -484,14 +540,31 @@ chrome.test.assertEq( TEST_PARTITIONED_COOKIE_SAME_KEY.name, cookies[1].name); })); + // Try supplying a URL, which causes implementation to take + // a different code path. + chrome.cookies.getAll( + { + url: TEST_PARTITIONED_COOKIE.url, + partitionKey: { + topLevelSite: + TEST_PARTITIONED_COOKIE.partitionKey.topLevelSite + } + }, + pass(function(cookies) { + chrome.test.assertEq(2, cookies.length); + chrome.test.assertEq( + TEST_PARTITIONED_COOKIE.name, cookies[0].name); + chrome.test.assertEq( + TEST_PARTITIONED_COOKIE_SAME_KEY.name, cookies[1].name); + })); // Set another cookie with a name common to the previous cookie but // with a partition key. Confirm that the getAll call only returns // the cookie with no partition key chrome.cookies.set(TEST_PARTITIONED_COOKIE_BASIC_COOKIE_NAME); chrome.cookies.getAll( - {name: TEST_BASIC_COOKIE.name}, pass(function(cookies) { + {name: TEST_SECURE_COOKIE.name}, pass(function(cookies) { chrome.test.assertEq(1, cookies.length); - chrome.test.assertEq(TEST_BASIC_COOKIE.name, cookies[0].name); + chrome.test.assertEq(TEST_SECURE_COOKIE.name, cookies[0].name); chrome.test.assertEq(null, cookies[0].partitionKey); })); @@ -500,6 +573,13 @@ chrome.cookies.getAll({partitionKey: {}}, pass(function(cookies) { chrome.test.assertEq(5, cookies.length); })); + // Try supplying a URL, which causes implementation to take + // a different code path. + chrome.cookies.getAll( + {url: TEST_PARTITIONED_COOKIE.url, partitionKey: {}}, + pass(function(cookies) { + chrome.test.assertEq(5, cookies.length); + })); // Confirm that passing an undefined top level site, returns // cookies with and without partition keys. @@ -508,24 +588,55 @@ pass(function(cookies) { chrome.test.assertEq(5, cookies.length); })); + // Try supplying a URL, which causes implementation to take + // a different code path. + chrome.cookies.getAll( + { + url: TEST_PARTITIONED_COOKIE.url, + partitionKey: {topLevelSite: undefined} + }, + pass(function(cookies) { + chrome.test.assertEq(5, cookies.length); + })); // Confirm that passing an empty string for top level site, // returns unpartitioned cookies. chrome.cookies.getAll( {partitionKey: {topLevelSite: ''}}, pass(function(cookies) { chrome.test.assertEq(1, cookies.length); - chrome.test.assertEq(TEST_BASIC_COOKIE.name, cookies[0].name); + chrome.test.assertEq(TEST_SECURE_COOKIE.name, cookies[0].name); chrome.test.assertEq(null, cookies[0].partitionKey); })); + // Try supplying a URL, which causes implementation to take + // a different code path. + chrome.cookies.getAll( + { + url: TEST_PARTITIONED_COOKIE.url, + partitionKey: {topLevelSite: ''} + }, + pass(function(cookies) { + chrome.test.assertEq(1, cookies.length); + chrome.test.assertEq(TEST_SECURE_COOKIE.name, cookies[0].name); + chrome.test.assertEq(null, cookies[0].partitionKey); + })); // Confirm that passing an empty object will only get // cookies with no partition key. chrome.cookies.getAll( {}, pass(function(cookies) { chrome.test.assertEq(1, cookies.length); - chrome.test.assertEq(TEST_BASIC_COOKIE.name, cookies[0].name); + chrome.test.assertEq(TEST_SECURE_COOKIE.name, cookies[0].name); chrome.test.assertEq(null, cookies[0].partitionKey); })); + // Try supplying a URL, which causes implementation to take + // a different code path. + chrome.cookies.getAll( + {url: TEST_PARTITIONED_COOKIE.url}, pass(function(cookies) { + chrome.test.assertEq(1, cookies.length); + chrome.test.assertEq(TEST_SECURE_COOKIE.name, cookies[0].name); + chrome.test.assertEq(null, cookies[0].partitionKey); + })); + // Confirm callback fails when an invalid partition key is passed chrome.cookies.getAll( {
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 43daeda..e24734f 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -25,7 +25,6 @@ "access_code_cast/access_code_cast_browsertest.cc", "bookmarks/bookmarks_browsertest.cc", "chrome_timeticks_browsertest.cc", - "commander/commander_browsertest.cc", "commerce_internals/commerce_internals_browsertest.cc", "cr_components/cr_components_browsertest.cc", "cr_elements/cr_elements_browsertest.cc", @@ -344,7 +343,6 @@ ":build_ts", "access_code_cast:build_grdp", "bookmarks:build_grdp", - "commander:build_grdp", "commerce_internals:build_grdp", "cr_components:build_grdp", "cr_elements:build_grdp", @@ -389,7 +387,6 @@ "$target_gen_dir/access_code_cast/resources.grdp", "$target_gen_dir/bookmarks/resources.grdp", "$target_gen_dir/chai_resources.grdp", - "$target_gen_dir/commander/resources.grdp", "$target_gen_dir/commerce_internals/resources.grdp", "$target_gen_dir/cr_components/resources.grdp", "$target_gen_dir/cr_elements/resources.grdp",
diff --git a/chrome/test/data/webui/commander/BUILD.gn b/chrome/test/data/webui/commander/BUILD.gn deleted file mode 100644 index 37fed2b4..0000000 --- a/chrome/test/data/webui/commander/BUILD.gn +++ /dev/null
@@ -1,22 +0,0 @@ -# Copyright 2022 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("../build_webui_tests.gni") - -build_webui_tests("build") { - files = [ - "commander_app_test.ts", - "test_commander_browser_proxy.ts", - ] - - ts_path_mappings = - [ "chrome://commander/*|" + - rebase_path("$root_gen_dir/chrome/browser/resources/commander/tsc/*", - target_gen_dir) ] - ts_deps = [ - "//chrome/browser/resources/commander:build_ts", - "//third_party/polymer/v3_0:library", - "//ui/webui/resources/js:build_ts", - ] -}
diff --git a/chrome/test/data/webui/commander/OWNERS b/chrome/test/data/webui/commander/OWNERS deleted file mode 100644 index d7b99b6..0000000 --- a/chrome/test/data/webui/commander/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -file://chrome/browser/ui/commander/OWNERS
diff --git a/chrome/test/data/webui/commander/commander_app_test.ts b/chrome/test/data/webui/commander/commander_app_test.ts deleted file mode 100644 index 1f8941c5..0000000 --- a/chrome/test/data/webui/commander/commander_app_test.ts +++ /dev/null
@@ -1,266 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'chrome://commander/app.js'; - -import type {CommanderAppElement} from 'chrome://commander/app.js'; -import {BrowserProxyImpl} from 'chrome://commander/browser_proxy.js'; -import type {ViewModel} from 'chrome://commander/types.js'; -import {Action, Entity} from 'chrome://commander/types.js'; -import {webUIListenerCallback} from 'chrome://resources/js/cr.js'; -import {keyDownOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; -import {assertDeepEquals, assertEquals, assertGT, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; -import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; - -import {TestCommanderBrowserProxy} from './test_commander_browser_proxy.js'; - -suite('CommanderWebUIBrowserTest', () => { - let app: CommanderAppElement; - let testProxy: TestCommanderBrowserProxy; - - /** - * Creates a basic view model skeleton from the provided data. - * Populated with action = DISPLAY_RESULTS, and an option per each title - * in `titles` with entity = COMMAND and `matchedRanges` = [[0, 1]]. - * @param resultSetId The value of `resultSetId` in the view model. - * @param titles A list of option titles. - */ - function createStubViewModel( - resultSetId: number, titles: string[]): ViewModel { - const options = titles.map(title => ({ - title: title, - entity: Entity.COMMAND, - matchedRanges: [[0, 1]], - })); - return { - resultSetId: resultSetId, - options: options, - action: Action.DISPLAY_RESULTS, - }; - } - - /** - * Asserts that of the elements in `elements`, only the element at - * `focusedIndex` has class 'focused'. - * @param elements An ordered list of elements. - * @param focusedIndex The index at which the focused element is - * expected to appear. - */ - function assertFocused( - elements: NodeListOf<HTMLElement>, focusedIndex: number) { - assertGT(elements.length, 0); - Array.from(elements).forEach((element, index) => { - const isFocused = element.classList.contains('focused'); - const isAriaSelected = - element.getAttribute('aria-selected') === 'true' ? true : false; - assertEquals(index === focusedIndex, isFocused); - assertEquals(isFocused, isAriaSelected); - }); - } - - setup(async () => { - testProxy = new TestCommanderBrowserProxy(); - BrowserProxyImpl.setInstance(testProxy); - document.body.innerHTML = window.trustedTypes!.emptyHTML; - app = document.createElement('commander-app'); - document.body.appendChild(app); - await flushTasks(); - }); - - test('esc dismisses', () => { - assertEquals(0, testProxy.getCallCount('dismiss')); - const input = app.$.input; - keyDownOn(input, 0, [], 'Escape'); - - assertEquals(1, testProxy.getCallCount('dismiss')); - }); - - test('typing sends textChanged', async () => { - const expectedText = 'orange'; - const input = app.$.input; - input.value = expectedText; - input.dispatchEvent(new Event('input')); - - const actualText = await testProxy.whenCalled('textChanged'); - assertEquals(expectedText, actualText); - }); - - test('display results view model change renders options', async () => { - const titles = ['William of Orange', 'Orangutan', 'Orange Juice']; - webUIListenerCallback( - 'view-model-updated', createStubViewModel(42, titles)); - await flushTasks(); - - const optionElements = app.shadowRoot!.querySelectorAll('commander-option'); - assertEquals(titles.length, optionElements.length); - - const actualTitles = Array.from(optionElements).map(el => { - return Array - .from(el.shadowRoot!.querySelectorAll<HTMLElement>('.title-piece')) - .map(piece => piece.innerText) - .join(''); - }); - assertDeepEquals(titles, actualTitles); - }); - - test('display results view model change sends heightChanged', async () => { - testProxy.resetResolver('heightChanged'); - webUIListenerCallback('view-model-updated', createStubViewModel(42, [ - 'William of Orange', - 'Orangutan', - 'Orange Juice', - ])); - await flushTasks(); - const height = await testProxy.whenCalled('heightChanged'); - assertEquals(document.body.offsetHeight, height); - }); - - test('clicking option sends optionSelected', async () => { - const expectedResultSetId = 42; - webUIListenerCallback( - 'view-model-updated', createStubViewModel(expectedResultSetId, [ - 'William of Orange', - 'Orangutan', - 'Orange Juice', - ])); - await flushTasks(); - - const optionElements = app.shadowRoot!.querySelectorAll('commander-option'); - assertTrue(!!optionElements[1]); - optionElements[1].click(); - const [optionIndex, resultID] = - await testProxy.whenCalled('optionSelected'); - assertEquals(1, optionIndex); - assertEquals(expectedResultSetId, resultID); - }); - - test('first option selected by default', async () => { - webUIListenerCallback('view-model-updated', createStubViewModel(42, [ - 'William of Orange', - 'Orangutan', - 'Orange Juice', - ])); - await flushTasks(); - - const optionElements = app.shadowRoot!.querySelectorAll('commander-option'); - assertFocused(optionElements, 0); - }); - - test('no results view shown if no results', async () => { - assertEquals(null, app.shadowRoot!.querySelector('#noResults')); - app.$.input.value = 'A'; - webUIListenerCallback('view-model-updated', createStubViewModel(42, [])); - await flushTasks(); - - assertEquals( - 0, app.shadowRoot!.querySelectorAll('commander-option').length); - assertNotEquals(null, app.shadowRoot!.querySelector('#noResults')); - }); - - test('no results view not shown for empty input', async () => { - assertEquals(null, app.shadowRoot!.querySelector('#noResults')); - webUIListenerCallback('view-model-updated', createStubViewModel(42, [])); - await flushTasks(); - - assertEquals('', app.$.input.value); - assertEquals( - 0, app.shadowRoot!.querySelectorAll('commander-option').length); - assertEquals(null, app.shadowRoot!.querySelector('#noResults')); - }); - - test('arrow keys change selection', async () => { - const input = app.$.input; - webUIListenerCallback('view-model-updated', createStubViewModel(42, [ - 'William of Orange', - 'Orangutan', - 'Orange Juice', - ])); - await flushTasks(); - - const optionElements = app.shadowRoot!.querySelectorAll('commander-option'); - keyDownOn(input, 0, [], 'ArrowDown'); - assertFocused(optionElements, 1); - keyDownOn(input, 0, [], 'ArrowDown'); - assertFocused(optionElements, 2); - keyDownOn(input, 0, [], 'ArrowDown'); - assertFocused(optionElements, 0); - - keyDownOn(input, 0, [], 'ArrowUp'); - assertFocused(optionElements, 2); - keyDownOn(input, 0, [], 'ArrowUp'); - assertFocused(optionElements, 1); - keyDownOn(input, 0, [], 'ArrowUp'); - assertFocused(optionElements, 0); - }); - - test('return sends optionSelected', async () => { - const input = app.$.input; - const expectedResultSetId = 42; - webUIListenerCallback( - 'view-model-updated', createStubViewModel(expectedResultSetId, [ - 'William of Orange', - 'Orangutan', - 'Orange Juice', - ])); - await flushTasks(); - - keyDownOn(input, 0, [], 'Enter'); - const [optionIndex, resultID] = - await testProxy.whenCalled('optionSelected'); - assertEquals(0, optionIndex); - assertEquals(expectedResultSetId, resultID); - }); - - test('prompt view model draws chip', async () => { - const expectedPrompt = 'Select fruit'; - webUIListenerCallback( - 'view-model-updated', - {resultSetId: 42, action: Action.PROMPT, promptText: expectedPrompt}); - await flushTasks(); - - const chips = app.shadowRoot!.querySelectorAll<HTMLElement>('.chip'); - assertEquals(1, chips.length); - assertEquals(expectedPrompt, chips[0]!.innerText); - }); - - test('backspacing over chip cancels prompt', async () => { - const expectedPrompt = 'Select fruit'; - webUIListenerCallback( - 'view-model-updated', - {resultSetId: 42, action: Action.PROMPT, promptText: expectedPrompt}); - await flushTasks(); - - const input = app.$.input; - input.value = 'A'; - - // Backspace over text doesn't delete the chip. - keyDownOn(input, 0, [], 'Backspace'); - assertEquals(0, testProxy.getCallCount('promptCancelled')); - - input.value = ''; - keyDownOn(input, 0, [], 'Backspace'); - assertEquals(1, testProxy.getCallCount('promptCancelled')); - }); - - test('focusing options updates aria-activedescendant', async () => { - const input = app.$.input; - const inputRow = app.$.inputRow; - assertEquals(null, inputRow.getAttribute('aria-selected')); - - webUIListenerCallback('view-model-updated', createStubViewModel(42, [ - 'William of Orange', - 'Orangutan', - 'Orange Juice', - ])); - await flushTasks(); - - const optionElements = app.shadowRoot!.querySelectorAll('commander-option'); - assertEquals(3, optionElements.length); - assertEquals( - optionElements[0]!.id, inputRow.getAttribute('aria-activedescendant')); - keyDownOn(input, 0, [], 'ArrowDown'); - assertEquals( - optionElements[1]!.id, inputRow.getAttribute('aria-activedescendant')); - }); -});
diff --git a/chrome/test/data/webui/commander/commander_browsertest.cc b/chrome/test/data/webui/commander/commander_browsertest.cc deleted file mode 100644 index caed76d..0000000 --- a/chrome/test/data/webui/commander/commander_browsertest.cc +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/common/webui_url_constants.h" -#include "chrome/test/base/web_ui_mocha_browser_test.h" -#include "content/public/test/browser_test.h" - -using CommanderWebUIBrowserTest = WebUIMochaBrowserTest; - -IN_PROC_BROWSER_TEST_F(CommanderWebUIBrowserTest, All) { - set_test_loader_host(chrome::kChromeUICommanderHost); - RunTest("commander/commander_app_test.js", "mocha.run()"); -}
diff --git a/chrome/test/data/webui/commander/test_commander_browser_proxy.ts b/chrome/test/data/webui/commander/test_commander_browser_proxy.ts deleted file mode 100644 index 64d2f672..0000000 --- a/chrome/test/data/webui/commander/test_commander_browser_proxy.ts +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import type {BrowserProxy} from 'chrome://commander/browser_proxy.js'; -import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; - -export class TestCommanderBrowserProxy extends TestBrowserProxy implements - BrowserProxy { - constructor() { - super([ - 'textChanged', - 'optionSelected', - 'heightChanged', - 'dismiss', - 'promptCancelled', - ]); - } - - textChanged(newText: string) { - this.methodCalled('textChanged', newText); - } - - optionSelected(index: number, resultSetId: number) { - this.methodCalled('optionSelected', [index, resultSetId]); - } - - heightChanged(newHeight: number) { - this.methodCalled('heightChanged', newHeight); - } - - dismiss() { - this.methodCalled('dismiss'); - } - - promptCancelled() { - this.methodCalled('promptCancelled'); - } -}
diff --git a/chrome/test/data/webui/new_tab_page/modules/v2/tab_resumption/module_test.ts b/chrome/test/data/webui/new_tab_page/modules/v2/tab_resumption/module_test.ts index 81adc02..079bc6a 100644 --- a/chrome/test/data/webui/new_tab_page/modules/v2/tab_resumption/module_test.ts +++ b/chrome/test/data/webui/new_tab_page/modules/v2/tab_resumption/module_test.ts
@@ -3,13 +3,14 @@ // found in the LICENSE file. import type {Tab} from 'chrome://new-tab-page/history_types.mojom-webui.js'; -import type {TabResumptionModuleElement} from 'chrome://new-tab-page/lazy_load.js'; +import type {DismissModuleInstanceEvent, TabResumptionModuleElement} from 'chrome://new-tab-page/lazy_load.js'; import {tabResumptionDescriptor, TabResumptionProxyImpl} from 'chrome://new-tab-page/lazy_load.js'; import {$$} from 'chrome://new-tab-page/new_tab_page.js'; import {PageHandlerRemote} from 'chrome://new-tab-page/tab_resumption.mojom-webui.js'; import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; import type {TestMock} from 'chrome://webui-test/test_mock.js'; +import {eventToPromise} from 'chrome://webui-test/test_util.js'; import {installMock} from '../../../test_support.js'; @@ -84,11 +85,12 @@ const actionMenuItems = [...actionMenu.querySelectorAll('button.dropdown-item')]; - assertEquals(3, actionMenuItems.length); - ['disable', 'info', 'customize-module'].forEach((action, index) => { - assertEquals( - action, actionMenuItems[index]!.getAttribute('data-action')); - }); + assertEquals(4, actionMenuItems.length); + ['dismiss', 'disable', 'info', 'customize-module'].forEach( + (action, index) => { + assertEquals( + action, actionMenuItems[index]!.getAttribute('data-action')); + }); }); test('Header info button click opens info dialog', async () => { @@ -103,5 +105,27 @@ assertTrue(!!$$(moduleElement, 'ntp-info-dialog')); }); + + test('Header dismiss button dispatches dismiss module event', async () => { + // Arrange. + const moduleElement = await initializeModule(createSampleTabs(1)); + + // Assert. + assertTrue(!!moduleElement); + const headerElement = $$(moduleElement, 'ntp-module-header-v2'); + assertTrue(!!headerElement); + const waitForDismissEvent = + eventToPromise('dismiss-module-instance', moduleElement); + headerElement!.dispatchEvent(new Event('dismiss-button-click')); + + const dismissEvent: DismissModuleInstanceEvent = + await waitForDismissEvent; + assertEquals(`Tabs hidden`, dismissEvent.detail.message); + + // Act. + const restoreCallback = dismissEvent.detail.restoreCallback!; + restoreCallback(); + assertTrue(!!moduleElement); + }); }); });
diff --git a/chrome/test/data/webui/side_panel/read_anything/BUILD.gn b/chrome/test/data/webui/side_panel/read_anything/BUILD.gn index 29259ef..b7361482c 100644 --- a/chrome/test/data/webui/side_panel/read_anything/BUILD.gn +++ b/chrome/test/data/webui/side_panel/read_anything/BUILD.gn
@@ -10,6 +10,7 @@ is_chrome_untrusted = true files = [ "checkmark_visible_on_selected.ts", + "voice_selection_menu_test.ts", "fake_reading_mode.ts", ] @@ -20,5 +21,9 @@ ts_path_mappings = [ "chrome-untrusted://read-anything-side-panel.top-chrome/*|" + rebase_path( "$root_gen_dir/chrome/browser/resources/side_panel/read_anything/tsc/*", target_gen_dir) ] - ts_deps = [ "//chrome/browser/resources/side_panel/read_anything:build_ts" ] + ts_deps = [ + "//chrome/browser/resources/side_panel/read_anything:build_ts", + "//third_party/polymer/v3_0:library", + "//ui/webui/resources/cr_elements:build_ts", + ] }
diff --git a/chrome/test/data/webui/side_panel/read_anything/read_anything_browsertest.cc b/chrome/test/data/webui/side_panel/read_anything/read_anything_browsertest.cc index 81073fcde..7efb94b 100644 --- a/chrome/test/data/webui/side_panel/read_anything/read_anything_browsertest.cc +++ b/chrome/test/data/webui/side_panel/read_anything/read_anything_browsertest.cc
@@ -48,3 +48,8 @@ RunSidePanelTest("side_panel/read_anything/checkmark_visible_on_selected.js", "mocha.run()", SidePanelEntryId::kReadAnything); } + +IN_PROC_BROWSER_TEST_F(ReadAnythingMochaTest, VoiceSelectionMenu) { + RunSidePanelTest("side_panel/read_anything/voice_selection_menu_test.js", + "mocha.run()", SidePanelEntryId::kReadAnything); +}
diff --git a/chrome/test/data/webui/side_panel/read_anything/voice_selection_menu_test.ts b/chrome/test/data/webui/side_panel/read_anything/voice_selection_menu_test.ts new file mode 100644 index 0000000..a2db461b --- /dev/null +++ b/chrome/test/data/webui/side_panel/read_anything/voice_selection_menu_test.ts
@@ -0,0 +1,98 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome-untrusted://read-anything-side-panel.top-chrome/voice_selection_menu.js'; + +import type {CrIconButtonElement} from '//resources/cr_elements/cr_icon_button/cr_icon_button.js'; +import {flush} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import type {VoiceSelectionMenuElement} from 'chrome-untrusted://read-anything-side-panel.top-chrome/voice_selection_menu.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome-untrusted://webui-test/chai_assert.js'; + +suite('VoiceSelectionMenuElement', () => { + let voiceSelectionMenu: VoiceSelectionMenuElement; + let availableVoices: SpeechSynthesisVoice[]; + + const setAvailableVoices = () => { + // Bypass Typescript compiler to allow us to set a private readonly + // property + // @ts-ignore + voiceSelectionMenu.availableVoices = availableVoices; + flush(); + }; + + setup(() => { + document.body.innerHTML = window.trustedTypes!.emptyHTML; + voiceSelectionMenu = document.createElement('voice-selection-menu'); + document.body.appendChild(voiceSelectionMenu); + }); + + suite('with one voice', () => { + setup(() => { + availableVoices = [{name: 'test voice 1'} as SpeechSynthesisVoice]; + setAvailableVoices(); + }); + + test('it does not show dropdown before click', () => { + const dropdownItems: NodeListOf<HTMLElement> = + voiceSelectionMenu.$.voiceSelectionMenu + .querySelectorAll<HTMLButtonElement>('.dropdown-item'); + + assertFalse(isVisible(dropdownItems.item(0))); + }); + + test('it shows dropdown items after button click', () => { + const button = + voiceSelectionMenu.shadowRoot!.querySelector<CrIconButtonElement>( + '#voice-selection'); + button!.click(); + flush(); + + const dropdownItems: NodeListOf<HTMLElement> = + voiceSelectionMenu.$.voiceSelectionMenu + .querySelectorAll<HTMLButtonElement>('.dropdown-item'); + + assertTrue(isVisible(dropdownItems.item(0)!)); + assertEquals( + dropdownItems.item(0)!.textContent!.trim(), availableVoices[0]!.name); + }); + + suite('when availableVoices updates', () => { + setup(() => { + availableVoices = [ + {name: 'test voice 1'} as SpeechSynthesisVoice, + {name: 'test voice 2'} as SpeechSynthesisVoice, + ]; + setAvailableVoices(); + }); + + test('it updates and displays the new voices', () => { + const button = + voiceSelectionMenu.shadowRoot!.querySelector<CrIconButtonElement>( + '#voice-selection')!; + button!.click(); + flush(); + + const dropdownItems: NodeListOf<HTMLElement> = + voiceSelectionMenu.$.voiceSelectionMenu + .querySelectorAll<HTMLButtonElement>('.dropdown-item'); + + assertEquals( + dropdownItems.item(0)!.textContent!.trim(), + availableVoices[0]!.name); + assertEquals( + dropdownItems.item(1)!.textContent!.trim(), + availableVoices[1]!.name); + assertEquals(dropdownItems.length, 2); + assertTrue(isVisible(dropdownItems.item(0)!)); + assertTrue(isVisible(dropdownItems.item(1)!)); + }); + }); + }); +}); + +function isVisible(element: HTMLElement) { + return !!( + element.offsetWidth || element.offsetHeight || + element.getClientRects().length); +}
diff --git a/chrome/test/supervised_user/family_member.cc b/chrome/test/supervised_user/family_member.cc index 43ca042..0d2e0ec1 100644 --- a/chrome/test/supervised_user/family_member.cc +++ b/chrome/test/supervised_user/family_member.cc
@@ -40,12 +40,12 @@ return identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kSignin); } -std::string GetFamilyMemberSettingsUrlBase(FamilyMember& member) { +std::string GetFamilyMemberSettingsUrlBase(const FamilyMember& member) { return base::StrCat({"https://families.google.com/u/0/manage/family/child/", GetAccountId(member.browser()->profile()).ToString()}); } -GURL GetControlListUrlFor(FamilyMember& member, std::string_view page) { +GURL GetControlListUrlFor(const FamilyMember& member, std::string_view page) { return GURL(base::StrCat( {GetFamilyMemberSettingsUrlBase(member), "/exceptions/", page})); } @@ -63,15 +63,15 @@ add_tab_function) {} FamilyMember::~FamilyMember() = default; -GURL FamilyMember::GetBlockListUrlFor(FamilyMember& member) const { +GURL FamilyMember::GetBlockListUrlFor(const FamilyMember& member) const { return GetControlListUrlFor(member, "blocked"); } -GURL FamilyMember::GetAllowListUrlFor(FamilyMember& member) const { +GURL FamilyMember::GetAllowListUrlFor(const FamilyMember& member) const { return GetControlListUrlFor(member, "allowed"); } -GURL FamilyMember::GetPermissionsUrlFor(FamilyMember& member) const { +GURL FamilyMember::GetPermissionsUrlFor(const FamilyMember& member) const { return GURL( base::StrCat({GetFamilyMemberSettingsUrlBase(member), "/permissions"})); }
diff --git a/chrome/test/supervised_user/family_member.h b/chrome/test/supervised_user/family_member.h index 0868bcb58..85e5250 100644 --- a/chrome/test/supervised_user/family_member.h +++ b/chrome/test/supervised_user/family_member.h
@@ -30,9 +30,9 @@ // Urls of family member's blocklist and allowlist settings. Member must be a // supervised user who is a subject to parental controls. - GURL GetBlockListUrlFor(FamilyMember& member) const; - GURL GetAllowListUrlFor(FamilyMember& member) const; - GURL GetPermissionsUrlFor(FamilyMember& member) const; + GURL GetBlockListUrlFor(const FamilyMember& member) const; + GURL GetAllowListUrlFor(const FamilyMember& member) const; + GURL GetPermissionsUrlFor(const FamilyMember& member) const; // Browsertest apis expect pointer. Browser* browser() const { return &browser_.get(); }
diff --git a/chrome/updater/util/unit_test_util_unittest.cc b/chrome/updater/util/unit_test_util_unittest.cc index 946eabd..c6b24af 100644 --- a/chrome/updater/util/unit_test_util_unittest.cc +++ b/chrome/updater/util/unit_test_util_unittest.cc
@@ -13,16 +13,13 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/functional/function_ref.h" #include "base/logging.h" #include "base/path_service.h" #include "base/process/launch.h" #include "base/process/process.h" -#include "base/strings/strcat.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/synchronization/waitable_event.h" -#include "base/test/bind.h" #include "base/test/test_timeouts.h" #include "build/build_config.h" #include "chrome/updater/test/integration_tests_impl.h" @@ -42,17 +39,20 @@ namespace updater::test { namespace { -template <typename StringT> -std::string ToString(const StringT& s) { - if constexpr (std::is_same_v<StringT, std::wstring>) { - return base::WideToUTF8(s); - } else { - return s; - } +std::string ToString(const std::string& s) { + return s; +} + +std::string ToString(const std::wstring& s) { + return base::WideToUTF8(s); } } // namespace +TEST(UnitTestUtil, ToString) { + EXPECT_EQ(ToString("test"), ToString(L"test")); +} + TEST(UnitTestUtil, Processes) { auto print_processes_tester = [](const base::FilePath::StringType& process_name) {
diff --git a/chromeos/constants/devicetype_unittest.cc b/chromeos/constants/devicetype_unittest.cc index b9d8dd6..3c133311 100644 --- a/chromeos/constants/devicetype_unittest.cc +++ b/chromeos/constants/devicetype_unittest.cc
@@ -67,6 +67,7 @@ #if BUILDFLAG(IS_CHROMEOS_LACROS) TEST(DeviceTypeTest, GetDeviceTypeLacros) { base::test::TaskEnvironment task_environment; + chromeos::ScopedDisableCrosapiForTesting disable_crosapi; { auto params = crosapi::mojom::BrowserInitParams::New(); params->device_type =
diff --git a/chromeos/crosapi/mojom/test_controller.mojom b/chromeos/crosapi/mojom/test_controller.mojom index 24f30e5..bbd8ef8 100644 --- a/chromeos/crosapi/mojom/test_controller.mojom +++ b/chromeos/crosapi/mojom/test_controller.mojom
@@ -322,11 +322,17 @@ [MinVersion=1] kFocusHighlight = 4, }; +[Stable, Extensible] +enum SnapPosition { + [Default] kPrimary = 0, + kSecondary = 1, +}; + // This interface is implemented by Ash-Chrome. // This interface provides tests a mechanism to mutate or query ash. // In the future, this interface may merge with an automation or a11y interface. -// Next version: 32 -// Next method id: 46 +// Next version: 33 +// Next method id: 48 [Stable, Uuid="1f93f9d7-e466-466c-a675-c21b48cf30d3"] interface TestController { // Clicks the middle of the views element identified by |element_name|. @@ -574,4 +580,12 @@ // Checks if a toast with a given `toast_id` is shown. [MinVersion=31] IsToastShown@45(string toast_id) => (bool toast_shown); + + // Snaps the given window to the given position. + [MinVersion=32] + SnapWindow@46(string window_id, SnapPosition position) => (); + + // Checks whether the shelf is currently visible. + [MinVersion=32] + IsShelfVisible@47() => (bool visible); };
diff --git a/chromeos/lacros/lacros_service.cc b/chromeos/lacros/lacros_service.cc index f367afc0..3f3cbd67 100644 --- a/chromeos/lacros/lacros_service.cc +++ b/chromeos/lacros/lacros_service.cc
@@ -839,6 +839,9 @@ } std::optional<uint32_t> LacrosService::CrosapiVersion() const { + if (chromeos::BrowserParamsProxy::Get()->IsCrosapiDisabledForTesting()) { + return std::nullopt; + } DCHECK(did_bind_receiver_); return chromeos::BrowserParamsProxy::Get()->CrosapiVersion(); } @@ -862,6 +865,9 @@ } int LacrosService::GetInterfaceVersionImpl(base::Token interface_uuid) const { + if (chromeos::BrowserParamsProxy::Get()->IsCrosapiDisabledForTesting()) { + return -1; + } if (!chromeos::BrowserParamsProxy::Get()->InterfaceVersions()) { return -1; }
diff --git a/chromeos/lacros/lacros_test_helper.cc b/chromeos/lacros/lacros_test_helper.cc index 9c1d68a..ea4f517 100644 --- a/chromeos/lacros/lacros_test_helper.cc +++ b/chromeos/lacros/lacros_test_helper.cc
@@ -7,7 +7,7 @@ #include "base/check.h" #include "base/test/test_future.h" #include "chromeos/crosapi/mojom/test_controller.mojom-test-utils.h" -#include "chromeos/startup/browser_params_proxy.h" +#include "chromeos/startup/browser_init_params.h" namespace chromeos { namespace { @@ -28,10 +28,20 @@ } } // namespace -ScopedLacrosServiceTestHelper::ScopedLacrosServiceTestHelper() { - CHECK(BrowserParamsProxy::IsCrosapiDisabledForTesting()); +ScopedDisableCrosapiForTesting::ScopedDisableCrosapiForTesting() + : disable_crosapi_resetter_( + &BrowserInitParams::is_crosapi_disabled_for_testing_, + true) { + // Ensure that no instance exist, to prevent interference. + CHECK(!LacrosService::Get()); } +// TODO(crbug.com/1196314): Ensure that no instance exist on destruction, too. +// Currently, browser_tests' shutdown is an exception. +ScopedDisableCrosapiForTesting::~ScopedDisableCrosapiForTesting() = default; + +ScopedLacrosServiceTestHelper::ScopedLacrosServiceTestHelper() = default; + ScopedLacrosServiceTestHelper::~ScopedLacrosServiceTestHelper() = default; bool IsAshVersionAtLeastForTesting(base::Version required_version) {
diff --git a/chromeos/lacros/lacros_test_helper.h b/chromeos/lacros/lacros_test_helper.h index 143aa216..200cf90 100644 --- a/chromeos/lacros/lacros_test_helper.h +++ b/chromeos/lacros/lacros_test_helper.h
@@ -11,6 +11,22 @@ namespace chromeos { +// Disables crosapi while this instance is alive. +// This must be instantiate before LacrosService is instantiated. +// Used only for testing purposes. +class ScopedDisableCrosapiForTesting { + public: + ScopedDisableCrosapiForTesting(); + ScopedDisableCrosapiForTesting(const ScopedDisableCrosapiForTesting&) = + delete; + ScopedDisableCrosapiForTesting& operator=( + const ScopedDisableCrosapiForTesting&) = delete; + ~ScopedDisableCrosapiForTesting(); + + private: + base::AutoReset<bool> disable_crosapi_resetter_; +}; + // Helper for tests to instantiate LacrosService. This should only be // used for unit tests, not browser tests. // Instantiated LacrosService is expected to be accessed via @@ -24,6 +40,7 @@ ~ScopedLacrosServiceTestHelper(); private: + ScopedDisableCrosapiForTesting disable_crosapi_; LacrosService lacros_service_; };
diff --git a/chromeos/startup/README.md b/chromeos/startup/README.md index 97f5cf5..58a4cad 100644 --- a/chromeos/startup/README.md +++ b/chromeos/startup/README.md
@@ -14,34 +14,3 @@ directly. Instead, Lacros code should use `BrowserParamsProxy` which dispatches to either `BrowserInitParams` and `BrowserPostLoginParams` based on whether Lacros was prelaunched at login screen or not. - - -### `BrowserInitParams` in production vs. testing - -In production, Lacros is invoked by Ash with the -`--crosapi-mojo-platform-channel-handle` command line switch pointing to a file -descriptor. This causes Lacros to populate `BrowserInitParams` with Ash-provided -data read from the file. This happens whenever the `BrowserInitParams` are -queried for the first time. - -In testing where Lacros is not invoked by Ash (e.g. Lacros unit and browser -tests) there are two scenarios: - -1) Lacros is invoked without crosapi command line switch. Then - `BrowserInitParams` is created empty. This is the case for example for - `unit_tests` and `browser_tests`. Crosapi is thereby effectively disabled. - -2) Lacros is invoked with crosapi command line switch. Then `BrowserInitParams` - are read from Ash just as in production *unless* there's a call to - `DisableCrosapiForTesting`, in which case the behavior follows that in (1). - (An assertion ensures that `DisableCrosapiForTesting` is called before the - first query of `BrowserInitParams`, if at all). - - Detail: For technical reasons, the command line switch here is not - `--crosapi-mojo-platform-channel-handle` but - `--lacros-mojo-socket-for-testing`. The test runner passes a socket through - which `BrowserTestBase` then requests the - `--crosapi-mojo-platform-channel-handle` file descriptor from Ash. - -Only `lacros_chrome_browsertests` and Lacros `interactive_ui_tests` follow (2), -with only very few uses of `DisableCrosapiForTesting`.
diff --git a/chromeos/startup/browser_init_params.cc b/chromeos/startup/browser_init_params.cc index 841a6a9..f9ac18a9 100644 --- a/chromeos/startup/browser_init_params.cc +++ b/chromeos/startup/browser_init_params.cc
@@ -7,8 +7,6 @@ #include <optional> #include <string> -#include "base/check_is_test.h" -#include "base/command_line.h" #include "chromeos/startup/startup.h" namespace chromeos { @@ -34,47 +32,17 @@ } // namespace -std::optional<bool> BrowserInitParams::is_crosapi_enabled_; - -bool BrowserInitParams::IsCrosapiDisabledForTesting() { - return !IsCrosapiEnabled(); -} - -bool BrowserInitParams::IsCrosapiEnabled() { - if (is_crosapi_enabled_.has_value()) { - return *is_crosapi_enabled_; - } - - const base::CommandLine* command_line = - base::CommandLine::ForCurrentProcess(); - const bool enabled = - command_line->HasSwitch("crosapi-mojo-platform-channel-handle") || - command_line->HasSwitch("lacros-mojo-socket-for-testing"); - if (!enabled) { - CHECK_IS_TEST(); - } - is_crosapi_enabled_ = enabled; - return enabled; -} - -void BrowserInitParams::DisableCrosapiForTesting() { - CHECK_IS_TEST(); - CHECK(!is_crosapi_enabled_.has_value()) - << "You are calling DisableCrosapiForTesting too late."; - is_crosapi_enabled_ = false; -} - BrowserInitParams::BrowserInitParams() - : init_params_(IsCrosapiEnabled() - ? ReadStartupBrowserInitParams() - : crosapi::mojom::BrowserInitParams::New()) { - if (IsCrosapiEnabled()) { - CHECK(init_params_) << "crosapi is enabled but BrowserInitParams could not " - "be read. You are probably trying to get or set " - "the BrowserInitParams too early."; - CHECK(init_params_->ash_chrome_version); - } else { - CHECK(init_params_); + : init_params_(is_crosapi_disabled_for_testing_ + ? crosapi::mojom::BrowserInitParams::New() + : ReadStartupBrowserInitParams()) { + if (!init_params_) { + LOG(WARNING) << "BrowserInitParams is not set. " + << "This message should not appear except for testing. " + << "For testing, consider setting " + << "BrowserInitParams::is_crosapi_disabled_for_testing_ " + << "to true if crosapi is not required."; + init_params_ = crosapi::mojom::BrowserInitParams::New(); } } @@ -91,15 +59,6 @@ // static void BrowserInitParams::SetInitParamsForTests( crosapi::mojom::BrowserInitParamsPtr init_params) { - CHECK_IS_TEST(); - if (IsCrosapiEnabled()) { - CHECK(init_params); - CHECK(init_params->ash_chrome_version) - << "crosapi is enabled but the given BrowserInitParams is missing " - "essential data. Make sure to use " - "BrowserInitParams::GetForTests()->Clone() and customize that " - "instead of starting with an empty one"; - } GetInstance()->init_params_ = std::move(init_params); } @@ -116,4 +75,7 @@ return browser_init_params.get(); } +// static +bool BrowserInitParams::is_crosapi_disabled_for_testing_ = false; + } // namespace chromeos
diff --git a/chromeos/startup/browser_init_params.h b/chromeos/startup/browser_init_params.h index 1163c98..a2ab0f8 100644 --- a/chromeos/startup/browser_init_params.h +++ b/chromeos/startup/browser_init_params.h
@@ -32,23 +32,16 @@ // Create Mem FD from `init_params_`. static base::ScopedFD CreateStartupData(); - // This will always be false in production. - static bool IsCrosapiDisabledForTesting(); - - // Use sparingly. This should be needed only in exceptional cases. In - // particular, Lacros unit_tests and browser_tests have crosapi disabled by - // default and don't need to call this. - // - // This action cannot be undone, so it must be used only by tests that run in - // separate processes. (However, crosapi is only enabled in such tests - // anyways, hence this is not really a restriction.) - // - // See also README.md. - static void DisableCrosapiForTesting(); + static bool is_crosapi_disabled_for_testing() { + return is_crosapi_disabled_for_testing_; + } private: friend base::NoDestructor<BrowserInitParams>; + // Needs to access |is_crosapi_disabled_for_testing_|. + friend class ScopedDisableCrosapiForTesting; + // Needs to access |Get()|. friend class BrowserParamsProxy; @@ -65,11 +58,13 @@ BrowserInitParams(); ~BrowserInitParams(); - static bool IsCrosapiEnabled(); + // Tests will set this to |true| which will make all crosapi functionality + // unavailable. Should be set from ScopedDisableCrosapiForTesting always. + // TODO(https://crbug.com/1131722): Ideally we could stub this out or make + // this functional for tests without modifying production code + static bool is_crosapi_disabled_for_testing_; - static std::optional<bool> is_crosapi_enabled_; - - // Parameters passed from ash-chrome (unless crosapi is disabled). + // Parameters passed from ash-chrome. crosapi::mojom::BrowserInitParamsPtr init_params_; };
diff --git a/chromeos/startup/browser_params_proxy.cc b/chromeos/startup/browser_params_proxy.cc index f82aae8..e9ab362 100644 --- a/chromeos/startup/browser_params_proxy.cc +++ b/chromeos/startup/browser_params_proxy.cc
@@ -26,12 +26,8 @@ return BrowserPostLoginParams::IsLoggedIn(); } -bool BrowserParamsProxy::IsCrosapiDisabledForTesting() { - return BrowserInitParams::IsCrosapiDisabledForTesting(); -} - -void BrowserParamsProxy::DisableCrosapiForTesting() { - return BrowserInitParams::DisableCrosapiForTesting(); +bool BrowserParamsProxy::IsCrosapiDisabledForTesting() const { + return BrowserInitParams::is_crosapi_disabled_for_testing(); } uint32_t BrowserParamsProxy::CrosapiVersion() const {
diff --git a/chromeos/startup/browser_params_proxy.h b/chromeos/startup/browser_params_proxy.h index 961e542..171d87f 100644 --- a/chromeos/startup/browser_params_proxy.h +++ b/chromeos/startup/browser_params_proxy.h
@@ -25,11 +25,8 @@ // Returns true if the user has logged in, false if not. static bool IsLoggedIn(); - // See documentation in browser_init_params.h. - static bool IsCrosapiDisabledForTesting(); - static void DisableCrosapiForTesting(); - // Init and post-login parameters' accessors are listed starting from here. + bool IsCrosapiDisabledForTesting() const; uint32_t CrosapiVersion() const;
diff --git a/clank b/clank index 80915fa..401e3e3 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 80915fa76a95b7fb3ba6db65df700a789109350f +Subproject commit 401e3e3bf126ea139d5680c5a16e9e0fe51cd0c6
diff --git a/components/android_autofill/browser/junit/BUILD.gn b/components/android_autofill/browser/junit/BUILD.gn index ddf40d5..2c006ce 100644 --- a/components/android_autofill/browser/junit/BUILD.gn +++ b/components/android_autofill/browser/junit/BUILD.gn
@@ -9,6 +9,7 @@ sources = [ "src/org/chromium/components/autofill/AutofillProviderTest.java", "src/org/chromium/components/autofill/AutofillRequestTest.java", + "src/org/chromium/components/autofill/AutofillSessionUMATest.java", "src/org/chromium/components/autofill/FormDataTest.java", "src/org/chromium/components/autofill/PrefillRequestTest.java", ] @@ -18,6 +19,7 @@ "//components/android_autofill/browser:features_java", "//components/android_autofill/browser:java", "//components/android_autofill/browser/test_support:java", + "//components/autofill/core/common/mojom:mojo_types_java", "//content/public/android:content_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/jni_zero:jni_zero_java",
diff --git a/components/android_autofill/browser/junit/src/org/chromium/components/autofill/AutofillSessionUMATest.java b/components/android_autofill/browser/junit/src/org/chromium/components/autofill/AutofillSessionUMATest.java new file mode 100644 index 0000000..0aa918b8 --- /dev/null +++ b/components/android_autofill/browser/junit/src/org/chromium/components/autofill/AutofillSessionUMATest.java
@@ -0,0 +1,241 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.autofill; + +import android.content.Context; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.robolectric.annotation.Config; + +import org.chromium.autofill.mojom.SubmissionSource; +import org.chromium.base.test.params.BlockJUnit4RunnerDelegate; +import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter; +import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; +import org.chromium.base.test.params.ParameterProvider; +import org.chromium.base.test.params.ParameterSet; +import org.chromium.base.test.params.ParameterizedRunner; +import org.chromium.base.test.util.HistogramWatcher; + +import java.util.Arrays; +import java.util.List; + +/** + * Tests that the "Autofill.WebView.AutofillSession(WithBottomSheet)" histograms are recorded + * correctly inside `AutofillProviderUMA`. + */ +@RunWith(ParameterizedRunner.class) +@UseRunnerDelegate(BlockJUnit4RunnerDelegate.class) +@Config(manifest = Config.NONE) +public class AutofillSessionUMATest { + private static final String NO_SUGGESTION = "NO_SUGGESTION"; + private static final String USER_SELECT_SUGGESTION = "USER_SELECT_SUGGESTION"; + private static final String USER_NOT_SELECT_SUGGESTION = "USER_NOT_SELECT_SUGGESTION"; + + /** Testing parameters. */ + public static class AutofillSessionParams implements ParameterProvider { + private static List<ParameterSet> sParams = + Arrays.asList( + new ParameterSet().value(NO_SUGGESTION).name(NO_SUGGESTION), + new ParameterSet() + .value(USER_SELECT_SUGGESTION) + .name(USER_SELECT_SUGGESTION), + new ParameterSet() + .value(USER_NOT_SELECT_SUGGESTION) + .name(USER_NOT_SELECT_SUGGESTION)); + + @Override + public List<ParameterSet> getParameters() { + return sParams; + } + } + + private AutofillProviderUMA mAutofillUMA; + private Context mContext; + + @Before + public void setUp() { + mContext = Mockito.mock(Context.class); + mAutofillUMA = + new AutofillProviderUMA( + mContext, /* isAwGCurrentAutofillService= */ true, /* packageName= */ ""); + } + + /** Tests that the "*_USER_CHANGE_FORM_FORM_SUBMITTED" buckets are emitted. */ + @Test + @UseMethodParameter(AutofillSessionParams.class) + public void testUserChangeFormFormSubmitted(String suggestionInteractionType) { + mAutofillUMA.onSessionStarted(/* autofillDisabled= */ false); + mAutofillUMA.onBottomSheetShown(); + + int histogramBucket = 0; + switch (suggestionInteractionType) { + case NO_SUGGESTION: + histogramBucket = AutofillProviderUMA.NO_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED; + break; + case USER_SELECT_SUGGESTION: + histogramBucket = + AutofillProviderUMA.USER_SELECT_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED; + mAutofillUMA.onSuggestionDisplayed(/* suggestionTimeMillis= */ 0); + mAutofillUMA.onAutofill(); + break; + case USER_NOT_SELECT_SUGGESTION: + histogramBucket = + AutofillProviderUMA + .USER_NOT_SELECT_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED; + mAutofillUMA.onSuggestionDisplayed(/* suggestionTimeMillis= */ 0); + break; + default: + assert false; // NOTREACHED() + break; + } + + HistogramWatcher histogramWatcher = + HistogramWatcher.newBuilder() + .expectIntRecord( + AutofillProviderUMA.UMA_AUTOFILL_AUTOFILL_SESSION, histogramBucket) + .expectIntRecord( + AutofillProviderUMA.UMA_AUTOFILL_AUTOFILL_SESSION_WITH_BOTTOM_SHEET, + histogramBucket) + .build(); + mAutofillUMA.onUserChangeFieldValue(/* isPreviouslyAutofilled= */ false); + mAutofillUMA.onFormSubmitted( + SubmissionSource.FORM_SUBMISSION, /* autofillDisabled= */ false); + histogramWatcher.assertExpected(); + } + + /** Tests that the "*_USER_CHANGE_FORM_NO_FORM_SUBMITTED" buckets are emitted. */ + @Test + @UseMethodParameter(AutofillSessionParams.class) + public void testUserChangeFormNoFormSubmitted(String suggestionInteractionType) { + mAutofillUMA.onSessionStarted(/* autofillDisabled= */ false); + mAutofillUMA.onBottomSheetShown(); + + int histogramBucket = 0; + switch (suggestionInteractionType) { + case NO_SUGGESTION: + histogramBucket = + AutofillProviderUMA.NO_SUGGESTION_USER_CHANGE_FORM_NO_FORM_SUBMITTED; + break; + case USER_SELECT_SUGGESTION: + histogramBucket = + AutofillProviderUMA + .USER_SELECT_SUGGESTION_USER_CHANGE_FORM_NO_FORM_SUBMITTED; + mAutofillUMA.onSuggestionDisplayed(/* suggestionTimeMillis= */ 0); + mAutofillUMA.onAutofill(); + break; + case USER_NOT_SELECT_SUGGESTION: + histogramBucket = + AutofillProviderUMA + .USER_NOT_SELECT_SUGGESTION_USER_CHANGE_FORM_NO_FORM_SUBMITTED; + mAutofillUMA.onSuggestionDisplayed(/* suggestionTimeMillis= */ 0); + break; + default: + assert false; // NOTREACHED() + break; + } + + HistogramWatcher histogramWatcher = + HistogramWatcher.newBuilder() + .expectIntRecord( + AutofillProviderUMA.UMA_AUTOFILL_AUTOFILL_SESSION, histogramBucket) + .expectIntRecord( + AutofillProviderUMA.UMA_AUTOFILL_AUTOFILL_SESSION_WITH_BOTTOM_SHEET, + histogramBucket) + .build(); + mAutofillUMA.onUserChangeFieldValue(/* isPreviouslyAutofilled= */ false); + mAutofillUMA.recordSession(/* autofillDisabled= */ false); + histogramWatcher.assertExpected(); + } + + /** Tests that the "*_USER_NOT_CHANGE_FORM_FORM_SUBMITTED" buckets are emitted. */ + @Test + @UseMethodParameter(AutofillSessionParams.class) + public void testUserNotChangeFormFormSubmitted(String suggestionInteractionType) { + mAutofillUMA.onSessionStarted(/* autofillDisabled= */ false); + mAutofillUMA.onBottomSheetShown(); + + int histogramBucket = 0; + switch (suggestionInteractionType) { + case NO_SUGGESTION: + histogramBucket = + AutofillProviderUMA.NO_SUGGESTION_USER_NOT_CHANGE_FORM_FORM_SUBMITTED; + break; + case USER_SELECT_SUGGESTION: + histogramBucket = + AutofillProviderUMA + .USER_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_FORM_SUBMITTED; + mAutofillUMA.onSuggestionDisplayed(/* suggestionTimeMillis= */ 0); + mAutofillUMA.onAutofill(); + break; + case USER_NOT_SELECT_SUGGESTION: + histogramBucket = + AutofillProviderUMA + .USER_NOT_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_FORM_SUBMITTED; + mAutofillUMA.onSuggestionDisplayed(/* suggestionTimeMillis= */ 0); + break; + default: + assert false; // NOTREACHED() + break; + } + + HistogramWatcher histogramWatcher = + HistogramWatcher.newBuilder() + .expectIntRecord( + AutofillProviderUMA.UMA_AUTOFILL_AUTOFILL_SESSION, histogramBucket) + .expectIntRecord( + AutofillProviderUMA.UMA_AUTOFILL_AUTOFILL_SESSION_WITH_BOTTOM_SHEET, + histogramBucket) + .build(); + mAutofillUMA.onFormSubmitted( + SubmissionSource.FORM_SUBMISSION, /* autofillDisabled= */ false); + histogramWatcher.assertExpected(); + } + + /** Tests that the "*_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED" buckets are emitted. */ + @Test + @UseMethodParameter(AutofillSessionParams.class) + public void testUserNotChangeFormNoFormSubmitted(String suggestionInteractionType) { + mAutofillUMA.onSessionStarted(/* autofillDisabled= */ false); + mAutofillUMA.onBottomSheetShown(); + + int histogramBucket = 0; + switch (suggestionInteractionType) { + case NO_SUGGESTION: + histogramBucket = + AutofillProviderUMA.NO_SUGGESTION_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED; + break; + case USER_SELECT_SUGGESTION: + histogramBucket = + AutofillProviderUMA + .USER_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED; + mAutofillUMA.onSuggestionDisplayed(/* suggestionTimeMillis= */ 0); + mAutofillUMA.onAutofill(); + break; + case USER_NOT_SELECT_SUGGESTION: + histogramBucket = + AutofillProviderUMA + .USER_NOT_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED; + mAutofillUMA.onSuggestionDisplayed(/* suggestionTimeMillis= */ 0); + break; + default: + assert false; // NOTREACHED() + break; + } + + HistogramWatcher histogramWatcher = + HistogramWatcher.newBuilder() + .expectIntRecord( + AutofillProviderUMA.UMA_AUTOFILL_AUTOFILL_SESSION, histogramBucket) + .expectIntRecord( + AutofillProviderUMA.UMA_AUTOFILL_AUTOFILL_SESSION_WITH_BOTTOM_SHEET, + histogramBucket) + .build(); + mAutofillUMA.recordSession(/* autofillDisabled= */ false); + histogramWatcher.assertExpected(); + } +}
diff --git a/components/browser_ui/strings/android/site_settings.grdp b/components/browser_ui/strings/android/site_settings.grdp index 4c626774..aa8aa601 100644 --- a/components/browser_ui/strings/android/site_settings.grdp +++ b/components/browser_ui/strings/android/site_settings.grdp
@@ -80,7 +80,7 @@ Microphone </message> <message name="IDS_MIDI_SYSEX_PERMISSION_TITLE" desc="Title of the permission that allows a website to get full control of MIDI devices [CHAR_LIMIT=32]"> - MIDI device control / reprogram + MIDI device control & reprogram </message> <message name="IDS_MOTION_SENSORS_PERMISSION_TITLE" desc="Title of the permission to use device's motion sensors (accelerometer, gyroscope, magnetometer) [CHAR_LIMIT=32]"> Motion sensors
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_MIDI_SYSEX_PERMISSION_TITLE.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_MIDI_SYSEX_PERMISSION_TITLE.png.sha1 index bd02d639..e42b7f9 100644 --- a/components/browser_ui/strings/android/site_settings_grdp/IDS_MIDI_SYSEX_PERMISSION_TITLE.png.sha1 +++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_MIDI_SYSEX_PERMISSION_TITLE.png.sha1
@@ -1 +1 @@ -2e6dacf067069dd4e37f196d27a9377bbc5d604a \ No newline at end of file +010d8ea2185e6904c1bc3aceaca86ab48541486a \ No newline at end of file
diff --git a/components/compose/core/browser/compose_features.cc b/components/compose/core/browser/compose_features.cc index 5ded57c..9154ced 100644 --- a/components/compose/core/browser/compose_features.cc +++ b/components/compose/core/browser/compose_features.cc
@@ -48,4 +48,9 @@ BASE_FEATURE(kComposeUiParams, "ComposeUiParams", base::FEATURE_DISABLED_BY_DEFAULT); + +BASE_FEATURE(kComposeTextOutputAnimation, + "ComposeTextOutputAnimation", + base::FEATURE_DISABLED_BY_DEFAULT); + } // namespace compose::features
diff --git a/components/compose/core/browser/compose_features.h b/components/compose/core/browser/compose_features.h index 7d8922c4..3b9da9a 100644 --- a/components/compose/core/browser/compose_features.h +++ b/components/compose/core/browser/compose_features.h
@@ -44,6 +44,9 @@ // Controls parameters around UI rendering. BASE_DECLARE_FEATURE(kComposeUiParams); +// Enables animation of text output. Applies only to on-device evaluation. +BASE_DECLARE_FEATURE(kComposeTextOutputAnimation); + } // namespace compose::features #endif // COMPONENTS_COMPOSE_CORE_BROWSER_COMPOSE_FEATURES_H_
diff --git a/components/cronet/android/cronet_combined_impl_native_proguard_golden.cfg b/components/cronet/android/cronet_combined_impl_native_proguard_golden.cfg index 6fba4cd7..d806dbff 100644 --- a/components/cronet/android/cronet_combined_impl_native_proguard_golden.cfg +++ b/components/cronet/android/cronet_combined_impl_native_proguard_golden.cfg
@@ -5,18 +5,9 @@ # Contains flags that can be safely shared with Cronet, and thus would be # appropriate for third-party apps to include. -# -# IMPORTANT: MAKE SURE ALL RULES IN THIS FILE ARE ADEQUATELY SCOPED TO ONLY -# AFFECT CHROMIUM CODE (typically that means the rule should have a restriction -# on something under `org.chromium`). These rules are shipped in Cronet which is -# a library used by a variety of downstream apps. ProGuard operates at the app -# level, not the library level. It doesn't automatically scope rules shipped -# in libraries. In other words: when downstream apps run ProGuard, these rules -# will be applied to their entire app. It is our responsibility to ensure the -# rules we ship in this way don't end up affecting code that is not ours. # Allow unused native methods to be removed, but prevent renaming on those that are kept. --keepclasseswithmembernames,includedescriptorclasses,allowaccessmodification class !cr_allowunused,org.chromium.base.library_loader.LinkerJni { +-keepclasseswithmembernames,includedescriptorclasses,allowaccessmodification class !cr_allowunused,** { native <methods>; } @@ -228,8 +219,3 @@ -keepclasseswithmembers,includedescriptorclasses,allowaccessmodification class ** { @org.jni_zero.CalledByNativeUnchecked <methods>; } - -# Allow unused native methods to be removed, but prevent renaming on those that are kept. --keepclasseswithmembernames,includedescriptorclasses,allowaccessmodification class org.jni_zero.*,J.N,J.*_N { - native <methods>; -}
diff --git a/components/enterprise/data_controls/action_context.h b/components/enterprise/data_controls/action_context.h index 6f67e4d5..8a65050c 100644 --- a/components/enterprise/data_controls/action_context.h +++ b/components/enterprise/data_controls/action_context.h
@@ -24,6 +24,11 @@ // Chrome tabs. This field is only used for clipboard interactions, and as // such defaults to "false". bool os_clipboard = false; + + // Indicates that the source of the data is a separate Chrome profile from the + // one receiving that data. This field is only used for clipboard + // interactions, and as such defaults to "false". + bool other_profile = false; }; struct ActionDestination { @@ -42,6 +47,13 @@ // interactions, and as such defaults to "false". bool os_clipboard = false; + // Indicates that the destination of the data is a separate Chrome profile + // from the one providing that data. As such, this should only be set to + // "true" for tab-to-tab clipboard interactions, destinations like the OS + // clipboard are not considered a separate profile. This field is only used + // for clipboard interactions, and as such defaults to "false". + bool other_profile = false; + #if BUILDFLAG(IS_CHROMEOS) Component component = Component::kUnknownComponent; #endif // BUILDFLAG(IS_CHROMEOS)
diff --git a/components/enterprise/data_controls/attributes_condition.cc b/components/enterprise/data_controls/attributes_condition.cc index e22bb9f..f336bb2 100644 --- a/components/enterprise/data_controls/attributes_condition.cc +++ b/components/enterprise/data_controls/attributes_condition.cc
@@ -34,6 +34,7 @@ incognito_ = value.FindBool(kKeyIncognito); os_clipboard_ = value.FindBool(kKeyOsClipboard); + other_profile_ = value.FindBool(kKeyOtherProfile); #if BUILDFLAG(IS_CHROMEOS) const base::Value::List* components_value = value.FindList(kKeyComponents); @@ -58,7 +59,8 @@ bool AttributesCondition::IsValid() const { bool valid = (url_matcher_ && !url_matcher_->IsEmpty()) || - incognito_.has_value() || os_clipboard_.has_value(); + incognito_.has_value() || os_clipboard_.has_value() || + other_profile_.has_value(); #if BUILDFLAG(IS_CHROMEOS) valid |= !components_.empty(); #endif // BUILDFLAG(IS_CHROMEOS) @@ -107,6 +109,14 @@ return os_clipboard == os_clipboard_.value(); } +bool AttributesCondition::OtherProfileMatches(bool other_profile) const { + if (!other_profile_.has_value()) { + return true; + } + + return other_profile == other_profile_.value(); +} + bool AttributesCondition::is_os_clipboard_condition() const { return os_clipboard_.has_value(); } @@ -140,10 +150,9 @@ return OsClipboardMatches(action_context.source.os_clipboard); } - if (!IncognitoMatches(action_context.source.incognito)) { - return false; - } - return URLMatches(action_context.source.url); + return IncognitoMatches(action_context.source.incognito) && + OtherProfileMatches(action_context.source.other_profile) && + URLMatches(action_context.source.url); } SourceAttributesCondition::SourceAttributesCondition( @@ -184,15 +193,12 @@ return OsClipboardMatches(action_context.destination.os_clipboard); } - if (!IncognitoMatches(action_context.destination.incognito)) { - return false; - } + return IncognitoMatches(action_context.destination.incognito) && + OtherProfileMatches(action_context.destination.other_profile) && #if BUILDFLAG(IS_CHROMEOS) - if (!ComponentMatches(action_context.destination.component)) { - return false; - } + ComponentMatches(action_context.destination.component) && #endif - return URLMatches(action_context.destination.url); + URLMatches(action_context.destination.url); } DestinationAttributesCondition::DestinationAttributesCondition(
diff --git a/components/enterprise/data_controls/attributes_condition.h b/components/enterprise/data_controls/attributes_condition.h index 1931445..09deedbd 100644 --- a/components/enterprise/data_controls/attributes_condition.h +++ b/components/enterprise/data_controls/attributes_condition.h
@@ -38,6 +38,7 @@ static constexpr char kKeyUrls[] = "urls"; static constexpr char kKeyIncognito[] = "incognito"; static constexpr char kKeyOsClipboard[] = "os_clipboard"; + static constexpr char kKeyOtherProfile[] = "other_profile"; #if BUILDFLAG(IS_CHROMEOS) static constexpr char kKeyComponents[] = "components"; #endif // BUILDFLAG(IS_CHROMEOS) @@ -65,6 +66,7 @@ // corresponding conditions. bool IncognitoMatches(bool incognito) const; bool OsClipboardMatches(bool os_clipboard) const; + bool OtherProfileMatches(bool other_profile) const; // Helpers to help check which attributes are meaningful to the condition. bool is_os_clipboard_condition() const; @@ -83,6 +85,10 @@ // the OS clipboard. It is always null for non-clipboard conditions. std::optional<bool> os_clipboard_; + // This attribute indicates the destination/source condition must/mustn't be + // a separate Chrome profile. It is always null for non-clipboard conditions. + std::optional<bool> other_profile_; + #if BUILDFLAG(IS_CHROMEOS) // A destination/source must be in this set to pass the condition, unless the // set is empty. @@ -97,6 +103,7 @@ static std::unique_ptr<Condition> Create(const base::Value& value); static std::unique_ptr<Condition> Create(const base::Value::Dict& value); + // data_controls::Condition: bool IsTriggered(const ActionContext& action_context) const override; private: @@ -113,6 +120,7 @@ static std::unique_ptr<Condition> Create(const base::Value& value); static std::unique_ptr<Condition> Create(const base::Value::Dict& value); + // data_controls::Condition: bool IsTriggered(const ActionContext& action_context) const override; private:
diff --git a/components/enterprise/data_controls/attributes_condition_unittest.cc b/components/enterprise/data_controls/attributes_condition_unittest.cc index d78e572..c7b7f5d 100644 --- a/components/enterprise/data_controls/attributes_condition_unittest.cc +++ b/components/enterprise/data_controls/attributes_condition_unittest.cc
@@ -51,6 +51,10 @@ CreateDict(R"({"os_clipboard": "str"})"))); ASSERT_FALSE(SourceAttributesCondition::Create( CreateDict(R"({"os_clipboard": 1234})"))); + ASSERT_FALSE(SourceAttributesCondition::Create( + CreateDict(R"({"other_profile": "str"})"))); + ASSERT_FALSE(SourceAttributesCondition::Create( + CreateDict(R"({"other_profile": 1234})"))); #if BUILDFLAG(IS_CHROMEOS) ASSERT_FALSE(SourceAttributesCondition::Create( CreateDict(R"({"urls": "https://foo.com", "components": "ARC"})"))); @@ -117,6 +121,10 @@ CreateDict(R"({"os_clipboard": "str"})"))); ASSERT_FALSE(DestinationAttributesCondition::Create( CreateDict(R"({"os_clipboard": 1234})"))); + ASSERT_FALSE(DestinationAttributesCondition::Create( + CreateDict(R"({"other_profile": "str"})"))); + ASSERT_FALSE(DestinationAttributesCondition::Create( + CreateDict(R"({"other_profile": 1234})"))); #if BUILDFLAG(IS_CHROMEOS) ASSERT_FALSE(DestinationAttributesCondition::Create( CreateDict(R"({"urls": "https://foo.com", "components": "ARC"})"))); @@ -471,6 +479,277 @@ ASSERT_FALSE(any_url->IsTriggered({.source = {}})); } +TEST(AttributesConditionTest, OtherProfileDestination) { + auto other_profile_dst = DestinationAttributesCondition::Create(CreateDict(R"( + { + "other_profile": true, + })")); + ASSERT_TRUE(other_profile_dst); + ASSERT_TRUE( + other_profile_dst->IsTriggered({.destination = {.other_profile = true}})); + ASSERT_FALSE(other_profile_dst->IsTriggered( + {.destination = {.other_profile = false}})); + ASSERT_FALSE( + other_profile_dst->IsTriggered({.source = {.other_profile = true}})); + ASSERT_FALSE( + other_profile_dst->IsTriggered({.source = {.other_profile = false}})); + + auto non_other_profile_dst = + DestinationAttributesCondition::Create(CreateDict(R"( + { + "other_profile": false, + })")); + ASSERT_TRUE(non_other_profile_dst); + ASSERT_FALSE(non_other_profile_dst->IsTriggered( + {.destination = {.other_profile = true}})); + ASSERT_TRUE(non_other_profile_dst->IsTriggered( + {.destination = {.other_profile = false}})); + ASSERT_TRUE( + non_other_profile_dst->IsTriggered({.source = {.other_profile = true}})); + ASSERT_TRUE( + non_other_profile_dst->IsTriggered({.source = {.other_profile = false}})); +} + +TEST(AttributesConditionTest, OtherProfileSource) { + auto other_profile_src = SourceAttributesCondition::Create(CreateDict(R"( + { + "other_profile": true, + })")); + ASSERT_TRUE(other_profile_src); + ASSERT_FALSE( + other_profile_src->IsTriggered({.destination = {.other_profile = true}})); + ASSERT_FALSE(other_profile_src->IsTriggered( + {.destination = {.other_profile = false}})); + ASSERT_TRUE( + other_profile_src->IsTriggered({.source = {.other_profile = true}})); + ASSERT_FALSE( + other_profile_src->IsTriggered({.source = {.other_profile = false}})); + + auto non_other_profile_src = SourceAttributesCondition::Create(CreateDict(R"( + { + "other_profile": false, + })")); + ASSERT_TRUE(non_other_profile_src); + ASSERT_TRUE(non_other_profile_src->IsTriggered( + {.destination = {.other_profile = true}})); + ASSERT_TRUE(non_other_profile_src->IsTriggered( + {.destination = {.other_profile = false}})); + ASSERT_FALSE( + non_other_profile_src->IsTriggered({.source = {.other_profile = true}})); + ASSERT_TRUE( + non_other_profile_src->IsTriggered({.source = {.other_profile = false}})); +} + +TEST(AttributesConditionTest, URLAndOtherProfileDestination) { + auto url_and_other_profile = + DestinationAttributesCondition::Create(CreateDict(R"( + { + "urls": ["google.com"], + "other_profile": true, + })")); + ASSERT_TRUE(url_and_other_profile); + ASSERT_TRUE(url_and_other_profile->IsTriggered( + {.destination = {.url = GURL(kGoogleUrl), .other_profile = true}})); + ASSERT_FALSE(url_and_other_profile->IsTriggered( + {.destination = {.url = GURL(kGoogleUrl), .other_profile = false}})); + ASSERT_FALSE(url_and_other_profile->IsTriggered( + {.destination = {.url = GURL(kGoogleUrl)}})); + ASSERT_FALSE(url_and_other_profile->IsTriggered( + {.destination = {.url = GURL(kChromiumUrl), .other_profile = true}})); + ASSERT_FALSE(url_and_other_profile->IsTriggered( + {.destination = {.url = GURL(kChromiumUrl), .other_profile = false}})); + ASSERT_FALSE(url_and_other_profile->IsTriggered( + {.destination = {.url = GURL(kChromiumUrl)}})); + ASSERT_FALSE(url_and_other_profile->IsTriggered( + {.destination = {.other_profile = true}})); + ASSERT_FALSE(url_and_other_profile->IsTriggered( + {.destination = {.other_profile = false}})); + + auto url_and_not_other_profile = + DestinationAttributesCondition::Create(CreateDict(R"( + { + "urls": ["google.com"], + "other_profile": false, + })")); + ASSERT_TRUE(url_and_not_other_profile); + ASSERT_FALSE(url_and_not_other_profile->IsTriggered( + {.destination = {.url = GURL(kGoogleUrl), .other_profile = true}})); + ASSERT_TRUE(url_and_not_other_profile->IsTriggered( + {.destination = {.url = GURL(kGoogleUrl), .other_profile = false}})); + ASSERT_TRUE(url_and_not_other_profile->IsTriggered( + {.destination = {.url = GURL(kGoogleUrl)}})); + ASSERT_FALSE(url_and_not_other_profile->IsTriggered( + {.destination = {.url = GURL(kChromiumUrl), .other_profile = true}})); + ASSERT_FALSE(url_and_not_other_profile->IsTriggered( + {.destination = {.url = GURL(kChromiumUrl), .other_profile = false}})); + ASSERT_FALSE(url_and_not_other_profile->IsTriggered( + {.destination = {.url = GURL(kChromiumUrl)}})); + ASSERT_FALSE(url_and_not_other_profile->IsTriggered( + {.destination = {.other_profile = true}})); + ASSERT_FALSE(url_and_not_other_profile->IsTriggered( + {.destination = {.other_profile = false}})); +} + +TEST(AttributesConditionTest, URLAndOtherProfileSource) { + auto url_and_other_profile = SourceAttributesCondition::Create(CreateDict(R"( + { + "urls": ["google.com"], + "other_profile": true, + })")); + ASSERT_TRUE(url_and_other_profile); + ASSERT_TRUE(url_and_other_profile->IsTriggered( + {.source = {.url = GURL(kGoogleUrl), .other_profile = true}})); + ASSERT_FALSE(url_and_other_profile->IsTriggered( + {.source = {.url = GURL(kGoogleUrl), .other_profile = false}})); + ASSERT_FALSE(url_and_other_profile->IsTriggered( + {.source = {.url = GURL(kGoogleUrl)}})); + ASSERT_FALSE(url_and_other_profile->IsTriggered( + {.source = {.url = GURL(kChromiumUrl), .other_profile = true}})); + ASSERT_FALSE(url_and_other_profile->IsTriggered( + {.source = {.url = GURL(kChromiumUrl), .other_profile = false}})); + ASSERT_FALSE(url_and_other_profile->IsTriggered( + {.source = {.url = GURL(kChromiumUrl)}})); + ASSERT_FALSE( + url_and_other_profile->IsTriggered({.source = {.other_profile = true}})); + ASSERT_FALSE( + url_and_other_profile->IsTriggered({.source = {.other_profile = false}})); + + auto url_and_not_other_profile = + SourceAttributesCondition::Create(CreateDict(R"( + { + "urls": ["google.com"], + "other_profile": false, + })")); + ASSERT_TRUE(url_and_not_other_profile); + ASSERT_FALSE(url_and_not_other_profile->IsTriggered( + {.source = {.url = GURL(kGoogleUrl), .other_profile = true}})); + ASSERT_TRUE(url_and_not_other_profile->IsTriggered( + {.source = {.url = GURL(kGoogleUrl), .other_profile = false}})); + ASSERT_TRUE(url_and_not_other_profile->IsTriggered( + {.source = {.url = GURL(kGoogleUrl)}})); + ASSERT_FALSE(url_and_not_other_profile->IsTriggered( + {.source = {.url = GURL(kChromiumUrl), .other_profile = true}})); + ASSERT_FALSE(url_and_not_other_profile->IsTriggered( + {.source = {.url = GURL(kChromiumUrl), .other_profile = false}})); + ASSERT_FALSE(url_and_not_other_profile->IsTriggered( + {.source = {.url = GURL(kChromiumUrl)}})); + ASSERT_FALSE(url_and_not_other_profile->IsTriggered( + {.source = {.other_profile = true}})); + ASSERT_FALSE(url_and_not_other_profile->IsTriggered( + {.source = {.other_profile = false}})); +} + +TEST(AttributesConditionTest, URLAndNoOtherProfileDestination) { + // When "other_profile" is not in the condition, its value in the context + // shouldn't affect whether the condition is triggered or not. + auto any_url = DestinationAttributesCondition::Create(CreateDict(R"( + { + "urls": ["*"], + })")); + ASSERT_TRUE(any_url); + ASSERT_TRUE(any_url->IsTriggered( + {.destination = {.url = GURL(kGoogleUrl), .other_profile = true}})); + ASSERT_TRUE(any_url->IsTriggered( + {.destination = {.url = GURL(kGoogleUrl), .other_profile = false}})); + ASSERT_TRUE(any_url->IsTriggered({.destination = {.url = GURL(kGoogleUrl)}})); + ASSERT_FALSE(any_url->IsTriggered({.destination = {.other_profile = true}})); + ASSERT_FALSE(any_url->IsTriggered({.destination = {.other_profile = false}})); + ASSERT_FALSE(any_url->IsTriggered({.destination = {}})); +} + +TEST(AttributesConditionTest, URLAndNoOtherProfileSource) { + // When "other_profile" is not in the condition, its value in the context + // shouldn't affect whether the condition is triggered or not. + auto any_url = SourceAttributesCondition::Create(CreateDict(R"( + { + "urls": ["*"], + })")); + ASSERT_TRUE(any_url); + ASSERT_TRUE(any_url->IsTriggered( + {.source = {.url = GURL(kGoogleUrl), .other_profile = true}})); + ASSERT_TRUE(any_url->IsTriggered( + {.source = {.url = GURL(kGoogleUrl), .other_profile = false}})); + ASSERT_TRUE(any_url->IsTriggered({.source = {.url = GURL(kGoogleUrl)}})); + ASSERT_FALSE(any_url->IsTriggered({.source = {.other_profile = true}})); + ASSERT_FALSE(any_url->IsTriggered({.source = {.other_profile = false}})); + ASSERT_FALSE(any_url->IsTriggered({.source = {}})); +} + +TEST(AttributesConditionTest, URLOtherProfileIncognitoSource) { + auto condition = SourceAttributesCondition::Create(CreateDict(R"( + { + "urls": ["google.com"], + "incognito": true, + "other_profile": true, + })")); + ASSERT_TRUE(condition); + + // The condition only triggers when all 3 tab-related attributes are matched, + // any other context should fail to trigger it. + ASSERT_TRUE(condition->IsTriggered({.source = {.url = GURL(kGoogleUrl), + .incognito = true, + .other_profile = true}})); + + ASSERT_FALSE(condition->IsTriggered( + {.source = {.url = GURL(kGoogleUrl), .incognito = true}})); + ASSERT_FALSE(condition->IsTriggered( + {.source = {.url = GURL(kGoogleUrl), .other_profile = true}})); + ASSERT_FALSE(condition->IsTriggered({.source = {.url = GURL(kChromiumUrl), + .incognito = true, + .other_profile = true}})); + ASSERT_FALSE(condition->IsTriggered( + {.source = {.url = GURL(kChromiumUrl), .incognito = true}})); + ASSERT_FALSE(condition->IsTriggered( + {.source = {.url = GURL(kChromiumUrl), .other_profile = true}})); + ASSERT_FALSE(condition->IsTriggered({.source = {.url = GURL(kGoogleUrl)}})); + ASSERT_FALSE(condition->IsTriggered({.source = {.url = GURL(kChromiumUrl)}})); + ASSERT_FALSE(condition->IsTriggered({.source = {.incognito = true}})); + ASSERT_FALSE(condition->IsTriggered({.source = {.incognito = false}})); + + ASSERT_FALSE(condition->IsTriggered({.source = {.other_profile = true}})); + ASSERT_FALSE(condition->IsTriggered({.source = {.other_profile = false}})); +} + +TEST(AttributesConditionTest, URLOtherProfileIncognitoDestination) { + auto condition = DestinationAttributesCondition::Create(CreateDict(R"( + { + "urls": ["google.com"], + "incognito": true, + "other_profile": true, + })")); + ASSERT_TRUE(condition); + + // The condition only triggers when all 3 tab-related attributes are matched, + // any other context should fail to trigger it. + ASSERT_TRUE(condition->IsTriggered({.destination = {.url = GURL(kGoogleUrl), + .incognito = true, + .other_profile = true}})); + + ASSERT_FALSE(condition->IsTriggered( + {.destination = {.url = GURL(kGoogleUrl), .incognito = true}})); + ASSERT_FALSE(condition->IsTriggered( + {.destination = {.url = GURL(kGoogleUrl), .other_profile = true}})); + ASSERT_FALSE( + condition->IsTriggered({.destination = {.url = GURL(kChromiumUrl), + .incognito = true, + .other_profile = true}})); + ASSERT_FALSE(condition->IsTriggered( + {.destination = {.url = GURL(kChromiumUrl), .incognito = true}})); + ASSERT_FALSE(condition->IsTriggered( + {.destination = {.url = GURL(kChromiumUrl), .other_profile = true}})); + ASSERT_FALSE( + condition->IsTriggered({.destination = {.url = GURL(kGoogleUrl)}})); + ASSERT_FALSE( + condition->IsTriggered({.destination = {.url = GURL(kChromiumUrl)}})); + ASSERT_FALSE(condition->IsTriggered({.destination = {.incognito = true}})); + ASSERT_FALSE(condition->IsTriggered({.destination = {.incognito = false}})); + + ASSERT_FALSE( + condition->IsTriggered({.destination = {.other_profile = true}})); + ASSERT_FALSE( + condition->IsTriggered({.destination = {.other_profile = false}})); +} + TEST(AttributesConditionTest, OsClipboardDestination) { auto os_clipboard_dst = DestinationAttributesCondition::Create(CreateDict(R"( {
diff --git a/components/enterprise/data_controls/rule.cc b/components/enterprise/data_controls/rule.cc index 4ba48e1..2e590394 100644 --- a/components/enterprise/data_controls/rule.cc +++ b/components/enterprise/data_controls/rule.cc
@@ -70,6 +70,7 @@ for (const char* anyof_condition : {kKeySources, kKeyDestinations, AttributesCondition::kKeyUrls, AttributesCondition::kKeyIncognito, + AttributesCondition::kKeyOtherProfile, #if BUILDFLAG(IS_CHROMEOS) AttributesCondition::kKeyComponents #endif // BUILDFLAG(IS_CHROMEOS)
diff --git a/components/exo/layer_tree_frame_sink_holder.cc b/components/exo/layer_tree_frame_sink_holder.cc index da76dba..b830d35c 100644 --- a/components/exo/layer_tree_frame_sink_holder.cc +++ b/components/exo/layer_tree_frame_sink_holder.cc
@@ -6,6 +6,7 @@ #include "base/containers/contains.h" #include "base/task/single_thread_task_runner.h" +#include "base/trace_event/typed_macros.h" #include "cc/mojo_embedder/async_layer_tree_frame_sink.h" #include "components/exo/surface_tree_host.h" #include "components/viz/common/frame_timing_details.h" @@ -387,6 +388,20 @@ cached_frame_->metadata.frame_token); } + const int64_t client_frame_trace_id = + cached_frame_->metadata.begin_frame_ack.trace_id; + if (client_frame_trace_id != -1) { + TRACE_EVENT_INSTANT( + "viz,benchmark,graphics.pipeline", "Graphics.Pipeline", + perfetto::Flow::Global(client_frame_trace_id), + [client_frame_trace_id](perfetto::EventContext ctx) { + auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>(); + auto* data = event->set_chrome_graphics_pipeline(); + data->set_step(perfetto::protos::pbzero::ChromeGraphicsPipeline:: + StepName::STEP_EXO_DISCARD_COMPOSITOR_FRAME); + data->set_display_trace_id(client_frame_trace_id); + }); + } cached_frame_.reset(); frame_timing_history_->FrameDiscarded(); @@ -470,18 +485,39 @@ void LayerTreeFrameSinkHolder::ProcessFirstPendingBeginFrame( viz::CompositorFrame* frame) { + // The client-side frame trace ID, if available, is temporarily stored in + // the frame's BeginFrameAck struct. Extract it before populating + // BeginFrameAck. + const int64_t client_frame_trace_id = + frame->metadata.begin_frame_ack.trace_id; + // If there are not-yet-handled BeginFrames requests from the remote side, // use `frame` as response to the earliest one. if (!pending_begin_frames_.empty()) { frame->metadata.begin_frame_ack = pending_begin_frames_.front().begin_frame_ack; pending_begin_frames_.pop(); - return; + } else { + // Submit an unsolicited frame. + frame->metadata.begin_frame_ack = + viz::BeginFrameAck::CreateManualAckWithDamage(); } - // Submit an unsolicited frame. - frame->metadata.begin_frame_ack = - viz::BeginFrameAck::CreateManualAckWithDamage(); + if (client_frame_trace_id != -1) { + // Use both the ID from the client-side frame submission and the ID from the + // BeginFrame request to connect the two flows. + TRACE_EVENT_INSTANT( + "viz,benchmark,graphics.pipeline", "Graphics.Pipeline", + perfetto::Flow::Global(client_frame_trace_id), + perfetto::Flow::Global(frame->metadata.begin_frame_ack.trace_id), + [client_frame_trace_id](perfetto::EventContext ctx) { + auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>(); + auto* data = event->set_chrome_graphics_pipeline(); + data->set_step(perfetto::protos::pbzero::ChromeGraphicsPipeline:: + StepName::STEP_EXO_SUBMIT_COMPOSITOR_FRAME); + data->set_display_trace_id(client_frame_trace_id); + }); + } } bool LayerTreeFrameSinkHolder::ShouldSubmitFrameNow() const {
diff --git a/components/exo/surface.cc b/components/exo/surface.cc index 3cd9ee96..194518a 100644 --- a/components/exo/surface.cc +++ b/components/exo/surface.cc
@@ -647,6 +647,10 @@ pending_state_.clip_rect_is_parent_coordinates = false; } +void Surface::SetFrameTraceId(int64_t frame_trace_id) { + pending_state_.frame_trace_id = frame_trace_id; +} + void Surface::SetClipRectOnParentSurface( const std::optional<gfx::RectF>& clip_rect) { TRACE_EVENT1("exo", "Surface::SetClipRectOnParentSurface", "clip_rect", @@ -947,6 +951,9 @@ cached_state_.presentation_callbacks.end(), pending_state_.presentation_callbacks); + cached_state_.frame_trace_id = pending_state_.frame_trace_id; + pending_state_.frame_trace_id = -1; + if (delegate_) delegate_->OnSurfaceCommit(); else @@ -1166,6 +1173,9 @@ state_.damage.Intersect(output_rect); } cached_state_.damage.Clear(); + + state_.frame_trace_id = cached_state_.frame_trace_id; + cached_state_.frame_trace_id = -1; } surface_hierarchy_content_bounds_ =
diff --git a/components/exo/surface.h b/components/exo/surface.h index b420604..eee1c40 100644 --- a/components/exo/surface.h +++ b/components/exo/surface.h
@@ -206,6 +206,10 @@ // Sets the surface's clip rectangle. void SetClipRect(const std::optional<gfx::RectF>& clip_rect); + // Sets the trace ID for tracking frame submission, which is used for the next + // surface commit. + void SetFrameTraceId(int64_t frame_trace_id); + // Sets the surface's clip rectangle on parent surface coordinates. // TODO(crbug.com/1457446): Remove this. void SetClipRectOnParentSurface(const std::optional<gfx::RectF>& clip_rect); @@ -496,6 +500,8 @@ // Returns the buffer scale of the last committed buffer. float GetBufferScale() const { return state_.basic_state.buffer_scale; } + int64_t GetFrameTraceId() const { return state_.frame_trace_id; } + // Returns the last committed buffer. Buffer* GetBuffer(); @@ -621,6 +627,10 @@ // for subsurfaces, and doesn't apply to children of this surface. // Persisted between commits. gfx::Transform surface_transform; + + // Trace ID for tracking frame submission. + // Not persisted between commits. + int64_t frame_trace_id = -1; }; friend class subtle::PropertyHelper;
diff --git a/components/exo/surface_tree_host.cc b/components/exo/surface_tree_host.cc index 32ac567..2427a68 100644 --- a/components/exo/surface_tree_host.cc +++ b/components/exo/surface_tree_host.cc
@@ -335,6 +335,21 @@ << ", StartupId=" << (startup_id ? *startup_id : "''"); } + const int64_t frame_trace_id = root_surface_->GetFrameTraceId(); + if (frame_trace_id != -1) { + frame.metadata.begin_frame_ack.trace_id = frame_trace_id; + TRACE_EVENT_INSTANT( + "viz,benchmark,graphics.pipeline", "Graphics.Pipeline", + perfetto::Flow::Global(frame_trace_id), + [frame_trace_id](perfetto::EventContext ctx) { + auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>(); + auto* data = event->set_chrome_graphics_pipeline(); + data->set_step(perfetto::protos::pbzero::ChromeGraphicsPipeline:: + StepName::STEP_EXO_CONSTRUCT_COMPOSITOR_FRAME); + data->set_display_trace_id(frame_trace_id); + }); + } + std::list<Surface::FrameCallback> current_frame_callbacks; PresentationCallbacks presentation_callbacks; root_surface_->AppendSurfaceHierarchyCallbacks(¤t_frame_callbacks,
diff --git a/components/exo/wayland/protocol/surface-augmenter.xml b/components/exo/wayland/protocol/surface-augmenter.xml index bff58290..117154a 100644 --- a/components/exo/wayland/protocol/surface-augmenter.xml +++ b/components/exo/wayland/protocol/surface-augmenter.xml
@@ -24,7 +24,7 @@ DEALINGS IN THE SOFTWARE. </copyright> - <interface name="surface_augmenter" version="10"> + <interface name="surface_augmenter" version="11"> <description summary="surface composition delegation"> The global interface exposing surface delegated composition capabilities is used to instantiate an interface extension for a @@ -89,7 +89,7 @@ </request> </interface> - <interface name="augmented_surface" version="10"> + <interface name="augmented_surface" version="11"> <description summary="delegate composition of a wl_surface"> An additional interface to a wl_surface object, which allows the client to specify the delegated composition of the surface @@ -248,11 +248,23 @@ <!-- Version 10 additions --> - <!-- CAUTION: Use Version 11 as a next since version. + <!-- This version updates the inner implementation of surface coordinate. No protocol is added for this version. --> + <!-- Version 11 additions --> + <request name="set_frame_trace_id" since="11"> + <description summary="sets a trace ID for tracking frame submission flow"> + This sets a trace ID to connect the frame submission trace event flow at + the client and the server side. + This state is double-buffered, and is applied on the next + wl_surface.commit. + </description> + <arg name="id_hi" type="uint" summary="high 32 bits of the trace ID"/> + <arg name="id_lo" type="uint" summary="low 32 bits of the trace ID"/> + </request> + </interface> <interface name="augmented_sub_surface" version="5">
diff --git a/components/exo/wayland/surface_augmenter.cc b/components/exo/wayland/surface_augmenter.cc index 4b1bf19..865e5b4 100644 --- a/components/exo/wayland/surface_augmenter.cc +++ b/components/exo/wayland/surface_augmenter.cc
@@ -95,6 +95,10 @@ surface_->SetClipRect(clip_rect); } + void SetFrameTraceId(int64_t frame_trace_id) { + surface_->SetFrameTraceId(frame_trace_id); + } + // SurfaceObserver: void OnSurfaceDestroying(Surface* surface) override { surface->RemoveSurfaceObserver(this); @@ -210,6 +214,25 @@ wl_fixed_to_double(height)); } +void augmented_surface_set_frame_trace_id(wl_client* client, + wl_resource* resource, + uint32_t id_hi, + uint32_t id_lo) { + base::CheckedNumeric<int64_t> id(id_hi); + id <<= 32; + id += id_lo; + + if (!id.IsValid()) { + wl_resource_post_error( + resource, AUGMENTED_SURFACE_ERROR_BAD_VALUE, + "The frame trace ID cannot be converted to a valid int64_t (%u, %u)", + id_hi, id_lo); + return; + } + + GetUserDataAs<AugmentedSurface>(resource)->SetFrameTraceId(id.ValueOrDie()); +} + const struct augmented_surface_interface augmented_implementation = { augmented_surface_destroy, augmented_surface_set_corners_DEPRECATED, @@ -219,6 +242,7 @@ augmented_surface_set_trusted_damage, augmented_surface_set_rounded_corners_clip_bounds, augmented_surface_set_clip_rect, + augmented_surface_set_frame_trace_id, }; ////////////////////////////////////////////////////////////////////////////////
diff --git a/components/exo/wayland/surface_augmenter.h b/components/exo/wayland/surface_augmenter.h index 1d63808..23703043 100644 --- a/components/exo/wayland/surface_augmenter.h +++ b/components/exo/wayland/surface_augmenter.h
@@ -11,12 +11,9 @@ namespace exo::wayland { -// Clients at version 8 think clip rect is in parent surface's space, while -// clients at version 9 or above think it's in local surface's space. -// Unfortunately, clipping in version 9 is implemented incorrectly. It has been -// fixed in version 10, so use version 10 instead. +// version: 11 constexpr uint32_t kSurfaceAugmenterVersion = - AUGMENTED_SURFACE_SET_CLIP_RECT_SINCE_VERSION + 2; + AUGMENTED_SURFACE_SET_FRAME_TRACE_ID_SINCE_VERSION; void bind_surface_augmenter(wl_client* client, void* data,
diff --git a/components/handoff/DIR_METADATA b/components/handoff/DIR_METADATA index 9719bd8..e773b40 100644 --- a/components/handoff/DIR_METADATA +++ b/components/handoff/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "UI>Browser" } +buganizer_public: { + component_id: 1457469 +}
diff --git a/components/heap_profiling/DIR_METADATA b/components/heap_profiling/DIR_METADATA index 77eae17..02385d6 100644 --- a/components/heap_profiling/DIR_METADATA +++ b/components/heap_profiling/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals>Instrumentation>Memory" } +buganizer_public: { + component_id: 1456375 +}
diff --git a/components/heavy_ad_intervention/COMMON_METADATA b/components/heavy_ad_intervention/COMMON_METADATA index 352eefc..4f4fe625 100644 --- a/components/heavy_ad_intervention/COMMON_METADATA +++ b/components/heavy_ad_intervention/COMMON_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "UI>Browser>AdFilter" } +buganizer_public: { + component_id: 1456114 +}
diff --git a/components/heavy_ad_intervention_strings_grdp/DIR_METADATA b/components/heavy_ad_intervention_strings_grdp/DIR_METADATA index 352eefc..4f4fe625 100644 --- a/components/heavy_ad_intervention_strings_grdp/DIR_METADATA +++ b/components/heavy_ad_intervention_strings_grdp/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "UI>Browser>AdFilter" } +buganizer_public: { + component_id: 1456114 +}
diff --git a/components/history/DIR_METADATA b/components/history/DIR_METADATA index 9b08ae7f..38f4bc1 100644 --- a/components/history/DIR_METADATA +++ b/components/history/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "UI>Browser>History" } +buganizer_public: { + component_id: 1456716 +}
diff --git a/components/history/ios/DIR_METADATA b/components/history/ios/DIR_METADATA index 1335a14..7b89d770 100644 --- a/components/history/ios/DIR_METADATA +++ b/components/history/ios/DIR_METADATA
@@ -1,4 +1,7 @@ -monorail { +monorail: { component: "Mobile>iOSWeb" } team_email: "ios-directory-owners@chromium.org" +buganizer_public: { + component_id: 1456915 +}
diff --git a/components/infobars/DIR_METADATA b/components/infobars/DIR_METADATA index 172afcf1..10216807 100644 --- a/components/infobars/DIR_METADATA +++ b/components/infobars/DIR_METADATA
@@ -1,4 +1,7 @@ -monorail { +monorail: { component: "UI>Browser>Infobars" } team_email: "chromium-reviews@chromium.org" +buganizer_public: { + component_id: 1456657 +}
diff --git a/components/infobars/android/DIR_METADATA b/components/infobars/android/DIR_METADATA index 2ae4e3f9..a433eb2 100644 --- a/components/infobars/android/DIR_METADATA +++ b/components/infobars/android/DIR_METADATA
@@ -1,4 +1,7 @@ -monorail { +monorail: { component: "UI>Browser>Mobile>Messages" } os: ANDROID +buganizer_public: { + component_id: 1457320 +}
diff --git a/components/installedapp/DIR_METADATA b/components/installedapp/DIR_METADATA index 320129e..3e23ee2 100644 --- a/components/installedapp/DIR_METADATA +++ b/components/installedapp/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "UI>Browser>WebAppInstalls" } +buganizer_public: { + component_id: 1457043 +}
diff --git a/components/ip_protection_auth/DIR_METADATA b/components/ip_protection_auth/DIR_METADATA index 142c8e0..10eb856c 100644 --- a/components/ip_protection_auth/DIR_METADATA +++ b/components/ip_protection_auth/DIR_METADATA
@@ -1,13 +1,8 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -team_email: "android-webview-dev@chromium.org" -monorail { +monorail: { component: "Mobile>WebView" } +team_email: "android-webview-dev@chromium.org" os: ANDROID +buganizer_public: { + component_id: 1456456 +}
diff --git a/components/javascript_dialogs/DIR_METADATA b/components/javascript_dialogs/DIR_METADATA index e3d54cf..380e8a6 100644 --- a/components/javascript_dialogs/DIR_METADATA +++ b/components/javascript_dialogs/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Blink>WindowDialog" } +buganizer_public: { + component_id: 1456366 +}
diff --git a/components/javascript_dialogs/views/DIR_METADATA b/components/javascript_dialogs/views/DIR_METADATA index 2cf1ad6..570367e6 100644 --- a/components/javascript_dialogs/views/DIR_METADATA +++ b/components/javascript_dialogs/views/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals>Views>Desktop" } +buganizer_public: { + component_id: 1456160 +}
diff --git a/components/javascript_dialogs_strings_grdp/DIR_METADATA b/components/javascript_dialogs_strings_grdp/DIR_METADATA index e3d54cf..380e8a6 100644 --- a/components/javascript_dialogs_strings_grdp/DIR_METADATA +++ b/components/javascript_dialogs_strings_grdp/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Blink>WindowDialog" } +buganizer_public: { + component_id: 1456366 +}
diff --git a/components/js_injection/DIR_METADATA b/components/js_injection/DIR_METADATA index 6e8bcf2c..12293d9 100644 --- a/components/js_injection/DIR_METADATA +++ b/components/js_injection/DIR_METADATA
@@ -1,5 +1,7 @@ -monorail { +monorail: { component: "Mobile>WebView" } - team_email: "android-webview-dev@chromium.org" +buganizer_public: { + component_id: 1456456 +}
diff --git a/components/keep_alive_registry/DIR_METADATA b/components/keep_alive_registry/DIR_METADATA index 14b5edb5..45f7798a6 100644 --- a/components/keep_alive_registry/DIR_METADATA +++ b/components/keep_alive_registry/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals" } +buganizer_public: { + component_id: 1456292 +}
diff --git a/components/keyed_service/DIR_METADATA b/components/keyed_service/DIR_METADATA index 14b5edb5..45f7798a6 100644 --- a/components/keyed_service/DIR_METADATA +++ b/components/keyed_service/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals" } +buganizer_public: { + component_id: 1456292 +}
diff --git a/components/lens/DIR_METADATA b/components/lens/DIR_METADATA index 749bdad..4f031d9 100644 --- a/components/lens/DIR_METADATA +++ b/components/lens/DIR_METADATA
@@ -1,4 +1,7 @@ -monorail { +monorail: { component: "UI>Browser" } team_email: "lens-chrome-eng+bugs@google.com" +buganizer_public: { + component_id: 1457469 +}
diff --git a/components/leveldb_proto/DIR_METADATA b/components/leveldb_proto/DIR_METADATA index f8e9454..dc35fd2 100644 --- a/components/leveldb_proto/DIR_METADATA +++ b/components/leveldb_proto/DIR_METADATA
@@ -1,5 +1,7 @@ -monorail { +monorail: { component: "Internals>Storage>LevelDBProto" } - team_email: "chromium-reviews@chromium.org" +buganizer_public: { + component_id: 1456195 +}
diff --git a/components/link_header_util/DIR_METADATA b/components/link_header_util/DIR_METADATA index af30f87..b61d0e7d 100644 --- a/components/link_header_util/DIR_METADATA +++ b/components/link_header_util/DIR_METADATA
@@ -1,5 +1,7 @@ -monorail { +monorail: { component: "Blink>Loader" } - team_email: "loading-dev@chromium.org" +buganizer_public: { + component_id: 1456695 +}
diff --git a/components/live_caption/DIR_METADATA b/components/live_caption/DIR_METADATA index 032b6e41..7db57e5 100644 --- a/components/live_caption/DIR_METADATA +++ b/components/live_caption/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals>Media>LiveCaption" } +buganizer_public: { + component_id: 1456191 +}
diff --git a/components/live_caption_strings_grdp/DIR_METADATA b/components/live_caption_strings_grdp/DIR_METADATA index 032b6e41..7db57e5 100644 --- a/components/live_caption_strings_grdp/DIR_METADATA +++ b/components/live_caption_strings_grdp/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals>Media>LiveCaption" } +buganizer_public: { + component_id: 1456191 +}
diff --git a/components/local_state/DIR_METADATA b/components/local_state/DIR_METADATA index 1c5b27e..b0fc17e 100644 --- a/components/local_state/DIR_METADATA +++ b/components/local_state/DIR_METADATA
@@ -1,5 +1,7 @@ -monorail { +monorail: { component: "Internals>Metrics>Variations" } - team_email: "chromium-dev@chromium.org" +buganizer_public: { + component_id: 1456342 +}
diff --git a/components/lookalikes/DIR_METADATA b/components/lookalikes/DIR_METADATA index b302215..062cfa8 100644 --- a/components/lookalikes/DIR_METADATA +++ b/components/lookalikes/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "UI>Browser>Interstitials" } +buganizer_public: { + component_id: 1456891 +}
diff --git a/components/management_strings_grdp/DIR_METADATA b/components/management_strings_grdp/DIR_METADATA index db7a5c4a..00d6003 100644 --- a/components/management_strings_grdp/DIR_METADATA +++ b/components/management_strings_grdp/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Privacy" } +buganizer_public: { + component_id: 1457231 +}
diff --git a/components/media_router/common/providers/cast/channel/BUILD.gn b/components/media_router/common/providers/cast/channel/BUILD.gn index d2df495..04192a22 100644 --- a/components/media_router/common/providers/cast/channel/BUILD.gn +++ b/components/media_router/common/providers/cast/channel/BUILD.gn
@@ -4,7 +4,7 @@ import("//testing/libfuzzer/fuzzer_test.gni") import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni") -import("//third_party/openscreen/src/build/config/data_headers_template.gni") +import("//third_party/openscreen/src/build_overrides/data_headers_template.gni") import("//third_party/protobuf/proto_library.gni") source_set("capability") {
diff --git a/components/memory_pressure/DIR_METADATA b/components/memory_pressure/DIR_METADATA index 2aaf8e2eed..744e51f 100644 --- a/components/memory_pressure/DIR_METADATA +++ b/components/memory_pressure/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals>Core" } +buganizer_public: { + component_id: 1456128 +}
diff --git a/components/memory_system/DIR_METADATA b/components/memory_system/DIR_METADATA index 77eae17..02385d6 100644 --- a/components/memory_system/DIR_METADATA +++ b/components/memory_system/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals>Instrumentation>Memory" } +buganizer_public: { + component_id: 1456375 +}
diff --git a/components/metal_util/DIR_METADATA b/components/metal_util/DIR_METADATA index f7e4412..5c9475b 100644 --- a/components/metal_util/DIR_METADATA +++ b/components/metal_util/DIR_METADATA
@@ -1,5 +1,7 @@ -monorail { +monorail: { component: "Internals>Compositing" } - team_email: "graphics-dev@chromium.org" +buganizer_public: { + component_id: 1456836 +}
diff --git a/components/metrics/debug/DIR_METADATA b/components/metrics/debug/DIR_METADATA index 7e7dcdb..feca9c13 100644 --- a/components/metrics/debug/DIR_METADATA +++ b/components/metrics/debug/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals>Metrics" -} \ No newline at end of file +} +buganizer_public: { + component_id: 1456863 +}
diff --git a/components/metrics_services_manager/DIR_METADATA b/components/metrics_services_manager/DIR_METADATA index 4cea270..d85366a 100644 --- a/components/metrics_services_manager/DIR_METADATA +++ b/components/metrics_services_manager/DIR_METADATA
@@ -1,5 +1,7 @@ -monorail { +monorail: { component: "Internals>Metrics" } - team_email: "chromium-dev@chromium.org" +buganizer_public: { + component_id: 1456863 +}
diff --git a/components/minidump_uploader/DIR_METADATA b/components/minidump_uploader/DIR_METADATA index 030c855..f494fb23 100644 --- a/components/minidump_uploader/DIR_METADATA +++ b/components/minidump_uploader/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals>CrashReporting" } +buganizer_public: { + component_id: 1456911 +}
diff --git a/components/mirroring/DIR_METADATA b/components/mirroring/DIR_METADATA index 23d2949f1..3e3712d 100644 --- a/components/mirroring/DIR_METADATA +++ b/components/mirroring/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals>Cast>Streaming" } +buganizer_public: { + component_id: 1456294 +}
diff --git a/components/module_installer/DIR_METADATA b/components/module_installer/DIR_METADATA index 29322247..0a3108ed 100644 --- a/components/module_installer/DIR_METADATA +++ b/components/module_installer/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Mobile>FeatureModules" } +buganizer_public: { + component_id: 1457149 +}
diff --git a/components/navigation_interception/DIR_METADATA b/components/navigation_interception/DIR_METADATA index 8581e1c..eb2cfac5 100644 --- a/components/navigation_interception/DIR_METADATA +++ b/components/navigation_interception/DIR_METADATA
@@ -1,5 +1,7 @@ -monorail { +monorail: { component: "UI>Browser>Navigation" } - team_email: "chromium-reviews@chromium.org" +buganizer_public: { + component_id: 1457065 +}
diff --git a/components/navigation_metrics/DIR_METADATA b/components/navigation_metrics/DIR_METADATA index 709d8280..788a957 100644 --- a/components/navigation_metrics/DIR_METADATA +++ b/components/navigation_metrics/DIR_METADATA
@@ -1,5 +1,7 @@ -monorail { +monorail: { component: "Internals>Network" } - team_email: "net-dev@chromium.org" +buganizer_public: { + component_id: 1456527 +}
diff --git a/components/net_log/DIR_METADATA b/components/net_log/DIR_METADATA index 83a0f7e5..ab6b537 100644 --- a/components/net_log/DIR_METADATA +++ b/components/net_log/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals>Network>Logging" } +buganizer_public: { + component_id: 1456192 +}
diff --git a/components/neterror/DIR_METADATA b/components/neterror/DIR_METADATA index 709d8280..788a957 100644 --- a/components/neterror/DIR_METADATA +++ b/components/neterror/DIR_METADATA
@@ -1,5 +1,7 @@ -monorail { +monorail: { component: "Internals>Network" } - team_email: "net-dev@chromium.org" +buganizer_public: { + component_id: 1456527 +}
diff --git a/components/network_hints/DIR_METADATA b/components/network_hints/DIR_METADATA index 2d14a86..1165612 100644 --- a/components/network_hints/DIR_METADATA +++ b/components/network_hints/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals>Network" } +buganizer_public: { + component_id: 1456527 +}
diff --git a/components/network_session_configurator/DIR_METADATA b/components/network_session_configurator/DIR_METADATA index 2d14a86..1165612 100644 --- a/components/network_session_configurator/DIR_METADATA +++ b/components/network_session_configurator/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals>Network" } +buganizer_public: { + component_id: 1456527 +}
diff --git a/components/network_time/DIR_METADATA b/components/network_time/DIR_METADATA index b302215..062cfa8 100644 --- a/components/network_time/DIR_METADATA +++ b/components/network_time/DIR_METADATA
@@ -1,3 +1,6 @@ -monorail { +monorail: { component: "UI>Browser>Interstitials" } +buganizer_public: { + component_id: 1456891 +}
diff --git a/components/new_or_sad_tab_strings_grdp/DIR_METADATA b/components/new_or_sad_tab_strings_grdp/DIR_METADATA index 1ee6aef..9860e9e3 100644 --- a/components/new_or_sad_tab_strings_grdp/DIR_METADATA +++ b/components/new_or_sad_tab_strings_grdp/DIR_METADATA
@@ -1,5 +1,7 @@ -monorail { +monorail: { component: "UI>Browser>NewTabPage" } - team_email: "ntp-dev@chromium.org" +buganizer_public: { + component_id: 1457163 +}
diff --git a/components/no_state_prefetch/DIR_METADATA b/components/no_state_prefetch/DIR_METADATA index eaf73c7..2ef4f22 100644 --- a/components/no_state_prefetch/DIR_METADATA +++ b/components/no_state_prefetch/DIR_METADATA
@@ -1,3 +1,6 @@ monorail: { component: "Internals>Preload" } +buganizer_public: { + component_id: 1457018 +}
diff --git a/components/omnibox/browser/history_provider.h b/components/omnibox/browser/history_provider.h index dffac2f..efebe4c 100644 --- a/components/omnibox/browser/history_provider.h +++ b/components/omnibox/browser/history_provider.h
@@ -45,7 +45,11 @@ AutocompleteProviderClient* client() const { return client_; } private: - raw_ptr<AutocompleteProviderClient> client_; + // TODO(https://issues.chromium.org/issues/41485238#comment6) investigate why + // this pointer is kept dangling, for longer than the duration of the task. + raw_ptr<AutocompleteProviderClient, + FlakyDanglingUntriaged | AcrossTasksDanglingUntriaged> + client_; }; #endif // COMPONENTS_OMNIBOX_BROWSER_HISTORY_PROVIDER_H_
diff --git a/components/optimization_guide/internal b/components/optimization_guide/internal index b5dce53..774f92f 160000 --- a/components/optimization_guide/internal +++ b/components/optimization_guide/internal
@@ -1 +1 @@ -Subproject commit b5dce536acaa9d9fedc1ea98b42586100f0e11c7 +Subproject commit 774f92f791e117e4cd26fa92d159d1d93fc4cfb6
diff --git a/components/password_manager/core/browser/features/password_features.cc b/components/password_manager/core/browser/features/password_features.cc index efb6fd8f..f6717a8 100644 --- a/components/password_manager/core/browser/features/password_features.cc +++ b/components/password_manager/core/browser/features/password_features.cc
@@ -119,13 +119,10 @@ "UnifiedPasswordManagerLocalPasswordsAndroidNoMigration", base::FEATURE_DISABLED_BY_DEFAULT); -// Setting the default value to 0 is convenient for testing. Every Android bot -// has *some* version of GmsCore installed, so all of them will satisfy the -// min version check. constinit const base::FeatureParam<int> kUPMLocalPasswordsMinGmsVersionCode( &kUnifiedPasswordManagerLocalPasswordsAndroidNoMigration, "min_gms_version", - /*default_value=*/0); + /*default_value=*/240212000); BASE_FEATURE(kUnifiedPasswordManagerLocalPasswordsAndroidWithMigration, "UnifiedPasswordManagerLocalPasswordsAndroidWithMigration",
diff --git a/components/performance_manager/graph/frame_node_impl.cc b/components/performance_manager/graph/frame_node_impl.cc index c079089..1e92d5bf 100644 --- a/components/performance_manager/graph/frame_node_impl.cc +++ b/components/performance_manager/graph/frame_node_impl.cc
@@ -615,15 +615,8 @@ // Make sure all weak pointers, even `weak_this_` that was created on the UI // thread in the constructor, can only be dereferenced on the graph sequence. - // - // If this is the first pointer dereferenced, it will bind all pointers from - // `weak_factory_` to the current sequence. If not, get() will DCHECK. - // DCHECK'ing the return value of get() prevents the compiler from optimizing - // it away. - // - // TODO(crbug.com/1134162): Use WeakPtrFactory::BindToCurrentSequence for this - // (it's clearer but currently not exposed publicly). - DCHECK(GetWeakPtr().get()); + weak_factory_.BindToCurrentSequence( + base::subtle::BindWeakPtrFactoryPassKey()); // Enable querying this node using process and frame routing ids. graph()->RegisterFrameNodeForId(process_node_->GetRenderProcessHostId(),
diff --git a/components/performance_manager/graph/page_node_impl.cc b/components/performance_manager/graph/page_node_impl.cc index 011e259..12a580b 100644 --- a/components/performance_manager/graph/page_node_impl.cc +++ b/components/performance_manager/graph/page_node_impl.cc
@@ -514,15 +514,8 @@ // Make sure all weak pointers, even `weak_this_` that was created on the UI // thread in the constructor, can only be dereferenced on the graph sequence. - // - // If this is the first pointer dereferenced, it will bind all pointers from - // `weak_factory_` to the current sequence. If not, get() will DCHECK. - // DCHECK'ing the return value of get() prevents the compiler from optimizing - // it away. - // - // TODO(crbug.com/1134162): Use WeakPtrFactory::BindToCurrentSequence for this - // (it's clearer but currently not exposed publicly). - DCHECK(GetWeakPtr().get()); + weak_factory_.BindToCurrentSequence( + base::subtle::BindWeakPtrFactoryPassKey()); } void PageNodeImpl::OnBeforeLeavingGraph() {
diff --git a/components/performance_manager/graph/process_node_impl.cc b/components/performance_manager/graph/process_node_impl.cc index c6a6cb1..13c676c 100644 --- a/components/performance_manager/graph/process_node_impl.cc +++ b/components/performance_manager/graph/process_node_impl.cc
@@ -438,15 +438,8 @@ // Make sure all weak pointers, even `weak_this_` that was created on the UI // thread in the constructor, can only be dereferenced on the graph sequence. - // - // If this is the first pointer dereferenced, it will bind all pointers from - // `weak_factory_` to the current sequence. If not, get() will DCHECK. - // DCHECK'ing the return value of get() prevents the compiler from optimizing - // it away. - // - // TODO(crbug.com/1134162): Use WeakPtrFactory::BindToCurrentSequence for this - // (it's clearer but currently not exposed publicly). - DCHECK(GetWeakPtr().get()); + weak_factory_.BindToCurrentSequence( + base::subtle::BindWeakPtrFactoryPassKey()); } void ProcessNodeImpl::OnBeforeLeavingGraph() {
diff --git a/components/performance_manager/graph/worker_node_impl.cc b/components/performance_manager/graph/worker_node_impl.cc index da4346d..108bfdb 100644 --- a/components/performance_manager/graph/worker_node_impl.cc +++ b/components/performance_manager/graph/worker_node_impl.cc
@@ -205,15 +205,8 @@ // Make sure all weak pointers, even `weak_this_` that was created on the UI // thread in the constructor, can only be dereferenced on the graph sequence. - // - // If this is the first pointer dereferenced, it will bind all pointers from - // `weak_factory_` to the current sequence. If not, get() will DCHECK. - // DCHECK'ing the return value of get() prevents the compiler from optimizing - // it away. - // - // TODO(crbug.com/1134162): Use WeakPtrFactory::BindToCurrentSequence for this - // (it's clearer but currently not exposed publicly). - DCHECK(GetWeakPtr().get()); + weak_factory_.BindToCurrentSequence( + base::subtle::BindWeakPtrFactoryPassKey()); process_node_->AddWorker(this); }
diff --git a/components/permissions_strings.grdp b/components/permissions_strings.grdp index ff4ad497..f46371c 100644 --- a/components/permissions_strings.grdp +++ b/components/permissions_strings.grdp
@@ -46,7 +46,7 @@ <ph name="site">$1<ex>mail.google.com</ex></ph> wants to send you notifications </message> <message name="IDS_MIDI_SYSEX_INFOBAR_TEXT" desc="Text requesting permission for a site to access MIDI devices with system exclusive messages."> - <ph name="URL">$1<ex>www.google.com</ex></ph> wants to control and reprogram your MIDI devices (SysEx) + <ph name="URL">$1<ex>www.google.com</ex></ph> wants to control and reprogram your MIDI devices </message> <message name="IDS_STORAGE_ACCESS_INFOBAR_TEXT" desc="Permission request shown if the user is visiting a site needs access to its data while it is embedded into another site."> <ph name="EMBEDDED_URL">$1<ex>news.site</ex></ph> wants to use cookies and site data on <ph name="TOP_LEVEL_URL">$2<ex>content_domain.site</ex></ph> @@ -92,7 +92,7 @@ Show notifications </message> <message name="IDS_MIDI_SYSEX_PERMISSION_FRAGMENT" desc="Permission asked in the permission bubble when a URL wants to access MIDI devices with system exclusive messages, along with other permissions requests. Preceded by the prompt 'This site would like to:'"> - Control and reprogram your MIDI devices (SysEx) + Control and reprogram your MIDI devices </message> <message name="IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_FRAGMENT" desc="Permission fragment shown in the permissions bubble when a web page requests access to the computer's microphone."> Use your microphone @@ -240,7 +240,7 @@ Get notifications? </message> <message name="IDS_MIDI_SYSEX_PERMISSION_CHIP" desc="Button text representing a request for accessing MIDI devices from a website. When clicked, shows a permission prompt bubble with more information."> - Control and reprogram MIDI devices? + Control & reprogram MIDI devices? </message> <message name="IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_CHIP" desc="Button text representing a request for accessing the computer's microphone from a website. When clicked, shows a permission prompt bubble with more information."> Use microphone?
diff --git a/components/permissions_strings_grdp/IDS_MIDI_SYSEX_INFOBAR_TEXT.png.sha1 b/components/permissions_strings_grdp/IDS_MIDI_SYSEX_INFOBAR_TEXT.png.sha1 index 4fba885..c0fcf13 100644 --- a/components/permissions_strings_grdp/IDS_MIDI_SYSEX_INFOBAR_TEXT.png.sha1 +++ b/components/permissions_strings_grdp/IDS_MIDI_SYSEX_INFOBAR_TEXT.png.sha1
@@ -1 +1 @@ -c4a11e6214949d3c76aea1391e6ca3684b710038 \ No newline at end of file +0631ba049a8d42413ceb2e91d51265e6663e9e19 \ No newline at end of file
diff --git a/components/permissions_strings_grdp/IDS_MIDI_SYSEX_PERMISSION_CHIP.png.sha1 b/components/permissions_strings_grdp/IDS_MIDI_SYSEX_PERMISSION_CHIP.png.sha1 index d7a7faf..ccde264c 100644 --- a/components/permissions_strings_grdp/IDS_MIDI_SYSEX_PERMISSION_CHIP.png.sha1 +++ b/components/permissions_strings_grdp/IDS_MIDI_SYSEX_PERMISSION_CHIP.png.sha1
@@ -1 +1 @@ -93719ccd6c72a73fcbaf4b05c26499f010d2f487 \ No newline at end of file +b9408644aa351a5869634f8ef7f0aeecd0964cce \ No newline at end of file
diff --git a/components/permissions_strings_grdp/IDS_MIDI_SYSEX_PERMISSION_FRAGMENT.png.sha1 b/components/permissions_strings_grdp/IDS_MIDI_SYSEX_PERMISSION_FRAGMENT.png.sha1 index d7a7faf..ccde264c 100644 --- a/components/permissions_strings_grdp/IDS_MIDI_SYSEX_PERMISSION_FRAGMENT.png.sha1 +++ b/components/permissions_strings_grdp/IDS_MIDI_SYSEX_PERMISSION_FRAGMENT.png.sha1
@@ -1 +1 @@ -93719ccd6c72a73fcbaf4b05c26499f010d2f487 \ No newline at end of file +b9408644aa351a5869634f8ef7f0aeecd0964cce \ No newline at end of file
diff --git a/components/safe_browsing/content/browser/async_check_tracker_unittest.cc b/components/safe_browsing/content/browser/async_check_tracker_unittest.cc index 32a0d67..9f3faf2 100644 --- a/components/safe_browsing/content/browser/async_check_tracker_unittest.cc +++ b/components/safe_browsing/content/browser/async_check_tracker_unittest.cc
@@ -121,7 +121,7 @@ navigation_id, mock_web_contents_getter_.Get(), /*complete_callback=*/base::NullCallback(), /*url_real_time_lookup_enabled=*/false, - /*can_urt_check_subresource_url=*/false, /*can_check_db=*/true, + /*can_check_db=*/true, /*can_check_high_confidence_allowlist=*/true, /*url_lookup_service_metric_suffix=*/"", /*url_lookup_service=*/nullptr,
diff --git a/components/safe_browsing/content/browser/browser_url_loader_throttle.cc b/components/safe_browsing/content/browser/browser_url_loader_throttle.cc index ce29341b..e2d94be 100644 --- a/components/safe_browsing/content/browser/browser_url_loader_throttle.cc +++ b/components/safe_browsing/content/browser/browser_url_loader_throttle.cc
@@ -214,8 +214,6 @@ url_lookup_service_ ? url_lookup_service_->CanCheckSafeBrowsingHighConfidenceAllowlist() : true; - bool can_urt_check_subresource_url = - url_lookup_service_ && url_lookup_service_->CanCheckSubresourceURL(); if (async_check_tracker_ && navigation_id_.has_value() && // Once |kSafeBrowsingSkipSubresources| is deprecated, the |kDocument| @@ -234,8 +232,7 @@ /*complete_callback=*/ base::BindRepeating(&BrowserURLLoaderThrottle::OnCompleteSyncCheck, weak_factory_.GetWeakPtr()), - /*url_real_time_lookup_enabled=*/false, - /*can_urt_check_subresource_url=*/false, can_check_db, + /*url_real_time_lookup_enabled=*/false, can_check_db, /*can_check_high_confidence_allowlist=*/true, /*url_lookup_service_metric_suffix=*/kNoRealTimeURLLookupService, /*url_lookup_service=*/nullptr, @@ -249,10 +246,9 @@ /*complete_callback=*/ base::BindRepeating(&BrowserURLLoaderThrottle::OnCompleteAsyncCheck, weak_factory_.GetWeakPtr()), - url_real_time_lookup_enabled_, can_urt_check_subresource_url, - can_check_db, can_check_high_confidence_allowlist, - url_lookup_service_metric_suffix_, url_lookup_service_, - hash_realtime_service_, hash_realtime_selection_, + url_real_time_lookup_enabled_, can_check_db, + can_check_high_confidence_allowlist, url_lookup_service_metric_suffix_, + url_lookup_service_, hash_realtime_service_, hash_realtime_selection_, /*is_async_check=*/true); if (on_sync_sb_checker_created_callback_for_testing_) { std::move(on_sync_sb_checker_created_callback_for_testing_).Run(); @@ -267,10 +263,9 @@ /*complete_callback=*/ base::BindRepeating(&BrowserURLLoaderThrottle::OnCompleteSyncCheck, weak_factory_.GetWeakPtr()), - url_real_time_lookup_enabled_, can_urt_check_subresource_url, - can_check_db, can_check_high_confidence_allowlist, - url_lookup_service_metric_suffix_, url_lookup_service_, - hash_realtime_service_, hash_realtime_selection_, + url_real_time_lookup_enabled_, can_check_db, + can_check_high_confidence_allowlist, url_lookup_service_metric_suffix_, + url_lookup_service_, hash_realtime_service_, hash_realtime_selection_, /*is_async_check=*/false); if (on_sync_sb_checker_created_callback_for_testing_) { std::move(on_sync_sb_checker_created_callback_for_testing_).Run();
diff --git a/components/safe_browsing/content/browser/browser_url_loader_throttle_unittest.cc b/components/safe_browsing/content/browser/browser_url_loader_throttle_unittest.cc index 8032c62..a50ff01e 100644 --- a/components/safe_browsing/content/browser/browser_url_loader_throttle_unittest.cc +++ b/components/safe_browsing/content/browser/browser_url_loader_throttle_unittest.cc
@@ -114,7 +114,7 @@ // RealTimeUrlLookupServiceBase: bool CanPerformFullURLLookup() const override { return true; } - bool CanCheckSubresourceURL() const override { return false; } + bool CanIncludeSubframeUrlInReferrerChain() const override { return false; } bool CanCheckSafeBrowsingDb() const override { return true; } bool CanCheckSafeBrowsingHighConfidenceAllowlist() const override { return true; @@ -123,14 +123,10 @@ std::string GetMetricSuffix() const override { return ".Mock"; } void StartLookup( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override {} void SendSampledRequest( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override {} private: @@ -143,8 +139,6 @@ bool CanSendPageLoadToken() const override { return false; } void GetAccessToken( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override {} std::optional<std::string> GetDMTokenString() const override { @@ -180,11 +174,9 @@ UnsafeResource::FrameTreeNodeId frame_tree_node_id, std::optional<int64_t> navigation_id, bool url_real_time_lookup_enabled, - bool can_urt_check_subresource_url, bool can_check_db, bool can_check_high_confidence_allowlist, std::string url_lookup_service_metric_suffix, - GURL last_committed_url, scoped_refptr<base::SequencedTaskRunner> ui_task_runner, base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui, base::WeakPtr<HashRealTimeService> hash_realtime_service_on_ui, @@ -202,11 +194,9 @@ frame_tree_node_id, navigation_id, url_real_time_lookup_enabled, - can_urt_check_subresource_url, can_check_db, can_check_high_confidence_allowlist, url_lookup_service_metric_suffix, - last_committed_url, ui_task_runner, url_lookup_service_on_ui, hash_realtime_service_on_ui, @@ -337,10 +327,9 @@ /*render_frame_token=*/std::nullopt, UnsafeResource::kNoFrameTreeNodeId, navigation_id, url_real_time_lookup_enabled, - /*can_urt_check_subresource_url=*/false, /*can_check_db=*/true, + /*can_check_db=*/true, /*can_check_high_confidence_allowlist=*/true, /*url_lookup_service_metric_suffix=*/"", - /*last_committed_url=*/GURL(), /*ui_task_runner=*/base::SequencedTaskRunner::GetCurrentDefault(), /*url_lookup_service_on_ui=*/nullptr, /*hash_realtime_service_on_ui=*/nullptr, @@ -362,10 +351,9 @@ /*render_frame_token=*/std::nullopt, UnsafeResource::kNoFrameTreeNodeId, /*navigation_id=*/0, url_real_time_lookup_enabled, - /*can_urt_check_subresource_url=*/false, /*can_check_db=*/true, + /*can_check_db=*/true, /*can_check_high_confidence_allowlist=*/true, /*url_lookup_service_metric_suffix=*/"", - /*last_committed_url=*/GURL(), /*ui_task_runner=*/base::SequencedTaskRunner::GetCurrentDefault(), /*url_lookup_service_on_ui=*/nullptr, /*hash_realtime_service_on_ui=*/nullptr,
diff --git a/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc b/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc index ab6919b..33490e98 100644 --- a/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc +++ b/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc
@@ -186,10 +186,9 @@ content::RenderFrameHost::kNoFrameTreeNodeId, /*navigation_id=*/std::nullopt, /*url_real_time_lookup_enabled=*/false, - /*can_urt_check_subresource_url=*/false, /*can_check_db=*/true, /*can_check_high_confidence_allowlist=*/true, /*url_lookup_service_metric_suffix=*/".None", - /*last_committed_url=*/GURL(), content::GetUIThreadTaskRunner({}), + content::GetUIThreadTaskRunner({}), /*url_lookup_service=*/nullptr, /*hash_realtime_service_on_ui=*/nullptr, /*hash_realtime_selection=*/
diff --git a/components/safe_browsing/content/browser/url_checker_on_sb.cc b/components/safe_browsing/content/browser/url_checker_on_sb.cc index 6d31ebba..1dba5315 100644 --- a/components/safe_browsing/content/browser/url_checker_on_sb.cc +++ b/components/safe_browsing/content/browser/url_checker_on_sb.cc
@@ -61,7 +61,6 @@ base::RepeatingCallback<content::WebContents*()> web_contents_getter, OnCompleteCheckCallback complete_callback, bool url_real_time_lookup_enabled, - bool can_urt_check_subresource_url, bool can_check_db, bool can_check_high_confidence_allowlist, std::string url_lookup_service_metric_suffix, @@ -75,7 +74,6 @@ web_contents_getter_(web_contents_getter), complete_callback_(std::move(complete_callback)), url_real_time_lookup_enabled_(url_real_time_lookup_enabled), - can_urt_check_subresource_url_(can_urt_check_subresource_url), can_check_db_(can_check_db), can_check_high_confidence_allowlist_(can_check_high_confidence_allowlist), url_lookup_service_metric_suffix_(url_lookup_service_metric_suffix), @@ -84,10 +82,6 @@ hash_realtime_selection_(hash_realtime_selection), creation_time_(base::TimeTicks::Now()), is_async_check_(is_async_check) { - content::WebContents* contents = web_contents_getter_.Run(); - if (!!contents) { - last_committed_url_ = contents->GetLastCommittedURL(); - } } UrlCheckerOnSB::~UrlCheckerOnSB() { @@ -116,9 +110,8 @@ params.has_user_gesture, url_checker_delegate, web_contents_getter_, nullptr, content::ChildProcessHost::kInvalidUniqueID, std::nullopt, frame_tree_node_id_, navigation_id_, url_real_time_lookup_enabled_, - can_urt_check_subresource_url_, can_check_db_, - can_check_high_confidence_allowlist_, url_lookup_service_metric_suffix_, - last_committed_url_, content::GetUIThreadTaskRunner({}), + can_check_db_, can_check_high_confidence_allowlist_, + url_lookup_service_metric_suffix_, content::GetUIThreadTaskRunner({}), url_lookup_service_, hash_realtime_service_, hash_realtime_selection_, is_async_check_); }
diff --git a/components/safe_browsing/content/browser/url_checker_on_sb.h b/components/safe_browsing/content/browser/url_checker_on_sb.h index 0a06db4..18a0773 100644 --- a/components/safe_browsing/content/browser/url_checker_on_sb.h +++ b/components/safe_browsing/content/browser/url_checker_on_sb.h
@@ -87,7 +87,6 @@ base::RepeatingCallback<content::WebContents*()> web_contents_getter, OnCompleteCheckCallback complete_callback, bool url_real_time_lookup_enabled, - bool can_urt_check_subresource_url, bool can_check_db, bool can_check_high_confidence_allowlist, std::string url_lookup_service_metric_suffix, @@ -154,12 +153,10 @@ base::RepeatingCallback<content::WebContents*()> web_contents_getter_; OnCompleteCheckCallback complete_callback_; bool url_real_time_lookup_enabled_ = false; - bool can_urt_check_subresource_url_ = false; bool can_check_db_ = true; bool can_check_high_confidence_allowlist_ = true; size_t pending_checks_ = 0; std::string url_lookup_service_metric_suffix_; - GURL last_committed_url_; // A list of URLs that are checked by |url_checker_|. std::vector<GURL> redirect_chain_; base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_;
diff --git a/components/safe_browsing/content/browser/web_api_handshake_checker.cc b/components/safe_browsing/content/browser/web_api_handshake_checker.cc index 17592bbd..f1f9b3d 100644 --- a/components/safe_browsing/content/browser/web_api_handshake_checker.cc +++ b/components/safe_browsing/content/browser/web_api_handshake_checker.cc
@@ -31,11 +31,6 @@ DCHECK(handshake_checker_); DCHECK(delegate_getter_); DCHECK(web_contents_getter_); - - content::WebContents* contents = web_contents_getter_.Run(); - if (!!contents) { - last_committed_url_ = contents->GetLastCommittedURL(); - } } void Check(const GURL& url) { @@ -78,9 +73,8 @@ /*render_frame_token=*/std::nullopt, frame_tree_node_id_, /*navigation_id=*/std::nullopt, /*url_real_time_lookup_enabled=*/false, - /*can_urt_check_subresource_url=*/false, /*can_check_db=*/true, /*can_check_high_confidence_allowlist=*/true, - /*url_lookup_service_metric_suffix=*/".None", last_committed_url_, + /*url_lookup_service_metric_suffix=*/".None", content::GetUIThreadTaskRunner({}), /*url_lookup_service=*/nullptr, /*hash_realtime_service_on_ui=*/nullptr, @@ -141,7 +135,6 @@ GetDelegateCallback delegate_getter_; GetWebContentsCallback web_contents_getter_; const int frame_tree_node_id_; - GURL last_committed_url_; std::unique_ptr<SafeBrowsingUrlCheckerImpl> url_checker_; base::WeakPtrFactory<CheckerOnSB> weak_factory_{this}; };
diff --git a/components/safe_browsing/core/browser/realtime/policy_engine.cc b/components/safe_browsing/core/browser/realtime/policy_engine.cc index d570e06..6a54bbd3 100644 --- a/components/safe_browsing/core/browser/realtime/policy_engine.cc +++ b/components/safe_browsing/core/browser/realtime/policy_engine.cc
@@ -120,18 +120,10 @@ // static bool RealTimePolicyEngine::CanPerformFullURLLookupForRequestDestination( - network::mojom::RequestDestination request_destination, - bool can_urt_check_subresource_url) { + network::mojom::RequestDestination request_destination) { UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.RT.RequestDestinations.Requested", request_destination); - if (request_destination == network::mojom::RequestDestination::kDocument) { - return true; - } - if (network::IsRequestDestinationEmbeddedFrame(request_destination) && - can_urt_check_subresource_url) { - return true; - } - return false; + return request_destination == network::mojom::RequestDestination::kDocument; } } // namespace safe_browsing
diff --git a/components/safe_browsing/core/browser/realtime/policy_engine.h b/components/safe_browsing/core/browser/realtime/policy_engine.h index c43816e..8eb0ef1 100644 --- a/components/safe_browsing/core/browser/realtime/policy_engine.h +++ b/components/safe_browsing/core/browser/realtime/policy_engine.h
@@ -35,12 +35,11 @@ using ClientConfiguredForTokenFetchesCallback = base::OnceCallback<bool(bool user_has_enabled_enhanced_protection)>; - // Return true if full URL lookups are enabled for |request_destination|. If - // |can_urt_check_subresource_url| is set to false, return true only if - // |request_destination| is |kDocument|. + // Return true if full URL lookups are enabled for |request_destination|. + // TODO(crbug.com/324108312): Remove this function as part of the cleanup + // after subresource checks are disabled. static bool CanPerformFullURLLookupForRequestDestination( - network::mojom::RequestDestination request_destination, - bool can_urt_check_subresource_url); + network::mojom::RequestDestination request_destination); // Return true if the profile is not Incognito and real-time fetches are // available in the user's country, and the user has opted in to ESB or MBB.
diff --git a/components/safe_browsing/core/browser/realtime/policy_engine_unittest.cc b/components/safe_browsing/core/browser/realtime/policy_engine_unittest.cc index fd25233..444a975 100644 --- a/components/safe_browsing/core/browser/realtime/policy_engine_unittest.cc +++ b/components/safe_browsing/core/browser/realtime/policy_engine_unittest.cc
@@ -191,9 +191,8 @@ } } -TEST_F( - RealTimePolicyEngineTest, - TestCanPerformFullURLLookup_EnabledMainFrameOnlyForSubresourceDisabledUser) { +TEST_F(RealTimePolicyEngineTest, + TestCanPerformFullURLLookup_EnabledMainFrameOnly) { for (int i = 0; i <= static_cast<int>(network::mojom::RequestDestination::kMaxValue); i++) { @@ -201,7 +200,7 @@ static_cast<network::mojom::RequestDestination>(i); bool enabled = RealTimePolicyEngine::CanPerformFullURLLookupForRequestDestination( - request_destination, /*can_urt_check_subresource_url=*/false); + request_destination); switch (request_destination) { case network::mojom::RequestDestination::kDocument: EXPECT_TRUE(enabled); @@ -213,31 +212,6 @@ } } -TEST_F( - RealTimePolicyEngineTest, - TestCanPerformFullURLLookup_EnabledNonMainFrameForSubresourceEnabledUser) { - for (int i = 0; - i <= static_cast<int>(network::mojom::RequestDestination::kMaxValue); - i++) { - network::mojom::RequestDestination request_destination = - static_cast<network::mojom::RequestDestination>(i); - bool enabled = - RealTimePolicyEngine::CanPerformFullURLLookupForRequestDestination( - request_destination, /*can_urt_check_subresource_url=*/true); - switch (request_destination) { - case network::mojom::RequestDestination::kDocument: - case network::mojom::RequestDestination::kIframe: - case network::mojom::RequestDestination::kFrame: - case network::mojom::RequestDestination::kFencedframe: - EXPECT_TRUE(enabled); - break; - default: - EXPECT_FALSE(enabled); - break; - } - } -} - TEST_F(RealTimePolicyEngineTest, TestIsInExcludedCountry) { const std::string non_excluded_countries[] = {"be", "br", "ca", "de", "es", "fr", "ie", "in", "jp", "nl",
diff --git a/components/safe_browsing/core/browser/realtime/url_lookup_service.cc b/components/safe_browsing/core/browser/realtime/url_lookup_service.cc index 18680be5..f152e7b 100644 --- a/components/safe_browsing/core/browser/realtime/url_lookup_service.cc +++ b/components/safe_browsing/core/browser/realtime/url_lookup_service.cc
@@ -78,14 +78,12 @@ void RealTimeUrlLookupService::GetAccessToken( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner) { token_fetcher_->Start(base::BindOnce( &RealTimeUrlLookupService::OnGetAccessToken, weak_factory_.GetWeakPtr(), - url, last_committed_url, is_mainframe, std::move(response_callback), - std::move(callback_task_runner), base::TimeTicks::Now())); + url, std::move(response_callback), std::move(callback_task_runner), + base::TimeTicks::Now())); } void RealTimeUrlLookupService::OnPrefChanged() { @@ -96,8 +94,6 @@ void RealTimeUrlLookupService::OnGetAccessToken( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, base::TimeTicks get_token_start_time, @@ -109,8 +105,8 @@ base::TimeTicks::Now() - get_token_start_time); base::UmaHistogramBoolean("SafeBrowsing.RT.HasTokenFromFetcher", !access_token.empty()); - SendRequest(url, last_committed_url, is_mainframe, access_token, - std::move(response_callback), std::move(callback_task_runner), + SendRequest(url, access_token, std::move(response_callback), + std::move(callback_task_runner), /* is_sampled_report */ false); } @@ -140,7 +136,7 @@ return true; } -bool RealTimeUrlLookupService::CanCheckSubresourceURL() const { +bool RealTimeUrlLookupService::CanIncludeSubframeUrlInReferrerChain() const { return IsEnhancedProtectionEnabled(*pref_service_) && CanPerformFullURLLookup(); }
diff --git a/components/safe_browsing/core/browser/realtime/url_lookup_service.h b/components/safe_browsing/core/browser/realtime/url_lookup_service.h index 4c113b3..70ef129e 100644 --- a/components/safe_browsing/core/browser/realtime/url_lookup_service.h +++ b/components/safe_browsing/core/browser/realtime/url_lookup_service.h
@@ -76,7 +76,7 @@ // RealTimeUrlLookupServiceBase: bool CanPerformFullURLLookup() const override; - bool CanCheckSubresourceURL() const override; + bool CanIncludeSubframeUrlInReferrerChain() const override; bool CanCheckSafeBrowsingDb() const override; bool CanCheckSafeBrowsingHighConfidenceAllowlist() const override; void Shutdown() override; @@ -100,8 +100,6 @@ bool CanSendPageLoadToken() const override; void GetAccessToken( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override; std::optional<std::string> GetDMTokenString() const override; @@ -120,8 +118,6 @@ // Called when the access token is obtained from |token_fetcher_|. void OnGetAccessToken( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, base::TimeTicks get_token_start_time,
diff --git a/components/safe_browsing/core/browser/realtime/url_lookup_service_base.cc b/components/safe_browsing/core/browser/realtime/url_lookup_service_base.cc index 128c312..40c8e5f 100644 --- a/components/safe_browsing/core/browser/realtime/url_lookup_service_base.cc +++ b/components/safe_browsing/core/browser/realtime/url_lookup_service_base.cc
@@ -296,13 +296,11 @@ void RealTimeUrlLookupServiceBase::SendSampledRequest( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, scoped_refptr<base::SequencedTaskRunner> callback_task_runner) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(url.is_valid()); - SendRequest(url, last_committed_url, is_mainframe, + SendRequest(url, /* access_token_string */ std::string(), /* response_callback */ base::NullCallback(), std::move(callback_task_runner), /* is_sampled_report */ true); @@ -310,8 +308,6 @@ void RealTimeUrlLookupServiceBase::StartLookup( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -339,11 +335,10 @@ } if (CanPerformFullURLLookupWithToken()) { - GetAccessToken(url, last_committed_url, is_mainframe, - std::move(response_callback), + GetAccessToken(url, std::move(response_callback), std::move(callback_task_runner)); } else { - SendRequest(url, last_committed_url, is_mainframe, + SendRequest(url, /* access_token_string */ std::string(), std::move(response_callback), std::move(callback_task_runner), /* is_sampled_report */ false); @@ -352,15 +347,13 @@ void RealTimeUrlLookupServiceBase::SendRequest( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, const std::string& access_token_string, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, bool is_sampled_report) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - std::unique_ptr<RTLookupRequest> request = FillRequestProto( - url, last_committed_url, is_mainframe, is_sampled_report); + std::unique_ptr<RTLookupRequest> request = + FillRequestProto(url, is_sampled_report); RecordRequestPopulationWithAndWithoutSuffix( "SafeBrowsing.RT.Request.UserPopulation", GetMetricSuffix(), request->population().user_population()); @@ -541,8 +534,6 @@ std::unique_ptr<RTLookupRequest> RealTimeUrlLookupServiceBase::FillRequestProto( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, bool is_sampled_report) { auto request = std::make_unique<RTLookupRequest>(); request->set_url(SanitizeURL(url).spec()); @@ -551,8 +542,7 @@ request->set_os_type(GetRTLookupRequestOSType()); request->set_report_type(is_sampled_report ? RTLookupRequest::SAMPLED_REPORT : RTLookupRequest::FULL_REPORT); - request->set_frame_type(is_mainframe ? RTLookupRequest::MAIN_FRAME - : RTLookupRequest::SUB_FRAME); + request->set_frame_type(RTLookupRequest::MAIN_FRAME); std::optional<std::string> dm_token_string = GetDMTokenString(); if (dm_token_string.has_value()) { request->set_dm_token(dm_token_string.value()); @@ -563,34 +553,15 @@ referrer_chain_provider_->IdentifyReferrerChainByPendingEventURL( SanitizeURL(url), GetReferrerUserGestureLimit(), request->mutable_referrer_chain()); - SanitizeReferrerChainEntries( - request->mutable_referrer_chain(), - GetMinAllowedTimestampForReferrerChains(), - /*should_remove_subresource_url=*/!CanCheckSubresourceURL()); + SanitizeReferrerChainEntries(request->mutable_referrer_chain(), + GetMinAllowedTimestampForReferrerChains(), + /*should_remove_subresource_url=*/ + !CanIncludeSubframeUrlInReferrerChain()); } if (CanSendPageLoadToken() && cache_manager_) { ChromeUserPopulation::PageLoadToken token; - if (is_mainframe) { - // If the current check is for a mainframe URL, the token must be - // refreshed. - token = cache_manager_->CreatePageLoadToken(url); - } else { - // If the current check is for a subframe URL, use |last_committed_url| to - // get the page load token. |last_committed_url| is used as a proxy for - // the current mainframe URL, because the mainframe URL has to be - // committed before subframe navigation starts. - token = cache_manager_->GetPageLoadToken(last_committed_url); - RecordBooleanWithAndWithoutSuffix( - "SafeBrowsing.PageLoadToken.RealTimeCheckHasToken", GetMetricSuffix(), - token.has_token_value()); - // It's possible that the token is not found because the last committed - // URL is not checked by real time URL check. Create a new page load token - // in this case. - if (!token.has_token_value()) { - token = cache_manager_->CreatePageLoadToken(last_committed_url); - } - } + token = cache_manager_->CreatePageLoadToken(url); request->mutable_population()->mutable_page_load_tokens()->Add()->Swap( &token); }
diff --git a/components/safe_browsing/core/browser/realtime/url_lookup_service_base.h b/components/safe_browsing/core/browser/realtime/url_lookup_service_base.h index 2bfc1134..c526a1a1 100644 --- a/components/safe_browsing/core/browser/realtime/url_lookup_service_base.h +++ b/components/safe_browsing/core/browser/realtime/url_lookup_service_base.h
@@ -103,13 +103,9 @@ // Start the full URL lookup for |url| and call |response_callback| // on |callback_task_runner| when response is received. - // |last_committed_url| and |is_mainframe| are for obtaining page - // load token for the request. // This function is overridden in unit tests. virtual void StartLookup( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner); @@ -117,8 +113,6 @@ // but to send Protego sampled request specifically. virtual void SendSampledRequest( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, scoped_refptr<base::SequencedTaskRunner> callback_task_runner); // Helper function to return a weak pointer. @@ -129,8 +123,9 @@ // record profile and the finch flag. virtual bool CanPerformFullURLLookup() const = 0; - // Returns true if this profile has opted-in to check subresource URLs. - virtual bool CanCheckSubresourceURL() const = 0; + // Returns true if this profile has opted-in to include subframe URLs in + // referrer chain. + virtual bool CanIncludeSubframeUrlInReferrerChain() const = 0; // Returns whether safe browsing database can be checked when real time URL // check is enabled. @@ -161,8 +156,6 @@ // It also attached an auth header if |access_token_string| is non-empty. void SendRequest( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, const std::string& access_token_string, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, @@ -199,8 +192,6 @@ // true. virtual void GetAccessToken( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner) = 0; @@ -275,8 +266,6 @@ // Fills in fields in |RTLookupRequest|. std::unique_ptr<RTLookupRequest> FillRequestProto( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, bool is_sampled_report); // Logs |request| and |oauth_token| on any open
diff --git a/components/safe_browsing/core/browser/realtime/url_lookup_service_unittest.cc b/components/safe_browsing/core/browser/realtime/url_lookup_service_unittest.cc index 665a077..8ed7b962 100644 --- a/components/safe_browsing/core/browser/realtime/url_lookup_service_unittest.cc +++ b/components/safe_browsing/core/browser/realtime/url_lookup_service_unittest.cc
@@ -180,11 +180,8 @@ } std::unique_ptr<RTLookupRequest> FillRequestProto( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, bool is_sampled_report) { - return rt_service_->FillRequestProto(url, last_committed_url, is_mainframe, - is_sampled_report); + return rt_service_->FillRequestProto(url, is_sampled_report); } std::unique_ptr<RTLookupResponse> GetCachedRealTimeUrlVerdict( const GURL& url) { @@ -335,8 +332,7 @@ EXPECT_CALL(request_callback, Run(_)).Times(1); EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ false, /* is_cached_response */ false, _)); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); task_environment_.RunUntilIdle(); } @@ -354,8 +350,6 @@ sync_preferences::TestingPrefServiceSyncable test_pref_service_; base::test::ScopedFeatureList feature_list_; std::unique_ptr<MockReferrerChainProvider> referrer_chain_provider_; - GURL last_committed_url_ = GURL("http://lastcommitted.test"); - bool is_mainframe_ = true; }; TEST_F(RealTimeUrlLookupServiceTest, TestFillRequestProto) { @@ -369,8 +363,7 @@ {"http://example.com/abc#123", "http://example.com/abc#123"}}; for (size_t i = 0; i < std::size(sanitize_url_cases); i++) { GURL url(sanitize_url_cases[i].url); - auto result = FillRequestProto(url, last_committed_url_, is_mainframe_, - /*is_sampled_report=*/i % 2 == 0); + auto result = FillRequestProto(url, /*is_sampled_report=*/i % 2 == 0); if (i % 2 == 0) { EXPECT_EQ(/* sampled report */ 2, result->report_type()); } else { @@ -397,46 +390,15 @@ GURL url(kTestUrl); GURL subframe_url(kTestSubframeUrl); - // mainframe URL - { - cache_manager_->SetPageLoadTokenForTesting( - url, CreatePageLoadToken("url_page_load_token")); - auto request = FillRequestProto(url, GURL(), /*is_mainframe=*/true, - /*is_sampled_report=*/false); - ASSERT_EQ(1, request->population().page_load_tokens_size()); - // The token should be re-generated for the mainframe URL. - EXPECT_NE("url_page_load_token", - request->population().page_load_tokens(0).token_value()); - EXPECT_EQ(ChromeUserPopulation::PageLoadToken::CLIENT_GENERATION, - request->population().page_load_tokens(0).token_source()); - } - - // subframe URL, token for the mainframe URL not found. - { - ChromeUserPopulation::PageLoadToken empty_token; - cache_manager_->SetPageLoadTokenForTesting(url, empty_token); - auto request = FillRequestProto(subframe_url, url, /*is_mainframe=*/false, - /*is_sampled_report=*/false); - ASSERT_EQ(1, request->population().page_load_tokens_size()); - // The token should be generated for the mainframe URL. - std::string token_value = - request->population().page_load_tokens(0).token_value(); - EXPECT_EQ(token_value, cache_manager_->GetPageLoadToken(url).token_value()); - EXPECT_FALSE( - cache_manager_->GetPageLoadToken(subframe_url).has_token_value()); - } - - // subframe URL, token for the mainframe URL found. - { - cache_manager_->SetPageLoadTokenForTesting( - url, CreatePageLoadToken("url_page_load_token")); - auto request = FillRequestProto(subframe_url, url, /*is_mainframe=*/false, - /*is_sampled_report=*/false); - ASSERT_EQ(1, request->population().page_load_tokens_size()); - // The token for the mainframe URL should be reused. - EXPECT_EQ("url_page_load_token", - request->population().page_load_tokens(0).token_value()); - } + cache_manager_->SetPageLoadTokenForTesting( + url, CreatePageLoadToken("url_page_load_token")); + auto request = FillRequestProto(url, /*is_sampled_report=*/false); + ASSERT_EQ(1, request->population().page_load_tokens_size()); + // The token should be re-generated for the mainframe URL. + EXPECT_NE("url_page_load_token", + request->population().page_load_tokens(0).token_value()); + EXPECT_EQ(ChromeUserPopulation::PageLoadToken::CLIENT_GENERATION, + request->population().page_load_tokens(0).token_source()); } TEST_F(RealTimeUrlLookupServiceTest, TestGetSBThreatTypeForRTThreatType) { @@ -525,8 +487,7 @@ EXPECT_CALL(request_callback, Run(_)).Times(0); base::MockCallback<RTLookupResponseCallback> response_callback; - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ true, @@ -553,8 +514,7 @@ "example.test/", RTLookupResponse::ThreatInfo::COVERING_MATCH); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - base::DoNothing(), + rt_service()->StartLookup(url, base::DoNothing(), base::SequencedTaskRunner::GetCurrentDefault()); FulfillAccessTokenRequest("access_token_string"); @@ -578,8 +538,7 @@ "example.test/", RTLookupResponse::ThreatInfo::COVERING_MATCH); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - base::DoNothing(), + rt_service()->StartLookup(url, base::DoNothing(), base::SequencedTaskRunner::GetCurrentDefault()); task_environment_.RunUntilIdle(); @@ -603,8 +562,7 @@ RTLookupResponse::ThreatInfo::COVERING_MATCH); task_environment_.RunUntilIdle(); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - base::DoNothing(), + rt_service()->StartLookup(url, base::DoNothing(), base::SequencedTaskRunner::GetCurrentDefault()); task_environment_.RunUntilIdle(); @@ -629,8 +587,7 @@ RTLookupResponse::ThreatInfo::COVERING_MATCH); task_environment_.RunUntilIdle(); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - base::DoNothing(), + rt_service()->StartLookup(url, base::DoNothing(), base::SequencedTaskRunner::GetCurrentDefault()); task_environment_.RunUntilIdle(); @@ -653,8 +610,7 @@ "example.test/", RTLookupResponse::ThreatInfo::COVERING_MATCH); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - base::DoNothing(), + rt_service()->StartLookup(url, base::DoNothing(), base::SequencedTaskRunner::GetCurrentDefault()); FulfillAccessTokenRequest("access_token_string"); @@ -678,8 +634,7 @@ "example.test/", RTLookupResponse::ThreatInfo::COVERING_MATCH); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - base::DoNothing(), + rt_service()->StartLookup(url, base::DoNothing(), base::SequencedTaskRunner::GetCurrentDefault()); FulfillAccessTokenRequest("access_token_string"); @@ -722,8 +677,7 @@ })); test_url_loader_factory_.SetInterceptor(interceptor.GetCallback()); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); EXPECT_TRUE(raw_token_fetcher()->WasStartCalled()); @@ -767,8 +721,7 @@ })); test_url_loader_factory_.SetInterceptor(interceptor.GetCallback()); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); EXPECT_TRUE(raw_token_fetcher()->WasStartCalled()); @@ -804,8 +757,7 @@ })); test_url_loader_factory_.SetInterceptor(interceptor.GetCallback()); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); task_environment_.RunUntilIdle(); @@ -831,8 +783,7 @@ EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ false, /* is_cached_response */ false, _)); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); FulfillAccessTokenRequest("invalid_token_string"); @@ -853,8 +804,7 @@ EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ false, /* is_cached_response */ false, _)); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); FulfillAccessTokenRequest("invalid_token_string"); @@ -907,8 +857,7 @@ })); test_url_loader_factory_.SetInterceptor(interceptor.GetCallback()); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); task_environment_.RunUntilIdle(); @@ -980,8 +929,7 @@ EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ true, /* is_cached_response */ false, _)); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); task_environment_.RunUntilIdle(); @@ -1050,8 +998,7 @@ EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ true, /* is_cached_response */ false, _)); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); task_environment_.RunUntilIdle(); @@ -1126,8 +1073,7 @@ })); test_url_loader_factory_.SetInterceptor(interceptor.GetCallback()); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); task_environment_.RunUntilIdle(); @@ -1146,8 +1092,7 @@ EXPECT_CALL(response_callback, Run(_, _, _)).Times(0); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); rt_service()->Shutdown(); @@ -1188,8 +1133,7 @@ EXPECT_CALL(request_callback, Run(_)).Times(0); EXPECT_CALL(response_callback, Run(_, _, _)).Times(0); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); rt_service()->Shutdown(); @@ -1215,8 +1159,7 @@ test_url_loader_factory_.SetInterceptor(interceptor.GetCallback()); rt_service()->SendSampledRequest( - url, last_committed_url_, is_mainframe_, - base::SequencedTaskRunner::GetCurrentDefault()); + url, base::SequencedTaskRunner::GetCurrentDefault()); rt_service()->Shutdown(); task_environment_.RunUntilIdle(); @@ -1246,8 +1189,7 @@ base::MockCallback<RTLookupResponseCallback> response_callback; EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ !make_fail, /* is_cached_response */ false, _)); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); task_environment_.RunUntilIdle(); }; @@ -1297,8 +1239,7 @@ base::MockCallback<RTLookupResponseCallback> response_callback; EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ false, /* is_cached_response */ false, _)); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); task_environment_.RunUntilIdle(); }; @@ -1338,8 +1279,7 @@ EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ true, /* is_cached_response */ true, _)); test_url_loader_factory_.SetInterceptor(request_callback.Get()); - rt_service()->StartLookup(cached_url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(cached_url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); task_environment_.RunUntilIdle(); @@ -1364,8 +1304,7 @@ EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ false, /* is_cached_response */ false, _)); test_url_loader_factory_.SetInterceptor(request_callback.Get()); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); task_environment_.RunUntilIdle(); @@ -1385,8 +1324,7 @@ base::MockCallback<RTLookupResponseCallback> response_callback; EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ false, /* is_cached_response */ false, _)); - rt_service()->StartLookup(url, last_committed_url_, is_mainframe_, - response_callback.Get(), + rt_service()->StartLookup(url, response_callback.Get(), base::SequencedTaskRunner::GetCurrentDefault()); task_environment_.RunUntilIdle(); };
diff --git a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc index 583ba992..bb031353 100644 --- a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc +++ b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc
@@ -116,11 +116,9 @@ UnsafeResource::FrameTreeNodeId frame_tree_node_id, std::optional<int64_t> navigation_id, bool url_real_time_lookup_enabled, - bool can_urt_check_subresource_url, bool can_check_db, bool can_check_high_confidence_allowlist, std::string url_lookup_service_metric_suffix, - GURL last_committed_url, scoped_refptr<base::SequencedTaskRunner> ui_task_runner, base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui, base::WeakPtr<HashRealTimeService> hash_realtime_service_on_ui, @@ -139,17 +137,14 @@ url_checker_delegate_(std::move(url_checker_delegate)), database_manager_(url_checker_delegate_->GetDatabaseManager()), url_real_time_lookup_enabled_(url_real_time_lookup_enabled), - can_urt_check_subresource_url_(can_urt_check_subresource_url), can_check_db_(can_check_db), can_check_high_confidence_allowlist_(can_check_high_confidence_allowlist), url_lookup_service_metric_suffix_(url_lookup_service_metric_suffix), - last_committed_url_(last_committed_url), ui_task_runner_(ui_task_runner), url_lookup_service_on_ui_(url_lookup_service_on_ui), hash_realtime_service_on_ui_(hash_realtime_service_on_ui), hash_realtime_selection_(hash_realtime_selection), is_async_check_(is_async_check) { - DCHECK(!can_urt_check_subresource_url_ || url_real_time_lookup_enabled_); DCHECK(url_real_time_lookup_enabled_ || can_check_db_); // This object is used exclusively on the IO thread but may be constructed on @@ -466,10 +461,14 @@ DCHECK(!lookup_mechanism_runner_); if (CanPerformFullURLLookup(url)) { performed_check = PerformedCheck::kUrlRealTimeCheck; + // TODO(crbug.com/324108312): Remove this CHECK after we remove subresource + // support in this class. + CHECK(request_destination_ == + network::mojom::RequestDestination::kDocument); lookup_mechanism = std::make_unique<UrlRealTimeMechanism>( - url, url_checker_delegate_->GetThreatTypes(), request_destination_, - database_manager_, can_check_db_, can_check_high_confidence_allowlist_, - url_lookup_service_metric_suffix_, last_committed_url_, ui_task_runner_, + url, url_checker_delegate_->GetThreatTypes(), database_manager_, + can_check_db_, can_check_high_confidence_allowlist_, + url_lookup_service_metric_suffix_, ui_task_runner_, url_lookup_service_on_ui_, url_checker_delegate_, web_contents_getter_); } else if (!can_check_db_) { return KickOffLookupMechanismResult( @@ -584,7 +583,7 @@ bool SafeBrowsingUrlCheckerImpl::CanPerformFullURLLookup(const GURL& url) { return url_real_time_lookup_enabled_ && RealTimePolicyEngine::CanPerformFullURLLookupForRequestDestination( - request_destination_, can_urt_check_subresource_url_) && + request_destination_) && RealTimeUrlLookupServiceBase::CanCheckUrl(url); }
diff --git a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h index 12cd887..d57a440c 100644 --- a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h +++ b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h
@@ -95,12 +95,6 @@ // which type of hash-prefix real-time lookup the profile is eligible for, if // any. These two must be computed in advance, since this class only exists // on the IO thread. - // |can_urt_check_subresource_url| indicates whether or not the profile has - // enabled real time URL lookups for subresource URLs. If this value is true, - // then |url_real_time_lookup_enabled| must also be true. - // |last_committed_url| is used for obtaining the page load token when the - // URL being checked is not a mainframe URL. Only used when URL real time - // lookup is performed. // |webui_delegate_| is allowed to be null. If non-null, it must outlive this // object. // TODO(crbug.com/1103222): Add an iOS-specific WebUIDelegate implementation @@ -123,11 +117,9 @@ frame_tree_node_id, std::optional<int64_t> navigation_id, bool url_real_time_lookup_enabled, - bool can_urt_check_subresource_url, bool can_check_db, bool can_check_high_confidence_allowlist, std::string url_lookup_service_metric_suffix, - GURL last_committed_url, scoped_refptr<base::SequencedTaskRunner> ui_task_runner, base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui, base::WeakPtr<HashRealTimeService> hash_realtime_service_on_ui, @@ -315,9 +307,6 @@ // Whether real time URL lookup is enabled for this request. bool url_real_time_lookup_enabled_; - // Whether non mainframe url can be checked for this profile. - bool can_urt_check_subresource_url_; - // Whether safe browsing database can be checked. It is set to false when // enterprise real time URL lookup is enabled and safe browsing is disabled // for this profile. @@ -330,11 +319,6 @@ // URL Lookup service suffix for logging metrics. std::string url_lookup_service_metric_suffix_; - // The last committed URL when the checker is constructed. It is used to - // obtain page load token when the URL being checked is not a mainframe URL. - // Only used when real time lookup is performed. - GURL last_committed_url_; - // The task runner for the UI thread. scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
diff --git a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl_unittest.cc b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl_unittest.cc index c71ae11..e2ffa49 100644 --- a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl_unittest.cc +++ b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl_unittest.cc
@@ -238,8 +238,6 @@ // if the threat type for the |gurl| is not set in advance. void StartLookup( const GURL& gurl, - const GURL& last_committed_url, - bool is_mainframe, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override { std::string url = gurl.spec(); @@ -290,8 +288,6 @@ void SendSampledRequest( const GURL& gurl, - const GURL& last_committed_url, - bool is_mainframe, scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override {} // |should_complete_lookup| should generally be true, unless you specifically @@ -310,7 +306,7 @@ // RealTimeUrlLookupServiceBase: bool CanPerformFullURLLookup() const override { return true; } - bool CanCheckSubresourceURL() const override { return false; } + bool CanIncludeSubframeUrlInReferrerChain() const override { return false; } bool CanCheckSafeBrowsingDb() const override { return true; } bool CanCheckSafeBrowsingHighConfidenceAllowlist() const override { return true; @@ -333,8 +329,6 @@ bool CanSendPageLoadToken() const override { return false; } void GetAccessToken( const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, RTLookupResponseCallback response_callback, scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override {} std::optional<std::string> GetDMTokenString() const override { @@ -400,7 +394,6 @@ struct CreateSafeBrowsingUrlCheckerOptionalArgs { network::mojom::RequestDestination request_destination = network::mojom::RequestDestination::kDocument; - bool can_urt_check_subresource_url = false; std::string url_lookup_service_metric_suffix = ".Enterprise"; }; @@ -433,12 +426,10 @@ mock_web_contents_getter.Get(), /*weak_web_state=*/nullptr, UnsafeResource::kNoRenderProcessId, std::nullopt, UnsafeResource::kNoFrameTreeNodeId, /*navigation_id=*/std::nullopt, - url_real_time_lookup_enabled, - optional_args.can_urt_check_subresource_url, can_check_safe_browsing_db, + url_real_time_lookup_enabled, can_check_safe_browsing_db, /*can_check_high_confidence_allowlist=*/true, /*url_lookup_service_metric_suffix=*/ optional_args.url_lookup_service_metric_suffix, - /*last_committed_url=*/GURL(), base::SequencedTaskRunner::GetCurrentDefault(), url_real_time_lookup_enabled ? url_lookup_service_->GetWeakPtr() : nullptr, @@ -478,33 +469,17 @@ } void CheckUrlRealTimeLocalMatchMetrics( std::optional<bool> expected_local_match_result, - std::optional<bool> expected_mainframe_log, std::optional<bool> expect_url_lookup_service_metric_suffix) { ASSERT_EQ(expected_local_match_result.has_value(), - expected_mainframe_log.has_value()); - ASSERT_EQ(expected_local_match_result.has_value(), expect_url_lookup_service_metric_suffix.has_value()); if (!expected_local_match_result.has_value()) { histogram_tester_.ExpectTotalCount( /*name=*/"SafeBrowsing.RT.LocalMatch.Result", /*expected_count=*/0); - histogram_tester_.ExpectTotalCount( - /*name=*/"SafeBrowsing.RT.LocalMatch.Result.Mainframe", - /*expected_count=*/0); - histogram_tester_.ExpectTotalCount( - /*name=*/"SafeBrowsing.RT.LocalMatch.Result.NonMainframe", - /*expected_count=*/0); } else { AsyncMatch expected_local_match_result_value = expected_local_match_result.value() ? AsyncMatch::MATCH : AsyncMatch::NO_MATCH; - histogram_tester_.ExpectUniqueSample( - /*name=*/"SafeBrowsing.RT.LocalMatch.Result", - /*sample=*/expected_local_match_result_value, - /*expected_bucket_count=*/1); - std::string expected_base_histogram = - expected_mainframe_log.value() - ? "SafeBrowsing.RT.LocalMatch.Result.Mainframe" - : "SafeBrowsing.RT.LocalMatch.Result.NonMainframe"; + std::string expected_base_histogram = "SafeBrowsing.RT.LocalMatch.Result"; histogram_tester_.ExpectUniqueSample( /*name=*/expected_base_histogram, /*sample=*/expected_local_match_result_value, @@ -684,7 +659,7 @@ task_environment_.RunUntilIdle(); CheckUrlRealTimeLocalMatchMetrics( - /*expected_local_match_result=*/true, /*expected_mainframe_log=*/true, + /*expected_local_match_result=*/true, /*expect_url_lookup_service_metric_suffix=*/true); } @@ -725,48 +700,38 @@ "SafeBrowsing.RT.GetCache.FallbackThreatType", /*expected_count=*/0); CheckUrlRealTimeLocalMatchMetrics( - /*expected_local_match_result=*/false, /*expected_mainframe_log=*/true, + /*expected_local_match_result=*/false, /*expect_url_lookup_service_metric_suffix=*/true); } TEST_F(SafeBrowsingUrlCheckerTest, - CheckUrl_UrlRealTimeEnabledSafeUrl_NonMainframe) { + CheckUrl_UrlRealTimeEnabledSafeBrowsingDisabled_NonMainframe) { base::HistogramTester histograms; auto safe_browsing_url_checker = CreateSafeBrowsingUrlChecker( /*url_real_time_lookup_enabled=*/true, - /*can_check_safe_browsing_db=*/true, + /*can_check_safe_browsing_db=*/false, /*hash_real_time_selection=*/ hash_realtime_utils::HashRealTimeSelection::kNone, /*optional_args=*/ - {.request_destination = network::mojom::RequestDestination::kFrame, - .can_urt_check_subresource_url = true}); + {.request_destination = network::mojom::RequestDestination::kFrame}); GURL url("https://example.test/"); - database_manager_->SetAllowlistLookupDetailsForUrl(url, /*match=*/false, - {"RT"}); - url_lookup_service_->SetThreatTypeForUrl(url, SB_THREAT_TYPE_SAFE, - /*should_complete_lookup=*/true); base::MockCallback<SafeBrowsingUrlCheckerImpl::NativeCheckUrlCallback> callback; - EXPECT_CALL( - callback, - Run(_, /*proceed=*/true, /*showed_interstitial=*/false, - /*has_post_commit_interstitial_skipped=*/false, - SafeBrowsingUrlCheckerImpl::PerformedCheck::kUrlRealTimeCheck)); + EXPECT_CALL(callback, + Run(_, /*proceed=*/true, /*showed_interstitial=*/false, + /*has_post_commit_interstitial_skipped=*/false, + SafeBrowsingUrlCheckerImpl::PerformedCheck::kCheckSkipped)); EXPECT_CALL(*url_checker_delegate_, StartDisplayingBlockingPageHelper(_, _, _, _, _)) .Times(0); safe_browsing_url_checker->CheckUrl(url, "GET", callback.Get()); task_environment_.RunUntilIdle(); - histogram_tester_.ExpectUniqueSample("SafeBrowsing.CheckUrl.Timeout", - /*sample=*/false, - /*expected_bucket_count=*/1); - CheckUrlRealTimeLocalMatchMetrics( - /*expected_local_match_result=*/false, /*expected_mainframe_log=*/false, - /*expect_url_lookup_service_metric_suffix=*/true); + /*expected_local_match_result=*/std::nullopt, + /*expect_url_lookup_service_metric_suffix=*/std::nullopt); } TEST_F(SafeBrowsingUrlCheckerTest, @@ -803,7 +768,7 @@ /*expected_bucket_count=*/1); CheckUrlRealTimeLocalMatchMetrics( - /*expected_local_match_result=*/false, /*expected_mainframe_log=*/true, + /*expected_local_match_result=*/false, /*expect_url_lookup_service_metric_suffix=*/false); } @@ -844,7 +809,7 @@ /*sample=*/SB_THREAT_TYPE_SAFE, /*expected_bucket_count=*/1); CheckUrlRealTimeLocalMatchMetrics( - /*expected_local_match_result=*/false, /*expected_mainframe_log=*/true, + /*expected_local_match_result=*/false, /*expect_url_lookup_service_metric_suffix=*/true); } @@ -881,7 +846,7 @@ /*sample=*/SB_THREAT_TYPE_URL_PHISHING, /*expected_bucket_count=*/1); CheckUrlRealTimeLocalMatchMetrics( - /*expected_local_match_result=*/false, /*expected_mainframe_log=*/true, + /*expected_local_match_result=*/false, /*expect_url_lookup_service_metric_suffix=*/true); } @@ -919,7 +884,7 @@ task_environment_.RunUntilIdle(); CheckUrlRealTimeLocalMatchMetrics( - /*expected_local_match_result=*/false, /*expected_mainframe_log=*/true, + /*expected_local_match_result=*/false, /*expect_url_lookup_service_metric_suffix=*/true); } @@ -947,7 +912,7 @@ task_environment_.RunUntilIdle(); CheckUrlRealTimeLocalMatchMetrics( - /*expected_local_match_result=*/false, /*expected_mainframe_log=*/true, + /*expected_local_match_result=*/false, /*expect_url_lookup_service_metric_suffix=*/true); } @@ -976,7 +941,7 @@ task_environment_.RunUntilIdle(); CheckUrlRealTimeLocalMatchMetrics( - /*expected_local_match_result=*/false, /*expected_mainframe_log=*/true, + /*expected_local_match_result=*/false, /*expect_url_lookup_service_metric_suffix=*/true); } @@ -1004,7 +969,7 @@ task_environment_.RunUntilIdle(); CheckUrlRealTimeLocalMatchMetrics( - /*expected_local_match_result=*/false, /*expected_mainframe_log=*/true, + /*expected_local_match_result=*/false, /*expect_url_lookup_service_metric_suffix=*/true); } @@ -1034,41 +999,11 @@ task_environment_.RunUntilIdle(); CheckUrlRealTimeLocalMatchMetrics( - /*expected_local_match_result=*/false, /*expected_mainframe_log=*/true, + /*expected_local_match_result=*/false, /*expect_url_lookup_service_metric_suffix=*/true); } TEST_F(SafeBrowsingUrlCheckerTest, - CheckUrl_UrlRealTimeEnabledSafeBrowsingDisabled_Subresource) { - auto safe_browsing_url_checker = CreateSafeBrowsingUrlChecker( - /*url_real_time_lookup_enabled=*/true, - /*can_check_safe_browsing_db=*/false, - /*hash_real_time_selection=*/ - hash_realtime_utils::HashRealTimeSelection::kNone, - /*optional_args=*/ - {.request_destination = network::mojom::RequestDestination::kScript}); - - GURL url("https://example.test/"); - - base::MockCallback<SafeBrowsingUrlCheckerImpl::NativeCheckUrlCallback> - callback; - EXPECT_CALL(callback, - Run(_, /*proceed=*/true, /*showed_interstitial=*/false, - /*has_post_commit_interstitial_skipped=*/false, - SafeBrowsingUrlCheckerImpl::PerformedCheck::kCheckSkipped)); - EXPECT_CALL(*url_checker_delegate_, - StartDisplayingBlockingPageHelper(_, _, _, _, _)) - .Times(0); - safe_browsing_url_checker->CheckUrl(url, "GET", callback.Get()); - - task_environment_.RunUntilIdle(); - CheckUrlRealTimeLocalMatchMetrics( - /*expected_local_match_result=*/std::nullopt, - /*expected_mainframe_log=*/std::nullopt, - /*expect_url_lookup_service_metric_suffix=*/std::nullopt); -} - -TEST_F(SafeBrowsingUrlCheckerTest, CheckUrl_UrlRealTimeEnabledRedirectUrlsSafe) { auto safe_browsing_url_checker = CreateSafeBrowsingUrlChecker( /*url_real_time_lookup_enabled=*/true,
diff --git a/components/safe_browsing/core/browser/url_realtime_mechanism.cc b/components/safe_browsing/core/browser/url_realtime_mechanism.cc index 8b5b50c..5dadbaf1 100644 --- a/components/safe_browsing/core/browser/url_realtime_mechanism.cc +++ b/components/safe_browsing/core/browser/url_realtime_mechanism.cc
@@ -22,20 +22,14 @@ void RecordLocalMatchResult( bool has_match, - network::mojom::RequestDestination request_destination, std::string url_lookup_service_metric_suffix) { AsyncMatch match_result = has_match ? AsyncMatch::MATCH : AsyncMatch::NO_MATCH; base::UmaHistogramEnumeration(kMatchResultHistogramName, match_result); - bool is_mainframe = - request_destination == network::mojom::RequestDestination::kDocument; - std::string frame_suffix = is_mainframe ? ".Mainframe" : ".NonMainframe"; - base::UmaHistogramEnumeration(kMatchResultHistogramName + frame_suffix, - match_result); if (!url_lookup_service_metric_suffix.empty()) { - base::UmaHistogramEnumeration(kMatchResultHistogramName + frame_suffix + - url_lookup_service_metric_suffix, - match_result); + base::UmaHistogramEnumeration( + kMatchResultHistogramName + url_lookup_service_metric_suffix, + match_result); } } @@ -44,22 +38,18 @@ UrlRealTimeMechanism::UrlRealTimeMechanism( const GURL& url, const SBThreatTypeSet& threat_types, - network::mojom::RequestDestination request_destination, scoped_refptr<SafeBrowsingDatabaseManager> database_manager, bool can_check_db, bool can_check_high_confidence_allowlist, std::string url_lookup_service_metric_suffix, - const GURL& last_committed_url, scoped_refptr<base::SequencedTaskRunner> ui_task_runner, base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui, scoped_refptr<UrlCheckerDelegate> url_checker_delegate, const base::RepeatingCallback<content::WebContents*()>& web_contents_getter) : SafeBrowsingLookupMechanism(url, threat_types, database_manager), - request_destination_(request_destination), can_check_db_(can_check_db), can_check_high_confidence_allowlist_(can_check_high_confidence_allowlist), url_lookup_service_metric_suffix_(url_lookup_service_metric_suffix), - last_committed_url_(last_committed_url), ui_task_runner_(ui_task_runner), url_lookup_service_on_ui_(url_lookup_service_on_ui), url_checker_delegate_(url_checker_delegate), @@ -73,8 +63,6 @@ UrlRealTimeMechanism::StartCheckInternal() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_NE(url_lookup_service_metric_suffix_, kNoRealTimeURLLookupService); - UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.RT.RequestDestinations.Checked", - request_destination_); bool check_allowlist = can_check_db_ && can_check_high_confidence_allowlist_; if (check_allowlist) { @@ -98,16 +86,14 @@ void UrlRealTimeMechanism::OnCheckUrlForHighConfidenceAllowlist( bool did_match_allowlist) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - RecordLocalMatchResult(did_match_allowlist, request_destination_, + RecordLocalMatchResult(did_match_allowlist, url_lookup_service_metric_suffix_); if (did_match_allowlist) { ui_task_runner_->PostTask( FROM_HERE, base::BindOnce(&UrlRealTimeMechanism::MaybeSendSampleRequest, - weak_factory_.GetWeakPtr(), url_, last_committed_url_, - /*is_mainframe=*/request_destination_ == - network::mojom::RequestDestination::kDocument, + weak_factory_.GetWeakPtr(), url_, url_lookup_service_on_ui_, base::SequencedTaskRunner::GetCurrentDefault())); // If the URL matches the high-confidence allowlist, still do the hash based @@ -120,9 +106,7 @@ ui_task_runner_->PostTask( FROM_HERE, base::BindOnce(&UrlRealTimeMechanism::StartLookupOnUIThread, - weak_factory_.GetWeakPtr(), url_, last_committed_url_, - /*is_mainframe=*/request_destination_ == - network::mojom::RequestDestination::kDocument, + weak_factory_.GetWeakPtr(), url_, url_lookup_service_on_ui_, base::SequencedTaskRunner::GetCurrentDefault())); } @@ -132,8 +116,6 @@ void UrlRealTimeMechanism::StartLookupOnUIThread( base::WeakPtr<UrlRealTimeMechanism> weak_ptr_on_io, const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui, scoped_refptr<base::SequencedTaskRunner> io_task_runner) { bool is_lookup_service_found = !!url_lookup_service_on_ui; @@ -149,16 +131,13 @@ RTLookupResponseCallback response_callback = base::BindOnce(&UrlRealTimeMechanism::OnLookupResponse, weak_ptr_on_io); - url_lookup_service_on_ui->StartLookup(url, last_committed_url, is_mainframe, - std::move(response_callback), + url_lookup_service_on_ui->StartLookup(url, std::move(response_callback), std::move(io_task_runner)); } void UrlRealTimeMechanism::MaybeSendSampleRequest( base::WeakPtr<UrlRealTimeMechanism> weak_ptr_on_io, const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui, scoped_refptr<base::SequencedTaskRunner> io_task_runner) { bool can_send_protego_sampled_ping = @@ -171,8 +150,8 @@ bool is_lookup_service_available = !url_lookup_service_on_ui->IsInBackoffMode(); if (is_lookup_service_available) { - url_lookup_service_on_ui->SendSampledRequest( - url, last_committed_url, is_mainframe, std::move(io_task_runner)); + url_lookup_service_on_ui->SendSampledRequest(url, + std::move(io_task_runner)); } }
diff --git a/components/safe_browsing/core/browser/url_realtime_mechanism.h b/components/safe_browsing/core/browser/url_realtime_mechanism.h index 72da4585..1118165 100644 --- a/components/safe_browsing/core/browser/url_realtime_mechanism.h +++ b/components/safe_browsing/core/browser/url_realtime_mechanism.h
@@ -27,12 +27,10 @@ UrlRealTimeMechanism( const GURL& url, const SBThreatTypeSet& threat_types, - network::mojom::RequestDestination request_destination, scoped_refptr<SafeBrowsingDatabaseManager> database_manager, bool can_check_db, bool can_check_high_confidence_allowlist, std::string url_lookup_service_metric_suffix, - const GURL& last_committed_url, scoped_refptr<base::SequencedTaskRunner> ui_task_runner, base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui, scoped_refptr<UrlCheckerDelegate> url_checker_delegate, @@ -57,8 +55,6 @@ static void StartLookupOnUIThread( base::WeakPtr<UrlRealTimeMechanism> weak_ptr_on_io, const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui, scoped_refptr<base::SequencedTaskRunner> io_task_runner); @@ -67,8 +63,6 @@ static void MaybeSendSampleRequest( base::WeakPtr<UrlRealTimeMechanism> weak_ptr_on_io, const GURL& url, - const GURL& last_committed_url, - bool is_mainframe, base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui, scoped_refptr<base::SequencedTaskRunner> io_task_runner); @@ -100,10 +94,6 @@ SEQUENCE_CHECKER(sequence_checker_); - // This is used only for logging purposes, primarily (but not exclusively) to - // distinguish between mainframe and non-mainframe resources. - const network::mojom::RequestDestination request_destination_; - // Whether safe browsing database can be checked. It is set to false when // enterprise real time URL lookup is enabled and safe browsing is disabled // for this profile. @@ -116,11 +106,6 @@ // URL Lookup service suffix for logging metrics. std::string url_lookup_service_metric_suffix_; - // The last committed URL when the checker is constructed. It is used to - // obtain page load token when the URL being checked is not a mainframe - // URL. - GURL last_committed_url_; - // The task runner for the UI thread. scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
diff --git a/components/sessions/core/session_id_generator.cc b/components/sessions/core/session_id_generator.cc index fc08fedb..8a58cd7 100644 --- a/components/sessions/core/session_id_generator.cc +++ b/components/sessions/core/session_id_generator.cc
@@ -61,16 +61,7 @@ SessionID SessionIdGenerator::NewUnique() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Init() should have been called in production (which initializes - // |local_state_|), but for test convenience, we allow operating even without - // underlying prefs. - if (local_state_) { - IncrementValueBy(1); - local_state_->SetInt64(kLastValuePref, last_value_); - } else { - // Test-only path. Will CHECK-fail if Init() is called later. - ++last_value_; - } + IncrementValueBy(1); DCHECK(SessionID::IsValidValue(last_value_)); return SessionID::FromSerializedValue(last_value_); } @@ -100,6 +91,12 @@ last_value_ = 0; } last_value_ += increment; + // Init() should have been called in production (which initializes + // |local_state_|), but for test convenience, we allow operating even without + // underlying prefs. + if (local_state_) { + local_state_->SetInt64(kLastValuePref, last_value_); + } } bool SessionIdGenerator::IsInitializedForTest() const {
diff --git a/components/site_settings_strings.grdp b/components/site_settings_strings.grdp index 466cf04c..cf1902d 100644 --- a/components/site_settings_strings.grdp +++ b/components/site_settings_strings.grdp
@@ -110,10 +110,10 @@ microphone </message> <message name="IDS_SITE_SETTINGS_TYPE_MIDI_SYSEX" desc="The label used for system exclusive messages for MIDI devices site settings controls."> - MIDI device control and reprogramming + MIDI device control & reprogram </message> <message name="IDS_SITE_SETTINGS_TYPE_MIDI_SYSEX_MID_SENTENCE" desc="The label used for system exclusive messages for MIDI devices site settings controls when used mid-sentence."> - MIDI device control and reprogramming + MIDI device control & reprogram </message> <message name="IDS_SITE_SETTINGS_TYPE_MOTION_SENSORS" desc="The label used for the motion sensor (accelerometer, gyroscope, magnetometer) site settings controls."> Motion sensors
diff --git a/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_MIDI_SYSEX.png.sha1 b/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_MIDI_SYSEX.png.sha1 index e9d6d03..7297323 100644 --- a/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_MIDI_SYSEX.png.sha1 +++ b/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_MIDI_SYSEX.png.sha1
@@ -1 +1 @@ -a6e4aa4f5b6476961a44794ecb1ecc00413e7d4e \ No newline at end of file +ce76948f019988de0b8843a1c9227bb492d38d7d \ No newline at end of file
diff --git a/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_MIDI_SYSEX_MID_SENTENCE.png.sha1 b/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_MIDI_SYSEX_MID_SENTENCE.png.sha1 index aba3bda..3bc6b95 100644 --- a/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_MIDI_SYSEX_MID_SENTENCE.png.sha1 +++ b/components/site_settings_strings_grdp/IDS_SITE_SETTINGS_TYPE_MIDI_SYSEX_MID_SENTENCE.png.sha1
@@ -1 +1 @@ -a18f229d1f0cdf0f181af561490521f98740ac87 \ No newline at end of file +1ee6913ad305b2f055eaf357e1eee1de97827d80 \ No newline at end of file
diff --git a/components/user_manager/BUILD.gn b/components/user_manager/BUILD.gn index 9ec444b..7f69ca68 100644 --- a/components/user_manager/BUILD.gn +++ b/components/user_manager/BUILD.gn
@@ -36,6 +36,8 @@ "include_exclude_account_id_filter.h", "known_user.cc", "known_user.h", + "multi_user/multi_user_sign_in_policy_controller.cc", + "multi_user/multi_user_sign_in_policy_controller.h", "scoped_user_manager.cc", "scoped_user_manager.h", "user.cc",
diff --git a/chrome/browser/ash/login/users/multi_profile_user_controller.cc b/components/user_manager/multi_user/multi_user_sign_in_policy_controller.cc similarity index 60% rename from chrome/browser/ash/login/users/multi_profile_user_controller.cc rename to components/user_manager/multi_user/multi_user_sign_in_policy_controller.cc index 2dfc95b..09539b46 100644 --- a/chrome/browser/ash/login/users/multi_profile_user_controller.cc +++ b/components/user_manager/multi_user/multi_user_sign_in_policy_controller.cc
@@ -2,67 +2,41 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ash/login/users/multi_profile_user_controller.h" +#include "components/user_manager/multi_user/multi_user_sign_in_policy_controller.h" #include <utility> -#include "ash/public/cpp/login_types.h" #include "base/functional/bind.h" #include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" -#include "components/sync_preferences/pref_service_syncable.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #include "components/user_manager/user_manager_pref_names.h" -namespace ash { +namespace user_manager { -// TODO(b/278643115) Remove the using when moved. -namespace prefs { -using user_manager::prefs::kCachedMultiProfileUserBehavior; -using user_manager::prefs::kMultiProfileNeverShowIntro; -using user_manager::prefs::kMultiProfileUserBehaviorPref; -using user_manager::prefs::kMultiProfileWarningShowDismissed; -} // namespace prefs -using user_manager::MultiUserSignInPolicy; -using user_manager::MultiUserSignInPolicyToPrefValue; -using user_manager::ParseMultiUserSignInPolicyPref; - -MultiProfileUserController::MultiProfileUserController( +MultiUserSignInPolicyController::MultiUserSignInPolicyController( PrefService* local_state, - user_manager::UserManager* user_manager) + UserManager* user_manager) : local_state_(local_state), user_manager_(user_manager) {} -MultiProfileUserController::~MultiProfileUserController() = default; +MultiUserSignInPolicyController::~MultiUserSignInPolicyController() = default; // static -void MultiProfileUserController::RegisterPrefs(PrefRegistrySimple* registry) { +void MultiUserSignInPolicyController::RegisterPrefs( + PrefRegistrySimple* registry) { registry->RegisterDictionaryPref(prefs::kCachedMultiProfileUserBehavior); } -// static -void MultiProfileUserController::RegisterProfilePrefs( - user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref(prefs::kMultiProfileUserBehaviorPref, - std::string(MultiUserSignInPolicyToPrefValue( - MultiUserSignInPolicy::kUnrestricted))); - registry->RegisterBooleanPref( - prefs::kMultiProfileNeverShowIntro, false, - user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF); - registry->RegisterBooleanPref( - prefs::kMultiProfileWarningShowDismissed, false, - user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF); -} - -void MultiProfileUserController::Shutdown() { +void MultiUserSignInPolicyController::Shutdown() { pref_watchers_.clear(); } std::optional<MultiUserSignInPolicy> -MultiProfileUserController::GetPrimaryUserPolicy() const { - const user_manager::User* user = user_manager_->GetPrimaryUser(); +MultiUserSignInPolicyController::GetPrimaryUserPolicy() const { + const User* user = user_manager_->GetPrimaryUser(); if (!user) { return std::nullopt; } @@ -76,9 +50,9 @@ prefs->GetString(prefs::kMultiProfileUserBehaviorPref)); } -bool MultiProfileUserController::IsUserAllowedInSession( +bool MultiUserSignInPolicyController::IsUserAllowedInSession( const std::string& user_email) const { - const user_manager::User* primary_user = user_manager_->GetPrimaryUser(); + const User* primary_user = user_manager_->GetPrimaryUser(); std::string primary_user_email; if (primary_user) { primary_user_email = primary_user->GetAccountId().GetUserEmail(); @@ -100,7 +74,7 @@ return policy == MultiUserSignInPolicy::kUnrestricted; } -void MultiProfileUserController::StartObserving(user_manager::User* user) { +void MultiUserSignInPolicyController::StartObserving(User* user) { // Profile name could be empty during tests. if (user->GetAccountId().GetUserEmail().empty() || !user->GetProfilePrefs()) { return; @@ -110,21 +84,21 @@ registrar->Init(user->GetProfilePrefs()); registrar->Add( prefs::kMultiProfileUserBehaviorPref, - base::BindRepeating(&MultiProfileUserController::OnUserPrefChanged, + base::BindRepeating(&MultiUserSignInPolicyController::OnUserPrefChanged, base::Unretained(this), user)); pref_watchers_.push_back(std::move(registrar)); OnUserPrefChanged(user); } -void MultiProfileUserController::RemoveCachedValues( +void MultiUserSignInPolicyController::RemoveCachedValues( std::string_view user_email) { ScopedDictPrefUpdate update(local_state_, prefs::kCachedMultiProfileUserBehavior); update->Remove(user_email); } -MultiUserSignInPolicy MultiProfileUserController::GetCachedValue( +MultiUserSignInPolicy MultiUserSignInPolicyController::GetCachedValue( std::string_view user_email) const { const base::Value::Dict& dict = local_state_->GetDict(prefs::kCachedMultiProfileUserBehavior); @@ -138,15 +112,16 @@ MultiUserSignInPolicy::kUnrestricted); } -void MultiProfileUserController::SetCachedValue(std::string_view user_email, - MultiUserSignInPolicy policy) { +void MultiUserSignInPolicyController::SetCachedValue( + std::string_view user_email, + MultiUserSignInPolicy policy) { ScopedDictPrefUpdate update(local_state_, prefs::kCachedMultiProfileUserBehavior); update->Set(user_email, MultiUserSignInPolicyToPrefValue(policy)); } -void MultiProfileUserController::CheckSessionUsers() { - for (const user_manager::User* user : user_manager_->GetLoggedInUsers()) { +void MultiUserSignInPolicyController::CheckSessionUsers() { + for (const User* user : user_manager_->GetLoggedInUsers()) { const std::string& user_email = user->GetAccountId().GetUserEmail(); if (!IsUserAllowedInSession(user_email)) { user_manager_->NotifyUserNotAllowed(user_email); @@ -155,7 +130,7 @@ } } -void MultiProfileUserController::OnUserPrefChanged(user_manager::User* user) { +void MultiUserSignInPolicyController::OnUserPrefChanged(User* user) { std::string user_email = user->GetAccountId().GetUserEmail(); CHECK(!user_email.empty()); @@ -177,4 +152,4 @@ CheckSessionUsers(); } -} // namespace ash +} // namespace user_manager
diff --git a/components/user_manager/multi_user/multi_user_sign_in_policy_controller.h b/components/user_manager/multi_user/multi_user_sign_in_policy_controller.h new file mode 100644 index 0000000..f4f88671 --- /dev/null +++ b/components/user_manager/multi_user/multi_user_sign_in_policy_controller.h
@@ -0,0 +1,83 @@ +// Copyright 2014 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_USER_MANAGER_MULTI_USER_MULTI_USER_SIGN_IN_POLICY_CONTROLLER_H_ +#define COMPONENTS_USER_MANAGER_MULTI_USER_MULTI_USER_SIGN_IN_POLICY_CONTROLLER_H_ + +#include <memory> +#include <string> +#include <string_view> +#include <vector> + +#include "base/memory/raw_ptr.h" +#include "components/user_manager/multi_user/multi_user_sign_in_policy.h" +#include "components/user_manager/user_manager_export.h" + +class PrefChangeRegistrar; +class PrefRegistrySimple; +class PrefService; + +namespace user_manager { + +class User; +class UserManager; + +// MultiUserSignInPolicyController decides whether a user is allowed to be in a +// multi user sign-in session. It caches the multi user sign-in behavior pref +// backed by user policy into local state so that the value is available before +// the user login and checks if the meaning of the value is respected. +class USER_MANAGER_EXPORT MultiUserSignInPolicyController { + public: + MultiUserSignInPolicyController(PrefService* local_state, + UserManager* user_manager); + + MultiUserSignInPolicyController(const MultiUserSignInPolicyController&) = + delete; + MultiUserSignInPolicyController& operator=( + const MultiUserSignInPolicyController&) = delete; + + ~MultiUserSignInPolicyController(); + + static void RegisterPrefs(PrefRegistrySimple* registry); + + // Stops to work. + void Shutdown(); + + // Returns the cached policy value for `user_email`. + MultiUserSignInPolicy GetCachedValue(std::string_view user_email) const; + + // Returns the primary user's policy. If there's no primary user, + // returns std::nullopt. + std::optional<MultiUserSignInPolicy> GetPrimaryUserPolicy() const; + + // Returns true if user allowed to be in the current session. + bool IsUserAllowedInSession(const std::string& user_email) const; + + // Starts to observe the multiprofile user behavior pref of the given user. + void StartObserving(User* user); + + // Removes the cached values for the given user. + void RemoveCachedValues(std::string_view user_email); + + private: + friend class MultiUserSignInPolicyControllerTest; + + // Sets the cached policy value. + void SetCachedValue(std::string_view user_email, + MultiUserSignInPolicy policy); + + // Checks if all users are allowed in the current session. + void CheckSessionUsers(); + + // Invoked when user behavior pref value changes. + void OnUserPrefChanged(User* user); + + raw_ptr<PrefService, DanglingUntriaged> local_state_; + raw_ptr<UserManager> user_manager_; + std::vector<std::unique_ptr<PrefChangeRegistrar>> pref_watchers_; +}; + +} // namespace user_manager + +#endif // COMPONENTS_USER_MANAGER_MULTI_USER_MULTI_USER_SIGN_IN_POLICY_CONTROLLER_H_
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 860dbc9..ce4e816 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1141,8 +1141,6 @@ "indexed_db/indexed_db_external_object.h", "indexed_db/indexed_db_external_object_storage.cc", "indexed_db/indexed_db_external_object_storage.h", - "indexed_db/indexed_db_factory.cc", - "indexed_db/indexed_db_factory.h", "indexed_db/indexed_db_factory_client.cc", "indexed_db/indexed_db_factory_client.h", "indexed_db/indexed_db_index_writer.cc", @@ -3213,6 +3211,8 @@ "memory/swap_metrics_driver_impl_linux.h", "navigation_transitions/back_forward_transition_animation_manager_android.cc", "navigation_transitions/back_forward_transition_animation_manager_android.h", + "navigation_transitions/back_forward_transition_animator.cc", + "navigation_transitions/back_forward_transition_animator.h", "navigation_transitions/physics_model.cc", "navigation_transitions/physics_model.h", "renderer_host/compositor_dependencies_android.cc",
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index bce15644..019506a 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -1869,16 +1869,8 @@ RunHtmlTest(FILE_PATH_LITERAL("contenteditable-docs-li.html")); } -// TODO(b/324376803): Re-enable flaky test. -#if BUILDFLAG(IS_MAC) -#define MAYBE_AccessibilityContenteditableDocsLi \ - DISABLED_AccessibilityContenteditableDocsLi -#else -#define MAYBE_AccessibilityContenteditableDocsLi \ - AccessibilityContenteditableDocsLi -#endif IN_PROC_BROWSER_TEST_P(YieldingParserDumpAccessibilityTreeTest, - MAYBE_AccessibilityContenteditableDocsLi) { + AccessibilityContenteditableDocsLi) { RunHtmlTest(FILE_PATH_LITERAL("contenteditable-docs-li.html")); }
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc index b581eec..6e8bca9 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -995,6 +995,10 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!initialized_); #endif + base::UmaHistogramEnumeration( + indexed_db::kBackingStoreActionUmaName, + indexed_db::IndexedDBAction::kBackingStoreOpenAttempt); + const IndexedDBDataFormatVersion latest_known_data_version = IndexedDBDataFormatVersion::GetCurrent(); const std::string schema_version_key = SchemaVersionKey::Encode();
diff --git a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc index f49a584..7c684f09 100644 --- a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc +++ b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
@@ -43,7 +43,6 @@ #include "content/browser/indexed_db/indexed_db_bucket_context.h" #include "content/browser/indexed_db/indexed_db_class_factory.h" #include "content/browser/indexed_db/indexed_db_context_impl.h" -#include "content/browser/indexed_db/indexed_db_factory.h" #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" #include "content/browser/indexed_db/indexed_db_leveldb_operations.h" #include "content/browser/indexed_db/indexed_db_value.h"
diff --git a/content/browser/indexed_db/indexed_db_bucket_context.cc b/content/browser/indexed_db/indexed_db_bucket_context.cc index 6eaf51af..c7f79fa 100644 --- a/content/browser/indexed_db/indexed_db_bucket_context.cc +++ b/content/browser/indexed_db/indexed_db_bucket_context.cc
@@ -355,11 +355,9 @@ IndexedDBBucketContext::kMaxEarliestBucketCompactionFromNow; IndexedDBBucketContext::Delegate::Delegate() - : on_fatal_error(base::DoNothing()), - on_corruption(base::DoNothing()), - on_ready_for_destruction(base::DoNothing()), + : on_ready_for_destruction(base::DoNothing()), on_content_changed(base::DoNothing()), - on_writing_transaction_complete(base::DoNothing()), + on_files_written(base::DoNothing()), for_each_bucket_context(base::DoNothing()) {} IndexedDBBucketContext::Delegate::Delegate(Delegate&& other) = default; @@ -621,7 +619,7 @@ continue; case IndexedDBDatabase::RunTasksResult::kError: - delegate().on_fatal_error.Run(status, {}); + OnDatabaseError(status, {}); return; case IndexedDBDatabase::RunTasksResult::kCanBeDestroyed: @@ -665,7 +663,7 @@ blink::mojom::IDBError::New(error.code(), error.message())); if (s.IsCorruption()) { - delegate().on_corruption.Run(error); + HandleBackingStoreCorruption(error); } } @@ -680,7 +678,7 @@ transaction_receiver, int64_t transaction_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - TRACE_EVENT0("IndexedDB", "IndexedDBFactory::Open"); + TRACE_EVENT0("IndexedDB", "IndexedDBBucketContext::Open"); // TODO(dgrogan): Don't let a non-existing database be opened (and therefore // created) if this origin is already over quota. @@ -693,7 +691,7 @@ if (!backing_store_) { IndexedDBFactoryClient(std::move(factory_client)).OnError(error); if (s.IsCorruption()) { - delegate().on_corruption.Run(error); + HandleBackingStoreCorruption(error); } return; } @@ -738,7 +736,7 @@ const std::u16string& name, bool force_close) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - TRACE_EVENT0("IndexedDB", "IndexedDBFactory::DeleteDatabase"); + TRACE_EVENT0("IndexedDB", "IndexedDBBucketContext::DeleteDatabase"); { leveldb::Status s; @@ -756,13 +754,13 @@ IndexedDBFactoryClient(std::move(factory_client)).OnError(error); if (s.IsCorruption()) { - delegate().on_corruption.Run(error); + HandleBackingStoreCorruption(error); } return; } } - auto on_deletion_complete = base::BindOnce( - delegate().on_writing_transaction_complete, /*flushed=*/true); + auto on_deletion_complete = + base::BindOnce(delegate().on_files_written, /*flushed=*/true); // First, check the databases that are already represented by // `IndexedDBDatabase` objects. If one exists, schedule it to be deleted and @@ -776,7 +774,7 @@ if (force_close) { leveldb::Status status = database->ForceCloseAndRunTasks(); if (!status.ok()) { - delegate().on_fatal_error.Run(status, "Error aborting transactions."); + OnDatabaseError(status, "Error aborting transactions."); } } return; @@ -792,7 +790,7 @@ "indexedDB.deleteDatabase."); IndexedDBFactoryClient(std::move(factory_client)).OnError(error); if (s.IsCorruption()) { - delegate().on_corruption.Run(error); + HandleBackingStoreCorruption(error); } return; } @@ -814,7 +812,7 @@ if (force_close) { leveldb::Status status = database_ptr->ForceCloseAndRunTasks(); if (!status.ok()) { - delegate().on_fatal_error.Run(status, "Error aborting transactions."); + OnDatabaseError(status, "Error aborting transactions."); } } } @@ -1173,6 +1171,48 @@ file_reader_map_.erase(path); } +void IndexedDBBucketContext::HandleBackingStoreCorruption( + const IndexedDBDatabaseError& error) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + // The message may contain the database path, which may be considered + // sensitive data, and those strings are passed to the extension, so strip it. + std::string sanitized_message = base::UTF16ToUTF8(error.message()); + base::ReplaceSubstringsAfterOffset(&sanitized_message, 0u, + data_path_.AsUTF8Unsafe(), "..."); + IndexedDBBackingStore::RecordCorruptionInfo(data_path_, bucket_locator(), + sanitized_message); + // Note: DestroyLevelDB only deletes LevelDB files, leaving all others, + // so our corruption info file will remain. + // The blob directory will be deleted when the database is recreated + // the next time it is opened. + const base::FilePath file_path = + data_path_.Append(indexed_db::GetLevelDBFileName(bucket_locator())); + ForceClose(/*will_be_deleted=*/false); + // `this` may be deleted. + + leveldb::Status s = + IndexedDBClassFactory::Get()->leveldb_factory().DestroyLevelDB(file_path); + DLOG_IF(ERROR, !s.ok()) << "Unable to delete backing store: " << s.ToString(); +} + +void IndexedDBBucketContext::OnDatabaseError(leveldb::Status status, + const std::string& message) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!status.ok()); + if (status.IsCorruption()) { + IndexedDBDatabaseError error( + blink::mojom::IDBException::kUnknownError, + base::ASCIIToUTF16(message.empty() ? status.ToString() : message)); + HandleBackingStoreCorruption(error); + return; + } + if (status.IsIOError()) { + quota_manager_proxy_->OnClientWriteFailed(bucket_info_.storage_key); + } + ForceClose(/*will_be_deleted=*/false); +} + bool IndexedDBBucketContext::OnMemoryDump( const base::trace_event::MemoryDumpArgs& args, base::trace_event::ProcessMemoryDump* pmd) { @@ -1252,7 +1292,7 @@ scoped_refptr<LevelDBState> database_state; bool is_disk_full; { - TRACE_EVENT0("IndexedDB", "IndexedDBFactory::OpenLevelDB"); + TRACE_EVENT0("IndexedDB", "IndexedDBBucketContext::OpenLevelDB"); base::TimeTicks begin_time = base::TimeTicks::Now(); size_t write_buffer_size = leveldb_env::WriteBufferSize( base::SysInfo::AmountOfTotalDiskSpace(database_path)); @@ -1273,7 +1313,7 @@ // Create the LevelDBScopes wrapper. std::unique_ptr<LevelDBScopes> scopes; { - TRACE_EVENT0("IndexedDB", "IndexedDBFactory::OpenLevelDBScopes"); + TRACE_EVENT0("IndexedDB", "IndexedDBBucketContext::OpenLevelDBScopes"); scopes = std::make_unique<LevelDBScopes>( ScopesPrefix::Encode(), /*max_write_batch_size_bytes=*/1024 * 1024, database_state, @@ -1282,7 +1322,8 @@ [](base::RepeatingCallback<void(leveldb::Status, const std::string&)> on_fatal_error, leveldb::Status s) { on_fatal_error.Run(s, {}); }, - delegate_.on_fatal_error)); + base::BindRepeating(&IndexedDBBucketContext::OnDatabaseError, + base::Unretained(this)))); status = scopes->Initialize(); if (UNLIKELY(!status.ok())) { @@ -1327,7 +1368,7 @@ auto backing_store = std::make_unique<IndexedDBBackingStore>( backing_store_mode, bucket_locator(), blob_path, std::move(database), - base::BindRepeating(delegate_.on_writing_transaction_complete, + base::BindRepeating(delegate_.on_files_written, /*flushed=*/true), base::BindRepeating(&IndexedDBBucketContext::ReportOutstandingBlobs, weak_factory_.GetWeakPtr()), @@ -1445,7 +1486,7 @@ lock_manager_ = std::move(lock_manager); backing_store_ = std::move(backing_store); backing_store_->set_bucket_context(this); - delegate().on_writing_transaction_complete.Run(/*flushed=*/true); + delegate().on_files_written.Run(/*flushed=*/true); return {leveldb::Status::OK(), IndexedDBDatabaseError(), data_loss_info}; }
diff --git a/content/browser/indexed_db/indexed_db_bucket_context.h b/content/browser/indexed_db/indexed_db_bucket_context.h index 5401281b3..9e50e6d 100644 --- a/content/browser/indexed_db/indexed_db_bucket_context.h +++ b/content/browser/indexed_db/indexed_db_bucket_context.h
@@ -46,7 +46,6 @@ class IndexedDBBucketContextHandle; class IndexedDBDatabase; class IndexedDBDataItemReader; -class IndexedDBFactory; class IndexedDBPreCloseTaskQueue; constexpr const char kIDBCloseImmediatelySwitch[] = "idb-close-immediately"; @@ -56,9 +55,9 @@ // // IndexedDBBucketContext will keep its backing store around while any of these // is true: -// * There are handles referencing the factory, +// * There are handles referencing the bucket context, // * There are outstanding blob references to this database's blob files, or -// * The factory is in-memory (i.e. an incognito profile). +// * The bucket context is in-memory (i.e. an incognito profile). // // When these qualities are no longer true, `RunTasks()` will invoke // `ResetBackingStore()`, which returns `this` to an uninitialized state. @@ -67,7 +66,7 @@ // IndexedDB task runner. To facilitate IndexedDB code running on multiple task // runners, `IndexedDBBucketContext` is in the process of becoming the single // point of communication between classes running on the main task runner, such -// as `IndexedDBFactory`, and those that pertain to a specific bucket and +// as `IndexedDBContextImpl`, and those that pertain to a specific bucket and // therefore run on a bucket's IDB task runner, such as `IndexedDBDatabase` or // `IndexedDBCursor`. class CONTENT_EXPORT IndexedDBBucketContext @@ -135,16 +134,6 @@ Delegate(const Delegate&) = delete; Delegate& operator=(const Delegate&) = delete; - // Called when a fatal error has occurred that should result in tearing down - // the backing store. `IndexedDBBucketContext` *may* be synchronously - // destroyed after this is invoked. The string, if non-empty, is used as an - // error message. - base::RepeatingCallback<void(leveldb::Status, const std::string&)> - on_fatal_error; - - // Called when the backing store has been corrupted. - base::RepeatingCallback<void(const IndexedDBDatabaseError&)> on_corruption; - // Called when the bucket context is ready to be destroyed. base::RepeatingCallback<void()> on_ready_for_destruction; @@ -156,11 +145,10 @@ const std::u16string& /*object_store_name*/)> on_content_changed; - // Called to inform the quota system that a transaction which may have - // updated the amount of disk space used has completed. The parameter is - // true for transactions that caused the backing store to flush. - base::RepeatingCallback<void(bool /*did_sync*/)> - on_writing_transaction_complete; + // Called to inform the quota system that an action which may have updated + // the amount of disk space used has completed. The parameter is true for + // transactions that caused the backing store to flush. + base::RepeatingCallback<void(bool /*did_sync*/)> on_files_written; // Called to run a given callback on every bucket context (including the one // in the current sequence and those in other sequences/associated with @@ -307,24 +295,33 @@ void CompactBackingStoreForTesting(); + // Called when a fatal error has occurred that should result in tearing down + // the backing store. `IndexedDBBucketContext` *may* be synchronously + // destroyed after this is invoked. The string, if non-empty, is used as an + // error message. + void OnDatabaseError(leveldb::Status status, const std::string& message); + + // Called when the backing store has been corrupted. + void HandleBackingStoreCorruption(const IndexedDBDatabaseError& error); + // base::trace_event::MemoryDumpProvider: bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, base::trace_event::ProcessMemoryDump* pmd) override; + bool force_close_called_for_testing() const { return skip_closing_sequence_; } + private: - friend IndexedDBFactory; friend IndexedDBBucketContextHandle; friend class IndexedDBBackingStoreTest; friend class IndexedDBDatabaseTest; - friend class IndexedDBFactoryTest; + friend class IndexedDBTest; friend class IndexedDBTransactionTest; - FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, CompactionKillSwitchWorks); - FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, CompactionTaskTiming); - FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, TombstoneSweeperTiming); - FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, TooLongOrigin); - FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTestWithStoragePartitioning, - BasicFactoryCreationAndTearDown); + FRIEND_TEST_ALL_PREFIXES(IndexedDBTest, CompactionKillSwitchWorks); + FRIEND_TEST_ALL_PREFIXES(IndexedDBTest, CompactionTaskTiming); + FRIEND_TEST_ALL_PREFIXES(IndexedDBTest, TombstoneSweeperTiming); + FRIEND_TEST_ALL_PREFIXES(IndexedDBTest, TooLongOrigin); + FRIEND_TEST_ALL_PREFIXES(IndexedDBTest, BasicFactoryCreationAndTearDown); FRIEND_TEST_ALL_PREFIXES(IndexedDBBucketContextTest, BucketSpaceDecay); // The data structure that stores everything bound to the receiver. This will @@ -360,8 +357,8 @@ void OnHandleCreated(); void OnHandleDestruction(); - // Returns true if this factory can be closed (no references, no blobs, and - // not persisting for incognito). + // Returns true if this bucket context can be closed (no references, no blobs, + // and not persisting for incognito). bool CanClose(); void MaybeStartClosing(); @@ -448,8 +445,8 @@ // have not yet been loaded. DBMap databases_; // This is the refcount for the number of IndexedDBBucketContextHandle's - // given out for this factory using OpenReference. This is used as closing - // criteria for this object, see CanClose. + // given out for this bucket context using OpenReference. This is used as + // closing criteria for this object, see CanClose. int64_t open_handles_ = 0; // A queue of callbacks representing `CheckCanUseDiskSpace()` requests.
diff --git a/content/browser/indexed_db/indexed_db_connection.cc b/content/browser/indexed_db/indexed_db_connection.cc index 8c7d9bcc..3ccdccd 100644 --- a/content/browser/indexed_db/indexed_db_connection.cc +++ b/content/browser/indexed_db/indexed_db_connection.cc
@@ -92,7 +92,7 @@ bucket_context_handle_->quota_manager()->NotifyBucketAccessed( bucket_context_handle_->bucket_locator(), base::Time::Now()); if (!status.ok()) { - bucket_context_handle_->delegate().on_fatal_error.Run(status, {}); + bucket_context_handle_->OnDatabaseError(status, {}); } bucket_context_handle_.Release(); return callbacks; @@ -154,8 +154,9 @@ TRACE_EVENT1("IndexedDB", "IndexedDBDatabase::Abort(error)", "txn.id", transaction->id()); leveldb::Status status = transaction->Abort(error); - if (!status.ok()) - bucket_context_handle_->delegate().on_fatal_error.Run(status, {}); + if (!status.ok()) { + bucket_context_handle_->OnDatabaseError(status, {}); + } } leveldb::Status IndexedDBConnection::AbortAllTransactions(
diff --git a/content/browser/indexed_db/indexed_db_context_impl.cc b/content/browser/indexed_db/indexed_db_context_impl.cc index 62abb6ff..6c3de7c 100644 --- a/content/browser/indexed_db/indexed_db_context_impl.cc +++ b/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -40,12 +40,9 @@ #include "components/services/storage/public/cpp/quota_error_or.h" #include "components/services/storage/public/mojom/quota_client.mojom.h" #include "components/services/storage/public/mojom/storage_usage_info.mojom.h" +#include "content/browser/indexed_db/indexed_db_backing_store.h" #include "content/browser/indexed_db/indexed_db_bucket_context.h" -#include "content/browser/indexed_db/indexed_db_bucket_context_handle.h" #include "content/browser/indexed_db/indexed_db_class_factory.h" -#include "content/browser/indexed_db/indexed_db_connection.h" -#include "content/browser/indexed_db/indexed_db_database.h" -#include "content/browser/indexed_db/indexed_db_factory.h" #include "content/browser/indexed_db/indexed_db_leveldb_operations.h" #include "content/browser/indexed_db/indexed_db_quota_client.h" #include "content/browser/indexed_db/indexed_db_transaction.h" @@ -64,6 +61,8 @@ namespace content { +using storage::BucketLocator; + namespace { static MockBrowserTestIndexedDBClassFactory* GetTestClassFactory() { @@ -81,6 +80,72 @@ return false; } +leveldb::Status GetDBSizeFromEnv(leveldb::Env* env, + const std::string& path, + int64_t* total_size_out) { + *total_size_out = 0; + // Root path should be /, but in MemEnv, a path name is not tailed with '/' + DCHECK_EQ(path.back(), '/'); + const std::string path_without_slash = path.substr(0, path.length() - 1); + + // This assumes that leveldb will not put a subdirectory into the directory + std::vector<std::string> file_names; + leveldb::Status s = env->GetChildren(path_without_slash, &file_names); + if (!s.ok()) { + return s; + } + + for (std::string& file_name : file_names) { + file_name.insert(0, path); + uint64_t file_size; + s = env->GetFileSize(file_name, &file_size); + if (!s.ok()) { + return s; + } else { + *total_size_out += static_cast<int64_t>(file_size); + } + } + return s; +} + +// Used to field IDBFactory requests when the quota system failed to +// find/return a bucket. +class MissingBucketErrorEndpoint : public blink::mojom::IDBFactory { + public: + MissingBucketErrorEndpoint() = default; + ~MissingBucketErrorEndpoint() override = default; + + // blink::mojom::IDBFactory implementation: + void GetDatabaseInfo(GetDatabaseInfoCallback callback) override { + std::move(callback).Run( + {}, blink::mojom::IDBError::New( + blink::mojom::IDBException::kUnknownError, u"Internal error.")); + } + + void Open(mojo::PendingAssociatedRemote<blink::mojom::IDBFactoryClient> + factory_client, + mojo::PendingAssociatedRemote<blink::mojom::IDBDatabaseCallbacks> + database_callbacks_remote, + const std::u16string& name, + int64_t version, + mojo::PendingAssociatedReceiver<blink::mojom::IDBTransaction> + transaction_receiver, + int64_t transaction_id) override { + IndexedDBFactoryClient(std::move(factory_client)) + .OnError(IndexedDBDatabaseError( + blink::mojom::IDBException::kUnknownError, u"Internal error.")); + } + + void DeleteDatabase(mojo::PendingAssociatedRemote< + blink::mojom::IDBFactoryClient> factory_client, + const std::u16string& name, + bool force_close) override { + IndexedDBFactoryClient(std::move(factory_client)) + .OnError(IndexedDBDatabaseError( + blink::mojom::IDBException::kUnknownError, u"Internal error.")); + } +}; + } // namespace IndexedDBContextImpl::IndexedDBContextImpl( @@ -155,7 +220,7 @@ // We cannot run this in the constructor it needs to be async, but the async // tasks might not finish before the destructor runs. InitializeFromFilesIfNeeded(base::DoNothing()); - receivers_.Add(this, std::move(control)); + control_receivers_.Add(this, std::move(control)); } void IndexedDBContextImpl::BindControl( @@ -167,7 +232,7 @@ } void IndexedDBContextImpl::BindIndexedDB( - const storage::BucketLocator& bucket_locator, + const BucketLocator& bucket_locator, mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> client_state_checker_remote, const base::UnguessableToken& client_token, @@ -194,14 +259,20 @@ mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> client_state_checker_remote, const base::UnguessableToken& client_token, - mojo::PendingReceiver<blink::mojom::IDBFactory> receiver, + mojo::PendingReceiver<blink::mojom::IDBFactory> pending_receiver, storage::QuotaErrorOr<storage::BucketInfo> bucket_info) { std::optional<storage::BucketInfo> bucket; if (bucket_info.has_value()) { bucket = bucket_info.value(); } - GetIDBFactory()->AddReceiver(bucket, std::move(client_state_checker_remote), - client_token, std::move(receiver)); + if (bucket) { + GetOrCreateBucketContext(*bucket, GetDataPath(bucket->ToBucketLocator())) + .AddReceiver(std::move(client_state_checker_remote), client_token, + std::move(pending_receiver)); + } else { + mojo::MakeSelfOwnedReceiver(std::make_unique<MissingBucketErrorEndpoint>(), + std::move(pending_receiver)); + } } // Note - this is being kept async (instead of having a 'sync' version) to allow @@ -236,20 +307,20 @@ }, std::move(callback))); - for (const auto& bucket : buckets.value()) { + for (const storage::BucketInfo& bucket : buckets.value()) { DoDeleteBucketData(bucket.ToBucketLocator(), barrier); } } void IndexedDBContextImpl::DeleteBucketData( - const storage::BucketLocator& bucket_locator, + const BucketLocator& bucket_locator, base::OnceCallback<void(bool)> callback) { DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence()); DoDeleteBucketData(bucket_locator, std::move(callback)); } void IndexedDBContextImpl::DoDeleteBucketData( - const storage::BucketLocator& bucket_locator, + const BucketLocator& bucket_locator, base::OnceCallback<void(bool)> callback) { ForceClose(bucket_locator.id, storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN, @@ -266,8 +337,8 @@ return; } + // TODO(estade): remove this and just obliterate the data directory. base::FilePath idb_file_path = GetLevelDBPath(bucket_locator); - leveldb::Status s = IndexedDBClassFactory::Get()->leveldb_factory().DestroyLevelDB( idb_file_path); @@ -287,23 +358,13 @@ void IndexedDBContextImpl::ForceClose(storage::BucketId bucket_id, storage::mojom::ForceCloseReason reason, base::OnceClosure closure) { - base::UmaHistogramEnumeration("WebCore.IndexedDB.Context.ForceCloseReason", - reason); - if (!LookUpBucket(bucket_id)) { - std::move(closure).Run(); - return; + auto it = bucket_contexts_.find(bucket_id); + if (it != bucket_contexts_.end()) { + it->second->ForceClose( + /*doom=*/reason == + storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN); } - if (!indexeddb_factory_.get()) { - std::move(closure).Run(); - return; - } - - // Make a copy of storage_key, as the ref might go away here during the close. - indexeddb_factory_->ForceClose( - bucket_id, - /*will_be_deleted=*/reason == - storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN); std::move(closure).Run(); } @@ -354,8 +415,7 @@ if (!handler) { return; } - std::vector<storage::BucketLocator> bucket_locators = - handler->GetAllBuckets(); + std::vector<BucketLocator> bucket_locators = handler->GetAllBuckets(); auto collect_buckets = base::BarrierCallback<storage::QuotaErrorOr<storage::BucketInfo>>( @@ -363,7 +423,7 @@ base::BindOnce(&IndexedDBContextImpl::OnBucketInfoReady, handler, std::move(callback))); - for (const auto& bucket_locator : bucket_locators) { + for (const BucketLocator& bucket_locator : bucket_locators) { handler->quota_manager_proxy_->GetBucketById( bucket_locator.id, handler->idb_task_runner_, collect_buckets); } @@ -381,17 +441,12 @@ std::vector<storage::mojom::IdbBucketMetadataPtr>>> bucket_map; - if (!indexeddb_factory_) { - std::move(callback).Run(is_incognito(), {}); - return; - } - for (const auto& quota_error_or_bucket_info : bucket_infos) { if (!quota_error_or_bucket_info.has_value()) { continue; } const storage::BucketInfo& bucket_info = quota_error_or_bucket_info.value(); - const storage::BucketLocator bucket_locator = bucket_info.ToBucketLocator(); + const BucketLocator bucket_locator = bucket_info.ToBucketLocator(); storage::mojom::IdbBucketMetadataPtr info = storage::mojom::IdbBucketMetadata::New(); @@ -405,7 +460,7 @@ } // TODO(crbug.com/1474996): This executes synchronously for now, but will // need to handle delayed responses. - indexeddb_factory_->FillInBucketMetadata( + FillInBucketMetadata( std::move(info), base::BindOnce( [](std::map< @@ -426,7 +481,7 @@ storage::mojom::IdbOriginMetadataPtr origin_metadata = storage::mojom::IdbOriginMetadata::New(); - origin_metadata->origin = std::move(origin_url); + origin_metadata->origin = origin_url; for (auto& [storage_key, buckets] : top_level_site_map) { storage::mojom::IdbStorageKeyMetadataPtr storage_key_metadata = @@ -466,7 +521,7 @@ void IndexedDBContextImpl::ApplyPolicyUpdates( std::vector<storage::mojom::StoragePolicyUpdatePtr> policy_updates) { DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence()); - for (const auto& update : policy_updates) { + for (const storage::mojom::StoragePolicyUpdatePtr& update : policy_updates) { if (!update->purge_on_shutdown) { origins_to_purge_on_shutdown_.erase(update->origin); } else { @@ -500,7 +555,7 @@ } void IndexedDBContextImpl::GetFilePathForTesting( - const storage::BucketLocator& bucket_locator, + const BucketLocator& bucket_locator, GetFilePathForTestingCallback callback) { std::move(callback).Run(GetLevelDBPath(bucket_locator)); } @@ -512,35 +567,33 @@ } void IndexedDBContextImpl::WriteToIndexedDBForTesting( - const storage::BucketLocator& bucket_locator, + const BucketLocator& bucket_locator, const std::string& key, const std::string& value, base::OnceClosure callback) { IndexedDBBucketContext* bucket_context = - GetIDBFactory()->GetBucketContextForTesting( // IN-TEST - bucket_locator.id); + GetBucketContextForTesting(bucket_locator.id); // IN-TEST TransactionalLevelDBDatabase* db = bucket_context->backing_store()->db(); std::string value_copy = value; leveldb::Status s = db->Put(key, &value_copy); CHECK(s.ok()) << s.ToString(); - GetIDBFactory()->ForceClose(bucket_locator.id, true); + bucket_context->ForceClose(true); std::move(callback).Run(); } void IndexedDBContextImpl::GetBlobCountForTesting( - const storage::BucketLocator& bucket_locator, + const BucketLocator& bucket_locator, GetBlobCountForTestingCallback callback) { std::move(callback).Run(GetBucketBlobFileCount(bucket_locator)); } void IndexedDBContextImpl::GetNextBlobNumberForTesting( - const storage::BucketLocator& bucket_locator, + const BucketLocator& bucket_locator, int64_t database_id, GetNextBlobNumberForTestingCallback callback) { IndexedDBBucketContext* bucket_context = - GetIDBFactory()->GetBucketContextForTesting( // IN-TEST - bucket_locator.id); + GetBucketContextForTesting(bucket_locator.id); // IN-TEST TransactionalLevelDBDatabase* db = bucket_context->backing_store()->db(); @@ -560,13 +613,12 @@ } void IndexedDBContextImpl::GetPathForBlobForTesting( - const storage::BucketLocator& bucket_locator, + const BucketLocator& bucket_locator, int64_t database_id, int64_t blob_number, GetPathForBlobForTestingCallback callback) { IndexedDBBucketContext* bucket_context = - GetIDBFactory()->GetBucketContextForTesting( // IN-TEST - bucket_locator.id); + GetBucketContextForTesting(bucket_locator.id); // IN-TEST IndexedDBBackingStore* backing_store = bucket_context->backing_store(); base::FilePath path = @@ -575,16 +627,19 @@ } void IndexedDBContextImpl::CompactBackingStoreForTesting( - const storage::BucketLocator& bucket_locator, + const BucketLocator& bucket_locator, base::OnceClosure callback) { - GetIDBFactory()->CompactBackingStoreForTesting(bucket_locator); // IN-TEST + auto it = bucket_contexts_.find(bucket_locator.id); + if (it != bucket_contexts_.end()) { + it->second->CompactBackingStoreForTesting(); // IN-TEST + } std::move(callback).Run(); } void IndexedDBContextImpl::GetUsageForTesting( GetUsageForTestingCallback callback) { int64_t total_size = 0; - for (const storage::BucketLocator& bucket : bucket_set_) { + for (const BucketLocator& bucket : bucket_set_) { total_size += GetBucketDiskUsage(bucket); } std::move(callback).Run(total_size); @@ -612,25 +667,16 @@ std::move(callback).Run(SchemaVersionKey::Encode(), DataVersionKey::Encode()); } -IndexedDBFactory* IndexedDBContextImpl::GetIDBFactory() { +std::vector<BucketLocator> IndexedDBContextImpl::GetAllBuckets() { DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence()); - if (!indexeddb_factory_.get()) { - indexeddb_factory_ = std::make_unique<IndexedDBFactory>(this); - } - return indexeddb_factory_.get(); + return std::vector<BucketLocator>(bucket_set_.begin(), bucket_set_.end()); } -std::vector<storage::BucketLocator> IndexedDBContextImpl::GetAllBuckets() { - DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence()); - return std::vector<storage::BucketLocator>(bucket_set_.begin(), - bucket_set_.end()); -} - -std::optional<storage::BucketLocator> IndexedDBContextImpl::LookUpBucket( +std::optional<BucketLocator> IndexedDBContextImpl::LookUpBucket( storage::BucketId bucket_id) { DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence()); auto bucket_locator = - base::ranges::find(bucket_set_, bucket_id, &storage::BucketLocator::id); + base::ranges::find(bucket_set_, bucket_id, &BucketLocator::id); if (bucket_locator == bucket_set_.end()) return std::nullopt; @@ -638,7 +684,7 @@ } int IndexedDBContextImpl::GetBucketBlobFileCount( - const storage::BucketLocator& bucket_locator) { + const BucketLocator& bucket_locator) { DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence()); int count = 0; base::FileEnumerator file_enumerator(GetBlobStorePath(bucket_locator), true, @@ -651,7 +697,7 @@ } int64_t IndexedDBContextImpl::GetBucketDiskUsage( - const storage::BucketLocator& bucket_locator) { + const BucketLocator& bucket_locator) { DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence()); if (!LookUpBucket(bucket_locator.id)) return 0; @@ -672,7 +718,7 @@ } base::Time IndexedDBContextImpl::GetBucketLastModified( - const storage::BucketLocator& bucket_locator) { + const BucketLocator& bucket_locator) { DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence()); if (!LookUpBucket(bucket_locator.id)) return base::Time(); @@ -691,14 +737,14 @@ } std::vector<base::FilePath> IndexedDBContextImpl::GetStoragePaths( - const storage::BucketLocator& bucket_locator) const { + const BucketLocator& bucket_locator) const { std::vector<base::FilePath> paths = {GetLevelDBPath(bucket_locator), GetBlobStorePath(bucket_locator)}; return paths; } base::FilePath IndexedDBContextImpl::GetDataPath( - const storage::BucketLocator& bucket_locator) const { + const BucketLocator& bucket_locator) const { if (is_incognito()) { return base::FilePath(); } @@ -727,18 +773,8 @@ return GetLegacyDataPath(); } -void IndexedDBContextImpl::FactoryOpened( - const storage::BucketLocator& bucket_locator) { - DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence()); - if (bucket_set_.insert(bucket_locator).second) { - // A newly created db, notify the quota system. - NotifyOfBucketModification(bucket_locator); - } -} - -void IndexedDBContextImpl::WritingTransactionComplete( - const storage::BucketLocator& bucket_locator, - bool flushed) { +void IndexedDBContextImpl::OnFilesWritten(const BucketLocator& bucket_locator, + bool flushed) { bucket_set_.insert(bucket_locator); NotifyOfBucketModification(bucket_locator); if (!flushed) { @@ -748,26 +784,8 @@ } } -void IndexedDBContextImpl::DatabaseDeleted( - const storage::BucketLocator& bucket_locator) { - bucket_set_.insert(bucket_locator); - NotifyOfBucketModification(bucket_locator); -} - -void IndexedDBContextImpl::BlobFilesCleaned( - const storage::BucketLocator& bucket_locator) { - NotifyOfBucketModification(bucket_locator); -} - -void IndexedDBContextImpl::NotifyIndexedDBListChanged( - const storage::BucketLocator& bucket_locator) { - for (auto& observer : observers_) { - observer->OnIndexedDBListChanged(bucket_locator); - } -} - void IndexedDBContextImpl::NotifyIndexedDBContentChanged( - const storage::BucketLocator& bucket_locator, + const BucketLocator& bucket_locator, const std::u16string& database_name, const std::u16string& object_store_name) { for (auto& observer : observers_) { @@ -778,8 +796,15 @@ IndexedDBContextImpl::~IndexedDBContextImpl() { DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence()); - if (indexeddb_factory_.get()) - indexeddb_factory_->ContextDestroyed(); + + // Invalidate the weak pointers that bind `on_ready_for_destruction` (among + // other callbacks) so that `ForceClose()` below doesn't mutate + // `bucket_contexts_` while it's being iterated. + weak_factory_.InvalidateWeakPtrs(); + for (const auto& [locator, context] : bucket_contexts_) { + context->ForceClose(/*doom=*/false); + } + bucket_contexts_.clear(); } void IndexedDBContextImpl::ShutdownOnIDBSequence() { @@ -794,7 +819,7 @@ return; } - for (const storage::BucketLocator& bucket_locator : bucket_set_) { + for (const BucketLocator& bucket_locator : bucket_set_) { // Delete the storage if its origin matches one of the origins to purge, or // if it is third-party and the top-level site is same-site with one of // those origins. @@ -810,9 +835,12 @@ } if (delete_bucket) { - GetIDBFactory()->ForceClose(bucket_locator.id, false); - base::DeletePathRecursively(GetLevelDBPath(bucket_locator)); - base::DeletePathRecursively(GetBlobStorePath(bucket_locator)); + auto it = bucket_contexts_.find(bucket_locator.id); + if (it != bucket_contexts_.end()) { + it->second->ForceClose(false); + } + base::ranges::for_each(GetStoragePaths(bucket_locator), + &base::DeletePathRecursively); } } } @@ -839,31 +867,29 @@ } base::FilePath IndexedDBContextImpl::GetBlobStorePath( - const storage::BucketLocator& bucket_locator) const { + const BucketLocator& bucket_locator) const { DCHECK(!is_incognito()); return GetDataPath(bucket_locator) .Append(indexed_db::GetBlobStoreFileName(bucket_locator)); } base::FilePath IndexedDBContextImpl::GetLevelDBPath( - const storage::BucketLocator& bucket_locator) const { + const BucketLocator& bucket_locator) const { DCHECK(!is_incognito()); return GetDataPath(bucket_locator) .Append(indexed_db::GetLevelDBFileName(bucket_locator)); } base::FilePath IndexedDBContextImpl::GetLevelDBPathForTesting( - const storage::BucketLocator& bucket_locator) const { + const BucketLocator& bucket_locator) const { return GetLevelDBPath(bucket_locator); } int64_t IndexedDBContextImpl::ReadUsageFromDisk( - const storage::BucketLocator& bucket_locator, + const BucketLocator& bucket_locator, bool write_in_progress) const { if (is_incognito()) { - if (!indexeddb_factory_) - return 0; - return indexeddb_factory_->GetInMemoryDBSize(bucket_locator); + return GetInMemoryDBSize(bucket_locator); } #if BUILDFLAG(IS_WIN) @@ -888,7 +914,7 @@ } void IndexedDBContextImpl::NotifyOfBucketModification( - const storage::BucketLocator& bucket_locator) { + const BucketLocator& bucket_locator) { // This method is called very frequently, for example after every transaction // commits. Recalculating disk usage is expensive and often unnecessary (e.g. // when many transactions commit in a row). Therefore, use a null delta to @@ -899,7 +925,9 @@ storage::QuotaClientType::kIndexedDatabase, bucket_locator, /*delta=*/std::nullopt, base::Time::Now(), base::SequencedTaskRunner::GetCurrentDefault(), base::DoNothing()); - NotifyIndexedDBListChanged(bucket_locator); + for (auto& observer : observers_) { + observer->OnIndexedDBListChanged(bucket_locator); + } } void IndexedDBContextImpl::InitializeFromFilesIfNeeded( @@ -926,31 +954,30 @@ return; } - using Barrier = - base::RepeatingCallback<void(std::optional<storage::BucketLocator>)>; - Barrier barrier = - base::BarrierCallback<std::optional<storage::BucketLocator>>( - storage_key_to_file_path.size() + bucket_id_to_file_path.size(), - base::BindOnce( - [](base::WeakPtr<IndexedDBContextImpl> context, - const std::vector<std::optional<storage::BucketLocator>>& - bucket_locators) { - DCHECK(context); - for (auto& locator : bucket_locators) { - if (locator) - context->bucket_set_.insert(*locator); - } - context->did_initialize_from_files_ = true; - for (base::OnceClosure& callback : - context->on_initialize_from_files_callbacks_) { - std::move(callback).Run(); - if (!context) { - return; - } - } - context->on_initialize_from_files_callbacks_.clear(); - }, - weak_factory_.GetWeakPtr())); + using Barrier = base::RepeatingCallback<void(std::optional<BucketLocator>)>; + Barrier barrier = base::BarrierCallback<std::optional<BucketLocator>>( + storage_key_to_file_path.size() + bucket_id_to_file_path.size(), + base::BindOnce( + [](base::WeakPtr<IndexedDBContextImpl> context, + const std::vector<std::optional<BucketLocator>>& bucket_locators) { + DCHECK(context); + for (const std::optional<BucketLocator>& locator : + bucket_locators) { + if (locator) { + context->bucket_set_.insert(*locator); + } + } + context->did_initialize_from_files_ = true; + for (base::OnceClosure& callback : + context->on_initialize_from_files_callbacks_) { + std::move(callback).Run(); + if (!context) { + return; + } + } + context->on_initialize_from_files_callbacks_.clear(); + }, + weak_factory_.GetWeakPtr())); auto on_lookup_done = base::BindRepeating( [](Barrier barrier, @@ -961,14 +988,14 @@ }, barrier); - for (auto& iter : storage_key_to_file_path) { + for (const auto& [storage_key, file_path] : storage_key_to_file_path) { quota_manager_proxy()->UpdateOrCreateBucket( - storage::BucketInitParams::ForDefaultBucket(iter.first), + storage::BucketInitParams::ForDefaultBucket(storage_key), idb_task_runner_, on_lookup_done); } - for (auto& iter : bucket_id_to_file_path) { - quota_manager_proxy()->GetBucketById(iter.first, idb_task_runner_, + for (const auto& [bucket_id, file_path] : bucket_id_to_file_path) { + quota_manager_proxy()->GetBucketById(bucket_id, idb_task_runner_, on_lookup_done); } } @@ -1040,4 +1067,123 @@ return bucket_id_to_file_path; } +void IndexedDBContextImpl::ForEachBucketContext( + IndexedDBBucketContext::InstanceClosure callback) { + for_each_bucket_context_ = callback; + for (auto& [bucket_id, bucket_context] : bucket_contexts_) { + bucket_context->RunInstanceClosure(for_each_bucket_context_); + } +} + +int64_t IndexedDBContextImpl::GetInMemoryDBSize( + const BucketLocator& bucket_locator) const { + auto it = bucket_contexts_.find(bucket_locator.id); + if (it == bucket_contexts_.end()) { + return 0; + } + IndexedDBBackingStore* backing_store = it->second->backing_store(); + int64_t level_db_size = 0; + leveldb::Status s = + GetDBSizeFromEnv(backing_store->db()->env(), "/", &level_db_size); + if (!s.ok()) { + LOG(ERROR) << "Failed to GetDBSizeFromEnv: " << s.ToString(); + } + return backing_store->GetInMemoryBlobSize() + level_db_size; +} + +std::vector<storage::BucketId> +IndexedDBContextImpl::GetOpenBucketIdsForTesting() const { + std::vector<storage::BucketId> output; + output.reserve(bucket_contexts_.size()); + for (const auto& [bucket_id, bucket_context] : bucket_contexts_) { + output.push_back(bucket_id); + } + return output; +} + +IndexedDBBucketContext* IndexedDBContextImpl::GetBucketContextForTesting( + const storage::BucketId& id) const { + auto it = bucket_contexts_.find(id); + if (it != bucket_contexts_.end()) { + return it->second.get(); + } + return nullptr; +} + +void IndexedDBContextImpl::FillInBucketMetadata( + storage::mojom::IdbBucketMetadataPtr info, + base::OnceCallback<void(storage::mojom::IdbBucketMetadataPtr)> result) { + auto it = bucket_contexts_.find(info->bucket_locator.id); + if (it == bucket_contexts_.end()) { + std::move(result).Run(std::move(info)); + } else { + it->second->FillInMetadata(std::move(info), std::move(result)); + } +} + +IndexedDBBucketContext& IndexedDBContextImpl::GetOrCreateBucketContext( + const storage::BucketInfo& bucket, + const base::FilePath& data_directory) { + TRACE_EVENT0("IndexedDB", "indexed_db::GetOrCreateBucketContext"); + auto it = bucket_contexts_.find(bucket.id); + if (it != bucket_contexts_.end()) { + return *it->second; + } + + const BucketLocator bucket_locator = bucket.ToBucketLocator(); + IndexedDBBucketContext::Delegate bucket_delegate; + bucket_delegate.on_ready_for_destruction = base::BindRepeating( + [](base::WeakPtr<IndexedDBContextImpl> context, + const BucketLocator& bucket_locator) { + if (context) { + context->bucket_contexts_.erase(bucket_locator.id); + } + }, + weak_factory_.GetWeakPtr(), bucket_locator); + bucket_delegate.on_content_changed = base::BindRepeating( + [](base::WeakPtr<IndexedDBContextImpl> context, + BucketLocator bucket_locator, const std::u16string& database_name, + const std::u16string& object_store_name) { + if (context) { + context->NotifyIndexedDBContentChanged(bucket_locator, database_name, + object_store_name); + } + }, + weak_factory_.GetWeakPtr(), bucket_locator); + bucket_delegate.on_files_written = base::BindRepeating( + [](base::WeakPtr<IndexedDBContextImpl> context, + BucketLocator bucket_locator, bool did_sync) { + if (context) { + context->OnFilesWritten(bucket_locator, did_sync); + } + }, + weak_factory_.GetWeakPtr(), bucket_locator); + bucket_delegate.for_each_bucket_context = base::BindRepeating( + &IndexedDBContextImpl::ForEachBucketContext, weak_factory_.GetWeakPtr()); + + mojo::PendingRemote<storage::mojom::BlobStorageContext> + cloned_blob_storage_context; + // May be null in unit tests. + if (blob_storage_context()) { + blob_storage_context()->Clone( + cloned_blob_storage_context.InitWithNewPipeAndPassReceiver()); + } + + mojo::PendingRemote<storage::mojom::FileSystemAccessContext> fsa_context; + // May be null in unit tests. + if (file_system_access_context()) { + file_system_access_context()->Clone( + fsa_context.InitWithNewPipeAndPassReceiver()); + } + + auto bucket_context = std::make_unique<IndexedDBBucketContext>( + bucket, data_directory, std::move(bucket_delegate), quota_manager_proxy(), + IOTaskRunner(), std::move(cloned_blob_storage_context), + std::move(fsa_context), for_each_bucket_context_); + + it = bucket_contexts_.emplace(bucket_locator.id, std::move(bucket_context)) + .first; + return *it->second; +} + } // namespace content
diff --git a/content/browser/indexed_db/indexed_db_context_impl.h b/content/browser/indexed_db/indexed_db_context_impl.h index f8fe89c..82f4ea3 100644 --- a/content/browser/indexed_db/indexed_db_context_impl.h +++ b/content/browser/indexed_db/indexed_db_context_impl.h
@@ -27,7 +27,7 @@ #include "components/services/storage/public/mojom/file_system_access_context.mojom.h" #include "components/services/storage/public/mojom/quota_client.mojom.h" #include "components/services/storage/public/mojom/storage_policy_update.mojom.h" -#include "content/browser/indexed_db/indexed_db_backing_store.h" +#include "content/browser/indexed_db/indexed_db_bucket_context.h" #include "content/common/content_export.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -49,7 +49,6 @@ } // namespace storage namespace content { -class IndexedDBFactory; class IndexedDBQuotaClient; class CONTENT_EXPORT IndexedDBContextImpl @@ -139,8 +138,6 @@ void DeleteBucketData(const storage::BucketLocator& bucket_locator, base::OnceCallback<void(bool success)> callback); - IndexedDBFactory* GetIDBFactory(); - int64_t GetBucketDiskUsage(const storage::BucketLocator& bucket_locator); const scoped_refptr<base::SequencedTaskRunner>& IDBTaskRunner() const { @@ -151,18 +148,11 @@ return io_task_runner_; } - // Methods called by IndexedDBFactory or IndexedDBDispatcherHost for - // quota support. - void FactoryOpened(const storage::BucketLocator& bucket_locator); - // Called when a transaction has completed for the given bucket. `flushed` is - // set to true if the transaction had strict durability (i.e. changes are - // flushed/synced to disk). - void WritingTransactionComplete(const storage::BucketLocator& bucket_locator, - bool flushed); - void DatabaseDeleted(const storage::BucketLocator& bucket_locator); - - // Called when blob files have been cleaned (an aggregated delayed task). - void BlobFilesCleaned(const storage::BucketLocator& bucket_locator); + // Called when files for the given bucket have been written. `flushed` is set + // to true if the writes were flushed to disk already, as with a transaction + // that has strict durability. + void OnFilesWritten(const storage::BucketLocator& bucket_locator, + bool flushed); // Will be null in unit tests. const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy() const { @@ -196,7 +186,6 @@ : nullptr; } - void NotifyIndexedDBListChanged(const storage::BucketLocator& bucket_locator); void NotifyIndexedDBContentChanged( const storage::BucketLocator& bucket_locator, const std::u16string& database_name, @@ -207,11 +196,14 @@ base::FilePath GetLevelDBPathForTesting( const storage::BucketLocator& bucket_locator) const; + IndexedDBBucketContext* GetBucketContextForTesting( + const storage::BucketId& id) const; + private: friend class IndexedDBTest; friend class IndexedDBFactoryTest; - - class IndexedDBGetUsageAndQuotaCallback; + FRIEND_TEST_ALL_PREFIXES(IndexedDBTest, BasicFactoryCreationAndTearDown); + FRIEND_TEST_ALL_PREFIXES(IndexedDBTest, TooLongOrigin); void BindControlOnIDBSequence( mojo::PendingReceiver<storage::mojom::IndexedDBControl> control); @@ -283,6 +275,28 @@ GetAllBucketsDetailsCallback callback, std::vector<storage::QuotaErrorOr<storage::BucketInfo>> bucket_infos); + // Applies the given `callback` to all bucket contexts. + void ForEachBucketContext(IndexedDBBucketContext::InstanceClosure callback); + + // For usage reporting. + int64_t GetInMemoryDBSize(const storage::BucketLocator& bucket_locator) const; + + std::vector<storage::BucketId> GetOpenBucketIdsForTesting() const; + + // Finishes filling in `info` with data relevant to idb-internals and passes + // the result back via `result`. The bucket is described by + // `info->bucket_locator`. + void FillInBucketMetadata( + storage::mojom::IdbBucketMetadataPtr info, + base::OnceCallback<void(storage::mojom::IdbBucketMetadataPtr)> result); + + IndexedDBBucketContext& GetOrCreateBucketContext( + const storage::BucketInfo& bucket, + const base::FilePath& data_directory); + + void CompactBackingStoreForTesting( + const storage::BucketLocator& bucket_locator); + const scoped_refptr<base::SequencedTaskRunner> idb_task_runner_; const scoped_refptr<base::TaskRunner> io_task_runner_; @@ -290,7 +304,6 @@ mojo::Remote<storage::mojom::BlobStorageContext> blob_storage_context_; mojo::Remote<storage::mojom::FileSystemAccessContext> file_system_access_context_; - std::unique_ptr<IndexedDBFactory> indexeddb_factory_; // If `base_data_path_` is empty then this is an incognito session and the // backing store will be held in-memory rather than on-disk. @@ -299,6 +312,10 @@ // If true, nothing (not even session-only data) should be deleted on exit. bool force_keep_session_state_; const scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; + + // This set contains all buckets that have stored IDB data on disk. This is + // distinct from `bucket_contexts_`, which are only created for active IDB + // clients. std::set<storage::BucketLocator> bucket_set_; // This map is a cache of the size used by a given bucket. It's calculated by @@ -342,13 +359,21 @@ const std::unique_ptr<storage::QuotaClientCallbackWrapper> quota_client_wrapper_; - mojo::ReceiverSet<storage::mojom::IndexedDBControl> receivers_; + mojo::ReceiverSet<storage::mojom::IndexedDBControl> control_receivers_; mojo::ReceiverSet<storage::mojom::IndexedDBControlTest> test_receivers_; + // See comment above IDBFactory overrides. + mojo::ReceiverSet<blink::mojom::IDBFactory> factory_receivers_; std::optional<mojo::Receiver<storage::mojom::MockFailureInjector>> mock_failure_injector_; mojo::RemoteSet<storage::mojom::IndexedDBObserver> observers_; mojo::Receiver<storage::mojom::QuotaClient> quota_client_receiver_; + // TODO(crbug.com/1474996): these bucket contexts need to be `SequenceBound`. + std::map<storage::BucketId, std::unique_ptr<IndexedDBBucketContext>> + bucket_contexts_; + + IndexedDBBucketContext::InstanceClosure for_each_bucket_context_; + // weak_factory_->GetWeakPtr() may be used on any thread, but the resulting // pointer must only be checked/used on idb_task_runner_. base::WeakPtrFactory<IndexedDBContextImpl> weak_factory_{this};
diff --git a/content/browser/indexed_db/indexed_db_context_unittest.cc b/content/browser/indexed_db/indexed_db_context_unittest.cc index b86fb96f..3dafd65 100644 --- a/content/browser/indexed_db/indexed_db_context_unittest.cc +++ b/content/browser/indexed_db/indexed_db_context_unittest.cc
@@ -21,7 +21,6 @@ #include "components/services/storage/public/cpp/buckets/constants.h" #include "components/services/storage/public/cpp/quota_error_or.h" #include "content/browser/indexed_db/indexed_db_context_impl.h" -#include "content/browser/indexed_db/indexed_db_factory.h" #include "content/browser/indexed_db/indexed_db_leveldb_operations.h" #include "content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h" #include "content/browser/indexed_db/mock_mojo_indexed_db_factory_client.h"
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc index 6ceb34f..689dab8 100644 --- a/content/browser/indexed_db/indexed_db_database.cc +++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -327,8 +327,7 @@ task_state != IndexedDBConnectionCoordinator::ExecuteTaskResult::kError); DCHECK(connections_.empty()); force_closing_ = false; - if (CanBeDestroyed()) - bucket_context_->QueueRunTasks(); + bucket_context_->QueueRunTasks(); return status; }
diff --git a/content/browser/indexed_db/indexed_db_database_unittest.cc b/content/browser/indexed_db/indexed_db_database_unittest.cc index 8c12cb9..21c3302 100644 --- a/content/browser/indexed_db/indexed_db_database_unittest.cc +++ b/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -32,7 +32,6 @@ #include "content/browser/indexed_db/indexed_db_connection.h" #include "content/browser/indexed_db/indexed_db_cursor.h" #include "content/browser/indexed_db/indexed_db_database_callbacks.h" -#include "content/browser/indexed_db/indexed_db_factory.h" #include "content/browser/indexed_db/indexed_db_factory_client.h" #include "content/browser/indexed_db/indexed_db_fake_backing_store.h" #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" @@ -69,8 +68,6 @@ base::SingleThreadTaskRunner::GetCurrentDefault().get()); IndexedDBBucketContext::Delegate delegate; - delegate.on_fatal_error = base::BindRepeating( - &IndexedDBDatabaseTest::OnFatalError, weak_factory_.GetWeakPtr()); delegate.on_ready_for_destruction = base::BindRepeating( &IndexedDBDatabaseTest::OnBucketContextReadyForDestruction, weak_factory_.GetWeakPtr()); @@ -90,10 +87,6 @@ void TearDown() override { db_ = nullptr; } - void OnFatalError(leveldb::Status s, const std::string& error_message) { - error_called_ = true; - } - void OnBucketContextReadyForDestruction() { bucket_context_.reset(); } void RunPostedTasks() { @@ -111,13 +104,11 @@ scoped_refptr<storage::MockQuotaManager> quota_manager_; scoped_refptr<storage::MockQuotaManagerProxy> quota_manager_proxy_; - // As `this` is owned by `bucket_context_`, tests that cause the database to + // As this is owned by `bucket_context_`, tests that cause the database to // be destroyed must manually reset this to null to avoid triggering dangling // pointer warnings. raw_ptr<IndexedDBDatabase> db_ = nullptr; - bool error_called_ = false; - base::WeakPtrFactory<IndexedDBDatabaseTest> weak_factory_{this}; }; @@ -517,7 +508,7 @@ EXPECT_TRUE(s.ok()); transaction_->SetCommitFlag(); RunPostedTasks(); - EXPECT_FALSE(error_called_); + EXPECT_TRUE(bucket_context_); EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); } @@ -539,7 +530,7 @@ db_->metadata().object_stores.find(store_id)->second.indexes.size()); transaction_->SetCommitFlag(); RunPostedTasks(); - EXPECT_FALSE(error_called_); + EXPECT_TRUE(bucket_context_); EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); EXPECT_EQ( 1ULL, @@ -567,9 +558,11 @@ /*auto_increment=*/false, transaction_); EXPECT_TRUE(s.ok()); EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); + db_ = nullptr; transaction_->SetCommitFlag(); RunPostedTasks(); - EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); + // A transaction error results in a deleted db. + EXPECT_TRUE(bucket_context_->GetDatabasesForTesting().empty()); } TEST_F(IndexedDBDatabaseOperationAbortTest, CreateIndex) { @@ -588,11 +581,11 @@ EXPECT_EQ( 1ULL, db_->metadata().object_stores.find(store_id)->second.indexes.size()); + db_ = nullptr; transaction_->SetCommitFlag(); RunPostedTasks(); - EXPECT_TRUE(error_called_); - EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); - db_ = nullptr; + // A transaction error results in a deleted db. + EXPECT_TRUE(bucket_context_->GetDatabasesForTesting().empty()); } TEST_F(IndexedDBDatabaseOperationTest, CreatePutDelete) { @@ -628,11 +621,11 @@ EXPECT_TRUE(s.ok()); EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); - db_ = nullptr; transaction_->SetCommitFlag(); RunPostedTasks(); - EXPECT_FALSE(error_called_); + // A transaction error would have resulted in a deleted db. + EXPECT_FALSE(bucket_context_->GetDatabasesForTesting().empty()); EXPECT_TRUE(s.ok()); }
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc index 5dd4a92..8cb1bad42 100644 --- a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc +++ b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
@@ -31,7 +31,6 @@ #include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "content/browser/indexed_db/indexed_db_context_impl.h" #include "content/browser/indexed_db/indexed_db_database_callbacks.h" -#include "content/browser/indexed_db/indexed_db_factory.h" #include "content/browser/indexed_db/indexed_db_factory_client.h" #include "content/browser/indexed_db/indexed_db_pending_connection.h" #include "content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h"
diff --git a/content/browser/indexed_db/indexed_db_factory.cc b/content/browser/indexed_db/indexed_db_factory.cc deleted file mode 100644 index fab8553..0000000 --- a/content/browser/indexed_db/indexed_db_factory.cc +++ /dev/null
@@ -1,430 +0,0 @@ -// Copyright 2013 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/indexed_db/indexed_db_factory.h" - -#include <inttypes.h> -#include <stdint.h> - -#include <string> -#include <tuple> -#include <utility> -#include <vector> - -#include "base/command_line.h" -#include "base/compiler_specific.h" -#include "base/containers/contains.h" -#include "base/feature_list.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/functional/bind.h" -#include "base/functional/callback_helpers.h" -#include "base/logging.h" -#include "base/metrics/histogram_functions.h" -#include "base/metrics/histogram_macros.h" -#include "base/ranges/algorithm.h" -#include "base/strings/strcat.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/system/sys_info.h" -#include "base/task/sequenced_task_runner.h" -#include "base/timer/elapsed_timer.h" -#include "base/timer/timer.h" -#include "base/trace_event/base_tracing.h" -#include "components/services/storage/indexed_db/leveldb/leveldb_factory.h" -#include "components/services/storage/indexed_db/scopes/leveldb_scopes.h" -#include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h" -#include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_factory.h" -#include "components/services/storage/privileged/mojom/indexed_db_control.mojom.h" -#include "components/services/storage/public/mojom/blob_storage_context.mojom.h" -#include "content/browser/indexed_db/indexed_db_bucket_context.h" -#include "content/browser/indexed_db/indexed_db_bucket_context_handle.h" -#include "content/browser/indexed_db/indexed_db_class_factory.h" -#include "content/browser/indexed_db/indexed_db_connection.h" -#include "content/browser/indexed_db/indexed_db_context_impl.h" -#include "content/browser/indexed_db/indexed_db_data_format_version.h" -#include "content/browser/indexed_db/indexed_db_database_error.h" -#include "content/browser/indexed_db/indexed_db_factory_client.h" -#include "content/browser/indexed_db/indexed_db_leveldb_operations.h" -#include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h" -#include "content/browser/indexed_db/indexed_db_reporting.h" -#include "content/browser/indexed_db/indexed_db_task_helper.h" -#include "content/browser/indexed_db/indexed_db_tombstone_sweeper.h" -#include "content/browser/indexed_db/indexed_db_transaction.h" -#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h" -#include "third_party/leveldatabase/env_chromium.h" - -namespace content { - -namespace { - -leveldb::Status GetDBSizeFromEnv(leveldb::Env* env, - const std::string& path, - int64_t* total_size_out) { - *total_size_out = 0; - // Root path should be /, but in MemEnv, a path name is not tailed with '/' - DCHECK_EQ(path.back(), '/'); - const std::string path_without_slash = path.substr(0, path.length() - 1); - - // This assumes that leveldb will not put a subdirectory into the directory - std::vector<std::string> file_names; - leveldb::Status s = env->GetChildren(path_without_slash, &file_names); - if (!s.ok()) { - return s; - } - - for (std::string& file_name : file_names) { - file_name.insert(0, path); - uint64_t file_size; - s = env->GetFileSize(file_name, &file_size); - if (!s.ok()) { - return s; - } else { - *total_size_out += static_cast<int64_t>(file_size); - } - } - return s; -} - -} // namespace - -IndexedDBFactory::IndexedDBFactory(IndexedDBContextImpl* context) - : context_(context) { - DCHECK(context); -} - -IndexedDBFactory::~IndexedDBFactory() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -} - -void IndexedDBFactory::AddReceiver( - std::optional<storage::BucketInfo> bucket, - mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> - client_state_checker_remote, - base::UnguessableToken client_token, - mojo::PendingReceiver<blink::mojom::IDBFactory> pending_receiver) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (bucket) { - GetOrCreateBucketContext(*bucket, - context_->GetDataPath(bucket->ToBucketLocator())) - .AddReceiver(std::move(client_state_checker_remote), client_token, - std::move(pending_receiver)); - } else { - receivers_.Add(this, std::move(pending_receiver)); - } -} - -void IndexedDBFactory::GetDatabaseInfo(GetDatabaseInfoCallback callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - TRACE_EVENT0("IndexedDB", "IndexedDBFactory::GetDatabaseInfo"); - - std::move(callback).Run( - {}, blink::mojom::IDBError::New(blink::mojom::IDBException::kUnknownError, - u"Internal error.")); -} - -void IndexedDBFactory::Open( - mojo::PendingAssociatedRemote<blink::mojom::IDBFactoryClient> - pending_factory_client, - mojo::PendingAssociatedRemote<blink::mojom::IDBDatabaseCallbacks> - database_callbacks_remote, - const std::u16string& name, - int64_t version, - mojo::PendingAssociatedReceiver<blink::mojom::IDBTransaction> - transaction_receiver, - int64_t transaction_id) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - TRACE_EVENT0("IndexedDB", "IndexedDBFactory::Open"); - - IndexedDBFactoryClient(std::move(pending_factory_client)) - .OnError(IndexedDBDatabaseError(blink::mojom::IDBException::kUnknownError, - u"Internal error.")); -} - -void IndexedDBFactory::DeleteDatabase( - mojo::PendingAssociatedRemote<blink::mojom::IDBFactoryClient> - pending_factory_client, - const std::u16string& name, - bool force_close) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - TRACE_EVENT0("IndexedDB", "IndexedDBFactory::DeleteDatabase"); - - IndexedDBFactoryClient(std::move(pending_factory_client)) - .OnError(IndexedDBDatabaseError(blink::mojom::IDBException::kUnknownError, - u"Internal error.")); -} - -void IndexedDBFactory::HandleBackingStoreFailure( - const storage::BucketLocator& bucket_locator) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // nullptr after ContextDestroyed() called, and in some unit tests. - if (!context_) { - return; - } - context_->ForceClose( - bucket_locator.id, - storage::mojom::ForceCloseReason::FORCE_CLOSE_BACKING_STORE_FAILURE, - base::DoNothing()); -} - -void IndexedDBFactory::HandleBackingStoreCorruption( - storage::BucketLocator bucket_locator, - const IndexedDBDatabaseError& error) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(context_); - const base::FilePath path_base = context_->GetDataPath(bucket_locator); - - // The message may contain the database path, which may be considered - // sensitive data, and those strings are passed to the extension, so strip it. - std::string sanitized_message = base::UTF16ToUTF8(error.message()); - base::ReplaceSubstringsAfterOffset(&sanitized_message, 0u, - path_base.AsUTF8Unsafe(), "..."); - IndexedDBBackingStore::RecordCorruptionInfo(path_base, bucket_locator, - sanitized_message); - HandleBackingStoreFailure(bucket_locator); - // Note: DestroyLevelDB only deletes LevelDB files, leaving all others, - // so our corruption info file will remain. - // The blob directory will be deleted when the database is recreated - // the next time it is opened. - const base::FilePath file_path = - path_base.Append(indexed_db::GetLevelDBFileName(bucket_locator)); - leveldb::Status s = - IndexedDBClassFactory::Get()->leveldb_factory().DestroyLevelDB(file_path); - DLOG_IF(ERROR, !s.ok()) << "Unable to delete backing store: " << s.ToString(); -} - -void IndexedDBFactory::ForceClose(storage::BucketId bucket_id, - bool will_be_deleted) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto it = bucket_contexts_.find(bucket_id); - if (it == bucket_contexts_.end()) { - return; - } - - it->second->ForceClose(/*doom=*/will_be_deleted); -} - -void IndexedDBFactory::ContextDestroyed() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Set `context_` to nullptr first to ensure no re-entry into the `context_` - // object during shutdown. This can happen in methods like BlobFilesCleaned. - context_ = nullptr; - // Invalidate the weak pointers that bind `on_ready_for_destruction` (among - // other callbacks) so that `ForceClose()` below doesn't mutate - // `bucket_contexts_` while it's being iterated. - idb_context_destruction_weak_factory_.InvalidateWeakPtrs(); - for (const auto& pair : bucket_contexts_) { - pair.second->ForceClose(/*doom=*/false); - } - bucket_contexts_.clear(); -} - -void IndexedDBFactory::ReportOutstandingBlobs( - const storage::BucketLocator& bucket_locator, - bool blobs_outstanding) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!context_) { - return; - } - auto it = bucket_contexts_.find(bucket_locator.id); - CHECK(it != bucket_contexts_.end()); - - it->second->ReportOutstandingBlobs(blobs_outstanding); -} - -void IndexedDBFactory::BlobFilesCleaned( - const storage::BucketLocator& bucket_locator) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // nullptr after ContextDestroyed() called, and in some unit tests. - if (!context_) { - return; - } - context_->BlobFilesCleaned(bucket_locator); -} - -void IndexedDBFactory::ForEachBucketContext( - IndexedDBBucketContext::InstanceClosure callback) { - for_each_bucket_context_ = callback; - for (auto& [bucket_id, bucket_context] : bucket_contexts_) { - bucket_context->RunInstanceClosure(for_each_bucket_context_); - } -} - -int64_t IndexedDBFactory::GetInMemoryDBSize( - const storage::BucketLocator& bucket_locator) const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto it = bucket_contexts_.find(bucket_locator.id); - if (it == bucket_contexts_.end()) { - return 0; - } - IndexedDBBackingStore* backing_store = it->second->backing_store(); - int64_t level_db_size = 0; - leveldb::Status s = - GetDBSizeFromEnv(backing_store->db()->env(), "/", &level_db_size); - if (!s.ok()) { - LOG(ERROR) << "Failed to GetDBSizeFromEnv: " << s.ToString(); - } - return backing_store->GetInMemoryBlobSize() + level_db_size; -} - -std::vector<storage::BucketId> IndexedDBFactory::GetOpenBucketIdsForTesting() - const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - std::vector<storage::BucketId> output; - output.reserve(bucket_contexts_.size()); - for (const auto& pair : bucket_contexts_) { - output.push_back(pair.first); - } - return output; -} - -IndexedDBBucketContext* IndexedDBFactory::GetBucketContextForTesting( - const storage::BucketId& id) const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto it = bucket_contexts_.find(id); - if (it != bucket_contexts_.end()) { - return it->second.get(); - } - return nullptr; -} - -void IndexedDBFactory::FillInBucketMetadata( - storage::mojom::IdbBucketMetadataPtr info, - base::OnceCallback<void(storage::mojom::IdbBucketMetadataPtr)> result) { - auto it = bucket_contexts_.find(info->bucket_locator.id); - if (it == bucket_contexts_.end()) { - std::move(result).Run(std::move(info)); - } else { - it->second->FillInMetadata(std::move(info), std::move(result)); - } -} - -void IndexedDBFactory::CompactBackingStoreForTesting( - const storage::BucketLocator& bucket_locator) { - auto it = bucket_contexts_.find(bucket_locator.id); - if (it != bucket_contexts_.end()) { - it->second->CompactBackingStoreForTesting(); // IN-TEST - } -} - -IndexedDBBucketContext& IndexedDBFactory::GetOrCreateBucketContext( - const storage::BucketInfo& bucket, - const base::FilePath& data_directory) { - TRACE_EVENT0("IndexedDB", "indexed_db::GetOrCreateBucketContext"); - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto it = bucket_contexts_.find(bucket.id); - if (it != bucket_contexts_.end()) { - return *it->second; - } - UMA_HISTOGRAM_ENUMERATION( - indexed_db::kBackingStoreActionUmaName, - indexed_db::IndexedDBAction::kBackingStoreOpenAttempt); - - const storage::BucketLocator bucket_locator = bucket.ToBucketLocator(); - IndexedDBBucketContext::Delegate bucket_delegate; - bucket_delegate.on_fatal_error = base::BindRepeating( - [](const storage::BucketLocator& bucket_locator, - base::WeakPtr<IndexedDBFactory> factory, leveldb::Status s, - const std::string& error_message) { - if (factory) { - factory->OnDatabaseError(bucket_locator, s, error_message); - } - }, - bucket_locator, weak_factory_.GetWeakPtr()); - bucket_delegate.on_corruption = base::BindRepeating( - [](const storage::BucketLocator& bucket_locator, - base::WeakPtr<IndexedDBFactory> factory, - const IndexedDBDatabaseError& error) { - if (factory) { - factory->HandleBackingStoreCorruption(bucket_locator, error); - } - }, - bucket_locator, weak_factory_.GetWeakPtr()); - bucket_delegate.on_ready_for_destruction = base::BindRepeating( - [](const storage::BucketLocator& bucket_locator, - base::WeakPtr<IndexedDBFactory> factory) { - if (factory) { - factory->bucket_contexts_.erase(bucket_locator.id); - } - }, - bucket_locator, idb_context_destruction_weak_factory_.GetWeakPtr()); - bucket_delegate.on_content_changed = base::BindRepeating( - [](base::WeakPtr<IndexedDBFactory> factory, - storage::BucketLocator bucket_locator, - const std::u16string& database_name, - const std::u16string& object_store_name) { - if (factory) { - factory->context_->NotifyIndexedDBContentChanged( - bucket_locator, database_name, object_store_name); - } - }, - idb_context_destruction_weak_factory_.GetWeakPtr(), bucket_locator); - bucket_delegate.on_writing_transaction_complete = base::BindRepeating( - [](base::WeakPtr<IndexedDBFactory> factory, - storage::BucketLocator bucket_locator, bool did_sync) { - if (factory) { - factory->context_->WritingTransactionComplete(bucket_locator, - did_sync); - } - }, - idb_context_destruction_weak_factory_.GetWeakPtr(), bucket_locator); - bucket_delegate.for_each_bucket_context = base::BindRepeating( - &IndexedDBFactory::ForEachBucketContext, weak_factory_.GetWeakPtr()); - - mojo::PendingRemote<storage::mojom::BlobStorageContext> blob_storage_context; - // May be null in unit tests. - if (context_->blob_storage_context()) { - context_->blob_storage_context()->Clone( - blob_storage_context.InitWithNewPipeAndPassReceiver()); - } - - mojo::PendingRemote<storage::mojom::FileSystemAccessContext> fsa_context; - // May be null in unit tests. - if (context_->file_system_access_context()) { - context_->file_system_access_context()->Clone( - fsa_context.InitWithNewPipeAndPassReceiver()); - } - - auto bucket_context = std::make_unique<IndexedDBBucketContext>( - bucket, data_directory, std::move(bucket_delegate), - context_->quota_manager_proxy(), context_->IOTaskRunner(), - std::move(blob_storage_context), std::move(fsa_context), - for_each_bucket_context_); - - it = bucket_contexts_.emplace(bucket_locator.id, std::move(bucket_context)) - .first; - return *it->second; -} - -void IndexedDBFactory::OnDatabaseError( - const storage::BucketLocator& bucket_locator, - leveldb::Status status, - const std::string& message) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!status.ok()); - if (status.IsCorruption()) { - IndexedDBDatabaseError error( - blink::mojom::IDBException::kUnknownError, - base::ASCIIToUTF16(message.empty() ? status.ToString() : message)); - HandleBackingStoreCorruption(bucket_locator, error); - return; - } - if (status.IsIOError()) { - context_->quota_manager_proxy()->OnClientWriteFailed( - bucket_locator.storage_key); - } - HandleBackingStoreFailure(bucket_locator); -} - -void IndexedDBFactory::OnDatabaseDeleted( - const storage::BucketLocator& bucket_locator) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!context_) { - return; - } - context_->DatabaseDeleted(bucket_locator); -} - -} // namespace content
diff --git a/content/browser/indexed_db/indexed_db_factory.h b/content/browser/indexed_db/indexed_db_factory.h deleted file mode 100644 index a9d5ef82..0000000 --- a/content/browser/indexed_db/indexed_db_factory.h +++ /dev/null
@@ -1,175 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_FACTORY_H_ -#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_FACTORY_H_ - -#include <stddef.h> - -#include <map> -#include <memory> -#include <set> -#include <string> -#include <tuple> -#include <utility> -#include <vector> - -#include "base/functional/callback.h" -#include "base/gtest_prod_util.h" -#include "base/memory/raw_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/sequence_checker.h" -#include "base/time/time.h" -#include "components/services/storage/privileged/mojom/indexed_db_client_state_checker.mojom.h" -#include "components/services/storage/public/cpp/buckets/bucket_id.h" -#include "components/services/storage/public/cpp/buckets/bucket_info.h" -#include "components/services/storage/public/cpp/buckets/bucket_locator.h" -#include "components/services/storage/public/mojom/blob_storage_context.mojom-forward.h" -#include "components/services/storage/public/mojom/file_system_access_context.mojom-forward.h" -#include "content/browser/indexed_db/indexed_db_backing_store.h" -#include "content/browser/indexed_db/indexed_db_bucket_context.h" -#include "content/browser/indexed_db/indexed_db_data_loss_info.h" -#include "content/browser/indexed_db/indexed_db_database_error.h" -#include "content/browser/indexed_db/indexed_db_pending_connection.h" -#include "content/browser/indexed_db/indexed_db_task_helper.h" -#include "content/common/content_export.h" -#include "mojo/public/cpp/bindings/receiver_set.h" -#include "third_party/blink/public/common/storage_key/storage_key.h" -#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h" -#include "third_party/leveldatabase/src/include/leveldb/status.h" - -namespace base { -class FilePath; -} // namespace base - -namespace content { -class IndexedDBContextImpl; - -// This class has a 1:1 relationship with `IndexedDBContextImpl`. -// TODO(crbug.com/1474996): merge with `IndexedDBContextImpl`. -class CONTENT_EXPORT IndexedDBFactory : public blink::mojom::IDBFactory { - public: - explicit IndexedDBFactory(IndexedDBContextImpl* context); - - IndexedDBFactory(const IndexedDBFactory&) = delete; - IndexedDBFactory& operator=(const IndexedDBFactory&) = delete; - - ~IndexedDBFactory() override; - - void AddReceiver( - std::optional<storage::BucketInfo> bucket, - mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>, - base::UnguessableToken client_token, - mojo::PendingReceiver<blink::mojom::IDBFactory> pending_receiver); - - // blink::mojom::IDBFactory implementation: - // - // The `IndexedDBFactory` is only an IDBFactory implementation for the case of - // a missing bucket, i.e. where the Quota system failed to retrieve a bucket. - // Hence, these implementations only return errors. In the normal case, - // the IndexedDBBucketContext is the IDBFactory endpoint. - void GetDatabaseInfo(GetDatabaseInfoCallback callback) override; - void Open(mojo::PendingAssociatedRemote<blink::mojom::IDBFactoryClient> - factory_client, - mojo::PendingAssociatedRemote<blink::mojom::IDBDatabaseCallbacks> - database_callbacks_remote, - const std::u16string& name, - int64_t version, - mojo::PendingAssociatedReceiver<blink::mojom::IDBTransaction> - transaction_receiver, - int64_t transaction_id) override; - void DeleteDatabase(mojo::PendingAssociatedRemote< - blink::mojom::IDBFactoryClient> factory_client, - const std::u16string& name, - bool force_close) override; - - // Close all connections to all databases within the bucket. If - // `will_be_deleted` is true, references to in-memory databases will be - // dropped thereby allowing their deletion (otherwise they are retained for - // the lifetime of the factory). - // - // TODO(dmurph): This eventually needs to be async, to support scopes - // multithreading. - void ForceClose(storage::BucketId bucket_id, bool will_be_deleted); - - // Called by the IndexedDBContext destructor so the factory can do cleanup. - void ContextDestroyed(); - - // For usage reporting. - int64_t GetInMemoryDBSize(const storage::BucketLocator& bucket_locator) const; - - std::vector<storage::BucketId> GetOpenBucketIdsForTesting() const; - - IndexedDBBucketContext* GetBucketContextForTesting( - const storage::BucketId& id) const; - - // Finishes filling in `info` with data relevant to idb-internals and passes - // the result back via `result`. The bucket is described by - // `info->bucket_locator`. - void FillInBucketMetadata( - storage::mojom::IdbBucketMetadataPtr info, - base::OnceCallback<void(storage::mojom::IdbBucketMetadataPtr)> result); - - void CompactBackingStoreForTesting( - const storage::BucketLocator& bucket_locator); - - private: - friend class IndexedDBFactoryTest; - FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTestWithStoragePartitioning, - BasicFactoryCreationAndTearDown); - FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, TooLongOrigin); - - IndexedDBBucketContext& GetOrCreateBucketContext( - const storage::BucketInfo& bucket, - const base::FilePath& data_directory); - - void HandleBackingStoreFailure(const storage::BucketLocator& bucket_locator); - - ////////////////////////////////////////////////////// - // Callbacks passed to bucket-sequence classes. - - // Applies the given `callback` to all bucket contexts. - void ForEachBucketContext(IndexedDBBucketContext::InstanceClosure callback); - - // Used to report fatal database errors. - void OnDatabaseError(const storage::BucketLocator& bucket_locator, - leveldb::Status s, - const std::string& message); - - void HandleBackingStoreCorruption(storage::BucketLocator bucket_locator, - const IndexedDBDatabaseError& error); - - void OnDatabaseDeleted(const storage::BucketLocator& bucket_locator); - - // Passed to IndexedDBBackingStore when blob files have been cleaned. - void BlobFilesCleaned(const storage::BucketLocator& bucket_locator); - - // Furnished to the IndexedDBActiveBlobRegistry as a callback. - void ReportOutstandingBlobs(const storage::BucketLocator& bucket_locator, - bool blobs_outstanding); - - SEQUENCE_CHECKER(sequence_checker_); - - // This will be set to null after `ContextDestroyed` is called. - raw_ptr<IndexedDBContextImpl> context_; - - IndexedDBBucketContext::InstanceClosure for_each_bucket_context_; - - // TODO(crbug.com/1474996): these bucket contexts need to be `SequenceBound`. - std::map<storage::BucketId, std::unique_ptr<IndexedDBBucketContext>> - bucket_contexts_; - - // See comment above IDBFactory overrides. - mojo::ReceiverSet<blink::mojom::IDBFactory> receivers_; - - // Weak pointers from this factory are invalidated when `context_` is - // destroyed. - base::WeakPtrFactory<IndexedDBFactory> idb_context_destruction_weak_factory_{ - this}; - base::WeakPtrFactory<IndexedDBFactory> weak_factory_{this}; -}; - -} // namespace content - -#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_FACTORY_H_
diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc deleted file mode 100644 index 7538ff6..0000000 --- a/content/browser/indexed_db/indexed_db_factory_unittest.cc +++ /dev/null
@@ -1,1034 +0,0 @@ -// Copyright 2013 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/indexed_db/indexed_db_factory.h" - -#include <stdint.h> - -#include <ctime> -#include <memory> -#include <utility> - -#include "base/auto_reset.h" -#include "base/barrier_closure.h" -#include "base/command_line.h" -#include "base/files/file_util.h" -#include "base/files/scoped_temp_dir.h" -#include "base/memory/scoped_refptr.h" -#include "base/run_loop.h" -#include "base/task/sequenced_task_runner.h" -#include "base/task/single_thread_task_runner.h" -#include "base/test/bind.h" -#include "base/test/gmock_callback_support.h" -#include "base/test/scoped_feature_list.h" -#include "base/test/task_environment.h" -#include "base/test/test_future.h" -#include "base/test/test_simple_task_runner.h" -#include "components/services/storage/indexed_db/leveldb/fake_leveldb_factory.h" -#include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h" -#include "components/services/storage/privileged/mojom/indexed_db_control.mojom-test-utils.h" -#include "components/services/storage/public/cpp/buckets/bucket_locator.h" -#include "components/services/storage/public/mojom/storage_usage_info.mojom.h" -#include "content/browser/indexed_db/indexed_db_backing_store.h" -#include "content/browser/indexed_db/indexed_db_bucket_context.h" -#include "content/browser/indexed_db/indexed_db_class_factory.h" -#include "content/browser/indexed_db/indexed_db_connection.h" -#include "content/browser/indexed_db/indexed_db_context_impl.h" -#include "content/browser/indexed_db/indexed_db_data_format_version.h" -#include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h" -#include "content/browser/indexed_db/indexed_db_transaction.h" -#include "content/browser/indexed_db/mock_indexed_db_factory_client.h" -#include "content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h" -#include "content/browser/indexed_db/mock_mojo_indexed_db_factory_client.h" -#include "mojo/public/cpp/bindings/associated_remote.h" -#include "net/base/features.h" -#include "storage/browser/test/mock_quota_manager_proxy.h" -#include "storage/browser/test/mock_special_storage_policy.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" -#include "third_party/blink/public/common/storage_key/storage_key.h" -#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h" -#include "url/gurl.h" -#include "url/origin.h" - -using blink::IndexedDBDatabaseMetadata; -using testing::_; -using url::Origin; - -namespace content { - -namespace { - -ACTION_TEMPLATE(MoveArgPointee, - HAS_1_TEMPLATE_PARAMS(int, k), - AND_1_VALUE_PARAMS(out)) { - *out = std::move(*::testing::get<k>(args)); -} - -storage::BucketInfo ToBucketInfo(const storage::BucketLocator& bucket_locator) { - storage::BucketInfo bucket_info; - bucket_info.id = bucket_locator.id; - bucket_info.storage_key = bucket_locator.storage_key; - bucket_info.name = storage::kDefaultBucketName; - return bucket_info; -} - -} // namespace - -class IndexedDBFactoryTest : public testing::Test { - public: - IndexedDBFactoryTest() = default; - - IndexedDBFactoryTest(const IndexedDBFactoryTest&) = delete; - IndexedDBFactoryTest& operator=(const IndexedDBFactoryTest&) = delete; - - void SetUp() override { - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - quota_policy_ = base::MakeRefCounted<storage::MockSpecialStoragePolicy>(); - quota_manager_ = base::MakeRefCounted<storage::MockQuotaManager>( - /*is_incognito=*/false, temp_dir_.GetPath(), - base::SingleThreadTaskRunner::GetCurrentDefault().get(), - quota_policy_.get()); - - quota_manager_proxy_ = base::MakeRefCounted<storage::MockQuotaManagerProxy>( - quota_manager_.get(), - base::SingleThreadTaskRunner::GetCurrentDefault().get()); - } - - void TearDown() override { - if (context_ && !context_->IsInMemoryContext()) { - IndexedDBFactory* factory = context_->GetIDBFactory(); - - // Loop through all open storage keys, and force close them, and request - // the deletion of the leveldb state. Once the states are no longer - // around, delete all of the databases on disk. - for (const auto& bucket_id : factory->GetOpenBucketIdsForTesting()) { - context_->ForceClose( - bucket_id, - storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN, - base::DoNothing()); - } - // All leveldb databases are closed, and they can be deleted. - for (auto bucket_locator : context_->GetAllBuckets()) { - base::test::TestFuture<bool> success; - context_->DeleteForStorageKey(bucket_locator.storage_key, - success.GetCallback()); - EXPECT_TRUE(success.Get()); - } - } - quota_manager_.reset(); - // Wait for mojo pipes to flush or there may be leaks. - task_environment_.RunUntilIdle(); - } - - IndexedDBBucketContextHandle CreateBucketHandle( - absl::optional<storage::BucketLocator> bucket_locator = absl::nullopt) { - if (!bucket_locator) { - const blink::StorageKey storage_key = - blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); - bucket_locator = storage::BucketLocator(); - bucket_locator->storage_key = storage_key; - } - IndexedDBBucketContextHandle bucket_context_handle( - factory()->GetOrCreateBucketContext( - ToBucketInfo(*bucket_locator), - context()->GetDataPath(*bucket_locator))); - bucket_context_handle->InitBackingStoreIfNeeded(/*create_if_missing=*/true); - return bucket_context_handle; - } - - void SetUpContext() { - context_ = std::make_unique<IndexedDBContextImpl>( - temp_dir_.GetPath(), quota_manager_proxy_.get(), - /*blob_storage_context=*/mojo::NullRemote(), - /*file_system_access_context=*/mojo::NullRemote(), - base::SequencedTaskRunner::GetCurrentDefault(), - base::SequencedTaskRunner::GetCurrentDefault()); - } - - void SetUpInMemoryContext() { - context_ = std::make_unique<IndexedDBContextImpl>( - base::FilePath(), quota_manager_proxy_.get(), - /*blob_storage_context=*/mojo::NullRemote(), - /*file_system_access_context=*/mojo::NullRemote(), - base::SequencedTaskRunner::GetCurrentDefault(), - base::SequencedTaskRunner::GetCurrentDefault()); - } - - void RunPostedTasks() { - base::RunLoop loop; - base::SequencedTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, loop.QuitClosure()); - loop.Run(); - } - - storage::BucketInfo GetOrCreateBucket( - const storage::BucketInitParams& params) { - base::test::TestFuture<storage::QuotaErrorOr<storage::BucketInfo>> future; - quota_manager_proxy_->UpdateOrCreateBucket( - params, base::SingleThreadTaskRunner::GetCurrentDefault(), - future.GetCallback()); - return future.Take().value(); - } - - void BindIndexedDBFactory( - mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> - checker_remote, - mojo::PendingReceiver<blink::mojom::IDBFactory> receiver, - storage::QuotaErrorOr<storage::BucketInfo> bucket_info) { - context()->BindIndexedDBImpl(std::move(checker_remote), - base::UnguessableToken(), std::move(receiver), - bucket_info); - } - - void VerifyBucketContext( - const storage::BucketId& id, - bool expected_context_exists, - std::optional<bool> expected_backing_store_exists = std::nullopt) { - IndexedDBBucketContext* context = factory()->GetBucketContextForTesting(id); - if (!expected_context_exists) { - EXPECT_FALSE(context); - EXPECT_FALSE(expected_backing_store_exists.has_value()); - } else { - ASSERT_TRUE(context); - if (expected_backing_store_exists.has_value()) { - EXPECT_EQ(*expected_backing_store_exists, !!context->backing_store()); - } - } - } - - protected: - IndexedDBContextImpl* context() const { return context_.get(); } - - IndexedDBFactory* factory() const { return context_->GetIDBFactory(); } - - storage::MockQuotaManager* quota_manager() { return quota_manager_.get(); } - - base::test::TaskEnvironment task_environment_{ - base::test::TaskEnvironment::TimeSource::MOCK_TIME}; - - base::ScopedTempDir temp_dir_; - scoped_refptr<storage::MockSpecialStoragePolicy> quota_policy_; - scoped_refptr<storage::MockQuotaManager> quota_manager_; - scoped_refptr<storage::MockQuotaManagerProxy> quota_manager_proxy_; - std::unique_ptr<IndexedDBContextImpl> context_; - std::unique_ptr<MockIndexedDBFactoryClient> mock_factory_client_; -}; - -class IndexedDBFactoryTestWithStoragePartitioning - : public IndexedDBFactoryTest, - public testing::WithParamInterface<bool> { - public: - IndexedDBFactoryTestWithStoragePartitioning() { - feature_list_.InitWithFeatureState( - net::features::kThirdPartyStoragePartitioning, - IsThirdPartyStoragePartitioningEnabled()); - } - - bool IsThirdPartyStoragePartitioningEnabled() { return GetParam(); } - - private: - base::test::ScopedFeatureList feature_list_; -}; - -INSTANTIATE_TEST_SUITE_P( - /* no prefix */, - IndexedDBFactoryTestWithStoragePartitioning, - testing::Bool()); - -TEST_P(IndexedDBFactoryTestWithStoragePartitioning, - BasicFactoryCreationAndTearDown) { - SetUpContext(); - - const blink::StorageKey storage_key_1 = - blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); - storage::BucketInfo bucket_1 = GetOrCreateBucket( - storage::BucketInitParams::ForDefaultBucket(storage_key_1)); - storage::BucketLocator bucket_locator_1 = bucket_1.ToBucketLocator(); - auto file_1 = context_->GetLevelDBPathForTesting(bucket_locator_1) - .AppendASCII("1.json"); - ASSERT_TRUE(CreateDirectory(file_1.DirName())); - ASSERT_TRUE(base::WriteFile(file_1, std::string(10, 'a'))); - - const blink::StorageKey storage_key_2 = - blink::StorageKey::CreateFromStringForTesting("http://localhost:82"); - storage::BucketInfo bucket_2 = GetOrCreateBucket( - storage::BucketInitParams::ForDefaultBucket(storage_key_2)); - storage::BucketLocator bucket_locator_2 = bucket_2.ToBucketLocator(); - auto file_2 = context_->GetLevelDBPathForTesting(bucket_locator_2) - .AppendASCII("2.json"); - ASSERT_TRUE(CreateDirectory(file_2.DirName())); - ASSERT_TRUE(base::WriteFile(file_2, std::string(100, 'a'))); - - const blink::StorageKey storage_key_3 = - blink::StorageKey::CreateFromStringForTesting("http://localhost2:82"); - storage::BucketInfo bucket_3 = GetOrCreateBucket( - storage::BucketInitParams::ForDefaultBucket(storage_key_3)); - storage::BucketLocator bucket_locator_3 = bucket_3.ToBucketLocator(); - auto file_3 = context_->GetLevelDBPathForTesting(bucket_locator_3) - .AppendASCII("3.json"); - ASSERT_TRUE(CreateDirectory(file_3.DirName())); - ASSERT_TRUE(base::WriteFile(file_3, std::string(1000, 'a'))); - - const blink::StorageKey storage_key_4 = blink::StorageKey::Create( - storage_key_1.origin(), net::SchemefulSite(storage_key_3.origin()), - blink::mojom::AncestorChainBit::kCrossSite); - storage::BucketInfo bucket_4 = GetOrCreateBucket( - storage::BucketInitParams::ForDefaultBucket(storage_key_4)); - storage::BucketLocator bucket_locator_4 = bucket_4.ToBucketLocator(); - auto file_4 = context_->GetLevelDBPathForTesting(bucket_locator_4) - .AppendASCII("4.json"); - ASSERT_TRUE(CreateDirectory(file_4.DirName())); - ASSERT_TRUE(base::WriteFile(file_4, std::string(10000, 'a'))); - - const blink::StorageKey storage_key_5 = storage_key_1; - storage::BucketInitParams params(storage_key_5, "inbox"); - storage::BucketInfo bucket_5 = GetOrCreateBucket(params); - storage::BucketLocator bucket_locator_5 = bucket_5.ToBucketLocator(); - auto file_5 = context_->GetLevelDBPathForTesting(bucket_locator_5) - .AppendASCII("5.json"); - ASSERT_TRUE(CreateDirectory(file_5.DirName())); - ASSERT_TRUE(base::WriteFile(file_5, std::string(20000, 'a'))); - EXPECT_NE(file_5.DirName(), file_1.DirName()); - - factory() - ->GetOrCreateBucketContext(bucket_1, - context()->GetDataPath(bucket_locator_1)) - .InitBackingStoreIfNeeded(true); - - factory() - ->GetOrCreateBucketContext(bucket_2, - context()->GetDataPath(bucket_locator_2)) - .InitBackingStoreIfNeeded(true); - - factory() - ->GetOrCreateBucketContext(bucket_3, - context()->GetDataPath(bucket_locator_3)) - .InitBackingStoreIfNeeded(true); - - factory() - ->GetOrCreateBucketContext(bucket_4, - context()->GetDataPath(bucket_locator_4)) - .InitBackingStoreIfNeeded(true); - - factory() - ->GetOrCreateBucketContext(bucket_5, - context()->GetDataPath(bucket_locator_5)) - .InitBackingStoreIfNeeded(true); - - int64_t bucket_size_1 = base::ComputeDirectorySize(file_1.DirName()); - int64_t bucket_size_4 = base::ComputeDirectorySize(file_4.DirName()); - int64_t bucket_size_5 = base::ComputeDirectorySize(file_5.DirName()); - - if (IsThirdPartyStoragePartitioningEnabled()) { - // If third party storage partitioning is on, additional space is taken - // by supporting files for the independent buckets. - EXPECT_NE(bucket_size_1, bucket_size_4); - } - EXPECT_NE(bucket_size_1, bucket_size_5); - - if (IsThirdPartyStoragePartitioningEnabled()) { - EXPECT_EQ(5ul, factory()->GetOpenBucketIdsForTesting().size()); - } else { - EXPECT_EQ(4ul, factory()->GetOpenBucketIdsForTesting().size()); - } -} - -TEST_F(IndexedDBFactoryTest, CloseSequenceStarts) { - SetUpContext(); - - IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); - const storage::BucketId bucket_id = - bucket_context_handle->bucket_locator().id; - bucket_context_handle.Release(); - - VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, - /*expected_backing_store_exists=*/true); - EXPECT_TRUE(factory()->GetBucketContextForTesting(bucket_id)->IsClosing()); - - factory()->ForceClose(bucket_id, false); - RunPostedTasks(); - VerifyBucketContext(bucket_id, /*expected_context_exists=*/false); -} - -TEST_F(IndexedDBFactoryTest, ImmediateClose) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - kIDBCloseImmediatelySwitch); - SetUpContext(); - - IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); - const storage::BucketId bucket_id = - bucket_context_handle->bucket_locator().id; - bucket_context_handle.Release(); - - VerifyBucketContext(bucket_id, /*expected_context_exists=*/true); - RunPostedTasks(); - VerifyBucketContext(bucket_id, /*expected_context_exists=*/false); -} - -// Similar to the above, but installs a receiver which prevents the bucket -// context from being destroyed. -TEST_F(IndexedDBFactoryTest, CloseWithReceiversActive) { - SetUpContext(); - - // Create bucket context. - IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); - const storage::BucketId bucket_id = - bucket_context_handle->bucket_locator().id; - // Connect an IDBFactory mojo client. - mojo::Remote<blink::mojom::IDBFactory> factory_remote; - mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> - checker_remote; - bucket_context_handle->AddReceiver( - std::move(checker_remote), /*client_token=*/{}, - factory_remote.BindNewPipeAndPassReceiver()); - - // The bucket context and the backing store should exist. - VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, - /*expected_backing_store_exists=*/true); - - // The last handle to the bucket context is released and the grace period - // elapses. - bucket_context_handle.Release(); - task_environment_.FastForwardBy(base::Seconds(2)); - - // This destroys the backing store, but the bucket context itself still - // exists... - VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, - /*expected_backing_store_exists=*/false); - - // ...until the last mojo client is disconnected. - factory_remote.reset(); - task_environment_.RunUntilIdle(); - - VerifyBucketContext(bucket_id, /*expected_context_exists=*/false); -} - -// Similar to the above, but reverses the order of receiver disconnection and -// handle destruction. -TEST_F(IndexedDBFactoryTest, CloseWithReceiversInactive) { - SetUpContext(); - - // Create bucket context. - IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); - const storage::BucketId bucket_id = - bucket_context_handle->bucket_locator().id; - // Connect an IDBFactory mojo client. - mojo::Remote<blink::mojom::IDBFactory> factory_remote; - mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> - checker_remote; - bucket_context_handle->AddReceiver( - std::move(checker_remote), /*client_token=*/{}, - factory_remote.BindNewPipeAndPassReceiver()); - - // The bucket context and the backing store should exist. - VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, - /*expected_backing_store_exists=*/true); - - // The last mojo client is disconnected. - factory_remote.reset(); - task_environment_.RunUntilIdle(); - - // The bucket context and the backing store should still exist. - VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, - /*expected_backing_store_exists=*/true); - - // The last handle to the bucket context is released and the grace period - // elapses. - bucket_context_handle.Release(); - task_environment_.FastForwardBy(base::Seconds(2)); - - VerifyBucketContext(bucket_id, /*expected_context_exists=*/false); -} - -TEST_F(IndexedDBFactoryTest, PreCloseTasksStart) { - SetUpContext(); - - { - // Open a connection & immediately release it to cause the closing sequence - // to start. - IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); - storage::BucketId bucket_id = bucket_context_handle->bucket_locator().id; - - mojo::Remote<blink::mojom::IDBFactory> factory_remote; - mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> - checker_remote; - BindIndexedDBFactory(std::move(checker_remote), - factory_remote.BindNewPipeAndPassReceiver(), - ToBucketInfo(bucket_context_handle->bucket_locator())); - - bucket_context_handle.Release(); - - VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, - /*expected_backing_store_exists=*/true); - EXPECT_TRUE(factory()->GetBucketContextForTesting(bucket_id)->IsClosing()); - - EXPECT_EQ( - IndexedDBBucketContext::ClosingState::kPreCloseGracePeriod, - factory()->GetBucketContextForTesting(bucket_id)->closing_stage()); - - task_environment_.FastForwardBy(base::Seconds(2)); - - // The factory should be closed, as the pre close tasks are delayed. - VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, - /*expected_backing_store_exists=*/false); - } - - // Move the clock to run the tasks in the next close sequence. - // NOTE: The constants rate-limiting sweeps and compaction are currently the - // same. This test may need to be restructured if these values diverge. - task_environment_.FastForwardBy( - IndexedDBBucketContext::kMaxEarliestGlobalSweepFromNow); - - { - // Open a connection & immediately release it to cause the closing sequence - // to start again. - IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); - storage::BucketId bucket_id = bucket_context_handle->bucket_locator().id; - bucket_context_handle.Release(); - - // Manually execute the timer so that the PreCloseTaskList task doesn't also - // run. - factory()->GetBucketContextForTesting(bucket_id)->close_timer()->FireNow(); - - // The pre-close tasks should be running now. - ASSERT_TRUE(factory()->GetBucketContextForTesting(bucket_id)); - EXPECT_EQ( - IndexedDBBucketContext::ClosingState::kRunningPreCloseTasks, - factory()->GetBucketContextForTesting(bucket_id)->closing_stage()); - ASSERT_TRUE(factory() - ->GetBucketContextForTesting(bucket_id) - ->pre_close_task_queue()); - EXPECT_TRUE(factory() - ->GetBucketContextForTesting(bucket_id) - ->pre_close_task_queue() - ->started()); - } - - { - // Stop sweep by opening a connection. - IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); - storage::BucketId bucket_id = bucket_context_handle->bucket_locator().id; - EXPECT_FALSE(bucket_context_handle->pre_close_task_queue()); - - // Move clock forward to trigger next sweep, but storage key has longer - // sweep minimum, so no tasks should execute. - task_environment_.FastForwardBy( - IndexedDBBucketContext::kMaxEarliestGlobalSweepFromNow); - - bucket_context_handle.Release(); - ASSERT_TRUE(factory()->GetBucketContextForTesting(bucket_id)); - EXPECT_EQ( - IndexedDBBucketContext::ClosingState::kPreCloseGracePeriod, - factory()->GetBucketContextForTesting(bucket_id)->closing_stage()); - - // Manually execute the timer so that the PreCloseTaskList task doesn't also - // run. - factory()->GetBucketContextForTesting(bucket_id)->close_timer()->FireNow(); - VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, - /*expected_backing_store_exists=*/true); - - RunPostedTasks(); - VerifyBucketContext(bucket_id, /*expected_context_exists=*/false); - } - - { - // Finally, move the clock forward so the storage key should allow a sweep. - task_environment_.FastForwardBy( - IndexedDBBucketContext::kMaxEarliestBucketSweepFromNow); - IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); - storage::BucketId bucket_id = bucket_context_handle->bucket_locator().id; - bucket_context_handle.Release(); - factory()->GetBucketContextForTesting(bucket_id)->close_timer()->FireNow(); - - ASSERT_TRUE(factory()->GetBucketContextForTesting(bucket_id)); - EXPECT_EQ( - IndexedDBBucketContext::ClosingState::kRunningPreCloseTasks, - factory()->GetBucketContextForTesting(bucket_id)->closing_stage()); - ASSERT_TRUE(factory() - ->GetBucketContextForTesting(bucket_id) - ->pre_close_task_queue()); - EXPECT_TRUE(factory() - ->GetBucketContextForTesting(bucket_id) - ->pre_close_task_queue() - ->started()); - } -} - -TEST_F(IndexedDBFactoryTest, TombstoneSweeperTiming) { - SetUpContext(); - - // Open a connection. - IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); - EXPECT_FALSE(bucket_context_handle->ShouldRunTombstoneSweeper()); - - // Move the clock to run the tasks in the next close sequence. - task_environment_.FastForwardBy( - IndexedDBBucketContext::kMaxEarliestGlobalSweepFromNow); - - EXPECT_TRUE(bucket_context_handle->ShouldRunTombstoneSweeper()); - - // Move clock forward to trigger next sweep, but storage key has longer - // sweep minimum, so no tasks should execute. - task_environment_.FastForwardBy( - IndexedDBBucketContext::kMaxEarliestGlobalSweepFromNow); - - EXPECT_FALSE(bucket_context_handle->ShouldRunTombstoneSweeper()); - - // Finally, move the clock forward so the storage key should allow a sweep. - task_environment_.FastForwardBy( - IndexedDBBucketContext::kMaxEarliestBucketSweepFromNow); - - EXPECT_TRUE(bucket_context_handle->ShouldRunTombstoneSweeper()); -} - -TEST_F(IndexedDBFactoryTest, CompactionTaskTiming) { - SetUpContext(); - - // Open a connection. - IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); - bucket_context_handle->InitBackingStoreIfNeeded(/*create_if_missing=*/true); - EXPECT_FALSE(bucket_context_handle->ShouldRunCompaction()); - - // Move the clock to run the tasks in the next close sequence. - task_environment_.FastForwardBy( - IndexedDBBucketContext::kMaxEarliestGlobalCompactionFromNow); - - EXPECT_TRUE(bucket_context_handle->ShouldRunCompaction()); - - // Move clock forward to trigger next compaction, but storage key has longer - // compaction minimum, so no tasks should execute. - task_environment_.FastForwardBy( - IndexedDBBucketContext::kMaxEarliestGlobalCompactionFromNow); - - EXPECT_FALSE(bucket_context_handle->ShouldRunCompaction()); - - // Finally, move the clock forward so the storage key should allow a - // compaction. - task_environment_.FastForwardBy( - IndexedDBBucketContext::kMaxEarliestBucketCompactionFromNow); - - EXPECT_TRUE(bucket_context_handle->ShouldRunCompaction()); -} - -TEST_F(IndexedDBFactoryTest, InMemoryFactoriesStay) { - SetUpInMemoryContext(); - ASSERT_TRUE(context()->IsInMemoryContext()); - - IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); - storage::BucketLocator bucket_locator = - bucket_context_handle->bucket_locator(); - - EXPECT_TRUE(bucket_context_handle->backing_store()->in_memory()); - bucket_context_handle.Release(); - - EXPECT_TRUE(factory()->GetBucketContextForTesting(bucket_locator.id)); - EXPECT_FALSE( - factory()->GetBucketContextForTesting(bucket_locator.id)->IsClosing()); - - factory()->ForceClose(bucket_locator.id, false); - VerifyBucketContext(bucket_locator.id, /*expected_context_exists=*/true, - /*expected_backing_store_exists=*/true); - - factory()->ForceClose(bucket_locator.id, true); - VerifyBucketContext(bucket_locator.id, /*expected_context_exists=*/false); -} - -TEST_F(IndexedDBFactoryTest, TooLongOrigin) { - SetUpContext(); - - base::FilePath temp_dir = - context()->GetFirstPartyDataPathForTesting().DirName(); - int limit = base::GetMaximumPathComponentLength(temp_dir); - EXPECT_GT(limit, 0); - - std::string origin(limit + 1, 'x'); - const blink::StorageKey too_long_storage_key = - blink::StorageKey::CreateFromStringForTesting("http://" + origin + - ":81/"); - storage::BucketInfo bucket_info = GetOrCreateBucket( - storage::BucketInitParams::ForDefaultBucket(too_long_storage_key)); - storage::BucketLocator bucket_locator = bucket_info.ToBucketLocator(); - - IndexedDBBucketContextHandle bucket_context_handle( - factory()->GetOrCreateBucketContext( - ToBucketInfo(bucket_locator), - context()->GetDataPath(bucket_locator))); - leveldb::Status s; - std::tie(s, std::ignore, std::ignore) = - bucket_context_handle->InitBackingStoreIfNeeded( - /*create_if_missing=*/true); - - EXPECT_TRUE(s.IsIOError()); -} - -TEST_F(IndexedDBFactoryTest, FactoryForceClose) { - SetUpContext(); - - IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); - storage::BucketLocator bucket_locator = - bucket_context_handle->bucket_locator(); - - bucket_context_handle->ForceClose(/*doom=*/false); - bucket_context_handle.Release(); - - VerifyBucketContext(bucket_locator.id, /*expected_context_exists=*/true, - /*expected_backing_store_exists=*/true); - RunPostedTasks(); - VerifyBucketContext(bucket_locator.id, /*expected_context_exists=*/false); -} - -// Tests that the backing store is closed when the connection is closed during -// upgrade. -TEST_F(IndexedDBFactoryTest, ConnectionCloseDuringUpgrade) { - SetUpContext(); - - const blink::StorageKey storage_key = - blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); - auto bucket_locator = storage::BucketLocator(); - bucket_locator.storage_key = storage_key; - - // Bind the IDBFactory. - mojo::Remote<blink::mojom::IDBFactory> factory_remote; - mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> - checker_remote; - BindIndexedDBFactory(std::move(checker_remote), - factory_remote.BindNewPipeAndPassReceiver(), - ToBucketInfo(bucket_locator)); - - // Now create a database and thus the backing store. - MockMojoIndexedDBFactoryClient client; - MockMojoIndexedDBDatabaseCallbacks database_callbacks; - base::RunLoop run_loop; - mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database; - EXPECT_CALL(client, MockedUpgradeNeeded) - .WillOnce( - testing::DoAll(MoveArgPointee<0>(&pending_database), - ::base::test::RunClosure(run_loop.QuitClosure()))); - mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; - factory_remote->Open(client.CreateInterfacePtrAndBind(), - database_callbacks.CreateInterfacePtrAndBind(), u"db", - /*version=*/1, - transaction_remote.BindNewEndpointAndPassReceiver(), - /*transaction_id=*/1); - run_loop.Run(); - - EXPECT_TRUE(factory()->GetBucketContextForTesting(bucket_locator.id)); - EXPECT_FALSE( - factory()->GetBucketContextForTesting(bucket_locator.id)->IsClosing()); - - // Drop the connection. - pending_database.reset(); - factory_remote.FlushForTesting(); - EXPECT_TRUE( - factory()->GetBucketContextForTesting(bucket_locator.id)->IsClosing()); -} - -TEST_F(IndexedDBFactoryTest, DeleteDatabase) { - SetUpContext(); - const blink::StorageKey storage_key = - blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); - auto bucket_locator = storage::BucketLocator(); - bucket_locator.storage_key = storage_key; - - // Bind the IDBFactory. - mojo::Remote<blink::mojom::IDBFactory> factory_remote; - mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> - checker_remote; - BindIndexedDBFactory(std::move(checker_remote), - factory_remote.BindNewPipeAndPassReceiver(), - ToBucketInfo(bucket_locator)); - - // Don't create a backing store if one doesn't exist. - { - // Delete db. - MockMojoIndexedDBFactoryClient client; - MockMojoIndexedDBDatabaseCallbacks database_callbacks; - base::RunLoop run_loop; - EXPECT_CALL(client, DeleteSuccess) - .WillOnce( - testing::DoAll(::base::test::RunClosure(run_loop.QuitClosure()))); - mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; - factory_remote->DeleteDatabase(client.CreateInterfacePtrAndBind(), u"db", - /*force_close=*/false); - run_loop.Run(); - - // Backing store shouldn't exist. - EXPECT_FALSE(factory() - ->GetBucketContextForTesting(bucket_locator.id) - ->backing_store()); - } - - // Now create a database and thus the backing store. - { - MockMojoIndexedDBFactoryClient client; - MockMojoIndexedDBDatabaseCallbacks database_callbacks; - base::RunLoop run_loop; - EXPECT_CALL(client, MockedOpenSuccess) - .WillOnce(::base::test::RunClosure(run_loop.QuitClosure())); - mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; - factory_remote->Open(client.CreateInterfacePtrAndBind(), - database_callbacks.CreateInterfacePtrAndBind(), u"db", - /*version=*/0, - transaction_remote.BindNewEndpointAndPassReceiver(), - /*transaction_id=*/1); - run_loop.Run(); - } - - // Delete the database now that the backing store actually exists. - { - MockMojoIndexedDBFactoryClient client; - MockMojoIndexedDBDatabaseCallbacks database_callbacks; - base::RunLoop run_loop; - EXPECT_CALL(client, DeleteSuccess) - .WillOnce( - testing::DoAll(::base::test::RunClosure(run_loop.QuitClosure()))); - mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; - factory_remote->DeleteDatabase(client.CreateInterfacePtrAndBind(), u"db", - /*force_close=*/false); - run_loop.Run(); - - // Since there are no more references the factory should be closing. - ASSERT_TRUE(factory()->GetBucketContextForTesting(bucket_locator.id)); - EXPECT_TRUE( - factory()->GetBucketContextForTesting(bucket_locator.id)->IsClosing()); - } -} - -TEST_F(IndexedDBFactoryTest, GetDatabaseNames_NoFactory) { - SetUpContext(); - - const blink::StorageKey storage_key = - blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); - auto bucket_locator = storage::BucketLocator(); - bucket_locator.storage_key = storage_key; - - // Bind the IDBFactory. - mojo::Remote<blink::mojom::IDBFactory> factory_remote; - mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> - checker_remote; - BindIndexedDBFactory(std::move(checker_remote), - factory_remote.BindNewPipeAndPassReceiver(), - ToBucketInfo(bucket_locator)); - - // Don't create a backing store if one doesn't exist. - { - base::test::TestFuture<std::vector<blink::mojom::IDBNameAndVersionPtr>, - blink::mojom::IDBErrorPtr> - info_future; - factory_remote->GetDatabaseInfo(info_future.GetCallback()); - ASSERT_TRUE(info_future.Wait()); - EXPECT_FALSE(factory() - ->GetBucketContextForTesting(bucket_locator.id) - ->backing_store()); - } - - // Now create a database and thus the backing store. - MockMojoIndexedDBFactoryClient client; - MockMojoIndexedDBDatabaseCallbacks database_callbacks; - base::RunLoop run_loop; - // It's necessary to hang onto the database connection or the connection - // will shut itself down and the backing store will close on its own. - mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database; - EXPECT_CALL(client, MockedOpenSuccess) - .WillOnce( - testing::DoAll(MoveArgPointee<0>(&pending_database), - ::base::test::RunClosure(run_loop.QuitClosure()))); - mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; - factory_remote->Open(client.CreateInterfacePtrAndBind(), - database_callbacks.CreateInterfacePtrAndBind(), u"db", - /*version=*/0, - transaction_remote.BindNewEndpointAndPassReceiver(), - /*transaction_id=*/1); - run_loop.Run(); - // GetDatabaseInfo didn't create the factory, so it shouldn't close it. - { - base::test::TestFuture<std::vector<blink::mojom::IDBNameAndVersionPtr>, - blink::mojom::IDBErrorPtr> - info_future; - factory_remote->GetDatabaseInfo(info_future.GetCallback()); - ASSERT_TRUE(info_future.Wait()); - - EXPECT_TRUE(factory()->GetBucketContextForTesting(bucket_locator.id)); - EXPECT_FALSE( - factory()->GetBucketContextForTesting(bucket_locator.id)->IsClosing()); - } -} - -TEST_F(IndexedDBFactoryTest, QuotaErrorOnDiskFull) { - SetUpContext(); - leveldb_env::SetDBFactoryForTesting(base::BindRepeating( - [](const leveldb_env::Options& options, const std::string& name, - std::unique_ptr<leveldb::DB>* dbptr) { - return leveldb_env::MakeIOError("foobar", "disk full", - leveldb_env::MethodID::kCreateDir, - base::File::FILE_ERROR_NO_SPACE); - })); - - // Bind the IDBFactory. - const blink::StorageKey storage_key = - blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); - auto bucket_locator = storage::BucketLocator(); - bucket_locator.storage_key = storage_key; - mojo::Remote<blink::mojom::IDBFactory> factory_remote; - mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> - checker_remote; - BindIndexedDBFactory(std::move(checker_remote), - factory_remote.BindNewPipeAndPassReceiver(), - ToBucketInfo(bucket_locator)); - - // Expect an error when opening. - MockMojoIndexedDBFactoryClient client; - MockMojoIndexedDBDatabaseCallbacks database_callbacks; - base::RunLoop run_loop; - EXPECT_CALL(client, Error) - .WillOnce( - testing::DoAll(::base::test::RunClosure(run_loop.QuitClosure()))); - mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; - factory_remote->Open(client.CreateInterfacePtrAndBind(), - database_callbacks.CreateInterfacePtrAndBind(), u"db", - /*version=*/1, - transaction_remote.BindNewEndpointAndPassReceiver(), - /*transaction_id=*/1); - run_loop.Run(); - - // A disk full error results in an error reported to the quota system. - ASSERT_EQ(1U, quota_manager()->write_error_tracker().size()); - EXPECT_EQ(storage_key, quota_manager()->write_error_tracker().begin()->first); - EXPECT_EQ(1, quota_manager()->write_error_tracker().begin()->second); - - leveldb_env::SetDBFactoryForTesting({}); -} - -TEST_F(IndexedDBFactoryTest, DatabaseFailedOpen) { - SetUpContext(); - const blink::StorageKey storage_key = - blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); - auto bucket_locator = storage::BucketLocator(); - bucket_locator.storage_key = storage_key; - const std::u16string db_name(u"db"); - - // Bind the IDBFactory. - mojo::Remote<blink::mojom::IDBFactory> factory_remote; - mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> - checker_remote; - BindIndexedDBFactory(std::move(checker_remote), - factory_remote.BindNewPipeAndPassReceiver(), - ToBucketInfo(bucket_locator)); - - // Open at version 2. - { - const int64_t db_version = 2; - MockMojoIndexedDBFactoryClient client; - MockMojoIndexedDBDatabaseCallbacks database_callbacks; - base::RunLoop run_loop; - EXPECT_CALL(client, MockedUpgradeNeeded) - .WillOnce( - testing::DoAll(::base::test::RunClosure(run_loop.QuitClosure()))); - mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; - factory_remote->Open(client.CreateInterfacePtrAndBind(), - database_callbacks.CreateInterfacePtrAndBind(), - db_name, db_version, - transaction_remote.BindNewEndpointAndPassReceiver(), - /*transaction_id=*/1); - run_loop.Run(); - } - - // Open at version < 2, which will fail. - { - const int64_t db_version = 1; - base::RunLoop run_loop; - MockMojoIndexedDBFactoryClient client; - MockMojoIndexedDBDatabaseCallbacks database_callbacks; - EXPECT_CALL(client, Error) - .WillOnce(::base::test::RunClosure(run_loop.QuitClosure())); - mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; - factory_remote->Open(client.CreateInterfacePtrAndBind(), - database_callbacks.CreateInterfacePtrAndBind(), - db_name, db_version, - transaction_remote.BindNewEndpointAndPassReceiver(), - /*transaction_id=*/2); - run_loop.Run(); - IndexedDBBucketContext* bucket_context = - factory()->GetBucketContextForTesting(bucket_locator.id); - ASSERT_TRUE(bucket_context); - EXPECT_FALSE( - base::Contains(bucket_context->GetDatabasesForTesting(), db_name)); - } -} - -// Test for `IndexedDBDataFormatVersion`. -TEST_F(IndexedDBFactoryTest, DataLoss) { - SetUpContext(); - const blink::StorageKey storage_key = - blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); - auto bucket_locator = storage::BucketLocator(); - bucket_locator.storage_key = storage_key; - const std::u16string db_name(u"test_db"); - - // Bind the IDBFactory. - mojo::Remote<blink::mojom::IDBFactory> factory_remote; - mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> - checker_remote; - BindIndexedDBFactory(std::move(checker_remote), - factory_remote.BindNewPipeAndPassReceiver(), - ToBucketInfo(bucket_locator)); - - // Set a data format version and create a new database. No data loss. - { - base::AutoReset<IndexedDBDataFormatVersion> override_version( - &IndexedDBDataFormatVersion::GetMutableCurrentForTesting(), - IndexedDBDataFormatVersion(3, 4)); - MockMojoIndexedDBFactoryClient client; - MockMojoIndexedDBDatabaseCallbacks database_callbacks; - base::RunLoop run_loop; - EXPECT_CALL(client, MockedUpgradeNeeded( - _, _, blink::mojom::IDBDataLoss::None, _, _)) - .WillOnce( - testing::DoAll(::base::test::RunClosure(run_loop.QuitClosure()))); - mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; - factory_remote->Open(client.CreateInterfacePtrAndBind(), - database_callbacks.CreateInterfacePtrAndBind(), - db_name, /*version=*/1, - transaction_remote.BindNewEndpointAndPassReceiver(), - /*transaction_id=*/1); - run_loop.Run(); - - // This step is necessary to make sure the backing store is closed so that - // the second `Open` will initialize it with the new (older) data format - // version. Without this step, the same `IndexedDBBackingStore` is reused - // because it's kept around for 2 seconds after the last connection is - // dropped. - base::RunLoop run_loop2; - context_->ForceClose( - bucket_locator.id, - storage::mojom::ForceCloseReason::FORCE_CLOSE_BACKING_STORE_FAILURE, - run_loop2.QuitClosure()); - run_loop2.Run(); - } - - // Set an older data format version and try to reopen said database. Expect - // total data loss. - { - base::AutoReset<IndexedDBDataFormatVersion> override_version( - &IndexedDBDataFormatVersion::GetMutableCurrentForTesting(), - IndexedDBDataFormatVersion(3, 3)); - base::RunLoop run_loop; - MockMojoIndexedDBFactoryClient client; - MockMojoIndexedDBDatabaseCallbacks database_callbacks; - EXPECT_CALL(client, MockedUpgradeNeeded( - _, _, blink::mojom::IDBDataLoss::Total, _, _)) - .WillOnce( - testing::DoAll(::base::test::RunClosure(run_loop.QuitClosure()))); - mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; - factory_remote->Open(client.CreateInterfacePtrAndBind(), - database_callbacks.CreateInterfacePtrAndBind(), - db_name, /*version=*/1, - transaction_remote.BindNewEndpointAndPassReceiver(), - /*transaction_id=*/2); - run_loop.Run(); - } -} - -} // namespace content
diff --git a/content/browser/indexed_db/indexed_db_transaction.cc b/content/browser/indexed_db/indexed_db_transaction.cc index f5c9adf1..1e434323 100644 --- a/content/browser/indexed_db/indexed_db_transaction.cc +++ b/content/browser/indexed_db/indexed_db_transaction.cc
@@ -546,8 +546,9 @@ base::ASCIIToUTF16(base::StringPrintf( "Failed to write blobs (%s)", WriteBlobToFileResultToString(error).c_str())))); - if (!status.ok()) - bucket_context_->delegate().on_fatal_error.Run(status, {}); + if (!status.ok()) { + bucket_context_->OnDatabaseError(status, {}); + } // The result is ignored. return leveldb::Status::OK(); } @@ -712,7 +713,7 @@ mode() == blink::mojom::IDBTransactionMode::VersionChange || backing_store_transaction_->durability() == blink::mojom::IDBTransactionDurability::Strict; - bucket_context_->delegate().on_writing_transaction_complete.Run(did_sync); + bucket_context_->delegate().on_files_written.Run(did_sync); } if (database_) { @@ -822,8 +823,9 @@ leveldb::Status result = Abort( IndexedDBDatabaseError(blink::mojom::IDBException::kTimeoutError, u"Transaction timed out due to inactivity.")); - if (!result.ok()) - bucket_context_->delegate().on_fatal_error.Run(result, {}); + if (!result.ok()) { + bucket_context_->OnDatabaseError(result, {}); + } } void IndexedDBTransaction::CloseOpenCursors() {
diff --git a/content/browser/indexed_db/indexed_db_transaction_unittest.cc b/content/browser/indexed_db/indexed_db_transaction_unittest.cc index a67e514..1ffd6053 100644 --- a/content/browser/indexed_db/indexed_db_transaction_unittest.cc +++ b/content/browser/indexed_db/indexed_db_transaction_unittest.cc
@@ -71,8 +71,6 @@ /*special_storage_policy=*/nullptr); IndexedDBBucketContext::Delegate delegate; - delegate.on_fatal_error = base::BindRepeating( - &IndexedDBTransactionTest::OnFatalError, base::Unretained(this)); delegate.on_ready_for_destruction = base::BindRepeating(&IndexedDBTransactionTest::OnDbReadyForDestruction, base::Unretained(this)); @@ -92,10 +90,6 @@ void TearDown() override { db_ = nullptr; } - void OnFatalError(leveldb::Status s, const std::string& /*error_message*/) { - error_called_ = true; - } - void OnDbReadyForDestruction() { bucket_context_.reset(); } void RunPostedTasks() { base::RunLoop().RunUntilIdle(); } @@ -133,8 +127,6 @@ std::unique_ptr<IndexedDBBucketContext> bucket_context_; raw_ptr<IndexedDBDatabase> db_; scoped_refptr<storage::MockQuotaManager> quota_manager_; - - bool error_called_ = false; }; class IndexedDBTransactionTestMode @@ -358,6 +350,7 @@ EXPECT_EQ(0, transaction->diagnostics().tasks_completed); db_->RegisterAndScheduleTransaction(transaction); + db_ = nullptr; EXPECT_FALSE(transaction->HasPendingTasks()); EXPECT_TRUE(transaction->IsTaskQueueEmpty()); @@ -385,15 +378,14 @@ EXPECT_TRUE(transaction->IsTaskQueueEmpty()); EXPECT_TRUE(transaction->task_queue_.empty()); EXPECT_TRUE(transaction->preemptive_task_queue_.empty()); - EXPECT_EQ(IndexedDBTransaction::STARTED, transaction->state()); + /// Transaction aborted due to the error. + EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state()); + transaction->SetCommitFlag(); EXPECT_EQ(1, transaction->diagnostics().tasks_scheduled); EXPECT_EQ(1, transaction->diagnostics().tasks_completed); - EXPECT_TRUE(error_called_); - - transaction->SetCommitFlag(); - RunPostedTasks(); - EXPECT_EQ(0UL, connection->transactions().size()); + // An error was reported which deletes the bucket context. + EXPECT_FALSE(bucket_context_); } TEST_F(IndexedDBTransactionTest, SchedulePreemptiveTask) { @@ -414,6 +406,7 @@ EXPECT_EQ(0, transaction->diagnostics().tasks_completed); db_->RegisterAndScheduleTransaction(transaction); + db_ = nullptr; EXPECT_FALSE(transaction->HasPendingTasks()); EXPECT_TRUE(transaction->IsTaskQueueEmpty()); @@ -445,7 +438,7 @@ transaction->DidCompletePreemptiveEvent(); transaction->SetCommitFlag(); RunPostedTasks(); - EXPECT_TRUE(error_called_); + EXPECT_TRUE(bucket_context_->force_close_called_for_testing()); } TEST_P(IndexedDBTransactionTestMode, AbortTasks) { @@ -457,6 +450,7 @@ mojo::NullAssociatedReceiver(), id, scope, GetParam(), new FakeTransaction(commit_failure)); db_->RegisterAndScheduleTransaction(transaction); + db_ = nullptr; AbortObserver observer; transaction->ScheduleTask( @@ -471,7 +465,8 @@ transaction->SetCommitFlag(); RunPostedTasks(); EXPECT_TRUE(observer.abort_task_called()); - EXPECT_TRUE(error_called_); + // An error was reported which deletes the databases. + EXPECT_TRUE(bucket_context_->GetDatabasesForTesting().empty()); } TEST_P(IndexedDBTransactionTestMode, AbortPreemptive) {
diff --git a/content/browser/indexed_db/indexed_db_unittest.cc b/content/browser/indexed_db/indexed_db_unittest.cc index e05a48f..f09c548 100644 --- a/content/browser/indexed_db/indexed_db_unittest.cc +++ b/content/browser/indexed_db/indexed_db_unittest.cc
@@ -27,8 +27,9 @@ #include "content/browser/indexed_db/indexed_db_class_factory.h" #include "content/browser/indexed_db/indexed_db_connection.h" #include "content/browser/indexed_db/indexed_db_context_impl.h" -#include "content/browser/indexed_db/indexed_db_factory.h" +#include "content/browser/indexed_db/indexed_db_data_format_version.h" #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" +#include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h" #include "content/browser/indexed_db/mock_indexed_db_factory_client.h" #include "content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h" #include "content/browser/indexed_db/mock_mojo_indexed_db_factory_client.h" @@ -45,6 +46,8 @@ #include "third_party/leveldatabase/src/include/leveldb/env.h" using blink::IndexedDBDatabaseMetadata; +using testing::_; +using url::Origin; namespace content { namespace { @@ -93,6 +96,14 @@ env, std::unique_ptr<leveldb::FileLock>(lock)); } +storage::BucketInfo ToBucketInfo(const storage::BucketLocator& bucket_locator) { + storage::BucketInfo bucket_info; + bucket_info.id = bucket_locator.id; + bucket_info.storage_key = bucket_locator.storage_key; + bucket_info.name = storage::kDefaultBucketName; + return bucket_info; +} + } // namespace class IndexedDBTest @@ -232,6 +243,15 @@ return bucket; } + void SetUpInMemoryContext() { + context_ = std::make_unique<IndexedDBContextImpl>( + base::FilePath(), quota_manager_proxy_.get(), + /*blob_storage_context=*/mojo::NullRemote(), + /*file_system_access_context=*/mojo::NullRemote(), + base::SequencedTaskRunner::GetCurrentDefault(), + base::SequencedTaskRunner::GetCurrentDefault()); + } + void RunPostedTasks() { base::RunLoop loop; context_->IDBTaskRunner()->PostTask(FROM_HERE, loop.QuitClosure()); @@ -240,20 +260,8 @@ void TearDown() override { if (context_ && !context_->IsInMemoryContext()) { - IndexedDBFactory* factory = context_->GetIDBFactory(); - - // Loop through all open buckets, and force close them, and request - // the deletion of the leveldb state. Once the states are no longer - // around, delete all of the databases on disk. - for (const auto& bucket_id : factory->GetOpenBucketIdsForTesting()) { - context_->ForceClose( - bucket_id, - storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN, - base::DoNothing()); - } - // All leveldb databases are closed, and they can be deleted. for (auto bucket_locator : context_->GetAllBuckets()) { - EXPECT_TRUE(DeleteForStorageKeySync(bucket_locator.storage_key)); + context_->DeleteBucketData(bucket_locator, base::DoNothing()); } } @@ -347,11 +355,59 @@ run_loop2.Run(); } + IndexedDBBucketContext& GetOrCreateBucketContext( + const storage::BucketInfo& bucket, + const base::FilePath& data_directory) { + return context_->GetOrCreateBucketContext(bucket, data_directory); + } + + storage::BucketInfo GetOrCreateBucket( + const storage::BucketInitParams& params) { + base::test::TestFuture<storage::QuotaErrorOr<storage::BucketInfo>> future; + quota_manager_proxy_->UpdateOrCreateBucket( + params, base::SingleThreadTaskRunner::GetCurrentDefault(), + future.GetCallback()); + return future.Take().value(); + } + + IndexedDBBucketContextHandle CreateBucketHandle( + absl::optional<storage::BucketLocator> bucket_locator = absl::nullopt) { + if (!bucket_locator) { + const blink::StorageKey storage_key = + blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); + bucket_locator = storage::BucketLocator(); + bucket_locator->storage_key = storage_key; + } + IndexedDBBucketContextHandle bucket_context_handle( + context_->GetOrCreateBucketContext( + ToBucketInfo(*bucket_locator), + context()->GetDataPath(*bucket_locator))); + bucket_context_handle->InitBackingStoreIfNeeded(/*create_if_missing=*/true); + return bucket_context_handle; + } + + void VerifyBucketContext( + const storage::BucketId& id, + bool expected_context_exists, + std::optional<bool> expected_backing_store_exists = std::nullopt) { + IndexedDBBucketContext* context = context_->GetBucketContextForTesting(id); + if (!expected_context_exists) { + EXPECT_FALSE(context); + EXPECT_FALSE(expected_backing_store_exists.has_value()); + } else { + ASSERT_TRUE(context); + if (expected_backing_store_exists.has_value()) { + EXPECT_EQ(*expected_backing_store_exists, !!context->backing_store()); + } + } + } + protected: IndexedDBContextImpl* context() const { return context_.get(); } base::test::ScopedFeatureList scoped_feature_list_; - base::test::TaskEnvironment task_environment_; + base::test::TaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; base::ScopedTempDir temp_dir_; scoped_refptr<storage::MockSpecialStoragePolicy> special_storage_policy_; scoped_refptr<storage::MockQuotaManager> quota_manager_; @@ -530,14 +586,13 @@ storage::BucketInfo bucket_info; VerifyForcedClosedCalled( base::BindOnce( - [](IndexedDBFactory* factory, storage::BucketInfo* bucket_info) { - factory->GetBucketContextForTesting(bucket_info->id) - ->delegate() - .on_fatal_error.Run( + [](IndexedDBContextImpl* context, storage::BucketInfo* bucket_info) { + context->GetBucketContextForTesting(bucket_info->id) + ->OnDatabaseError( leveldb::Status::NotSupported("operation not supported"), {}); }, - context()->GetIDBFactory(), &bucket_info), + context(), &bucket_info), &bucket_info); } @@ -562,19 +617,6 @@ EXPECT_TRUE(base::DirectoryExists(test_path)); } -// Verifies that the IDB connection is force closed when the context is -// destroyed. -TEST_P(IndexedDBTestFirstOrThirdParty, - ForceCloseOpenDatabasesOnContextDestroyed) { - storage::BucketInfo bucket_info; - VerifyForcedClosedCalled( - base::BindOnce(&IndexedDBFactory::ContextDestroyed, - base::Unretained(context()->GetIDBFactory())), - &bucket_info); - EXPECT_FALSE( - context()->GetIDBFactory()->GetBucketContextForTesting(bucket_info.id)); -} - TEST_P(IndexedDBTestFirstOrThirdParty, DeleteFailsIfDirectoryLocked) { const blink::StorageKey kTestStorageKey = GetTestStorageKey(); storage::BucketInfo bucket_info = InitBucket(kTestStorageKey); @@ -618,4 +660,753 @@ } } +TEST_P(IndexedDBTest, BasicFactoryCreationAndTearDown) { + const blink::StorageKey storage_key_1 = + blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); + storage::BucketInfo bucket_1 = GetOrCreateBucket( + storage::BucketInitParams::ForDefaultBucket(storage_key_1)); + storage::BucketLocator bucket_locator_1 = bucket_1.ToBucketLocator(); + auto file_1 = context_->GetLevelDBPathForTesting(bucket_locator_1) + .AppendASCII("1.json"); + ASSERT_TRUE(CreateDirectory(file_1.DirName())); + ASSERT_TRUE(base::WriteFile(file_1, std::string(10, 'a'))); + + const blink::StorageKey storage_key_2 = + blink::StorageKey::CreateFromStringForTesting("http://localhost:82"); + storage::BucketInfo bucket_2 = GetOrCreateBucket( + storage::BucketInitParams::ForDefaultBucket(storage_key_2)); + storage::BucketLocator bucket_locator_2 = bucket_2.ToBucketLocator(); + auto file_2 = context_->GetLevelDBPathForTesting(bucket_locator_2) + .AppendASCII("2.json"); + ASSERT_TRUE(CreateDirectory(file_2.DirName())); + ASSERT_TRUE(base::WriteFile(file_2, std::string(100, 'a'))); + + const blink::StorageKey storage_key_3 = + blink::StorageKey::CreateFromStringForTesting("http://localhost2:82"); + storage::BucketInfo bucket_3 = GetOrCreateBucket( + storage::BucketInitParams::ForDefaultBucket(storage_key_3)); + storage::BucketLocator bucket_locator_3 = bucket_3.ToBucketLocator(); + auto file_3 = context_->GetLevelDBPathForTesting(bucket_locator_3) + .AppendASCII("3.json"); + ASSERT_TRUE(CreateDirectory(file_3.DirName())); + ASSERT_TRUE(base::WriteFile(file_3, std::string(1000, 'a'))); + + const blink::StorageKey storage_key_4 = blink::StorageKey::Create( + storage_key_1.origin(), net::SchemefulSite(storage_key_3.origin()), + blink::mojom::AncestorChainBit::kCrossSite); + storage::BucketInfo bucket_4 = GetOrCreateBucket( + storage::BucketInitParams::ForDefaultBucket(storage_key_4)); + storage::BucketLocator bucket_locator_4 = bucket_4.ToBucketLocator(); + auto file_4 = context_->GetLevelDBPathForTesting(bucket_locator_4) + .AppendASCII("4.json"); + ASSERT_TRUE(CreateDirectory(file_4.DirName())); + ASSERT_TRUE(base::WriteFile(file_4, std::string(10000, 'a'))); + + const blink::StorageKey storage_key_5 = storage_key_1; + storage::BucketInitParams params(storage_key_5, "inbox"); + storage::BucketInfo bucket_5 = GetOrCreateBucket(params); + storage::BucketLocator bucket_locator_5 = bucket_5.ToBucketLocator(); + auto file_5 = context_->GetLevelDBPathForTesting(bucket_locator_5) + .AppendASCII("5.json"); + ASSERT_TRUE(CreateDirectory(file_5.DirName())); + ASSERT_TRUE(base::WriteFile(file_5, std::string(20000, 'a'))); + EXPECT_NE(file_5.DirName(), file_1.DirName()); + + GetOrCreateBucketContext(bucket_1, context()->GetDataPath(bucket_locator_1)) + .InitBackingStoreIfNeeded(true); + + GetOrCreateBucketContext(bucket_2, context()->GetDataPath(bucket_locator_2)) + .InitBackingStoreIfNeeded(true); + + GetOrCreateBucketContext(bucket_3, context()->GetDataPath(bucket_locator_3)) + .InitBackingStoreIfNeeded(true); + + GetOrCreateBucketContext(bucket_4, context()->GetDataPath(bucket_locator_4)) + .InitBackingStoreIfNeeded(true); + + GetOrCreateBucketContext(bucket_5, context()->GetDataPath(bucket_locator_5)) + .InitBackingStoreIfNeeded(true); + + int64_t bucket_size_1 = base::ComputeDirectorySize(file_1.DirName()); + int64_t bucket_size_4 = base::ComputeDirectorySize(file_4.DirName()); + int64_t bucket_size_5 = base::ComputeDirectorySize(file_5.DirName()); + + if (IsThirdPartyStoragePartitioningEnabled()) { + // If third party storage partitioning is on, additional space is taken + // by supporting files for the independent buckets. + EXPECT_NE(bucket_size_1, bucket_size_4); + } + EXPECT_NE(bucket_size_1, bucket_size_5); + + if (IsThirdPartyStoragePartitioningEnabled()) { + EXPECT_EQ(5ul, context_->GetOpenBucketIdsForTesting().size()); + } else { + EXPECT_EQ(4ul, context_->GetOpenBucketIdsForTesting().size()); + } +} + +TEST_P(IndexedDBTest, CloseSequenceStarts) { + IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); + const storage::BucketId bucket_id = + bucket_context_handle->bucket_locator().id; + bucket_context_handle.Release(); + + VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, + /*expected_backing_store_exists=*/true); + EXPECT_TRUE(context_->GetBucketContextForTesting(bucket_id)->IsClosing()); + + context_->ForceClose(bucket_id, {}, base::DoNothing()); + RunPostedTasks(); + VerifyBucketContext(bucket_id, /*expected_context_exists=*/false); +} + +TEST_P(IndexedDBTest, ImmediateClose) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + kIDBCloseImmediatelySwitch); + IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); + const storage::BucketId bucket_id = + bucket_context_handle->bucket_locator().id; + bucket_context_handle.Release(); + + VerifyBucketContext(bucket_id, /*expected_context_exists=*/true); + RunPostedTasks(); + VerifyBucketContext(bucket_id, /*expected_context_exists=*/false); +} + +// Similar to the above, but installs a receiver which prevents the bucket +// context from being destroyed. +TEST_P(IndexedDBTest, CloseWithReceiversActive) { + // Create bucket context. + IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); + const storage::BucketId bucket_id = + bucket_context_handle->bucket_locator().id; + // Connect an IDBFactory mojo client. + mojo::Remote<blink::mojom::IDBFactory> factory_remote; + mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> + checker_remote; + bucket_context_handle->AddReceiver( + std::move(checker_remote), /*client_token=*/{}, + factory_remote.BindNewPipeAndPassReceiver()); + + // The bucket context and the backing store should exist. + VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, + /*expected_backing_store_exists=*/true); + + // The last handle to the bucket context is released and the grace period + // elapses. + bucket_context_handle.Release(); + task_environment_.FastForwardBy(base::Seconds(2)); + + // This destroys the backing store, but the bucket context itself still + // exists... + VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, + /*expected_backing_store_exists=*/false); + + // ...until the last mojo client is disconnected. + factory_remote.reset(); + task_environment_.RunUntilIdle(); + + VerifyBucketContext(bucket_id, /*expected_context_exists=*/false); +} + +// Similar to the above, but reverses the order of receiver disconnection and +// handle destruction. +TEST_P(IndexedDBTest, CloseWithReceiversInactive) { + // Create bucket context. + IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); + const storage::BucketId bucket_id = + bucket_context_handle->bucket_locator().id; + // Connect an IDBFactory mojo client. + mojo::Remote<blink::mojom::IDBFactory> factory_remote; + mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> + checker_remote; + bucket_context_handle->AddReceiver( + std::move(checker_remote), /*client_token=*/{}, + factory_remote.BindNewPipeAndPassReceiver()); + + // The bucket context and the backing store should exist. + VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, + /*expected_backing_store_exists=*/true); + + // The last mojo client is disconnected. + factory_remote.reset(); + task_environment_.RunUntilIdle(); + + // The bucket context and the backing store should still exist. + VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, + /*expected_backing_store_exists=*/true); + + // The last handle to the bucket context is released and the grace period + // elapses. + bucket_context_handle.Release(); + task_environment_.FastForwardBy(base::Seconds(2)); + + VerifyBucketContext(bucket_id, /*expected_context_exists=*/false); +} + +TEST_P(IndexedDBTest, PreCloseTasksStart) { + { + // Open a connection & immediately release it to cause the closing sequence + // to start. + IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); + storage::BucketId bucket_id = bucket_context_handle->bucket_locator().id; + + mojo::Remote<blink::mojom::IDBFactory> factory_remote; + mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> + checker_remote; + BindIndexedDBFactory(std::move(checker_remote), + factory_remote.BindNewPipeAndPassReceiver(), + ToBucketInfo(bucket_context_handle->bucket_locator())); + + bucket_context_handle.Release(); + + VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, + /*expected_backing_store_exists=*/true); + EXPECT_TRUE(context_->GetBucketContextForTesting(bucket_id)->IsClosing()); + + EXPECT_EQ(IndexedDBBucketContext::ClosingState::kPreCloseGracePeriod, + context_->GetBucketContextForTesting(bucket_id)->closing_stage()); + + task_environment_.FastForwardBy(base::Seconds(2)); + + // The factory should be closed, as the pre close tasks are delayed. + VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, + /*expected_backing_store_exists=*/false); + } + + // Move the clock to run the tasks in the next close sequence. + // NOTE: The constants rate-limiting sweeps and compaction are currently the + // same. This test may need to be restructured if these values diverge. + task_environment_.FastForwardBy( + IndexedDBBucketContext::kMaxEarliestGlobalSweepFromNow); + + { + // Open a connection & immediately release it to cause the closing sequence + // to start again. + IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); + storage::BucketId bucket_id = bucket_context_handle->bucket_locator().id; + bucket_context_handle.Release(); + + // Manually execute the timer so that the PreCloseTaskList task doesn't also + // run. + context_->GetBucketContextForTesting(bucket_id)->close_timer()->FireNow(); + + // The pre-close tasks should be running now. + ASSERT_TRUE(context_->GetBucketContextForTesting(bucket_id)); + EXPECT_EQ(IndexedDBBucketContext::ClosingState::kRunningPreCloseTasks, + context_->GetBucketContextForTesting(bucket_id)->closing_stage()); + ASSERT_TRUE(context_->GetBucketContextForTesting(bucket_id) + ->pre_close_task_queue()); + EXPECT_TRUE(context_->GetBucketContextForTesting(bucket_id) + ->pre_close_task_queue() + ->started()); + } + + { + // Stop sweep by opening a connection. + IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); + storage::BucketId bucket_id = bucket_context_handle->bucket_locator().id; + EXPECT_FALSE(bucket_context_handle->pre_close_task_queue()); + + // Move clock forward to trigger next sweep, but storage key has longer + // sweep minimum, so no tasks should execute. + task_environment_.FastForwardBy( + IndexedDBBucketContext::kMaxEarliestGlobalSweepFromNow); + + bucket_context_handle.Release(); + ASSERT_TRUE(context_->GetBucketContextForTesting(bucket_id)); + EXPECT_EQ(IndexedDBBucketContext::ClosingState::kPreCloseGracePeriod, + context_->GetBucketContextForTesting(bucket_id)->closing_stage()); + + // Manually execute the timer so that the PreCloseTaskList task doesn't also + // run. + context_->GetBucketContextForTesting(bucket_id)->close_timer()->FireNow(); + VerifyBucketContext(bucket_id, /*expected_context_exists=*/true, + /*expected_backing_store_exists=*/true); + + RunPostedTasks(); + VerifyBucketContext(bucket_id, /*expected_context_exists=*/false); + } + + { + // Finally, move the clock forward so the storage key should allow a sweep. + task_environment_.FastForwardBy( + IndexedDBBucketContext::kMaxEarliestBucketSweepFromNow); + IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); + storage::BucketId bucket_id = bucket_context_handle->bucket_locator().id; + bucket_context_handle.Release(); + context_->GetBucketContextForTesting(bucket_id)->close_timer()->FireNow(); + + ASSERT_TRUE(context_->GetBucketContextForTesting(bucket_id)); + EXPECT_EQ(IndexedDBBucketContext::ClosingState::kRunningPreCloseTasks, + context_->GetBucketContextForTesting(bucket_id)->closing_stage()); + ASSERT_TRUE(context_->GetBucketContextForTesting(bucket_id) + ->pre_close_task_queue()); + EXPECT_TRUE(context_->GetBucketContextForTesting(bucket_id) + ->pre_close_task_queue() + ->started()); + } +} + +TEST_P(IndexedDBTest, TombstoneSweeperTiming) { + // Open a connection. + IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); + EXPECT_FALSE(bucket_context_handle->ShouldRunTombstoneSweeper()); + + // Move the clock to run the tasks in the next close sequence. + task_environment_.FastForwardBy( + IndexedDBBucketContext::kMaxEarliestGlobalSweepFromNow); + + EXPECT_TRUE(bucket_context_handle->ShouldRunTombstoneSweeper()); + + // Move clock forward to trigger next sweep, but storage key has longer + // sweep minimum, so no tasks should execute. + task_environment_.FastForwardBy( + IndexedDBBucketContext::kMaxEarliestGlobalSweepFromNow); + + EXPECT_FALSE(bucket_context_handle->ShouldRunTombstoneSweeper()); + + // Finally, move the clock forward so the storage key should allow a sweep. + task_environment_.FastForwardBy( + IndexedDBBucketContext::kMaxEarliestBucketSweepFromNow); + + EXPECT_TRUE(bucket_context_handle->ShouldRunTombstoneSweeper()); +} + +TEST_P(IndexedDBTest, CompactionTaskTiming) { + // Open a connection. + IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); + bucket_context_handle->InitBackingStoreIfNeeded(/*create_if_missing=*/true); + EXPECT_FALSE(bucket_context_handle->ShouldRunCompaction()); + + // Move the clock to run the tasks in the next close sequence. + task_environment_.FastForwardBy( + IndexedDBBucketContext::kMaxEarliestGlobalCompactionFromNow); + + EXPECT_TRUE(bucket_context_handle->ShouldRunCompaction()); + + // Move clock forward to trigger next compaction, but storage key has longer + // compaction minimum, so no tasks should execute. + task_environment_.FastForwardBy( + IndexedDBBucketContext::kMaxEarliestGlobalCompactionFromNow); + + EXPECT_FALSE(bucket_context_handle->ShouldRunCompaction()); + + // Finally, move the clock forward so the storage key should allow a + // compaction. + task_environment_.FastForwardBy( + IndexedDBBucketContext::kMaxEarliestBucketCompactionFromNow); + + EXPECT_TRUE(bucket_context_handle->ShouldRunCompaction()); +} + +TEST_P(IndexedDBTest, InMemoryFactoriesStay) { + SetUpInMemoryContext(); + ASSERT_TRUE(context()->IsInMemoryContext()); + + IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); + storage::BucketLocator bucket_locator = + bucket_context_handle->bucket_locator(); + + EXPECT_TRUE(bucket_context_handle->backing_store()->in_memory()); + bucket_context_handle.Release(); + + EXPECT_TRUE(context_->GetBucketContextForTesting(bucket_locator.id)); + EXPECT_FALSE( + context_->GetBucketContextForTesting(bucket_locator.id)->IsClosing()); + + context_->ForceClose( + bucket_locator.id, + storage::mojom::ForceCloseReason::FORCE_CLOSE_INTERNALS_PAGE, + base::DoNothing()); + VerifyBucketContext(bucket_locator.id, /*expected_context_exists=*/true, + /*expected_backing_store_exists=*/true); + + context_->ForceClose( + bucket_locator.id, + storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN, + base::DoNothing()); + VerifyBucketContext(bucket_locator.id, /*expected_context_exists=*/false); +} + +TEST_P(IndexedDBTest, TooLongOrigin) { + base::FilePath temp_dir = + context()->GetFirstPartyDataPathForTesting().DirName(); + int limit = base::GetMaximumPathComponentLength(temp_dir); + EXPECT_GT(limit, 0); + + std::string origin(limit + 1, 'x'); + const blink::StorageKey too_long_storage_key = + blink::StorageKey::CreateFromStringForTesting("http://" + origin + + ":81/"); + storage::BucketInfo bucket_info = GetOrCreateBucket( + storage::BucketInitParams::ForDefaultBucket(too_long_storage_key)); + storage::BucketLocator bucket_locator = bucket_info.ToBucketLocator(); + + IndexedDBBucketContextHandle bucket_context_handle(GetOrCreateBucketContext( + ToBucketInfo(bucket_locator), context()->GetDataPath(bucket_locator))); + leveldb::Status s; + std::tie(s, std::ignore, std::ignore) = + bucket_context_handle->InitBackingStoreIfNeeded( + /*create_if_missing=*/true); + + EXPECT_TRUE(s.IsIOError()); +} + +TEST_P(IndexedDBTest, FactoryForceClose) { + IndexedDBBucketContextHandle bucket_context_handle = CreateBucketHandle(); + storage::BucketLocator bucket_locator = + bucket_context_handle->bucket_locator(); + + bucket_context_handle->ForceClose(/*doom=*/false); + bucket_context_handle.Release(); + + VerifyBucketContext(bucket_locator.id, /*expected_context_exists=*/true, + /*expected_backing_store_exists=*/true); + RunPostedTasks(); + VerifyBucketContext(bucket_locator.id, /*expected_context_exists=*/false); +} + +// Tests that the backing store is closed when the connection is closed during +// upgrade. +TEST_P(IndexedDBTest, ConnectionCloseDuringUpgrade) { + const blink::StorageKey storage_key = + blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); + auto bucket_locator = storage::BucketLocator(); + bucket_locator.storage_key = storage_key; + + // Bind the IDBFactory. + mojo::Remote<blink::mojom::IDBFactory> factory_remote; + mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> + checker_remote; + BindIndexedDBFactory(std::move(checker_remote), + factory_remote.BindNewPipeAndPassReceiver(), + ToBucketInfo(bucket_locator)); + + // Now create a database and thus the backing store. + MockMojoIndexedDBFactoryClient client; + MockMojoIndexedDBDatabaseCallbacks database_callbacks; + base::RunLoop run_loop; + mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database; + EXPECT_CALL(client, MockedUpgradeNeeded) + .WillOnce( + testing::DoAll(MoveArgPointee<0>(&pending_database), + ::base::test::RunClosure(run_loop.QuitClosure()))); + mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; + factory_remote->Open(client.CreateInterfacePtrAndBind(), + database_callbacks.CreateInterfacePtrAndBind(), u"db", + /*version=*/1, + transaction_remote.BindNewEndpointAndPassReceiver(), + /*transaction_id=*/1); + run_loop.Run(); + + EXPECT_TRUE(context_->GetBucketContextForTesting(bucket_locator.id)); + EXPECT_FALSE( + context_->GetBucketContextForTesting(bucket_locator.id)->IsClosing()); + + // Drop the connection. + pending_database.reset(); + factory_remote.FlushForTesting(); + EXPECT_TRUE( + context_->GetBucketContextForTesting(bucket_locator.id)->IsClosing()); +} + +TEST_P(IndexedDBTest, DeleteDatabase) { + const blink::StorageKey storage_key = + blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); + auto bucket_locator = storage::BucketLocator(); + bucket_locator.storage_key = storage_key; + + // Bind the IDBFactory. + mojo::Remote<blink::mojom::IDBFactory> factory_remote; + mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> + checker_remote; + BindIndexedDBFactory(std::move(checker_remote), + factory_remote.BindNewPipeAndPassReceiver(), + ToBucketInfo(bucket_locator)); + + // Don't create a backing store if one doesn't exist. + { + // Delete db. + MockMojoIndexedDBFactoryClient client; + MockMojoIndexedDBDatabaseCallbacks database_callbacks; + base::RunLoop run_loop; + EXPECT_CALL(client, DeleteSuccess) + .WillOnce( + testing::DoAll(::base::test::RunClosure(run_loop.QuitClosure()))); + mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; + factory_remote->DeleteDatabase(client.CreateInterfacePtrAndBind(), u"db", + /*force_close=*/false); + run_loop.Run(); + + // Backing store shouldn't exist. + EXPECT_FALSE(context_->GetBucketContextForTesting(bucket_locator.id) + ->backing_store()); + } + + // Now create a database and thus the backing store. + { + MockMojoIndexedDBFactoryClient client; + MockMojoIndexedDBDatabaseCallbacks database_callbacks; + base::RunLoop run_loop; + EXPECT_CALL(client, MockedOpenSuccess) + .WillOnce(::base::test::RunClosure(run_loop.QuitClosure())); + mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; + factory_remote->Open(client.CreateInterfacePtrAndBind(), + database_callbacks.CreateInterfacePtrAndBind(), u"db", + /*version=*/0, + transaction_remote.BindNewEndpointAndPassReceiver(), + /*transaction_id=*/1); + run_loop.Run(); + } + + // Delete the database now that the backing store actually exists. + { + MockMojoIndexedDBFactoryClient client; + MockMojoIndexedDBDatabaseCallbacks database_callbacks; + base::RunLoop run_loop; + EXPECT_CALL(client, DeleteSuccess) + .WillOnce( + testing::DoAll(::base::test::RunClosure(run_loop.QuitClosure()))); + mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; + factory_remote->DeleteDatabase(client.CreateInterfacePtrAndBind(), u"db", + /*force_close=*/false); + run_loop.Run(); + + // Since there are no more references the factory should be closing. + ASSERT_TRUE(context_->GetBucketContextForTesting(bucket_locator.id)); + EXPECT_TRUE( + context_->GetBucketContextForTesting(bucket_locator.id)->IsClosing()); + } +} + +TEST_P(IndexedDBTest, GetDatabaseNames_NoFactory) { + const blink::StorageKey storage_key = + blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); + auto bucket_locator = storage::BucketLocator(); + bucket_locator.storage_key = storage_key; + + // Bind the IDBFactory. + mojo::Remote<blink::mojom::IDBFactory> factory_remote; + mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> + checker_remote; + BindIndexedDBFactory(std::move(checker_remote), + factory_remote.BindNewPipeAndPassReceiver(), + ToBucketInfo(bucket_locator)); + + // Don't create a backing store if one doesn't exist. + { + base::test::TestFuture<std::vector<blink::mojom::IDBNameAndVersionPtr>, + blink::mojom::IDBErrorPtr> + info_future; + factory_remote->GetDatabaseInfo(info_future.GetCallback()); + ASSERT_TRUE(info_future.Wait()); + EXPECT_FALSE(context_->GetBucketContextForTesting(bucket_locator.id) + ->backing_store()); + } + + // Now create a database and thus the backing store. + MockMojoIndexedDBFactoryClient client; + MockMojoIndexedDBDatabaseCallbacks database_callbacks; + base::RunLoop run_loop; + // It's necessary to hang onto the database connection or the connection + // will shut itself down and the backing store will close on its own. + mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database; + EXPECT_CALL(client, MockedOpenSuccess) + .WillOnce( + testing::DoAll(MoveArgPointee<0>(&pending_database), + ::base::test::RunClosure(run_loop.QuitClosure()))); + mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; + factory_remote->Open(client.CreateInterfacePtrAndBind(), + database_callbacks.CreateInterfacePtrAndBind(), u"db", + /*version=*/0, + transaction_remote.BindNewEndpointAndPassReceiver(), + /*transaction_id=*/1); + run_loop.Run(); + // GetDatabaseInfo didn't create the factory, so it shouldn't close it. + { + base::test::TestFuture<std::vector<blink::mojom::IDBNameAndVersionPtr>, + blink::mojom::IDBErrorPtr> + info_future; + factory_remote->GetDatabaseInfo(info_future.GetCallback()); + ASSERT_TRUE(info_future.Wait()); + + EXPECT_TRUE(context_->GetBucketContextForTesting(bucket_locator.id)); + EXPECT_FALSE( + context_->GetBucketContextForTesting(bucket_locator.id)->IsClosing()); + } +} + +TEST_P(IndexedDBTest, QuotaErrorOnDiskFull) { + leveldb_env::SetDBFactoryForTesting(base::BindRepeating( + [](const leveldb_env::Options& options, const std::string& name, + std::unique_ptr<leveldb::DB>* dbptr) { + return leveldb_env::MakeIOError("foobar", "disk full", + leveldb_env::MethodID::kCreateDir, + base::File::FILE_ERROR_NO_SPACE); + })); + + // Bind the IDBFactory. + const blink::StorageKey storage_key = + blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); + auto bucket_locator = storage::BucketLocator(); + bucket_locator.storage_key = storage_key; + mojo::Remote<blink::mojom::IDBFactory> factory_remote; + mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> + checker_remote; + BindIndexedDBFactory(std::move(checker_remote), + factory_remote.BindNewPipeAndPassReceiver(), + ToBucketInfo(bucket_locator)); + + // Expect an error when opening. + MockMojoIndexedDBFactoryClient client; + MockMojoIndexedDBDatabaseCallbacks database_callbacks; + base::RunLoop run_loop; + EXPECT_CALL(client, Error) + .WillOnce( + testing::DoAll(::base::test::RunClosure(run_loop.QuitClosure()))); + mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; + factory_remote->Open(client.CreateInterfacePtrAndBind(), + database_callbacks.CreateInterfacePtrAndBind(), u"db", + /*version=*/1, + transaction_remote.BindNewEndpointAndPassReceiver(), + /*transaction_id=*/1); + run_loop.Run(); + + // A disk full error results in an error reported to the quota system. + ASSERT_EQ(1U, quota_manager_->write_error_tracker().size()); + EXPECT_EQ(storage_key, quota_manager_->write_error_tracker().begin()->first); + EXPECT_EQ(1, quota_manager_->write_error_tracker().begin()->second); + + leveldb_env::SetDBFactoryForTesting({}); +} + +TEST_P(IndexedDBTest, DatabaseFailedOpen) { + const blink::StorageKey storage_key = + blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); + auto bucket_locator = storage::BucketLocator(); + bucket_locator.storage_key = storage_key; + const std::u16string db_name(u"db"); + + // Bind the IDBFactory. + mojo::Remote<blink::mojom::IDBFactory> factory_remote; + mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> + checker_remote; + BindIndexedDBFactory(std::move(checker_remote), + factory_remote.BindNewPipeAndPassReceiver(), + ToBucketInfo(bucket_locator)); + + // Open at version 2. + { + const int64_t db_version = 2; + MockMojoIndexedDBFactoryClient client; + MockMojoIndexedDBDatabaseCallbacks database_callbacks; + base::RunLoop run_loop; + EXPECT_CALL(client, MockedUpgradeNeeded) + .WillOnce( + testing::DoAll(::base::test::RunClosure(run_loop.QuitClosure()))); + mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; + factory_remote->Open(client.CreateInterfacePtrAndBind(), + database_callbacks.CreateInterfacePtrAndBind(), + db_name, db_version, + transaction_remote.BindNewEndpointAndPassReceiver(), + /*transaction_id=*/1); + run_loop.Run(); + } + + // Open at version < 2, which will fail. + { + const int64_t db_version = 1; + base::RunLoop run_loop; + MockMojoIndexedDBFactoryClient client; + MockMojoIndexedDBDatabaseCallbacks database_callbacks; + EXPECT_CALL(client, Error) + .WillOnce(::base::test::RunClosure(run_loop.QuitClosure())); + mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; + factory_remote->Open(client.CreateInterfacePtrAndBind(), + database_callbacks.CreateInterfacePtrAndBind(), + db_name, db_version, + transaction_remote.BindNewEndpointAndPassReceiver(), + /*transaction_id=*/2); + run_loop.Run(); + IndexedDBBucketContext* bucket_context = + context_->GetBucketContextForTesting(bucket_locator.id); + ASSERT_TRUE(bucket_context); + EXPECT_FALSE( + base::Contains(bucket_context->GetDatabasesForTesting(), db_name)); + } +} + +// Test for `IndexedDBDataFormatVersion`. +TEST_P(IndexedDBTest, DataLoss) { + const blink::StorageKey storage_key = + blink::StorageKey::CreateFromStringForTesting("http://localhost:81"); + auto bucket_locator = storage::BucketLocator(); + bucket_locator.storage_key = storage_key; + const std::u16string db_name(u"test_db"); + + // Bind the IDBFactory. + mojo::Remote<blink::mojom::IDBFactory> factory_remote; + mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker> + checker_remote; + BindIndexedDBFactory(std::move(checker_remote), + factory_remote.BindNewPipeAndPassReceiver(), + ToBucketInfo(bucket_locator)); + + // Set a data format version and create a new database. No data loss. + { + base::AutoReset<IndexedDBDataFormatVersion> override_version( + &IndexedDBDataFormatVersion::GetMutableCurrentForTesting(), + IndexedDBDataFormatVersion(3, 4)); + MockMojoIndexedDBFactoryClient client; + MockMojoIndexedDBDatabaseCallbacks database_callbacks; + base::RunLoop run_loop; + EXPECT_CALL(client, MockedUpgradeNeeded( + _, _, blink::mojom::IDBDataLoss::None, _, _)) + .WillOnce( + testing::DoAll(::base::test::RunClosure(run_loop.QuitClosure()))); + mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; + factory_remote->Open(client.CreateInterfacePtrAndBind(), + database_callbacks.CreateInterfacePtrAndBind(), + db_name, /*version=*/1, + transaction_remote.BindNewEndpointAndPassReceiver(), + /*transaction_id=*/1); + run_loop.Run(); + + // This step is necessary to make sure the backing store is closed so that + // the second `Open` will initialize it with the new (older) data format + // version. Without this step, the same `IndexedDBBackingStore` is reused + // because it's kept around for 2 seconds after the last connection is + // dropped. + base::RunLoop run_loop2; + context_->ForceClose( + bucket_locator.id, + storage::mojom::ForceCloseReason::FORCE_CLOSE_BACKING_STORE_FAILURE, + run_loop2.QuitClosure()); + run_loop2.Run(); + } + + // Set an older data format version and try to reopen said database. Expect + // total data loss. + { + base::AutoReset<IndexedDBDataFormatVersion> override_version( + &IndexedDBDataFormatVersion::GetMutableCurrentForTesting(), + IndexedDBDataFormatVersion(3, 3)); + base::RunLoop run_loop; + MockMojoIndexedDBFactoryClient client; + MockMojoIndexedDBDatabaseCallbacks database_callbacks; + EXPECT_CALL(client, MockedUpgradeNeeded( + _, _, blink::mojom::IDBDataLoss::Total, _, _)) + .WillOnce( + testing::DoAll(::base::test::RunClosure(run_loop.QuitClosure()))); + mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote; + factory_remote->Open(client.CreateInterfacePtrAndBind(), + database_callbacks.CreateInterfacePtrAndBind(), + db_name, /*version=*/1, + transaction_remote.BindNewEndpointAndPassReceiver(), + /*transaction_id=*/2); + run_loop.Run(); + } +} + } // namespace content
diff --git a/content/browser/launch_as_mojo_client_browsertest.cc b/content/browser/launch_as_mojo_client_browsertest.cc index 542959ae..8fd807e 100644 --- a/content/browser/launch_as_mojo_client_browsertest.cc +++ b/content/browser/launch_as_mojo_client_browsertest.cc
@@ -155,10 +155,6 @@ mojo::Remote<mojom::ShellController> shell_controller_; }; -// TODO(http://crbug.com/323984075): This test invokes content_shell in a way -// that is not supported on Lacros (without crosapi data). Figure out what to -// do about that. -#if !BUILDFLAG(IS_CHROMEOS_LACROS) IN_PROC_BROWSER_TEST_F(LaunchAsMojoClientBrowserTest, LaunchAndBindInterface) { // Verifies that we can launch an instance of Content Shell with a Mojo // invitation on the command line and reach the new browser process's exposed @@ -184,7 +180,6 @@ shell_controller->ShutDown(); } -#endif // !BUILDFLAG(IS_CHROMEOS_LACROS) #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) // TODO(crbug.com/1259557): This test implementation fundamentally conflicts
diff --git a/content/browser/navigation_transitions/back_forward_transition_animation_manager_android.cc b/content/browser/navigation_transitions/back_forward_transition_animation_manager_android.cc index e0b9b862..57d1a1c 100644 --- a/content/browser/navigation_transitions/back_forward_transition_animation_manager_android.cc +++ b/content/browser/navigation_transitions/back_forward_transition_animation_manager_android.cc
@@ -4,15 +4,8 @@ #include "content/browser/navigation_transitions/back_forward_transition_animation_manager_android.h" -#include "content/browser/renderer_host/compositor_impl_android.h" #include "content/browser/renderer_host/navigation_controller_impl.h" -#include "content/browser/renderer_host/navigation_transitions/navigation_entry_screenshot_cache.h" -#include "content/browser/renderer_host/render_widget_host_impl.h" -#include "content/browser/renderer_host/render_widget_host_view_android.h" #include "content/browser/web_contents/web_contents_view_android.h" -#include "content/public/browser/navigation_handle.h" -#include "content/public/browser/render_widget_host_observer.h" -#include "ui/android/window_android.h" #include "ui/events/back_gesture_event.h" namespace content { @@ -49,393 +42,14 @@ } // namespace -//=========================== `AnimationManagerImpl` =========================== - -class BackForwardTransitionAnimationManagerAndroid::AnimationManagerImpl - : public RenderFrameMetadataProvider::Observer, - ui::WindowAndroidObserver, - WebContentsObserver, - RenderWidgetHostObserver { - public: - AnimationManagerImpl( - WebContentsViewAndroid* web_contents_view_android, - NavigationControllerImpl* controller, - const ui::BackGestureEvent& gesture, - HistoryNavType nav_type, - SwipeEdge edge, - BackForwardTransitionAnimationManagerAndroid* animation_manager); - AnimationManagerImpl(const AnimationManagerImpl&) = delete; - AnimationManagerImpl& operator=(const AnimationManagerImpl&) = delete; - ~AnimationManagerImpl() override; - - // `RenderFrameMetadataProvider::Observer`: - void OnRenderFrameMetadataChangedBeforeActivation( - const cc::RenderFrameMetadata& metadata) override {} - void OnRenderFrameMetadataChangedAfterActivation( - base::TimeTicks activation_time) override; - void OnRenderFrameSubmission() override {} - void OnLocalSurfaceIdChanged( - const cc::RenderFrameMetadata& metadata) override {} - - // `ui::WindowAndroidObserver`: - void OnRootWindowVisibilityChanged(bool visible) override; - void OnAttachCompositor() override {} - void OnDetachCompositor() override; - void OnAnimate(base::TimeTicks frame_begin_time) override; - void OnActivityStopped() override {} - void OnActivityStarted() override {} - - // `WebContentsObserver`: - void DidFinishNavigation(NavigationHandle* navigation_handle) override; - - // `RenderWidgetHostObserver`: - void RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) override; - - // Mirrors the APIs on `BackForwardTransitionAnimationManager`. - void OnGestureProgressed(const ui::BackGestureEvent& gesture); - void OnGestureCancelled(); - void OnGestureInvoked(); - void OnRenderWidgetHostViewSwapped(RenderWidgetHost* old_widget_host, - RenderWidgetHost* new_widget_host); - - private: - const HistoryNavType nav_type_; - const SwipeEdge edge_; - - // The manager back-pointer. Guaranteed to outlive the impl. - const raw_ptr<BackForwardTransitionAnimationManagerAndroid> - animation_manager_; - - // Tracks the `NavigationRequest` created by the gesture back navigation of a - // primary main frame. - std::optional<int64_t> - primary_main_frame_navigation_request_id_of_gesture_nav_; - - enum class NavigationTerminalState { - // Navigation has not begun, or not yet committed. - kNotSet = 0, - // The navigation has either committed to a new doc, or an error page. - kCommitted, - // The navigation has been cancelled (replaced by a secondary navigation, or - // aborted by the user). - kCancelled, - }; - // Set via `DidFinishNavigation()`. Records if the navigation has successfully - // committed. - NavigationTerminalState navigation_state_ = NavigationTerminalState::kNotSet; - - // If viz has already activated a frame for the new page before the invoke - // animation finishes, we set this bit so we can start the crossfade animation - // immediately after the invoke animation. - bool viz_has_activated_first_frame_ = false; - - // The widget host for the new page. Only set after the new page's widget is - // swapped in. This class listens to the first - // `OnRenderFrameMetadataChangedAfterActivation()` on the new widget host. - // This first notification signals that viz has processed a frame submitted by - // the renderer, at which we can safely cross-fade from the screenshot to the - // new page. - // - // Stays null for 204/205/Download, or for cancelled navigations. Also reset - // to null when the tracked `RenderWidgetHost` is destroyed. - raw_ptr<RenderWidgetHostImpl> new_render_widget_host_; - - // Set by the latest `OnGestureProgressed()`. - ui::BackGestureEvent latest_progress_gesture_; -}; - -BackForwardTransitionAnimationManagerAndroid::AnimationManagerImpl:: - AnimationManagerImpl( - WebContentsViewAndroid* web_contents_view_android, - NavigationControllerImpl* controller, - const ui::BackGestureEvent& gesture, - HistoryNavType nav_type, - SwipeEdge edge, - BackForwardTransitionAnimationManagerAndroid* animation_manager) - : nav_type_(nav_type), - edge_(edge), - animation_manager_(animation_manager), - latest_progress_gesture_(gesture) { - CHECK_EQ(nav_type_, HistoryNavType::kBackward); - CHECK_EQ(edge_, SwipeEdge::LEFT); - // TODO(https://crbug.com/1509888): Directly advance to the start state. -} - -BackForwardTransitionAnimationManagerAndroid::AnimationManagerImpl:: - ~AnimationManagerImpl() { - // TODO(https://crbug.com/1509888): - // - Reset the transformation on WCVA::parent_for_web_page_widgets_; - // - Remove UIResource for the screenshot; - // - Detach and destroy the screenshot layer. -} - -// This is only called after we subscribe to the new `RenderWidgetHost` in -// `OnRenderWidgetHostViewSwapped()`, meaning this method, just like -// `OnRenderWidgetHostViewSwapped()`, won't be called for 204/205/Download -// navigations, and won't be called if the navigation is cancelled. -// -// The manager won't be notified by the -// `OnRenderFrameMetadataChangedAfterActivation()`s that arrive earlier than -// `DidCommitNavigation()` either if the renderer is too busy to reply the -// DidCommit message while viz has already activated a new frame for the new -// page. See `OnRenderWidgetHostViewSwapped()` on how we guard this case. -void BackForwardTransitionAnimationManagerAndroid::AnimationManagerImpl:: - OnRenderFrameMetadataChangedAfterActivation( - base::TimeTicks activation_time) { - // `OnRenderWidgetHostViewSwapped()` is the prerequisite for this API. - CHECK(new_render_widget_host_); - - // `DidFinishNavigation()` must have been called, because the swap of - // `RenderWidgetHostView`s and `DidFinishNavigation()` happen in the same - // atomic callstack (all part of the `DidCommitNavigation`). - // - // The navigation must have successfully committed, resulting us swapping the - // `RenderWidgetHostView`s thus getting this notification. - CHECK_EQ(navigation_state_, NavigationTerminalState::kCommitted); - - CHECK(!viz_has_activated_first_frame_) - << "OnRenderFrameMetadataChangedAfterActivation can only be called once."; - viz_has_activated_first_frame_ = true; - - // No longer interested in any other compositor frame submission - // notifications. We can safely dismiss the previewed screenshot now. - new_render_widget_host_->render_frame_metadata_provider()->RemoveObserver( - this); - new_render_widget_host_->RemoveObserver(this); - new_render_widget_host_ = nullptr; - - // TODO(https://crbug.com/1509888): Advance to the next state to display the - // cross-fade animation. -} - -void BackForwardTransitionAnimationManagerAndroid::AnimationManagerImpl:: - OnRootWindowVisibilityChanged(bool visible) { - if (!visible) { - ui::WindowAndroid* window_android = - animation_manager_->web_contents_view_android_ - ->GetTopLevelNativeWindow(); - CHECK(window_android); - window_android->RemoveObserver(this); - - ui::WindowAndroidCompositor* compositor = window_android->GetCompositor(); - CHECK(compositor); - - animation_manager_->OnAnimationsFinished(); - } -} - -void BackForwardTransitionAnimationManagerAndroid::AnimationManagerImpl:: - OnDetachCompositor() { - ui::WindowAndroid* window_android = - animation_manager_->web_contents_view_android_->GetTopLevelNativeWindow(); - window_android->RemoveObserver(this); - - ui::WindowAndroidCompositor* compositor = window_android->GetCompositor(); - CHECK(compositor); - - animation_manager_->OnAnimationsFinished(); -} - -void BackForwardTransitionAnimationManagerAndroid::AnimationManagerImpl:: - OnAnimate(base::TimeTicks frame_begin_time) { - // TODO(https://crbug.com/1509888): Implement this. - // - // if (crossfade) { Tick `effect_` } - // else { ask `physics_model_` to compute the offsets } - // - // if (done) { advance to next state } - // else { WindowAndroid::SetNeedsAnimate } -} - -void BackForwardTransitionAnimationManagerAndroid::AnimationManagerImpl:: - DidFinishNavigation(NavigationHandle* navigation_handle) { - if (!primary_main_frame_navigation_request_id_of_gesture_nav_.has_value()) { - // This accounts for when the user is in the middle of a swipe but a - // navigation occurs. While the user is swiping, the current page is - // partially out of the viewport. Since a navigation has just committed in - // the browser, we must recenter the current page. - // - // TODO(https://crbug.com/1509888): - // - Advance to the `kDisplayingCancelAnimation`. - // - Also put the screenshot back to it's navigation entry. - return; - } - if (primary_main_frame_navigation_request_id_of_gesture_nav_.value() != - navigation_handle->GetNavigationId()) { - // Ignore any other request's destruction. We are only interested in the - // primary main frame's request created by this animation manager, as a - // result of a user-initiated session history navigation. - return; - } - - CHECK_EQ(navigation_state_, NavigationTerminalState::kNotSet) - << "DidFinishNavigation can only be called once. We might have observed " - "the wrong navigation request."; - - navigation_state_ = navigation_handle->HasCommitted() - ? NavigationTerminalState::kCommitted - : NavigationTerminalState::kCancelled; - WebContentsObserver::Observe(nullptr); - - // TODO(https://crbug.com/1509888): OnDidFinishNavigation on physics model. - - if (navigation_handle->IsErrorPage()) { - CHECK_EQ(navigation_state_, NavigationTerminalState::kCommitted); - // TODO(https://crbug.com/1509887): Implement a different UX if we decide - // not show the animation at all (i.e. abort animation early when we - // receive the response header). - } else { - if (UNLIKELY(navigation_state_ == NavigationTerminalState::kCancelled)) { - // 204/205/Download, or the ongoing navigation is cancelled. We need to - // animate the old page back. - // - // TODO(https://crbug.com/1509886): We might need a better UX than just - // display the cancel animation. - // - // TODO(https://crbug.com/1509888): Manually advance to the cancel state, - // since the gesture navigation is being cancelled, meaning this animation - // manager won't receive a `OnGestureCancelled()`. - } - } - // TODO(https://crbug.com/1519149): Handle the cross-origin server redirect. - // We cannot show a cross-origin fullscreen overlay of a.com if a.com redirect - // the user to b.com. -} - -void BackForwardTransitionAnimationManagerAndroid::AnimationManagerImpl:: - RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) { - if (widget_host == new_render_widget_host_) { - // Our new widget host is about to be destroyed. This can happen for a - // client redirect, where we never get the - // `OnRenderFrameMetadataChangedAfterActivation()` of any frame of a - // committed renderer. The screenshot isn't dismissed even after the gesture - // navigation is committed. - // - // In such cases we simply advance to play the cross-fade from the - // screenshot to whichever surface underneath the screenshot. - // - // TODO(https://crbug.com/1509888): Also CHECK `state_` that `this` is - // waiting for new frame submissions. - CHECK_EQ(navigation_state_, NavigationTerminalState::kCommitted); - new_render_widget_host_ = nullptr; - // TODO(https://crbug.com/1509888): Advance to play the cross-fade - // animation. - } -} - -void BackForwardTransitionAnimationManagerAndroid::AnimationManagerImpl:: - OnGestureProgressed(const ui::BackGestureEvent& gesture) { - CHECK_GE(gesture.progress(), 0.f); - CHECK_LE(gesture.progress(), 1.f); - - latest_progress_gesture_ = gesture; - - // TODO(https://crbug.com/1509888): - // - Ask physics model for transforms. - // - Set the layers' transforms per `result`. - // - Tick `effect_` with a fitted timestamp. -} - -void BackForwardTransitionAnimationManagerAndroid::AnimationManagerImpl:: - OnGestureCancelled() { - // TODO(https://crbug.com/1509888): Advance to displaying the cancel - // animation. -} - -void BackForwardTransitionAnimationManagerAndroid::AnimationManagerImpl:: - OnGestureInvoked() { - // TODO(https://crbug.com/1509888): Set the request ID immediately after - // calling `NavigationController::GoToIndex()`. After GoToIndex(): - // - If the controller doesn't have a pending entry, then we must have failed - // creating a `NavigationRequest`. Play the cancel animation. - // - If the primary `FrameTreeNode` has a `NavigationRequest`, set its ID to - // `navigation_request_id_`. If the main frame is navigating away, we will - // listen to the request of the main frame. - // - TODO(https://crbug.com/1517736) Else, traverse the entire `FrameTree` and - // collect all the navigation requests . - // - // TODO(crbug.com/1515916): Handle the subframe navigations where we have - // multiple navigation requests for the subframes. Fow now the subframe - // navigations are implicitly not animated because we don't capture - // screenshots for subframe navigations. - - // TODO(https://crbug.com/1509888): Advance to displaying the invoke - // animation. -} - -void BackForwardTransitionAnimationManagerAndroid::AnimationManagerImpl:: - OnRenderWidgetHostViewSwapped(RenderWidgetHost* old_widget_host, - RenderWidgetHost* new_widget_host) { - auto* old_view = - static_cast<RenderWidgetHostViewAndroid*>(old_widget_host->GetView()); - if (old_view) { - // TODO(https://crbug.com/1488075): There might be a visual glitch if the - // old page is unloaded while we are still displaying the invoke animation. - // For now, make a deep copy of the old surface layer from `old_rwhva` and - // put the deep copy on top of the `WCVA::parent_for_web_page_widgets_`. - // - // Ideally, we need a way to preserve a minimal visual state of the old - // page. - } else { - // If we do a back navigation from a crashed page, we won't have an - // `old_view`. - // - // TODO(https://crbug.com/1488075): The Clank's interstitial page isn't - // drawn by `old_view`. We need to address as part of "navigating from NTP" - // animation. - } - - // We must have a live new widget. - CHECK(new_widget_host); - // `render_frame_metadata_provider()` is guaranteed non-null. - std::optional<viz::LocalSurfaceId> last_frame_local_surface_id = - static_cast<RenderWidgetHostImpl*>(new_widget_host) - ->render_frame_metadata_provider() - ->LastRenderFrameMetadata() - .local_surface_id; - auto* new_view = - static_cast<RenderWidgetHostViewBase*>(new_widget_host->GetView()); - if (last_frame_local_surface_id.has_value() && - last_frame_local_surface_id.value().is_valid() && - last_frame_local_surface_id.value().embed_token() == - new_view->GetLocalSurfaceId().embed_token() && - last_frame_local_surface_id.value().IsSameOrNewerThan( - new_view->GetLocalSurfaceId())) { - // This can happen where the renderer's main thread is very busy to reply - // `DidCommitNavigation()` back to the browser, but viz has already - // activated the first frame. Because the browser hasn't received the - // `DidCommitNavigation()` message, this animation manager hasn't subscribed - // to the new widget host, therefore missed out on the first - // `OnRenderFrameMetadataChangedAfterActivation()`. The screenshot will stay - // until the next `OnRenderFrameMetadataChangedAfterActivation()` - // notification. - // - // In this case we inspect the `LocalSurfaceId` of activated frame. If the - // ID is greater than what the browser is embedding, we know viz has already - // activated a frame. We don't need to subscribe to the new widget host - // for `OnRenderFrameMetadataChangedAfterActivation()` at all. - CHECK(!viz_has_activated_first_frame_); - viz_has_activated_first_frame_ = true; - return; - } - - // We subscribe to `new_widget_host` to get notified when the new renderer - // draws a new frame, so we can start cross-fading from the preview screenshot - // to the new page's live content. - CHECK(!new_render_widget_host_); - new_render_widget_host_ = RenderWidgetHostImpl::From(new_widget_host); - new_render_widget_host_->AddObserver(this); - new_render_widget_host_->render_frame_metadata_provider()->AddObserver(this); -} - -//=============== `BackForwardTransitionAnimationManagerAndroid` =============== - BackForwardTransitionAnimationManagerAndroid:: BackForwardTransitionAnimationManagerAndroid( WebContentsViewAndroid* web_contents_view_android, NavigationControllerImpl* navigation_controller) : web_contents_view_android_(web_contents_view_android), - navigation_controller_(navigation_controller) {} + navigation_controller_(navigation_controller), + animator_factory_( + std::make_unique<BackForwardTransitionAnimator::Factory>()) {} BackForwardTransitionAnimationManagerAndroid:: ~BackForwardTransitionAnimationManagerAndroid() = default; @@ -455,14 +69,14 @@ << "The embedder should only delegate the history navigation task " "to this manager if there is a destination entry."; - if (impl_) { + if (animator_) { // It's possible for a user to start a second gesture when the first gesture // is still on-going (aka "chained back"). For now, abort the previous // animation (impl's dtor will reset the layer's position and reclaim all // the resources). // // TODO(https://crbug.com/1425943): We need a proper UX to support this. - impl_.reset(); + animator_.reset(); } if (ShouldSkipDefaultNavTransitionForPendingUX(navigation_type, edge) || @@ -476,29 +90,29 @@ return; } - impl_ = std::make_unique<AnimationManagerImpl>( - web_contents_view_android_.get(), navigation_controller_.get(), gesture, - navigation_type, edge, this); + animator_ = animator_factory_->Create(web_contents_view_android_.get(), + navigation_controller_.get(), gesture, + navigation_type, edge, this); } void BackForwardTransitionAnimationManagerAndroid::OnGestureProgressed( const ui::BackGestureEvent& gesture) { - if (impl_) { - impl_->OnGestureProgressed(gesture); + if (animator_) { + animator_->OnGestureProgressed(gesture); } } void BackForwardTransitionAnimationManagerAndroid::OnGestureCancelled() { - if (impl_) { - impl_->OnGestureCancelled(); + if (animator_) { + animator_->OnGestureCancelled(); } destination_entry_index_.reset(); } void BackForwardTransitionAnimationManagerAndroid::OnGestureInvoked() { - if (impl_) { + if (animator_) { CHECK(!destination_entry_index_.has_value()); - impl_->OnGestureInvoked(); + animator_->OnGestureInvoked(); } else { CHECK(destination_entry_index_.has_value()); navigation_controller_->GoToIndex(*destination_entry_index_); @@ -509,14 +123,14 @@ void BackForwardTransitionAnimationManagerAndroid:: OnRenderWidgetHostViewSwapped(RenderWidgetHost* old_widget_host, RenderWidgetHost* new_widget_host) { - if (impl_) { - impl_->OnRenderWidgetHostViewSwapped(old_widget_host, new_widget_host); + if (animator_) { + animator_->OnRenderWidgetHostViewSwapped(old_widget_host, new_widget_host); } } void BackForwardTransitionAnimationManagerAndroid::OnAnimationsFinished() { - CHECK(impl_); - impl_.reset(); + CHECK(animator_); + animator_.reset(); } } // namespace content
diff --git a/content/browser/navigation_transitions/back_forward_transition_animation_manager_android.h b/content/browser/navigation_transitions/back_forward_transition_animation_manager_android.h index c1104f4..f93e0fcb 100644 --- a/content/browser/navigation_transitions/back_forward_transition_animation_manager_android.h +++ b/content/browser/navigation_transitions/back_forward_transition_animation_manager_android.h
@@ -8,10 +8,8 @@ #include <memory> #include "base/memory/raw_ptr.h" +#include "content/browser/navigation_transitions/back_forward_transition_animator.h" #include "content/public/browser/back_forward_transition_animation_manager.h" -#include "content/public/browser/render_frame_metadata_provider.h" -#include "content/public/browser/web_contents_observer.h" -#include "ui/android/window_android_observer.h" namespace ui { class BackGestureEvent; @@ -23,11 +21,11 @@ class RenderWidgetHost; class WebContentsViewAndroid; -// A wrapper class that forwards the gesture event APIs to the `impl_`. It +// A wrapper class that forwards the gesture event APIs to the `animator_`. It // limits the APIs explosed to the embedder. Owned by `WebContentsViewAndroid`. // // If for some reason the history navigation couldn't be animated, this class -// won't create an `impl_`, and will start the history navigation via the +// won't create an `animator_`, and will start the history navigation via the // `NavigationController`. // TODO(https://crbug.com/1424477): We should always animate a gesture history // navigation. @@ -77,15 +75,24 @@ void OnRenderWidgetHostViewSwapped(RenderWidgetHost* old_widget_host, RenderWidgetHost* new_widget_host); - private: - // The actual implementation of the animation manager that manages the history - // navigation animation. One instance per gesture. - class AnimationManagerImpl; - - // `impl_` invokes this callback to erase itself, when all the animation has - // finished in the browser UI. + // `animator_` invokes this callback to erase itself, when all the animation + // has finished in the browser UI. void OnAnimationsFinished(); + WebContentsViewAndroid* web_contents_view_android() const { + return web_contents_view_android_; + } + + NavigationControllerImpl* navigation_controller() const { + return navigation_controller_; + } + + void set_animator_factory_for_testing( + std::unique_ptr<BackForwardTransitionAnimator::Factory> factory) { + animator_factory_ = std::move(factory); + } + + private: // The owning `WebContentsViewAndroid`. Guaranteed to outlive `this`. const raw_ptr<WebContentsViewAndroid> web_contents_view_android_; @@ -106,10 +113,17 @@ // want to lead the user to the wrong entry. std::optional<int> destination_entry_index_; + // The actual implementation of the animation manager that manages the history + // navigation animation. One instance per gesture. + // // Only instantiated if the user gesture will trigger an animated session // history preview. Created when the eligible `OnGestureStarted()` arrives, // and destroyed when the animations finish (`OnAnimationsFinished()`). - std::unique_ptr<AnimationManagerImpl> impl_; + // + // `animator_` is only instantiated via `animator_factory_`. Tests can + // override the `animator_factory_` via `set_animator_factory_for_testing()`. + std::unique_ptr<BackForwardTransitionAnimator> animator_; + std::unique_ptr<BackForwardTransitionAnimator::Factory> animator_factory_; }; } // namespace content
diff --git a/content/browser/navigation_transitions/back_forward_transition_animator.cc b/content/browser/navigation_transitions/back_forward_transition_animator.cc new file mode 100644 index 0000000..ac2a0ab --- /dev/null +++ b/content/browser/navigation_transitions/back_forward_transition_animator.cc
@@ -0,0 +1,314 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/navigation_transitions/back_forward_transition_animator.h" + +#include "content/browser/navigation_transitions/back_forward_transition_animation_manager_android.h" +#include "content/browser/renderer_host/render_widget_host_impl.h" +#include "content/browser/renderer_host/render_widget_host_view_android.h" +#include "content/browser/web_contents/web_contents_view_android.h" +#include "content/public/browser/navigation_handle.h" + +namespace content { + +namespace { + +using HistoryNavType = BackForwardTransitionAnimationManager::NavigationType; +using SwipeEdge = ui::BackGestureEventSwipeEdge; + +} // namespace + +std::unique_ptr<BackForwardTransitionAnimator> +BackForwardTransitionAnimator::Factory::Create( + WebContentsViewAndroid* web_contents_view_android, + NavigationControllerImpl* controller, + const ui::BackGestureEvent& gesture, + HistoryNavType nav_type, + SwipeEdge edge, + BackForwardTransitionAnimationManagerAndroid* animation_manager) { + return base::WrapUnique(new BackForwardTransitionAnimator( + web_contents_view_android, controller, gesture, nav_type, edge, + animation_manager)); +} + +BackForwardTransitionAnimator::BackForwardTransitionAnimator( + WebContentsViewAndroid* web_contents_view_android, + NavigationControllerImpl* controller, + const ui::BackGestureEvent& gesture, + HistoryNavType nav_type, + SwipeEdge edge, + BackForwardTransitionAnimationManagerAndroid* animation_manager) + : nav_type_(nav_type), + edge_(edge), + animation_manager_(animation_manager), + latest_progress_gesture_(gesture) { + CHECK_EQ(nav_type_, HistoryNavType::kBackward); + CHECK_EQ(edge_, SwipeEdge::LEFT); + // TODO(https://crbug.com/1509888): Directly advance to the start state. +} + +BackForwardTransitionAnimator::~BackForwardTransitionAnimator() { + // TODO(https://crbug.com/1509888): + // - Reset the transformation on WCVA::parent_for_web_page_widgets_; + // - Remove UIResource for the screenshot; + // - Detach and destroy the screenshot layer. +} + +void BackForwardTransitionAnimator::OnGestureProgressed( + const ui::BackGestureEvent& gesture) { + CHECK_GE(gesture.progress(), 0.f); + CHECK_LE(gesture.progress(), 1.f); + + latest_progress_gesture_ = gesture; + + // TODO(https://crbug.com/1509888): + // - Ask physics model for transforms. + // - Set the layers' transforms per `result`. + // - Tick `effect_` with a fitted timestamp. +} + +void BackForwardTransitionAnimator::OnGestureCancelled() { + // TODO(https://crbug.com/1509888): Advance to displaying the cancel + // animation. +} + +void BackForwardTransitionAnimator::OnGestureInvoked() { + // TODO(https://crbug.com/1509888): Set the request ID immediately after + // calling `NavigationController::GoToIndex()`. After GoToIndex(): + // - If the controller doesn't have a pending entry, then we must have failed + // creating a `NavigationRequest`. Play the cancel animation. + // - If the primary `FrameTreeNode` has a `NavigationRequest`, set its ID to + // `navigation_request_id_`. If the main frame is navigating away, we will + // listen to the request of the main frame. + // - TODO(https://crbug.com/1517736) Else, traverse the entire `FrameTree` and + // collect all the navigation requests . + // + // TODO(crbug.com/1515916): Handle the subframe navigations where we have + // multiple navigation requests for the subframes. Fow now the subframe + // navigations are implicitly not animated because we don't capture + // screenshots for subframe navigations. + + // TODO(https://crbug.com/1509888): Advance to displaying the invoke + // animation. +} + +void BackForwardTransitionAnimator::OnRenderWidgetHostViewSwapped( + RenderWidgetHost* old_widget_host, + RenderWidgetHost* new_widget_host) { + auto* old_view = + static_cast<RenderWidgetHostViewAndroid*>(old_widget_host->GetView()); + if (old_view) { + // TODO(https://crbug.com/1488075): There might be a visual glitch if the + // old page is unloaded while we are still displaying the invoke animation. + // For now, make a deep copy of the old surface layer from `old_rwhva` and + // put the deep copy on top of the `WCVA::parent_for_web_page_widgets_`. + // + // Ideally, we need a way to preserve a minimal visual state of the old + // page. + } else { + // If we do a back navigation from a crashed page, we won't have an + // `old_view`. + // + // TODO(https://crbug.com/1488075): The Clank's interstitial page isn't + // drawn by `old_view`. We need to address as part of "navigating from NTP" + // animation. + } + + // We must have a live new widget. + CHECK(new_widget_host); + // `render_frame_metadata_provider()` is guaranteed non-null. + std::optional<viz::LocalSurfaceId> last_frame_local_surface_id = + static_cast<RenderWidgetHostImpl*>(new_widget_host) + ->render_frame_metadata_provider() + ->LastRenderFrameMetadata() + .local_surface_id; + auto* new_view = + static_cast<RenderWidgetHostViewBase*>(new_widget_host->GetView()); + if (last_frame_local_surface_id.has_value() && + last_frame_local_surface_id.value().is_valid() && + last_frame_local_surface_id.value().embed_token() == + new_view->GetLocalSurfaceId().embed_token() && + last_frame_local_surface_id.value().IsSameOrNewerThan( + new_view->GetLocalSurfaceId())) { + // This can happen where the renderer's main thread is very busy to reply + // `DidCommitNavigation()` back to the browser, but viz has already + // activated the first frame. Because the browser hasn't received the + // `DidCommitNavigation()` message, this animation manager hasn't subscribed + // to the new widget host, therefore missed out on the first + // `OnRenderFrameMetadataChangedAfterActivation()`. The screenshot will stay + // until the next `OnRenderFrameMetadataChangedAfterActivation()` + // notification. + // + // In this case we inspect the `LocalSurfaceId` of activated frame. If the + // ID is greater than what the browser is embedding, we know viz has already + // activated a frame. We don't need to subscribe to the new widget host + // for `OnRenderFrameMetadataChangedAfterActivation()` at all. + CHECK(!viz_has_activated_first_frame_); + viz_has_activated_first_frame_ = true; + return; + } + + // We subscribe to `new_widget_host` to get notified when the new renderer + // draws a new frame, so we can start cross-fading from the preview screenshot + // to the new page's live content. + CHECK(!new_render_widget_host_); + new_render_widget_host_ = RenderWidgetHostImpl::From(new_widget_host); + new_render_widget_host_->AddObserver(this); + new_render_widget_host_->render_frame_metadata_provider()->AddObserver(this); +} + +// This is only called after we subscribe to the new `RenderWidgetHost` in +// `OnRenderWidgetHostViewSwapped()`, meaning this method, just like +// `OnRenderWidgetHostViewSwapped()`, won't be called for 204/205/Download +// navigations, and won't be called if the navigation is cancelled. +// +// The manager won't be notified by the +// `OnRenderFrameMetadataChangedAfterActivation()`s that arrive earlier than +// `DidCommitNavigation()` either if the renderer is too busy to reply the +// DidCommit message while viz has already activated a new frame for the new +// page. See `OnRenderWidgetHostViewSwapped()` on how we guard this case. +void BackForwardTransitionAnimator::OnRenderFrameMetadataChangedAfterActivation( + base::TimeTicks activation_time) { + // `OnRenderWidgetHostViewSwapped()` is the prerequisite for this API. + CHECK(new_render_widget_host_); + + // `DidFinishNavigation()` must have been called, because the swap of + // `RenderWidgetHostView`s and `DidFinishNavigation()` happen in the same + // atomic callstack (all part of the `DidCommitNavigation`). + // + // The navigation must have successfully committed, resulting us swapping the + // `RenderWidgetHostView`s thus getting this notification. + CHECK_EQ(navigation_state_, NavigationTerminalState::kCommitted); + + CHECK(!viz_has_activated_first_frame_) + << "OnRenderFrameMetadataChangedAfterActivation can only be called once."; + viz_has_activated_first_frame_ = true; + + // No longer interested in any other compositor frame submission + // notifications. We can safely dismiss the previewed screenshot now. + new_render_widget_host_->render_frame_metadata_provider()->RemoveObserver( + this); + new_render_widget_host_->RemoveObserver(this); + new_render_widget_host_ = nullptr; + + // TODO(https://crbug.com/1509888): Advance to the next state to display the + // cross-fade animation. +} + +void BackForwardTransitionAnimator::OnRootWindowVisibilityChanged( + bool visible) { + if (!visible) { + ui::WindowAndroid* window_android = + animation_manager_->web_contents_view_android() + ->GetTopLevelNativeWindow(); + CHECK(window_android); + window_android->RemoveObserver(this); + + ui::WindowAndroidCompositor* compositor = window_android->GetCompositor(); + CHECK(compositor); + + animation_manager_->OnAnimationsFinished(); + } +} + +void BackForwardTransitionAnimator::OnDetachCompositor() { + ui::WindowAndroid* window_android = + animation_manager_->web_contents_view_android() + ->GetTopLevelNativeWindow(); + window_android->RemoveObserver(this); + + ui::WindowAndroidCompositor* compositor = window_android->GetCompositor(); + CHECK(compositor); + + animation_manager_->OnAnimationsFinished(); +} + +void BackForwardTransitionAnimator::OnAnimate( + base::TimeTicks frame_begin_time) { + // TODO(https://crbug.com/1509888): Implement this. + // + // if (crossfade) { Tick `effect_` } + // else { ask `physics_model_` to compute the offsets } + // + // if (done) { advance to next state } + // else { WindowAndroid::SetNeedsAnimate } +} + +void BackForwardTransitionAnimator::DidFinishNavigation( + NavigationHandle* navigation_handle) { + if (!primary_main_frame_navigation_request_id_of_gesture_nav_.has_value()) { + // This accounts for when the user is in the middle of a swipe but a + // navigation occurs. While the user is swiping, the current page is + // partially out of the viewport. Since a navigation has just committed in + // the browser, we must recenter the current page. + // + // TODO(https://crbug.com/1509888): + // - Advance to the `kDisplayingCancelAnimation`. + // - Also put the screenshot back to it's navigation entry. + return; + } + if (primary_main_frame_navigation_request_id_of_gesture_nav_.value() != + navigation_handle->GetNavigationId()) { + // Ignore any other request's destruction. We are only interested in the + // primary main frame's request created by this animation manager, as a + // result of a user-initiated session history navigation. + return; + } + + CHECK_EQ(navigation_state_, NavigationTerminalState::kNotSet) + << "DidFinishNavigation can only be called once. We might have observed " + "the wrong navigation request."; + + navigation_state_ = navigation_handle->HasCommitted() + ? NavigationTerminalState::kCommitted + : NavigationTerminalState::kCancelled; + WebContentsObserver::Observe(nullptr); + + // TODO(https://crbug.com/1509888): OnDidFinishNavigation on physics model. + + if (navigation_handle->IsErrorPage()) { + CHECK_EQ(navigation_state_, NavigationTerminalState::kCommitted); + // TODO(https://crbug.com/1509887): Implement a different UX if we decide + // not show the animation at all (i.e. abort animation early when we + // receive the response header). + } else { + if (UNLIKELY(navigation_state_ == NavigationTerminalState::kCancelled)) { + // 204/205/Download, or the ongoing navigation is cancelled. We need to + // animate the old page back. + // + // TODO(https://crbug.com/1509886): We might need a better UX than just + // display the cancel animation. + // + // TODO(https://crbug.com/1509888): Manually advance to the cancel state, + // since the gesture navigation is being cancelled, meaning this animation + // manager won't receive a `OnGestureCancelled()`. + } + } + // TODO(https://crbug.com/1519149): Handle the cross-origin server redirect. + // We cannot show a cross-origin fullscreen overlay of a.com if a.com redirect + // the user to b.com. +} + +void BackForwardTransitionAnimator::RenderWidgetHostDestroyed( + RenderWidgetHost* widget_host) { + if (widget_host == new_render_widget_host_) { + // Our new widget host is about to be destroyed. This can happen for a + // client redirect, where we never get the + // `OnRenderFrameMetadataChangedAfterActivation()` of any frame of a + // committed renderer. The screenshot isn't dismissed even after the gesture + // navigation is committed. + // + // In such cases we simply advance to play the cross-fade from the + // screenshot to whichever surface underneath the screenshot. + // + // TODO(https://crbug.com/1509888): Also CHECK `state_` that `this` is + // waiting for new frame submissions. + CHECK_EQ(navigation_state_, NavigationTerminalState::kCommitted); + new_render_widget_host_ = nullptr; + // TODO(https://crbug.com/1509888): Advance to play the cross-fade + // animation. + } +} + +} // namespace content
diff --git a/content/browser/navigation_transitions/back_forward_transition_animator.h b/content/browser/navigation_transitions/back_forward_transition_animator.h new file mode 100644 index 0000000..dc040c70 --- /dev/null +++ b/content/browser/navigation_transitions/back_forward_transition_animator.h
@@ -0,0 +1,141 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_NAVIGATION_TRANSITIONS_BACK_FORWARD_TRANSITION_ANIMATOR_H_ +#define CONTENT_BROWSER_NAVIGATION_TRANSITIONS_BACK_FORWARD_TRANSITION_ANIMATOR_H_ + +#include "content/public/browser/back_forward_transition_animation_manager.h" +#include "content/public/browser/render_frame_metadata_provider.h" +#include "content/public/browser/render_widget_host_observer.h" +#include "content/public/browser/web_contents_observer.h" +#include "ui/android/window_android_observer.h" +#include "ui/events/back_gesture_event.h" + +namespace content { + +class NavigationControllerImpl; +class WebContentsViewAndroid; +class BackForwardTransitionAnimationManagerAndroid; +class RenderWidgetHostImpl; + +// This class listens to gesture events for navigating the session history and +// updates the UI in response. It is 1:1 with a single gesture, i.e. each time +// the user touches the screen to start a gesture a new instance is created. +class CONTENT_EXPORT BackForwardTransitionAnimator + : public RenderFrameMetadataProvider::Observer, + public ui::WindowAndroidObserver, + public WebContentsObserver, + public RenderWidgetHostObserver { + public: + // To create the `BackForwardTransitionAnimator`. Tests can override this + // factory to supply a customized version of `BackForwardTransitionAnimator`. + class Factory { + public: + Factory() = default; + Factory(const Factory&) = delete; + Factory& operator=(const Factory&) = delete; + virtual ~Factory() = default; + + virtual std::unique_ptr<BackForwardTransitionAnimator> Create( + WebContentsViewAndroid* web_contents_view_android, + NavigationControllerImpl* controller, + const ui::BackGestureEvent& gesture, + BackForwardTransitionAnimationManager::NavigationType nav_type, + ui::BackGestureEventSwipeEdge edge, + BackForwardTransitionAnimationManagerAndroid* animation_manager); + }; + + BackForwardTransitionAnimator(const BackForwardTransitionAnimator&) = delete; + BackForwardTransitionAnimator& operator=( + const BackForwardTransitionAnimator&) = delete; + ~BackForwardTransitionAnimator() override; + + // Mirrors the APIs on `BackForwardTransitionAnimationManager`. + void OnGestureProgressed(const ui::BackGestureEvent& gesture); + void OnGestureCancelled(); + void OnGestureInvoked(); + void OnRenderWidgetHostViewSwapped(RenderWidgetHost* old_widget_host, + RenderWidgetHost* new_widget_host); + + protected: + BackForwardTransitionAnimator( + WebContentsViewAndroid* web_contents_view_android, + NavigationControllerImpl* controller, + const ui::BackGestureEvent& gesture, + BackForwardTransitionAnimationManager::NavigationType nav_type, + ui::BackGestureEventSwipeEdge edge, + BackForwardTransitionAnimationManagerAndroid* animation_manager); + + // `RenderFrameMetadataProvider::Observer`: + void OnRenderFrameMetadataChangedBeforeActivation( + const cc::RenderFrameMetadata& metadata) override {} + void OnRenderFrameMetadataChangedAfterActivation( + base::TimeTicks activation_time) override; + void OnRenderFrameSubmission() override {} + void OnLocalSurfaceIdChanged( + const cc::RenderFrameMetadata& metadata) override {} + + // `ui::WindowAndroidObserver`: + void OnRootWindowVisibilityChanged(bool visible) override; + void OnAttachCompositor() override {} + void OnDetachCompositor() override; + void OnAnimate(base::TimeTicks frame_begin_time) override; + void OnActivityStopped() override {} + void OnActivityStarted() override {} + + // `WebContentsObserver`: + void DidFinishNavigation(NavigationHandle* navigation_handle) override; + + // `RenderWidgetHostObserver`: + void RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) override; + + private: + const BackForwardTransitionAnimationManager::NavigationType nav_type_; + const ui::BackGestureEventSwipeEdge edge_; + + // The manager back-pointer. Guaranteed to outlive the impl. + const raw_ptr<BackForwardTransitionAnimationManagerAndroid> + animation_manager_; + + // Tracks the `NavigationRequest` created by the gesture back navigation of a + // primary main frame. + std::optional<int64_t> + primary_main_frame_navigation_request_id_of_gesture_nav_; + + enum class NavigationTerminalState { + // Navigation has not begun, or not yet committed. + kNotSet = 0, + // The navigation has either committed to a new doc, or an error page. + kCommitted, + // The navigation has been cancelled (replaced by a secondary navigation, or + // aborted by the user). + kCancelled, + }; + // Set via `DidFinishNavigation()`. Records if the navigation has successfully + // committed. + NavigationTerminalState navigation_state_ = NavigationTerminalState::kNotSet; + + // If viz has already activated a frame for the new page before the invoke + // animation finishes, we set this bit so we can start the crossfade animation + // immediately after the invoke animation. + bool viz_has_activated_first_frame_ = false; + + // The widget host for the new page. Only set after the new page's widget is + // swapped in. This class listens to the first + // `OnRenderFrameMetadataChangedAfterActivation()` on the new widget host. + // This first notification signals that viz has processed a frame submitted by + // the renderer, at which we can safely cross-fade from the screenshot to the + // new page. + // + // Stays null for 204/205/Download, or for cancelled navigations. Also reset + // to null when the tracked `RenderWidgetHost` is destroyed. + raw_ptr<RenderWidgetHostImpl> new_render_widget_host_; + + // Set by the latest `OnGestureProgressed()`. + ui::BackGestureEvent latest_progress_gesture_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_NAVIGATION_TRANSITIONS_BACK_FORWARD_TRANSITION_ANIMATOR_H_
diff --git a/content/browser/renderer_host/README.md b/content/browser/renderer_host/README.md index 290e1d9..0dc10fe4 100644 --- a/content/browser/renderer_host/README.md +++ b/content/browser/renderer_host/README.md
@@ -35,7 +35,7 @@ For diagrams and explanations of how those classes fit with each other, see also [this documentation](https://www.chromium.org/developers/design-documents/oop-iframes/) -and [docs/frame_trees.md](https://source.chromium.org/chromium/chromium/src/+/main:docs/frame_trees.md). +and [docs/frame_trees.md](https://chromium.googlesource.com/chromium/src/+/main/docs/frame_trees.md). ### Connections between browser and renderer/GPU processes, process-related code Represents child processes (e.g., renderers, GPU, etc) and their connection to @@ -58,8 +58,8 @@ history items (for pages), made up of a tree of session history items (for frames). -See also [docs/navigation.md](https://source.chromium.org/chromium/chromium/src/+/main:docs/navigation.md) -and [docs/session_history.md](https://source.chromium.org/chromium/chromium/src/+/main:docs/session_history.md). +See also [docs/navigation.md](https://chromium.googlesource.com/chromium/src/+/main/docs/navigation.md) +and [docs/session_history.md](https://chromium.googlesource.com/chromium/src/+/main/docs/session_history.md). ### Compositing, input, display Coordinates handling of input, display, and compositing between the browser, @@ -86,4 +86,4 @@ Code in this directory can't call up to the WebContents "layer," except through delegate interfaces (e.g. RenderFrameHostDelegate). This is to separate out code that deals with the renderer process and code that deals with the tab. -This is enfoced by the [DEPS](https://source.chromium.org/chromium/chromium/src/+/main:content/browser/renderer_host/DEPS). \ No newline at end of file +This is enforced by the [DEPS](https://source.chromium.org/chromium/chromium/src/+/main:content/browser/renderer_host/DEPS).
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index 8298cc2a..d13e74f 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -603,7 +603,7 @@ MediaStreamRequestType request_type, const StreamControls& stream_controls, MediaDeviceSaltAndOrigin salt_and_origin, - DeviceStoppedCallback device_stopped_cb = DeviceStoppedCallback()) + DeviceStoppedCallback device_stopped_callback = DeviceStoppedCallback()) : requesting_render_frame_host_id(requesting_render_frame_host_id), requester_id(requester_id), page_request_id(page_request_id), @@ -611,7 +611,7 @@ audio_stream_selection_info_ptr( std::move(audio_stream_selection_info_ptr)), salt_and_origin(std::move(salt_and_origin)), - device_stopped_cb(std::move(device_stopped_cb)), + device_stopped_callback(std::move(device_stopped_callback)), should_stop_in_future_( /*size=*/static_cast<size_t>(MediaStreamType::NUM_MEDIA_TYPES), /*value=*/false), @@ -964,7 +964,7 @@ blink::mojom::StreamDevicesSet stream_devices_set; blink::mojom::StreamDevicesSet old_stream_devices_set; - DeviceStoppedCallback device_stopped_cb; + DeviceStoppedCallback device_stopped_callback; std::unique_ptr<MediaStreamUIProxy> ui_proxy; @@ -1057,7 +1057,7 @@ StreamSelectionInfoPtr audio_stream_selection_info_ptr, const StreamControls& controls, MediaDeviceSaltAndOrigin salt_and_origin, - MediaAccessRequestCallback media_access_request_cb) + MediaAccessRequestCallback media_access_request_callback) : DeviceRequest(requesting_render_frame_host_id, requester_id, page_request_id, @@ -1066,7 +1066,8 @@ blink::MEDIA_DEVICE_ACCESS, controls, std::move(salt_and_origin)), - media_access_request_cb_(std::move(media_access_request_cb)) {} + media_access_request_callback_( + std::move(media_access_request_callback)) {} ~MediaAccessRequest() override { DCHECK_CURRENTLY_ON(BrowserThread::IO); } @@ -1074,19 +1075,19 @@ const std::string& label, const blink::mojom::StreamDevicesSet& stream_devices_set) override { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(media_access_request_cb_); + DCHECK(media_access_request_callback_); SendLogMessage(base::StringPrintf( "FinalizeMediaAccessRequest({label=%s}, {requester_id=" "%d}, {request_type=%s})", label.c_str(), requester_id, RequestTypeToString(request_type()))); - std::move(media_access_request_cb_) + std::move(media_access_request_callback_) .Run(stream_devices_set, std::move(ui_proxy)); } void FinalizeRequestFailed(MediaStreamRequestResult) override { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(media_access_request_cb_); - std::move(media_access_request_cb_) + DCHECK(media_access_request_callback_); + std::move(media_access_request_callback_) .Run(/*stream_devices_set=*/blink::mojom::StreamDevicesSet(), std::move(ui_proxy)); } @@ -1098,7 +1099,7 @@ // Callback to the requester which audio/video devices have been selected. // It can be null if the requester has no interest to know the result. - MediaAccessRequestCallback media_access_request_cb_; + MediaAccessRequestCallback media_access_request_callback_; base::WeakPtrFactory<DeviceRequest> weak_factory_{this}; }; @@ -1114,12 +1115,12 @@ MediaStreamRequestType request_type, const StreamControls& controls, MediaDeviceSaltAndOrigin salt_and_origin, - DeviceStoppedCallback device_stopped_cb, - DeviceChangedCallback device_changed_cb, - DeviceRequestStateChangeCallback device_request_state_change_cb, + DeviceStoppedCallback device_stopped_callback, + DeviceChangedCallback device_changed_callback, + DeviceRequestStateChangeCallback device_request_state_change_callback, DeviceCaptureConfigurationChangeCallback - device_capture_configuration_change_cb, - DeviceCaptureHandleChangeCallback device_capture_handle_change_cb, + device_capture_configuration_change_callback, + DeviceCaptureHandleChangeCallback device_capture_handle_change_callback, ZoomLevelChangeCallback zoom_level_change_callback) : DeviceRequest(requesting_render_frame_host_id, requester_id, @@ -1129,19 +1130,19 @@ request_type, controls, std::move(salt_and_origin), - std::move(device_stopped_cb)), - device_changed_cb_(std::move(device_changed_cb)), - device_request_state_change_cb_( - std::move(device_request_state_change_cb)), - device_capture_configuration_change_cb_( - std::move(device_capture_configuration_change_cb)), - device_capture_handle_change_cb_( - std::move(device_capture_handle_change_cb)), + std::move(device_stopped_callback)), + device_changed_callback_(std::move(device_changed_callback)), + device_request_state_change_callback_( + std::move(device_request_state_change_callback)), + device_capture_configuration_change_callback_( + std::move(device_capture_configuration_change_callback)), + device_capture_handle_change_callback_( + std::move(device_capture_handle_change_callback)), zoom_level_change_callback_(std::move(zoom_level_change_callback)) {} void FinalizeChangeDevice(const std::string& label) override { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(device_changed_cb_); + DCHECK(device_changed_callback_); DCHECK_EQ(1u, old_stream_devices_set.stream_devices.size()); DCHECK_EQ(1u, stream_devices_set.stream_devices.size()); @@ -1181,12 +1182,12 @@ old_devices_of_new_device_type.pop_back(); } - device_changed_cb_.Run(label, old_device, new_device); + device_changed_callback_.Run(label, old_device, new_device); } for (const auto& old_media_stream_devices : old_devices_by_type) { for (const auto& old_device : old_media_stream_devices) { - device_changed_cb_.Run(label, old_device, MediaStreamDevice()); + device_changed_callback_.Run(label, old_device, MediaStreamDevice()); } } } @@ -1197,7 +1198,7 @@ blink::mojom::MediaStreamStateChange new_state) override { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (!device_request_state_change_cb_) { + if (!device_request_state_change_callback_) { return; } @@ -1213,7 +1214,7 @@ } const blink::MediaStreamDevice& device = device_ptr->value(); if (DesktopMediaID::Parse(device.id) == media_id) { - device_request_state_change_cb_.Run(label, device, new_state); + device_request_state_change_callback_.Run(label, device, new_state); } } } @@ -1222,8 +1223,8 @@ void OnCaptureConfigurationChanged( const std::string& label, const blink::MediaStreamDevice& device) override { - if (device_capture_configuration_change_cb_) { - device_capture_configuration_change_cb_.Run(label, device); + if (device_capture_configuration_change_callback_) { + device_capture_configuration_change_callback_.Run(label, device); } } @@ -1258,8 +1259,8 @@ device->display_media_info->capture_handle = capture_handle.Clone(); - if (device_capture_handle_change_cb_) { - device_capture_handle_change_cb_.Run(label, *device); + if (device_capture_handle_change_callback_) { + device_capture_handle_change_callback_.Run(label, *device); } } @@ -1298,11 +1299,11 @@ #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) private: - DeviceChangedCallback device_changed_cb_; - DeviceRequestStateChangeCallback device_request_state_change_cb_; + DeviceChangedCallback device_changed_callback_; + DeviceRequestStateChangeCallback device_request_state_change_callback_; DeviceCaptureConfigurationChangeCallback - device_capture_configuration_change_cb_; - DeviceCaptureHandleChangeCallback device_capture_handle_change_cb_; + device_capture_configuration_change_callback_; + DeviceCaptureHandleChangeCallback device_capture_handle_change_callback_; ZoomLevelChangeCallback zoom_level_change_callback_; }; @@ -1317,36 +1318,37 @@ StreamSelectionInfoPtr audio_stream_selection_info_ptr, const StreamControls& controls, MediaDeviceSaltAndOrigin salt_and_origin, - DeviceStoppedCallback device_stopped_cb, - DeviceChangedCallback device_changed_cb, - DeviceRequestStateChangeCallback device_request_state_change_cb, + DeviceStoppedCallback device_stopped_callback, + DeviceChangedCallback device_changed_callback, + DeviceRequestStateChangeCallback device_request_state_change_callback, DeviceCaptureConfigurationChangeCallback - device_capture_configuration_change_cb, - DeviceCaptureHandleChangeCallback device_capture_handle_change_cb, + device_capture_configuration_change_callback, + DeviceCaptureHandleChangeCallback device_capture_handle_change_callback, ZoomLevelChangeCallback zoom_level_change_callback, - GenerateStreamsCallback generate_streams_cb) - : CreateDeviceRequest(requesting_render_frame_host_id, - requester_id, - page_request_id, - user_gesture, - std::move(audio_stream_selection_info_ptr), - blink::MEDIA_GENERATE_STREAM, - controls, - std::move(salt_and_origin), - std::move(device_stopped_cb), - std::move(device_changed_cb), - std::move(device_request_state_change_cb), - std::move(device_capture_configuration_change_cb), - std::move(device_capture_handle_change_cb), - std::move(zoom_level_change_callback)), - generate_streams_cb_(std::move(generate_streams_cb)) { - DCHECK(generate_streams_cb_); + GenerateStreamsCallback generate_streams_callback) + : CreateDeviceRequest( + requesting_render_frame_host_id, + requester_id, + page_request_id, + user_gesture, + std::move(audio_stream_selection_info_ptr), + blink::MEDIA_GENERATE_STREAM, + controls, + std::move(salt_and_origin), + std::move(device_stopped_callback), + std::move(device_changed_callback), + std::move(device_request_state_change_callback), + std::move(device_capture_configuration_change_callback), + std::move(device_capture_handle_change_callback), + std::move(zoom_level_change_callback)), + generate_streams_callback_(std::move(generate_streams_callback)) { + DCHECK(generate_streams_callback_); } ~GenerateStreamsRequest() override { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (generate_streams_cb_) { - std::move(generate_streams_cb_) + if (generate_streams_callback_) { + std::move(generate_streams_callback_) .Run(MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, /*label=*/std::string(), /*stream_devices_set=*/nullptr, @@ -1356,16 +1358,16 @@ void PanTiltZoomPermissionChecked(const std::string& label, bool pan_tilt_zoom_allowed) override { - DCHECK(generate_streams_cb_); - std::move(generate_streams_cb_) + DCHECK(generate_streams_callback_); + std::move(generate_streams_callback_) .Run(MediaStreamRequestResult::OK, label, stream_devices_set.Clone(), pan_tilt_zoom_allowed); } void FinalizeRequestFailed(MediaStreamRequestResult result) override { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(generate_streams_cb_); - std::move(generate_streams_cb_) + DCHECK(generate_streams_callback_); + std::move(generate_streams_callback_) .Run(result, /*label=*/std::string(), /*stream_devices_set=*/nullptr, /*pan_tilt_zoom_allowed=*/false); @@ -1376,7 +1378,7 @@ return weak_factory_.GetWeakPtr(); } - GenerateStreamsCallback generate_streams_cb_; + GenerateStreamsCallback generate_streams_callback_; base::WeakPtrFactory<DeviceRequest> weak_factory_{this}; }; @@ -1388,43 +1390,44 @@ int requester_id, int page_request_id, MediaDeviceSaltAndOrigin salt_and_origin, - DeviceStoppedCallback device_stopped_cb, - DeviceChangedCallback device_changed_cb, - DeviceRequestStateChangeCallback device_request_state_change_cb, + DeviceStoppedCallback device_stopped_callback, + DeviceChangedCallback device_changed_callback, + DeviceRequestStateChangeCallback device_request_state_change_callback, DeviceCaptureConfigurationChangeCallback - device_capture_configuration_change_cb, - DeviceCaptureHandleChangeCallback device_capture_handle_change_cb, + device_capture_configuration_change_callback, + DeviceCaptureHandleChangeCallback device_capture_handle_change_callback, ZoomLevelChangeCallback zoom_level_change_callback, - GetOpenDeviceCallback get_open_device_cb) - : CreateDeviceRequest(requesting_render_frame_host_id, - requester_id, - page_request_id, - /*user_gesture=*/false, - /*audio_stream_selection_info_ptr=*/nullptr, - blink::MEDIA_GET_OPEN_DEVICE, - StreamControls(), - std::move(salt_and_origin), - std::move(device_stopped_cb), - std::move(device_changed_cb), - std::move(device_request_state_change_cb), - std::move(device_capture_configuration_change_cb), - std::move(device_capture_handle_change_cb), - std::move(zoom_level_change_callback)), - get_open_device_cb_(std::move(get_open_device_cb)) { - DCHECK(get_open_device_cb_); + GetOpenDeviceCallback get_open_device_callback) + : CreateDeviceRequest( + requesting_render_frame_host_id, + requester_id, + page_request_id, + /*user_gesture=*/false, + /*audio_stream_selection_info_ptr=*/nullptr, + blink::MEDIA_GET_OPEN_DEVICE, + StreamControls(), + std::move(salt_and_origin), + std::move(device_stopped_callback), + std::move(device_changed_callback), + std::move(device_request_state_change_callback), + std::move(device_capture_configuration_change_callback), + std::move(device_capture_handle_change_callback), + std::move(zoom_level_change_callback)), + get_open_device_callback_(std::move(get_open_device_callback)) { + DCHECK(get_open_device_callback_); } ~GetOpenDeviceRequest() override { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (get_open_device_cb_) { - std::move(get_open_device_cb_) + if (get_open_device_callback_) { + std::move(get_open_device_callback_) .Run(MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, nullptr); } } void PanTiltZoomPermissionChecked(const std::string& label, bool pan_tilt_zoom_allowed) override { - DCHECK(get_open_device_cb_); + DCHECK(get_open_device_callback_); // GetOpenDevice is only available with exactly one stream. DCHECK_EQ(stream_devices_set.stream_devices.size(), 1u); const blink::mojom::StreamDevices& stream_devices = @@ -1437,15 +1440,15 @@ ? stream_devices.video_device.value() : stream_devices.audio_device.value(); - std::move(get_open_device_cb_) + std::move(get_open_device_callback_) .Run(MediaStreamRequestResult::OK, GetOpenDeviceResponse::New(label, device, pan_tilt_zoom_allowed)); } void FinalizeRequestFailed(MediaStreamRequestResult result) override { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(get_open_device_cb_); - std::move(get_open_device_cb_).Run(result, /*response=*/nullptr); + DCHECK(get_open_device_callback_); + std::move(get_open_device_callback_).Run(result, /*response=*/nullptr); } private: @@ -1459,7 +1462,7 @@ // MediaStreamRequestResult::OK. Otherwise, returns // MediaStreamRequestResult::INVALID_STATE along with std::nullopt instead of // a MediaStreamDevice. - GetOpenDeviceCallback get_open_device_cb_; + GetOpenDeviceCallback get_open_device_callback_; base::WeakPtrFactory<DeviceRequest> weak_factory_{this}; }; @@ -1472,8 +1475,8 @@ StreamSelectionInfoPtr audio_stream_selection_info_ptr, const StreamControls& controls, MediaDeviceSaltAndOrigin salt_and_origin, - DeviceStoppedCallback device_stopped_cb, - OpenDeviceCallback open_device_cb) + DeviceStoppedCallback device_stopped_callback, + OpenDeviceCallback open_device_callback) : DeviceRequest(requesting_render_frame_host_id, requester_id, page_request_id, @@ -1482,35 +1485,35 @@ blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY, controls, std::move(salt_and_origin), - std::move(device_stopped_cb)), - open_device_cb_(std::move(open_device_cb)) { - DCHECK(open_device_cb_); + std::move(device_stopped_callback)), + open_device_callback_(std::move(open_device_callback)) { + DCHECK(open_device_callback_); } ~OpenDeviceRequest() override { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (open_device_cb_) { - std::move(open_device_cb_) + if (open_device_callback_) { + std::move(open_device_callback_) .Run(/*success=*/false, std::string(), MediaStreamDevice()); } } void FinalizeRequest(const std::string& label) override { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(open_device_cb_); + DCHECK(open_device_callback_); SendLogMessage(base::StringPrintf( "FinalizeOpenDevice({label=%s}, {requester_id=" "%d}, {request_type=%s})", label.c_str(), requester_id, RequestTypeToString(request_type()))); - std::move(open_device_cb_) + std::move(open_device_callback_) .Run(/*success=*/true, label, blink::ToMediaStreamDevicesList(stream_devices_set).front()); } void FinalizeRequestFailed(MediaStreamRequestResult result) override { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(open_device_cb_); - std::move(open_device_cb_) + DCHECK(open_device_callback_); + std::move(open_device_callback_) .Run(/*success=*/false, /*label=*/std::string(), MediaStreamDevice()); } @@ -1522,7 +1525,7 @@ // This callback is only used by pepper and tries to open the device // identified by device_id. If it is opened successfully, it returns this // device. Otherwise, returns an empty device. - OpenDeviceCallback open_device_cb_; + OpenDeviceCallback open_device_callback_; base::WeakPtrFactory<DeviceRequest> weak_factory_{this}; }; @@ -1746,13 +1749,13 @@ MediaDeviceSaltAndOrigin salt_and_origin, bool user_gesture, StreamSelectionInfoPtr audio_stream_selection_info_ptr, - GenerateStreamsCallback generate_streams_cb, - DeviceStoppedCallback device_stopped_cb, - DeviceChangedCallback device_changed_cb, - DeviceRequestStateChangeCallback device_request_state_change_cb, + GenerateStreamsCallback generate_streams_callback, + DeviceStoppedCallback device_stopped_callback, + DeviceChangedCallback device_changed_callback, + DeviceRequestStateChangeCallback device_request_state_change_callback, DeviceCaptureConfigurationChangeCallback - device_capture_configuration_change_cb, - DeviceCaptureHandleChangeCallback device_capture_handle_change_cb, + device_capture_configuration_change_callback, + DeviceCaptureHandleChangeCallback device_capture_handle_change_callback, ZoomLevelChangeCallback zoom_level_change_callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); SendLogMessage(GetGenerateStreamsLogString(render_frame_host_id, requester_id, @@ -1761,13 +1764,13 @@ std::make_unique<GenerateStreamsRequest>( render_frame_host_id, requester_id, page_request_id, user_gesture, std::move(audio_stream_selection_info_ptr), controls, - std::move(salt_and_origin), std::move(device_stopped_cb), - std::move(device_changed_cb), - std::move(device_request_state_change_cb), - std::move(device_capture_configuration_change_cb), - std::move(device_capture_handle_change_cb), + std::move(salt_and_origin), std::move(device_stopped_callback), + std::move(device_changed_callback), + std::move(device_request_state_change_callback), + std::move(device_capture_configuration_change_callback), + std::move(device_capture_handle_change_callback), std::move(zoom_level_change_callback), - std::move(generate_streams_cb)); + std::move(generate_streams_callback)); DeviceRequests::const_iterator request_it = AddRequest(std::move(request)); const std::string& label = request_it->first; @@ -1802,13 +1805,13 @@ int requester_id, int page_request_id, MediaDeviceSaltAndOrigin salt_and_origin, - GetOpenDeviceCallback get_open_device_cb, - DeviceStoppedCallback device_stopped_cb, - DeviceChangedCallback device_changed_cb, - DeviceRequestStateChangeCallback device_request_state_change_cb, + GetOpenDeviceCallback get_open_device_callback, + DeviceStoppedCallback device_stopped_callback, + DeviceChangedCallback device_changed_callback, + DeviceRequestStateChangeCallback device_request_state_change_callback, DeviceCaptureConfigurationChangeCallback - device_capture_configuration_change_cb, - DeviceCaptureHandleChangeCallback device_capture_handle_change_cb, + device_capture_configuration_change_callback, + DeviceCaptureHandleChangeCallback device_capture_handle_change_callback, ZoomLevelChangeCallback zoom_level_change_callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(base::FeatureList::IsEnabled(features::kMediaStreamTrackTransfer)); @@ -1816,12 +1819,13 @@ std::unique_ptr<DeviceRequest> request = std::make_unique<GetOpenDeviceRequest>( render_frame_host_id, requester_id, page_request_id, - std::move(salt_and_origin), std::move(device_stopped_cb), - std::move(device_changed_cb), - std::move(device_request_state_change_cb), - std::move(device_capture_configuration_change_cb), - std::move(device_capture_handle_change_cb), - std::move(zoom_level_change_callback), std::move(get_open_device_cb)); + std::move(salt_and_origin), std::move(device_stopped_callback), + std::move(device_changed_callback), + std::move(device_request_state_change_callback), + std::move(device_capture_configuration_change_callback), + std::move(device_capture_handle_change_callback), + std::move(zoom_level_change_callback), + std::move(get_open_device_callback)); DeviceRequests::const_iterator request_it = AddRequest(std::move(request)); const std::string& new_label = request_it->first; @@ -2106,8 +2110,8 @@ // To ensure consistent behavior when sessions are closed, use the // stop callback to stop audio streams. if (blink::IsAudioInputMediaType(device.type) && - request->device_stopped_cb) { - request->device_stopped_cb.Run(labeled_request.first, device); + request->device_stopped_callback) { + request->device_stopped_callback.Run(labeled_request.first, device); } if (request->ui_proxy) { const DesktopMediaID media_id = DesktopMediaID::Parse(device.id); @@ -2127,8 +2131,8 @@ const std::string& device_id, MediaStreamType type, MediaDeviceSaltAndOrigin salt_and_origin, - OpenDeviceCallback open_device_cb, - DeviceStoppedCallback device_stopped_cb) { + OpenDeviceCallback open_device_callback, + DeviceStoppedCallback device_stopped_callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(type == MediaStreamType::DEVICE_AUDIO_CAPTURE || type == MediaStreamType::DEVICE_VIDEO_CAPTURE); @@ -2153,8 +2157,8 @@ auto request = std::make_unique<OpenDeviceRequest>( render_frame_host_id, requester_id, page_request_id, std::move(audio_stream_selection_info_ptr), controls, - std::move(salt_and_origin), std::move(device_stopped_cb), - std::move(open_device_cb)); + std::move(salt_and_origin), std::move(device_stopped_callback), + std::move(open_device_callback)); const std::string& label = AddRequest(std::move(request))->first; // Post a task and handle the request asynchronously. The reason is that the @@ -2208,8 +2212,8 @@ request->salt_and_origin, media_device_info.device_id); if (device.id == source_id && device.type == stream_type) { session_ids.push_back(device.session_id()); - if (request->device_stopped_cb) { - request->device_stopped_cb.Run(labeled_request.first, device); + if (request->device_stopped_callback) { + request->device_stopped_callback.Run(labeled_request.first, device); } } } @@ -3769,7 +3773,7 @@ label.c_str())); // Notify renderers that the devices in the stream will be stopped. - if (request->device_stopped_cb) { + if (request->device_stopped_callback) { for (const blink::mojom::StreamDevicesPtr& stream_devices_ptr : request->stream_devices_set.stream_devices) { const blink::mojom::StreamDevices& stream_devices = *stream_devices_ptr; @@ -3781,7 +3785,7 @@ continue; } const blink::MediaStreamDevice& device = device_ptr->value(); - request->device_stopped_cb.Run(label, device); + request->device_stopped_callback.Run(label, device); } } } @@ -4101,12 +4105,12 @@ label.c_str(), request->requester_id, RequestTypeToString(request->request_type()))); - MediaStreamUI::SourceCallback device_changed_cb; + MediaStreamUI::SourceCallback device_changed_callback; if (request->stream_controls().dynamic_surface_switching_requested && ChangeSourceSupported( blink::ToMediaStreamDevicesList(request->stream_devices_set)) && base::FeatureList::IsEnabled(features::kDesktopCaptureChangeSource)) { - device_changed_cb = base::BindRepeating( + device_changed_callback = base::BindRepeating( &MediaStreamManager::ChangeMediaStreamSourceFromBrowser, base::Unretained(this), label); } @@ -4135,7 +4139,7 @@ request->ui_proxy->OnStarted( base::BindOnce(&MediaStreamManager::StopMediaStreamFromBrowser, base::Unretained(this), label), - device_changed_cb, + device_changed_callback, base::BindOnce(&MediaStreamManager::OnMediaStreamUIWindowId, base::Unretained(this), request->video_type(), request->stream_devices_set.Clone()),
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h index d06054d8..86a3cb7 100644 --- a/content/browser/renderer_host/media/media_stream_manager.h +++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -215,13 +215,12 @@ // GenerateStream opens new media devices according to |controls|. It creates // a new request which is identified by a unique string that's returned to the - // caller. `render_frame_host_id` is used to determine - // where the infobar will appear to the user. |device_stopped_cb| is set to - // receive device stopped notifications. |device_changed_cb| is set to receive - // device changed notifications. |device_request_state_change_cb| is used to - // notify clients about request state changes. - // TODO(crbug.com/1288839): Package device-related callbacks into a single - // struct. + // caller. `render_frame_host_id` is used to determine where the infobar will + // appear to the user. |device_stopped_callback| is set to receive device + // stopped notifications. |device_changed_callback| is set to receive device + // changed notifications. |device_request_state_change_callback| is used to + // notify clients about request state changes. TODO(crbug.com/1288839): + // Package device-related callbacks into a single struct. void GenerateStreams( GlobalRenderFrameHostId render_frame_host_id, int requester_id, @@ -230,18 +229,18 @@ MediaDeviceSaltAndOrigin salt_and_origin, bool user_gesture, blink::mojom::StreamSelectionInfoPtr audio_stream_selection_info_ptr, - GenerateStreamsCallback generate_stream_cb, - DeviceStoppedCallback device_stopped_cb, - DeviceChangedCallback device_changed_cb, - DeviceRequestStateChangeCallback device_request_state_change_cb, + GenerateStreamsCallback generate_stream_callback, + DeviceStoppedCallback device_stopped_callback, + DeviceChangedCallback device_changed_callback, + DeviceRequestStateChangeCallback device_request_state_change_callback, DeviceCaptureConfigurationChangeCallback - device_capture_configuration_change_cb, - DeviceCaptureHandleChangeCallback device_capture_handle_change_cb, + device_capture_configuration_change_callback, + DeviceCaptureHandleChangeCallback device_capture_handle_change_callback, ZoomLevelChangeCallback zoom_level_change_callback); // Accesses an existing open device, identified by |device_session_id|, // and associates it with a new DeviceRequest. This device is then returned by - // invoking |get_open_device_cb| asynchronously. + // invoking |get_open_device_callback| asynchronously. void GetOpenDevice( const base::UnguessableToken& device_session_id, const base::UnguessableToken& transfer_id, @@ -249,13 +248,13 @@ int requester_id, int page_request_id, MediaDeviceSaltAndOrigin salt_and_origin, - GetOpenDeviceCallback get_open_device_cb, - DeviceStoppedCallback device_stopped_cb, - DeviceChangedCallback device_changed_cb, - DeviceRequestStateChangeCallback device_request_state_change_cb, + GetOpenDeviceCallback get_open_device_callback, + DeviceStoppedCallback device_stopped_callback, + DeviceChangedCallback device_changed_callback, + DeviceRequestStateChangeCallback device_request_state_change_callback, DeviceCaptureConfigurationChangeCallback - device_capture_configuration_change_cb, - DeviceCaptureHandleChangeCallback device_capture_handle_change_cb, + device_capture_configuration_change_callback, + DeviceCaptureHandleChangeCallback device_capture_handle_change_callback, ZoomLevelChangeCallback zoom_level_change_callback); // Cancel an open request identified by |page_request_id| for the given frame. @@ -286,16 +285,16 @@ // Open a device identified by |device_id|. |type| must be either // MEDIA_DEVICE_AUDIO_CAPTURE or MEDIA_DEVICE_VIDEO_CAPTURE. - // |device_stopped_cb| is set to receive device stopped notifications. The - // request is identified using string returned to the caller. + // |device_stopped_callback| is set to receive device stopped notifications. + // The request is identified using string returned to the caller. void OpenDevice(GlobalRenderFrameHostId render_frame_host_id, int requester_id, int page_request_id, const std::string& device_id, blink::mojom::MediaStreamType type, MediaDeviceSaltAndOrigin salt_and_origin, - OpenDeviceCallback open_device_cb, - DeviceStoppedCallback device_stopped_cb); + OpenDeviceCallback open_device_callback, + DeviceStoppedCallback device_stopped_callback); // Find |device_id| in the list of |requests_|, and returns its session id, // or an empty base::UnguessableToken if not found. Must be called on the IO
diff --git a/content/browser/renderer_host/media/peer_connection_tracker_host.cc b/content/browser/renderer_host/media/peer_connection_tracker_host.cc index 3600c82f..8e8b7ae 100644 --- a/content/browser/renderer_host/media/peer_connection_tracker_host.cc +++ b/content/browser/renderer_host/media/peer_connection_tracker_host.cc
@@ -104,7 +104,7 @@ for (auto& observer : GetObserverList()) { observer.OnPeerConnectionAdded(frame_id_, info->lid, peer_pid_, url, - info->rtc_configuration, info->constraints); + info->rtc_configuration); } }
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index a82a50d..37b819d 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -13562,11 +13562,6 @@ accessibility_fatal_error_count_ = 0; UpdateIsolatableSandboxedIframeTracking(navigation_request); - - // After commit, the browser process's access of the features' state becomes - // read-only. (i.e. It can only get feature state, not set) - RuntimeFeatureStateDocumentData::CreateForCurrentDocument( - this, navigation_request->GetRuntimeFeatureStateContext()); } // TODO(arthursonzogni): Below, many NavigationRequest's objects are passed from @@ -13593,6 +13588,8 @@ // this frame embeds a subframe when that subframe navigates). required_csp_ = navigation_request->TakeRequiredCSP(); + // After commit, the browser process's access of the features' state becomes + // read-only. (i.e. It can only get feature state, not set) RuntimeFeatureStateDocumentData::CreateForCurrentDocument( this, navigation_request->GetRuntimeFeatureStateContext());
diff --git a/content/browser/renderer_host/spare_render_process_host_manager.h b/content/browser/renderer_host/spare_render_process_host_manager.h index 9d2ba05..b7ebfd3 100644 --- a/content/browser/renderer_host/spare_render_process_host_manager.h +++ b/content/browser/renderer_host/spare_render_process_host_manager.h
@@ -5,6 +5,8 @@ #ifndef CONTENT_BROWSER_RENDERER_HOST_SPARE_RENDER_PROCESS_HOST_MANAGER_H_ #define CONTENT_BROWSER_RENDERER_HOST_SPARE_RENDER_PROCESS_HOST_MANAGER_H_ +#include <optional> + #include "base/callback_list.h" #include "base/functional/callback.h" #include "base/memory/raw_ptr.h"
diff --git a/content/browser/tracing/tracing_end_to_end_browsertest.cc b/content/browser/tracing/tracing_end_to_end_browsertest.cc index 04f4c41..e74bbfc1 100644 --- a/content/browser/tracing/tracing_end_to_end_browsertest.cc +++ b/content/browser/tracing/tracing_end_to_end_browsertest.cc
@@ -550,11 +550,17 @@ std::vector<std::string>{"test_event"})); } -// The test fails on Android because Renderers can't connect to an arbitrary -// socket. -#if !BUILDFLAG(IS_ANDROID) // Tests that system tracing works from a sandboxed process (Renderer). -IN_PROC_BROWSER_TEST_F(SystemTracingEndToEndBrowserTest, PerformanceMark) { +// The test fails on Android because Renderers can't connect to an +// arbitrary socket. Flaky on Mac since the renderer doesn't connect on +// time. crbug.com/324063092 +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) +#define MAYBE_PerformanceMark DISABLED_PerformanceMark +#else +#define MAYBE_PerformanceMark PerformanceMark +#endif +IN_PROC_BROWSER_TEST_F(SystemTracingEndToEndBrowserTest, + MAYBE_PerformanceMark) { auto session = perfetto::Tracing::NewTrace(perfetto::kSystemBackend); session->Setup(base::test::DefaultTraceConfig("blink.user_timing", false)); base::RunLoop start_session; @@ -572,7 +578,8 @@ // connecting to the service), but it doesn't matter. We just want to make // sure that at least one of them is there. std::vector<char> trace; - for (size_t i = 0; i < 100; i++) { + size_t i = 0; + for (; i < 300; i++) { EXPECT_TRUE(ExecJs(tab, "performance.mark('mark1');")); base::RunLoop flush; @@ -588,6 +595,7 @@ break; } } + ASSERT_LT(i, 300U); base::test::TestTraceProcessorImpl ttp; absl::Status status = ttp.ParseTrace(trace); @@ -603,7 +611,6 @@ ::testing::ElementsAre(std::vector<std::string>{"name"}, std::vector<std::string>{"mark1"})); } -#endif // !BUILDFLAG(IS_ANDROID) #endif // BUILDFLAG(IS_POSIX) } // namespace content
diff --git a/content/browser/webid/digital_credentials/digital_credential_provider.h b/content/browser/webid/digital_credentials/digital_credential_provider.h index 7a0145dc..d7e1fa9 100644 --- a/content/browser/webid/digital_credentials/digital_credential_provider.h +++ b/content/browser/webid/digital_credentials/digital_credential_provider.h
@@ -11,13 +11,10 @@ #include "base/values.h" #include "content/common/content_export.h" #include "content/public/browser/web_contents.h" -#include "third_party/blink/public/mojom/webid/federated_auth_request.mojom.h" #include "url/origin.h" #include <string> -using blink::mojom::DigitalCredentialFieldRequirementPtr; - namespace content { // Coordinates between the web and native apps such that the latter can share
diff --git a/content/browser/webid/digital_credentials/digital_credential_provider_android.h b/content/browser/webid/digital_credentials/digital_credential_provider_android.h index 99b471e7..cab05847 100644 --- a/content/browser/webid/digital_credentials/digital_credential_provider_android.h +++ b/content/browser/webid/digital_credentials/digital_credential_provider_android.h
@@ -15,8 +15,6 @@ #include <jni.h> -using blink::mojom::DigitalCredentialFieldRequirementPtr; - namespace content { class WebContents;
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc index cf463ed..51d0ffd 100644 --- a/content/browser/webid/federated_auth_request_impl.cc +++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -601,10 +601,10 @@ permission_context, identity_registry, std::move(receiver)); } -std::vector<blink::mojom::IdentityProviderPtr> +std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> FederatedAuthRequestImpl::MaybeAddRegisteredProviders( - std::vector<blink::mojom::IdentityProviderPtr>& providers) { - std::vector<blink::mojom::IdentityProviderPtr> result; + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr>& providers) { + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> result; std::vector<GURL> registered_config_urls = permission_delegate_->GetRegisteredIdPs(); @@ -617,16 +617,15 @@ std::reverse(registered_config_urls.begin(), registered_config_urls.end()); for (auto& provider : providers) { - if (!provider->is_federated() || - !provider->get_federated()->config->use_registered_config_urls) { + if (!provider->config->use_registered_config_urls) { result.emplace_back(provider->Clone()); continue; } for (auto& configURL : registered_config_urls) { - blink::mojom::IdentityProviderPtr idp = provider->Clone(); - idp->get_federated()->config->use_registered_config_urls = false; - idp->get_federated()->config->config_url = configURL; + blink::mojom::IdentityProviderRequestOptionsPtr idp = provider->Clone(); + idp->config->use_registered_config_urls = false; + idp->config->config_url = configURL; result.emplace_back(std::move(idp)); } } @@ -645,7 +644,7 @@ // Expand the providers list with registered providers. if (IsFedCmIdPRegistrationEnabled()) { for (auto& idp_get_params_ptr : idp_get_params_ptrs) { - std::vector<blink::mojom::IdentityProviderPtr> providers = + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> providers = MaybeAddRegisteredProviders(idp_get_params_ptr->providers); idp_get_params_ptr->providers = std::move(providers); } @@ -733,7 +732,6 @@ fedcm_metrics_ = CreateFedCmMetrics(idp_get_params_ptrs[0] ->providers[0] - ->get_federated() ->config->config_url, render_frame_host().GetPageUkmSourceId(), /*is_disabled=*/idp_get_params_ptrs.size() > 1); @@ -821,8 +819,7 @@ for (auto& idp_ptr : idp_get_params_ptr->providers) { // Throw an error if duplicate IDPs are specified. const bool is_unique_idp = - unique_idps.insert(idp_ptr->get_federated()->config->config_url) - .second; + unique_idps.insert(idp_ptr->config->config_url).second; if (!is_unique_idp) { CompleteRequestWithError(FederatedAuthRequestResult::kError, /*token_status=*/std::nullopt, @@ -831,8 +828,7 @@ return; } - url::Origin idp_origin = - url::Origin::Create(idp_ptr->get_federated()->config->config_url); + url::Origin idp_origin = url::Origin::Create(idp_ptr->config->config_url); if (!network::IsOriginPotentiallyTrustworthy(idp_origin)) { CompleteRequestWithError(FederatedAuthRequestResult::kError, TokenStatus::kIdpNotPotentiallyTrustworthy, @@ -845,15 +841,14 @@ for (auto& idp_get_params_ptr : idp_get_params_ptrs) { for (auto& idp_ptr : idp_get_params_ptr->providers) { - idp_order_.push_back(idp_ptr->get_federated()->config->config_url); + idp_order_.push_back(idp_ptr->config->config_url); bool has_failing_idp_signin_status = webid::ShouldFailAccountsEndpointRequestBecauseNotSignedInWithIdp( - render_frame_host(), idp_ptr->get_federated()->config->config_url, + render_frame_host(), idp_ptr->config->config_url, permission_delegate_); - url::Origin idp_origin = - url::Origin::Create(idp_ptr->get_federated()->config->config_url); + url::Origin idp_origin = url::Origin::Create(idp_ptr->config->config_url); if (has_failing_idp_signin_status && webid::GetIdpSigninStatusMode(render_frame_host(), idp_origin) == FedCmIdpSigninStatusMode::ENABLED) { @@ -862,7 +857,7 @@ // In the multi IDP case, we do not want to complete the request // right away as there are other IDPs which may be logged in. But we // also do not want to fetch this IDP. - unique_idps.erase(idp_ptr->get_federated()->config->config_url); + unique_idps.erase(idp_ptr->config->config_url); continue; } // If the user is known to be signed-out and the RP is request @@ -892,13 +887,12 @@ } } } - if (ShouldFailBeforeFetchingAccounts( - idp_ptr->get_federated()->config->config_url)) { + if (ShouldFailBeforeFetchingAccounts(idp_ptr->config->config_url)) { if (IsFedCmMultipleIdentityProvidersEnabled()) { // In the multi IDP case, we do not want to complete the request right // away as there are other IDPs which may be logged in. But we also do // not want to fetch this IDP. - unique_idps.erase(idp_ptr->get_federated()->config->config_url); + unique_idps.erase(idp_ptr->config->config_url); continue; } CompleteRequestWithError( @@ -911,11 +905,10 @@ blink::mojom::RpContext rp_context = idp_get_params_ptr->context; blink::mojom::RpMode rp_mode = idp_get_params_ptr->mode; - const GURL& idp_config_url = idp_ptr->get_federated()->config->config_url; + const GURL& idp_config_url = idp_ptr->config->config_url; token_request_get_infos_.emplace( idp_config_url, - IdentityProviderGetInfo(std::move(idp_ptr->get_federated()), - rp_context, rp_mode)); + IdentityProviderGetInfo(std::move(idp_ptr), rp_context, rp_mode)); } } @@ -1223,6 +1216,27 @@ IdpNetworkRequestManager::ClientMetadata client_metadata) { // TODO(yigu): Clean up the client metadata related errors for metrics and // console logs. + if (!idp_info->metadata.brand_background_color && + idp_info->metadata.brand_text_color) { + idp_info->metadata.brand_text_color = std::nullopt; + render_frame_host().AddMessageToConsole( + blink::mojom::ConsoleMessageLevel::kWarning, + "The FedCM text color is ignored because background color was not " + "provided"); + } + if (idp_info->metadata.brand_background_color && + idp_info->metadata.brand_text_color) { + float text_contrast_ratio = color_utils::GetContrastRatio( + *idp_info->metadata.brand_background_color, + *idp_info->metadata.brand_text_color); + if (text_contrast_ratio < color_utils::kMinimumReadableContrastRatio) { + idp_info->metadata.brand_text_color = std::nullopt; + render_frame_host().AddMessageToConsole( + blink::mojom::ConsoleMessageLevel::kWarning, + "The FedCM text color is ignored because it does not contrast enough " + "with the provided background color"); + } + } OnFetchDataForIdpSucceeded(std::move(idp_info), accounts, client_metadata); }
diff --git a/content/browser/webid/federated_auth_request_impl.h b/content/browser/webid/federated_auth_request_impl.h index fef254c..fe2d125a 100644 --- a/content/browser/webid/federated_auth_request_impl.h +++ b/content/browser/webid/federated_auth_request_impl.h
@@ -245,8 +245,9 @@ // dialog we show to the user. void OnIdpMismatch(std::unique_ptr<IdentityProviderInfo> idp_info); - std::vector<blink::mojom::IdentityProviderPtr> MaybeAddRegisteredProviders( - std::vector<blink::mojom::IdentityProviderPtr>& providers); + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> + MaybeAddRegisteredProviders( + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr>& providers); void MaybeShowAccountsDialog(); void ShowModalDialog(const GURL& idp_config_url, const GURL& url_to_show);
diff --git a/content/browser/webid/federated_auth_request_impl_multiple_frames_unittest.cc b/content/browser/webid/federated_auth_request_impl_multiple_frames_unittest.cc index f9d4b13..0d36f01 100644 --- a/content/browser/webid/federated_auth_request_impl_multiple_frames_unittest.cc +++ b/content/browser/webid/federated_auth_request_impl_multiple_frames_unittest.cc
@@ -279,10 +279,8 @@ auto federated = blink::mojom::IdentityProviderRequestOptions::New(); federated->config = std::move(config_ptr); federated->nonce = kNonce; - std::vector<blink::mojom::IdentityProviderPtr> idp_ptrs; - blink::mojom::IdentityProviderPtr idp_ptr = - blink::mojom::IdentityProvider::NewFederated(std::move(federated)); - idp_ptrs.push_back(std::move(idp_ptr)); + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> idp_ptrs; + idp_ptrs.push_back(std::move(federated)); auto get_params = blink::mojom::IdentityProviderGetParameters::New( std::move(idp_ptrs), /*rp_context=*/blink::mojom::RpContext::kSignIn,
diff --git a/content/browser/webid/federated_auth_request_impl_unittest.cc b/content/browser/webid/federated_auth_request_impl_unittest.cc index f1fd996..b175bf1e 100644 --- a/content/browser/webid/federated_auth_request_impl_unittest.cc +++ b/content/browser/webid/federated_auth_request_impl_unittest.cc
@@ -267,6 +267,8 @@ std::string metrics_endpoint; std::string idp_login_url; std::string disconnect_endpoint; + std::optional<SkColor> brand_background_color; + std::optional<SkColor> brand_text_color; }; struct MockIdpInfo { @@ -338,15 +340,15 @@ static const MockIdpInfo kDefaultIdentityProviderInfo{ {kWellKnown, {ParseStatus::kSuccess, net::HTTP_OK}}, - { - {ParseStatus::kSuccess, net::HTTP_OK}, - kAccountsEndpoint, - kTokenEndpoint, - kClientMetadataEndpoint, - kMetricsEndpoint, - kIdpLoginUrl, - kIdpDisconnectUrl, - }, + {{ParseStatus::kSuccess, net::HTTP_OK}, + kAccountsEndpoint, + kTokenEndpoint, + kClientMetadataEndpoint, + kMetricsEndpoint, + kIdpLoginUrl, + kIdpDisconnectUrl, + /*brand_background_color=*/std::nullopt, + /*brand_text_color=*/std::nullopt}, kDefaultClientMetadata, {ParseStatus::kSuccess, net::HTTP_OK}, kSingleAccount, @@ -358,15 +360,15 @@ constexpr char kProviderTwoUrlFull[] = "https://idp2.example/fedcm.json"; static const MockIdpInfo kProviderTwoInfo{ {{kProviderTwoUrlFull}}, - { - {ParseStatus::kSuccess, net::HTTP_OK}, - "https://idp2.example/accounts", - "https://idp2.example/token", - "https://idp2.example/client_metadata", - "https://idp2.example/metrics", - "https://idp2.example/login_url", - "https://idp2.example/disconnect", - }, + {{ParseStatus::kSuccess, net::HTTP_OK}, + "https://idp2.example/accounts", + "https://idp2.example/token", + "https://idp2.example/client_metadata", + "https://idp2.example/metrics", + "https://idp2.example/login_url", + "https://idp2.example/disconnect", + /*brand_background_color=*/std::nullopt, + /*brand_text_color=*/std::nullopt}, kDefaultClientMetadata, {ParseStatus::kSuccess, net::HTTP_OK}, kMultipleAccounts}; @@ -454,22 +456,19 @@ ++num_fetched_[FetchedEndpoint::CONFIG]; std::string provider_key = provider.spec(); + const MockConfig& config = config_.idp_info[provider_key].config; IdpNetworkRequestManager::Endpoints endpoints; - endpoints.token = - GURL(config_.idp_info[provider_key].config.token_endpoint); - endpoints.accounts = - GURL(config_.idp_info[provider_key].config.accounts_endpoint); - endpoints.client_metadata = - GURL(config_.idp_info[provider_key].config.client_metadata_endpoint); - endpoints.metrics = - GURL(config_.idp_info[provider_key].config.metrics_endpoint); - endpoints.disconnect = - GURL(config_.idp_info[provider_key].config.disconnect_endpoint); + endpoints.token = GURL(config.token_endpoint); + endpoints.accounts = GURL(config.accounts_endpoint); + endpoints.client_metadata = GURL(config.client_metadata_endpoint); + endpoints.metrics = GURL(config.metrics_endpoint); + endpoints.disconnect = GURL(config.disconnect_endpoint); IdentityProviderMetadata idp_metadata; idp_metadata.config_url = provider; - idp_metadata.idp_login_url = - GURL(config_.idp_info[provider_key].config.idp_login_url); + idp_metadata.idp_login_url = GURL(config.idp_login_url); + idp_metadata.brand_background_color = config.brand_background_color; + idp_metadata.brand_text_color = config.brand_text_color; base::SequencedTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), @@ -642,6 +641,9 @@ AccountList displayed_accounts; std::optional<IdentityRequestAccount::SignInMode> sign_in_mode; blink::mojom::RpContext rp_context; + // The last seen background/text color from IdP metadata. + std::optional<SkColor> brand_background_color; + std::optional<SkColor> brand_text_color; // State related to ShowFailureDialog(). size_t num_show_idp_signin_status_mismatch_dialog_requests{0u}; // State related to ShowIdpSigninFailureDialog(). @@ -697,6 +699,9 @@ if (idp_data.has_login_status_mismatch) { state_->displayed_mismatch_idps.push_back(idp_data.idp_for_display); } + state_->brand_background_color = + idp_data.idp_metadata.brand_background_color; + state_->brand_text_color = idp_data.idp_metadata.brand_text_color; } switch (accounts_dialog_action_) { @@ -994,7 +999,7 @@ // If multiple IdPs are received, add them to a single get call. Unittests // for multiple get calls can be added later as needed. - std::vector<blink::mojom::IdentityProviderPtr> idp_ptrs; + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> idp_ptrs; for (const auto& identity_provider : request_parameters.identity_providers) { blink::mojom::IdentityProviderRequestOptionsPtr options = @@ -1006,9 +1011,7 @@ options->login_hint = identity_provider.login_hint; options->domain_hint = identity_provider.domain_hint; options->scope = std::move(identity_provider.scope); - blink::mojom::IdentityProviderPtr idp_ptr = - blink::mojom::IdentityProvider::NewFederated(std::move(options)); - idp_ptrs.push_back(std::move(idp_ptr)); + idp_ptrs.push_back(std::move(options)); } blink::mojom::IdentityProviderGetParametersPtr get_params = blink::mojom::IdentityProviderGetParameters::New( @@ -1135,6 +1138,14 @@ .num_show_idp_signin_status_mismatch_dialog_requests; } + std::optional<SkColor> brand_background_color() const { + return dialog_controller_state_.brand_background_color; + } + + std::optional<SkColor> brand_text_color() const { + return dialog_controller_state_.brand_text_color; + } + int CountNumLoginStateIsSignin() { int num_sign_in_login_state = 0; for (const auto& account : displayed_accounts()) { @@ -1402,13 +1413,15 @@ url::Origin::Create(GURL(config_url)), accounts); } - std::vector<blink::mojom::IdentityProviderPtr> MaybeAddRegisteredProviders( - std::vector<blink::mojom::IdentityProviderPtr>& providers) { + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> + MaybeAddRegisteredProviders( + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr>& providers) { return federated_auth_request_impl_->MaybeAddRegisteredProviders(providers); } - blink::mojom::IdentityProviderPtr NewNamedIdP(GURL config_url, - std::string client_id) { + blink::mojom::IdentityProviderRequestOptionsPtr NewNamedIdP( + GURL config_url, + std::string client_id) { blink::mojom::IdentityProviderRequestOptionsPtr options = blink::mojom::IdentityProviderRequestOptions::New(); blink::mojom::IdentityProviderConfigPtr config = @@ -1416,10 +1429,11 @@ config->config_url = config_url; config->client_id = client_id; options->config = std::move(config); - return blink::mojom::IdentityProvider::NewFederated(std::move(options)); + return options; } - blink::mojom::IdentityProviderPtr NewRegisteredIdP(std::string client_id) { + blink::mojom::IdentityProviderRequestOptionsPtr NewRegisteredIdP( + std::string client_id) { blink::mojom::IdentityProviderConfigPtr config = blink::mojom::IdentityProviderConfig::New(); config->use_registered_config_urls = true; @@ -1428,7 +1442,7 @@ blink::mojom::IdentityProviderRequestOptions::New(); options->config = std::move(config); - return blink::mojom::IdentityProvider::NewFederated(std::move(options)); + return options; } void SimulateLoginToIdP(std::string login_url = kIdpLoginUrl) { @@ -5933,9 +5947,9 @@ // Test that no registered IdP is added without a registry requested. TEST_F(FederatedAuthRequestImplTest, MaybeAddRegisteredProvidersEmptyList) { - std::vector<blink::mojom::IdentityProviderPtr> providers; + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> providers; - std::vector<blink::mojom::IdentityProviderPtr> result = + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> result = MaybeAddRegisteredProviders(providers); EXPECT_TRUE(result.empty()); @@ -5943,14 +5957,14 @@ // Test that no registered IdP with only named providers requested. TEST_F(FederatedAuthRequestImplTest, MaybeAddRegisteredProvidersNamed) { - std::vector<blink::mojom::IdentityProviderPtr> providers; + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> providers; providers.emplace_back(NewNamedIdP(GURL("https://idp.example"), kClientId)); - std::vector<blink::mojom::IdentityProviderPtr> result = + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> result = MaybeAddRegisteredProviders(providers); // Expects the vector to be the same. - std::vector<blink::mojom::IdentityProviderPtr> expected; + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> expected; expected.emplace_back(NewNamedIdP(GURL("https://idp.example"), kClientId)); EXPECT_EQ(expected, result); @@ -5958,7 +5972,7 @@ // Test that a registered provider is added. TEST_F(FederatedAuthRequestImplTest, MaybeAddRegisteredProvidersAdded) { - std::vector<blink::mojom::IdentityProviderPtr> providers; + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> providers; providers.emplace_back(NewRegisteredIdP(kClientId)); std::vector<GURL> registry; @@ -5967,11 +5981,11 @@ EXPECT_CALL(*test_permission_delegate_, GetRegisteredIdPs()) .WillOnce(Return(registry)); - std::vector<blink::mojom::IdentityProviderPtr> result = + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> result = MaybeAddRegisteredProviders(providers); // Expects that the registered IdP gets replaced by a named IdP. - std::vector<blink::mojom::IdentityProviderPtr> expected; + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> expected; expected.emplace_back(NewNamedIdP(GURL("https://idp.example"), kClientId)); EXPECT_EQ(expected, result); @@ -5980,7 +5994,7 @@ // Test that all registered IdPs are expanded. TEST_F(FederatedAuthRequestImplTest, MaybeAddRegisteredProvidersAllRequestsForRegisteredIdPsAreExpanded) { - std::vector<blink::mojom::IdentityProviderPtr> providers; + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> providers; providers.emplace_back(NewRegisteredIdP(kClientId)); providers.emplace_back(NewRegisteredIdP(kClientId)); @@ -5990,11 +6004,11 @@ EXPECT_CALL(*test_permission_delegate_, GetRegisteredIdPs()) .WillOnce(Return(registry)); - std::vector<blink::mojom::IdentityProviderPtr> result = + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> result = MaybeAddRegisteredProviders(providers); // Expects that the registered IdP gets replaced by a named IdP. - std::vector<blink::mojom::IdentityProviderPtr> expected; + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> expected; expected.emplace_back(NewNamedIdP(GURL("https://idp.example"), kClientId)); expected.emplace_back(NewNamedIdP(GURL("https://idp.example"), kClientId)); @@ -6004,7 +6018,7 @@ // Test that the registry can add two idps. TEST_F(FederatedAuthRequestImplTest, MaybeAddRegisteredProvidersTwoRegisteredIdPs) { - std::vector<blink::mojom::IdentityProviderPtr> providers; + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> providers; providers.emplace_back(NewRegisteredIdP(kClientId)); std::vector<GURL> registry; @@ -6014,10 +6028,10 @@ EXPECT_CALL(*test_permission_delegate_, GetRegisteredIdPs()) .WillOnce(Return(registry)); - std::vector<blink::mojom::IdentityProviderPtr> result = + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> result = MaybeAddRegisteredProviders(providers); - std::vector<blink::mojom::IdentityProviderPtr> expected; + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> expected; expected.emplace_back(NewNamedIdP(GURL("https://idp2.example"), kClientId)); expected.emplace_back(NewNamedIdP(GURL("https://idp1.example"), kClientId)); @@ -6027,7 +6041,7 @@ // Test that registered idps are inserted inline. TEST_F(FederatedAuthRequestImplTest, MaybeAddRegisteredProvidersInsertedInline) { - std::vector<blink::mojom::IdentityProviderPtr> providers; + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> providers; providers.emplace_back(NewNamedIdP(GURL("https://idp1.example"), kClientId)); providers.emplace_back(NewRegisteredIdP(kClientId)); providers.emplace_back(NewNamedIdP(GURL("https://idp2.example"), kClientId)); @@ -6039,11 +6053,11 @@ EXPECT_CALL(*test_permission_delegate_, GetRegisteredIdPs()) .WillOnce(Return(registry)); - std::vector<blink::mojom::IdentityProviderPtr> result = + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> result = MaybeAddRegisteredProviders(providers); // Expects that the registered IdP gets replaced by a named IdP. - std::vector<blink::mojom::IdentityProviderPtr> expected; + std::vector<blink::mojom::IdentityProviderRequestOptionsPtr> expected; expected.emplace_back(NewNamedIdP(GURL("https://idp1.example"), kClientId)); expected.emplace_back( NewNamedIdP(GURL("https://idp-registered2.example"), kClientId)); @@ -6556,6 +6570,42 @@ main_test_rfh()->GetLastCommittedOrigin())); } +// Tests that when background text is passed but no background color, the +// background text is ignored. +TEST_F(FederatedAuthRequestImplTest, + BrandingWithTextColorAndNoBackgroundColor) { + MockConfiguration configuration = kConfigurationValid; + configuration.idp_info[kProviderUrlFull].config.brand_text_color = + SkColorSetRGB(10, 10, 10); + RequestExpectations expectations = kExpectationSuccess; + expectations.standalone_console_message = + "The FedCM text color is ignored because background color was not " + "provided"; + RunAuthTest(kDefaultRequestParameters, expectations, configuration); + + EXPECT_EQ(brand_background_color(), std::nullopt); + EXPECT_EQ(brand_text_color(), std::nullopt); +} + +// Tests that when background text does not contrast enough with the background +// color, the text color is ignored. +TEST_F(FederatedAuthRequestImplTest, + BrandingWithInsufficientContrastTextColor) { + MockConfiguration configuration = kConfigurationValid; + configuration.idp_info[kProviderUrlFull].config.brand_background_color = + SkColorSetRGB(0, 0, 0); + configuration.idp_info[kProviderUrlFull].config.brand_text_color = + SkColorSetRGB(1, 1, 1); + RequestExpectations expectations = kExpectationSuccess; + expectations.standalone_console_message = + "The FedCM text color is ignored because it does not contrast enough " + "with the provided background color"; + RunAuthTest(kDefaultRequestParameters, expectations, configuration); + + EXPECT_EQ(brand_background_color(), SkColorSetRGB(0, 0, 0)); + EXPECT_EQ(brand_text_color(), std::nullopt); +} + class FederatedAuthRequestExampleOrgTest : public FederatedAuthRequestImplTest { public: FederatedAuthRequestExampleOrgTest()
diff --git a/content/browser/webid/idp_network_request_manager.cc b/content/browser/webid/idp_network_request_manager.cc index 3a7244e4..b8d40b41 100644 --- a/content/browser/webid/idp_network_request_manager.cc +++ b/content/browser/webid/idp_network_request_manager.cc
@@ -315,16 +315,8 @@ IdentityProviderMetadata& idp_metadata) { idp_metadata.brand_background_color = ParseCssColor(idp_metadata_value.FindString(kIdpBrandingBackgroundColor)); - if (idp_metadata.brand_background_color) { - idp_metadata.brand_text_color = ParseCssColor( - idp_metadata_value.FindString(kIdpBrandingForegroundColor)); - if (idp_metadata.brand_text_color) { - float text_contrast_ratio = color_utils::GetContrastRatio( - *idp_metadata.brand_background_color, *idp_metadata.brand_text_color); - if (text_contrast_ratio < color_utils::kMinimumReadableContrastRatio) - idp_metadata.brand_text_color = std::nullopt; - } - } + idp_metadata.brand_text_color = + ParseCssColor(idp_metadata_value.FindString(kIdpBrandingForegroundColor)); const base::Value::List* icons_value = idp_metadata_value.FindList(kIdpBrandingIcons);
diff --git a/content/browser/webid/idp_network_request_manager_unittest.cc b/content/browser/webid/idp_network_request_manager_unittest.cc index 0887415e..ba187d2 100644 --- a/content/browser/webid/idp_network_request_manager_unittest.cc +++ b/content/browser/webid/idp_network_request_manager_unittest.cc
@@ -713,7 +713,7 @@ } TEST_F(IdpNetworkRequestManagerTest, - ParseConfigIgnoreInsufficientContrastTextColor) { + ParseConfigWithInsufficientContrastTextColor) { const char test_json[] = R"({ "branding" : { "background_color": "#000000", @@ -729,11 +729,11 @@ EXPECT_EQ(ParseStatus::kSuccess, fetch_status.parse_status); EXPECT_EQ(net::HTTP_OK, fetch_status.response_code); EXPECT_EQ(SkColorSetRGB(0, 0, 0), idp_metadata.brand_background_color); - EXPECT_EQ(std::nullopt, idp_metadata.brand_text_color); + EXPECT_EQ(SkColorSetRGB(1, 1, 1), idp_metadata.brand_text_color); } TEST_F(IdpNetworkRequestManagerTest, - ParseConfigBrandingIgnoreCustomTextColorNoCustomBackgroundColor) { + ParseConfigBrandingWithTextColorAndNoBackgroundColor) { const char test_json[] = R"({ "branding" : { "color": "blue" @@ -748,7 +748,7 @@ EXPECT_EQ(ParseStatus::kSuccess, fetch_status.parse_status); EXPECT_EQ(net::HTTP_OK, fetch_status.response_code); EXPECT_EQ(std::nullopt, idp_metadata.brand_background_color); - EXPECT_EQ(std::nullopt, idp_metadata.brand_text_color); + EXPECT_EQ(SkColorSetRGB(0, 0, 255), idp_metadata.brand_text_color); } TEST_F(IdpNetworkRequestManagerTest, ParseConfigBrandingSelectBestSize) {
diff --git a/content/browser/webrtc/webrtc_internals.cc b/content/browser/webrtc/webrtc_internals.cc index 3b0af57d..eb14f3b0 100644 --- a/content/browser/webrtc/webrtc_internals.cc +++ b/content/browser/webrtc/webrtc_internals.cc
@@ -176,8 +176,7 @@ int lid, ProcessId pid, const string& url, - const string& rtc_configuration, - const string& constraints) { + const string& rtc_configuration) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // TODO(tommi): Consider changing this design so that webrtc-internals has @@ -188,7 +187,6 @@ dict.Set("lid", lid); dict.Set("pid", static_cast<int>(pid)); dict.Set("rtcConfiguration", rtc_configuration); - dict.Set("constraints", constraints); dict.Set("url", url); dict.Set("isOpen", true); dict.Set("connected", false);
diff --git a/content/browser/webrtc/webrtc_internals.h b/content/browser/webrtc/webrtc_internals.h index 084dbc9..8fff926 100644 --- a/content/browser/webrtc/webrtc_internals.h +++ b/content/browser/webrtc/webrtc_internals.h
@@ -62,8 +62,7 @@ int lid, base::ProcessId pid, const std::string& url, - const std::string& rtc_configuration, - const std::string& constraints) override; + const std::string& rtc_configuration) override; void OnPeerConnectionRemoved(GlobalRenderFrameHostId frame_id, int lid) override; void OnPeerConnectionUpdated(GlobalRenderFrameHostId frame_id,
diff --git a/content/browser/webrtc/webrtc_internals_message_handler_unittest.cc b/content/browser/webrtc/webrtc_internals_message_handler_unittest.cc index 4aeab25..8d69204f 100644 --- a/content/browser/webrtc/webrtc_internals_message_handler_unittest.cc +++ b/content/browser/webrtc/webrtc_internals_message_handler_unittest.cc
@@ -26,7 +26,6 @@ static const GlobalRenderFrameHostId kFrameId = {20, 30}; static const int kPid = 35; static const int kLid = 75; -static const char kConstraints[] = "c"; static const char kRtcConfiguration[] = "r"; static const char kUrl[] = "u"; @@ -84,7 +83,7 @@ NavigateAndCommit(example_url); webrtc_internals.OnPeerConnectionAdded(kFrameId, kPid, kLid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); base::RunLoop().RunUntilIdle(); auto navigation = content::NavigationSimulator::CreateBrowserInitiated(
diff --git a/content/browser/webrtc/webrtc_internals_unittest.cc b/content/browser/webrtc/webrtc_internals_unittest.cc index cbbdca0..720b618 100644 --- a/content/browser/webrtc/webrtc_internals_unittest.cc +++ b/content/browser/webrtc/webrtc_internals_unittest.cc
@@ -28,7 +28,6 @@ const int kLid = 40; const int kPid = 123; const int kRequestId = 1; -const char kConstraints[] = "c"; const char kRtcConfiguration[] = "r"; const char kUrl[] = "u"; const char* const kWakeLockConnectingValues[] = {"checking", "connected", @@ -223,7 +222,7 @@ webrtc_internals.RemoveObserver(&observer); // The observer should not get notified of this activity. webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); GetUIThreadTaskRunner({})->PostTask(FROM_HERE, loop.QuitClosure()); loop.Run(); @@ -239,7 +238,7 @@ base::RunLoop loop; WebRTCInternalsForTest webrtc_internals; webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); webrtc_internals.OnPeerConnectionUpdated(kFrameId, kLid, "update_type", "update_value"); GetUIThreadTaskRunner({})->PostTask(FROM_HERE, loop.QuitClosure()); @@ -268,7 +267,7 @@ MockWebRtcInternalsProxy observer; webrtc_internals.AddObserver(&observer); webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); webrtc_internals.OnPeerConnectionUpdated(kFrameId, kLid, "update_type", "update_value"); GetUIThreadTaskRunner({})->PostTask(FROM_HERE, loop.QuitClosure()); @@ -307,7 +306,7 @@ WebRTCInternalsForTest webrtc_internals; webrtc_internals.AddObserver(&observer); webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); loop.Run(); @@ -321,7 +320,6 @@ VerifyInt(dict, "pid", kPid); VerifyString(dict, "url", kUrl); VerifyString(dict, "rtcConfiguration", kRtcConfiguration); - VerifyString(dict, "constraints", kConstraints); webrtc_internals.RemoveObserver(&observer); webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLid); @@ -335,7 +333,7 @@ WebRTCInternalsForTest webrtc_internals; webrtc_internals.AddObserver(&observer); webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); webrtc_internals.OnPeerConnectionRemoved(kFrameId, kLid); loop.Run(); @@ -359,7 +357,7 @@ WebRTCInternalsForTest webrtc_internals; webrtc_internals.AddObserver(&observer); webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); const std::string update_type = "fakeType"; const std::string update_value = "fakeValue"; @@ -576,7 +574,7 @@ webrtc_internals.AddObserver(&observer); webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); webrtc_internals.OnPeerConnectionUpdated(kFrameId, kLid, update_type, update_value); @@ -597,7 +595,6 @@ VerifyInt(dict, "pid", kPid); VerifyString(dict, "url", kUrl); VerifyString(dict, "rtcConfiguration", kRtcConfiguration); - VerifyString(dict, "constraints", kConstraints); const base::Value::List* log_value = dict.FindList("log"); ASSERT_TRUE(log_value); @@ -621,7 +618,7 @@ WebRTCInternalsForTest webrtc_internals; webrtc_internals.AddObserver(&observer); webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); base::Value::List list; list.Append("xxx"); @@ -649,7 +646,7 @@ WebRTCInternalsForTest webrtc_internals; webrtc_internals.AddObserver(&observer); webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); base::Value::List list; list.Append("xxx"); @@ -695,7 +692,7 @@ EXPECT_FALSE(webrtc_internals.HasWakeLock()); webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); EXPECT_FALSE(webrtc_internals.HasWakeLock()); @@ -713,7 +710,7 @@ EXPECT_FALSE(webrtc_internals.HasWakeLock()); webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); EXPECT_FALSE(webrtc_internals.HasWakeLock()); @@ -736,7 +733,7 @@ EXPECT_FALSE(webrtc_internals.HasWakeLock()); webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); EXPECT_FALSE(webrtc_internals.HasWakeLock()); @@ -763,7 +760,7 @@ EXPECT_FALSE(webrtc_internals.HasWakeLock()); webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); EXPECT_FALSE(webrtc_internals.HasWakeLock()); @@ -791,7 +788,7 @@ EXPECT_FALSE(webrtc_internals.HasWakeLock()); webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); EXPECT_FALSE(webrtc_internals.HasWakeLock()); @@ -822,7 +819,7 @@ EXPECT_FALSE(webrtc_internals.HasWakeLock()); webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); EXPECT_FALSE(webrtc_internals.HasWakeLock()); @@ -857,7 +854,7 @@ for (const int lid : kLids) { webrtc_internals.OnPeerConnectionAdded(kFrameId, lid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); EXPECT_FALSE(webrtc_internals.HasWakeLock()); } @@ -918,7 +915,7 @@ EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); webrtc_internals.OnPeerConnectionAdded(kFrameId, kLid, kPid, kUrl, - kRtcConfiguration, kConstraints); + kRtcConfiguration); EXPECT_EQ(webrtc_internals.num_connected_connections(), 0); EXPECT_EQ(0u, observer.latest_connections_count());
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityNodeInfoUtils.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityNodeInfoUtils.java index dffd1452..77bc0a7 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityNodeInfoUtils.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityNodeInfoUtils.java
@@ -62,7 +62,8 @@ * @param node Object to create a toString for * @return String Custom toString result for the given object */ - public static String toString(AccessibilityNodeInfoCompat node) { + public static String toString( + AccessibilityNodeInfoCompat node, boolean includeScreenSizeDependentAttributes) { if (node == null) return ""; StringBuilder builder = new StringBuilder(); @@ -144,7 +145,7 @@ if (node.isPassword()) { builder.append(" password"); } - if (node.isScrollable()) { + if (node.isScrollable() && includeScreenSizeDependentAttributes) { builder.append(" scrollable"); } if (node.isSelected()) { @@ -180,8 +181,10 @@ } // Actions and Bundle extras - Always print. - builder.append(" actions:").append(toString(node.getActionList())); - builder.append(" bundle:").append(toString(node.getExtras())); + builder.append(" actions:") + .append(toString(node.getActionList(), includeScreenSizeDependentAttributes)); + builder.append(" bundle:") + .append(toString(node.getExtras(), includeScreenSizeDependentAttributes)); return builder.toString(); } @@ -225,7 +228,8 @@ } private static String toString( - List<AccessibilityNodeInfoCompat.AccessibilityActionCompat> actionList) { + List<AccessibilityNodeInfoCompat.AccessibilityActionCompat> actionList, + boolean includeScreenSizeDependentAttributes) { // Sort actions list to ensure consistent output of tests. Collections.sort(actionList, (a1, b2) -> Integer.compare(a1.getId(), b2.getId())); @@ -241,6 +245,14 @@ || action.equals(ACTION_LONG_CLICK)) { continue; } + + // When |includeScreenSizeDependentAttributes| is true, we include all other actions, + // so append and return early, otherwise continue to checks below. + if (includeScreenSizeDependentAttributes) { + actionStrings.add(toString(action.getId())); + continue; + } + // Scroll actions are dependent on screen size, so ignore them to reduce flakiness if (action.equals(ACTION_SCROLL_FORWARD) || action.equals(ACTION_SCROLL_BACKWARD) @@ -331,7 +343,7 @@ */ } - private static String toString(Bundle extras) { + private static String toString(Bundle extras, boolean includeScreenSizeDependentAttributes) { // Sort keys to ensure consistent output of tests. List<String> sortedKeySet = new ArrayList<String>(extras.keySet()); Collections.sort(sortedKeySet, CASE_INSENSITIVE_ORDER); @@ -341,8 +353,11 @@ builder.append("["); for (String key : sortedKeySet) { // Two Bundle extras are related to bounding boxes, these should be ignored so the - // tests can safely run on varying devices and not be screen-dependent. - if (key.equals(EXTRAS_KEY_UNCLIPPED_TOP) || key.equals(EXTRAS_KEY_UNCLIPPED_BOTTOM)) { + // tests can safely run on varying devices and not be screen-dependent, unless + // explicitly allowed for this instance. + if (!includeScreenSizeDependentAttributes + && (key.equals(EXTRAS_KEY_UNCLIPPED_TOP) + || key.equals(EXTRAS_KEY_UNCLIPPED_BOTTOM))) { continue; } @@ -359,8 +374,8 @@ } // To prevent flakiness or dependency on screensize/form factor, drop the "offscreen" - // Bundle extra. - if (key.equals(EXTRAS_KEY_OFFSCREEN)) { + // Bundle extra, unless explicitly allowed for this instance. + if (!includeScreenSizeDependentAttributes && key.equals(EXTRAS_KEY_OFFSCREEN)) { continue; }
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java index 11a5e11..e2574c1 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
@@ -889,7 +889,8 @@ // so temporarily set the |mAccessibilityEnabledOverride| flag to true, then disable it. mAccessibilityEnabledOverride = true; String returnString = - AccessibilityNodeInfoUtils.toString(createAccessibilityNodeInfo(virtualViewId)); + AccessibilityNodeInfoUtils.toString( + createAccessibilityNodeInfo(virtualViewId), true); mAccessibilityEnabledOverride = false; return returnString; }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java index d593a3c45..367adf8 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java
@@ -176,7 +176,7 @@ int rootNodevvId = mActivityTestRule.waitForNodeMatching(sClassNameMatcher, "android.webkit.WebView"); AccessibilityNodeInfoCompat nodeInfo = createAccessibilityNodeInfo(rootNodevvId); - builder.append(AccessibilityNodeInfoUtils.toString(nodeInfo)); + builder.append(AccessibilityNodeInfoUtils.toString(nodeInfo, false)); // Recursively generate strings for all descendants. for (int i = 0; i < nodeInfo.getChildCount(); ++i) { @@ -207,7 +207,9 @@ */ private void recursivelyFormatTree( AccessibilityNodeInfoCompat node, StringBuilder builder, String indent) { - builder.append("\n").append(indent).append(AccessibilityNodeInfoUtils.toString(node)); + builder.append("\n") + .append(indent) + .append(AccessibilityNodeInfoUtils.toString(node, false)); for (int j = 0; j < node.getChildCount(); ++j) { int childId = mActivityTestRule.getChildId(node, j); AccessibilityNodeInfoCompat childNodeInfo = createAccessibilityNodeInfo(childId);
diff --git a/content/public/browser/peer_connection_tracker_host_observer.h b/content/public/browser/peer_connection_tracker_host_observer.h index 699e683..c8c2b40 100644 --- a/content/public/browser/peer_connection_tracker_host_observer.h +++ b/content/public/browser/peer_connection_tracker_host_observer.h
@@ -35,8 +35,7 @@ int lid, base::ProcessId pid, const std::string& url, - const std::string& rtc_configuration, - const std::string& constraints) {} + const std::string& rtc_configuration) {} // This method is called when a peer connection is destroyed. // - |render_frame_host_id| identifies the RenderFrameHost.
diff --git a/content/public/test/DEPS b/content/public/test/DEPS index abfba8f..0d15af6 100644 --- a/content/public/test/DEPS +++ b/content/public/test/DEPS
@@ -5,7 +5,7 @@ # everywhere. "+chromeos/crosapi/cpp/crosapi_constants.h", "+chromeos/lacros/lacros_service.h", - "+chromeos/startup/browser_params_proxy.h", + "+chromeos/lacros/lacros_test_helper.h", "+chromeos/startup/startup_switches.h", # Tests can use all content/public headers.
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc index b81f943..501ec5a 100644 --- a/content/public/test/browser_test_base.cc +++ b/content/public/test/browser_test_base.cc
@@ -129,7 +129,7 @@ #if BUILDFLAG(IS_CHROMEOS_LACROS) #include "base/files/scoped_file.h" #include "chromeos/crosapi/cpp/crosapi_constants.h" // nogncheck -#include "chromeos/startup/browser_params_proxy.h" +#include "chromeos/lacros/lacros_test_helper.h" #include "chromeos/startup/startup_switches.h" // nogncheck #include "mojo/public/cpp/platform/socket_utils_posix.h" #endif @@ -455,14 +455,16 @@ // For more details, please see: // //chrome/browser/ash/crosapi/test_mojo_connection_manager.h. { - if (!chromeos::BrowserParamsProxy::Get()->IsCrosapiDisabledForTesting()) { - // TODO(crbug.com/1127581): Switch to use |kLacrosMojoSocketForTesting| in - // //ash/constants/ash_switches.h. - // Please refer to the CL comments for why it can't be done now: - // http://crrev.com/c/2402580/2/content/public/test/browser_test_base.cc - CHECK(command_line->HasSwitch("lacros-mojo-socket-for-testing")); - std::string socket_path = - command_line->GetSwitchValueASCII("lacros-mojo-socket-for-testing"); + // TODO(crbug.com/1127581): Switch to use |kLacrosMojoSocketForTesting| in + // //ash/constants/ash_switches.h. + // Please refer to the CL comments for why it can't be done now: + // http://crrev.com/c/2402580/2/content/public/test/browser_test_base.cc + std::string socket_path = + command_line->GetSwitchValueASCII("lacros-mojo-socket-for-testing"); + if (socket_path.empty()) { + disable_crosapi_ = + std::make_unique<chromeos::ScopedDisableCrosapiForTesting>(); + } else { auto channel = mojo::NamedPlatformChannel::ConnectToServer(socket_path); base::ScopedFD socket_fd = channel.TakePlatformHandle().TakeFD();
diff --git a/content/public/test/browser_test_base.h b/content/public/test/browser_test_base.h index c28b0381..4f66dbd 100644 --- a/content/public/test/browser_test_base.h +++ b/content/public/test/browser_test_base.h
@@ -45,6 +45,10 @@ class TimeDelta; } // namespace base +namespace chromeos { +class ScopedDisableCrosapiForTesting; +} + namespace ui { class ScopedAnimationDurationScaleMode; } @@ -290,6 +294,10 @@ // not run and report a false positive result. bool set_up_called_ = false; +#if BUILDFLAG(IS_CHROMEOS_LACROS) + std::unique_ptr<chromeos::ScopedDisableCrosapiForTesting> disable_crosapi_; +#endif + std::unique_ptr<storage::QuotaSettings> quota_settings_; std::unique_ptr<NoRendererCrashesAssertion> no_renderer_crashes_assertion_;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 9a0d9d4..6d38819 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -420,14 +420,14 @@ bool IsValidCommitUrl(const GURL& url) { // Invalid URLs are not accepted by the browser process. if (!url.is_valid()) { - base::UmaHistogramEnumeration("Navigation.Renderer.BlockedByFilterURL", + base::UmaHistogramEnumeration("Navigation.Renderer.BlockedForFilterURL", RendererBlockedURLReason::kInvalidURL); return false; } // Do not send a URL longer than Mojo will serialize. if (url.possibly_invalid_spec().length() > url::kMaxURLChars) { - base::UmaHistogramEnumeration("Navigation.Renderer.BlockedByFilterURL", + base::UmaHistogramEnumeration("Navigation.Renderer.BlockedForFilterURL", RendererBlockedURLReason::kTooLongURL); return false; } @@ -436,7 +436,7 @@ // fragments). if (url.SchemeIs(url::kAboutScheme) && (!url.IsAboutBlank() && !url.IsAboutSrcdoc())) { - base::UmaHistogramEnumeration("Navigation.Renderer.BlockedByFilterURL", + base::UmaHistogramEnumeration("Navigation.Renderer.BlockedForFilterURL", RendererBlockedURLReason::kBadAboutURL); return false; }
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 90ef83d..438c00c 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -787,7 +787,6 @@ "//chromeos/crosapi/cpp:crosapi_constants", "//chromeos/lacros", "//chromeos/lacros:test_support", - "//chromeos/startup", "//chromeos/startup:constants", ] } @@ -2419,7 +2418,6 @@ "../browser/indexed_db/indexed_db_context_unittest.cc", "../browser/indexed_db/indexed_db_database_unittest.cc", "../browser/indexed_db/indexed_db_dispatcher_host_unittest.cc", - "../browser/indexed_db/indexed_db_factory_unittest.cc", "../browser/indexed_db/indexed_db_fake_backing_store.cc", "../browser/indexed_db/indexed_db_fake_backing_store.h", "../browser/indexed_db/indexed_db_leveldb_coding_unittest.cc",
diff --git a/content/test/data/accessibility/accname/desc-combobox-focusable-expected-android-external.txt b/content/test/data/accessibility/accname/desc-combobox-focusable-expected-android-external.txt index 04a2c360..c337e11 100644 --- a/content/test/data/accessibility/accname/desc-combobox-focusable-expected-android-external.txt +++ b/content/test/data/accessibility/accname/desc-combobox-focusable-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++Spinner text:"English" hint:"Choose your language." viewIdResName:"test" canOpenPopUp clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="comboBoxMenuButton", hint="Choose your language."] \ No newline at end of file
diff --git a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-external.txt b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-external.txt index e7696a3e..076c107 100644 --- a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-external.txt +++ b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++EditText hint:"Important stuff My name is Eli the weird. (QED) Where are my marbles?" viewIdResName:"test" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Important stuff My name is Eli the weird. (QED) Where are my marbles?"] ++View viewIdResName:"descId" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++TextView text:"My" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] @@ -12,4 +12,4 @@ ++++++View actions:[AX_FOCUS] bundle:[chromeRole="layoutTableRow"] ++++++++View text:"Where" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="layoutTableCell"] ++++++++View actions:[AX_FOCUS] bundle:[chromeRole="layoutTableCell"] -++++++++View text:"are my marbles?" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="layoutTableCell"] +++++++++View text:"are my marbles?" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="layoutTableCell"] \ No newline at end of file
diff --git a/content/test/data/accessibility/accname/name-combobox-focusable-expected-android-external.txt b/content/test/data/accessibility/accname/name-combobox-focusable-expected-android-external.txt index 04a2c360..c337e11 100644 --- a/content/test/data/accessibility/accname/name-combobox-focusable-expected-android-external.txt +++ b/content/test/data/accessibility/accname/name-combobox-focusable-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++Spinner text:"English" hint:"Choose your language." viewIdResName:"test" canOpenPopUp clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="comboBoxMenuButton", hint="Choose your language."] \ No newline at end of file
diff --git a/content/test/data/accessibility/accname/name-div-content-only-expected-android-external.txt b/content/test/data/accessibility/accname/name-div-content-only-expected-android-external.txt index e44ef3e..984440c 100644 --- a/content/test/data/accessibility/accname/name-div-content-only-expected-android-external.txt +++ b/content/test/data/accessibility/accname/name-div-content-only-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Div with text" viewIdResName:"test" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/annotation-roles-expected-android-external.txt b/content/test/data/accessibility/aria/annotation-roles-expected-android-external.txt index 177e5f6..278003e9 100644 --- a/content/test/data/accessibility/aria/annotation-roles-expected-android-external.txt +++ b/content/test/data/accessibility/aria/annotation-roles-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"comment" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="comment", roleDescription="comment"] ++View text:"suggestion" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="suggestion", roleDescription="suggestion"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"]
diff --git a/content/test/data/accessibility/aria/aria-alert-expected-android-external.txt b/content/test/data/accessibility/aria/aria-alert-expected-android-external.txt index 2e34cfd..42d2a0f 100644 --- a/content/test/data/accessibility/aria/aria-alert-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-alert-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"This test is for aria role="alert"" viewIdResName:"ariaalert" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="alert", roleDescription="alert"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-alertdialog-expected-android-external.txt b/content/test/data/accessibility/aria/aria-alertdialog-expected-android-external.txt index af9e965..d730270 100644 --- a/content/test/data/accessibility/aria/aria-alertdialog-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-alertdialog-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View paneTitle:"dialog opened." actions:[AX_FOCUS] bundle:[chromeRole="alertDialog", roleDescription="alert dialog"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-application-expected-android-external.txt b/content/test/data/accessibility/aria/aria-application-expected-android-external.txt index 3258c9c1..ede6bf4 100644 --- a/content/test/data/accessibility/aria/aria-application-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-application-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View viewIdResName:"testAriaApplication" actions:[AX_FOCUS] bundle:[chromeRole="application", roleDescription="application"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-article-expected-android-external.txt b/content/test/data/accessibility/aria/aria-article-expected-android-external.txt index ee1cd56..6e43e4d2 100644 --- a/content/test/data/accessibility/aria/aria-article-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-article-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"This is an ARIA article." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="article", roleDescription="article"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-atomic-expected-android-external.txt b/content/test/data/accessibility/aria/aria-atomic-expected-android-external.txt index 0b4e7d6..efc64b48 100644 --- a/content/test/data/accessibility/aria/aria-atomic-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-atomic-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"This test is for aria-atomic="false"" viewIdResName:"ariaatomicfalse" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="log", roleDescription="log"] ++View text:"This test is for aria-atomic="true"" viewIdResName:"ariaatomictrue" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="log", roleDescription="log"] ++View text:"This test is for alert." viewIdResName:"alert" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="alert", roleDescription="alert"]
diff --git a/content/test/data/accessibility/aria/aria-autocomplete-expected-android-external.txt b/content/test/data/accessibility/aria/aria-autocomplete-expected-android-external.txt index 454b2ac2..772850a1 100644 --- a/content/test/data/accessibility/aria/aria-autocomplete-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-autocomplete-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText text:"autocomplete=inline" canOpenPopUp clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textFieldWithComboBox", clickableScore="300"] ++++EditText text:"autocomplete=list" canOpenPopUp clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textFieldWithComboBox", clickableScore="300"]
diff --git a/content/test/data/accessibility/aria/aria-banner-expected-android-external.txt b/content/test/data/accessibility/aria/aria-banner-expected-android-external.txt index 40e41ce1..6d55957 100644 --- a/content/test/data/accessibility/aria/aria-banner-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-banner-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Chromium Browser" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="banner", roleDescription="banner"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-braillelabel-expected-android-external.txt b/content/test/data/accessibility/aria/aria-braillelabel-expected-android-external.txt index d4a7bc5..d2abffa 100644 --- a/content/test/data/accessibility/aria/aria-braillelabel-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-braillelabel-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++CheckBox checkable clickable actions:[CLICK, AX_FOCUS] bundle:[brailleLabel="aria braille label", chromeRole="checkBox", roleDescription="checkbox"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-brailleroledescription-expected-android-external.txt b/content/test/data/accessibility/aria/aria-brailleroledescription-expected-android-external.txt index 94d9fd9..5ae37781 100644 --- a/content/test/data/accessibility/aria/aria-brailleroledescription-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-brailleroledescription-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++CheckBox checkable clickable actions:[CLICK, AX_FOCUS] bundle:[brailleRoleDescription="aria braille role description", chromeRole="checkBox", roleDescription="checkbox"] ++CheckBox checkable clickable actions:[CLICK, AX_FOCUS] bundle:[chromeRole="checkBox", roleDescription="checkbox"] ++CheckBox checkable clickable actions:[CLICK, AX_FOCUS] bundle:[chromeRole="checkBox", roleDescription="checkbox"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-busy-expected-android-external.txt b/content/test/data/accessibility/aria/aria-busy-expected-android-external.txt index 779bd928..d897c94 100644 --- a/content/test/data/accessibility/aria/aria-busy-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-busy-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Busy log" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="log", roleDescription="log"] ++View text:"Not-busy log" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="log", roleDescription="log"] ++TextView hint:"plain div" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hint="plain div"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-button-expected-android-external.txt b/content/test/data/accessibility/aria/aria-button-expected-android-external.txt index 2e4c46f..940fe1b 100644 --- a/content/test/data/accessibility/aria/aria-button-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-button-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++Button text:"Button1" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", roleDescription="button"] ++ToggleButton text:"Button2" stateDescription:"On" checkable checked clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="toggleButton", roleDescription="toggle button"] ++ToggleButton text:"Button3" stateDescription:"Off" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="toggleButton", roleDescription="toggle button"]
diff --git a/content/test/data/accessibility/aria/aria-cell-expected-android-external.txt b/content/test/data/accessibility/aria/aria-cell-expected-android-external.txt index 1e4b264..14a55f8 100644 --- a/content/test/data/accessibility/aria/aria-cell-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-cell-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=2, cols=2] actions:[AX_FOCUS] bundle:[chromeRole="table", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Browser" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/aria/aria-checkbox-expected-android-external.txt b/content/test/data/accessibility/aria/aria-checkbox-expected-android-external.txt index f50d173..ace5381 100644 --- a/content/test/data/accessibility/aria/aria-checkbox-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-checkbox-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++CheckBox text:"CheckBox1" checkable checked clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", roleDescription="checkbox"] ++CheckBox text:"CheckBox2" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", roleDescription="checkbox"] ++CheckBox text:"CheckBox3" stateDescription:"Partially Checked" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", roleDescription="checkbox"]
diff --git a/content/test/data/accessibility/aria/aria-checked-expected-android-external.txt b/content/test/data/accessibility/aria/aria-checked-expected-android-external.txt index 5dcd28a1..edd3d9e 100644 --- a/content/test/data/accessibility/aria/aria-checked-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-checked-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++CheckBox checkable checked clickable focusable actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="checkBox", roleDescription="checkbox"] ++CheckBox checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="checkBox", roleDescription="checkbox"] ++CheckBox stateDescription:"Partially Checked" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="checkBox", roleDescription="checkbox"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-code-expected-android-external.txt b/content/test/data/accessibility/aria/aria-code-expected-android-external.txt index fdc7a2b..5814aa1 100644 --- a/content/test/data/accessibility/aria/aria-code-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-code-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"role" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="code"] ++View text:"element (no name)" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="code"] ++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/aria/aria-col-attr-expected-android-external.txt b/content/test/data/accessibility/aria/aria-col-attr-expected-android-external.txt index a1dcfb95..473ca5b 100644 --- a/content/test/data/accessibility/aria/aria-col-attr-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-col-attr-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=2, cols=4] actions:[AX_FOCUS] bundle:[chromeRole="grid", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"cell 2" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/aria/aria-col-row-index-expected-android-external.txt b/content/test/data/accessibility/aria/aria-col-row-index-expected-android-external.txt index 4b53b2f..d119362 100644 --- a/content/test/data/accessibility/aria/aria-col-row-index-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-col-row-index-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=5, cols=4] actions:[AX_FOCUS] bundle:[chromeRole="table", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="rowGroup"] ++++++View actions:[AX_FOCUS] bundle:[chromeRole="row"]
diff --git a/content/test/data/accessibility/aria/aria-col-row-index-undefined-expected-android-external.txt b/content/test/data/accessibility/aria/aria-col-row-index-undefined-expected-android-external.txt index 8339213..b4a5955 100644 --- a/content/test/data/accessibility/aria/aria-col-row-index-undefined-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-col-row-index-undefined-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=3, cols=3] actions:[AX_FOCUS] bundle:[chromeRole="table", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="rowGroup"] ++++++View actions:[AX_FOCUS] bundle:[chromeRole="row"]
diff --git a/content/test/data/accessibility/aria/aria-columnheader-expected-android-external.txt b/content/test/data/accessibility/aria/aria-columnheader-expected-android-external.txt index 7d00566..da5b2ddf 100644 --- a/content/test/data/accessibility/aria/aria-columnheader-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-columnheader-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=3, cols=2] actions:[AX_FOCUS] bundle:[chromeRole="grid", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Browser" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/aria/aria-combobox-expected-android-external.txt b/content/test/data/accessibility/aria/aria-combobox-expected-android-external.txt index d27b5eed..8bde327 100644 --- a/content/test/data/accessibility/aria/aria-combobox-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-combobox-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable scrollable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"State" viewIdResName:"state_label" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++EditText hint:"State" canOpenPopUp clickable editable disabled focusable focused inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[CLEAR_FOCUS, CLICK, AX_FOCUS, COLLAPSE] bundle:[chromeRole="textFieldWithComboBox", clickableScore="300", hint="State"] ++ListView viewIdResName:"state_list" clickable CollectionInfo:[rows=2, cols=1] actions:[CLICK, AX_FOCUS] bundle:[chromeRole="listBox", clickableScore="300", roleDescription="list box"]
diff --git a/content/test/data/accessibility/aria/aria-combobox-implicit-haspopup-expected-android-external.txt b/content/test/data/accessibility/aria/aria-combobox-implicit-haspopup-expected-android-external.txt index c3ab803..dfe147a 100644 --- a/content/test/data/accessibility/aria/aria-combobox-implicit-haspopup-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-combobox-implicit-haspopup-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View hint:"ComboBoxGrouping" canOpenPopUp actions:[AX_FOCUS] bundle:[chromeRole="comboBoxGrouping", hint="ComboBoxGrouping"] ++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] ++EditText hint:"TextFieldWithComboBox" canOpenPopUp clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textFieldWithComboBox", clickableScore="300", hint="TextFieldWithComboBox"]
diff --git a/content/test/data/accessibility/aria/aria-combobox-uneditable-expected-android-external.txt b/content/test/data/accessibility/aria/aria-combobox-uneditable-expected-android-external.txt index 4b1bf0a..5d8fde0 100644 --- a/content/test/data/accessibility/aria/aria-combobox-uneditable-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-combobox-uneditable-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Choose a fruit, with text content" viewIdResName:"combo1-label" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++Spinner text:"Apple" hint:"Choose a fruit, with text content" canOpenPopUp clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="comboBoxMenuButton", hint="Choose a fruit, with text content"] ++ListView viewIdResName:"listbox1" clickable CollectionInfo:[rows=3, cols=1] actions:[CLICK, AX_FOCUS] bundle:[chromeRole="listBox", clickableScore="300", roleDescription="list box"]
diff --git a/content/test/data/accessibility/aria/aria-complementary-expected-android-external.txt b/content/test/data/accessibility/aria/aria-complementary-expected-android-external.txt index fb0bb77..65b236c2 100644 --- a/content/test/data/accessibility/aria/aria-complementary-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-complementary-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"This is ARIA role complementary." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="complementary", roleDescription="complementary"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-contentinfo-expected-android-external.txt b/content/test/data/accessibility/aria/aria-contentinfo-expected-android-external.txt index 570ea1e..e55b555b 100644 --- a/content/test/data/accessibility/aria/aria-contentinfo-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-contentinfo-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"This is ARIA role contentinfo." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="contentInfo", roleDescription="content information"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-controls-expected-android-external.txt b/content/test/data/accessibility/aria/aria-controls-expected-android-external.txt index 9dc7320..44d5db3 100644 --- a/content/test/data/accessibility/aria/aria-controls-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-controls-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="menuBar", roleDescription="menu bar"] ++++MenuItem text:"File" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItem", roleDescription="menu item"] ++++MenuItem text:"Edit" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItem", roleDescription="menu item"]
diff --git a/content/test/data/accessibility/aria/aria-current-expected-android-external.txt b/content/test/data/accessibility/aria/aria-current-expected-android-external.txt index 2ef06b2..8572452 100644 --- a/content/test/data/accessibility/aria/aria-current-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-current-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"null" contentDescription:"Section one" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/aria/aria-current.html#section1"] ++++TextView text:"Section one" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText", clickableScore="100"] ++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/aria/aria-definition-expected-android-external.txt b/content/test/data/accessibility/aria/aria-definition-expected-android-external.txt index 01f160b..3ba23d1 100644 --- a/content/test/data/accessibility/aria/aria-definition-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-definition-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="definition", roleDescription="definition"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-describedby-expected-android-external.txt b/content/test/data/accessibility/aria/aria-describedby-expected-android-external.txt index 45843907..400c6a8 100644 --- a/content/test/data/accessibility/aria/aria-describedby-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-describedby-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++EditText hint:"Your username should be your email id" viewIdResName:"username" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Your username should be your email id"] ++View text:"Your username should be your email id" viewIdResName:"username-tip" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="tooltip", roleDescription="tooltip"] ++EditText hint:"mmddyy" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="mmddyy"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-description-expected-android-external.txt b/content/test/data/accessibility/aria/aria-description-expected-android-external.txt index c9ca931..37ab48a 100644 --- a/content/test/data/accessibility/aria/aria-description-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-description-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"description" hint:"Text-description" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="Text-description"] ++TextView text:"both" hint:"Description from describedby" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="Description from describedby"] ++View text:"Description from describedby" viewIdResName:"desc1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="tooltip", roleDescription="tooltip"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-details-expected-android-external.txt b/content/test/data/accessibility/aria/aria-details-expected-android-external.txt index 4aad73b..92928b4 100644 --- a/content/test/data/accessibility/aria/aria-details-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-details-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] ++TextView text:"Details" viewIdResName:"details" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"]
diff --git a/content/test/data/accessibility/aria/aria-details-multiple-expected-android-external.txt b/content/test/data/accessibility/aria/aria-details-multiple-expected-android-external.txt index ca45526..095df63 100644 --- a/content/test/data/accessibility/aria/aria-details-multiple-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-details-multiple-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Some " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++View text:"highlighted text" viewIdResName:"annotated-text" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="mark", roleDescription="highlight"] ++TextView text:" example." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/aria/aria-dialog-expected-android-external.txt b/content/test/data/accessibility/aria/aria-dialog-expected-android-external.txt index 6673b514..c2df45f 100644 --- a/content/test/data/accessibility/aria/aria-dialog-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-dialog-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++Dialog text:"This is ARIA dialog." paneTitle:"dialog opened." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="dialog", roleDescription="dialog"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-directory-expected-android-external.txt b/content/test/data/accessibility/aria/aria-directory-expected-android-external.txt index aa2abe1..04f7ac88 100644 --- a/content/test/data/accessibility/aria/aria-directory-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-directory-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=0, cols=0] actions:[AX_FOCUS] bundle:[chromeRole="directory", roleDescription="directory"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-disabled-expected-android-external.txt b/content/test/data/accessibility/aria/aria-disabled-expected-android-external.txt index 9ae9a31..b9cfdc7 100644 --- a/content/test/data/accessibility/aria/aria-disabled-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-disabled-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] ++++EditText clickable editable disabled focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="textField"]
diff --git a/content/test/data/accessibility/aria/aria-document-expected-android-external.txt b/content/test/data/accessibility/aria/aria-document-expected-android-external.txt index 9801a8a0..e54d480 100644 --- a/content/test/data/accessibility/aria/aria-document-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-document-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"aria role document" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="document", roleDescription="document"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-emphasis-expected-android-external.txt b/content/test/data/accessibility/aria/aria-emphasis-expected-android-external.txt index 1fcf715e..beff8496 100644 --- a/content/test/data/accessibility/aria/aria-emphasis-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-emphasis-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"role" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="emphasis"] ++View text:"element (no name)" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="emphasis"] ++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/aria/aria-errormessage-expected-android-external.txt b/content/test/data/accessibility/aria/aria-errormessage-expected-android-external.txt index 3520c83f..19d9e69 100644 --- a/content/test/data/accessibility/aria/aria-errormessage-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-errormessage-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText hint:"Invalid is true" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Invalid is true"] ++++EditText hint:"Invalid is true with multiple errors" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Invalid is true with multiple errors"] @@ -7,4 +7,4 @@ ++TextView text:"Error for invalid input" viewIdResName:"error1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++TextView text:"Another error for invalid input" viewIdResName:"error2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++TextView text:"Error for input which is not invalid" viewIdResName:"error3" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] -++TextView text:"Error for input with invalid not set" viewIdResName:"error4" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] +++TextView text:"Error for input with invalid not set" viewIdResName:"error4" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-expanded-expected-android-external.txt b/content/test/data/accessibility/aria/aria-expanded-expected-android-external.txt index c4b84bea..7b2ff16 100644 --- a/content/test/data/accessibility/aria/aria-expanded-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-expanded-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="menu", roleDescription="menu"] ++++MenuItem text:"New" canOpenPopUp clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="menuItem", roleDescription="menu item"] ++++MenuItem text:"Open" canOpenPopUp clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, COLLAPSE] bundle:[chromeRole="menuItem", roleDescription="menu item"]
diff --git a/content/test/data/accessibility/aria/aria-figure-expected-android-external.txt b/content/test/data/accessibility/aria/aria-figure-expected-android-external.txt index a79c3cea..ab961bdb 100644 --- a/content/test/data/accessibility/aria/aria-figure-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-figure-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Figure" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="figure", roleDescription="graphic"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-flowto-expected-android-external.txt b/content/test/data/accessibility/aria/aria-flowto-expected-android-external.txt index b83d2901..365b0d1 100644 --- a/content/test/data/accessibility/aria/aria-flowto-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-flowto-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"current" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"] ++View text:"next" viewIdResName:"next" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="footer", roleDescription="footer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-form-expected-android-external.txt b/content/test/data/accessibility/aria/aria-form-expected-android-external.txt index aad7904..b068180 100644 --- a/content/test/data/accessibility/aria/aria-form-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-form-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Unnamed ARIA form: must fall back to the native role." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] ++TextView text:"Unnamed ARIA form on plain div uses generic container role." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++View text:"Named form" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="form"]
diff --git a/content/test/data/accessibility/aria/aria-generic-expected-android-external.txt b/content/test/data/accessibility/aria/aria-generic-expected-android-external.txt index fcd0cab..1cd90f5 100644 --- a/content/test/data/accessibility/aria/aria-generic-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-generic-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"content" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-grid-expected-android-external.txt b/content/test/data/accessibility/aria/aria-grid-expected-android-external.txt index 33e4e8c..a99719c 100644 --- a/content/test/data/accessibility/aria/aria-grid-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-grid-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=2, cols=2] actions:[AX_FOCUS] bundle:[chromeRole="grid", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Browser" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/aria/aria-gridcell-expected-android-external.txt b/content/test/data/accessibility/aria/aria-gridcell-expected-android-external.txt index 6d84742..824cdfc9 100644 --- a/content/test/data/accessibility/aria/aria-gridcell-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-gridcell-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView stateDescription:"multiselectable, none selected." CollectionInfo:[rows=2, cols=2] actions:[AX_FOCUS] bundle:[chromeRole="grid", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Browser" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/aria/aria-group-expected-android-external.txt b/content/test/data/accessibility/aria/aria-group-expected-android-external.txt index 6ab7082..2b8ab0f 100644 --- a/content/test/data/accessibility/aria/aria-group-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-group-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="group"] ++++View text:"null" contentDescription:"Group Link1" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", roleDescription="link"] ++++++TextView text:"Group Link1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/aria/aria-haspopup-expected-android-external.txt b/content/test/data/accessibility/aria/aria-haspopup-expected-android-external.txt index 56d349e..9248be6 100644 --- a/content/test/data/accessibility/aria/aria-haspopup-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-haspopup-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++Spinner canOpenPopUp clickable focusable actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="comboBoxMenuButton"] ++Spinner canOpenPopUp clickable focusable actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="comboBoxMenuButton"] ++Spinner canOpenPopUp clickable focusable actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="comboBoxMenuButton"]
diff --git a/content/test/data/accessibility/aria/aria-heading-expected-android-external.txt b/content/test/data/accessibility/aria/aria-heading-expected-android-external.txt index 742fa7d..838c5b15 100644 --- a/content/test/data/accessibility/aria/aria-heading-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-heading-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"ARIA Heading 1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 1"] ++TextView text:"ARIA Heading 2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 2"] ++TextView text:"ARIA Heading 3" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 3"]
diff --git a/content/test/data/accessibility/aria/aria-hidden-described-by-expected-android-external.txt b/content/test/data/accessibility/aria/aria-hidden-described-by-expected-android-external.txt index 5044297f..d93f97c9 100644 --- a/content/test/data/accessibility/aria/aria-hidden-described-by-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-hidden-described-by-expected-android-external.txt
@@ -1,6 +1,6 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++TextView text:"span-A" hint:"span-1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-1"] ++++TextView text:"span-B" hint:"span-2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-2"] ++++TextView text:"span-C" hint:"span-3" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-3"] -++++TextView text:"span-D" hint:"span-4" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-4"] +++++TextView text:"span-D" hint:"span-4" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-4"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-hidden-expected-android-external.txt b/content/test/data/accessibility/aria/aria-hidden-expected-android-external.txt index 52781ca5..6beb60b5 100644 --- a/content/test/data/accessibility/aria/aria-hidden-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-hidden-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"blockDisplay" viewIdResName:"blockDisplay" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"blockDisplay Hiddenfalse" viewIdResName:"blockDisplayAriaHiddenFalse" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"blockDisplay Hiddentruefocusable" viewIdResName:"blockDisplayAriaHiddenTrueFocusable" focusable notVisibleToUser actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-hidden-labelled-by-expected-android-external.txt b/content/test/data/accessibility/aria/aria-hidden-labelled-by-expected-android-external.txt index c877b10..de32d3a 100644 --- a/content/test/data/accessibility/aria/aria-hidden-labelled-by-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-hidden-labelled-by-expected-android-external.txt
@@ -1,8 +1,8 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++TextView text:"span-2" viewIdResName:"s2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++++TextView text:"span-4" viewIdResName:"s3" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++++View text:"span-1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] ++++View text:"span-2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] ++++View text:"span-3" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] -++++View text:"span-4" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] +++++View text:"span-4" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-illegal-val-expected-android-external.txt b/content/test/data/accessibility/aria/aria-illegal-val-expected-android-external.txt index 1fbb56b..cb5c1ae 100644 --- a/content/test/data/accessibility/aria/aria-illegal-val-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-illegal-val-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Atomic illegal" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="log", roleDescription="log"] ++EditText hint:"Autocomplete illegal" clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="Autocomplete illegal"] ++View text:"Busy illegal" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="log", roleDescription="log"]
diff --git a/content/test/data/accessibility/aria/aria-img-child-expected-android-external.txt b/content/test/data/accessibility/aria/aria-img-child-expected-android-external.txt index 7c32865..a1d88e7 100644 --- a/content/test/data/accessibility/aria/aria-img-child-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-img-child-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++Image actions:[AX_FOCUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-img-expected-android-external.txt b/content/test/data/accessibility/aria/aria-img-expected-android-external.txt index b1d24da..48a98d9 100644 --- a/content/test/data/accessibility/aria/aria-img-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-img-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++Image actions:[AX_FOCUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic"] ++Image actions:[AX_FOCUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-insertion-deletion-expected-android-external.txt b/content/test/data/accessibility/aria/aria-insertion-deletion-expected-android-external.txt index 83728cd..ee72e2f 100644 --- a/content/test/data/accessibility/aria/aria-insertion-deletion-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-insertion-deletion-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"] ++++TextView text:"My favorite browser is " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View text:"ABC" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="contentDeletion", roleDescription="deletion"]
diff --git a/content/test/data/accessibility/aria/aria-keyshortcuts-expected-android-external.txt b/content/test/data/accessibility/aria/aria-keyshortcuts-expected-android-external.txt index 6a47677..e8ad763 100644 --- a/content/test/data/accessibility/aria/aria-keyshortcuts-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-keyshortcuts-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Button text:"Cut" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] ++++Button text:"Copy" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"]
diff --git a/content/test/data/accessibility/aria/aria-label-augment-inner-text-expected-android-external.txt b/content/test/data/accessibility/aria/aria-label-augment-inner-text-expected-android-external.txt index 6186c79..061856faa 100644 --- a/content/test/data/accessibility/aria/aria-label-augment-inner-text-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-label-augment-inner-text-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"null" contentDescription:"Link" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/aria/aria-label-augment-inner-text.html#"] ++++++TextView text:"Link" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText", clickableScore="100"]
diff --git a/content/test/data/accessibility/aria/aria-label-expected-android-external.txt b/content/test/data/accessibility/aria/aria-label-expected-android-external.txt index 6bcc748..34d70057 100644 --- a/content/test/data/accessibility/aria/aria-label-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-label-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++CheckBox text:"aria label" checkable clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", roleDescription="checkbox"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-labelledby-heading-expected-android-external.txt b/content/test/data/accessibility/aria/aria-labelledby-heading-expected-android-external.txt index 827ed142..7dd32576 100644 --- a/content/test/data/accessibility/aria/aria-labelledby-heading-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-labelledby-heading-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++EditText hint:"h2" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="h2"] ++TextView text:"h2" viewIdResName:"h2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 2"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-list-expected-android-external.txt b/content/test/data/accessibility/aria/aria-list-expected-android-external.txt index 4fbfb230..b073c7d 100644 --- a/content/test/data/accessibility/aria/aria-list-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-list-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=3, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View text:"1" CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listItem"] ++++View text:"2" CollectionItemInfo:[rowIndex=1, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listItem"]
diff --git a/content/test/data/accessibility/aria/aria-listbox-aria-selected-expected-android-external.txt b/content/test/data/accessibility/aria/aria-listbox-aria-selected-expected-android-external.txt index f5a70d4..8dc35486 100644 --- a/content/test/data/accessibility/aria/aria-listbox-aria-selected-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-listbox-aria-selected-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView stateDescription:"multiselectable, 2 of 5 selected." clickable CollectionInfo:[rows=5, cols=1] actions:[CLICK, AX_FOCUS] bundle:[chromeRole="listBox", roleDescription="list box"] ++++View text:"Item 1" viewIdResName:"it1" focusable CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBoxOption"] ++++View text:"Item 2" viewIdResName:"it2" focusable CollectionItemInfo:[rowIndex=1, colIndex=0] actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBoxOption"]
diff --git a/content/test/data/accessibility/aria/aria-listbox-disabled-expected-android-external.txt b/content/test/data/accessibility/aria/aria-listbox-disabled-expected-android-external.txt index 97f6f48..6c1747f8 100644 --- a/content/test/data/accessibility/aria/aria-listbox-disabled-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-listbox-disabled-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Start of test: striped should have selected state" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 1"] ++ListView clickable disabled CollectionInfo:[rows=4, cols=1] actions:[CLICK, AX_FOCUS] bundle:[chromeRole="listBox", roleDescription="list box"] ++++View text:"Orange" disabled focusable CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBoxOption"]
diff --git a/content/test/data/accessibility/aria/aria-listbox-expected-android-external.txt b/content/test/data/accessibility/aria/aria-listbox-expected-android-external.txt index 30773a58..bde6a3e 100644 --- a/content/test/data/accessibility/aria/aria-listbox-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-listbox-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView clickable CollectionInfo:[rows=4, cols=1] actions:[CLICK, AX_FOCUS] bundle:[chromeRole="listBox", clickableScore="300", roleDescription="list box"] ++++View text:"Item 1" clickable focusable CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBoxOption", clickableScore="200"] ++++View text:"Item 2" clickable focusable CollectionItemInfo:[rowIndex=1, colIndex=0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBoxOption", clickableScore="200"]
diff --git a/content/test/data/accessibility/aria/aria-listitem-expected-android-external.txt b/content/test/data/accessibility/aria/aria-listitem-expected-android-external.txt index 060117e..3a9d503c 100644 --- a/content/test/data/accessibility/aria/aria-listitem-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-listitem-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=2, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View text:"1" CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listItem"] ++++View text:"2" CollectionItemInfo:[rowIndex=1, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listItem"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-live-expected-android-external.txt b/content/test/data/accessibility/aria/aria-live-expected-android-external.txt index 32a039e..fb7f579 100644 --- a/content/test/data/accessibility/aria/aria-live-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-live-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="marquee", roleDescription="marquee"] ++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="marquee", roleDescription="marquee"] ++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="marquee", roleDescription="marquee"]
diff --git a/content/test/data/accessibility/aria/aria-live-with-content-expected-android-external.txt b/content/test/data/accessibility/aria/aria-live-with-content-expected-android-external.txt index db048c66..09e8aa89 100644 --- a/content/test/data/accessibility/aria/aria-live-with-content-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-live-with-content-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Off" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="marquee", roleDescription="marquee"] ++View text:"Polite" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="marquee", roleDescription="marquee"] ++View text:"Assertive" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="marquee", roleDescription="marquee"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-log-expected-android-external.txt b/content/test/data/accessibility/aria/aria-log-expected-android-external.txt index 26ce2e6a..fcce233 100644 --- a/content/test/data/accessibility/aria/aria-log-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-log-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="log", roleDescription="log"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-main-expected-android-external.txt b/content/test/data/accessibility/aria/aria-main-expected-android-external.txt index a9ec597..6cb11b7 100644 --- a/content/test/data/accessibility/aria/aria-main-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-main-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="main", roleDescription="main"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-marquee-expected-android-external.txt b/content/test/data/accessibility/aria/aria-marquee-expected-android-external.txt index c1a5960..764b47dc 100644 --- a/content/test/data/accessibility/aria/aria-marquee-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-marquee-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="marquee", roleDescription="marquee"] ++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="marquee", roleDescription="marquee"] ++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="marquee", roleDescription="marquee"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-math-expected-android-external.txt b/content/test/data/accessibility/aria/aria-math-expected-android-external.txt index ea80674..aec6ee80 100644 --- a/content/test/data/accessibility/aria/aria-math-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-math-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"ARIA role math." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="math", roleDescription="math"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-menu-expected-android-external.txt b/content/test/data/accessibility/aria/aria-menu-expected-android-external.txt index b3fe52a..ab7eeaf 100644 --- a/content/test/data/accessibility/aria/aria-menu-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-menu-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="menuBar", roleDescription="menu bar"] ++++MenuItem text:"File" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItem", roleDescription="menu item"] ++++MenuItem text:"Edit" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItem", roleDescription="menu item"]
diff --git a/content/test/data/accessibility/aria/aria-menubar-expected-android-external.txt b/content/test/data/accessibility/aria/aria-menubar-expected-android-external.txt index 6319eb4f..a6a9612 100644 --- a/content/test/data/accessibility/aria/aria-menubar-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-menubar-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="menuBar", roleDescription="menu bar"] ++++MenuItem text:"File" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItem", roleDescription="menu item"] ++++MenuItem text:"Edit" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItem", roleDescription="menu item"]
diff --git a/content/test/data/accessibility/aria/aria-menuitem-expected-android-external.txt b/content/test/data/accessibility/aria/aria-menuitem-expected-android-external.txt index 0116223..78e4df5 100644 --- a/content/test/data/accessibility/aria/aria-menuitem-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-menuitem-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="menu", roleDescription="menu"] ++++MenuItem text:"File" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItem", roleDescription="menu item"] ++++MenuItem text:"Edit" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItem", roleDescription="menu item"]
diff --git a/content/test/data/accessibility/aria/aria-menuitem-in-group-expected-android-external.txt b/content/test/data/accessibility/aria/aria-menuitem-in-group-expected-android-external.txt index f2147559..cd5c32b 100644 --- a/content/test/data/accessibility/aria/aria-menuitem-in-group-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-menuitem-in-group-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="group"] ++++MenuItem text:"Menu item" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItem", roleDescription="menu item"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-menuitemcheckbox-expected-android-external.txt b/content/test/data/accessibility/aria/aria-menuitemcheckbox-expected-android-external.txt index 1b51862..acb1d259 100644 --- a/content/test/data/accessibility/aria/aria-menuitemcheckbox-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-menuitemcheckbox-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="menu", roleDescription="menu"] ++++MenuItem text:"Menu item 1" checkable clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItemCheckBox", roleDescription="checkbox"] ++++MenuItem text:"Menu item 2" checkable checked clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItemCheckBox", roleDescription="checkbox"]
diff --git a/content/test/data/accessibility/aria/aria-menuitemradio-expected-android-external.txt b/content/test/data/accessibility/aria/aria-menuitemradio-expected-android-external.txt index 3b80cf58..61411ca 100644 --- a/content/test/data/accessibility/aria/aria-menuitemradio-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-menuitemradio-expected-android-external.txt
@@ -1,5 +1,5 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="menu", roleDescription="menu"] ++++MenuItem text:"Menu item 1" checkable clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItemRadio", roleDescription="radio button"] ++++MenuItem text:"Menu item 2" checkable checked clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItemRadio", roleDescription="radio button"] -++++MenuItem text:"Menu item 3" checkable clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItemRadio", roleDescription="radio button"] +++++MenuItem text:"Menu item 3" checkable clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItemRadio", roleDescription="radio button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-meter-expected-android-external.txt b/content/test/data/accessibility/aria/aria-meter-expected-android-external.txt index b9297ae..f662b46 100644 --- a/content/test/data/accessibility/aria/aria-meter-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-meter-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ProgressBar text:"half-way, funding" actions:[AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="meter", roleDescription="meter"] ++ProgressBar text:"10, funding" RangeInfo:[current=10.0, min=0.0, max=100.0] actions:[AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="meter", roleDescription="meter"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-mismatched-table-attr-expected-android-external.txt b/content/test/data/accessibility/aria/aria-mismatched-table-attr-expected-android-external.txt index 9171308..20ccca3f 100644 --- a/content/test/data/accessibility/aria/aria-mismatched-table-attr-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-mismatched-table-attr-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=3, cols=3] actions:[AX_FOCUS] bundle:[chromeRole="grid", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Column 1" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/aria/aria-multiline-expected-android-external.txt b/content/test/data/accessibility/aria/aria-multiline-expected-android-external.txt index f3464d3..51008f8 100644 --- a/content/test/data/accessibility/aria/aria-multiline-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-multiline-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++EditText clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField"] ++EditText clickable editable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-multiselectable-expected-android-external.txt b/content/test/data/accessibility/aria/aria-multiselectable-expected-android-external.txt index a619644..79076621 100644 --- a/content/test/data/accessibility/aria/aria-multiselectable-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-multiselectable-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView text:"My Listbox" stateDescription:"multiselectable, none selected." clickable focusable CollectionInfo:[rows=4, cols=1] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBox", clickableScore="300", roleDescription="list box"] ++ListView text:"My Listbox" stateDescription:"multiselectable, none selected." clickable focusable CollectionInfo:[rows=4, cols=1] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBox", clickableScore="300", roleDescription="list box"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-navigation-expected-android-external.txt b/content/test/data/accessibility/aria/aria-navigation-expected-android-external.txt index c772649d..67ac1a9 100644 --- a/content/test/data/accessibility/aria/aria-navigation-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-navigation-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="navigation", roleDescription="navigation"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-none-expected-android-external.txt b/content/test/data/accessibility/aria/aria-none-expected-android-external.txt index 6c6f1c5b..17932f3 100644 --- a/content/test/data/accessibility/aria/aria-none-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-none-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"With aria-role none" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-note-expected-android-external.txt b/content/test/data/accessibility/aria/aria-note-expected-android-external.txt index 7ebceea..a3437663 100644 --- a/content/test/data/accessibility/aria/aria-note-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-note-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="note", roleDescription="note"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-option-complex-children-expected-android-external.txt b/content/test/data/accessibility/aria/aria-option-complex-children-expected-android-external.txt index 3c102bc..3dd04f1 100644 --- a/content/test/data/accessibility/aria/aria-option-complex-children-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-option-complex-children-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView clickable CollectionInfo:[rows=2, cols=1] actions:[CLICK, AX_FOCUS] bundle:[chromeRole="listBox", roleDescription="list box"] ++++View text:"label-WAI-ARIA 1.1" viewIdResName:"opt1" focusable selected CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBoxOption"] ++++++View text:"null" hint:"title-WAI-ARIA 1.1" contentDescription:"href-WAI-ARIA 1.1" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="title-WAI-ARIA 1.1", roleDescription="link", targetUrl="https://www.w3.org/TR/wai-aria-practices-1.1/"]
diff --git a/content/test/data/accessibility/aria/aria-option-expected-android-external.txt b/content/test/data/accessibility/aria/aria-option-expected-android-external.txt index 045bdab9..0586ea1 100644 --- a/content/test/data/accessibility/aria/aria-option-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-option-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView clickable CollectionInfo:[rows=5, cols=1] actions:[CLICK, AX_FOCUS] bundle:[chromeRole="listBox", clickableScore="300", roleDescription="list box"] ++++View text:"option 1" viewIdResName:"opt1" clickable focusable CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBoxOption", clickableScore="200"] ++++View text:"label 2" viewIdResName:"opt2" clickable focusable CollectionItemInfo:[rowIndex=1, colIndex=0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBoxOption", clickableScore="200"]
diff --git a/content/test/data/accessibility/aria/aria-orientation-expected-android-external.txt b/content/test/data/accessibility/aria/aria-orientation-expected-android-external.txt index 52e27a5..2440e313 100644 --- a/content/test/data/accessibility/aria/aria-orientation-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-orientation-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View canOpenPopUp actions:[AX_FOCUS] bundle:[chromeRole="comboBoxGrouping"] ++View canOpenPopUp actions:[AX_FOCUS] bundle:[chromeRole="comboBoxGrouping"] ++View canOpenPopUp actions:[AX_FOCUS] bundle:[chromeRole="comboBoxGrouping"]
diff --git a/content/test/data/accessibility/aria/aria-owns-expected-android-external.txt b/content/test/data/accessibility/aria/aria-owns-expected-android-external.txt index 13cddcc..1ee5adb 100644 --- a/content/test/data/accessibility/aria/aria-owns-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-owns-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=3, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS] bundle:[chromeRole="listItem"] ++++++View text:"• " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listMarker"]
diff --git a/content/test/data/accessibility/aria/aria-owns-from-display-none-expected-android-external.txt b/content/test/data/accessibility/aria/aria-owns-from-display-none-expected-android-external.txt index 7db6adb..3b0d5e0 100644 --- a/content/test/data/accessibility/aria/aria-owns-from-display-none-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-owns-from-display-none-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++EditText viewIdResName:"input-0" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-owns-ignored-expected-android-external.txt b/content/test/data/accessibility/aria/aria-owns-ignored-expected-android-external.txt index e75328b..b7e677e 100644 --- a/content/test/data/accessibility/aria/aria-owns-ignored-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-owns-ignored-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Ordinary presentation element with id" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="splitter", roleDescription="splitter"] ++View text:"An aria-owned element is never ignored" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="splitter", roleDescription="splitter"] ++View actions:[AX_FOCUS] bundle:[chromeRole="group"]
diff --git a/content/test/data/accessibility/aria/aria-owns-list-expected-android-external.txt b/content/test/data/accessibility/aria/aria-owns-list-expected-android-external.txt index f74756a..2f352632 100644 --- a/content/test/data/accessibility/aria/aria-owns-list-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-owns-list-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=2, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View text:"One" viewIdResName:"one" CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listItem"] ++++View text:"Two" viewIdResName:"two" CollectionItemInfo:[rowIndex=1, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listItem"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-presentation-expected-android-external.txt b/content/test/data/accessibility/aria/aria-presentation-expected-android-external.txt index a7eee56..5a123f1 100644 --- a/content/test/data/accessibility/aria/aria-presentation-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-presentation-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"aria-role presentation" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-presentation-in-list-expected-android-external.txt b/content/test/data/accessibility/aria/aria-presentation-in-list-expected-android-external.txt index ff9f0520..5e06803 100644 --- a/content/test/data/accessibility/aria/aria-presentation-in-list-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-presentation-in-list-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=2, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS] bundle:[chromeRole="listItem"] ++++++View text:"• " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listMarker"]
diff --git a/content/test/data/accessibility/aria/aria-pressed-expected-android-external.txt b/content/test/data/accessibility/aria/aria-pressed-expected-android-external.txt index c3f49aea..4d36227ee 100644 --- a/content/test/data/accessibility/aria/aria-pressed-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-pressed-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++Button text:"Regular button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", roleDescription="button"] ++ToggleButton text:"Toggle button unpressed" stateDescription:"Off" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="toggleButton", roleDescription="toggle button"] ++ToggleButton text:"Toggle button pressed" stateDescription:"On" checkable checked clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="toggleButton", roleDescription="toggle button"]
diff --git a/content/test/data/accessibility/aria/aria-progressbar-expected-android-external.txt b/content/test/data/accessibility/aria/aria-progressbar-expected-android-external.txt index 49390fd1..05948f1 100644 --- a/content/test/data/accessibility/aria/aria-progressbar-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-progressbar-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ProgressBar text:"3" RangeInfo:[current=3.0, min=1.0, max=37.0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="progressIndicator", roleDescription="progress indicator"] ++ProgressBar text:"three" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="progressIndicator", roleDescription="progress indicator"] ++ProgressBar text:"indeterminate" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="progressIndicator", roleDescription="progress indicator"]
diff --git a/content/test/data/accessibility/aria/aria-radio-expected-android-external.txt b/content/test/data/accessibility/aria/aria-radio-expected-android-external.txt index 8ca9400..37a080c1 100644 --- a/content/test/data/accessibility/aria/aria-radio-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-radio-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++RadioButton text:"Radio1" checkable clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="radioButton", roleDescription="radio button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-radiogroup-expected-android-external.txt b/content/test/data/accessibility/aria/aria-radiogroup-expected-android-external.txt index f5bd69c4..614dc11a 100644 --- a/content/test/data/accessibility/aria/aria-radiogroup-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-radiogroup-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++RadioGroup text:"My group" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="radioGroup", roleDescription="radio group"] ++++RadioButton text:"Radio 1" stateDescription:"Not checked. In group, option 1 of 2" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="radioButton", roleDescription="radio button"] ++++RadioButton text:"Radio 2" stateDescription:"Not checked. In group, option 2 of 2" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="radioButton", roleDescription="radio button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-readonly-expected-android-external.txt b/content/test/data/accessibility/aria/aria-readonly-expected-android-external.txt index 927e2c4..9ff5390 100644 --- a/content/test/data/accessibility/aria/aria-readonly-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-readonly-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText text:"Readonly-false input" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"]
diff --git a/content/test/data/accessibility/aria/aria-region-expected-android-external.txt b/content/test/data/accessibility/aria/aria-region-expected-android-external.txt index 2c083bc..5633837 100644 --- a/content/test/data/accessibility/aria/aria-region-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-region-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Unnamed ARIA region: must fall back to the native role." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] ++TextView text:"Unnamed ARIA region on plain div uses generic container role." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++View text:"Named region" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"]
diff --git a/content/test/data/accessibility/aria/aria-relevant-expected-android-external.txt b/content/test/data/accessibility/aria/aria-relevant-expected-android-external.txt index 9517a35a..0ec7a19 100644 --- a/content/test/data/accessibility/aria/aria-relevant-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-relevant-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="log", roleDescription="log"] ++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="log", roleDescription="log"] ++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="log", roleDescription="log"]
diff --git a/content/test/data/accessibility/aria/aria-required-expected-android-external.txt b/content/test/data/accessibility/aria/aria-required-expected-android-external.txt index a2b7f21..1ee3418 100644 --- a/content/test/data/accessibility/aria/aria-required-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-required-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++RadioGroup actions:[AX_FOCUS] bundle:[chromeRole="radioGroup", roleDescription="radio group"] ++++RadioButton stateDescription:"Not checked. In group, option 1 of 2" checkable clickable actions:[CLICK, AX_FOCUS] bundle:[chromeRole="radioButton", roleDescription="radio button"] ++++RadioButton stateDescription:"Not checked. In group, option 2 of 2" checkable clickable actions:[CLICK, AX_FOCUS] bundle:[chromeRole="radioButton", roleDescription="radio button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-roledescription-expected-android-external.txt b/content/test/data/accessibility/aria/aria-roledescription-expected-android-external.txt index 23c7814..b320d96 100644 --- a/content/test/data/accessibility/aria/aria-roledescription-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-roledescription-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++Button text:"Native button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] ++Button text:"ARIA button" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", roleDescription="button"] ++Button text:"Clicky button" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", roleDescription="Clicky"]
diff --git a/content/test/data/accessibility/aria/aria-row-attr-expected-android-external.txt b/content/test/data/accessibility/aria/aria-row-attr-expected-android-external.txt index 3ace529..f6138c6 100644 --- a/content/test/data/accessibility/aria/aria-row-attr-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-row-attr-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=2, cols=3] actions:[AX_FOCUS] bundle:[chromeRole="grid", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"cell 2" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/aria/aria-row-expected-android-external.txt b/content/test/data/accessibility/aria/aria-row-expected-android-external.txt index 7d00566..da5b2ddf 100644 --- a/content/test/data/accessibility/aria/aria-row-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-row-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=3, cols=2] actions:[AX_FOCUS] bundle:[chromeRole="grid", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Browser" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/aria/aria-rowgroup-expected-android-external.txt b/content/test/data/accessibility/aria/aria-rowgroup-expected-android-external.txt index fec40ac..5122d67 100644 --- a/content/test/data/accessibility/aria/aria-rowgroup-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-rowgroup-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=0, cols=0] actions:[AX_FOCUS] bundle:[chromeRole="grid", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="rowGroup"] ++++++View actions:[AX_FOCUS] bundle:[chromeRole="row"]
diff --git a/content/test/data/accessibility/aria/aria-rowheader-expected-android-external.txt b/content/test/data/accessibility/aria/aria-rowheader-expected-android-external.txt index 44fca4b..c4d6115 100644 --- a/content/test/data/accessibility/aria/aria-rowheader-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-rowheader-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=2, cols=3] actions:[AX_FOCUS] bundle:[chromeRole="grid", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Browser" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rowHeader", roleDescription="row header"]
diff --git a/content/test/data/accessibility/aria/aria-scrollbar-expected-android-external.txt b/content/test/data/accessibility/aria/aria-scrollbar-expected-android-external.txt index 6307f97..f29ec87 100644 --- a/content/test/data/accessibility/aria/aria-scrollbar-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-scrollbar-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"55" clickable focusable RangeInfo:[current=55.0, min=0.0, max=100.0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="scrollBar", roleDescription="scroll bar"] ++View text:"55" clickable focusable RangeInfo:[current=55.0, min=0.0, max=100.0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="scrollBar", roleDescription="scroll bar"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-search-expected-android-external.txt b/content/test/data/accessibility/aria/aria-search-expected-android-external.txt index 66f19414..c202e065 100644 --- a/content/test/data/accessibility/aria/aria-search-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-search-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"ARIA role search." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="search", roleDescription="search"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-selected-expected-android-external.txt b/content/test/data/accessibility/aria/aria-selected-expected-android-external.txt index 09b0380..ed62a60 100644 --- a/content/test/data/accessibility/aria/aria-selected-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-selected-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView clickable CollectionInfo:[rows=2, cols=1] actions:[CLICK, AX_FOCUS] bundle:[chromeRole="listBox", clickableScore="300", roleDescription="list box"] ++++View text:"1" clickable focusable selected CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBoxOption", clickableScore="200"] ++++View text:"2" clickable focusable CollectionItemInfo:[rowIndex=1, colIndex=0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBoxOption", clickableScore="200"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-separator-expected-android-external.txt b/content/test/data/accessibility/aria/aria-separator-expected-android-external.txt index e3b9276..25ca81b9 100644 --- a/content/test/data/accessibility/aria/aria-separator-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-separator-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Before" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++View actions:[AX_FOCUS] bundle:[chromeRole="splitter", roleDescription="splitter"] ++View text:"1" clickable focusable RangeInfo:[current=1.0, min=1.0, max=3.0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="splitter", roleDescription="splitter"]
diff --git a/content/test/data/accessibility/aria/aria-setsize-expected-android-external.txt b/content/test/data/accessibility/aria/aria-setsize-expected-android-external.txt index aefccd2..fb11c9e 100644 --- a/content/test/data/accessibility/aria/aria-setsize-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-setsize-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView clickable CollectionInfo:[rows=4, cols=1] actions:[CLICK, AX_FOCUS] bundle:[chromeRole="listBox", clickableScore="300", roleDescription="list box"] ++++View text:"Item 1" clickable focusable CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBoxOption", clickableScore="200"] ++++View text:"Item 2" clickable focusable CollectionItemInfo:[rowIndex=1, colIndex=0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBoxOption", clickableScore="200"]
diff --git a/content/test/data/accessibility/aria/aria-slider-expected-android-external.txt b/content/test/data/accessibility/aria/aria-slider-expected-android-external.txt index 742c4b4..7e585195 100644 --- a/content/test/data/accessibility/aria/aria-slider-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-slider-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++SeekBar text:"5" clickable RangeInfo:[current=5.0, min=1.0, max=10.0] actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-sort-aria-grid-expected-android-external.txt b/content/test/data/accessibility/aria/aria-sort-aria-grid-expected-android-external.txt index 2e1922c..39587b42 100644 --- a/content/test/data/accessibility/aria/aria-sort-aria-grid-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-sort-aria-grid-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=3, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="grid", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Alphabet" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/aria/aria-sort-html-table-expected-android-external.txt b/content/test/data/accessibility/aria/aria-sort-html-table-expected-android-external.txt index 70aacb78..e991d39 100644 --- a/content/test/data/accessibility/aria/aria-sort-html-table-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-sort-html-table-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView text:"Data table" CollectionInfo:[rows=3, cols=1] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="table", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Alphabet" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/aria/aria-status-expected-android-external.txt b/content/test/data/accessibility/aria/aria-status-expected-android-external.txt index 439c4d2..76a9e85 100644 --- a/content/test/data/accessibility/aria/aria-status-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-status-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="status", roleDescription="status"] ++View actions:[AX_FOCUS] bundle:[chromeRole="status", roleDescription="status"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-strong-expected-android-external.txt b/content/test/data/accessibility/aria/aria-strong-expected-android-external.txt index 6c959d8..2b7ff5c 100644 --- a/content/test/data/accessibility/aria/aria-strong-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-strong-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"role" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="strong"] ++View text:"element (no name)" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="strong"] ++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/aria/aria-subscript-expected-android-external.txt b/content/test/data/accessibility/aria/aria-subscript-expected-android-external.txt index 7d02eee..7572b12f 100644 --- a/content/test/data/accessibility/aria/aria-subscript-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-subscript-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"] ++++TextView text:"This text contains " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View text:"subscript" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="subscript"]
diff --git a/content/test/data/accessibility/aria/aria-superscript-expected-android-external.txt b/content/test/data/accessibility/aria/aria-superscript-expected-android-external.txt index 08ed889..448e90d8 100644 --- a/content/test/data/accessibility/aria/aria-superscript-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-superscript-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"] ++++TextView text:"This text contains " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View text:"superscript" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="superscript"]
diff --git a/content/test/data/accessibility/aria/aria-switch-expected-android-external.txt b/content/test/data/accessibility/aria/aria-switch-expected-android-external.txt index d5689983..a999ffa 100644 --- a/content/test/data/accessibility/aria/aria-switch-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-switch-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ToggleButton text:"Switch1" stateDescription:"Off" checkable clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="switch", roleDescription="switch"] ++ToggleButton text:"Switch2" stateDescription:"Off" checkable clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="switch", roleDescription="switch"] ++ToggleButton text:"Switch3" stateDescription:"On" checkable checked clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="switch", roleDescription="switch"]
diff --git a/content/test/data/accessibility/aria/aria-tab-expected-android-external.txt b/content/test/data/accessibility/aria/aria-tab-expected-android-external.txt index ae765fc..cb73203 100644 --- a/content/test/data/accessibility/aria/aria-tab-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-tab-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TabWidget actions:[AX_FOCUS] bundle:[chromeRole="tabList", roleDescription="tab list"] ++++View text:"Tab 1" viewIdResName:"tab1" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="tab", roleDescription="tab"] ++++View text:"Tab 2" viewIdResName:"tab2" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="tab", roleDescription="tab"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-tab-nested-in-lists-expected-android-external.txt b/content/test/data/accessibility/aria/aria-tab-nested-in-lists-expected-android-external.txt index 0f5b376..0b21b61 100644 --- a/content/test/data/accessibility/aria/aria-tab-nested-in-lists-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-tab-nested-in-lists-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TabWidget actions:[AX_FOCUS] bundle:[chromeRole="tabList", roleDescription="tab list"] ++++View text:"tab1" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="tab", roleDescription="tab"] ++++View text:"tab2" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="tab", roleDescription="tab"]
diff --git a/content/test/data/accessibility/aria/aria-table-expected-android-external.txt b/content/test/data/accessibility/aria/aria-table-expected-android-external.txt index 1e4b264..14a55f8 100644 --- a/content/test/data/accessibility/aria/aria-table-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-table-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=2, cols=2] actions:[AX_FOCUS] bundle:[chromeRole="table", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Browser" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/aria/aria-tablist-aria-level-expected-android-external.txt b/content/test/data/accessibility/aria/aria-tablist-aria-level-expected-android-external.txt index 040eb8ac..9a219fe 100644 --- a/content/test/data/accessibility/aria/aria-tablist-aria-level-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-tablist-aria-level-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TabWidget actions:[AX_FOCUS] bundle:[chromeRole="tabList", roleDescription="tab list"] ++++View text:"Tab 1 of 2, level 1" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="tab", roleDescription="tab"] ++++View text:"Tab 2 of 2, level 1" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="tab", roleDescription="tab"]
diff --git a/content/test/data/accessibility/aria/aria-tablist-expected-android-external.txt b/content/test/data/accessibility/aria/aria-tablist-expected-android-external.txt index fc5fa3f8..0f510b7 100644 --- a/content/test/data/accessibility/aria/aria-tablist-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-tablist-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TabWidget actions:[AX_FOCUS] bundle:[chromeRole="tabList", roleDescription="tab list"] ++++View text:"Tab 1, level 1" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="tab", roleDescription="tab"] ++++View text:"Tab 2, level 1" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="tab", roleDescription="tab"]
diff --git a/content/test/data/accessibility/aria/aria-tabpanel-expected-android-external.txt b/content/test/data/accessibility/aria/aria-tabpanel-expected-android-external.txt index daeddedd..dc5286d 100644 --- a/content/test/data/accessibility/aria/aria-tabpanel-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-tabpanel-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TabWidget actions:[AX_FOCUS] bundle:[chromeRole="tabList", roleDescription="tab list"] ++++View text:"Item" viewIdResName:"item" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="tab", roleDescription="tab"] ++++++TextView text:"Item" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 3"]
diff --git a/content/test/data/accessibility/aria/aria-term-expected-android-external.txt b/content/test/data/accessibility/aria/aria-term-expected-android-external.txt index be86ff5..a7be000 100644 --- a/content/test/data/accessibility/aria/aria-term-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-term-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=0, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View text:"Term1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="term", roleDescription="term"] ++++View text:"Definition1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="definition", roleDescription="definition"]
diff --git a/content/test/data/accessibility/aria/aria-textbox-expected-android-external.txt b/content/test/data/accessibility/aria/aria-textbox-expected-android-external.txt index 0252af40..b523f6b 100644 --- a/content/test/data/accessibility/aria/aria-textbox-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-textbox-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++EditText text:"\n TextBox1\n " clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] ++EditText text:"\n TextBox2\n " clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-textbox-with-aria-textbox-child-expected-android-external.txt b/content/test/data/accessibility/aria/aria-textbox-with-aria-textbox-child-expected-android-external.txt index 4d3b6102..8443b5f 100644 --- a/content/test/data/accessibility/aria/aria-textbox-with-aria-textbox-child-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-textbox-with-aria-textbox-child-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++EditText text:"Foo\nBar\nBar\nBaz\nBaz" hint:"not editable" clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="not editable"] ++++TextView text:"Foo" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++++EditText text:"Bar" hint:"nested, not editable, rich" clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="nested, not editable, rich"]
diff --git a/content/test/data/accessibility/aria/aria-textbox-with-non-text-children-expected-android-external.txt b/content/test/data/accessibility/aria/aria-textbox-with-non-text-children-expected-android-external.txt index ad61df3..664f712 100644 --- a/content/test/data/accessibility/aria/aria-textbox-with-non-text-children-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-textbox-with-non-text-children-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++EditText text:"focusable: oklink name: \n" hint:"not editable" clickable editable focusable textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="not editable"] ++++TextView text:"focusable: " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++Button text:"ok" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"]
diff --git a/content/test/data/accessibility/aria/aria-time-expected-android-external.txt b/content/test/data/accessibility/aria/aria-time-expected-android-external.txt index 9e91fe6..ed023942 100644 --- a/content/test/data/accessibility/aria/aria-time-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-time-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"role" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="time"] ++View text:"element (no name)" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="time"] ++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/aria/aria-timer-expected-android-external.txt b/content/test/data/accessibility/aria/aria-timer-expected-android-external.txt index 4812f18..0b2f346e 100644 --- a/content/test/data/accessibility/aria/aria-timer-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-timer-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"This test is for aria-role = timer" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="timer", roleDescription="timer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-togglebutton-expected-android-external.txt b/content/test/data/accessibility/aria/aria-togglebutton-expected-android-external.txt index 5e629fb..3e2684f 100644 --- a/content/test/data/accessibility/aria/aria-togglebutton-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-togglebutton-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++Button text:"Regular button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", roleDescription="button"] ++ToggleButton text:"Toggle button" stateDescription:"Off" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="toggleButton", roleDescription="toggle button"] ++ToggleButton text:"Toggle button" stateDescription:"On" checkable checked clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="toggleButton", roleDescription="toggle button"]
diff --git a/content/test/data/accessibility/aria/aria-toolbar-expected-android-external.txt b/content/test/data/accessibility/aria/aria-toolbar-expected-android-external.txt index cffeca7..6d0b705 100644 --- a/content/test/data/accessibility/aria/aria-toolbar-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-toolbar-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"A toolbar" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="toolbar", roleDescription="toolbar"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-tooltip-expected-android-external.txt b/content/test/data/accessibility/aria/aria-tooltip-expected-android-external.txt index 2450421..0a6bd93 100644 --- a/content/test/data/accessibility/aria/aria-tooltip-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-tooltip-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++EditText hint:"Your username should be your email id" viewIdResName:"username" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Your username should be your email id"] ++View text:"Your username should be your email id" viewIdResName:"username-tip" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="tooltip", roleDescription="tooltip"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-tree-discontinuous-expected-android-external.txt b/content/test/data/accessibility/aria/aria-tree-discontinuous-expected-android-external.txt index 0538103..0d2a7c8b 100644 --- a/content/test/data/accessibility/aria/aria-tree-discontinuous-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-tree-discontinuous-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View CollectionInfo:[hierarchical, rows=2, cols=0] actions:[AX_FOCUS] bundle:[chromeRole="tree", roleDescription="tree"] ++++View text:"card content" clickable focusable CollectionItemInfo:[rowSpan=0, colSpan=0, rowIndex=0, colIndex=0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="treeItem", roleDescription="tree item"] ++++TextView actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"]
diff --git a/content/test/data/accessibility/aria/aria-tree-expected-android-external.txt b/content/test/data/accessibility/aria/aria-tree-expected-android-external.txt index 5889231..1ea02c2 100644 --- a/content/test/data/accessibility/aria/aria-tree-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-tree-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View CollectionInfo:[hierarchical, rows=2, cols=0] actions:[AX_FOCUS] bundle:[chromeRole="tree", roleDescription="tree"] ++++View text:"Animals" stateDescription:"Partially Checked" clickable CollectionItemInfo:[rowSpan=0, colSpan=0, rowIndex=0, colIndex=0] actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="treeItem", roleDescription="tree item"] ++++++View text:"null" contentDescription:"Animals" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/aria/aria-tree.html#animals"]
diff --git a/content/test/data/accessibility/aria/aria-treegrid-expected-android-external.txt b/content/test/data/accessibility/aria/aria-treegrid-expected-android-external.txt index efa3970..de13e43 100644 --- a/content/test/data/accessibility/aria/aria-treegrid-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-treegrid-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView clickable CollectionInfo:[rows=3, cols=2] actions:[CLICK, AX_FOCUS] bundle:[chromeRole="treeGrid", roleDescription="tree grid"] ++++View text:"Cell 1, row 1, level 1 Cell 2, row 1, level 1" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="row"] ++++++View text:"Cell 1, row 1, level 1" CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="cell"]
diff --git a/content/test/data/accessibility/aria/aria-treeitem-nested-in-lists-expected-android-external.txt b/content/test/data/accessibility/aria/aria-treeitem-nested-in-lists-expected-android-external.txt index 8785e4b..f0df461 100644 --- a/content/test/data/accessibility/aria/aria-treeitem-nested-in-lists-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-treeitem-nested-in-lists-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View CollectionInfo:[hierarchical, rows=5, cols=0] actions:[AX_FOCUS] bundle:[chromeRole="tree", roleDescription="tree"] ++++View text:"treeitem 2 of 5, level 1" clickable CollectionItemInfo:[rowSpan=0, colSpan=0, rowIndex=1, colIndex=0] actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="treeItem", roleDescription="tree item"] ++++View text:"treeitem 3 of 5, level 1" clickable CollectionItemInfo:[rowSpan=0, colSpan=0, rowIndex=2, colIndex=0] actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="treeItem", roleDescription="tree item"] @@ -15,4 +15,4 @@ ++++++++TextView text:"tasks" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++++++View text:"meeting" clickable CollectionItemInfo:[rowSpan=0, colSpan=0, rowIndex=0, colIndex=0] actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="treeItem", roleDescription="tree item"] ++++++++View text:"lunch" clickable CollectionItemInfo:[rowSpan=0, colSpan=0, rowIndex=1, colIndex=0] actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="treeItem", roleDescription="tree item"] -++++View text:"cook dinner" clickable CollectionItemInfo:[rowSpan=0, colSpan=0, rowIndex=2, colIndex=0] actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="treeItem", roleDescription="tree item"] +++++View text:"cook dinner" clickable CollectionItemInfo:[rowSpan=0, colSpan=0, rowIndex=2, colIndex=0] actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="treeItem", roleDescription="tree item"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-valuenow-expected-android-external.txt b/content/test/data/accessibility/aria/aria-valuenow-expected-android-external.txt index 810d90a..3c6ed73 100644 --- a/content/test/data/accessibility/aria/aria-valuenow-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-valuenow-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ProgressBar text:"3" RangeInfo:[current=3.0, min=0.0, max=100.0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="progressIndicator", roleDescription="progress indicator"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-valuetext-expected-android-external.txt b/content/test/data/accessibility/aria/aria-valuetext-expected-android-external.txt index 7c937ab..e2ac769 100644 --- a/content/test/data/accessibility/aria/aria-valuetext-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-valuetext-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ProgressBar text:"three" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="progressIndicator", roleDescription="progress indicator"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-virtualcontent-expected-android-external.txt b/content/test/data/accessibility/aria/aria-virtualcontent-expected-android-external.txt index 29562520..7ad39393e 100644 --- a/content/test/data/accessibility/aria/aria-virtualcontent-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-virtualcontent-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"hello world" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/dpub-roles-expected-android-external.txt b/content/test/data/accessibility/aria/dpub-roles-expected-android-external.txt index e16163f1..f9616a5 100644 --- a/content/test/data/accessibility/aria/dpub-roles-expected-android-external.txt +++ b/content/test/data/accessibility/aria/dpub-roles-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View text:"doc-abstract" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="docAbstract", roleDescription="abstract"] ++View text:"doc-acknowledgments" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="docAcknowledgments", roleDescription="acknowledgments"] ++View text:"doc-afterword" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="docAfterword", roleDescription="afterword"]
diff --git a/content/test/data/accessibility/aria/graphics-roles-expected-android-external.txt b/content/test/data/accessibility/aria/graphics-roles-expected-android-external.txt index d314c82..af6bfb5b 100644 --- a/content/test/data/accessibility/aria/graphics-roles-expected-android-external.txt +++ b/content/test/data/accessibility/aria/graphics-roles-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View text:"graphics-document" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="graphicsDocument", roleDescription="graphics document"] ++View text:"graphics-object" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="graphicsObject", roleDescription="graphics object"] ++View text:"graphics-symbol" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="graphicsSymbol", hasImage="true", roleDescription="graphics symbol"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/hidden-described-by-expected-android-external.txt b/content/test/data/accessibility/aria/hidden-described-by-expected-android-external.txt index 2eb3030..4c472b0 100644 --- a/content/test/data/accessibility/aria/hidden-described-by-expected-android-external.txt +++ b/content/test/data/accessibility/aria/hidden-described-by-expected-android-external.txt
@@ -1,5 +1,5 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++TextView text:"span-A3" hint:"span-A4" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-A4"] ++++TextView text:"span-B" hint:"span-A2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-A2"] -++++TextView text:"span-C" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] +++++TextView text:"span-C" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/hidden-expected-android-external.txt b/content/test/data/accessibility/aria/hidden-expected-android-external.txt index 93d259e..620ac08 100644 --- a/content/test/data/accessibility/aria/hidden-expected-android-external.txt +++ b/content/test/data/accessibility/aria/hidden-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++TextView hint:"b" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hint="b"] -++++TextView hint:"c" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hint="c"] +++++TextView hint:"c" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hint="c"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/hidden-labelled-by-expected-android-external.txt b/content/test/data/accessibility/aria/hidden-labelled-by-expected-android-external.txt index ab12503..483f6003 100644 --- a/content/test/data/accessibility/aria/hidden-labelled-by-expected-android-external.txt +++ b/content/test/data/accessibility/aria/hidden-labelled-by-expected-android-external.txt
@@ -1,5 +1,5 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"span-A4" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] ++++View text:"span-A2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] -++++TextView text:"span-C" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] +++++TextView text:"span-C" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/input-text-aria-placeholder-expected-android-external.txt b/content/test/data/accessibility/aria/input-text-aria-placeholder-expected-android-external.txt index 0f468034..65dd2f1 100644 --- a/content/test/data/accessibility/aria/input-text-aria-placeholder-expected-android-external.txt +++ b/content/test/data/accessibility/aria/input-text-aria-placeholder-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++EditText hint:"aria-placeholder1" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="aria-placeholder1"] ++EditText hint:"placeholder2" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="placeholder2"] ++EditText hint:"aria-label3 placeholder3" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="aria-label3 placeholder3"]
diff --git a/content/test/data/accessibility/aria/presentational-expected-android-external.txt b/content/test/data/accessibility/aria/presentational-expected-android-external.txt index 8fe489c7..bd4ecda 100644 --- a/content/test/data/accessibility/aria/presentational-expected-android-external.txt +++ b/content/test/data/accessibility/aria/presentational-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="section"] ++++View text:"Heading with link" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 2"] ++++++TextView text:"Heading " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/aria/toggle-button-expand-collapse-expected-android-external.txt b/content/test/data/accessibility/aria/toggle-button-expand-collapse-expected-android-external.txt index 95b52e7..cfd1b01 100644 --- a/content/test/data/accessibility/aria/toggle-button-expand-collapse-expected-android-external.txt +++ b/content/test/data/accessibility/aria/toggle-button-expand-collapse-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ToggleButton text:"Toggle button, pressed, collapsed" stateDescription:"On" canOpenPopUp checkable checked clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="toggleButton", roleDescription="menu pop up button"] ++ToggleButton text:"Toggle button, not pressed, collapsed" stateDescription:"Off" canOpenPopUp checkable clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="toggleButton", roleDescription="menu pop up button"] ++ToggleButton text:"Toggle button, pressed, expanded" stateDescription:"On" canOpenPopUp checkable checked clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, COLLAPSE] bundle:[chromeRole="toggleButton", roleDescription="menu pop up button"]
diff --git a/content/test/data/accessibility/css/alt-text-expected-android-external.txt b/content/test/data/accessibility/css/alt-text-expected-android-external.txt index 7716dd2..555d713a 100644 --- a/content/test/data/accessibility/css/alt-text-expected-android-external.txt +++ b/content/test/data/accessibility/css/alt-text-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View viewIdResName:"controlparent" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++TextView text:"item1item2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic"]
diff --git a/content/test/data/accessibility/css/background-color-transparent-expected-android-external.txt b/content/test/data/accessibility/css/background-color-transparent-expected-android-external.txt index 222624b..16a47e6a 100644 --- a/content/test/data/accessibility/css/background-color-transparent-expected-android-external.txt +++ b/content/test/data/accessibility/css/background-color-transparent-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Document base color." viewIdResName:"default" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"Transparent color." viewIdResName:"transparent" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++TextView text:"Obscuring background." viewIdResName:"obscuring-background" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"]
diff --git a/content/test/data/accessibility/css/before-after-code-expected-android-external.txt b/content/test/data/accessibility/css/before-after-code-expected-android-external.txt index 70f5903..de05c9b 100644 --- a/content/test/data/accessibility/css/before-after-code-expected-android-external.txt +++ b/content/test/data/accessibility/css/before-after-code-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"start" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++TextView text:"text with " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/css/color-expected-android-external.txt b/content/test/data/accessibility/css/color-expected-android-external.txt index 9c4f6d05..e904ec4a 100644 --- a/content/test/data/accessibility/css/color-expected-android-external.txt +++ b/content/test/data/accessibility/css/color-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Red on blue." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++EditText text:"Default. Blue background. Green text." clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200"] \ No newline at end of file
diff --git a/content/test/data/accessibility/css/dom-element-css-alternative-text-expected-android-external.txt b/content/test/data/accessibility/css/dom-element-css-alternative-text-expected-android-external.txt index e42477f0..6e971bde 100644 --- a/content/test/data/accessibility/css/dom-element-css-alternative-text-expected-android-external.txt +++ b/content/test/data/accessibility/css/dom-element-css-alternative-text-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image text:"alternative text" viewIdResName:"element" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic"] \ No newline at end of file
diff --git a/content/test/data/accessibility/css/font-size-expected-android-external.txt b/content/test/data/accessibility/css/font-size-expected-android-external.txt index 0376f18..b9eab4a 100644 --- a/content/test/data/accessibility/css/font-size-expected-android-external.txt +++ b/content/test/data/accessibility/css/font-size-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"10.2340920823px" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++TextView text:"10px" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++TextView text:"11px" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"]
diff --git a/content/test/data/accessibility/css/font-style-expected-android-external.txt b/content/test/data/accessibility/css/font-style-expected-android-external.txt index 667f568..e8444f1 100644 --- a/content/test/data/accessibility/css/font-style-expected-android-external.txt +++ b/content/test/data/accessibility/css/font-style-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"The quick brown fox jumped over dog" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++EditText text:"Normal bold italic underline line-through subscript superscript" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200"] \ No newline at end of file
diff --git a/content/test/data/accessibility/css/language-expected-android-external.txt b/content/test/data/accessibility/css/language-expected-android-external.txt index 08f4fb5..9f1140c2 100644 --- a/content/test/data/accessibility/css/language-expected-android-external.txt +++ b/content/test/data/accessibility/css/language-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Espanyol" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++TextView text:"Comment allez-vous?" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] \ No newline at end of file
diff --git a/content/test/data/accessibility/css/list-marker-styles-custom-expected-android-external.txt b/content/test/data/accessibility/css/list-marker-styles-custom-expected-android-external.txt index 85ec3409..0051d055 100644 --- a/content/test/data/accessibility/css/list-marker-styles-custom-expected-android-external.txt +++ b/content/test/data/accessibility/css/list-marker-styles-custom-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=1, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS] bundle:[chromeRole="listItem"] ++++++View text:"• " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listMarker"]
diff --git a/content/test/data/accessibility/css/pseudo-element-alternative-text-expected-android-external.txt b/content/test/data/accessibility/css/pseudo-element-alternative-text-expected-android-external.txt index 88c1c23..66a2752f 100644 --- a/content/test/data/accessibility/css/pseudo-element-alternative-text-expected-android-external.txt +++ b/content/test/data/accessibility/css/pseudo-element-alternative-text-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View viewIdResName:"parent" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image text:"alternative text" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic"] ++++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/css/pseudo-element-positioned-expected-android-external.txt b/content/test/data/accessibility/css/pseudo-element-positioned-expected-android-external.txt index b75c3e4c..ff308fa 100644 --- a/content/test/data/accessibility/css/pseudo-element-positioned-expected-android-external.txt +++ b/content/test/data/accessibility/css/pseudo-element-positioned-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Empty before and after" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++TextView text:"Empty positioned before and after" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"pseudo" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"]
diff --git a/content/test/data/accessibility/css/pseudo-elements-expected-android-external.txt b/content/test/data/accessibility/css/pseudo-elements-expected-android-external.txt index ad40ef2..ac5adaa 100644 --- a/content/test/data/accessibility/css/pseudo-elements-expected-android-external.txt +++ b/content/test/data/accessibility/css/pseudo-elements-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"[ Foo ]" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 1"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/a-expected-android-external.txt b/content/test/data/accessibility/html/a-expected-android-external.txt index ee42ac4..7216ef6 100644 --- a/content/test/data/accessibility/html/a-expected-android-external.txt +++ b/content/test/data/accessibility/html/a-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"null" contentDescription:"normal link" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="http://www.google.com/"] ++++++TextView text:"normal link" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText", clickableScore="100"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/a-name-calc-expected-android-external.txt b/content/test/data/accessibility/html/a-name-calc-expected-android-external.txt index 42b7489..55b891bd 100644 --- a/content/test/data/accessibility/html/a-name-calc-expected-android-external.txt +++ b/content/test/data/accessibility/html/a-name-calc-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"null" contentDescription:"InnerText0" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/a-name-calc.html#"] ++++TextView text:"InnerText0" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText", clickableScore="100"] ++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/html/a-name-expected-android-external.txt b/content/test/data/accessibility/html/a-name-expected-android-external.txt index 9a88ba6..7fe585c9 100644 --- a/content/test/data/accessibility/html/a-name-expected-android-external.txt +++ b/content/test/data/accessibility/html/a-name-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"named anchor" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++View text:"null" contentDescription:"both a named anchor and a link" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/a-name.html#foo"] ++++TextView text:"both a named anchor and a link" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText", clickableScore="100"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/a-nested-structure-expected-android-external.txt b/content/test/data/accessibility/html/a-nested-structure-expected-android-external.txt index 5cb3082..5ffd8ec99 100644 --- a/content/test/data/accessibility/html/a-nested-structure-expected-android-external.txt +++ b/content/test/data/accessibility/html/a-nested-structure-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"null" contentDescription:"Header 1 List element 1 List element 2 List element 3" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="http://www.foobar.com/"] ++++++TextView text:"Header 1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", clickableScore="100", roleDescription="heading 1"]
diff --git a/content/test/data/accessibility/html/a-no-text-expected-android-external.txt b/content/test/data/accessibility/html/a-no-text-expected-android-external.txt index a0c591f..b9d8286 100644 --- a/content/test/data/accessibility/html/a-no-text-expected-android-external.txt +++ b/content/test/data/accessibility/html/a-no-text-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++View text:"null" contentDescription:"dest1" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hasImage="true", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/dest1"] ++++++Image actions:[AX_FOCUS] bundle:[chromeRole="image", clickableScore="100", hasImage="true", roleDescription="graphic"]
diff --git a/content/test/data/accessibility/html/a-with-img-expected-android-external.txt b/content/test/data/accessibility/html/a-with-img-expected-android-external.txt index 2bb9703..092b632 100644 --- a/content/test/data/accessibility/html/a-with-img-expected-android-external.txt +++ b/content/test/data/accessibility/html/a-with-img-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++View text:"null" contentDescription:"Link with image at start." clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hasImage="true", roleDescription="link", targetUrl="http://www.google.com/"] ++++++Image text:"Link" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", clickableScore="100", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/bullet.png"] @@ -16,4 +16,4 @@ ++++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View text:"null" contentDescription:"Link with image at the end, it's a bullet" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hasImage="true", roleDescription="link", targetUrl="http://www.google.com/"] ++++++TextView text:"Link with image at the " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText", clickableScore="100"] -++++++Image text:"end, it's a bullet" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", clickableScore="100", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/bullet.png"] +++++++Image text:"end, it's a bullet" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", clickableScore="100", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/bullet.png"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/abbr-expected-android-external.txt b/content/test/data/accessibility/html/abbr-expected-android-external.txt index 3b1b0f6..f7cbffd5 100644 --- a/content/test/data/accessibility/html/abbr-expected-android-external.txt +++ b/content/test/data/accessibility/html/abbr-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"] ++++TextView text:"The " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View text:"World Health Organization" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="abbr"]
diff --git a/content/test/data/accessibility/html/accordion-expected-android-external.txt b/content/test/data/accessibility/html/accordion-expected-android-external.txt index e4e2ea3d..be5f7bd 100644 --- a/content/test/data/accessibility/html/accordion-expected-android-external.txt +++ b/content/test/data/accessibility/html/accordion-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Accordion Section #1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 3"] ++++Button text:"Accordion Section #1" viewIdResName:"header1control" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COLLAPSE] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] ++View text:"Accordion Section #1" viewIdResName:"section1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"]
diff --git a/content/test/data/accessibility/html/action-verbs-expected-android-external.txt b/content/test/data/accessibility/html/action-verbs-expected-android-external.txt index 1d70db83..71009c8 100644 --- a/content/test/data/accessibility/html/action-verbs-expected-android-external.txt +++ b/content/test/data/accessibility/html/action-verbs-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView text:"Action verbs" focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] +WebView text:"Action verbs" focusable focused actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Generic div" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"Heading" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 1"] ++Button text:"Button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"]
diff --git a/content/test/data/accessibility/html/actions-expected-android-external.txt b/content/test/data/accessibility/html/actions-expected-android-external.txt index 1f105d0..92c42c1 100644 --- a/content/test/data/accessibility/html/actions-expected-android-external.txt +++ b/content/test/data/accessibility/html/actions-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView text:"Actions" focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] +WebView text:"Actions" focusable focused actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++SeekBar text:"50" clickable focusable RangeInfo:[current=50.0, min=1.0, max=100.0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"] ++++EditText hint:"Test textfield" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Test textfield"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/address-expected-android-external.txt b/content/test/data/accessibility/html/address-expected-android-external.txt index 94296ea2..0c9e7b2 100644 --- a/content/test/data/accessibility/html/address-expected-android-external.txt +++ b/content/test/data/accessibility/html/address-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Please contact John Citizen for more information." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/area-expected-android-external.txt b/content/test/data/accessibility/html/area-expected-android-external.txt index 21f26bb..b850493 100644 --- a/content/test/data/accessibility/html/area-expected-android-external.txt +++ b/content/test/data/accessibility/html/area-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image text:"pipe" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/pipe.jpg"] -++++++View text:"null" contentDescription:"pipe1" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/fake.htm"] +++++++View text:"null" contentDescription:"pipe1" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/fake.htm"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/article-expected-android-external.txt b/content/test/data/accessibility/html/article-expected-android-external.txt index 3a8b91d..6edab1a 100644 --- a/content/test/data/accessibility/html/article-expected-android-external.txt +++ b/content/test/data/accessibility/html/article-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"This is an article element." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="article", roleDescription="article"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/aside-expected-android-external.txt b/content/test/data/accessibility/html/aside-expected-android-external.txt index dd9e93f..855c282b 100644 --- a/content/test/data/accessibility/html/aside-expected-android-external.txt +++ b/content/test/data/accessibility/html/aside-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"The aside tag defines some content aside from the content it is placed in." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++View actions:[AX_FOCUS] bundle:[chromeRole="complementary", roleDescription="complementary"] ++++TextView text:"Body aside" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 4"]
diff --git a/content/test/data/accessibility/html/aside-inside-other-section-expected-android-external.txt b/content/test/data/accessibility/html/aside-inside-other-section-expected-android-external.txt index 0dc01266..a7c607da 100644 --- a/content/test/data/accessibility/html/aside-inside-other-section-expected-android-external.txt +++ b/content/test/data/accessibility/html/aside-inside-other-section-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="article", roleDescription="article"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++++TextView text:"Unnamed aside inside article." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"]
diff --git a/content/test/data/accessibility/html/aside-inside-section-role-generic-expected-android-external.txt b/content/test/data/accessibility/html/aside-inside-section-role-generic-expected-android-external.txt index 1620ba80..64741c9 100644 --- a/content/test/data/accessibility/html/aside-inside-section-role-generic-expected-android-external.txt +++ b/content/test/data/accessibility/html/aside-inside-section-role-generic-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="complementary", roleDescription="complementary"] ++++TextView text:"aside inside section with role presentational." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"]
diff --git a/content/test/data/accessibility/html/b-expected-android-external.txt b/content/test/data/accessibility/html/b-expected-android-external.txt index 2734761..5d351f58 100644 --- a/content/test/data/accessibility/html/b-expected-android-external.txt +++ b/content/test/data/accessibility/html/b-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Some bold text" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/bdo-expected-android-external.txt b/content/test/data/accessibility/html/bdo-expected-android-external.txt index 66303d3..f378a09 100644 --- a/content/test/data/accessibility/html/bdo-expected-android-external.txt +++ b/content/test/data/accessibility/html/bdo-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Some LTR text Some RTL text with some LTR text embedded" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/blockquote-expected-android-external.txt b/content/test/data/accessibility/html/blockquote-expected-android-external.txt index fe42e5b6..f5d0a03 100644 --- a/content/test/data/accessibility/html/blockquote-expected-android-external.txt +++ b/content/test/data/accessibility/html/blockquote-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="blockquote", roleDescription="blockquote"] ++++TextView text:"First blockquote has a child element." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++View text:"Second blockquote has no child." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="blockquote", roleDescription="blockquote"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/blockquote-levels-expected-android-external.txt b/content/test/data/accessibility/html/blockquote-levels-expected-android-external.txt index 013530e..edef7b9 100644 --- a/content/test/data/accessibility/html/blockquote-levels-expected-android-external.txt +++ b/content/test/data/accessibility/html/blockquote-levels-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="blockquote", roleDescription="blockquote"] ++++TextView text:"Top level" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="blockquote", roleDescription="blockquote"]
diff --git a/content/test/data/accessibility/html/body-expected-android-external.txt b/content/test/data/accessibility/html/body-expected-android-external.txt index 2cdd1a3..725c1c5 100644 --- a/content/test/data/accessibility/html/body-expected-android-external.txt +++ b/content/test/data/accessibility/html/body-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"This test is for body tag" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/br-expected-android-external.txt b/content/test/data/accessibility/html/br-expected-android-external.txt index 4faf4c97..1e58b5d 100644 --- a/content/test/data/accessibility/html/br-expected-android-external.txt +++ b/content/test/data/accessibility/html/br-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"\n" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="lineBreak"] ++TextView text:"Text line 1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++TextView text:"Text line 2\nText line 3" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"]
diff --git a/content/test/data/accessibility/html/button-expected-android-external.txt b/content/test/data/accessibility/html/button-expected-android-external.txt index 89d96e4..aa58093 100644 --- a/content/test/data/accessibility/html/button-expected-android-external.txt +++ b/content/test/data/accessibility/html/button-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Button text:"Click me!" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/button-name-calc-expected-android-external.txt b/content/test/data/accessibility/html/button-name-calc-expected-android-external.txt index 9ce15e6..cb50dc9b 100644 --- a/content/test/data/accessibility/html/button-name-calc-expected-android-external.txt +++ b/content/test/data/accessibility/html/button-name-calc-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++Button text:"InnerText0" viewIdResName:"c0" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] ++Button text:"InnerText1" hint:"Title1" viewIdResName:"c1" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hint="Title1", roleDescription="button"] ++Button text:"AriaLabel2" hint:"Title2" viewIdResName:"c2" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hint="Title2", roleDescription="button"]
diff --git a/content/test/data/accessibility/html/button-with-listbox-popup-expected-android-external.txt b/content/test/data/accessibility/html/button-with-listbox-popup-expected-android-external.txt index ae6a14e0..8ae15cb 100644 --- a/content/test/data/accessibility/html/button-with-listbox-popup-expected-android-external.txt +++ b/content/test/data/accessibility/html/button-with-listbox-popup-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View viewIdResName:"test1" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++TextView text:"Choose one:" viewIdResName:"span" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++++Button text:"Choose one: Foo" viewIdResName:"test" canOpenPopUp clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="popUpButton", clickableScore="300", roleDescription="pop up button"]
diff --git a/content/test/data/accessibility/html/canvas-expected-android-external.txt b/content/test/data/accessibility/html/canvas-expected-android-external.txt index 1abbc3a..b71f111c 100644 --- a/content/test/data/accessibility/html/canvas-expected-android-external.txt +++ b/content/test/data/accessibility/html/canvas-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image text:"Static fallback" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="canvas", hasImage="true"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="canvas", hasImage="true"]
diff --git a/content/test/data/accessibility/html/canvas-fallback-expected-android-external.txt b/content/test/data/accessibility/html/canvas-fallback-expected-android-external.txt index 8256ed0..b4ea1c4 100644 --- a/content/test/data/accessibility/html/canvas-fallback-expected-android-external.txt +++ b/content/test/data/accessibility/html/canvas-fallback-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image text:"Static fallback" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="canvas", hasImage="true"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="canvas", hasImage="true"] @@ -9,4 +9,4 @@ ++++++TextView text:"\n " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++++TextView text:"\n " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++++TextView text:"\n " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++++TextView text:"\n " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] +++++++TextView text:"\n " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/caption-expected-android-external.txt b/content/test/data/accessibility/html/caption-expected-android-external.txt index 8d616bd0..1532c28 100644 --- a/content/test/data/accessibility/html/caption-expected-android-external.txt +++ b/content/test/data/accessibility/html/caption-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView text:"Browser and Engine" CollectionInfo:[rows=3, cols=2] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="table", roleDescription="table"] ++++View text:"Browser and Engine" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="caption"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"]
diff --git a/content/test/data/accessibility/html/character-locations-expected-android-external.txt b/content/test/data/accessibility/html/character-locations-expected-android-external.txt index 71478b2..30442a4c 100644 --- a/content/test/data/accessibility/html/character-locations-expected-android-external.txt +++ b/content/test/data/accessibility/html/character-locations-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView text:"Character Locations" focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView text:"Character Locations" focusable focused actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++TextView text:"Heading" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 1"] ++TextView text:"Paragraph" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++Button text:"Button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] @@ -7,4 +7,4 @@ ++Image text:"Image with alt text" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic"] ++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++View text:"null" contentDescription:"Image inside link" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hasImage="true", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/character-locations.html#"] -++++Image text:"Image inside link" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", clickableScore="100", hasImage="true", roleDescription="graphic"] +++++Image text:"Image inside link" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", clickableScore="100", hasImage="true", roleDescription="graphic"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/checkbox-name-calc-expected-android-external.txt b/content/test/data/accessibility/html/checkbox-name-calc-expected-android-external.txt index 507d9340..12bdf6d 100644 --- a/content/test/data/accessibility/html/checkbox-name-calc-expected-android-external.txt +++ b/content/test/data/accessibility/html/checkbox-name-calc-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++CheckBox text:"Title0" viewIdResName:"c0" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", clickableScore="300", roleDescription="checkbox"] ++CheckBox text:"Label1" hint:"Title1" viewIdResName:"c1" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", clickableScore="300", hint="Title1", roleDescription="checkbox"] ++CheckBox text:"AriaLabel2" hint:"Title2" viewIdResName:"c2" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", clickableScore="300", hint="Title2", roleDescription="checkbox"]
diff --git a/content/test/data/accessibility/html/cite-expected-android-external.txt b/content/test/data/accessibility/html/cite-expected-android-external.txt index 2c2219c..6b2cf762 100644 --- a/content/test/data/accessibility/html/cite-expected-android-external.txt +++ b/content/test/data/accessibility/html/cite-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++Image text:"Pipe" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/pipe.jpg"] ++TextView text:"The pipe clicked by SomeOne." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/clickable-ancestor-expected-android-external.txt b/content/test/data/accessibility/html/clickable-ancestor-expected-android-external.txt index 3e9fa98..496d8b9 100644 --- a/content/test/data/accessibility/html/clickable-ancestor-expected-android-external.txt +++ b/content/test/data/accessibility/html/clickable-ancestor-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView text:"Checking nodes marked as clickable" focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] +WebView text:"Checking nodes marked as clickable" focusable focused actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Generic div" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"Heading" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 1"] ++Button text:"Button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"]
diff --git a/content/test/data/accessibility/html/clickable-score-expected-android-external.txt b/content/test/data/accessibility/html/clickable-score-expected-android-external.txt index d6d95e704..83f7ba21 100644 --- a/content/test/data/accessibility/html/clickable-score-expected-android-external.txt +++ b/content/test/data/accessibility/html/clickable-score-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++Button text:"High score" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] ++Button text:"High score" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] ++Button text:"No score" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", roleDescription="button"]
diff --git a/content/test/data/accessibility/html/code-expected-android-external.txt b/content/test/data/accessibility/html/code-expected-android-external.txt index 276df4d..b5ae9b6c 100644 --- a/content/test/data/accessibility/html/code-expected-android-external.txt +++ b/content/test/data/accessibility/html/code-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"A piece of computer code" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="code"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/col-expected-android-external.txt b/content/test/data/accessibility/html/col-expected-android-external.txt index 1e4b264..14a55f8 100644 --- a/content/test/data/accessibility/html/col-expected-android-external.txt +++ b/content/test/data/accessibility/html/col-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=2, cols=2] actions:[AX_FOCUS] bundle:[chromeRole="table", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Browser" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/html/colgroup-expected-android-external.txt b/content/test/data/accessibility/html/colgroup-expected-android-external.txt index 7560392e..798c1fd6 100644 --- a/content/test/data/accessibility/html/colgroup-expected-android-external.txt +++ b/content/test/data/accessibility/html/colgroup-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=2, cols=2] actions:[AX_FOCUS] bundle:[chromeRole="table", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Single" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/html/combobox-optgroup-expected-android-external.txt b/content/test/data/accessibility/html/combobox-optgroup-expected-android-external.txt index c538ab3..ee1a06fb 100644 --- a/content/test/data/accessibility/html/combobox-optgroup-expected-android-external.txt +++ b/content/test/data/accessibility/html/combobox-optgroup-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"Mercedes Label" canOpenPopUp clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="comboBoxSelect", clickableScore="300", roleDescription="menu pop up button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-expected-android-external.txt b/content/test/data/accessibility/html/contenteditable-descendants-expected-android-external.txt index b99c1a8..eb4f501 100644 --- a/content/test/data/accessibility/html/contenteditable-descendants-expected-android-external.txt +++ b/content/test/data/accessibility/html/contenteditable-descendants-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++EditText text:"A contenteditable with a link and an \n\n and a Button.\nAlways expose editable tables as tables.\n1. Editable list item." clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200", hasImage="true"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph", clickableScore="100", hasImage="true"] ++++++TextView text:"A contenteditable with a " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText", clickableScore="100"]
diff --git a/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-android-external.txt b/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-android-external.txt index 20a62d8..8461e8c 100644 --- a/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-android-external.txt +++ b/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++EditText text:"This is editable.\nThis is not editable.\nBut this one is.\nSo is this one." clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200"] ++++TextView text:"This is editable." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph", clickableScore="100"] ++++TextView text:"This is not editable." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText", clickableScore="100"]
diff --git a/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-android-external.txt b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-android-external.txt index d399e23e..781bd8b 100644 --- a/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-android-external.txt +++ b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++EditText hint:"label" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200", hint="label"] ++EditText hint:"description" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200", hint="description"] ++EditText hint:"title" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200", hint="title"]
diff --git a/content/test/data/accessibility/html/continuations-expected-android-external.txt b/content/test/data/accessibility/html/continuations-expected-android-external.txt index 2f36637..6590c3d 100644 --- a/content/test/data/accessibility/html/continuations-expected-android-external.txt +++ b/content/test/data/accessibility/html/continuations-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Group 1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++++Button text:"Before" viewIdResName:"before" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"]
diff --git a/content/test/data/accessibility/html/dd-expected-android-external.txt b/content/test/data/accessibility/html/dd-expected-android-external.txt index 69736c1..4f62974 100644 --- a/content/test/data/accessibility/html/dd-expected-android-external.txt +++ b/content/test/data/accessibility/html/dd-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=1, cols=0] actions:[AX_FOCUS] bundle:[chromeRole="descriptionList"] ++++View text:"Coffee" CollectionItemInfo:[rowSpan=0, colSpan=0, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="descriptionListTerm"] ++++View text:"Black hot drink" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="descriptionListDetail", roleDescription="definition"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/del-expected-android-external.txt b/content/test/data/accessibility/html/del-expected-android-external.txt index 254b5957..0923a10 100644 --- a/content/test/data/accessibility/html/del-expected-android-external.txt +++ b/content/test/data/accessibility/html/del-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"] ++++TextView text:"I am " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View text:"vegetarian" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="contentDeletion", roleDescription="deletion"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/details-expected-android-external.txt b/content/test/data/accessibility/html/details-expected-android-external.txt index fd2b4fb3..dd6f4b2 100644 --- a/content/test/data/accessibility/html/details-expected-android-external.txt +++ b/content/test/data/accessibility/html/details-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="details"] ++++View text:"details tag" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="disclosureTriangle", clickableScore="300", roleDescription="disclosure triangle"] ++View actions:[AX_FOCUS] bundle:[chromeRole="details"]
diff --git a/content/test/data/accessibility/html/details-name-expected-android-external.txt b/content/test/data/accessibility/html/details-name-expected-android-external.txt index 13b00d43..4c6e529d 100644 --- a/content/test/data/accessibility/html/details-name-expected-android-external.txt +++ b/content/test/data/accessibility/html/details-name-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="details"] ++++View text:"the summary" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="disclosureTriangle", clickableScore="300", roleDescription="disclosure triangle"] ++View actions:[AX_FOCUS] bundle:[chromeRole="section"] @@ -8,4 +8,4 @@ ++++View actions:[AX_FOCUS] bundle:[chromeRole="details"] ++++++View text:"dimensions" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="disclosureTriangleGrouped", clickableScore="300", roleDescription="disclosure triangle"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="details"] -++++++View text:"origin" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="disclosureTriangleGrouped", clickableScore="300", roleDescription="disclosure triangle"] +++++++View text:"origin" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="disclosureTriangleGrouped", clickableScore="300", roleDescription="disclosure triangle"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/dfn-expected-android-external.txt b/content/test/data/accessibility/html/dfn-expected-android-external.txt index ec7a41db..97f31c21 100644 --- a/content/test/data/accessibility/html/dfn-expected-android-external.txt +++ b/content/test/data/accessibility/html/dfn-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"Web Browser" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="term", roleDescription="term"] ++++TextView text:" A computer program with a graphical user interface for displaying HTML files, used to navigate the World Wide Web." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/dialog-expected-android-external.txt b/content/test/data/accessibility/html/dialog-expected-android-external.txt index b18bca0..60d14eb 100644 --- a/content/test/data/accessibility/html/dialog-expected-android-external.txt +++ b/content/test/data/accessibility/html/dialog-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++Dialog text:"Text in dialog" paneTitle:"dialog opened." focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="dialog", roleDescription="dialog"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +++Dialog text:"Text in dialog" paneTitle:"dialog opened." focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="dialog", roleDescription="dialog"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/disabled-expected-android-external.txt b/content/test/data/accessibility/html/disabled-expected-android-external.txt index 4aaebb5..0e374dc8 100644 --- a/content/test/data/accessibility/html/disabled-expected-android-external.txt +++ b/content/test/data/accessibility/html/disabled-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++CheckBox text:"Enabled" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", clickableScore="300", roleDescription="checkbox"] ++CheckBox text:"Disabled" checkable clickable disabled actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", roleDescription="checkbox"] ++Button text:"Enabled" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"]
diff --git a/content/test/data/accessibility/html/div-expected-android-external.txt b/content/test/data/accessibility/html/div-expected-android-external.txt index eb2bcef..2557e0a 100644 --- a/content/test/data/accessibility/html/div-expected-android-external.txt +++ b/content/test/data/accessibility/html/div-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Unfocusable div" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"Focusable div" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/dl-expected-android-external.txt b/content/test/data/accessibility/html/dl-expected-android-external.txt index f6c908c..211e8ab 100644 --- a/content/test/data/accessibility/html/dl-expected-android-external.txt +++ b/content/test/data/accessibility/html/dl-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=1, cols=0] actions:[AX_FOCUS] bundle:[chromeRole="descriptionList"] ++++View text:"Term" CollectionItemInfo:[rowSpan=0, colSpan=0, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="descriptionListTerm"] ++++View text:"Description" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="descriptionListDetail", roleDescription="definition"]
diff --git a/content/test/data/accessibility/html/dt-expected-android-external.txt b/content/test/data/accessibility/html/dt-expected-android-external.txt index 69736c1..4f62974 100644 --- a/content/test/data/accessibility/html/dt-expected-android-external.txt +++ b/content/test/data/accessibility/html/dt-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=1, cols=0] actions:[AX_FOCUS] bundle:[chromeRole="descriptionList"] ++++View text:"Coffee" CollectionItemInfo:[rowSpan=0, colSpan=0, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="descriptionListTerm"] ++++View text:"Black hot drink" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="descriptionListDetail", roleDescription="definition"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/element-class-id-src-attr-expected-android-external.txt b/content/test/data/accessibility/html/element-class-id-src-attr-expected-android-external.txt index 40d0b2a5..c8dbf2b 100644 --- a/content/test/data/accessibility/html/element-class-id-src-attr-expected-android-external.txt +++ b/content/test/data/accessibility/html/element-class-id-src-attr-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++TextView text:"Image" viewIdResName:"headerID" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 1"] ++Image text:"ImageAlt" viewIdResName:"imageID" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/greenbox.png"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/em-expected-android-external.txt b/content/test/data/accessibility/html/em-expected-android-external.txt index 2f28f0c..d3bbfe3 100644 --- a/content/test/data/accessibility/html/em-expected-android-external.txt +++ b/content/test/data/accessibility/html/em-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++TextView text:"One word is " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View text:"emphasized" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="emphasis"]
diff --git a/content/test/data/accessibility/html/embed-expected-android-external.txt b/content/test/data/accessibility/html/embed-expected-android-external.txt index e0ec3cb8..04d8f0f 100644 --- a/content/test/data/accessibility/html/embed-expected-android-external.txt +++ b/content/test/data/accessibility/html/embed-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View disabled actions:[AX_FOCUS] bundle:[chromeRole="embeddedObject", roleDescription="object"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/fieldset-expected-android-external.txt b/content/test/data/accessibility/html/fieldset-expected-android-external.txt index 54d1c3d4..c0747f0 100644 --- a/content/test/data/accessibility/html/fieldset-expected-android-external.txt +++ b/content/test/data/accessibility/html/fieldset-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="section"] ++++View text:"Browser Engines:" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] ++++++View text:"Browser Engines:" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="legend"]
diff --git a/content/test/data/accessibility/html/figcaption-expected-android-external.txt b/content/test/data/accessibility/html/figcaption-expected-android-external.txt index 92904c3..e7f7fe6 100644 --- a/content/test/data/accessibility/html/figcaption-expected-android-external.txt +++ b/content/test/data/accessibility/html/figcaption-expected-android-external.txt
@@ -1,7 +1,7 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="figure", hasImage="true", roleDescription="graphic"] ++++Image text:"This is a green box." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/greenbox.png"] ++++View text:"Fig.1 - A green Box" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="figcaption"] ++View actions:[AX_FOCUS] bundle:[chromeRole="figure", hasImage="true", roleDescription="graphic"] ++++Image text:"This is a blue box." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/greenbox.png"] -++++View text:"Fig.2 - A blue Box" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="figcaption"] +++++View text:"Fig.2 - A blue Box" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="figcaption"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/figure-expected-android-external.txt b/content/test/data/accessibility/html/figure-expected-android-external.txt index e3d7c99..f9bc9868 100644 --- a/content/test/data/accessibility/html/figure-expected-android-external.txt +++ b/content/test/data/accessibility/html/figure-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="figure", hasImage="true", roleDescription="graphic"] ++++Image text:"Sunspots" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/pipe.jpg"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/fixed-width-text-expected-android-external.txt b/content/test/data/accessibility/html/fixed-width-text-expected-android-external.txt index 14ad851..8779a16 100644 --- a/content/test/data/accessibility/html/fixed-width-text-expected-android-external.txt +++ b/content/test/data/accessibility/html/fixed-width-text-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Hello,\nWorld" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/footer-expected-android-external.txt b/content/test/data/accessibility/html/footer-expected-android-external.txt index 013110c..0ff9aa97 100644 --- a/content/test/data/accessibility/html/footer-expected-android-external.txt +++ b/content/test/data/accessibility/html/footer-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Footer element" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="footer", roleDescription="footer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/footer-inside-other-section-expected-android-external.txt b/content/test/data/accessibility/html/footer-inside-other-section-expected-android-external.txt index b01c29f..8f6a262 100644 --- a/content/test/data/accessibility/html/footer-inside-other-section-expected-android-external.txt +++ b/content/test/data/accessibility/html/footer-inside-other-section-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="article", roleDescription="article"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="footerAsNonLandmark"] ++++++TextView text:"footer inside article." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"]
diff --git a/content/test/data/accessibility/html/form-expected-android-external.txt b/content/test/data/accessibility/html/form-expected-android-external.txt index 4440ddfb..fb451ae 100644 --- a/content/test/data/accessibility/html/form-expected-android-external.txt +++ b/content/test/data/accessibility/html/form-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="section"] ++++Button text:"Submit" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] ++View text:"Name" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="form"]
diff --git a/content/test/data/accessibility/html/header-expected-android-external.txt b/content/test/data/accessibility/html/header-expected-android-external.txt index 39b47beb..cfd2b7b1 100644 --- a/content/test/data/accessibility/html/header-expected-android-external.txt +++ b/content/test/data/accessibility/html/header-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Chromium Browser" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="header", roleDescription="banner"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/header-inside-other-section-expected-android-external.txt b/content/test/data/accessibility/html/header-inside-other-section-expected-android-external.txt index a7cd68f..d018962 100644 --- a/content/test/data/accessibility/html/header-inside-other-section-expected-android-external.txt +++ b/content/test/data/accessibility/html/header-inside-other-section-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="article", roleDescription="article"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="headerAsNonLandmark"] ++++++TextView text:"Header inside article." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"]
diff --git a/content/test/data/accessibility/html/heading-expected-android-external.txt b/content/test/data/accessibility/html/heading-expected-android-external.txt index cd10b114..70dac9e2 100644 --- a/content/test/data/accessibility/html/heading-expected-android-external.txt +++ b/content/test/data/accessibility/html/heading-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Heading 1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 1"] ++TextView text:"Heading 2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 2"] ++TextView text:"Heading 3" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 3"]
diff --git a/content/test/data/accessibility/html/heading-with-tabIndex-expected-android-external.txt b/content/test/data/accessibility/html/heading-with-tabIndex-expected-android-external.txt index 75d888afb..bd31953 100644 --- a/content/test/data/accessibility/html/heading-with-tabIndex-expected-android-external.txt +++ b/content/test/data/accessibility/html/heading-with-tabIndex-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Heading 2, no tabIndex" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 2"] ++TextView text:"Heading 1, tabIndex of negative 1" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 1"] ++TextView text:"Heading 3, tabIndex of 0" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 3"]
diff --git a/content/test/data/accessibility/html/hr-expected-android-external.txt b/content/test/data/accessibility/html/hr-expected-android-external.txt index 9f4a433..82b8d95 100644 --- a/content/test/data/accessibility/html/hr-expected-android-external.txt +++ b/content/test/data/accessibility/html/hr-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Before." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++View text:"Dividing line" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="splitter", roleDescription="splitter"] ++TextView text:"Middle." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"]
diff --git a/content/test/data/accessibility/html/html-attributes-and-tag-names-expected-android-external.txt b/content/test/data/accessibility/html/html-attributes-and-tag-names-expected-android-external.txt index 9de5786..3aaaae6 100644 --- a/content/test/data/accessibility/html/html-attributes-and-tag-names-expected-android-external.txt +++ b/content/test/data/accessibility/html/html-attributes-and-tag-names-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView text:"Hello World" focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] +WebView text:"Hello World" focusable focused actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Heading" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 1"] ++TextView text:"Paragraph" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"]
diff --git a/content/test/data/accessibility/html/html-expected-android-external.txt b/content/test/data/accessibility/html/html-expected-android-external.txt index a2911a9..0b81ceb9 100644 --- a/content/test/data/accessibility/html/html-expected-android-external.txt +++ b/content/test/data/accessibility/html/html-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView text:"HTML element" focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] +WebView text:"HTML element" focusable focused actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++View text:"BODY element" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++++Button text:"Button element" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/i-expected-android-external.txt b/content/test/data/accessibility/html/i-expected-android-external.txt index f33d1bc..734ef50 100644 --- a/content/test/data/accessibility/html/i-expected-android-external.txt +++ b/content/test/data/accessibility/html/i-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"This is to check italic property using i tag." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/id-expected-android-external.txt b/content/test/data/accessibility/html/id-expected-android-external.txt index 283ee446..1b38c99 100644 --- a/content/test/data/accessibility/html/id-expected-android-external.txt +++ b/content/test/data/accessibility/html/id-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"No id" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++TextView text:"Has id" viewIdResName:"para2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-cross-process-expected-android-external.txt b/content/test/data/accessibility/html/iframe-cross-process-expected-android-external.txt index eff08d8a..bdd3201da 100644 --- a/content/test/data/accessibility/html/iframe-cross-process-expected-android-external.txt +++ b/content/test/data/accessibility/html/iframe-cross-process-expected-android-external.txt
@@ -1,7 +1,7 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Before frame" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="iframe"] -++++++View text:"Error" focusable scrollable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] +++++++View text:"Error" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++++++++TextView text:"Could not load the requested resource.\nError code: -6 (net::ERR_FILE_NOT_FOUND)" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"After frame" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-expected-android-external.txt b/content/test/data/accessibility/html/iframe-expected-android-external.txt index 3e5ebdd..f8d54e6 100644 --- a/content/test/data/accessibility/html/iframe-expected-android-external.txt +++ b/content/test/data/accessibility/html/iframe-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="iframe"] -++++++View scrollable actions:[AX_FOCUS] bundle:[chromeRole="rootWebArea"] \ No newline at end of file +++++++View actions:[AX_FOCUS] bundle:[chromeRole="rootWebArea"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-focus-expected-android-external.txt b/content/test/data/accessibility/html/iframe-focus-expected-android-external.txt index 279ab5530..5cd981f2 100644 --- a/content/test/data/accessibility/html/iframe-focus-expected-android-external.txt +++ b/content/test/data/accessibility/html/iframe-focus-expected-android-external.txt
@@ -1,10 +1,10 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="iframe"] -++++++View scrollable actions:[AX_FOCUS] bundle:[chromeRole="rootWebArea"] +++++++View actions:[AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++++++++Button text:"Button with focus handler" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] ++++++++TextView viewIdResName:"focused_log" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="iframe"] -++++++View scrollable actions:[AX_FOCUS] bundle:[chromeRole="rootWebArea"] +++++++View actions:[AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++++++++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++++++++Button text:"Ordinary Button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-traversal-expected-android-external.txt b/content/test/data/accessibility/html/iframe-traversal-expected-android-external.txt index 4fd2618..f1b370ab 100644 --- a/content/test/data/accessibility/html/iframe-traversal-expected-android-external.txt +++ b/content/test/data/accessibility/html/iframe-traversal-expected-android-external.txt
@@ -1,7 +1,7 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Before iframe" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="iframe"] -++++++View text:"Error" focusable scrollable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] +++++++View text:"Error" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++++++++TextView text:"Could not load the requested resource.\nError code: -6 (net::ERR_FILE_NOT_FOUND)" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"After iframe" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/img-empty-alt-expected-android-external.txt b/content/test/data/accessibility/html/img-empty-alt-expected-android-external.txt index 453ddfc..8adb793 100644 --- a/content/test/data/accessibility/html/img-empty-alt-expected-android-external.txt +++ b/content/test/data/accessibility/html/img-empty-alt-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/read.jpg"] @@ -7,4 +7,4 @@ ++++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++Image text:"read" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/read.jpg"] ++++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++Image text:"full" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/read.jpg"] +++++Image text:"full" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/read.jpg"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/img-expected-android-external.txt b/content/test/data/accessibility/html/img-expected-android-external.txt index 779b59d..b4bf48c 100644 --- a/content/test/data/accessibility/html/img-expected-android-external.txt +++ b/content/test/data/accessibility/html/img-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image text:"pipe" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/pipe.jpg"] ++++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/html/img-link-empty-alt-expected-android-external.txt b/content/test/data/accessibility/html/img-link-empty-alt-expected-android-external.txt index c28f764c..52ab526 100644 --- a/content/test/data/accessibility/html/img-link-empty-alt-expected-android-external.txt +++ b/content/test/data/accessibility/html/img-link-empty-alt-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++View text:"null" contentDescription:"unread " clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo"] ++++++TextView text:"unread " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText", clickableScore="100"]
diff --git a/content/test/data/accessibility/html/in-page-links-expected-android-external.txt b/content/test/data/accessibility/html/in-page-links-expected-android-external.txt index 830f815..5347808 100644 --- a/content/test/data/accessibility/html/in-page-links-expected-android-external.txt +++ b/content/test/data/accessibility/html/in-page-links-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"null" contentDescription:"Empty anchor" viewIdResName:"anchor1" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/in-page-links.html#emptyAnchor"] ++++TextView text:"Empty anchor" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText", clickableScore="100"] ++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/html/input-button-expected-android-external.txt b/content/test/data/accessibility/html/input-button-expected-android-external.txt index ab7ced1..84e41bd 100644 --- a/content/test/data/accessibility/html/input-button-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-button-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Button text:"Button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] ++++Button text:"Name" hint:"Description" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hint="Description", roleDescription="button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-checkbox-label-expected-android-external.txt b/content/test/data/accessibility/html/input-checkbox-label-expected-android-external.txt index 6df49e4..fddf607 100644 --- a/content/test/data/accessibility/html/input-checkbox-label-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-checkbox-label-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++CheckBox text:"Checkbox Title" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", clickableScore="300", roleDescription="checkbox"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-color-expected-android-external.txt b/content/test/data/accessibility/html/input-color-expected-android-external.txt index d18c0223..fd0a9c30 100644 --- a/content/test/data/accessibility/html/input-color-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-color-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Spinner text:"#FF9900" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="colorWell", clickableScore="300", roleDescription="color picker"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-color-with-popup-open-expected-android-external.txt b/content/test/data/accessibility/html/input-color-with-popup-open-expected-android-external.txt index d18c0223..fd0a9c30 100644 --- a/content/test/data/accessibility/html/input-color-with-popup-open-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-color-with-popup-open-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Spinner text:"#FF9900" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="colorWell", clickableScore="300", roleDescription="color picker"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-date-expected-android-external.txt b/content/test/data/accessibility/html/input-date-expected-android-external.txt index fc430fe..2b6c8a2 100644 --- a/content/test/data/accessibility/html/input-date-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-date-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Spinner text:"2008-09-01" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", roleDescription="date picker"] ++++Spinner text:"2008-09-01" hint:"When" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", hint="When", roleDescription="date picker"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-expected-android-external.txt b/content/test/data/accessibility/html/input-date-with-popup-open-expected-android-external.txt index 510d01d..f4b0454 100644 --- a/content/test/data/accessibility/html/input-date-with-popup-open-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-date-with-popup-open-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Spinner text:"2008-09-01" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", roleDescription="date picker"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-android-external.txt b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-android-external.txt index 3d32f31..b5998cc1 100644 --- a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-android-external.txt
@@ -1,5 +1,5 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Spinner text:"2008-09-01" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", roleDescription="date picker"] ++++Spinner text:"2008-09-01" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", roleDescription="date picker"] -++++Spinner text:"2008-09-01" hint:"Third date picker" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", hint="Third date picker", roleDescription="date picker"] +++++Spinner text:"2008-09-01" hint:"Third date picker" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", hint="Third date picker", roleDescription="date picker"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-android-external.txt b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-android-external.txt index 96460d74..b5998cc1 100644 --- a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Spinner text:"2008-09-01" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", roleDescription="date picker"] ++++Spinner text:"2008-09-01" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", roleDescription="date picker"]
diff --git a/content/test/data/accessibility/html/input-datetime-expected-android-external.txt b/content/test/data/accessibility/html/input-datetime-expected-android-external.txt index d8fc6b5..39cc40d 100644 --- a/content/test/data/accessibility/html/input-datetime-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-datetime-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText text:"1/1/2015 1:00AM" clickable editable focusable inputType:4 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] ++++EditText text:"1/1/2015 1:00AM" hint:"Launch" clickable editable focusable inputType:4 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Launch"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-datetime-local-expected-android-external.txt b/content/test/data/accessibility/html/input-datetime-local-expected-android-external.txt index cd4bf0a..3fd6dedb 100644 --- a/content/test/data/accessibility/html/input-datetime-local-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-datetime-local-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Spinner clickable focusable inputType:4 actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="dateTime", clickableScore="300", roleDescription="local date and time picker"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-email-expected-android-external.txt b/content/test/data/accessibility/html/input-email-expected-android-external.txt index 0ee9e0e..7e6821f5 100644 --- a/content/test/data/accessibility/html/input-email-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-email-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText text:"someone@example.com" clickable editable focusable inputType:209 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-file-expected-android-external.txt b/content/test/data/accessibility/html/input-file-expected-android-external.txt index 46a37a5..af7334a 100644 --- a/content/test/data/accessibility/html/input-file-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-file-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] -++++Button text:"Choose File: No file chosen" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] +++++Button text:"Choose File: No file chosen" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-image-expected-android-external.txt b/content/test/data/accessibility/html/input-image-expected-android-external.txt index b0273d1..7cda54c 100644 --- a/content/test/data/accessibility/html/input-image-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-image-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View viewIdResName:"body" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Button text:"Submit" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-list-expected-android-external.txt b/content/test/data/accessibility/html/input-list-expected-android-external.txt index 5329ccb..2bffb33d 100644 --- a/content/test/data/accessibility/html/input-list-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-list-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="labelText"] ++++++TextView text:"Choose a pokemon " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/html/input-month-expected-android-external.txt b/content/test/data/accessibility/html/input-month-expected-android-external.txt index 7ce2028b..a13cf408 100644 --- a/content/test/data/accessibility/html/input-month-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-month-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Spinner clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="dateTime", clickableScore="300", roleDescription="month picker"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-number-expected-android-external.txt b/content/test/data/accessibility/html/input-number-expected-android-external.txt index dcdb466..3115997 100644 --- a/content/test/data/accessibility/html/input-number-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-number-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText text:"1" clickable editable focusable inputType:2 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, SET_PROGRESS, IME_ENTER] bundle:[chromeRole="spinButton", clickableScore="300", roleDescription="spin button"] ++++EditText text:"6" clickable editable focusable inputType:2 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, SET_PROGRESS, IME_ENTER] bundle:[chromeRole="spinButton", clickableScore="300", roleDescription="spin button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-password-obscured-expected-android-external.txt b/content/test/data/accessibility/html/input-password-obscured-expected-android-external.txt index e781724..c2b7719 100644 --- a/content/test/data/accessibility/html/input-password-obscured-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-password-obscured-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText text:"•••" viewIdResName:"input" clickable editable focusable password inputType:225 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-radio-checkbox-label-expected-android-external.txt b/content/test/data/accessibility/html/input-radio-checkbox-label-expected-android-external.txt index 68a760f..fb8aca55 100644 --- a/content/test/data/accessibility/html/input-radio-checkbox-label-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-radio-checkbox-label-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++RadioButton text:"label ignored for radio button" viewIdResName:"radio1" stateDescription:"Not checked. In group, option 1 of 2" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="radioButton", clickableScore="300", roleDescription="radio button"] ++++CheckBox text:"label ignored for checkbox" viewIdResName:"checkbox1" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", clickableScore="300", roleDescription="checkbox"]
diff --git a/content/test/data/accessibility/html/input-radio-expected-android-external.txt b/content/test/data/accessibility/html/input-radio-expected-android-external.txt index fe73ae5..dd3e4ef 100644 --- a/content/test/data/accessibility/html/input-radio-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-radio-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="section"] ++++RadioButton checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="radioButton", clickableScore="300", roleDescription="radio button"] ++++TextView text:"Radio1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/html/input-radio-in-menu-expected-android-external.txt b/content/test/data/accessibility/html/input-radio-in-menu-expected-android-external.txt index 8b10e78..1e7afea3 100644 --- a/content/test/data/accessibility/html/input-radio-in-menu-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-radio-in-menu-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="menu", roleDescription="menu"] ++++RadioButton stateDescription:"Checked. In group, option 1 of 3" checkable checked clickable focusable actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="radioButton", clickableScore="300", roleDescription="radio button"] ++++TextView text:"Radio0 " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/html/input-range-expected-android-external.txt b/content/test/data/accessibility/html/input-range-expected-android-external.txt index 7f1e4fe4..4154f52b 100644 --- a/content/test/data/accessibility/html/input-range-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-range-expected-android-external.txt
@@ -1,8 +1,8 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++SeekBar text:"5" clickable focusable RangeInfo:[current=5.0, min=1.0, max=10.0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"] ++++SeekBar text:"3" clickable focusable RangeInfo:[current=3.0, min=1.0, max=10.0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"] ++++SeekBar text:"Medium" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"] ++++SeekBar text:"Friday" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"] ++++SeekBar text:"0.2" clickable focusable RangeInfo:[current=0.2, min=-1.0, max=1.0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"] -++++SeekBar text:"50" clickable focusable RangeInfo:[current=50.0, min=0.0, max=100.0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"] +++++SeekBar text:"50" clickable focusable RangeInfo:[current=50.0, min=0.0, max=100.0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-reset-expected-android-external.txt b/content/test/data/accessibility/html/input-reset-expected-android-external.txt index ce02aef..36d8f04 100644 --- a/content/test/data/accessibility/html/input-reset-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-reset-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] ++++Button text:"Reset" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-search-expected-android-external.txt b/content/test/data/accessibility/html/input-search-expected-android-external.txt index a8dfd6c0e..dc001bc7 100644 --- a/content/test/data/accessibility/html/input-search-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-search-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText text:"Search terms" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="searchBox", clickableScore="300", roleDescription="search text field"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-submit-expected-android-external.txt b/content/test/data/accessibility/html/input-submit-expected-android-external.txt index d4a28c8..202c26e0 100644 --- a/content/test/data/accessibility/html/input-submit-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-submit-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="section"] ++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] ++++Button text:"First submit in a form is a valid default button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] @@ -8,4 +8,4 @@ ++++Button text:"First image button in a form is a valid default button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hasImage="true", roleDescription="button"] ++++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++Button text:"Second image button in a form not a valid default button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hasImage="true", roleDescription="button"] -++Button text:"Submit outside of form not a valid default button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] +++Button text:"Submit outside of form not a valid default button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-suggestions-source-element-expected-android-external.txt b/content/test/data/accessibility/html/input-suggestions-source-element-expected-android-external.txt index 96fe1fb..d10db731 100644 --- a/content/test/data/accessibility/html/input-suggestions-source-element-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-suggestions-source-element-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText canOpenPopUp clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textFieldWithComboBox", clickableScore="300"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-tel-expected-android-external.txt b/content/test/data/accessibility/html/input-tel-expected-android-external.txt index b5ce652..02cf74c 100644 --- a/content/test/data/accessibility/html/input-tel-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-tel-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText text:"123-456-7890" clickable editable focusable inputType:3 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-text-expected-android-external.txt b/content/test/data/accessibility/html/input-text-expected-android-external.txt index 7a0f820..c694e8ae 100644 --- a/content/test/data/accessibility/html/input-text-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-text-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable scrollable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText hint:"Name" clickable editable focusable focused inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[CLEAR_FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Name"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-text-name-calc-expected-android-external.txt b/content/test/data/accessibility/html/input-text-name-calc-expected-android-external.txt index 28dc283..10063fb6 100644 --- a/content/test/data/accessibility/html/input-text-name-calc-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-text-name-calc-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++EditText hint:"Title0" viewIdResName:"c0" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Title0"] ++EditText hint:"Label1 Title1" viewIdResName:"c1" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Label1 Title1"] ++EditText hint:"AriaLabel2 Title2" viewIdResName:"c2" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="AriaLabel2 Title2"]
diff --git a/content/test/data/accessibility/html/input-text-range-expected-android-external.txt b/content/test/data/accessibility/html/input-text-range-expected-android-external.txt index a683655..e97ecfb 100644 --- a/content/test/data/accessibility/html/input-text-range-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-text-range-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++SeekBar text:"medium" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="labelText"]
diff --git a/content/test/data/accessibility/html/input-text-read-only-expected-android-external.txt b/content/test/data/accessibility/html/input-text-read-only-expected-android-external.txt index 80f50f4..b9753c5 100644 --- a/content/test/data/accessibility/html/input-text-read-only-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-text-read-only-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable scrollable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText hint:"Name" clickable editable disabled focusable focused inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[CLEAR_FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="textField", clickableScore="300", hint="Name"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-text-value-expected-android-external.txt b/content/test/data/accessibility/html/input-text-value-expected-android-external.txt index caf5c293..8bec58e 100644 --- a/content/test/data/accessibility/html/input-text-value-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-text-value-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"l1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="labelText"] ++++EditText hint:"l1" viewIdResName:"i1" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="l1"]
diff --git a/content/test/data/accessibility/html/input-time-expected-android-external.txt b/content/test/data/accessibility/html/input-time-expected-android-external.txt index 0d38378d..3b539285 100644 --- a/content/test/data/accessibility/html/input-time-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-time-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Spinner text:"00:00:00" clickable focusable inputType:36 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="inputTime", clickableScore="300", roleDescription="time picker"] ++++Spinner text:"00:00:00" hint:"Breakfast" clickable focusable inputType:36 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="inputTime", clickableScore="300", hint="Breakfast", roleDescription="time picker"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-time-with-popup-open-expected-android-external.txt b/content/test/data/accessibility/html/input-time-with-popup-open-expected-android-external.txt index 984879d6..639a122 100644 --- a/content/test/data/accessibility/html/input-time-with-popup-open-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-time-with-popup-open-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Spinner text:"13:50:02.922" clickable focusable inputType:36 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="inputTime", clickableScore="300", roleDescription="time picker"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-url-expected-android-external.txt b/content/test/data/accessibility/html/input-url-expected-android-external.txt index 3b5ebf14..007de18 100644 --- a/content/test/data/accessibility/html/input-url-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-url-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText text:"example.com" error:"Invalid entry" clickable contentInvalid editable focusable inputType:17 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-week-expected-android-external.txt b/content/test/data/accessibility/html/input-week-expected-android-external.txt index 967b9cc..5eb269590a 100644 --- a/content/test/data/accessibility/html/input-week-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-week-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Spinner clickable focusable inputType:4 actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="dateTime", clickableScore="300", roleDescription="week picker"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/ins-expected-android-external.txt b/content/test/data/accessibility/html/ins-expected-android-external.txt index 83728cd..ee72e2f 100644 --- a/content/test/data/accessibility/html/ins-expected-android-external.txt +++ b/content/test/data/accessibility/html/ins-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"] ++++TextView text:"My favorite browser is " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View text:"ABC" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="contentDeletion", roleDescription="deletion"]
diff --git a/content/test/data/accessibility/html/interactive-controls-with-labels-expected-android-external.txt b/content/test/data/accessibility/html/interactive-controls-with-labels-expected-android-external.txt index 2d0a174..69c5464 100644 --- a/content/test/data/accessibility/html/interactive-controls-with-labels-expected-android-external.txt +++ b/content/test/data/accessibility/html/interactive-controls-with-labels-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Test label" viewIdResName:"label1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="labelText"] ++TextView text:"aria label" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"Test label" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"]
diff --git a/content/test/data/accessibility/html/isInteresting-expected-android-external.txt b/content/test/data/accessibility/html/isInteresting-expected-android-external.txt index 66f849c..66f3594 100644 --- a/content/test/data/accessibility/html/isInteresting-expected-android-external.txt +++ b/content/test/data/accessibility/html/isInteresting-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"A non focusable child of a control should not be interesting on Android" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 1"] ++TextView text:"Div with click handler" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", clickableScore="200"] ++Button text:"I am interesting" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/label-expected-android-external.txt b/content/test/data/accessibility/html/label-expected-android-external.txt index 6d69b86..fd16aa1 100644 --- a/content/test/data/accessibility/html/label-expected-android-external.txt +++ b/content/test/data/accessibility/html/label-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"Label" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="labelText"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/legend-expected-android-external.txt b/content/test/data/accessibility/html/legend-expected-android-external.txt index 4ccd99b5..19cf9fcb 100644 --- a/content/test/data/accessibility/html/legend-expected-android-external.txt +++ b/content/test/data/accessibility/html/legend-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="section"] ++++View text:"Browser Engines:" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] ++++++View text:"Browser Engines:" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="legend"]
diff --git a/content/test/data/accessibility/html/li-expected-android-external.txt b/content/test/data/accessibility/html/li-expected-android-external.txt index 6d04263..721dafd 100644 --- a/content/test/data/accessibility/html/li-expected-android-external.txt +++ b/content/test/data/accessibility/html/li-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=3, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View text:"Custom name" CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listItem"] ++++++View text:"• " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listMarker"]
diff --git a/content/test/data/accessibility/html/link-inside-heading-expected-android-external.txt b/content/test/data/accessibility/html/link-inside-heading-expected-android-external.txt index ffff2e96..397087fe8 100644 --- a/content/test/data/accessibility/html/link-inside-heading-expected-android-external.txt +++ b/content/test/data/accessibility/html/link-inside-heading-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Link In Heading" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 1 link"] ++++View text:"null" contentDescription:"Link In Heading" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="heading 1 link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/link-inside-heading.html#"] ++++++TextView text:"Link In Heading" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText", clickableScore="100"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/list-expected-android-external.txt b/content/test/data/accessibility/html/list-expected-android-external.txt index d542816..e516369 100644 --- a/content/test/data/accessibility/html/list-expected-android-external.txt +++ b/content/test/data/accessibility/html/list-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=3, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS] bundle:[chromeRole="listItem"] ++++++View text:"• " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listMarker"]
diff --git a/content/test/data/accessibility/html/list-item-aria-setsize-unknown-expected-android-external.txt b/content/test/data/accessibility/html/list-item-aria-setsize-unknown-expected-android-external.txt index 1546f1ed..00ac160 100644 --- a/content/test/data/accessibility/html/list-item-aria-setsize-unknown-expected-android-external.txt +++ b/content/test/data/accessibility/html/list-item-aria-setsize-unknown-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[hierarchical, rows=8, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View text:"Level 1, item 5 of set size unknown" CollectionItemInfo:[rowIndex=4, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listItem"] ++++View CollectionItemInfo:[rowIndex=5, colIndex=0] actions:[AX_FOCUS] bundle:[chromeRole="listItem"]
diff --git a/content/test/data/accessibility/html/list-item-aria-setsize-unknown-flattened-expected-android-external.txt b/content/test/data/accessibility/html/list-item-aria-setsize-unknown-flattened-expected-android-external.txt index b452980..0ee6522 100644 --- a/content/test/data/accessibility/html/list-item-aria-setsize-unknown-flattened-expected-android-external.txt +++ b/content/test/data/accessibility/html/list-item-aria-setsize-unknown-flattened-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=1, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View text:"Level 1, item 1 of set size unknown" CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listItem"] ++ListView CollectionInfo:[rows=1, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"]
diff --git a/content/test/data/accessibility/html/list-markers-expected-android-external.txt b/content/test/data/accessibility/html/list-markers-expected-android-external.txt index 2bd6cde62..c4bd14c 100644 --- a/content/test/data/accessibility/html/list-markers-expected-android-external.txt +++ b/content/test/data/accessibility/html/list-markers-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=3, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS] bundle:[chromeRole="listItem"] ++++++View text:"• " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listMarker"]
diff --git a/content/test/data/accessibility/html/main-expected-android-external.txt b/content/test/data/accessibility/html/main-expected-android-external.txt index bf4f891..b8cc4ab 100644 --- a/content/test/data/accessibility/html/main-expected-android-external.txt +++ b/content/test/data/accessibility/html/main-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"This is main element." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="main", roleDescription="main"] ++View text:"This is an ARIA role main." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="main", roleDescription="main"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/map-any-contents-expected-android-external.txt b/content/test/data/accessibility/html/map-any-contents-expected-android-external.txt index a77a1a9..4c961c5 100644 --- a/content/test/data/accessibility/html/map-any-contents-expected-android-external.txt +++ b/content/test/data/accessibility/html/map-any-contents-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image text:"pipe" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/pipe.jpg"] ++++++TextView text:"Headings are allowed in a map" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 1"] @@ -7,4 +7,4 @@ ++++++++TextView text:"So are " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++++++View text:"other elements" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="mark", roleDescription="highlight"] ++++++++TextView text:"!" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++++Button text:"Even a button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] +++++++Button text:"Even a button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/mark-expected-android-external.txt b/content/test/data/accessibility/html/mark-expected-android-external.txt index 6ee348e..0ff0564 100644 --- a/content/test/data/accessibility/html/mark-expected-android-external.txt +++ b/content/test/data/accessibility/html/mark-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"] ++++TextView text:"This test is to check " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View text:"mark tag" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="mark", roleDescription="highlight"]
diff --git a/content/test/data/accessibility/html/math-expected-android-external.txt b/content/test/data/accessibility/html/math-expected-android-external.txt index a97ae4e..83e686a 100644 --- a/content/test/data/accessibility/html/math-expected-android-external.txt +++ b/content/test/data/accessibility/html/math-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="mathMLMath", roleDescription="math"] ++++++View actions:[AX_FOCUS] bundle:[chromeRole="mathMLRow"]
diff --git a/content/test/data/accessibility/html/menu-expected-android-external.txt b/content/test/data/accessibility/html/menu-expected-android-external.txt index 0cfcd04..3378a0c 100644 --- a/content/test/data/accessibility/html/menu-expected-android-external.txt +++ b/content/test/data/accessibility/html/menu-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Menu is deprecated, but it may still be used semantically with list item children. For more history, see crbug.com/87553." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++ListView CollectionInfo:[rows=2, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View text:"Cats" CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listItem"]
diff --git a/content/test/data/accessibility/html/meter-expected-android-external.txt b/content/test/data/accessibility/html/meter-expected-android-external.txt index 58db7b8..39ff2ff 100644 --- a/content/test/data/accessibility/html/meter-expected-android-external.txt +++ b/content/test/data/accessibility/html/meter-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++ProgressBar text:"2" RangeInfo:[current=2.0, min=1.0, max=10.0] actions:[AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="meter", roleDescription="meter"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/navigation-expected-android-external.txt b/content/test/data/accessibility/html/navigation-expected-android-external.txt index b97e7fa8..03fdbbc 100644 --- a/content/test/data/accessibility/html/navigation-expected-android-external.txt +++ b/content/test/data/accessibility/html/navigation-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="navigation", roleDescription="navigation"] ++++View text:"null" contentDescription:"Don't click on me" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///fake/"] ++++++TextView text:"Don't click on me" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText", clickableScore="100"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/nestedlist-expected-android-external.txt b/content/test/data/accessibility/html/nestedlist-expected-android-external.txt index 8d8a88ea..a03ece4 100644 --- a/content/test/data/accessibility/html/nestedlist-expected-android-external.txt +++ b/content/test/data/accessibility/html/nestedlist-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"This is a multi-leveled list" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++ListView CollectionInfo:[hierarchical, rows=3, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS] bundle:[chromeRole="listItem"]
diff --git a/content/test/data/accessibility/html/object-expected-android-external.txt b/content/test/data/accessibility/html/object-expected-android-external.txt index d30be048..42591f76 100644 --- a/content/test/data/accessibility/html/object-expected-android-external.txt +++ b/content/test/data/accessibility/html/object-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View disabled actions:[AX_FOCUS] bundle:[chromeRole="pluginObject", roleDescription="object"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/offscreen-iframe-content-expected-android-external.txt b/content/test/data/accessibility/html/offscreen-iframe-content-expected-android-external.txt index 7f029ff..58a8342 100644 --- a/content/test/data/accessibility/html/offscreen-iframe-content-expected-android-external.txt +++ b/content/test/data/accessibility/html/offscreen-iframe-content-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"iframe_onscreen" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] ++View text:"iframe_offscreen" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/offscreen-iframe-expected-android-external.txt b/content/test/data/accessibility/html/offscreen-iframe-expected-android-external.txt index 56adbf13..d931e584 100644 --- a/content/test/data/accessibility/html/offscreen-iframe-expected-android-external.txt +++ b/content/test/data/accessibility/html/offscreen-iframe-expected-android-external.txt
@@ -1,6 +1,6 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="iframe"] -++++++View scrollable actions:[AX_FOCUS] bundle:[chromeRole="rootWebArea"] +++++++View actions:[AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++++++++View text:"iframe_onscreen" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] ++++++++View text:"iframe_offscreen" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/offscreen-select-expected-android-external.txt b/content/test/data/accessibility/html/offscreen-select-expected-android-external.txt index 3ba9e43..dc0cea1 100644 --- a/content/test/data/accessibility/html/offscreen-select-expected-android-external.txt +++ b/content/test/data/accessibility/html/offscreen-select-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Onscreen 1" canOpenPopUp clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="comboBoxSelect", clickableScore="300", roleDescription="menu pop up button"] ++View text:"Offscreen 1" canOpenPopUp clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="comboBoxSelect", clickableScore="300", roleDescription="menu pop up button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/ol-expected-android-external.txt b/content/test/data/accessibility/html/ol-expected-android-external.txt index 4baaab2..bda0894 100644 --- a/content/test/data/accessibility/html/ol-expected-android-external.txt +++ b/content/test/data/accessibility/html/ol-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=3, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS] bundle:[chromeRole="listItem"] ++++++View text:"1. " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listMarker"]
diff --git a/content/test/data/accessibility/html/optgroup-expected-android-external.txt b/content/test/data/accessibility/html/optgroup-expected-android-external.txt index 2e87234..34815da 100644 --- a/content/test/data/accessibility/html/optgroup-expected-android-external.txt +++ b/content/test/data/accessibility/html/optgroup-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View viewIdResName:"listbox" canOpenPopUp clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, EXPAND] bundle:[chromeRole="comboBoxSelect", clickableScore="300", roleDescription="menu pop up button"] ++++++View notVisibleToUser actions:[AX_FOCUS] bundle:[chromeRole="menuListPopup"]
diff --git a/content/test/data/accessibility/html/output-expected-android-external.txt b/content/test/data/accessibility/html/output-expected-android-external.txt index b53aaab2..fb20a7f 100644 --- a/content/test/data/accessibility/html/output-expected-android-external.txt +++ b/content/test/data/accessibility/html/output-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="section"] ++++EditText clickable editable focusable inputType:2 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, SET_PROGRESS, IME_ENTER] bundle:[chromeRole="spinButton", clickableScore="300", roleDescription="spin button"] ++++TextView text:" + " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/html/overflow-actions-expected-android-external.txt b/content/test/data/accessibility/html/overflow-actions-expected-android-external.txt index be4a02a..29023fb 100644 --- a/content/test/data/accessibility/html/overflow-actions-expected-android-external.txt +++ b/content/test/data/accessibility/html/overflow-actions-expected-android-external.txt
@@ -1,5 +1,5 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++View text:"Example Paragraph 1 Example Paragraph 2" focusable scrollable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +++View text:"Example Paragraph 1 Example Paragraph 2" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++TextView text:"Example Paragraph 1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] -++++TextView text:"Example Paragraph 2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] +++++TextView text:"Example Paragraph 2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/p-expected-android-external.txt b/content/test/data/accessibility/html/p-expected-android-external.txt index 57bd1a2..639b392 100644 --- a/content/test/data/accessibility/html/p-expected-android-external.txt +++ b/content/test/data/accessibility/html/p-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Before" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++TextView text:"Paragraph" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++TextView text:"After" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/param-expected-android-external.txt b/content/test/data/accessibility/html/param-expected-android-external.txt index d30be048..42591f76 100644 --- a/content/test/data/accessibility/html/param-expected-android-external.txt +++ b/content/test/data/accessibility/html/param-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View disabled actions:[AX_FOCUS] bundle:[chromeRole="pluginObject", roleDescription="object"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/picture-expected-android-external.txt b/content/test/data/accessibility/html/picture-expected-android-external.txt index 5b90f30..339be4f 100644 --- a/content/test/data/accessibility/html/picture-expected-android-external.txt +++ b/content/test/data/accessibility/html/picture-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image text:"x" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/400.webp"] ++++Image text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/400.webp"]
diff --git a/content/test/data/accessibility/html/pre-expected-android-external.txt b/content/test/data/accessibility/html/pre-expected-android-external.txt index bb1d7d9..800adf08 100644 --- a/content/test/data/accessibility/html/pre-expected-android-external.txt +++ b/content/test/data/accessibility/html/pre-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"This test is to check pre\nformatting." viewIdResName:"pre" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"This test is to check pre\nformatting" viewIdResName:"div-pre" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"This test is to check pre\nformatting." viewIdResName:"div-pre-wrap" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"]
diff --git a/content/test/data/accessibility/html/progress-expected-android-external.txt b/content/test/data/accessibility/html/progress-expected-android-external.txt index 599873db..b70ad818 100644 --- a/content/test/data/accessibility/html/progress-expected-android-external.txt +++ b/content/test/data/accessibility/html/progress-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++ProgressBar text:"22" RangeInfo:[current=22.0, min=0.0, max=100.0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="progressIndicator", roleDescription="progress indicator"] ++++ProgressBar text:"indeterminate" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="progressIndicator", roleDescription="progress indicator"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/q-expected-android-external.txt b/content/test/data/accessibility/html/q-expected-android-external.txt index f0483a7..0f1bc558 100644 --- a/content/test/data/accessibility/html/q-expected-android-external.txt +++ b/content/test/data/accessibility/html/q-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"This is “Chromium Blink” based browser." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/replaced-node-across-trees-expected-android-external.txt b/content/test/data/accessibility/html/replaced-node-across-trees-expected-android-external.txt index 0297e6f..6a26f69 100644 --- a/content/test/data/accessibility/html/replaced-node-across-trees-expected-android-external.txt +++ b/content/test/data/accessibility/html/replaced-node-across-trees-expected-android-external.txt
@@ -1,8 +1,8 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Before frame" viewIdResName:"s1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="iframe"] -++++++View scrollable actions:[AX_FOCUS] bundle:[chromeRole="rootWebArea"] +++++++View actions:[AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++++++++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++++++++TextView text:"Text in iframe" viewIdResName:"s1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"After frame" viewIdResName:"s2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/ruby-expected-android-external.txt b/content/test/data/accessibility/html/ruby-expected-android-external.txt index 3b797cc..b18c4c4 100644 --- a/content/test/data/accessibility/html/ruby-expected-android-external.txt +++ b/content/test/data/accessibility/html/ruby-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"ruby base" hint:"ruby text" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="ruby", hint="ruby text"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"] ++++View text:"ruby base" hint:"ruby text" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="ruby", hint="ruby text"]
diff --git a/content/test/data/accessibility/html/s-expected-android-external.txt b/content/test/data/accessibility/html/s-expected-android-external.txt index 55a7d80..fbea0c9b 100644 --- a/content/test/data/accessibility/html/s-expected-android-external.txt +++ b/content/test/data/accessibility/html/s-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"My car is blue." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="contentDeletion", roleDescription="deletion"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/samp-expected-android-external.txt b/content/test/data/accessibility/html/samp-expected-android-external.txt index 9c31122..df85054 100644 --- a/content/test/data/accessibility/html/samp-expected-android-external.txt +++ b/content/test/data/accessibility/html/samp-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Sample output from a computer program" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/scrollable-expected-android-external.txt b/content/test/data/accessibility/html/scrollable-expected-android-external.txt index acf6aab..ce82b716 100644 --- a/content/test/data/accessibility/html/scrollable-expected-android-external.txt +++ b/content/test/data/accessibility/html/scrollable-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"not scrollable" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] -++TextView focusable scrollable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="genericContainer"] -++TextView focusable scrollable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="genericContainer"] +++TextView focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="genericContainer"] +++TextView focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/scrollable-overflow-expected-android-external.txt b/content/test/data/accessibility/html/scrollable-overflow-expected-android-external.txt index 1c35aa9c..7669757 100644 --- a/content/test/data/accessibility/html/scrollable-overflow-expected-android-external.txt +++ b/content/test/data/accessibility/html/scrollable-overflow-expected-android-external.txt
@@ -1,20 +1,20 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"no overflow" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++TextView text:"clipped large lots of text more text" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] -++EditText text:"ab cd" clickable editable focusable multiLine scrollable textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] +++EditText text:"ab cd" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++TextView text:"tiny" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++View actions:[AX_FOCUS] bundle:[chromeRole="group"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++++TextView text:"x=hidden" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] -++++View text:"x=hidden" focusable scrollable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] -++++View text:"x=auto" focusable scrollable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] -++++View text:"x=scroll" focusable scrollable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] +++++View text:"x=hidden" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] +++++View text:"x=auto" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] +++++View text:"x=scroll" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++++TextView text:"x=visible" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++View actions:[AX_FOCUS] bundle:[chromeRole="group"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++++TextView text:"y=hidden" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] -++++View text:"y=hidden" focusable scrollable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] -++++View text:"y=auto" focusable scrollable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] -++++View text:"y=scroll" focusable scrollable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] -++++TextView text:"y=visible" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] +++++View text:"y=hidden" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] +++++View text:"y=auto" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] +++++View text:"y=scroll" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] +++++TextView text:"y=visible" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/scrollable-textarea-expected-android-external.txt b/content/test/data/accessibility/html/scrollable-textarea-expected-android-external.txt index 63d31a6..b6c8679 100644 --- a/content/test/data/accessibility/html/scrollable-textarea-expected-android-external.txt +++ b/content/test/data/accessibility/html/scrollable-textarea-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText text:"little" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] -++++EditText text:"lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text" clickable editable focusable multiLine scrollable textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] \ No newline at end of file +++++EditText text:"lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text+ lots+of+text" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/search-expected-android-external.txt b/content/test/data/accessibility/html/search-expected-android-external.txt index 0a2a52b7..01f9a28 100644 --- a/content/test/data/accessibility/html/search-expected-android-external.txt +++ b/content/test/data/accessibility/html/search-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="search", roleDescription="search"] ++++View text:"Search element." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="labelText"] ++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="searchBox", clickableScore="300", roleDescription="search text field"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/section-expected-android-external.txt b/content/test/data/accessibility/html/section-expected-android-external.txt index bb679f84..0c39350e 100644 --- a/content/test/data/accessibility/html/section-expected-android-external.txt +++ b/content/test/data/accessibility/html/section-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"An unnamed section element gets the section role." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="section"] ++View text:"name" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"] ++View text:"Named section element #2 gets the region role" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"]
diff --git a/content/test/data/accessibility/html/select-expected-android-external.txt b/content/test/data/accessibility/html/select-expected-android-external.txt index 8145dfd..e53f0c7e 100644 --- a/content/test/data/accessibility/html/select-expected-android-external.txt +++ b/content/test/data/accessibility/html/select-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"Placeholder option" viewIdResName:"A" canOpenPopUp clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="comboBoxSelect", clickableScore="300", roleDescription="menu pop up button"] ++++View text:"Option 2" viewIdResName:"B" canOpenPopUp clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="comboBoxSelect", clickableScore="300", roleDescription="menu pop up button"]
diff --git a/content/test/data/accessibility/html/selection-container-expected-android-external.txt b/content/test/data/accessibility/html/selection-container-expected-android-external.txt index 8fa5ef7e..11e59507 100644 --- a/content/test/data/accessibility/html/selection-container-expected-android-external.txt +++ b/content/test/data/accessibility/html/selection-container-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"selection_list" viewIdResName:"listbox" canOpenPopUp clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="comboBoxSelect", clickableScore="300", roleDescription="menu pop up button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/simple_spans-expected-android-external.txt b/content/test/data/accessibility/html/simple_spans-expected-android-external.txt index bbe49ae..7c04836 100644 --- a/content/test/data/accessibility/html/simple_spans-expected-android-external.txt +++ b/content/test/data/accessibility/html/simple_spans-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++TextView text:"Some text" viewIdResName:"s1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/html/small-expected-android-external.txt b/content/test/data/accessibility/html/small-expected-android-external.txt index 09584c05..5a215309 100644 --- a/content/test/data/accessibility/html/small-expected-android-external.txt +++ b/content/test/data/accessibility/html/small-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Chromiumopen source project" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/span-expected-android-external.txt b/content/test/data/accessibility/html/span-expected-android-external.txt index 5e8491b..cba4dac 100644 --- a/content/test/data/accessibility/html/span-expected-android-external.txt +++ b/content/test/data/accessibility/html/span-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"This paragraph has text in spans." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"] ++++TextView text:"E1. Eat" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/html/spans-separated-by-space-expected-android-external.txt b/content/test/data/accessibility/html/spans-separated-by-space-expected-android-external.txt index 984671b..5702a12 100644 --- a/content/test/data/accessibility/html/spans-separated-by-space-expected-android-external.txt +++ b/content/test/data/accessibility/html/spans-separated-by-space-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Hello world" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/static-list-expected-android-external.txt b/content/test/data/accessibility/html/static-list-expected-android-external.txt index d4e7ea9..e825420 100644 --- a/content/test/data/accessibility/html/static-list-expected-android-external.txt +++ b/content/test/data/accessibility/html/static-list-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=3, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS] bundle:[chromeRole="listItem"] ++++++View text:"1. " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listMarker"]
diff --git a/content/test/data/accessibility/html/strong-expected-android-external.txt b/content/test/data/accessibility/html/strong-expected-android-external.txt index 25051ff..bf2aff6 100644 --- a/content/test/data/accessibility/html/strong-expected-android-external.txt +++ b/content/test/data/accessibility/html/strong-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"Strong text" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="strong"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/sub-expected-android-external.txt b/content/test/data/accessibility/html/sub-expected-android-external.txt index e87871b..e35c41c0 100644 --- a/content/test/data/accessibility/html/sub-expected-android-external.txt +++ b/content/test/data/accessibility/html/sub-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"] ++++TextView text:"This text contains " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View text:"subscript" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="subscript"]
diff --git a/content/test/data/accessibility/html/summary-expected-android-external.txt b/content/test/data/accessibility/html/summary-expected-android-external.txt index 2232fc3..dc729d07 100644 --- a/content/test/data/accessibility/html/summary-expected-android-external.txt +++ b/content/test/data/accessibility/html/summary-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="details"] ++++View text:"details tag" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="disclosureTriangle", clickableScore="300", roleDescription="disclosure triangle"] ++View actions:[AX_FOCUS] bundle:[chromeRole="details"]
diff --git a/content/test/data/accessibility/html/sup-expected-android-external.txt b/content/test/data/accessibility/html/sup-expected-android-external.txt index 9a7d07f2..208c353 100644 --- a/content/test/data/accessibility/html/sup-expected-android-external.txt +++ b/content/test/data/accessibility/html/sup-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"] ++++TextView text:"This text contains" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View text:"superscript" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="superscript"]
diff --git a/content/test/data/accessibility/html/svg-as-object-source-expected-android-external.txt b/content/test/data/accessibility/html/svg-as-object-source-expected-android-external.txt index 4308c99..10daf585 100644 --- a/content/test/data/accessibility/html/svg-as-object-source-expected-android-external.txt +++ b/content/test/data/accessibility/html/svg-as-object-source-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"object without space" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="pluginObject", roleDescription="object"] ++++View text:"object with space" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="pluginObject", roleDescription="object"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/svg-child-of-button-expected-android-external.txt b/content/test/data/accessibility/html/svg-child-of-button-expected-android-external.txt index 39488e5..b484c2a3 100644 --- a/content/test/data/accessibility/html/svg-child-of-button-expected-android-external.txt +++ b/content/test/data/accessibility/html/svg-child-of-button-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Button text:"Search" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hasImage="true", roleDescription="button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/svg-child-of-svg-expected-android-external.txt b/content/test/data/accessibility/html/svg-child-of-svg-expected-android-external.txt index 8e2851e..650f068 100644 --- a/content/test/data/accessibility/html/svg-child-of-svg-expected-android-external.txt +++ b/content/test/data/accessibility/html/svg-child-of-svg-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image text:"Has two simple children" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic"] ++++Image text:"Has two focusable children" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"]
diff --git a/content/test/data/accessibility/html/svg-desc-in-group-expected-android-external.txt b/content/test/data/accessibility/html/svg-desc-in-group-expected-android-external.txt index c8bc6ffd..1e293be 100644 --- a/content/test/data/accessibility/html/svg-desc-in-group-expected-android-external.txt +++ b/content/test/data/accessibility/html/svg-desc-in-group-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] ++++++View hint:"Group with circle and text" actions:[AX_FOCUS] bundle:[chromeRole="group", hint="Group with circle and text"]
diff --git a/content/test/data/accessibility/html/svg-expected-android-external.txt b/content/test/data/accessibility/html/svg-expected-android-external.txt index d224d281..0dd9170 100644 --- a/content/test/data/accessibility/html/svg-expected-android-external.txt +++ b/content/test/data/accessibility/html/svg-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image text:"svg" hint:"SVG Title Tag" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="svgRoot", hasImage="true", hint="SVG Title Tag", roleDescription="graphic"] ++++++TextView text:"Test" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/svg-symbol-with-role-expected-android-external.txt b/content/test/data/accessibility/html/svg-symbol-with-role-expected-android-external.txt index 959ced7..7a18522 100644 --- a/content/test/data/accessibility/html/svg-symbol-with-role-expected-android-external.txt +++ b/content/test/data/accessibility/html/svg-symbol-with-role-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] ++++++Button text:"Click me!" viewIdResName:"myRect" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", roleDescription="fancy button"]
diff --git a/content/test/data/accessibility/html/svg-text-alternative-computation-expected-android-external.txt b/content/test/data/accessibility/html/svg-text-alternative-computation-expected-android-external.txt index a058d8d..7e764b1 100644 --- a/content/test/data/accessibility/html/svg-text-alternative-computation-expected-android-external.txt +++ b/content/test/data/accessibility/html/svg-text-alternative-computation-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] ++++++View text:"null" hint:"Link (from title)" contentDescription:"Link (from aria-labelledby)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from title)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"]
diff --git a/content/test/data/accessibility/html/svg-with-clickable-rect-expected-android-external.txt b/content/test/data/accessibility/html/svg-with-clickable-rect-expected-android-external.txt index b17c971..72376e8d 100644 --- a/content/test/data/accessibility/html/svg-with-clickable-rect-expected-android-external.txt +++ b/content/test/data/accessibility/html/svg-with-clickable-rect-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] ++++++View viewIdResName:"clickable" clickable actions:[CLICK, AX_FOCUS] bundle:[chromeRole="graphicsSymbol", clickableScore="200", hasImage="true", roleDescription="graphics symbol"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/svg-with-foreign-object-expected-android-external.txt b/content/test/data/accessibility/html/svg-with-foreign-object-expected-android-external.txt index 7148893..d513b4a 100644 --- a/content/test/data/accessibility/html/svg-with-foreign-object-expected-android-external.txt +++ b/content/test/data/accessibility/html/svg-with-foreign-object-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] ++++++TextView text:"Hello world" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/svg-with-link-to-document-expected-android-external.txt b/content/test/data/accessibility/html/svg-with-link-to-document-expected-android-external.txt index 7b82f3d0..94129bd 100644 --- a/content/test/data/accessibility/html/svg-with-link-to-document-expected-android-external.txt +++ b/content/test/data/accessibility/html/svg-with-link-to-document-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image text:"svg" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] ++++++View text:"null" contentDescription:"svg-with-link-to-document" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/svg-with-link-to-document.html#"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/svg-with-non-link-anchors-expected-android-external.txt b/content/test/data/accessibility/html/svg-with-non-link-anchors-expected-android-external.txt index d39b972..a7e9a25 100644 --- a/content/test/data/accessibility/html/svg-with-non-link-anchors-expected-android-external.txt +++ b/content/test/data/accessibility/html/svg-with-non-link-anchors-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image text:"Text descendants" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] ++++++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"]
diff --git a/content/test/data/accessibility/html/tabindex-expose-children-expected-android-external.txt b/content/test/data/accessibility/html/tabindex-expose-children-expected-android-external.txt index 07da67c9..ceb5374 100644 --- a/content/test/data/accessibility/html/tabindex-expose-children-expected-android-external.txt +++ b/content/test/data/accessibility/html/tabindex-expose-children-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="layoutTable"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="layoutTableRow"] ++++++View text:"1." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="layoutTableCell"]
diff --git a/content/test/data/accessibility/html/table-focusable-sections-expected-android-external.txt b/content/test/data/accessibility/html/table-focusable-sections-expected-android-external.txt index ccca0591..a6426aa0 100644 --- a/content/test/data/accessibility/html/table-focusable-sections-expected-android-external.txt +++ b/content/test/data/accessibility/html/table-focusable-sections-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView text:"Table example - focusable thead, tbody, tfoot" focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] +WebView text:"Table example - focusable thead, tbody, tfoot" focusable focused actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=4, cols=2] actions:[AX_FOCUS] bundle:[chromeRole="table", roleDescription="table"] ++++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="rowGroup"] ++++++View actions:[AX_FOCUS] bundle:[chromeRole="row"]
diff --git a/content/test/data/accessibility/html/table-layout-expected-android-external.txt b/content/test/data/accessibility/html/table-layout-expected-android-external.txt index 25d6253..88b384d9 100644 --- a/content/test/data/accessibility/html/table-layout-expected-android-external.txt +++ b/content/test/data/accessibility/html/table-layout-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView text:"Table example #2" focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] +WebView text:"Table example #2" focusable focused actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="layoutTable"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="layoutTableRow"] ++++++View text:"1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="layoutTableCell"]
diff --git a/content/test/data/accessibility/html/table-presentation-expected-android-external.txt b/content/test/data/accessibility/html/table-presentation-expected-android-external.txt index 1221450..e1ce2d80 100644 --- a/content/test/data/accessibility/html/table-presentation-expected-android-external.txt +++ b/content/test/data/accessibility/html/table-presentation-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView text:"Table with role=presentation" focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] +WebView text:"Table with role=presentation" focusable focused actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"4" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"]
diff --git a/content/test/data/accessibility/html/table-simple-2-expected-android-external.txt b/content/test/data/accessibility/html/table-simple-2-expected-android-external.txt index 25d6253..88b384d9 100644 --- a/content/test/data/accessibility/html/table-simple-2-expected-android-external.txt +++ b/content/test/data/accessibility/html/table-simple-2-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView text:"Table example #2" focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] +WebView text:"Table example #2" focusable focused actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="layoutTable"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="layoutTableRow"] ++++++View text:"1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="layoutTableCell"]
diff --git a/content/test/data/accessibility/html/table-simple-expected-android-external.txt b/content/test/data/accessibility/html/table-simple-expected-android-external.txt index 49d25bb..b71d29d 100644 --- a/content/test/data/accessibility/html/table-simple-expected-android-external.txt +++ b/content/test/data/accessibility/html/table-simple-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView text:"Table example" focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] +WebView text:"Table example" focusable focused actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=3, cols=2] actions:[AX_FOCUS] bundle:[chromeRole="table", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Pair" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/html/table-spans-expected-android-external.txt b/content/test/data/accessibility/html/table-spans-expected-android-external.txt index dacbd977..aaebcf6 100644 --- a/content/test/data/accessibility/html/table-spans-expected-android-external.txt +++ b/content/test/data/accessibility/html/table-spans-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView text:"Table example with rowspan and colspan" focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] +WebView text:"Table example with rowspan and colspan" focusable focused actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=2, cols=2] actions:[AX_FOCUS] bundle:[chromeRole="table", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"AD" CollectionItemInfo:[rowSpan=2, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="cell"]
diff --git a/content/test/data/accessibility/html/table-th-colheader-expected-android-external.txt b/content/test/data/accessibility/html/table-th-colheader-expected-android-external.txt index 497b0d6..bfdb2d3 100644 --- a/content/test/data/accessibility/html/table-th-colheader-expected-android-external.txt +++ b/content/test/data/accessibility/html/table-th-colheader-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=2, cols=2] actions:[AX_FOCUS] bundle:[chromeRole="table", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Firstname" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/html/table-th-rowheader-expected-android-external.txt b/content/test/data/accessibility/html/table-th-rowheader-expected-android-external.txt index 95ff401..a796801e 100644 --- a/content/test/data/accessibility/html/table-th-rowheader-expected-android-external.txt +++ b/content/test/data/accessibility/html/table-th-rowheader-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView text:"Table example - th rowheader" focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] +WebView text:"Table example - th rowheader" focusable focused actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=2, cols=2] actions:[AX_FOCUS] bundle:[chromeRole="table", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Firstname" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rowHeader", roleDescription="row header"]
diff --git a/content/test/data/accessibility/html/table-thead-tbody-tfoot-expected-android-external.txt b/content/test/data/accessibility/html/table-thead-tbody-tfoot-expected-android-external.txt index 720a529f..eb24baa4 100644 --- a/content/test/data/accessibility/html/table-thead-tbody-tfoot-expected-android-external.txt +++ b/content/test/data/accessibility/html/table-thead-tbody-tfoot-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView text:"Table example - thead, tbody, tfoot" focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] +WebView text:"Table example - thead, tbody, tfoot" focusable focused actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++GridView CollectionInfo:[rows=4, cols=2] actions:[AX_FOCUS] bundle:[chromeRole="table", roleDescription="table"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Sum" CollectionItemInfo:[heading, rowIndex=0, colIndex=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="columnHeader", roleDescription="column header"]
diff --git a/content/test/data/accessibility/html/text-align-expected-android-external.txt b/content/test/data/accessibility/html/text-align-expected-android-external.txt index 732e34f..391d5d5e 100644 --- a/content/test/data/accessibility/html/text-align-expected-android-external.txt +++ b/content/test/data/accessibility/html/text-align-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Left-aligned text" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"Right-aligned text" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"Centered text" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"]
diff --git a/content/test/data/accessibility/html/text-indent-expected-android-external.txt b/content/test/data/accessibility/html/text-indent-expected-android-external.txt index aff17c8..e928dad 100644 --- a/content/test/data/accessibility/html/text-indent-expected-android-external.txt +++ b/content/test/data/accessibility/html/text-indent-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Text indent 50px" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"Text indent -50px" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"Text indent 0px" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"]
diff --git a/content/test/data/accessibility/html/textarea-expected-android-external.txt b/content/test/data/accessibility/html/textarea-expected-android-external.txt index 77ffa1c1..57cf28a3 100644 --- a/content/test/data/accessibility/html/textarea-expected-android-external.txt +++ b/content/test/data/accessibility/html/textarea-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText text:"The \ntextarea tag defines a multi-line text input control.\n" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/textarea-read-only-expected-android-external.txt b/content/test/data/accessibility/html/textarea-read-only-expected-android-external.txt index 0bf0b96..37ab641 100644 --- a/content/test/data/accessibility/html/textarea-read-only-expected-android-external.txt +++ b/content/test/data/accessibility/html/textarea-read-only-expected-android-external.txt
@@ -1,3 +1,3 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText text:"The textarea tag defines a multi-line text input control.\n" clickable editable disabled focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="textField", clickableScore="300"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/time-expected-android-external.txt b/content/test/data/accessibility/html/time-expected-android-external.txt index 3d58de3..9b09aaa7f 100644 --- a/content/test/data/accessibility/html/time-expected-android-external.txt +++ b/content/test/data/accessibility/html/time-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"10:00" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="time"] ++++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/html/ul-contenteditable-expected-android-external.txt b/content/test/data/accessibility/html/ul-contenteditable-expected-android-external.txt index 820da000..b3280e56 100644 --- a/content/test/data/accessibility/html/ul-contenteditable-expected-android-external.txt +++ b/content/test/data/accessibility/html/ul-contenteditable-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++EditText text:"• Hello\n• Bye" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/ul-expected-android-external.txt b/content/test/data/accessibility/html/ul-expected-android-external.txt index 2384d381..8fd0f0e4 100644 --- a/content/test/data/accessibility/html/ul-expected-android-external.txt +++ b/content/test/data/accessibility/html/ul-expected-android-external.txt
@@ -1,4 +1,4 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView CollectionInfo:[rows=3, cols=1] actions:[AX_FOCUS] bundle:[chromeRole="list"] ++++View CollectionItemInfo:[rowIndex=0, colIndex=0] actions:[AX_FOCUS] bundle:[chromeRole="listItem"] ++++++View text:"• " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listMarker"]
diff --git a/content/test/data/accessibility/html/var-expected-android-external.txt b/content/test/data/accessibility/html/var-expected-android-external.txt index eaff036e..69cc2d1 100644 --- a/content/test/data/accessibility/html/var-expected-android-external.txt +++ b/content/test/data/accessibility/html/var-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Variable" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/wbr-expected-android-external.txt b/content/test/data/accessibility/html/wbr-expected-android-external.txt index d4efeda..91e00b3 100644 --- a/content/test/data/accessibility/html/wbr-expected-android-external.txt +++ b/content/test/data/accessibility/html/wbr-expected-android-external.txt
@@ -1,2 +1,2 @@ -WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] +WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Supercalifragilisticexpialidocious" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/web_test/browser/web_test_content_browser_client.cc b/content/web_test/browser/web_test_content_browser_client.cc index 3b2947c..9ccceff 100644 --- a/content/web_test/browser/web_test_content_browser_client.cc +++ b/content/web_test/browser/web_test_content_browser_client.cc
@@ -618,6 +618,10 @@ sensor_provider_manager_->Bind(std::move(receiver)); } +void WebTestContentBrowserClient::ResetWebSensorProviderAutomation() { + sensor_provider_manager_.reset(); +} + std::unique_ptr<LoginDelegate> WebTestContentBrowserClient::CreateLoginDelegate( const net::AuthChallengeInfo& auth_info, content::WebContents* web_contents,
diff --git a/content/web_test/browser/web_test_content_browser_client.h b/content/web_test/browser/web_test_content_browser_client.h index 1b60d72c..d1f87a94 100644 --- a/content/web_test/browser/web_test_content_browser_client.h +++ b/content/web_test/browser/web_test_content_browser_client.h
@@ -57,6 +57,8 @@ std::unique_ptr<FakeBluetoothChooser> GetNextFakeBluetoothChooser(); void ResetFakeBluetoothDelegate(); + void ResetWebSensorProviderAutomation(); + // ContentBrowserClient overrides. void BrowserChildProcessHostCreated(BrowserChildProcessHost* host) override; void ExposeInterfacesToRenderer(
diff --git a/content/web_test/browser/web_test_control_host.cc b/content/web_test/browser/web_test_control_host.cc index 49c9aa5..fb758517 100644 --- a/content/web_test/browser/web_test_control_host.cc +++ b/content/web_test/browser/web_test_control_host.cc
@@ -706,6 +706,7 @@ WebTestContentBrowserClient::Get()->SetPopupBlockingEnabled(true); WebTestContentBrowserClient::Get()->ResetMockClipboardHosts(); WebTestContentBrowserClient::Get()->ResetFakeBluetoothDelegate(); + WebTestContentBrowserClient::Get()->ResetWebSensorProviderAutomation(); WebTestContentBrowserClient::Get() ->GetWebTestBrowserContext() ->GetWebTestPermissionManager()
diff --git a/docs/security/shepherd.md b/docs/security/shepherd.md index 25d77f4c..d0b16cd6 100644 --- a/docs/security/shepherd.md +++ b/docs/security/shepherd.md
@@ -251,7 +251,8 @@ We do not release severe security regressions, so we need to know the earliest impacted Chrome release branch. -First, if an issue [doesn’t impact Chrome users by default, add the hotlist +First, if an issue [doesn’t impact Chrome users by default (such as be being +behind a disabled feature or a command line flag), add the hotlist **`Security_Impact-None`**](security-labels.md#when-to-use-security_impact_none-toc_security_impact_none); otherwise, set a **Found In** milestone in the `Found In` field as follows:
diff --git a/docs/ui/learn/bestpractices/layout.md b/docs/ui/learn/bestpractices/layout.md index d07f64a..2a33408 100644 --- a/docs/ui/learn/bestpractices/layout.md +++ b/docs/ui/learn/bestpractices/layout.md
@@ -496,7 +496,7 @@ [Current code][4] uses [`FlexLayout`][] to achieve the desired result, resulting in clearer code. -[4]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/views/hover_button.cc;l=106;drc=888af74006ea1c4ee9907d18c8df2a7ca424eab9 +[4]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/views/controls/hover_button.cc;l=129;drc=0139ceffb2f8e1f64b7c30834e57d5793e529ed7 |||---||| @@ -597,12 +597,16 @@ std::unique_ptr<views::View> secondary_view, ...) { ... + // Set the layout manager to ignore the + // ink_drop_container to ensure the ink drop tracks + // the bounds of its parent. + ink_drop_container()->SetProperty( + views::kViewIgnoredByLayoutKey, true); + SetLayoutManager( std::make_unique<views::FlexLayout>()) ->SetCrossAxisAlignment( - views::LayoutAlignment::kCenter) - .SetChildViewIgnoredByLayout( - ink_drop_container(), true); + views::LayoutAlignment::kCenter); ... icon_view_ = AddChildView(std::make_unique<IconWrapper>(
diff --git a/docs/ui/views/metadata_properties.md b/docs/ui/views/metadata_properties.md index 4093668..ed9a5a6 100644 --- a/docs/ui/views/metadata_properties.md +++ b/docs/ui/views/metadata_properties.md
@@ -22,7 +22,7 @@ ``` class ASH_EXPORT MyViewClass : public views::View { public: - METADATA_HEADER(MyViewClass); + METADATA_HEADER(MyViewClass, views::View); // ... Public API goes here ... @@ -39,7 +39,7 @@ ``` class MyViewClass::MyNestedView : public views::View { public: - METADATA_HEADER(MyNestedView); + METADATA_HEADER(MyNestedView, views::View); // ... Public API goes here …
diff --git a/docs/website b/docs/website index 7854b9d..324a451 160000 --- a/docs/website +++ b/docs/website
@@ -1 +1 @@ -Subproject commit 7854b9d90b9fb1e57c50e6f039bc44fa587a9eca +Subproject commit 324a451ec11c32fdfc9e57facb78dba9e1be4cce
diff --git a/gpu/command_buffer/service/raster_decoder_unittest_base.cc b/gpu/command_buffer/service/raster_decoder_unittest_base.cc index de4ed2a..6723ae82 100644 --- a/gpu/command_buffer/service/raster_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/raster_decoder_unittest_base.cc
@@ -111,9 +111,6 @@ // in turn initialize FeatureInfo, which needs a context to determine // extension support. context_ = new StrictMock<GLContextMock>(); - // The stub ctx needs to be initialized so that the gl::GLContext can - // store the offscreen stub |surface|. - context_->Initialize(surface_.get(), {}); context_->SetExtensionsString(all_extensions.c_str()); context_->SetGLVersionString(init.gl_version.c_str());
diff --git a/gpu/command_buffer/service/shared_context_state.cc b/gpu/command_buffer/service/shared_context_state.cc index a03fd2f4..d8b78ad49 100644 --- a/gpu/command_buffer/service/shared_context_state.cc +++ b/gpu/command_buffer/service/shared_context_state.cc
@@ -220,6 +220,7 @@ share_group_(std::move(share_group)), context_(context), real_context_(std::move(context)), + surface_(std::move(surface)), sk_surface_cache_(MaxNumSkSurface()) { if (gr_context_type_ == GrContextType::kVulkan) { if (vk_context_provider_) { @@ -230,11 +231,6 @@ } } - DCHECK(context_ && surface && context_->default_surface()); - // |this| no longer stores the |surface| as that one must be stored by the - // context. Do a sanity check that it is true. - DCHECK(context_->default_surface() == surface); - if (base::SingleThreadTaskRunner::HasCurrentDefault()) { base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( this, "SharedContextState", @@ -278,7 +274,15 @@ // current, or the GrContext was already abandoned if the GLContext was lost. owned_gr_context_.reset(); + // |surface_| needs to be destroyed while there is a current GL context if + // using GL, as some implementations make calls to the GL bindings. Any such + // implementations will themselves ensure that the context is current in their + // destructor (we cannot blindly make the context current here, as there are + // other implementations that crash if the context is made current at this + // point :\). However, we drop our reference to |surface_| before releasing + // the context below so that the release has the intended effect. last_current_surface_ = nullptr; + surface_.reset(); if (context_->IsCurrent(nullptr)) context_->ReleaseCurrent(nullptr); @@ -563,7 +567,7 @@ auto virtual_context = base::MakeRefCounted<GLContextVirtual>( share_group_.get(), real_context_.get(), weak_ptr_factory_.GetWeakPtr()); - if (!virtual_context->Initialize(surface(), gl::GLContextAttribs())) { + if (!virtual_context->Initialize(surface_.get(), gl::GLContextAttribs())) { LOG(ERROR) << "SharedContextState::InitializeGL failure Initialize " "virtual context failed"; feature_info_ = nullptr; @@ -642,9 +646,8 @@ const bool using_gl = GrContextIsGL() || needs_gl; if (using_gl) { - gl::GLSurface* dont_care_surface = last_current_surface_ - ? last_current_surface_.get() - : context_->default_surface(); + gl::GLSurface* dont_care_surface = + last_current_surface_ ? last_current_surface_.get() : surface_.get(); surface = surface ? surface : dont_care_surface; if (!context_->MakeCurrent(surface)) { @@ -828,14 +831,8 @@ } } -gl::GLSurface* SharedContextState::surface() const { - return context_->default_surface(); -} - gl::GLDisplay* SharedContextState::display() { - auto* gl_surface = surface(); - DCHECK(gl_surface); - return gl_surface->GetGLDisplay(); + return surface_.get()->GetGLDisplay(); } bool SharedContextState::initialized() const {
diff --git a/gpu/command_buffer/service/shared_context_state.h b/gpu/command_buffer/service/shared_context_state.h index a885986..e57deab 100644 --- a/gpu/command_buffer/service/shared_context_state.h +++ b/gpu/command_buffer/service/shared_context_state.h
@@ -146,7 +146,7 @@ gl::GLShareGroup* share_group() const { return share_group_.get(); } gl::GLContext* context() const { return context_.get(); } gl::GLContext* real_context() const { return real_context_.get(); } - gl::GLSurface* surface() const; + gl::GLSurface* surface() const { return surface_.get(); } gl::GLDisplay* display(); // non const since it calls GLSurface::GetGLDisplay viz::VulkanContextProvider* vk_context_provider() const { return vk_context_provider_; @@ -378,6 +378,7 @@ scoped_refptr<gl::GLShareGroup> share_group_; scoped_refptr<gl::GLContext> context_; scoped_refptr<gl::GLContext> real_context_; + scoped_refptr<gl::GLSurface> surface_; // Most recent surface that this ShareContextState was made current with. // Avoids a call to MakeCurrent with a different surface, if we don't
diff --git a/gpu/command_buffer/service/shared_context_state_unittest.cc b/gpu/command_buffer/service/shared_context_state_unittest.cc index dd4bd29..e3782e34 100644 --- a/gpu/command_buffer/service/shared_context_state_unittest.cc +++ b/gpu/command_buffer/service/shared_context_state_unittest.cc
@@ -58,9 +58,6 @@ context->SetGLVersionString(gl_version); const char gl_extensions[] = "GL_KHR_robustness"; context->SetExtensionsString(gl_extensions); - // The stub ctx needs to be initialized so that the gl::GLContext can - // store the offscreen stub |surface|. - context->Initialize(surface.get(), {}); context->MakeCurrent(surface.get());
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl index f4ef9ab9..7d6c4a1 100644 --- a/infra/config/generated/testing/variants.pyl +++ b/infra/config/generated/testing/variants.pyl
@@ -23,7 +23,7 @@ 'identifier': 'BRYA_RELEASE_BETA', 'skylab': { 'cros_board': 'brya', - 'cros_img': 'brya-release/R121-15699.40.0', + 'cros_img': 'brya-release/R121-15699.54.0', 'dut_pool': 'chrome', }, }, @@ -31,7 +31,7 @@ 'identifier': 'BRYA_RELEASE_DEV', 'skylab': { 'cros_board': 'brya', - 'cros_img': 'brya-release/R122-15748.0.0', + 'cros_img': 'brya-release/R123-15770.0.0', 'dut_pool': 'chrome', }, }, @@ -47,7 +47,7 @@ 'identifier': 'BRYA_RELEASE_STABLE', 'skylab': { 'cros_board': 'brya', - 'cros_img': 'brya-release/R120-15662.76.0', + 'cros_img': 'brya-release/R121-15699.58.0', 'dut_pool': 'chrome', }, }, @@ -55,7 +55,7 @@ 'identifier': 'FIZZ_RELEASE_BETA', 'skylab': { 'cros_board': 'fizz', - 'cros_img': 'fizz-release/R121-15699.40.0', + 'cros_img': 'fizz-release/R122-15753.13.0', 'dut_pool': 'chrome', }, }, @@ -63,7 +63,7 @@ 'identifier': 'FIZZ_RELEASE_DEV', 'skylab': { 'cros_board': 'fizz', - 'cros_img': 'fizz-release/R122-15748.0.0', + 'cros_img': 'fizz-release/R123-15770.0.0', 'dut_pool': 'chrome', }, }, @@ -79,7 +79,7 @@ 'identifier': 'FIZZ_RELEASE_STABLE', 'skylab': { 'cros_board': 'fizz', - 'cros_img': 'fizz-release/R120-15662.76.0', + 'cros_img': 'fizz-release/R121-15699.58.0', 'dut_pool': 'chrome', }, }, @@ -87,7 +87,7 @@ 'identifier': 'GUYBRUSH_RELEASE_BETA', 'skylab': { 'cros_board': 'guybrush', - 'cros_img': 'guybrush-release/R121-15699.40.0', + 'cros_img': 'guybrush-release/R122-15753.13.0', 'dut_pool': 'chrome', }, }, @@ -95,7 +95,7 @@ 'identifier': 'GUYBRUSH_RELEASE_DEV', 'skylab': { 'cros_board': 'guybrush', - 'cros_img': 'guybrush-release/R122-15748.0.0', + 'cros_img': 'guybrush-release/R123-15770.0.0', 'dut_pool': 'chrome', }, }, @@ -111,7 +111,7 @@ 'identifier': 'GUYBRUSH_RELEASE_STABLE', 'skylab': { 'cros_board': 'guybrush', - 'cros_img': 'guybrush-release/R120-15662.76.0', + 'cros_img': 'guybrush-release/R121-15699.58.0', 'dut_pool': 'chrome', }, }, @@ -159,7 +159,7 @@ 'identifier': 'PUFF_RELEASE_BETA', 'skylab': { 'cros_board': 'puff', - 'cros_img': 'puff-release/R121-15699.40.0', + 'cros_img': 'puff-release/R122-15753.13.0', 'dut_pool': 'chrome', }, }, @@ -167,7 +167,7 @@ 'identifier': 'PUFF_RELEASE_DEV', 'skylab': { 'cros_board': 'puff', - 'cros_img': 'puff-release/R122-15748.0.0', + 'cros_img': 'puff-release/R123-15770.0.0', 'dut_pool': 'chrome', }, }, @@ -183,7 +183,7 @@ 'identifier': 'PUFF_RELEASE_STABLE', 'skylab': { 'cros_board': 'puff', - 'cros_img': 'puff-release/R120-15662.76.0', + 'cros_img': 'puff-release/R121-15699.58.0', 'dut_pool': 'chrome', }, }, @@ -307,16 +307,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 123.0.6288.0', + 'description': 'Run with ash-chrome version 123.0.6289.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6289.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v123.0.6288.0', - 'revision': 'version:123.0.6288.0', + 'location': 'lacros_version_skew_tests_v123.0.6289.0', + 'revision': 'version:123.0.6289.0', }, ], },
diff --git a/infra/config/targets/cros-skylab-variants.json b/infra/config/targets/cros-skylab-variants.json index a1f28e3..6da1f2e 100644 --- a/infra/config/targets/cros-skylab-variants.json +++ b/infra/config/targets/cros-skylab-variants.json
@@ -19,8 +19,8 @@ "CROS_BRYA_RELEASE_DEV": { "skylab": { "cros_board": "brya", - "cros_chrome_version": "122.0.6241.0", - "cros_img": "brya-release/R122-15748.0.0", + "cros_chrome_version": "123.0.6276.0", + "cros_img": "brya-release/R123-15770.0.0", "dut_pool": "chrome" }, "enabled": true, @@ -29,8 +29,8 @@ "CROS_BRYA_RELEASE_BETA": { "skylab": { "cros_board": "brya", - "cros_chrome_version": "121.0.6167.82", - "cros_img": "brya-release/R121-15699.40.0", + "cros_chrome_version": "121.0.6167.155", + "cros_img": "brya-release/R121-15699.54.0", "dut_pool": "chrome" }, "enabled": true, @@ -39,8 +39,8 @@ "CROS_BRYA_RELEASE_STABLE": { "skylab": { "cros_board": "brya", - "cros_chrome_version": "120.0.6099.235", - "cros_img": "brya-release/R120-15662.76.0", + "cros_chrome_version": "121.0.6167.159", + "cros_img": "brya-release/R121-15699.58.0", "dut_pool": "chrome" }, "enabled": true, @@ -58,8 +58,8 @@ "CROS_FIZZ_RELEASE_DEV": { "skylab": { "cros_board": "fizz", - "cros_chrome_version": "122.0.6241.0", - "cros_img": "fizz-release/R122-15748.0.0", + "cros_chrome_version": "123.0.6276.0", + "cros_img": "fizz-release/R123-15770.0.0", "dut_pool": "chrome" }, "enabled": true, @@ -68,8 +68,8 @@ "CROS_FIZZ_RELEASE_BETA": { "skylab": { "cros_board": "fizz", - "cros_chrome_version": "121.0.6167.82", - "cros_img": "fizz-release/R121-15699.40.0", + "cros_chrome_version": "122.0.6261.21", + "cros_img": "fizz-release/R122-15753.13.0", "dut_pool": "chrome" }, "enabled": true, @@ -78,8 +78,8 @@ "CROS_FIZZ_RELEASE_STABLE": { "skylab": { "cros_board": "fizz", - "cros_chrome_version": "120.0.6099.235", - "cros_img": "fizz-release/R120-15662.76.0", + "cros_chrome_version": "121.0.6167.159", + "cros_img": "fizz-release/R121-15699.58.0", "dut_pool": "chrome" }, "enabled": true, @@ -97,8 +97,8 @@ "CROS_GUYBRUSH_RELEASE_DEV": { "skylab": { "cros_board": "guybrush", - "cros_chrome_version": "122.0.6241.0", - "cros_img": "guybrush-release/R122-15748.0.0", + "cros_chrome_version": "123.0.6276.0", + "cros_img": "guybrush-release/R123-15770.0.0", "dut_pool": "chrome" }, "enabled": true, @@ -107,8 +107,8 @@ "CROS_GUYBRUSH_RELEASE_BETA": { "skylab": { "cros_board": "guybrush", - "cros_chrome_version": "121.0.6167.82", - "cros_img": "guybrush-release/R121-15699.40.0", + "cros_chrome_version": "122.0.6261.21", + "cros_img": "guybrush-release/R122-15753.13.0", "dut_pool": "chrome" }, "enabled": true, @@ -117,8 +117,8 @@ "CROS_GUYBRUSH_RELEASE_STABLE": { "skylab": { "cros_board": "guybrush", - "cros_chrome_version": "120.0.6099.235", - "cros_img": "guybrush-release/R120-15662.76.0", + "cros_chrome_version": "121.0.6167.159", + "cros_img": "guybrush-release/R121-15699.58.0", "dut_pool": "chrome" }, "enabled": true, @@ -136,8 +136,8 @@ "CROS_PUFF_RELEASE_DEV": { "skylab": { "cros_board": "puff", - "cros_chrome_version": "122.0.6241.0", - "cros_img": "puff-release/R122-15748.0.0", + "cros_chrome_version": "123.0.6276.0", + "cros_img": "puff-release/R123-15770.0.0", "dut_pool": "chrome" }, "enabled": true, @@ -146,8 +146,8 @@ "CROS_PUFF_RELEASE_BETA": { "skylab": { "cros_board": "puff", - "cros_chrome_version": "121.0.6167.82", - "cros_img": "puff-release/R121-15699.40.0", + "cros_chrome_version": "122.0.6261.21", + "cros_img": "puff-release/R122-15753.13.0", "dut_pool": "chrome" }, "enabled": true, @@ -156,8 +156,8 @@ "CROS_PUFF_RELEASE_STABLE": { "skylab": { "cros_board": "puff", - "cros_chrome_version": "120.0.6099.235", - "cros_img": "puff-release/R120-15662.76.0", + "cros_chrome_version": "121.0.6167.159", + "cros_img": "puff-release/R121-15699.58.0", "dut_pool": "chrome" }, "enabled": true,
diff --git a/infra/config/targets/lacros-version-skew-variants.json b/infra/config/targets/lacros-version-skew-variants.json index 9dcd8d4..69921bf9 100644 --- a/infra/config/targets/lacros-version-skew-variants.json +++ b/infra/config/targets/lacros-version-skew-variants.json
@@ -1,16 +1,16 @@ { "LACROS_VERSION_SKEW_CANARY": { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6289.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6288.0", + "description": "Run with ash-chrome version 123.0.6289.0", "identifier": "Lacros version skew testing ash canary", "swarming": { "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6288.0", - "revision": "version:123.0.6288.0" + "location": "lacros_version_skew_tests_v123.0.6289.0", + "revision": "version:123.0.6289.0" } ] }
diff --git a/internal b/internal index 8ca742c..40aab3e 160000 --- a/internal +++ b/internal
@@ -1 +1 @@ -Subproject commit 8ca742cefe79b6c919d7f9a13a41e050a5ef62d1 +Subproject commit 40aab3e1c4517d57070812a86d5538d5809895a4
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn index 728a111d..0f2ca2a 100644 --- a/ios/chrome/app/BUILD.gn +++ b/ios/chrome/app/BUILD.gn
@@ -63,6 +63,7 @@ sources = [ "app_metrics_app_state_agent_unittest.mm", "deferred_initialization_runner_unittest.mm", + "main_controller_unittest.mm", "post_restore_app_agent_unittest.mm", "safe_mode_app_state_agent_unittest.mm", "tab_opener_unittest.mm", @@ -77,7 +78,10 @@ ":variations_app_state_agent", "//base", "//base/test:test_support", + "//components/bookmarks/test", "//components/metrics", + "//components/open_from_clipboard", + "//components/open_from_clipboard:test_support", "//components/prefs", "//components/prefs:test_support", "//components/sync_preferences:sync_preferences", @@ -90,10 +94,15 @@ "//ios/chrome/app/application_delegate:tab_opening", "//ios/chrome/app/application_delegate:test_support", "//ios/chrome/app/application_delegate:url_opener_params", + "//ios/chrome/browser/bookmarks/model", "//ios/chrome/browser/metrics/model", "//ios/chrome/browser/promos_manager/model", "//ios/chrome/browser/promos_manager/model:constants", "//ios/chrome/browser/promos_manager/model:test_support", + "//ios/chrome/browser/reading_list/model", + "//ios/chrome/browser/reading_list/model:test_support", + "//ios/chrome/browser/sessions", + "//ios/chrome/browser/sessions:fake", "//ios/chrome/browser/shared/coordinator/scene", "//ios/chrome/browser/shared/coordinator/scene:scene_state_header", "//ios/chrome/browser/shared/coordinator/scene:scene_testing", @@ -113,6 +122,7 @@ "//ios/chrome/browser/ui/main", "//ios/chrome/browser/ui/safe_mode", "//ios/chrome/browser/variations/model:fetcher", + "//ios/chrome/browser/web_state_list/model/web_usage_enabler", "//ios/chrome/common/app_group", "//ios/chrome/test:test_support", "//ios/public/provider/chrome/browser/app_distribution:app_distribution_api", @@ -145,6 +155,7 @@ deps = [ ":tests_hook", "//components/signin/internal/identity_manager", + "//ios/public/provider/chrome/browser/primes:primes_api", ] } @@ -219,6 +230,7 @@ ] deps = [ "//base", + "//ios/chrome/app:tests_hook", "//ios/chrome/app/application_delegate:application_delegate_internal", "//ios/chrome/app/application_delegate:observing_app_state_agent", "//ios/chrome/browser/metrics/model",
diff --git a/ios/chrome/app/DEPS b/ios/chrome/app/DEPS index cab2adb..2799b50 100644 --- a/ios/chrome/app/DEPS +++ b/ios/chrome/app/DEPS
@@ -58,5 +58,6 @@ ".*test\.mm": [ "+components/previous_session_info/previous_session_info_private.h", "+components/sync_preferences", + "+components/open_from_clipboard", ], }
diff --git a/ios/chrome/app/app_metrics_app_state_agent.mm b/ios/chrome/app/app_metrics_app_state_agent.mm index 5494e20..5db060b 100644 --- a/ios/chrome/app/app_metrics_app_state_agent.mm +++ b/ios/chrome/app/app_metrics_app_state_agent.mm
@@ -9,6 +9,7 @@ #import "ios/chrome/app/application_delegate/app_state.h" #import "ios/chrome/app/application_delegate/metrics_mediator.h" #import "ios/chrome/app/application_delegate/startup_information.h" +#import "ios/chrome/app/tests_hook.h" #import "ios/chrome/browser/metrics/model/ios_profile_session_durations_service.h" #import "ios/chrome/browser/metrics/model/ios_profile_session_durations_service_factory.h" #import "ios/chrome/browser/shared/coordinator/scene/scene_controller.h" @@ -102,6 +103,7 @@ [MetricsMediator logStartupDuration:self.appState.startupInformation]; if (ios::provider::IsPrimesSupported()) { ios::provider::PrimesAppReady(); + tests_hook::SignalAppLaunched(); } } }
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index b1cf68f7..8f2ee66b 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -1459,12 +1459,16 @@ if (willShowActivityIndicator) { // User interaction still needs to be disabled as a way to // force reload all the web states and to reset NTPs. - WebUsageEnablerBrowserAgent::FromBrowser( - browserProviderInterface.mainBrowserProvider.browser) - ->SetWebUsageEnabled(false); - WebUsageEnablerBrowserAgent::FromBrowser( - browserProviderInterface.incognitoBrowserProvider.browser) - ->SetWebUsageEnabled(false); + if (Browser* mainBrowser = + browserProviderInterface.mainBrowserProvider.browser) { + WebUsageEnablerBrowserAgent::FromBrowser(mainBrowser) + ->SetWebUsageEnabled(false); + } + if (Browser* incognitoBrowser = + browserProviderInterface.incognitoBrowserProvider.browser) { + WebUsageEnablerBrowserAgent::FromBrowser(incognitoBrowser) + ->SetWebUsageEnabled(false); + } if (didShowActivityIndicator && browserProviderInterface.mainBrowserProvider.browser) { @@ -1475,14 +1479,14 @@ [handler hideActivityOverlay]; } } - if (browserProviderInterface.mainBrowserProvider.browser) { - WebUsageEnablerBrowserAgent::FromBrowser( - browserProviderInterface.mainBrowserProvider.browser) + if (Browser* mainBrowser = + browserProviderInterface.mainBrowserProvider.browser) { + WebUsageEnablerBrowserAgent::FromBrowser(mainBrowser) ->SetWebUsageEnabled(true); } - if (browserProviderInterface.incognitoBrowserProvider.browser) { - WebUsageEnablerBrowserAgent::FromBrowser( - browserProviderInterface.incognitoBrowserProvider.browser) + if (Browser* incognitoBrowser = + browserProviderInterface.incognitoBrowserProvider.browser) { + WebUsageEnablerBrowserAgent::FromBrowser(incognitoBrowser) ->SetWebUsageEnabled(true); } [browserProviderInterface.currentBrowserProvider setPrimary:YES];
diff --git a/ios/chrome/app/main_controller_unittest.mm b/ios/chrome/app/main_controller_unittest.mm new file mode 100644 index 0000000..843d3e41 --- /dev/null +++ b/ios/chrome/app/main_controller_unittest.mm
@@ -0,0 +1,83 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/app/main_controller.h" + +#import "base/test/ios/wait_util.h" +#import "components/bookmarks/test/bookmark_test_helpers.h" +#import "components/open_from_clipboard/clipboard_recent_content.h" +#import "components/open_from_clipboard/fake_clipboard_recent_content.h" +#import "ios/chrome/app/application_delegate/app_state.h" +#import "ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h" +#import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" +#import "ios/chrome/browser/reading_list/model/reading_list_model_factory.h" +#import "ios/chrome/browser/reading_list/model/reading_list_test_utils.h" +#import "ios/chrome/browser/sessions/fake_tab_restore_service.h" +#import "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" +#import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h" +#import "ios/chrome/browser/web_state_list/model/web_usage_enabler/web_usage_enabler_browser_agent.h" +#import "ios/web/public/test/web_task_environment.h" +#import "testing/gmock/include/gmock/gmock.h" +#import "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" +#import "third_party/ocmock/gtest_support.h" + +// Tests MainController. +class MainControllerTest : public PlatformTest { + protected: + MainControllerTest() { + ClipboardRecentContent::SetInstance( + std::make_unique<FakeClipboardRecentContent>()); + + TestChromeBrowserState::Builder builder; + builder.AddTestingFactory(IOSChromeTabRestoreServiceFactory::GetInstance(), + FakeTabRestoreService::GetTestingFactory()); + builder.AddTestingFactory( + ios::LocalOrSyncableBookmarkModelFactory::GetInstance(), + ios::LocalOrSyncableBookmarkModelFactory::GetDefaultFactory()); + builder.AddTestingFactory( + ReadingListModelFactory::GetInstance(), + base::BindRepeating(&BuildReadingListModelWithFakeStorage, + std::vector<scoped_refptr<ReadingListEntry>>())); + + browser_state_ = builder.Build(); + + bookmarks::BookmarkModel* bookmarks_model = + ios::LocalOrSyncableBookmarkModelFactory::GetForBrowserState( + browser_state_.get()); + bookmarks::test::WaitForBookmarkModelToLoad(bookmarks_model); + bookmarks::BookmarkModel* account_bookmark_model = + ios::AccountBookmarkModelFactory::GetForBrowserState( + browser_state_.get()); + bookmarks::test::WaitForBookmarkModelToLoad(account_bookmark_model); + + app_state_ = [[AppState alloc] initWithStartupInformation:nil]; + } + + MainController* CreateMainController() { + MainController* main_controller = [[MainController alloc] init]; + main_controller.appState = app_state_; + return main_controller; + } + + web::WebTaskEnvironment task_environment_; + AppState* app_state_; + std::unique_ptr<TestChromeBrowserState> browser_state_; +}; + +// Tests removing the browsing data with no interface provider. There is no +// clear repro steps for this issue but it is happening in the wild. Prevent +// regression on crbug.com/1522188. +TEST_F(MainControllerTest, RemoveBrowsingDataNoInterfaceProvider) { + MainController* main_controller = CreateMainController(); + + base::RunLoop run_loop; + [main_controller + removeBrowsingDataForBrowserState:browser_state_.get() + timePeriod:browsing_data::TimePeriod::ALL_TIME + removeMask:BrowsingDataRemoveMask::REMOVE_ALL + completionBlock:base::CallbackToBlock( + run_loop.QuitClosure())]; + run_loop.Run(); +}
diff --git a/ios/chrome/app/perf_tests_hook.mm b/ios/chrome/app/perf_tests_hook.mm index 8a34eee..e0514d9 100644 --- a/ios/chrome/app/perf_tests_hook.mm +++ b/ios/chrome/app/perf_tests_hook.mm
@@ -5,9 +5,12 @@ #import "ios/chrome/app/tests_hook.h" #import <Foundation/Foundation.h> +#import <os/log.h> +#import <os/signpost.h> #import "base/time/time.h" #import "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h" +#import "ios/public/provider/chrome/browser/primes/primes_api.h" namespace tests_hook { @@ -80,6 +83,25 @@ void SetUpTestsIfPresent() {} void RunTestsIfPresent() {} +void SignalAppLaunched() { + // The app launched signal is only used by startup tests, which unlike EG + // tests do not have a tear down method which stops logging, so stop logging + // here to flush logs + ios::provider::PrimesStopLogging(); + + os_log_t hke_os_log = os_log_create("com.google.hawkeye.ios", + OS_LOG_CATEGORY_POINTS_OF_INTEREST); + os_signpost_id_t os_signpost = os_signpost_id_generate(hke_os_log); + os_signpost_event_emit(hke_os_log, os_signpost, "APP_LAUNCHED"); + // For startup tests instrumented with xctrace we need to log the signal using + // os_log + os_log(hke_os_log, "APP_LAUNCHED"); + + // For regular startup tests we rely on printf to signal that the app has + // started and can be terminated + printf("APP_LAUNCHED\n"); +} + base::TimeDelta PasswordCheckMinimumDuration() { // No artificial delays for perf tests. return base::Seconds(0);
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index be89e22..9f8cbbe4 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -4832,9 +4832,15 @@ <message name="IDS_IOS_SWIPE_LEFT_TO_INCOGNITO_IPH" desc="The text for the full screen in-product help for swipe right to see incognito tabs on regular tabs grid for RTL devices."> You can swipe left to browse in Incognito. </message> + <message name="IDS_IOS_SWIPE_LEFT_TO_INCOGNITO_IPH_VOICEOVER" desc="The voice over announcement for the full screen in-product help for swipe right to see incognito tabs on regular tabs grid for RTL devices."> + You can scroll right to browse in Incognito. + </message> <message name="IDS_IOS_SWIPE_RIGHT_TO_INCOGNITO_IPH" desc="The text for the full screen in-product help for swipe right to see incognito tabs on regular tabs grid."> You can swipe right to browse in Incognito. </message> + <message name="IDS_IOS_SWIPE_RIGHT_TO_INCOGNITO_IPH_VOICEOVER" desc="The voice over announcement for the full screen in-product help for swipe right to see incognito tabs on regular tabs grid."> + You can scroll left to browse in Incognito. + </message> <message name="IDS_IOS_SYNC_ADDRESSES_DIALOG_CONTINUE" desc="Action of a dialog to enable saving addresses to the Google Account. If the user chose to continue, addresses will start syncing."> Continue </message> @@ -4946,6 +4952,9 @@ <message name="IDS_IOS_TABS_SEARCH_OPEN_TABS_SECTION_HEADER_TITLE" desc="Section header for the section that contains all the open tabs from the search results."> Open Tabs </message> + <message name="IDS_IOS_TABS_SEARCH_TAB_GROUPS_SECTION_HEADER_TITLE" desc="Section header for the section that contains all the tab groups from the search results."> + Tab Groups + </message> <message name="IDS_IOS_TABS_SEARCH_SUGGESTED_ACTIONS" desc="Section header for the suggested actions section shown in the tab grid at the bottom of search results."> Suggested </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_SWIPE_LEFT_TO_INCOGNITO_IPH_VOICEOVER.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_SWIPE_LEFT_TO_INCOGNITO_IPH_VOICEOVER.png.sha1 new file mode 100644 index 0000000..843e343 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_SWIPE_LEFT_TO_INCOGNITO_IPH_VOICEOVER.png.sha1
@@ -0,0 +1 @@ +a51bc2b77d9afa3853b78fe1419870e013340621 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_SWIPE_RIGHT_TO_INCOGNITO_IPH_VOICEOVER.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_SWIPE_RIGHT_TO_INCOGNITO_IPH_VOICEOVER.png.sha1 new file mode 100644 index 0000000..1f83ee3 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_SWIPE_RIGHT_TO_INCOGNITO_IPH_VOICEOVER.png.sha1
@@ -0,0 +1 @@ +d06edd6fbb11385775657ed0ce880cfedd2d277c \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_TABS_SEARCH_TAB_GROUPS_SECTION_HEADER_TITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_TABS_SEARCH_TAB_GROUPS_SECTION_HEADER_TITLE.png.sha1 new file mode 100644 index 0000000..63093f4 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_TABS_SEARCH_TAB_GROUPS_SECTION_HEADER_TITLE.png.sha1
@@ -0,0 +1 @@ +acb556beb5a7b03a59e5e9c34ef3008bdc802df5 \ No newline at end of file
diff --git a/ios/chrome/app/tests_fake_hook.mm b/ios/chrome/app/tests_fake_hook.mm index 0402f62..cebec66b 100644 --- a/ios/chrome/app/tests_fake_hook.mm +++ b/ios/chrome/app/tests_fake_hook.mm
@@ -66,6 +66,7 @@ } void SetUpTestsIfPresent() {} void RunTestsIfPresent() {} +void SignalAppLaunched() {} base::TimeDelta PasswordCheckMinimumDuration() { return base::Seconds(3);
diff --git a/ios/chrome/app/tests_hook.h b/ios/chrome/app/tests_hook.h index 17afa245..678761e 100644 --- a/ios/chrome/app/tests_hook.h +++ b/ios/chrome/app/tests_hook.h
@@ -115,6 +115,10 @@ // tests. void RunTestsIfPresent(); +// Signal that the app has successfully launched. Only used by performance +// tests. +void SignalAppLaunched(); + // Minimum duration of password checks. The password check UI displays checks as // in progress for at least this duration in order to avoid updating the UI too // fast and making it flicker. Test targets do not have an artificial minimum
diff --git a/ios/chrome/browser/application_context/model/application_context_impl.h b/ios/chrome/browser/application_context/model/application_context_impl.h index d0f2429..87965e9 100644 --- a/ios/chrome/browser/application_context/model/application_context_impl.h +++ b/ios/chrome/browser/application_context/model/application_context_impl.h
@@ -86,6 +86,16 @@ PushNotificationService* GetPushNotificationService() override; private: + // Represents the possible application states the app can be in. + enum class AppState { + kForeground, + kBackground, + }; + + // Helper method to implement the work required when transitioning between + // application states. + void OnAppEnterState(AppState app_state); + // Sets the locale used by the application. void SetApplicationLocale(const std::string& locale);
diff --git a/ios/chrome/browser/application_context/model/application_context_impl.mm b/ios/chrome/browser/application_context/model/application_context_impl.mm index 182bee9..4f7430a 100644 --- a/ios/chrome/browser/application_context/model/application_context_impl.mm +++ b/ios/chrome/browser/application_context/model/application_context_impl.mm
@@ -249,57 +249,14 @@ DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!tearing_down_); - // Tell the metrics services that the application resumes. - PrefService* local_state = GetLocalState(); - metrics::MetricsService* metrics_service = GetMetricsService(); - if (metrics_service && local_state) { - metrics_service->OnAppEnterForeground(); - local_state->CommitPendingWrite(); - } - - variations::VariationsService* variations_service = GetVariationsService(); - if (variations_service) { - variations_service->OnAppEnterForeground(); - } - ukm::UkmService* ukm_service = GetMetricsServicesManager()->GetUkmService(); - if (ukm_service) { - ukm_service->OnAppEnterForeground(); - } + OnAppEnterState(AppState::kForeground); } void ApplicationContextImpl::OnAppEnterBackground() { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!tearing_down_); - // Mark all the ChromeBrowserStates as clean and persist history. - std::vector<ChromeBrowserState*> loaded_browser_state = - GetChromeBrowserStateManager()->GetLoadedBrowserStates(); - for (ChromeBrowserState* browser_state : loaded_browser_state) { - if (history::HistoryService* history_service = - ios::HistoryServiceFactory::GetForBrowserStateIfExists( - browser_state, ServiceAccessType::EXPLICIT_ACCESS)) { - history_service->HandleBackgrounding(); - } - - PrefService* browser_state_prefs = browser_state->GetPrefs(); - if (browser_state_prefs) { - browser_state_prefs->CommitPendingWrite(); - } - } - - // Tell the metrics services they were cleanly shutdown. - metrics::MetricsService* metrics_service = GetMetricsService(); - if (metrics_service) { - metrics_service->OnAppEnterBackground( - /*keep_recording_in_background=*/true); - } - ukm::UkmService* ukm_service = GetMetricsServicesManager()->GetUkmService(); - if (ukm_service) { - ukm_service->OnAppEnterBackground(); - } - - // Persisting to disk is protected by a critical task, so no other special - // handling is necessary on iOS. + OnAppEnterState(AppState::kBackground); } bool ApplicationContextImpl::WasLastShutdownClean() { @@ -557,6 +514,90 @@ return push_notification_service_.get(); } +void ApplicationContextImpl::OnAppEnterState(AppState app_state) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(!tearing_down_); + + // Tell the metrics services that the application state changes (taking + // care not to create the services if they have not been created yet). + if (metrics_services_manager_) { + if (metrics::MetricsService* metrics_service = + metrics_services_manager_->GetMetricsService()) { + switch (app_state) { + case AppState::kForeground: + metrics_service->OnAppEnterForeground(); + break; + + case AppState::kBackground: + metrics_service->OnAppEnterBackground(); + break; + } + } + + if (variations::VariationsService* variations_service = + metrics_services_manager_->GetVariationsService()) { + switch (app_state) { + case AppState::kForeground: + variations_service->OnAppEnterForeground(); + break; + + case AppState::kBackground: + // Nothing to do for VariationsService when entering background. + break; + } + } + + if (ukm::UkmService* ukm_service = + metrics_services_manager_->GetUkmService()) { + switch (app_state) { + case AppState::kForeground: + ukm_service->OnAppEnterForeground(); + break; + + case AppState::kBackground: + ukm_service->OnAppEnterBackground(); + break; + } + } + } + + // Request saving the local state prefs and all loaded ChromeBrowserStates' + // prefs (taking care not to create the objects if they have not been created + // yet). + if (chrome_browser_state_manager_) { + std::vector<ChromeBrowserState*> loaded_browser_states = + chrome_browser_state_manager_->GetLoadedBrowserStates(); + + for (ChromeBrowserState* browser_state : loaded_browser_states) { + switch (app_state) { + case AppState::kForeground: + // Nothing extra to do when entering foreground. + break; + + case AppState::kBackground: + if (history::HistoryService* history_service = + ios::HistoryServiceFactory::GetForBrowserStateIfExists( + browser_state, ServiceAccessType::EXPLICIT_ACCESS)) { + history_service->HandleBackgrounding(); + } + break; + } + + // No need to check that `GetPrefs()` returns non-null value since the + // ChromeBrowserState owns its PrefService and thus the method cannot + // return null. + browser_state->GetPrefs()->CommitPendingWrite(); + } + } + + if (local_state_) { + local_state_->CommitPendingWrite(); + } + + // Persisting to disk is protected by a critical task, so no other special + // handling is necessary on iOS. +} + void ApplicationContextImpl::SetApplicationLocale(const std::string& locale) { DCHECK(thread_checker_.CalledOnValidThread()); application_locale_ = locale;
diff --git a/ios/chrome/browser/default_browser/OWNERS b/ios/chrome/browser/default_browser/OWNERS new file mode 100644 index 0000000..625bcfe8 --- /dev/null +++ b/ios/chrome/browser/default_browser/OWNERS
@@ -0,0 +1,3 @@ +gayane@google.com +gujen@google.com +sebsg@chromium.org
diff --git a/ios/chrome/browser/default_browser/model/promo_source.h b/ios/chrome/browser/default_browser/model/promo_source.h index 18557228..5943a33 100644 --- a/ios/chrome/browser/default_browser/model/promo_source.h +++ b/ios/chrome/browser/default_browser/model/promo_source.h
@@ -10,14 +10,15 @@ // LINT.IfChange enum class DefaultBrowserPromoSource { kSettings = 0, - kOmnibox, - kExternalIntent, - kSetUpList, + kOmnibox = 1, + kExternalIntent = 2, + kSetUpList = 3, // kExternalAction refers to Chrome being opened with a "ChromeExternalAction" // host. - kExternalAction, - kMaxValue = kExternalAction, + kExternalAction = 4, + kTipsNotification = 5, + kMaxValue = kTipsNotification, }; -// LINT.ThenChange(//tools/metrics/histograms/metadata/ios/enums.xml) +// LINT.ThenChange(tools/metrics/histograms/metadata/settings/enums.xml) #endif // IOS_CHROME_BROWSER_DEFAULT_BROWSER_MODEL_PROMO_SOURCE_H_
diff --git a/ios/chrome/browser/default_browser/model/utils.mm b/ios/chrome/browser/default_browser/model/utils.mm index f2a52cb4..b215189 100644 --- a/ios/chrome/browser/default_browser/model/utils.mm +++ b/ios/chrome/browser/default_browser/model/utils.mm
@@ -463,8 +463,15 @@ } std::string GetVideoPromoVariant() { - return base::GetFieldTrialParamValueByFeature( - kDefaultBrowserVideoPromo, "default_browser_video_promo_variant"); + if (!IsDefaultBrowserVideoPromoEnabled()) { + return ""; + } + std::string variant = base::GetFieldTrialParamValueByFeature( + kDefaultBrowserVideoPromo, kDefaultBrowserVideoPromoVariant); + if (variant != "") { + return variant; + } + return kVideoFullscreenPromo; } } // namespace
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index ef92881..32ff3b1 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -1588,6 +1588,10 @@ {"tab-grid-always-bounce", flag_descriptions::kTabGridAlwaysBounceName, flag_descriptions::kTabGridAlwaysBounceDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kTabGridAlwaysBounce)}, + {"omnibox-rich-autocompletion", + flag_descriptions::kOmniboxRichAutocompletionName, + flag_descriptions::kOmniboxRichAutocompletionDescription, flags_ui::kOsIos, + FEATURE_VALUE_TYPE(omnibox::kRichAutocompletion)}, {"disable-lens-camera", flag_descriptions::kDisableLensCameraName, flag_descriptions::kDisableLensCameraDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kDisableLensCamera)},
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index dbcaa04..91fd1114 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -724,6 +724,12 @@ const char kOmniboxPopupRowContentConfigurationDescription[] = "Enables the use of content configuration for the omnibox popup row."; +const char kOmniboxRichAutocompletionName[] = + "Omnibox rich inline autocompletion"; +const char kOmniboxRichAutocompletionDescription[] = + "Enables omnibox rich inline autocompletion. Expands inline autocomplete " + "to any type of input that users repeatedly use to get to specific URLs."; + extern const char kOmniboxSuggestionsRTLImprovementsName[] = "Omnibox Improved RTL Suggestion Layout"; extern const char kOmniboxSuggestionsRTLImprovementsDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index e58c7dc..d525790 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -642,6 +642,10 @@ extern const char kOmniboxPopupRowContentConfigurationName[]; extern const char kOmniboxPopupRowContentConfigurationDescription[]; +// Title and description for omnibox rich inline autocompletion. +extern const char kOmniboxRichAutocompletionName[]; +extern const char kOmniboxRichAutocompletionDescription[]; + // Title and description for improved RTL layout of suggestions. extern const char kOmniboxSuggestionsRTLImprovementsName[]; extern const char kOmniboxSuggestionsRTLImprovementsDescription[];
diff --git a/ios/chrome/browser/intents/user_activity_browser_agent.h b/ios/chrome/browser/intents/user_activity_browser_agent.h index 3fec3dd5..75aed841 100644 --- a/ios/chrome/browser/intents/user_activity_browser_agent.h +++ b/ios/chrome/browser/intents/user_activity_browser_agent.h
@@ -86,6 +86,9 @@ void OverloadContinueUserActivityURL(BOOL open_existing_tab, NSURL* webpage_url); + // Clears startup parameters. + void ClearStartupParameters(); + SEQUENCE_CHECKER(sequence_checker_); // The browser associated with this agent.
diff --git a/ios/chrome/browser/intents/user_activity_browser_agent.mm b/ios/chrome/browser/intents/user_activity_browser_agent.mm index 632f2e2..def0100 100644 --- a/ios/chrome/browser/intents/user_activity_browser_agent.mm +++ b/ios/chrome/browser/intents/user_activity_browser_agent.mm
@@ -567,6 +567,9 @@ // Record metric. } + base::OnceClosure closure = + base::BindOnce(&UserActivityBrowserAgent::ClearStartupParameters, + weak_ptr_factory_.GetWeakPtr()); [tab_opener_ dismissModalsAndMaybeOpenSelectedTabInMode:target_mode withUrlLoadParams:params @@ -574,10 +577,8 @@ startupParameters] postOpeningAction] != FOCUS_OMNIBOX - completion:^{ - [connection_information_ - setStartupParameters:nil]; - }]; + completion:base::CallbackToBlock( + std::move(closure))]; } BOOL UserActivityBrowserAgent::ProceedWithUserActivity( @@ -757,14 +758,16 @@ [tab_opener_ URLIsOpenedInRegularMode:webpage_GURL]) { // Record metric. } + + base::OnceClosure closure = + base::BindOnce(&UserActivityBrowserAgent::ClearStartupParameters, + weak_ptr_factory_.GetWeakPtr()); [tab_opener_ dismissModalsAndMaybeOpenSelectedTabInMode:target_mode withUrlLoadParams:params dismissOmnibox:YES - completion:^{ - [connection_information_ - setStartupParameters:nil]; - }]; + completion:base::CallbackToBlock( + std::move(closure))]; return YES; } @@ -791,25 +794,23 @@ BOOL dismiss_omnibox = [[connection_information_ startupParameters] postOpeningAction] != FOCUS_OMNIBOX; - // Using a weak reference to `connection_information_` to solve a memory leak - // issue. `tab_opener_` and `connection_information_` are the same object in + // Using a weak reference to `this` to solve a memory leak issue. + // `tab_opener_` and `connection_information_` are the same object in // some cases (SceneController). This retains the object while the block // exists. Then this block is passed around and in some cases it ends up // stored in BrowserViewController. This results in a memory leak that looks // like this: SceneController -> BrowserViewWrangler -> BrowserCoordinator // -> BrowserViewController -> SceneController - __weak id<ConnectionInformation> weak_connection_info = - connection_information_; - + base::OnceClosure closure = + base::BindOnce(&UserActivityBrowserAgent::ClearStartupParameters, + weak_ptr_factory_.GetWeakPtr()); [tab_opener_ - dismissModalsAndOpenMultipleTabsWithURLs:weak_connection_info + dismissModalsAndOpenMultipleTabsWithURLs:connection_information_ .startupParameters.URLs inIncognitoMode:incognito_mode dismissOmnibox:dismiss_omnibox - completion:^{ - weak_connection_info.startupParameters = - nil; - }]; + completion:base::CallbackToBlock( + std::move(closure))]; } GURL UserActivityBrowserAgent::GenerateResultGURLFromSearchQuery( @@ -841,3 +842,7 @@ UIApplicationStateActive; ContinueUserActivityURL(webpage_url, is_active, open_existing_tab); } + +void UserActivityBrowserAgent::ClearStartupParameters() { + connection_information_.startupParameters = nil; +}
diff --git a/ios/chrome/browser/main/model/browser_util.h b/ios/chrome/browser/main/model/browser_util.h index b263a4fc..1ec68187 100644 --- a/ios/chrome/browser/main/model/browser_util.h +++ b/ios/chrome/browser/main/model/browser_util.h
@@ -24,13 +24,11 @@ }; // Move the web state from `source_browser` at `source_tab_index` to -// `destination_browser` web state list at `destination_tab_index` with the -// given flag. +// `destination_browser` web state list given the insertion `params`. void MoveTabFromBrowserToBrowser(Browser* source_browser, int source_tab_index, Browser* destination_browser, - int destination_tab_index, - WebStateList::InsertionFlags flags); + WebStateList::InsertionParams params); // Move the web state from `source_browser` at `source_tab_index` to // `destination_browser` web state list at `destination_tab_index`. @@ -40,12 +38,11 @@ int destination_tab_index); // Moves the tab to the `destination_tab_index` in `destination_browser` with -// the given flag. It is an error to try to move a tab across profiles +// `params`. It is an error to try to move a tab across profiles // (incognito <-> regular). void MoveTabToBrowser(web::WebStateID tab_id, Browser* destination_browser, - int destination_tab_index, - WebStateList::InsertionFlags flags); + WebStateList::InsertionParams params); // Moves the tab to the `destination_tab_index` in `destination_browser`. It is // an error to try to move a tab across profiles (incognito <-> regular).
diff --git a/ios/chrome/browser/main/model/browser_util.mm b/ios/chrome/browser/main/model/browser_util.mm index 0ca3343..84a0bc8 100644 --- a/ios/chrome/browser/main/model/browser_util.mm +++ b/ios/chrome/browser/main/model/browser_util.mm
@@ -40,12 +40,11 @@ void MoveTabFromBrowserToBrowser(Browser* source_browser, int source_tab_index, Browser* destination_browser, - int destination_tab_index, - WebStateList::InsertionFlags flags) { + WebStateList::InsertionParams params) { if (source_browser == destination_browser) { // This is a reorder operation within the same WebStateList. destination_browser->GetWebStateList()->MoveWebStateAt( - source_tab_index, destination_tab_index); + source_tab_index, params.desired_index); return; } std::unique_ptr<web::WebState> web_state = @@ -55,19 +54,12 @@ MoveSnapshot(snapshot_tab_helper->GetSnapshotID(), source_browser, destination_browser); - WebStateList::InsertionFlags insertion_flags = flags; - if (insertion_flags == WebStateList::InsertionFlags::INSERT_NO_FLAGS) { - insertion_flags = WebStateList::INSERT_FORCE_INDEX; - // TODO(crbug.com/1264451): Remove this workaround when it will not be - // longer required to have an active WebState in the WebStateList. - if (destination_browser->GetWebStateList()->empty()) { - insertion_flags = WebStateList::INSERT_ACTIVATE; - } + // TODO(crbug.com/1264451): Remove this workaround when it will no longer be + // required to have an active WebState in the WebStateList. + if (destination_browser->GetWebStateList()->empty()) { + params.Activate(); } - WebStateList::InsertionParams params = - WebStateList::InsertionParams::ForDeprecationMigration( - insertion_flags, destination_tab_index); destination_browser->GetWebStateList()->InsertWebState(std::move(web_state), params); } @@ -76,15 +68,14 @@ int source_tab_index, Browser* destination_browser, int destination_tab_index) { - MoveTabFromBrowserToBrowser(source_browser, source_tab_index, - destination_browser, destination_tab_index, - WebStateList::InsertionFlags::INSERT_NO_FLAGS); + MoveTabFromBrowserToBrowser( + source_browser, source_tab_index, destination_browser, + WebStateList::InsertionParams::AtIndex(destination_tab_index)); } void MoveTabToBrowser(web::WebStateID tab_id, Browser* destination_browser, - int destination_tab_index, - WebStateList::InsertionFlags flags) { + WebStateList::InsertionParams params) { DCHECK(tab_id.valid()); ChromeBrowserState* browser_state = destination_browser->GetBrowserState(); BrowserList* browser_list = @@ -101,15 +92,15 @@ return; } MoveTabFromBrowserToBrowser(tab_info.browser, tab_info.tab_index, - destination_browser, destination_tab_index, - flags); + destination_browser, params); } void MoveTabToBrowser(web::WebStateID tab_id, Browser* destination_browser, int destination_tab_index) { - MoveTabToBrowser(tab_id, destination_browser, destination_tab_index, - WebStateList::InsertionFlags::INSERT_NO_FLAGS); + MoveTabToBrowser( + tab_id, destination_browser, + WebStateList::InsertionParams::AtIndex(destination_tab_index)); } BrowserAndIndex FindBrowserAndIndex(web::WebStateID tab_id,
diff --git a/ios/chrome/browser/parcel_tracking/parcel_tracking_util.mm b/ios/chrome/browser/parcel_tracking/parcel_tracking_util.mm index 2e65caf..2219cd5 100644 --- a/ios/chrome/browser/parcel_tracking/parcel_tracking_util.mm +++ b/ios/chrome/browser/parcel_tracking/parcel_tracking_util.mm
@@ -24,6 +24,10 @@ #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.h" #import "ios/chrome/browser/ui/ntp/metrics/home_metrics.h" +namespace { +const CGFloat parcelLimit = 5; +} // namespace + bool IsIOSParcelTrackingEnabled() { return base::FeatureList::IsEnabled(kIOSParcelTracking) && GetApplicationContext()->GetLocalState()->GetBoolean( @@ -104,19 +108,20 @@ [parcel_numbers removeObject:tracking_id]; } } + // Add the remaining parcels to filtered_parcels array. NSMutableArray<CustomTextCheckingResult*>* filtered_parcels = [[NSMutableArray alloc] init]; - // Add the remaining parcels to filtered_parcels array. for (CustomTextCheckingResult* parcel : parcels) { if ([parcel_numbers containsObject:parcel.carrierNumber]) { [filtered_parcels addObject:parcel]; } } - if (filtered_parcels.count == 0) { - return; + // Only track or offer to track when number of packages is less than 6. + if (filtered_parcels.count > 0 && + filtered_parcels.count <= parcelLimit) { + [parcel_tracking_commands_handler + showTrackingForFilteredParcels:filtered_parcels]; } - [parcel_tracking_commands_handler - showTrackingForFilteredParcels:filtered_parcels]; }, parcel_tracking_commands_handler, parcels)); }
diff --git a/ios/chrome/browser/sessions/fake_tab_restore_service.mm b/ios/chrome/browser/sessions/fake_tab_restore_service.mm index 02fa4bc..2791d62e 100644 --- a/ios/chrome/browser/sessions/fake_tab_restore_service.mm +++ b/ios/chrome/browser/sessions/fake_tab_restore_service.mm
@@ -24,12 +24,10 @@ void FakeTabRestoreService::AddObserver( sessions::TabRestoreServiceObserver* observer) { - NOTREACHED(); } void FakeTabRestoreService::RemoveObserver( sessions::TabRestoreServiceObserver* observer) { - NOTREACHED(); } std::optional<SessionID> FakeTabRestoreService::CreateHistoricalTab( @@ -71,7 +69,6 @@ } void FakeTabRestoreService::ClearEntries() { - NOTREACHED(); } void FakeTabRestoreService::DeleteNavigationEntries( @@ -116,7 +113,6 @@ } void FakeTabRestoreService::DeleteLastSession() { - NOTREACHED(); } bool FakeTabRestoreService::IsRestoring() const {
diff --git a/ios/chrome/browser/sessions/session_loading.mm b/ios/chrome/browser/sessions/session_loading.mm index da3a0aa..6007a23b 100644 --- a/ios/chrome/browser/sessions/session_loading.mm +++ b/ios/chrome/browser/sessions/session_loading.mm
@@ -113,8 +113,9 @@ const OrderControllerSourceFromWebStateListStorage source(storage); const OrderController order_controller(source); - result.set_active_index(order_controller.DetermineNewActiveIndex( - storage.active_index(), removing_indexes)); + result.set_active_index(removing_indexes.IndexAfterRemoval( + order_controller.DetermineNewActiveIndex(storage.active_index(), + removing_indexes))); } const int items_size = storage.items_size();
diff --git a/ios/chrome/browser/sessions/session_restoration_browser_agent.mm b/ios/chrome/browser/sessions/session_restoration_browser_agent.mm index a36a785..ecfb0e7 100644 --- a/ios/chrome/browser/sessions/session_restoration_browser_agent.mm +++ b/ios/chrome/browser/sessions/session_restoration_browser_agent.mm
@@ -130,8 +130,8 @@ // Update the `active_index` using the shared logic and the knowledge // of the removed items. - active_index = - order_controller.DetermineNewActiveIndex(active_index, removing_indexes); + active_index = removing_indexes.IndexAfterRemoval( + order_controller.DetermineNewActiveIndex(active_index, removing_indexes)); return active_index != WebStateList::kInvalidIndex ? static_cast<NSUInteger>(active_index)
diff --git a/ios/chrome/browser/sessions/web_state_list_serialization.mm b/ios/chrome/browser/sessions/web_state_list_serialization.mm index 6a8ad7a1..c2e46ee 100644 --- a/ios/chrome/browser/sessions/web_state_list_serialization.mm +++ b/ios/chrome/browser/sessions/web_state_list_serialization.mm
@@ -419,8 +419,9 @@ OrderControllerSourceFromWebStateList source(*web_state_list); OrderController order_controller(source); - const int active_index = order_controller.DetermineNewActiveIndex( - web_state_list->active_index(), std::move(removing_indexes)); + const int active_index = removing_indexes.IndexAfterRemoval( + order_controller.DetermineNewActiveIndex(web_state_list->active_index(), + removing_indexes)); NSUInteger selectedIndex = active_index != WebStateList::kInvalidIndex ? static_cast<NSUInteger>(active_index) @@ -484,8 +485,9 @@ OrderControllerSourceFromWebStateList source(web_state_list); OrderController order_controller(source); - const int active_index = order_controller.DetermineNewActiveIndex( - web_state_list.active_index(), std::move(removing_indexes)); + const int active_index = removing_indexes.IndexAfterRemoval( + order_controller.DetermineNewActiveIndex(web_state_list.active_index(), + removing_indexes)); DCHECK_LT(active_index, web_state_list.count()); storage.set_active_index(active_index); }
diff --git a/ios/chrome/browser/shared/model/web_state_list/order_controller.h b/ios/chrome/browser/shared/model/web_state_list/order_controller.h index b2fefb43..c391137 100644 --- a/ios/chrome/browser/shared/model/web_state_list/order_controller.h +++ b/ios/chrome/browser/shared/model/web_state_list/order_controller.h
@@ -49,10 +49,12 @@ int DetermineInsertionIndex(InsertionParams params) const; // Determines where to shift the active index after a WebState is closed. - // The returned index will either be WebStateList::kInvalidIndex or in be - // in range for the WebStateList once the element has been removed (i.e. - // this function accounts for the fact that the element at `removing_index` - // will be removed from the WebStateList). + // + // The index returned does not take into consideration the elements to be + // closed. If the calling code needs the index after closing the elements, + // it should use RemovingIndexes::IndexAfterRemoval(...) on the returned + // value. + // // Logic diagram: crbug.com/1395319 int DetermineNewActiveIndex(int active_index, const RemovingIndexes& removing_indexes) const;
diff --git a/ios/chrome/browser/shared/model/web_state_list/order_controller.mm b/ios/chrome/browser/shared/model/web_state_list/order_controller.mm index 078fc6f1..af7a5e1 100644 --- a/ios/chrome/browser/shared/model/web_state_list/order_controller.mm +++ b/ios/chrome/browser/shared/model/web_state_list/order_controller.mm
@@ -16,6 +16,8 @@ namespace { +using Range = OrderController::Range; + // Finds the index of the `n`-th child of the WebState at `opener_index` that // is not removed. If there are less than `n` such item, returns the index of // the last one. If there are no items returns WebStateList::kInvalidIndex. @@ -23,9 +25,6 @@ // If `check_navigation_index` is true, the opener-opened relationship is // considered as broken if the opener has navigated away since the child has // been opened. -// -// The returned index, if not WebStateList::kInvalidIndex, is the updated -// index after all the WebState scheduled for removal have been removed. int FindIndexOfNthWebStateOpenedBy(const RemovingIndexes& removing_indexes, const OrderControllerSource& source, bool check_navigation_index, @@ -59,29 +58,25 @@ } } - return removing_indexes.IndexAfterRemoval(found_index); + return found_index; } -// Returns the index of the closest item from `index` in range `start` - `end` -// that is not scheduled for deletion or WebStateList::kInvalidIndex. Prefer a -// WebState after `index` over one before. -// -// The returned index, if not WebStateList::kInvalidIndex, is the updated -// index after all the WebState scheduled for removal have been removed. +// Returns the index of the closest item from `index` in `range` that is not +// scheduled for deletion or WebStateList::kInvalidIndex. Prefer a WebState +// after `index` over one before. int FindClosestWebStateInRange(const RemovingIndexes& removing_indexes, int index, - int start, - int end) { - for (int i = index + 1; i < end; ++i) { + Range range) { + for (int i = index + 1; i < range.end; ++i) { if (!removing_indexes.Contains(i)) { - return removing_indexes.IndexAfterRemoval(i); + return i; } } - for (int i = start; i < index; ++i) { - const int j = index - 1 - (i - start); + for (int i = range.begin; i < index; ++i) { + const int j = index - 1 - (i - range.begin); if (!removing_indexes.Contains(j)) { - return removing_indexes.IndexAfterRemoval(j); + return j; } } @@ -182,20 +177,18 @@ // If the active element is not removed, then the active element won't change // but its index may need to be tweaked if after some of the removed elements. - const int active_index_after_removal = - removing_indexes.IndexAfterRemoval(active_index); - if (active_index_after_removal != WebStateList::kInvalidIndex) { - return active_index_after_removal; + if (!removing_indexes.Contains(active_index)) { + return active_index; } // Check if any of the "child" of the active WebState can be selected to be // the new active element. Prefer childs located after the active element, // but this may end up selecting an element before it. - const int child_index_after_removal = FindIndexOfNthWebStateOpenedBy( + const int child_index = FindIndexOfNthWebStateOpenedBy( removing_indexes, source_.get(), /* check_navigation_index */ false, active_index, active_index, 1); - if (child_index_after_removal != WebStateList::kInvalidIndex) { - return child_index_after_removal; + if (child_index != WebStateList::kInvalidIndex) { + return child_index; } const int opener_index = source_->GetOpenerOfItemAt(active_index); @@ -203,18 +196,16 @@ // Check if any of the "sibling" of the active WebState can be selected // to be the new active element. Prefer siblings located after the active // element, but this may end up selecting an element before it. - const int sibling_index_after_removal = FindIndexOfNthWebStateOpenedBy( + const int sibling_index = FindIndexOfNthWebStateOpenedBy( removing_indexes, source_.get(), /* check_navigation_index */ false, opener_index, active_index, 1); - if (sibling_index_after_removal != WebStateList::kInvalidIndex) { - return sibling_index_after_removal; + if (sibling_index != WebStateList::kInvalidIndex) { + return sibling_index; } // If the opener is not removed, select it as the next WebState. - const int opener_index_after_removal = - removing_indexes.IndexAfterRemoval(opener_index); - if (opener_index_after_removal != WebStateList::kInvalidIndex) { - return opener_index_after_removal; + if (!removing_indexes.Contains(opener_index)) { + return opener_index; } } @@ -224,15 +215,17 @@ // Look for the closest non-removed WebState in the same group (pinned or // regular WebStates). int closest_index = FindClosestWebStateInRange( - removing_indexes, active_index, is_pinned ? 0 : pinned_count, - is_pinned ? pinned_count : count); + removing_indexes, active_index, + Range{.begin = is_pinned ? 0 : pinned_count, + .end = is_pinned ? pinned_count : count}); if (closest_index == WebStateList::kInvalidIndex) { // If all items in the same group are removed, look for the closest // WebState in the other group (pinned or regular WebStates). closest_index = FindClosestWebStateInRange( - removing_indexes, active_index, is_pinned ? pinned_count : 0, - is_pinned ? count : pinned_count); + removing_indexes, active_index, + Range{.begin = is_pinned ? pinned_count : 0, + .end = is_pinned ? count : pinned_count}); } DCHECK_NE(closest_index, WebStateList::kInvalidIndex);
diff --git a/ios/chrome/browser/shared/model/web_state_list/order_controller_unittest.mm b/ios/chrome/browser/shared/model/web_state_list/order_controller_unittest.mm index 598cae9..9f6e381 100644 --- a/ios/chrome/browser/shared/model/web_state_list/order_controller_unittest.mm +++ b/ios/chrome/browser/shared/model/web_state_list/order_controller_unittest.mm
@@ -285,17 +285,17 @@ WebStateList::kInvalidIndex, {})); // Verify that if closing an item that is not active, the active item is - // not changed, but the index is updated if the item is after the closed - // one. + // not changed. The returned index is the index before closing the other + // items, so it should not change. EXPECT_EQ(4, order_controller.DetermineNewActiveIndex(4, {5})); - EXPECT_EQ(5, order_controller.DetermineNewActiveIndex(6, {5})); + EXPECT_EQ(6, order_controller.DetermineNewActiveIndex(6, {5})); EXPECT_EQ(4, order_controller.DetermineNewActiveIndex(4, {5, 7})); - EXPECT_EQ(5, order_controller.DetermineNewActiveIndex(6, {5, 7})); - EXPECT_EQ(5, order_controller.DetermineNewActiveIndex(7, {5, 6})); + EXPECT_EQ(6, order_controller.DetermineNewActiveIndex(6, {5, 7})); + EXPECT_EQ(7, order_controller.DetermineNewActiveIndex(7, {5, 6})); // Verify that if closing an item with siblings, the next sibling is // selected, even if it is before the active one. - EXPECT_EQ(4, order_controller.DetermineNewActiveIndex(4, {4})); + EXPECT_EQ(5, order_controller.DetermineNewActiveIndex(4, {4})); EXPECT_EQ(4, order_controller.DetermineNewActiveIndex(5, {5})); // Verify that if closing an item with opener but no sibling, then the @@ -304,12 +304,16 @@ // Verify that if closing an item with children, the first child is // selected, even if it is before the active item. - EXPECT_EQ(5, order_controller.DetermineNewActiveIndex(1, {1})); + EXPECT_EQ(6, order_controller.DetermineNewActiveIndex(1, {1})); EXPECT_EQ(2, order_controller.DetermineNewActiveIndex(7, {7})); + // Veriffy that closing an item with multiple children, the first + // one is selected. + EXPECT_EQ(4, order_controller.DetermineNewActiveIndex(0, {0})); + // Verify that if closing an item with no child, the next item is // selected, or the previous one if the last item was closed. - EXPECT_EQ(3, order_controller.DetermineNewActiveIndex(3, {3})); + EXPECT_EQ(4, order_controller.DetermineNewActiveIndex(3, {3})); EXPECT_EQ(7, order_controller.DetermineNewActiveIndex(8, {8})); // Verify that if closing an item and its siblings, the opener is @@ -318,11 +322,11 @@ // Verify that if closing an item with children, the first non closed // child is selected. - EXPECT_EQ(3, order_controller.DetermineNewActiveIndex(0, {0, 4})); + EXPECT_EQ(5, order_controller.DetermineNewActiveIndex(0, {0, 4})); // Verify that if closing an item with children and all its children, // the tab after it is selected. - EXPECT_EQ(0, order_controller.DetermineNewActiveIndex(0, {0, 4, 5})); + EXPECT_EQ(1, order_controller.DetermineNewActiveIndex(0, {0, 4, 5})); // Verify that if closing an item, all its children and all the item // after it, then the tab before it is selected.
diff --git a/ios/chrome/browser/shared/model/web_state_list/web_state_list.h b/ios/chrome/browser/shared/model/web_state_list/web_state_list.h index e339cd0..07b11a9 100644 --- a/ios/chrome/browser/shared/model/web_state_list/web_state_list.h +++ b/ios/chrome/browser/shared/model/web_state_list/web_state_list.h
@@ -56,7 +56,9 @@ return *this; } - // Whether the WebState inherits its opener. + // Whether the WebState inherits its opener. If set, the WebState opener is + // set to the active WebState, otherwise it must be explicitly passed via + // `WithOpener`. InsertionParams& InheritOpener(bool inherits_opener = true) { this->inherit_opener = inherits_opener; return *this; @@ -73,36 +75,6 @@ this->pinned = pin; return *this; } - - // To simplify migrating off of the deprecated `InsertWebState` member - // function, convert a set of insertion parameters to real InsertionParams. - static InsertionParams ForDeprecationMigration( - int insertion_flags, - int desired_index = kInvalidIndex, - WebStateOpener opener = WebStateOpener()); - }; - - // Deprecated. Use InsertionParams. - enum InsertionFlags { - // Used to indicate that nothing special should happen to the newly - // inserted WebState. - INSERT_NO_FLAGS = 0, - - // Used to indicate that the WebState should be activated on insertion. - INSERT_ACTIVATE = 1 << 0, - - // If not set, the insertion index of the WebState is left up to the - // order controller associated with the WebStateList so the insertion - // index may differ from the specified index. Otherwise the supplied - // index is used. - INSERT_FORCE_INDEX = 1 << 1, - - // If set, the WebState opener is set to the active WebState, otherwise - // it must be explicitly passed. - INSERT_INHERIT_OPENER = 1 << 2, - - // Used to indicate that the WebState should be pinned on insertion. - INSERT_PINNED = 1 << 3, }; // Constants used when closing WebStates.
diff --git a/ios/chrome/browser/shared/model/web_state_list/web_state_list.mm b/ios/chrome/browser/shared/model/web_state_list/web_state_list.mm index f2ce6f9b..a0fa4a00 100644 --- a/ios/chrome/browser/shared/model/web_state_list/web_state_list.mm +++ b/ios/chrome/browser/shared/model/web_state_list/web_state_list.mm
@@ -22,32 +22,12 @@ namespace { // Returns whether the given flag is set in a flagset. -bool IsInsertionFlagSet(int flagset, WebStateList::InsertionFlags flag) { - return (flagset & flag) == flag; -} - -// Returns whether the given flag is set in a flagset. bool IsClosingFlagSet(int flagset, WebStateList::ClosingFlags flag) { return (flagset & flag) == flag; } } // namespace -WebStateList::InsertionParams -WebStateList::InsertionParams::ForDeprecationMigration(int insertion_flags, - int desired_index, - WebStateOpener opener) { - InsertionParams params = InsertionParams::Automatic(); - if (IsInsertionFlagSet(insertion_flags, INSERT_FORCE_INDEX)) { - params = InsertionParams::AtIndex(desired_index); - } - params.WithOpener(opener) - .InheritOpener(IsInsertionFlagSet(insertion_flags, INSERT_INHERIT_OPENER)) - .Activate(IsInsertionFlagSet(insertion_flags, INSERT_ACTIVATE)) - .Pinned(IsInsertionFlagSet(insertion_flags, INSERT_PINNED)); - return params; -} - WebStateList::ScopedBatchOperation::ScopedBatchOperation( WebStateList* web_state_list) : web_state_list_(web_state_list) { @@ -608,8 +588,11 @@ // the WebStateListDidChange with kDetach. OrderControllerSourceFromWebStateList source(*this); OrderController order_controller(source); - active_index_ = - order_controller.DetermineNewActiveIndex(active_index_, {index}); + + RemovingIndexes removing_indexes({index}); + active_index_ = removing_indexes.IndexAfterRemoval( + order_controller.DetermineNewActiveIndex(active_index_, + removing_indexes)); ClearOpenersReferencing(index); std::unique_ptr<web::WebState> detached_web_state = @@ -656,19 +639,14 @@ // Immediately determine the new active index to avoid // sending multiple notification about changing active // WebState. - int new_active_index = kInvalidIndex; - if (start_index != 0) { - std::vector<int> removing_indexes; - removing_indexes.reserve(count() - start_index); - for (int i = start_index; i < count(); ++i) { - removing_indexes.push_back(i); - } + OrderControllerSourceFromWebStateList source(*this); + OrderController order_controller(source); - OrderControllerSourceFromWebStateList source(*this); - OrderController order_controller(source); - new_active_index = order_controller.DetermineNewActiveIndex( - active_index_, RemovingIndexes(std::move(removing_indexes))); - } + const int new_active_index = order_controller.DetermineNewActiveIndex( + active_index_, + RemovingIndexes::Range(start_index, count() - start_index)); + + ActivateWebStateAtImpl(new_active_index); // Detach all web states in a first pass, before destroying them at once // later. This avoids odd side effects as a result of WebStateImpl's @@ -677,17 +655,6 @@ std::vector<std::unique_ptr<web::WebState>> detached_web_states; const bool is_user_action = IsClosingFlagSet(close_flags, CLOSE_USER_ACTION); - if (new_active_index != active_index_) { - web::WebState* old_active_web_state = GetActiveWebState(); - SetActiveIndex(new_active_index); - - // Notify the event to the observers that a WebState is detached and an - // active WebState is updated as well. - detached_web_states.push_back(DetachWebStateAtImpl( - count() - 1, DetachParams::ClosingWithUpdateActiveWebState( - is_user_action, old_active_web_state))); - } - while (count() > start_index) { detached_web_states.push_back(DetachWebStateAtImpl( count() - 1, DetachParams::Closing(is_user_action)));
diff --git a/ios/chrome/browser/shared/public/features/features.mm b/ios/chrome/browser/shared/public/features/features.mm index 69f57d7e..a12bc9b 100644 --- a/ios/chrome/browser/shared/public/features/features.mm +++ b/ios/chrome/browser/shared/public/features/features.mm
@@ -75,7 +75,7 @@ BASE_FEATURE(kDefaultBrowserVideoPromo, "DefaultBrowserVideoPromo", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); const char kIOSEditMenuPartialTranslateNoIncognitoParam[] = "IOSEditMenuPartialTranslateNoIncognitoParam";
diff --git a/ios/chrome/browser/tab_insertion/model/tab_insertion_browser_agent.mm b/ios/chrome/browser/tab_insertion/model/tab_insertion_browser_agent.mm index a419d7a3..eca89b6 100644 --- a/ios/chrome/browser/tab_insertion/model/tab_insertion_browser_agent.mm +++ b/ios/chrome/browser/tab_insertion/model/tab_insertion_browser_agent.mm
@@ -60,26 +60,6 @@ WebStateList* const web_state_list = browser_->GetWebStateList(); ChromeBrowserState* const browser_state = browser_->GetBrowserState(); - int insertion_index = WebStateList::kInvalidIndex; - int insertion_flags = WebStateList::INSERT_NO_FLAGS; - if (tab_insertion_params.index != TabInsertion::kPositionAutomatically) { - DCHECK_LE(tab_insertion_params.index, INT_MAX); - insertion_index = static_cast<int>(tab_insertion_params.index); - insertion_flags |= WebStateList::INSERT_FORCE_INDEX; - } else if (!ui::PageTransitionCoreTypeIs(web_load_params.transition_type, - ui::PAGE_TRANSITION_LINK)) { - insertion_index = web_state_list->count(); - insertion_flags |= WebStateList::INSERT_FORCE_INDEX; - } - - if (!tab_insertion_params.in_background) { - insertion_flags |= WebStateList::INSERT_ACTIVATE; - } - - if (tab_insertion_params.inherit_opener) { - insertion_flags |= WebStateList::INSERT_INHERIT_OPENER; - } - std::unique_ptr<web::WebState> web_state; web::WebState::CreateParams create_params(browser_state); create_params.created_with_opener = tab_insertion_params.opened_by_dom; @@ -117,10 +97,17 @@ web_state->GetNavigationManager()->LoadURLWithParams(web_load_params); } - const WebStateList::InsertionParams params = - WebStateList::InsertionParams::ForDeprecationMigration( - insertion_flags, insertion_index, - WebStateOpener(tab_insertion_params.parent)); + WebStateList::InsertionParams params = + WebStateList::InsertionParams::Automatic(); + if (tab_insertion_params.index != TabInsertion::kPositionAutomatically) { + params = WebStateList::InsertionParams::AtIndex(tab_insertion_params.index); + } else if (!ui::PageTransitionCoreTypeIs(web_load_params.transition_type, + ui::PAGE_TRANSITION_LINK)) { + params = WebStateList::InsertionParams::AtIndex(web_state_list->count()); + } + params.Activate(!tab_insertion_params.in_background) + .InheritOpener(tab_insertion_params.inherit_opener) + .WithOpener(WebStateOpener(tab_insertion_params.parent)); web::WebState* web_state_ptr = web_state.get(); web_state_list->InsertWebState(std::move(web_state), params); return web_state_ptr;
diff --git a/ios/chrome/browser/tabs/model/inactive_tabs/utils.mm b/ios/chrome/browser/tabs/model/inactive_tabs/utils.mm index 7a42751..8ba1c7e 100644 --- a/ios/chrome/browser/tabs/model/inactive_tabs/utils.mm +++ b/ios/chrome/browser/tabs/model/inactive_tabs/utils.mm
@@ -179,18 +179,15 @@ } if (base::ranges::binary_search(indexes_moving, index)) { - // Using INSERT_FORCE_INDEX allow to insert all the moved tabs at the - // expected location and INSERT_ACTIVATE allow to activate the tab if - // needed (e.g. the first moved tab from source when target has no - // active WebState). - const int insertion_flags = - WebStateList::INSERT_FORCE_INDEX | - (index == index_to_activate ? WebStateList::INSERT_ACTIVATE - : WebStateList::INSERT_NO_FLAGS); + // Using `AtIndex` allows to insert all the moved tabs with a desired + // location and `Activate` allows to activate the tab if needed (e.g. the + // first moved tab from source when target has no active WebState). + const WebStateList::InsertionParams params = + WebStateList::InsertionParams::AtIndex(insertion_index) + .Activate(index == index_to_activate); - MoveTabFromBrowserToBrowser( - source_browser, index, target_browser, insertion_index, - static_cast<WebStateList::InsertionFlags>(insertion_flags)); + MoveTabFromBrowserToBrowser(source_browser, index, target_browser, + params); continue; } }
diff --git a/ios/chrome/browser/tips_notifications/model/OWNERS b/ios/chrome/browser/tips_notifications/OWNERS similarity index 100% rename from ios/chrome/browser/tips_notifications/model/OWNERS rename to ios/chrome/browser/tips_notifications/OWNERS
diff --git a/ios/chrome/browser/tips_notifications/eg_test/BUILD.gn b/ios/chrome/browser/tips_notifications/eg_test/BUILD.gn new file mode 100644 index 0000000..0292bfc --- /dev/null +++ b/ios/chrome/browser/tips_notifications/eg_test/BUILD.gn
@@ -0,0 +1,25 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("eg2_tests") { + configs += [ "//build/config/ios:xctest_config" ] + testonly = true + sources = [ "tips_notifications_egtest.mm" ] + deps = [ + "//base", + "//base/test:test_support", + "//ios/chrome/browser/shared/model/prefs:pref_names", + "//ios/chrome/browser/shared/public/features", + "//ios/chrome/browser/signin/model:fake_system_identity", + "//ios/chrome/browser/tips_notifications/model:utils", + "//ios/chrome/browser/ui/authentication:eg_test_support+eg2", + "//ios/chrome/browser/ui/authentication/signin:constants", + "//ios/chrome/browser/ui/content_suggestions:eg_test_support+eg2", + "//ios/chrome/browser/ui/content_suggestions/set_up_list:constants", + "//ios/chrome/browser/ui/push_notification:test_support", + "//ios/chrome/common/ui/confirmation_alert:constants", + "//ios/chrome/test/earl_grey:eg_test_support+eg2", + "//ios/testing/earl_grey:eg_test_support+eg2", + ] +}
diff --git a/ios/chrome/browser/tips_notifications/eg_test/tips_notifications_egtest.mm b/ios/chrome/browser/tips_notifications/eg_test/tips_notifications_egtest.mm new file mode 100644 index 0000000..91bd0006 --- /dev/null +++ b/ios/chrome/browser/tips_notifications/eg_test/tips_notifications_egtest.mm
@@ -0,0 +1,168 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "base/strings/stringprintf.h" +#import "ios/chrome/browser/shared/model/prefs/pref_names.h" +#import "ios/chrome/browser/shared/public/features/features.h" +#import "ios/chrome/browser/signin/model/fake_system_identity.h" +#import "ios/chrome/browser/tips_notifications/model/utils.h" +#import "ios/chrome/browser/ui/authentication/signin/signin_constants.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" +#import "ios/chrome/browser/ui/content_suggestions/new_tab_page_app_interface.h" +#import "ios/chrome/browser/ui/content_suggestions/set_up_list/constants.h" +#import "ios/chrome/common/ui/confirmation_alert/constants.h" +#import "ios/chrome/test/earl_grey/chrome_actions.h" +#import "ios/chrome/test/earl_grey/chrome_earl_grey.h" +#import "ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h" +#import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" +#import "ios/chrome/test/earl_grey/chrome_matchers.h" +#import "ios/chrome/test/earl_grey/chrome_test_case.h" +#import "ios/testing/earl_grey/app_launch_manager.h" +#import "ios/testing/earl_grey/earl_grey_test.h" + +namespace { + +// Long presses the view with the given `accessibility_id`. +void LongPressView(NSString* accessibility_id) { + id<GREYMatcher> matcher = grey_accessibilityID(accessibility_id); + [[EarlGrey selectElementWithMatcher:matcher] performAction:grey_longPress()]; +} + +// Wait for a view that contains a partial match to the given `text`, then tap +// it. +void WaitForThenTapText(NSString* text) { + id item = chrome_test_util::ContainsPartialText(text); + [ChromeEarlGrey waitForSufficientlyVisibleElementWithMatcher:item]; + [[EarlGrey selectElementWithMatcher:item] performAction:grey_tap()]; +} + +// Taps a view containing a partial match to the given `text`. +void TapText(NSString* text) { + id item = grey_allOf(chrome_test_util::ContainsPartialText(text), + grey_sufficientlyVisible(), nil); + [[EarlGrey selectElementWithMatcher:item] performAction:grey_tap()]; +} + +// Taps "Allow" on notification permissions alert, if it appears. +void MaybeTapAllowNotifications() { + XCUIApplication* springboardApplication = [[XCUIApplication alloc] + initWithBundleIdentifier:@"com.apple.springboard"]; + auto button = springboardApplication.buttons[@"Allow"]; + if ([button waitForExistenceWithTimeout:2]) { + [button tap]; + [ChromeEarlGreyUI waitForAppToIdle]; + } +} + +void TapNotification() { + XCUIApplication* springboardApplication = [[XCUIApplication alloc] + initWithBundleIdentifier:@"com.apple.springboard"]; + auto notification = + springboardApplication.otherElements[@"Notification"].firstMatch; + GREYAssert([notification waitForExistenceWithTimeout:4], + @"A notification did not appear"); + [notification tap]; + [ChromeEarlGreyUI waitForAppToIdle]; +} + +} // namespace + +// Test case for Tips Notifications. +@interface TipsNotificationsTestCase : ChromeTestCase +@end + +@implementation TipsNotificationsTestCase + +- (AppLaunchConfiguration)appConfigurationForTestCase { + AppLaunchConfiguration config; + // config.features_enabled.push_back(kIOSTipsNotifications); + config.features_enabled.push_back(kMagicStack); + + // Enable Tips Notifications with 1s trigger time. + std::string enableFeatures = base::StringPrintf( + "--enable-features=%s:%s/%s", kIOSTipsNotifications.name, + kIOSTipsNotificationsTriggerTimeParam, "1s"); + config.additional_args.push_back(enableFeatures); + return config; +} + ++ (void)setUpForTestCase { + [super setUpForTestCase]; + + [ChromeEarlGreyAppInterface writeFirstRunSentinel]; + [ChromeEarlGreyAppInterface clearDefaultBrowserPromoData]; + [ChromeEarlGrey resetDataForLocalStatePref: + prefs::kIosCredentialProviderPromoLastActionTaken]; + [NewTabPageAppInterface resetSetUpListPrefs]; +} + +- (void)optInToTipsNotifications { + // Long press the SetUpList module. + LongPressView(set_up_list::kDefaultBrowserItemID); + + // Tap the menu item to enable notifications. + TapText(@"Turn on Notifications"); + MaybeTapAllowNotifications(); + + // Tap the confirmation snackbar. + WaitForThenTapText(@"notifications turned on"); +} + +// Tests triggering and interacting with each of the Tips notifications. +- (void)testTriggerNotifications { + XCUIApplication* app = [[XCUIApplication alloc] init]; + [self optInToTipsNotifications]; + + // Trigger the Default Browser Notification. + [XCUIDevice.sharedDevice pressButton:XCUIDeviceButtonHome]; + [ChromeEarlGrey resetDataForLocalStatePref:kTipsNotificationsSentPref]; + [app activate]; + TapNotification(); + + // Verify that the Default Browser Promo is visible. + id<GREYMatcher> defaultBrowserView = + chrome_test_util::DefaultBrowserSettingsTableViewMatcher(); + [[EarlGrey selectElementWithMatcher:defaultBrowserView] + assertWithMatcher:grey_sufficientlyVisible()]; + + // Tap "cancel". + [[EarlGrey + selectElementWithMatcher:chrome_test_util::NavigationBarCancelButton()] + performAction:grey_tap()]; + + // Trigger the What's New notification. + [XCUIDevice.sharedDevice pressButton:XCUIDeviceButtonHome]; + [app activate]; + TapNotification(); + + // Verify that the What's New screen is showing. + id<GREYMatcher> whatsNewView = grey_accessibilityID(@"kWhatsNewListViewId"); + [[EarlGrey selectElementWithMatcher:whatsNewView] + assertWithMatcher:grey_sufficientlyVisible()]; + + // Dismiss the What's New screen. + id<GREYMatcher> whatsNewDoneButton = + grey_accessibilityID(@"kWhatsNewTableViewNavigationDismissButtonId"); + [[EarlGrey selectElementWithMatcher:whatsNewDoneButton] + performAction:grey_tap()]; + + // Trigger the Signin notification. + [XCUIDevice.sharedDevice pressButton:XCUIDeviceButtonHome]; + [app activate]; + [SigninEarlGrey addFakeIdentity:[FakeSystemIdentity fakeIdentity1]]; + TapNotification(); + + // Verify the signin screen is showing + id<GREYMatcher> signinView = + grey_accessibilityID(kWebSigninAccessibilityIdentifier); + [[EarlGrey selectElementWithMatcher:signinView] + assertWithMatcher:grey_sufficientlyVisible()]; + + // Dismiss Signin. + [[EarlGrey + selectElementWithMatcher:chrome_test_util::NavigationBarCancelButton()] + performAction:grey_tap()]; +} + +@end
diff --git a/ios/chrome/browser/tips_notifications/model/BUILD.gn b/ios/chrome/browser/tips_notifications/model/BUILD.gn index f3a978d..fbdd06e 100644 --- a/ios/chrome/browser/tips_notifications/model/BUILD.gn +++ b/ios/chrome/browser/tips_notifications/model/BUILD.gn
@@ -11,6 +11,7 @@ ":utils", "//base", "//components/feature_engagement/public", + "//ios/chrome/browser/default_browser/model", "//ios/chrome/browser/default_browser/model:utils", "//ios/chrome/browser/feature_engagement/model", "//ios/chrome/browser/push_notification/model:push_notification_client", @@ -23,6 +24,7 @@ "//ios/chrome/browser/signin/model", "//ios/chrome/browser/ui/authentication:signin_presenter", ] + frameworks = [ "UserNotifications.framework" ] } source_set("utils") { @@ -36,6 +38,7 @@ "//ios/chrome/browser/shared/public/features", "//ui/base", ] + frameworks = [ "UserNotifications.framework" ] } source_set("unit_tests") { @@ -46,6 +49,7 @@ ":utils", "//base", "//base/test:test_support", + "//ios/chrome/browser/default_browser/model", "//ios/chrome/browser/default_browser/model:test_support", "//ios/chrome/browser/default_browser/model:utils", "//ios/chrome/browser/first_run/model",
diff --git a/ios/chrome/browser/tips_notifications/model/tips_notification_client.mm b/ios/chrome/browser/tips_notifications/model/tips_notification_client.mm index f79ae19..9836abe 100644 --- a/ios/chrome/browser/tips_notifications/model/tips_notification_client.mm +++ b/ios/chrome/browser/tips_notifications/model/tips_notification_client.mm
@@ -10,6 +10,7 @@ #import "components/prefs/pref_registry_simple.h" #import "components/prefs/pref_service.h" #import "components/sync/base/features.h" +#import "ios/chrome/browser/default_browser/model/promo_source.h" #import "ios/chrome/browser/default_browser/model/utils.h" #import "ios/chrome/browser/feature_engagement/model/tracker_factory.h" #import "ios/chrome/browser/shared/coordinator/scene/scene_state.h" @@ -21,7 +22,7 @@ #import "ios/chrome/browser/shared/model/utils/first_run_util.h" #import "ios/chrome/browser/shared/public/commands/browser_coordinator_commands.h" #import "ios/chrome/browser/shared/public/commands/command_dispatcher.h" -#import "ios/chrome/browser/shared/public/commands/promos_manager_commands.h" +#import "ios/chrome/browser/shared/public/commands/settings_commands.h" #import "ios/chrome/browser/shared/public/commands/show_signin_command.h" #import "ios/chrome/browser/signin/model/authentication_service.h" #import "ios/chrome/browser/signin/model/authentication_service_factory.h" @@ -268,8 +269,10 @@ void TipsNotificationClient::ShowDefaultBrowserPromo() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); Browser* browser = GetSceneLevelForegroundActiveBrowser(); - [HandlerForProtocol(browser->GetCommandDispatcher(), PromosManagerCommands) - maybeDisplayDefaultBrowserPromo]; + [HandlerForProtocol(browser->GetCommandDispatcher(), SettingsCommands) + showDefaultBrowserSettingsFromViewController:nil + sourceForUMA:DefaultBrowserPromoSource:: + kTipsNotification]; } void TipsNotificationClient::ShowWhatsNew() {
diff --git a/ios/chrome/browser/tips_notifications/model/tips_notification_client_unittest.mm b/ios/chrome/browser/tips_notifications/model/tips_notification_client_unittest.mm index a28593b..2c335ee 100644 --- a/ios/chrome/browser/tips_notifications/model/tips_notification_client_unittest.mm +++ b/ios/chrome/browser/tips_notifications/model/tips_notification_client_unittest.mm
@@ -8,6 +8,7 @@ #import "base/test/task_environment.h" #import "base/threading/thread_restrictions.h" +#import "ios/chrome/browser/default_browser/model/promo_source.h" #import "ios/chrome/browser/default_browser/model/utils.h" #import "ios/chrome/browser/default_browser/model/utils_test_support.h" #import "ios/chrome/browser/first_run/model/first_run.h" @@ -19,7 +20,7 @@ #import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state_manager.h" #import "ios/chrome/browser/shared/public/commands/browser_coordinator_commands.h" #import "ios/chrome/browser/shared/public/commands/command_dispatcher.h" -#import "ios/chrome/browser/shared/public/commands/promos_manager_commands.h" +#import "ios/chrome/browser/shared/public/commands/settings_commands.h" #import "ios/chrome/browser/tips_notifications/model/utils.h" #import "ios/chrome/test/testing_application_context.h" #import "ios/testing/scoped_block_swizzler.h" @@ -182,11 +183,14 @@ // Tests that the client handles a Default Browser notification response. TEST_F(TipsNotificationClientTest, DefaultBrowserHandle) { - id mock_handler = OCMProtocolMock(@protocol(PromosManagerCommands)); - OCMExpect([mock_handler maybeDisplayDefaultBrowserPromo]); + id mock_handler = OCMProtocolMock(@protocol(SettingsCommands)); + OCMExpect([mock_handler + showDefaultBrowserSettingsFromViewController:nil + sourceForUMA:DefaultBrowserPromoSource:: + kTipsNotification]); [browser_->GetCommandDispatcher() startDispatchingToTarget:mock_handler - forProtocol:@protocol(PromosManagerCommands)]; + forProtocol:@protocol(SettingsCommands)]; id mock_response = MockRequestResponse(TipsNotificationType::kDefaultBrowser); client_->HandleNotificationInteraction(mock_response);
diff --git a/ios/chrome/browser/ui/bubble/bubble_dismissal_reason_type.h b/ios/chrome/browser/ui/bubble/bubble_dismissal_reason_type.h index 96cc67d..6c967e0 100644 --- a/ios/chrome/browser/ui/bubble/bubble_dismissal_reason_type.h +++ b/ios/chrome/browser/ui/bubble/bubble_dismissal_reason_type.h
@@ -22,7 +22,8 @@ kTappedSnooze = 6, kTappedOutsideIPHAndAnchorView = 7, kTappedAnchorView = 8, - kMaxValue = kTappedAnchorView, + kVoiceOverAnnouncementEnded = 9, + kMaxValue = kVoiceOverAnnouncementEnded, }; // Used for the bubble's dismissal callback.
diff --git a/ios/chrome/browser/ui/bubble/bubble_presenter.mm b/ios/chrome/browser/ui/bubble/bubble_presenter.mm index 292f2fe..71e822e4 100644 --- a/ios/chrome/browser/ui/bubble/bubble_presenter.mm +++ b/ios/chrome/browser/ui/bubble/bubble_presenter.mm
@@ -581,6 +581,7 @@ - (void)presentPullToRefreshGestureInProductHelp { if (UIAccessibilityIsVoiceOverRunning() || (![self canPresentBubble])) { + // TODO(crbug.com/1521489): Add voice over announcement once fixed. return; } const base::Feature& pullToRefreshFeature =
diff --git a/ios/chrome/browser/ui/bubble/gesture_iph/gesture_in_product_help_view.h b/ios/chrome/browser/ui/bubble/gesture_iph/gesture_in_product_help_view.h index 8ef79e19..f0f06d4 100644 --- a/ios/chrome/browser/ui/bubble/gesture_iph/gesture_in_product_help_view.h +++ b/ios/chrome/browser/ui/bubble/gesture_iph/gesture_in_product_help_view.h
@@ -29,11 +29,21 @@ /// - `direction` also indicates which side of the view the user could perform /// the swipe action on. Note that the swipe movement would be toward the /// opposite direction. +/// `voiceOverAnnouncement` provides a message specifically for voice-over +/// users. This message is both shown visually in a bubble and read aloud. If +/// value is `nil`, the `text` will be used for voice-over users. - (instancetype)initWithText:(NSString*)text bubbleBoundingSize:(CGSize)bubbleBoundingSize arrowDirection:(BubbleArrowDirection)direction + voiceOverAnnouncement:(NSString*)voiceOverAnnouncement NS_DESIGNATED_INITIALIZER; +/// Convenience initializer that does not provide a way to specify a different +/// message for voice-over users. +- (instancetype)initWithText:(NSString*)text + bubbleBoundingSize:(CGSize)bubbleBoundingSize + arrowDirection:(BubbleArrowDirection)direction; + - (instancetype)init NS_UNAVAILABLE; - (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; - (instancetype)initWithCoder:(NSCoder*)coder NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/ui/bubble/gesture_iph/gesture_in_product_help_view.mm b/ios/chrome/browser/ui/bubble/gesture_iph/gesture_in_product_help_view.mm index d85fd654..a883af8 100644 --- a/ios/chrome/browser/ui/bubble/gesture_iph/gesture_in_product_help_view.mm +++ b/ios/chrome/browser/ui/bubble/gesture_iph/gesture_in_product_help_view.mm
@@ -220,14 +220,20 @@ // Number of times the animation has already repeated. int _currentAnimationRepeatCount; + + // If `YES`, a static view, instead of an animation, would be displayed and + // auto-dismissed on timeout. + BOOL _reduceMotion; } - (instancetype)initWithText:(NSString*)text bubbleBoundingSize:(CGSize)bubbleBoundingSize - arrowDirection:(BubbleArrowDirection)direction { + arrowDirection:(BubbleArrowDirection)direction + voiceOverAnnouncement:(NSString*)voiceOverAnnouncement { if (self = [super initWithFrame:CGRectZero]) { - self.isAccessibilityElement = YES; - _text = text; + _text = UIAccessibilityIsVoiceOverRunning() && voiceOverAnnouncement + ? voiceOverAnnouncement + : text; _needsRepositionBubbleAndGestureIndicator = NO; _currentAnimationRepeatCount = 0; _dismissCallback = ^(IPHDismissalReasonType reason, @@ -235,6 +241,10 @@ }; _animationRepeatCount = 3; _bidirectional = NO; + _reduceMotion = UIAccessibilityIsReduceMotionEnabled() || + UIAccessibilityIsVoiceOverRunning(); + self.isAccessibilityElement = YES; + self.accessibilityViewIsModal = YES; // Background view. UIView* backgroundView = [[UIView alloc] initWithFrame:CGRectZero]; @@ -262,18 +272,33 @@ ]; [NSLayoutConstraint activateConstraints:_gestureIndicatorSizeConstraints]; - // Dismiss button. - __weak GestureInProductHelpView* weakSelf = self; - UIAction* dismissButtonAction = [UIAction actionWithHandler:^(UIAction* _) { - [weakSelf dismissWithReason:IPHDismissalReasonType::kTappedClose]; - }]; - _dismissButton = CreateDismissButton(dismissButtonAction); - [self addSubview:_dismissButton]; - [NSLayoutConstraint activateConstraints:[self dismissButtonConstraints]]; + if (!UIAccessibilityIsVoiceOverRunning()) { + // Dismiss button. It will be untappable in voice over mode, so only show + // it to non-voiceOver users. VoiceOver users are able to dismiss the + // view by swiping to the next accessibility element, and therefore don't + // need the button. + __weak GestureInProductHelpView* weakSelf = self; + UIAction* dismissButtonAction = + [UIAction actionWithHandler:^(UIAction* _) { + [weakSelf dismissWithReason:IPHDismissalReasonType::kTappedClose]; + }]; + _dismissButton = CreateDismissButton(dismissButtonAction); + [self addSubview:_dismissButton]; + [NSLayoutConstraint activateConstraints:[self dismissButtonConstraints]]; + } } return self; } +- (instancetype)initWithText:(NSString*)text + bubbleBoundingSize:(CGSize)bubbleBoundingSize + arrowDirection:(BubbleArrowDirection)direction { + return [self initWithText:text + bubbleBoundingSize:bubbleBoundingSize + arrowDirection:direction + voiceOverAnnouncement:nil]; +} + - (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize { // Computes the smallest possible size that would fit all the UI elements in // all their animated positions. @@ -281,7 +306,7 @@ CGFloat min_height = _bubbleView.frame.size.height + [_dismissButton intrinsicContentSize].height + kDismissButtonMargin; - if (UIAccessibilityIsReduceMotionEnabled()) { + if (_reduceMotion) { return CGSizeMake(min_width, min_height); } switch (_bubbleView.direction) { @@ -339,10 +364,22 @@ - (void)startAnimationAfterDelay:(base::TimeDelta)delay { CHECK(self.superview); CHECK_GT(self.animationRepeatCount, 0); - __weak GestureInProductHelpView* weakSelf = self; + if (UIAccessibilityIsVoiceOverRunning()) { + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, + _text); + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector + (handleUIAccessibilityAnnouncementDidFinishNotification:) + name:UIAccessibilityAnnouncementDidFinishNotification + object:nil]; + } + + __weak GestureInProductHelpView* weakSelf = self; if (UIAccessibilityIsReduceMotionEnabled()) { - // Dismiss after the same timeout as with animation enabled. + // Dismiss after the same timeout as with animation enabled, or when + // voiceover stops. base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( FROM_HERE, base::BindOnce(^{ [weakSelf dismissWithReason:IPHDismissalReasonType::kTimedOut]; @@ -477,6 +514,11 @@ } } +- (void)handleUIAccessibilityAnnouncementDidFinishNotification: + (NSNotification*)notification { + [self dismissWithReason:IPHDismissalReasonType::kVoiceOverAnnouncementEnded]; +} + #pragma mark - Initial positioning helpers // Initial bubble setup and positioning. @@ -489,8 +531,7 @@ _bubbleView.overrideUserInterfaceStyle = UIUserInterfaceStyleLight; _bubbleView.accessibilityIdentifier = kGestureInProductHelpViewBubbleAXId; [self addSubview:_bubbleView]; - [_bubbleView setArrowHidden:!UIAccessibilityIsReduceMotionEnabled() - animated:NO]; + [_bubbleView setArrowHidden:!_reduceMotion animated:NO]; } // Initial distance between the bubble and the center of the gesture indicator
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.h index e32b06b..1687349 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.h
@@ -23,11 +23,11 @@ kCompactedSetUpList = 5, kSetUpListAllSet = 6, kSafetyCheck = 7, - kSafetyCheckMultiRow = 8, - kSafetyCheckMultiRowOverflow = 9, + // Removed: kSafetyCheckMultiRow = 8, + // Removed: kSafetyCheckMultiRowOverflow = 9, kTabResumption = 10, kParcelTracking = 11, - kParcelTrackingSeeMore = 12, + // Removed: kParcelTrackingSeeMore = 12, kSetUpListNotifications = 13, kPlaceholder = 14, kMaxValue = kPlaceholder,
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.mm index 3f0ecb7..6d27955 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.mm
@@ -65,10 +65,7 @@ switch (type) { case ContentSuggestionsModuleType::kTabResumption: case ContentSuggestionsModuleType::kSafetyCheck: - case ContentSuggestionsModuleType::kSafetyCheckMultiRow: - case ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow: case ContentSuggestionsModuleType::kParcelTracking: - case ContentSuggestionsModuleType::kParcelTrackingSeeMore: case ContentSuggestionsModuleType::kMostVisited: case ContentSuggestionsModuleType::kShortcuts: case ContentSuggestionsModuleType::kPlaceholder:
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm index d095eb9..7809fcb 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -414,8 +414,6 @@ [self.contentSuggestionsMediator disableTabResumption]; break; case ContentSuggestionsModuleType::kSafetyCheck: - case ContentSuggestionsModuleType::kSafetyCheckMultiRow: - case ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow: [self.contentSuggestionsMediator disableSafetyCheck:type]; break; case ContentSuggestionsModuleType::kSetUpListSync: @@ -425,8 +423,7 @@ case ContentSuggestionsModuleType::kCompactedSetUpList: [self.contentSuggestionsMediator disableSetUpList]; break; - case ContentSuggestionsModuleType::kParcelTracking: - case ContentSuggestionsModuleType::kParcelTrackingSeeMore: { + case ContentSuggestionsModuleType::kParcelTracking: { [self presentParcelTrackingAlertCoordinator]; break; }
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm index a2ae19a..fc06fa08 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm
@@ -329,8 +329,7 @@ for (NSUInteger index = 0; index < [_latestMagicStackOrder count]; index++) { ContentSuggestionsModuleType type = (ContentSuggestionsModuleType)[_latestMagicStackOrder[index] intValue]; - if (type == ContentSuggestionsModuleType::kParcelTracking || - type == ContentSuggestionsModuleType::kParcelTrackingSeeMore) { + if (type == ContentSuggestionsModuleType::kParcelTracking) { MagicStackOrderChange change{MagicStackOrderChange::Type::kInsert}; change.new_module = type; change.index = index; @@ -346,8 +345,7 @@ for (NSUInteger i = 0; i < [_latestMagicStackOrder count]; i++) { ContentSuggestionsModuleType type = (ContentSuggestionsModuleType)[_latestMagicStackOrder[i] intValue]; - if (type == ContentSuggestionsModuleType::kParcelTracking || - type == ContentSuggestionsModuleType::kParcelTrackingSeeMore) { + if (type == ContentSuggestionsModuleType::kParcelTracking) { MagicStackOrderChange change{MagicStackOrderChange::Type::kRemove}; change.old_module = type; change.index = [self indexForMagicStackModule:type]; @@ -511,18 +509,12 @@ if (IsIOSParcelTrackingEnabled() && !IsParcelTrackingDisabled(GetApplicationContext()->GetLocalState())) { - if ([[self parcelTrackingItems] firstObject].shouldShowSeeMore) { - [magicStackModules - addObject:@(int( - ContentSuggestionsModuleType::kParcelTrackingSeeMore))]; - } else { for (NSUInteger i = 0; i < [[self parcelTrackingItems] count]; i++) { // Magic Stack will show up to two modules to match the number of // parcels tracked. [magicStackModules addObject:@(int(ContentSuggestionsModuleType::kParcelTracking))]; } - } } return magicStackModules; @@ -561,8 +553,6 @@ [magicStackOrder addObject:moduleNumber]; break; case ContentSuggestionsModuleType::kSafetyCheck: - case ContentSuggestionsModuleType::kSafetyCheckMultiRow: - case ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow: if (!IsSafetyCheckMagicStackEnabled() || safety_check_prefs::IsSafetyCheckInMagicStackDisabled( _localState)) { @@ -581,17 +571,12 @@ if (IsIOSParcelTrackingEnabled() && !IsParcelTrackingDisabled( GetApplicationContext()->GetLocalState())) { - if ([[self parcelTrackingItems] firstObject].shouldShowSeeMore) { - [magicStackOrder addObject:@(int(ContentSuggestionsModuleType:: - kParcelTrackingSeeMore))]; - } else { for (NSUInteger i = 0; i < [[self parcelTrackingItems] count]; i++) { // Magic Stack will show up to two modules to match the number of // parcels tracked. [magicStackOrder addObject:moduleNumber]; } - } } break; default: @@ -700,18 +685,7 @@ - (void)addSafetyCheckToMagicStackOrder:(NSMutableArray*)order { CHECK(IsSafetyCheckMagicStackEnabled()); - int checkIssuesCount = - CheckIssuesCount(self.safetyCheckMediator.safetyCheckState); - - if (checkIssuesCount > 2) { - [order addObject:@(int(ContentSuggestionsModuleType:: - kSafetyCheckMultiRowOverflow))]; - } else if (checkIssuesCount > 1) { - [order - addObject:@(int(ContentSuggestionsModuleType::kSafetyCheckMultiRow))]; - } else { [order addObject:@(int(ContentSuggestionsModuleType::kSafetyCheck))]; - } } // Returns YES if the conditions are right to display the Set Up List.
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recorder.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recorder.mm index ab21fe1f..62bc10f1 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recorder.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recorder.mm
@@ -74,9 +74,7 @@ break; } - case ContentSuggestionsModuleType::kSafetyCheck: - case ContentSuggestionsModuleType::kSafetyCheckMultiRow: - case ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow: { + case ContentSuggestionsModuleType::kSafetyCheck: { // Increment freshness pref since it is an impression of // the latest Safety Check results as the top module. int freshness_impression_count = _localState->GetInteger( @@ -99,8 +97,7 @@ freshness_impression_count + 1); break; } - case ContentSuggestionsModuleType::kParcelTracking: - case ContentSuggestionsModuleType::kParcelTrackingSeeMore: { + case ContentSuggestionsModuleType::kParcelTracking: { // Increment freshness pref since it is an impression of // the latest Tab Resumption results as the top module. int freshness_impression_count = _localState->GetInteger( @@ -140,8 +137,6 @@ kMaxModuleEngagementIndex); break; case ContentSuggestionsModuleType::kSafetyCheck: - case ContentSuggestionsModuleType::kSafetyCheckMultiRow: - case ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow: UMA_HISTOGRAM_EXACT_LINEAR( kMagicStackModuleEngagementSafetyCheckIndexHistogram, index, kMaxModuleEngagementIndex); @@ -152,7 +147,6 @@ kMaxModuleEngagementIndex); break; case ContentSuggestionsModuleType::kParcelTracking: - case ContentSuggestionsModuleType::kParcelTrackingSeeMore: UMA_HISTOGRAM_EXACT_LINEAR( kMagicStackModuleEngagementParcelTrackingIndexHistogram, index, kMaxModuleEngagementIndex);
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm index 7fbcffb8..b80a779c 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -752,14 +752,14 @@ SetUpListItemViewData* allSetData = [[SetUpListItemViewData alloc] initWithType:SetUpListItemType::kAllSet complete:NO]; - allSetData.heroCellMagicStackLayout = - !set_up_list_utils::ShouldShowCompactedSetUpListModule(); - SetUpListItemView* view = - [[SetUpListItemView alloc] initWithData:allSetData]; - MagicStackModuleContainer* allSetModule = [[MagicStackModuleContainer alloc] - initWithContentView:view - type:ContentSuggestionsModuleType::kSetUpListAllSet - delegate:self]; + allSetData.compactLayout = NO; + allSetData.heroCellMagicStackLayout = YES; + + SetUpListConfig* config = [[SetUpListConfig alloc] init]; + config.setUpListItems = @[ allSetData ]; + MagicStackModuleContainer* allSetModule = + [[MagicStackModuleContainer alloc] init]; + [allSetModule configureWithConfig:config]; // Determine which module to swap out. [self removeSetUpListItemsWithNewModule:allSetModule]; return; @@ -794,9 +794,7 @@ ContentSuggestionsModuleType type = (ContentSuggestionsModuleType)[moduleValue intValue]; - if (type == ContentSuggestionsModuleType::kSafetyCheck || - type == ContentSuggestionsModuleType::kSafetyCheckMultiRow || - type == ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow) { + if (type == ContentSuggestionsModuleType::kSafetyCheck) { safetyCheckModuleOrderIndex = idx; *stop = YES; @@ -979,13 +977,13 @@ - (void)seeMoreWasTappedForModuleType:(ContentSuggestionsModuleType)type { switch (type) { - case ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow: + case ContentSuggestionsModuleType::kSafetyCheck: [self.audience didSelectSafetyCheckItem:SafetyCheckItemType::kDefault]; break; case ContentSuggestionsModuleType::kCompactedSetUpList: [self.audience showSetUpListShowMoreMenu]; break; - case ContentSuggestionsModuleType::kParcelTrackingSeeMore: + case ContentSuggestionsModuleType::kParcelTracking: [self.audience showMagicStackParcelList]; break; default: @@ -1001,16 +999,6 @@ [self.audience enableNotifications:type]; } -// Returns the module's subtitle, if any, given the Magic Stack module `type`. -- (NSString*)subtitleStringForModule:(ContentSuggestionsModuleType)type { - if (type == ContentSuggestionsModuleType::kSafetyCheck || - type == ContentSuggestionsModuleType::kSafetyCheckMultiRow) { - return FormatElapsedTimeSinceLastSafetyCheck(_safetyCheckState.lastRunTime); - } - - return @""; -} - #pragma mark - Private // Returns whether the Magic Stack has been constructed and has already been @@ -1228,16 +1216,13 @@ moduleContainer = _setUpListAllSetModule; break; } - case ContentSuggestionsModuleType::kSafetyCheck: - case ContentSuggestionsModuleType::kSafetyCheckMultiRow: - case ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow: { + case ContentSuggestionsModuleType::kSafetyCheck: { if (IsSafetyCheckMagicStackEnabled()) { moduleContainer = self.safetyCheckModuleContainer; } break; } case ContentSuggestionsModuleType::kParcelTracking: - case ContentSuggestionsModuleType::kParcelTrackingSeeMore: if (IsIOSParcelTrackingEnabled()) { for (MagicStackModuleContainer* parcelModule in _parcelTrackingModuleContainers) {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_unittest.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_unittest.mm index b76d25cc..b8bb9ae 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_unittest.mm
@@ -316,8 +316,7 @@ } // Tests that the Safety Check module (of type `kSafetyCheck`) correctly -// replaces itself at the index of an existing Safety Check module of different -// type (`kSafetyCheckMultiRow`), if it exists. +// replaces itself at the index of an existing Safety Check module. TEST_F(ContentSuggestionsViewControllerTest, TestReplaceSafetyCheckMultiRowWithSafetyCheck) { scoped_feature_list_.Reset(); @@ -329,7 +328,7 @@ [view_controller_ setMagicStackOrder:@[ @(int(ContentSuggestionsModuleType::kMostVisited)), @(int(ContentSuggestionsModuleType::kShortcuts)), - @(int(ContentSuggestionsModuleType::kSafetyCheckMultiRow)), + @(int(ContentSuggestionsModuleType::kSafetyCheck)), ]]; [view_controller_ setShortcutTilesConfig:ShortcutsConfigWithBookmark()]; @@ -368,8 +367,7 @@ MagicStackModuleContainer* safetyCheckModule = (MagicStackModuleContainer*)subviews[2]; - EXPECT_EQ(ContentSuggestionsModuleType::kSafetyCheckMultiRow, - safetyCheckModule.type); + EXPECT_EQ(ContentSuggestionsModuleType::kSafetyCheck, safetyCheckModule.type); SafetyCheckState* defaultSafetyCheckState = [[SafetyCheckState alloc] initWithUpdateChromeState:UpdateChromeSafetyCheckState::kDefault @@ -517,42 +515,3 @@ EXPECT_EQ(ContentSuggestionsModuleType::kParcelTracking, parcelTrackingModule.type); } - -// Tests the Safety Check module correctly displays when the existing module -// state and current module state differ ([a] multi-row to [b] single-row -// state). -TEST_F(ContentSuggestionsViewControllerTest, TestFooBar) { - scoped_feature_list_.Reset(); - scoped_feature_list_.InitWithFeatures({kMagicStack, kSafetyCheckMagicStack}, - {}); - - // Trigger viewDidLoad. - [view_controller_ loadViewIfNeeded]; - - [view_controller_ setMagicStackOrder:@[ - @(int(ContentSuggestionsModuleType::kSafetyCheckMultiRow)), - ]]; - - // Single-row Safety Check state. - SafetyCheckState* safetyCheckState = [[SafetyCheckState alloc] - initWithUpdateChromeState:UpdateChromeSafetyCheckState::kUpToDate - passwordState:PasswordSafetyCheckState::kSafe - safeBrowsingState:SafeBrowsingSafetyCheckState::kSafe - runningState:RunningSafetyCheckState::kDefault]; - - [view_controller_ showSafetyCheck:safetyCheckState]; - - UIStackView* magicStack = FindMagicStack(); - - // Assert order is correct. - NSArray<UIView*>* subviews = magicStack.arrangedSubviews; - - // One module should exist. - ASSERT_EQ(1u, [subviews count]); - - MagicStackModuleContainer* safetyCheckModule = - (MagicStackModuleContainer*)subviews[0]; - - // Should be kSafetyCheck now, instead of kSafetyCheckMultiRow. - EXPECT_EQ(ContentSuggestionsModuleType::kSafetyCheck, safetyCheckModule.type); -}
diff --git a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container.h b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container.h index f341cccc..6c4f8ee 100644 --- a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container.h +++ b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container.h
@@ -14,13 +14,6 @@ // Container View for a module in the Magic Stack. @interface MagicStackModuleContainer : UIView -// Initialize and configure with `contentView` for `type`. DEPRECATED: Please -// use -initWithFrame: and -configureWithConfig: if adding a module before -// UICollectionView migration is complete. -- (instancetype)initWithContentView:(UIView*)contentView - type:(ContentSuggestionsModuleType)type - delegate: - (id<MagicStackModuleContainerDelegate>)delegate; - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; // Configures this container with `config`.
diff --git a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container.mm b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container.mm index e5195eb..8efae4c5 100644 --- a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container.mm +++ b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container.mm
@@ -17,6 +17,8 @@ #import "ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container_delegate.h" #import "ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_contents_factory.h" #import "ios/chrome/browser/ui/content_suggestions/magic_stack/most_visited_tiles_config.h" +#import "ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_state.h" +#import "ios/chrome/browser/ui/content_suggestions/safety_check/utils.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" #import "ios/chrome/common/ui/util/constraints_ui_util.h" #import "ios/chrome/common/ui/util/ui_util.h" @@ -70,6 +72,7 @@ UIStackView* _titleStackView; MagicStackModuleContentsFactory* _magicStackModuleContentsFactory; NSLayoutConstraint* _containerHeightAnchor; + NSLayoutConstraint* _contentStackViewBottomMarginAnchor; } - (instancetype)initWithFrame:(CGRect)frame { @@ -190,60 +193,16 @@ [NSLayoutConstraint activateConstraints:@[ _containerHeightAnchor ]]; [self addSubview:_stackView]; - AddSameConstraintsWithInsets(_stackView, self, [self contentMargins]); - } - return self; -} - -- (instancetype)initWithContentView:(UIView*)contentView - type:(ContentSuggestionsModuleType)type - delegate: - (id<MagicStackModuleContainerDelegate>)delegate { - if (self = [self initWithFrame:CGRectZero]) { - _type = type; - _delegate = delegate; - if ([self allowsLongPress]) { - [self addInteraction:[[UIContextMenuInteraction alloc] - initWithDelegate:self]]; - } - - _title.text = [MagicStackModuleContainer titleStringForModule:_type]; - _title.accessibilityIdentifier = - [MagicStackModuleContainer accessibilityIdentifierForModule:_type]; - - _seeMoreButton.hidden = ![self shouldShowSeeMore]; - - if ([self shouldShowSubtitle]) { - // TODO(crbug.com/1474992): Update MagicStackModuleContainer to take an id - // config in its initializer so the container can build itself from a - // passed config/state object. - NSString* subtitle = [_delegate subtitleStringForModule:_type]; - _subtitle.text = subtitle; - _subtitle.accessibilityIdentifier = subtitle; - } - - _title.hidden = [_title.text length] == 0; - - _separator.hidden = ![self shouldShowSeparator]; - - _contentView = contentView; - [_stackView addArrangedSubview:_contentView]; - - // Configures `contentView` to be the view willing to expand if needed to - // fill extra vertical space in the container. - [_contentView - setContentCompressionResistancePriority:UILayoutPriorityDefaultLow - forAxis:UILayoutConstraintAxisVertical]; - - NSMutableArray* accessibilityElements = - [[NSMutableArray alloc] initWithObjects:_title, nil]; - if ([self shouldShowSeeMore]) { - [accessibilityElements addObject:_seeMoreButton]; - } else if ([self shouldShowSubtitle]) { - [accessibilityElements addObject:_subtitle]; - } - [accessibilityElements addObject:_contentView]; - self.accessibilityElements = accessibilityElements; + AddSameConstraintsToSidesWithInsets( + _stackView, self, + (LayoutSides::kTop | LayoutSides::kLeading | LayoutSides::kTrailing), + NSDirectionalEdgeInsetsMake(kContentTopInset, kContentHorizontalInset, + 0, kContentHorizontalInset)); + _contentStackViewBottomMarginAnchor = + [_stackView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor + constant:-kContentBottomInset]; + [NSLayoutConstraint + activateConstraints:@[ _contentStackViewBottomMarginAnchor ]]; } return self; } @@ -288,7 +247,7 @@ // TODO(crbug.com/1474992): Update MagicStackModuleContainer to take an id // config in its initializer so the container can build itself from a // passed config/state object. - NSString* subtitle = [_delegate subtitleStringForModule:_type]; + NSString* subtitle = [self subtitleStringForConfig:config]; _subtitle.text = subtitle; _subtitle.accessibilityIdentifier = subtitle; } @@ -308,9 +267,11 @@ setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisVertical]; + [self updateBottomContentMarginsForConfig:config]; + NSMutableArray* accessibilityElements = [[NSMutableArray alloc] initWithObjects:_title, nil]; - if ([self shouldShowSeeMore]) { + if (config.shouldShowSeeMore) { [accessibilityElements addObject:_seeMoreButton]; } else if ([self shouldShowSubtitle]) { [accessibilityElements addObject:_subtitle]; @@ -341,11 +302,8 @@ case ContentSuggestionsModuleType::kSetUpListNotifications: return content_suggestions::SetUpListTitleString(); case ContentSuggestionsModuleType::kSafetyCheck: - case ContentSuggestionsModuleType::kSafetyCheckMultiRow: - case ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow: return l10n_util::GetNSString(IDS_IOS_SAFETY_CHECK_TITLE); case ContentSuggestionsModuleType::kParcelTracking: - case ContentSuggestionsModuleType::kParcelTrackingSeeMore: return l10n_util::GetNSString( IDS_IOS_CONTENT_SUGGESTIONS_PARCEL_TRACKING_MODULE_TITLE); default: @@ -378,22 +336,27 @@ return CreateDynamicFont(UIFontTextStyleFootnote, UIFontWeightRegular); } -// Returns the content insets. -- (NSDirectionalEdgeInsets)contentMargins { - NSDirectionalEdgeInsets contentMargins = - NSDirectionalEdgeInsetsMake(kContentTopInset, kContentHorizontalInset, - kContentBottomInset, kContentHorizontalInset); - switch (_type) { +// Updates the bottom content margins if the module contents need it. +- (void)updateBottomContentMarginsForConfig:(MagicStackModule*)config { + switch (config.type) { case ContentSuggestionsModuleType::kMostVisited: case ContentSuggestionsModuleType::kShortcuts: - case ContentSuggestionsModuleType::kSafetyCheckMultiRow: - case ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow: - contentMargins.bottom = kReducedContentBottomInset; + _contentStackViewBottomMarginAnchor.constant = + -kReducedContentBottomInset; break; + case ContentSuggestionsModuleType::kSafetyCheck: { + SafetyCheckState* safetyCheckConfig = + static_cast<SafetyCheckState*>(config); + if ([safetyCheckConfig numberOfIssues] > 1) { + _contentStackViewBottomMarginAnchor.constant = + -kReducedContentBottomInset; + } + break; + } + default: break; } - return contentMargins; } #pragma mark - UITraitEnvironment @@ -476,15 +439,12 @@ switch (_type) { case ContentSuggestionsModuleType::kTabResumption: case ContentSuggestionsModuleType::kSafetyCheck: - case ContentSuggestionsModuleType::kSafetyCheckMultiRow: - case ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow: case ContentSuggestionsModuleType::kSetUpListSync: case ContentSuggestionsModuleType::kSetUpListDefaultBrowser: case ContentSuggestionsModuleType::kSetUpListAutofill: case ContentSuggestionsModuleType::kSetUpListNotifications: case ContentSuggestionsModuleType::kCompactedSetUpList: case ContentSuggestionsModuleType::kParcelTracking: - case ContentSuggestionsModuleType::kParcelTrackingSeeMore: return YES; default: return NO; @@ -496,24 +456,21 @@ - (BOOL)shouldShowSubtitle { switch (_type) { case ContentSuggestionsModuleType::kSafetyCheck: - case ContentSuggestionsModuleType::kSafetyCheckMultiRow: return YES; default: return NO; } } -// Based on ContentSuggestionsModuleType, returns YES if a "See More" button -// should be displayed in the module. -- (BOOL)shouldShowSeeMore { - switch (_type) { - case ContentSuggestionsModuleType::kCompactedSetUpList: - case ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow: - case ContentSuggestionsModuleType::kParcelTrackingSeeMore: - return YES; - default: - return NO; +// Returns the module's subtitle, if any, given the Magic Stack module `type`. +- (NSString*)subtitleStringForConfig:(MagicStackModule*)config { + if (config.type == ContentSuggestionsModuleType::kSafetyCheck) { + SafetyCheckState* safetyCheckConfig = + static_cast<SafetyCheckState*>(config); + return FormatElapsedTimeSinceLastSafetyCheck(safetyCheckConfig.lastRunTime); } + + return @""; } // Based on ContentSuggestionsModuleType, returns YES if a separator should be @@ -540,8 +497,6 @@ case ContentSuggestionsModuleType::kTabResumption: return l10n_util::GetNSString(IDS_IOS_TAB_RESUMPTION_CONTEXT_MENU_TITLE); case ContentSuggestionsModuleType::kSafetyCheck: - case ContentSuggestionsModuleType::kSafetyCheckMultiRow: - case ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow: return l10n_util::GetNSString(IDS_IOS_SAFETY_CHECK_CONTEXT_MENU_TITLE); case ContentSuggestionsModuleType::kSetUpListSync: case ContentSuggestionsModuleType::kSetUpListDefaultBrowser: @@ -551,7 +506,6 @@ return l10n_util::GetNSString( IDS_IOS_SET_UP_LIST_HIDE_MODULE_CONTEXT_MENU_TITLE); case ContentSuggestionsModuleType::kParcelTracking: - case ContentSuggestionsModuleType::kParcelTrackingSeeMore: return l10n_util::GetNSString(IDS_IOS_PARCEL_TRACKING_CONTEXT_MENU_TITLE); default: NOTREACHED_NORETURN(); @@ -565,8 +519,6 @@ return l10n_util::GetNSString( IDS_IOS_TAB_RESUMPTION_CONTEXT_MENU_DESCRIPTION); case ContentSuggestionsModuleType::kSafetyCheck: - case ContentSuggestionsModuleType::kSafetyCheckMultiRow: - case ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow: return l10n_util::GetNSString( IDS_IOS_SAFETY_CHECK_CONTEXT_MENU_DESCRIPTION); case ContentSuggestionsModuleType::kSetUpListSync: @@ -579,7 +531,6 @@ l10n_util::GetStringUTF16( content_suggestions::SetUpListTitleStringID())); case ContentSuggestionsModuleType::kParcelTracking: - case ContentSuggestionsModuleType::kParcelTrackingSeeMore: return l10n_util::GetNSStringF( IDS_IOS_PARCEL_TRACKING_CONTEXT_MENU_DESCRIPTION, base::SysNSStringToUTF16(l10n_util::GetNSString(
diff --git a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container_delegate.h b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container_delegate.h index d63780b1..fdcd158 100644 --- a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container_delegate.h +++ b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container_delegate.h
@@ -28,9 +28,6 @@ // notifications. - (void)enableNotifications:(ContentSuggestionsModuleType)type; -// Returns the subtitle string for the module `type`. -- (NSString*)subtitleStringForModule:(ContentSuggestionsModuleType)type; - @end #endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CELLS_MAGIC_STACK_MODULE_CONTAINER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_contents_factory.mm b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_contents_factory.mm index 69ac6339..29514fa0 100644 --- a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_contents_factory.mm +++ b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_contents_factory.mm
@@ -58,15 +58,12 @@ static_cast<TabResumptionItem*>(config); return [self tabResumptionViewForConfig:tabResumptionItem]; } - case ContentSuggestionsModuleType::kParcelTracking: - case ContentSuggestionsModuleType::kParcelTrackingSeeMore: { + case ContentSuggestionsModuleType::kParcelTracking: { ParcelTrackingItem* parcelTrackingItem = static_cast<ParcelTrackingItem*>(config); return [self parcelTrackingViewForConfig:parcelTrackingItem]; } - case ContentSuggestionsModuleType::kSafetyCheck: - case ContentSuggestionsModuleType::kSafetyCheckMultiRow: - case ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow: { + case ContentSuggestionsModuleType::kSafetyCheck: { SafetyCheckState* safetyCheckConfig = static_cast<SafetyCheckState*>(config); return [self safetyCheckViewForConfigState:safetyCheckConfig];
diff --git a/ios/chrome/browser/ui/content_suggestions/parcel_tracking/parcel_tracking_item.mm b/ios/chrome/browser/ui/content_suggestions/parcel_tracking/parcel_tracking_item.mm index 49484a8c..54c5574 100644 --- a/ios/chrome/browser/ui/content_suggestions/parcel_tracking/parcel_tracking_item.mm +++ b/ios/chrome/browser/ui/content_suggestions/parcel_tracking/parcel_tracking_item.mm
@@ -13,9 +13,6 @@ #pragma mark - MagicStackModule - (ContentSuggestionsModuleType)type { - if (self.shouldShowSeeMore) { - return ContentSuggestionsModuleType::kParcelTrackingSeeMore; - } return ContentSuggestionsModuleType::kParcelTracking; }
diff --git a/ios/chrome/browser/ui/content_suggestions/parcel_tracking/parcel_tracking_mediator.mm b/ios/chrome/browser/ui/content_suggestions/parcel_tracking/parcel_tracking_mediator.mm index 35f7a3c1..b69aa43f 100644 --- a/ios/chrome/browser/ui/content_suggestions/parcel_tracking/parcel_tracking_mediator.mm +++ b/ios/chrome/browser/ui/content_suggestions/parcel_tracking/parcel_tracking_mediator.mm
@@ -103,11 +103,8 @@ - (void)loadParcelTrackingPage:(GURL)parcelTrackingURL { [self.NTPMetricsDelegate parcelTrackingOpened]; - ContentSuggestionsModuleType type = - [_parcelTrackingItems count] > 2 - ? ContentSuggestionsModuleType::kParcelTrackingSeeMore - : ContentSuggestionsModuleType::kParcelTracking; - [self.delegate logMagicStackEngagementForType:type]; + [self.delegate logMagicStackEngagementForType:ContentSuggestionsModuleType:: + kParcelTracking]; _URLLoadingBrowserAgent->Load(UrlLoadParams::InCurrentTab(parcelTrackingURL)); }
diff --git a/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_magic_stack_mediator.mm b/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_magic_stack_mediator.mm index 1a456ae..c7998438 100644 --- a/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_magic_stack_mediator.mm +++ b/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_magic_stack_mediator.mm
@@ -136,7 +136,7 @@ - (void)runningStateChanged:(RunningSafetyCheckState)state { _safetyCheckState.runningState = state; - _safetyCheckState.shouldShowSeeMore = CheckIssuesCount(_safetyCheckState) > 2; + _safetyCheckState.shouldShowSeeMore = [_safetyCheckState numberOfIssues] > 2; if (safety_check_prefs::IsSafetyCheckInMagicStackDisabled(_localState)) { // Safety Check can be disabled by long-pressing the module, so
diff --git a/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_state.h b/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_state.h index d641f478..c4b0883 100644 --- a/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_state.h +++ b/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_state.h
@@ -29,6 +29,9 @@ safeBrowsingState:(SafeBrowsingSafetyCheckState)safeBrowsingState runningState:(RunningSafetyCheckState)runningState; +// Returns the number of check issues found. +- (NSUInteger)numberOfIssues; + // The current state of the Update Chrome check. @property(nonatomic, readwrite) UpdateChromeSafetyCheckState updateChromeState;
diff --git a/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_state.mm b/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_state.mm index faa07d2..5d17793b 100644 --- a/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_state.mm +++ b/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_state.mm
@@ -25,15 +25,26 @@ return self; } +#pragma mark - Public + +- (NSUInteger)numberOfIssues { + NSUInteger invalidCheckCount = 0; + if (InvalidUpdateChromeState(_updateChromeState)) { + invalidCheckCount++; + } + if (InvalidPasswordState(_passwordState)) { + invalidCheckCount++; + } + if (InvalidSafeBrowsingState(_safeBrowsingState)) { + invalidCheckCount++; + } + + return invalidCheckCount; +} + #pragma mark - MagicStackModule - (ContentSuggestionsModuleType)type { - int issues = CheckIssuesCount(self); - if (issues > 2) { - return ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow; - } else if (issues == 2) { - return ContentSuggestionsModuleType::kSafetyCheckMultiRow; - } return ContentSuggestionsModuleType::kSafetyCheck; }
diff --git a/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_view.mm b/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_view.mm index dbc85f9..1231dea 100644 --- a/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_view.mm +++ b/ios/chrome/browser/ui/content_suggestions/safety_check/safety_check_view.mm
@@ -95,7 +95,7 @@ return; } - int checkIssuesCount = CheckIssuesCount(_state); + int checkIssuesCount = [_state numberOfIssues]; // Show the "All Safe" state if there are no check issues. if (checkIssuesCount == 0) {
diff --git a/ios/chrome/browser/ui/content_suggestions/safety_check/utils.h b/ios/chrome/browser/ui/content_suggestions/safety_check/utils.h index e6a6b61..be6a5d9 100644 --- a/ios/chrome/browser/ui/content_suggestions/safety_check/utils.h +++ b/ios/chrome/browser/ui/content_suggestions/safety_check/utils.h
@@ -46,9 +46,6 @@ // check in the Safety Check (Magic Stack) module. bool InvalidSafeBrowsingState(SafeBrowsingSafetyCheckState state); -// Returns the number of check issues found given `state`. -int CheckIssuesCount(SafetyCheckState* state); - // Returns true if the Safety Check can be run given `last_run_time`. bool CanRunSafetyCheck(std::optional<base::Time> last_run_time);
diff --git a/ios/chrome/browser/ui/content_suggestions/safety_check/utils.mm b/ios/chrome/browser/ui/content_suggestions/safety_check/utils.mm index 5518cd8c..b53c2cd5 100644 --- a/ios/chrome/browser/ui/content_suggestions/safety_check/utils.mm +++ b/ios/chrome/browser/ui/content_suggestions/safety_check/utils.mm
@@ -137,24 +137,6 @@ return state == SafeBrowsingSafetyCheckState::kUnsafe; } -int CheckIssuesCount(SafetyCheckState* state) { - int invalid_check_count = 0; - - if (InvalidUpdateChromeState(state.updateChromeState)) { - invalid_check_count++; - } - - if (InvalidPasswordState(state.passwordState)) { - invalid_check_count++; - } - - if (InvalidSafeBrowsingState(state.safeBrowsingState)) { - invalid_check_count++; - } - - return invalid_check_count; -} - bool CanRunSafetyCheck(std::optional<base::Time> last_run_time) { // The Safety Check should be run if it's never been run before. if (!last_run_time.has_value()) {
diff --git a/ios/chrome/browser/ui/default_promo/promo_handler/default_browser_promo_manager_unittest.mm b/ios/chrome/browser/ui/default_promo/promo_handler/default_browser_promo_manager_unittest.mm index 209bc5b..5d5f47e2 100644 --- a/ios/chrome/browser/ui/default_promo/promo_handler/default_browser_promo_manager_unittest.mm +++ b/ios/chrome/browser/ui/default_promo/promo_handler/default_browser_promo_manager_unittest.mm
@@ -131,6 +131,7 @@ // Tests that the DefaultPromoTypeGeneral promo is shown when it was detected // that the user is likely interested in the promo. TEST_F(DefaultBrowserPromoManagerTest, showDefaultBrowserFullscreenPromo) { + feature_list_.InitWithFeatures({}, {kDefaultBrowserVideoPromo}); TestingApplicationContext::GetGlobal()->SetLastShutdownClean(true); id mock = [OCMockObject mockForClass:[DefaultBrowserPromoManager class]]; LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeGeneral); @@ -145,7 +146,7 @@ TEST_F(DefaultBrowserPromoManagerTest, showDefaultBrowserFullscreenPromo_TriggerExpEnabled) { feature_list_.InitWithFeatures({kDefaultBrowserTriggerCriteriaExperiment}, - {}); + {kDefaultBrowserVideoPromo}); TestingApplicationContext::GetGlobal()->SetLastShutdownClean(true); id mock = [OCMockObject mockForClass:[DefaultBrowserPromoManager class]]; @@ -158,4 +159,18 @@ [default_browser_promo_manager_ start]; EXPECT_OCMOCK_VERIFY(mock); } + +// Tests that the DefaultPromoTypeVideo promo is shown instead of the generic +// promo when the video promo is enabled. +TEST_F(DefaultBrowserPromoManagerTest, showVideoPromo) { + feature_list_.InitWithFeatures({kDefaultBrowserVideoPromo}, {}); + TestingApplicationContext::GetGlobal()->SetLastShutdownClean(true); + id mock = [OCMockObject mockForClass:[DefaultBrowserPromoManager class]]; + LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeGeneral); + SignIn(); + [[mock expect] showPromoForTesting:DefaultPromoTypeVideo]; + [default_browser_promo_manager_ start]; + EXPECT_OCMOCK_VERIFY(mock); +} + } // namespace
diff --git a/ios/chrome/browser/ui/ntp/metrics/BUILD.gn b/ios/chrome/browser/ui/ntp/metrics/BUILD.gn index 7e045e4..46bbfee 100644 --- a/ios/chrome/browser/ui/ntp/metrics/BUILD.gn +++ b/ios/chrome/browser/ui/ntp/metrics/BUILD.gn
@@ -18,7 +18,9 @@ ":constants", "//base", "//components/favicon_base", + "//components/feed/core/common:feed_core_common", "//components/feed/core/v2/public:common", + "//components/feed/core/v2/public/ios:feed_ios_public", "//components/metrics", "//components/ntp_tiles", "//components/prefs",
diff --git a/ios/chrome/browser/ui/ntp/metrics/DEPS b/ios/chrome/browser/ui/ntp/metrics/DEPS new file mode 100644 index 0000000..0be8573 --- /dev/null +++ b/ios/chrome/browser/ui/ntp/metrics/DEPS
@@ -0,0 +1,6 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^feed_metrics_recorder.mm": [ + "+components/feed/core/common/pref_names.h" + ], +} \ No newline at end of file
diff --git a/ios/chrome/browser/ui/ntp/metrics/feed_metrics_recorder.mm b/ios/chrome/browser/ui/ntp/metrics/feed_metrics_recorder.mm index 05b8456f..2fab5375 100644 --- a/ios/chrome/browser/ui/ntp/metrics/feed_metrics_recorder.mm +++ b/ios/chrome/browser/ui/ntp/metrics/feed_metrics_recorder.mm
@@ -12,6 +12,9 @@ #import "base/metrics/user_metrics.h" #import "base/metrics/user_metrics_action.h" #import "base/time/time.h" +#import "components/feed/core/common/pref_names.h" +#import "components/feed/core/v2/public/ios/notice_card_tracker.h" +#import "components/feed/core/v2/public/ios/prefs.h" #import "components/prefs/pref_service.h" #import "ios/chrome/browser/metrics/model/constants.h" #import "ios/chrome/browser/shared/public/features/features.h" @@ -463,6 +466,7 @@ - (void)recordNoticeCardShown:(BOOL)shown { base::UmaHistogramBoolean(kDiscoverFeedNoticeCardFulfilled, shown); + feed::prefs::SetLastFetchHadNoticeCard(*self.prefService, shown); } - (void)recordFeedArticlesFetchDurationInSeconds: @@ -557,6 +561,8 @@ - (void)recordActivityLoggingEnabled:(BOOL)loggingEnabled { base::UmaHistogramBoolean(kDiscoverFeedActivityLoggingEnabled, loggingEnabled); + self.prefService->SetBoolean(feed::prefs::kLastFetchHadLoggingEnabled, + loggingEnabled); } - (void)recordBrokenNTPHierarchy:(BrokenNTPHierarchyRelationship)relationship {
diff --git a/ios/chrome/browser/ui/ntp/metrics/home_metrics.mm b/ios/chrome/browser/ui/ntp/metrics/home_metrics.mm index 0bb1462b..bf36104 100644 --- a/ios/chrome/browser/ui/ntp/metrics/home_metrics.mm +++ b/ios/chrome/browser/ui/ntp/metrics/home_metrics.mm
@@ -32,9 +32,7 @@ base::UserMetricsAction("IOSMagicStackShortcutsFreshSignal")); break; } - case ContentSuggestionsModuleType::kSafetyCheck: - case ContentSuggestionsModuleType::kSafetyCheckMultiRow: - case ContentSuggestionsModuleType::kSafetyCheckMultiRowOverflow: { + case ContentSuggestionsModuleType::kSafetyCheck: { PrefService* local_state = GetApplicationContext()->GetLocalState(); local_state->SetInteger( prefs::kIosMagicStackSegmentationSafetyCheckImpressionsSinceFreshness,
diff --git a/ios/chrome/browser/ui/push_notification/OWNERS b/ios/chrome/browser/ui/push_notification/OWNERS new file mode 100644 index 0000000..08b5daa7 --- /dev/null +++ b/ios/chrome/browser/ui/push_notification/OWNERS
@@ -0,0 +1,2 @@ +scottyoder@google.com +hiramahmood@google.com \ No newline at end of file
diff --git a/ios/chrome/browser/ui/settings/privacy/safe_browsing/BUILD.gn b/ios/chrome/browser/ui/settings/privacy/safe_browsing/BUILD.gn index 7c8842b..c18992c 100644 --- a/ios/chrome/browser/ui/settings/privacy/safe_browsing/BUILD.gn +++ b/ios/chrome/browser/ui/settings/privacy/safe_browsing/BUILD.gn
@@ -48,6 +48,7 @@ "//ios/chrome/browser/signin/model", "//ios/chrome/browser/ui/authentication", "//ios/chrome/browser/ui/authentication/enterprise:enterprise_utils", + "//ios/chrome/browser/ui/keyboard", "//ios/chrome/browser/ui/settings:settings_root", "//ios/chrome/browser/ui/settings/cells", "//ios/chrome/browser/ui/settings/elements:enterprise_info_popover_view_controller",
diff --git a/ios/chrome/browser/ui/settings/privacy/safe_browsing/safe_browsing_enhanced_protection_view_controller.mm b/ios/chrome/browser/ui/settings/privacy/safe_browsing/safe_browsing_enhanced_protection_view_controller.mm index f4227db..908c02e 100644 --- a/ios/chrome/browser/ui/settings/privacy/safe_browsing/safe_browsing_enhanced_protection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/privacy/safe_browsing/safe_browsing_enhanced_protection_view_controller.mm
@@ -19,6 +19,7 @@ #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_cell.h" #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_text_header_footer_item.h" #import "ios/chrome/browser/shared/ui/table_view/legacy_chrome_table_view_styler.h" +#import "ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.h" #import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_item.h" #import "ios/chrome/browser/ui/settings/privacy/safe_browsing/safe_browsing_constants.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" @@ -240,6 +241,23 @@ return NO; } +#pragma mark - UIResponder + +// To always be able to register key commands via -keyCommands, the VC must be +// able to become first responder. +- (BOOL)canBecomeFirstResponder { + return YES; +} + +- (NSArray<UIKeyCommand*>*)keyCommands { + return @[ UIKeyCommand.cr_close ]; +} + +- (void)keyCommand_close { + base::RecordAction(base::UserMetricsAction("MobileKeyCommandClose")); + [self dismissViewControllerAnimated:YES completion:nil]; +} + #pragma mark - TableViewLinkHeaderFooterItemDelegate - (void)view:(TableViewLinkHeaderFooterView*)view didTapLinkURL:(CrURL*)URL {
diff --git a/ios/chrome/browser/ui/settings/privacy/safe_browsing/safe_browsing_standard_protection_view_controller.mm b/ios/chrome/browser/ui/settings/privacy/safe_browsing/safe_browsing_standard_protection_view_controller.mm index e32b45e..03bbf34 100644 --- a/ios/chrome/browser/ui/settings/privacy/safe_browsing/safe_browsing_standard_protection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/privacy/safe_browsing/safe_browsing_standard_protection_view_controller.mm
@@ -12,6 +12,7 @@ #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_cell.h" #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_cell.h" #import "ios/chrome/browser/shared/ui/table_view/legacy_chrome_table_view_styler.h" +#import "ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.h" #import "ios/chrome/browser/ui/settings/cells/safe_browsing_header_item.h" #import "ios/chrome/browser/ui/settings/elements/enterprise_info_popover_view_controller.h" #import "ios/chrome/browser/ui/settings/privacy/safe_browsing/safe_browsing_constants.h" @@ -131,6 +132,23 @@ return cell; } +#pragma mark - UIResponder + +// To always be able to register key commands via -keyCommands, the VC must be +// able to become first responder. +- (BOOL)canBecomeFirstResponder { + return YES; +} + +- (NSArray<UIKeyCommand*>*)keyCommands { + return @[ UIKeyCommand.cr_close ]; +} + +- (void)keyCommand_close { + base::RecordAction(base::UserMetricsAction("MobileKeyCommandClose")); + [self dismissViewControllerAnimated:YES completion:nil]; +} + #pragma mark - SettingsControllerProtocol - (void)reportDismissalUserAction {
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_view_controller.mm index bd6c275d..a86f626 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_view_controller.mm
@@ -46,6 +46,7 @@ #import "ios/chrome/browser/ui/tab_switcher/tab_grid/transitions/tab_grid_transition_item.h" #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_item.h" #import "ios/chrome/browser/ui/tab_switcher/tab_utils.h" +#import "ios/chrome/common/ui/colors/semantic_color_names.h" #import "ios/chrome/common/ui/util/constraints_ui_util.h" #import "ios/chrome/grit/ios_strings.h" #import "ios/public/provider/chrome/browser/modals/modals_api.h" @@ -73,6 +74,8 @@ namespace { NSString* const kSuggestedActionsSectionIdentifier = @"SuggestedActionsSectionIdentifier"; +NSString* const kGridTabGroupsSectionIdentifier = + @"GridTabGroupsSectionIdentifier"; NSString* const kCellIdentifier = @"GridCellIdentifier"; NSString* const kGroupCellIdentifier = @"GroupGridCellIdentifier"; @@ -560,6 +563,14 @@ gridHeader.value = l10n_util::GetNSStringF(IDS_IOS_TABS_SEARCH_OPEN_TABS_COUNT, base::SysNSStringToUTF16(resultsCount)); + } else if (base::FeatureList::IsEnabled(kTabGroupsInGrid) && + [sectionIdentifier + isEqualToString:kGridTabGroupsSectionIdentifier]) { + gridHeader.title = l10n_util::GetNSString( + IDS_IOS_TABS_SEARCH_TAB_GROUPS_SECTION_HEADER_TITLE); + // TODO(crbug.com/1501837): Add the right number of found tabs. + gridHeader.value = l10n_util::GetNSStringF( + IDS_IOS_TABS_SEARCH_OPEN_TABS_COUNT, base::SysNSStringToUTF16(@"0")); } else if ([sectionIdentifier isEqualToString:kSuggestedActionsSectionIdentifier]) { gridHeader.title = @@ -1080,6 +1091,11 @@ // Optional Suggested Actions section. if (self.showingSuggestedActions) { + if (base::FeatureList::IsEnabled(kTabGroupsInGrid)) { + [snapshot + appendSectionsWithIdentifiers:@[ kGridTabGroupsSectionIdentifier ]]; + } + [snapshot appendSectionsWithIdentifiers:@[ kSuggestedActionsSectionIdentifier ]]; GridItemIdentifier* itemIdentifier = @@ -1284,16 +1300,25 @@ GridSnapshot* snapshot = self.diffableDataSource.snapshot; if (self.mode == TabGridModeSearch && self.searchText.length) { if (!self.showingSuggestedActions) { + if (base::FeatureList::IsEnabled(kTabGroupsInGrid)) { + [snapshot + appendSectionsWithIdentifiers:@[ kGridTabGroupsSectionIdentifier ]]; + } [snapshot appendSectionsWithIdentifiers:@[ kSuggestedActionsSectionIdentifier ]]; GridItemIdentifier* itemIdentifier = [GridItemIdentifier suggestedActionsIdentifier]; [snapshot appendItemsWithIdentifiers:@[ itemIdentifier ]]; + self.showingSuggestedActions = YES; } } else { if (self.showingSuggestedActions) { + if (base::FeatureList::IsEnabled(kTabGroupsInGrid)) { + [snapshot + deleteSectionsWithIdentifiers:@[ kGridTabGroupsSectionIdentifier ]]; + } [snapshot deleteSectionsWithIdentifiers:@[ kSuggestedActionsSectionIdentifier ]]; @@ -1628,7 +1653,8 @@ cell.delegate = self; cell.theme = self.theme; cell.itemIdentifier = item.identifier; - cell.title = item.title; + // TODO(crbug.com/1501837): Add the right title when the model is available. + cell.title = @"Temporary Title"; cell.titleHidden = item.hidesTitle; cell.accessibilityIdentifier = GroupGridCellAccessibilityIdentifier(index); if (self.mode == TabGridModeSelection) { @@ -1648,7 +1674,7 @@ cell.itemIdentifier == itemForSnapshot.identifier) { // TODO(crbug.com/1501837): Remove once the group color is available // throught the group model. Keep for now for testing purposes. - cell.icon = favicon; + cell.groupColorName = kYellow500Color; GroupTabInfo* snapshotFavicon = [[GroupTabInfo alloc] init]; snapshotFavicon.snapshot = snapshot; snapshotFavicon.favicon = favicon;
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_layout.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_layout.mm index f6119e5..f06cb29 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_layout.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_layout.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_layout.h" #import "base/notreached.h" +#import "ios/chrome/browser/shared/public/features/features.h" #import "ios/chrome/browser/shared/ui/util/rtl_geometry.h" #import "ios/chrome/common/ui/util/ui_util.h" #import "ios/web/common/uikit_ui_util.h" @@ -390,9 +391,20 @@ return TabsSection(layoutEnvironment, self.tabsSectionHeaderType, self.sectionInsets); } - if (sectionIndex == 1) { - return SuggestedActionsSection(layoutEnvironment, self.sectionInsets); + if (base::FeatureList::IsEnabled(kTabGroupsInGrid)) { + if (sectionIndex == 1) { + return TabsSection(layoutEnvironment, self.tabsSectionHeaderType, + self.sectionInsets); + } + if (sectionIndex == 2) { + return SuggestedActionsSection(layoutEnvironment, self.sectionInsets); + } + } else { + if (sectionIndex == 1) { + return SuggestedActionsSection(layoutEnvironment, self.sectionInsets); + } } + NOTREACHED_NORETURN(); }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/group_grid_cell.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/group_grid_cell.h index 698dbba..87acf774 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/group_grid_cell.h +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/group_grid_cell.h
@@ -27,7 +27,7 @@ // The look of the cell. @property(nonatomic, assign) GridTheme theme; // Settable UI elements of the group cell. -@property(nonatomic, weak) UIImage* icon; +@property(nonatomic, copy) NSString* groupColorName; @property(nonatomic, copy) NSString* title; @property(nonatomic, assign) BOOL titleHidden; // Sets to update and keep cell alpha in sync.
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/group_grid_cell.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/group_grid_cell.mm index d5bb52b..c65d39a12 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/group_grid_cell.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/group_grid_cell.mm
@@ -31,6 +31,7 @@ const CGFloat kSnapshotViewLeadingOffset = 4; const CGFloat kSnapshotViewTrailingOffset = 4; const CGFloat kSnapShotViewBottomOffset = 4; +const CGFloat kGroupColorViewSize = 18; // The vertical/horizontal spacing to apply between the snapshot views. const CGFloat kSpacing = 4; @@ -50,7 +51,7 @@ NSLayoutConstraint* _topBarHeightConstraint; // Visual components of the cell. UIView* _topBar; - UIImageView* _iconView; + UIView* _groupColorView; UILabel* _titleLabel; UIImageView* _closeIconView; UIImageView* _selectIconView; @@ -193,7 +194,7 @@ [super prepareForReuse]; self.title = nil; self.titleHidden = NO; - self.icon = nil; + self.groupColorName = nil; [self configureWithGroupTabInfos:nil totalTabsCount:0]; self.selected = NO; self.opacity = 1.0; @@ -237,9 +238,11 @@ _theme = theme; } -- (void)setIcon:(UIImage*)icon { - _iconView.image = icon; - _icon = icon; +- (void)setGroupColorName:(NSString*)groupColorName { + if (groupColorName) { + _groupColorName = groupColorName; + _groupColorView.backgroundColor = [UIColor colorNamed:_groupColorName]; + } } - (void)configureWithGroupTabInfos:(NSArray<GroupTabInfo*>*)groupTabInfos @@ -330,13 +333,9 @@ _topBar = [[UIView alloc] init]; _topBar.translatesAutoresizingMaskIntoConstraints = NO; - _iconView = [[UIImageView alloc] init]; - _iconView.translatesAutoresizingMaskIntoConstraints = NO; - _iconView.contentMode = UIViewContentModeScaleAspectFill; - _iconView.layer.cornerRadius = kGridCellIconCornerRadius; - _iconView.layer.masksToBounds = YES; - _iconView.backgroundColor = UIColor.clearColor; - _iconView.tintColor = [UIColor colorNamed:kGrey400Color]; + _groupColorView = [[UIView alloc] init]; + _groupColorView.translatesAutoresizingMaskIntoConstraints = NO; + _groupColorView.layer.cornerRadius = kGroupColorViewSize / 2; _titleLabel = [[UILabel alloc] init]; _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; @@ -359,7 +358,7 @@ [_topBar addSubview:_selectIconView]; - [_topBar addSubview:_iconView]; + [_topBar addSubview:_groupColorView]; [_topBar addSubview:_titleLabel]; [_topBar addSubview:_closeIconView]; @@ -367,19 +366,21 @@ [_titleLabel.leadingAnchor constraintEqualToAnchor:_topBar.leadingAnchor constant:kGridCellHeaderLeadingInset], - [_iconView.widthAnchor constraintEqualToConstant:0], - [_iconView.heightAnchor constraintEqualToConstant:0], + [_groupColorView.widthAnchor constraintEqualToConstant:0], + [_groupColorView.heightAnchor constraintEqualToConstant:0], ]; _nonAccessibilityConstraints = @[ - [_iconView.leadingAnchor + [_groupColorView.heightAnchor + constraintEqualToConstant:kGroupColorViewSize], + [_groupColorView.widthAnchor constraintEqualToConstant:kGroupColorViewSize], + [_groupColorView.leadingAnchor constraintEqualToAnchor:_topBar.leadingAnchor constant:kGridCellHeaderLeadingInset], - [_iconView.centerYAnchor constraintEqualToAnchor:_topBar.centerYAnchor], - [_iconView.widthAnchor constraintEqualToConstant:kGridCellIconDiameter], - [_iconView.heightAnchor constraintEqualToConstant:kGridCellIconDiameter], + [_groupColorView.centerYAnchor + constraintEqualToAnchor:_topBar.centerYAnchor], [_titleLabel.leadingAnchor - constraintEqualToAnchor:_iconView.trailingAnchor + constraintEqualToAnchor:_groupColorView.trailingAnchor constant:kGridCellHeaderLeadingInset], ];
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_mediator.mm index e603e500..bf054bd 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_mediator.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_mediator.mm
@@ -359,8 +359,9 @@ // Move tab across Browsers. base::UmaHistogramEnumeration(kUmaPinnedViewDragOrigin, DragItemOrigin::kOtherBrwoser); - MoveTabToBrowser(tabInfo.tabID, self.browser, destinationIndex, - WebStateList::INSERT_PINNED); + const WebStateList::InsertionParams params = + WebStateList::InsertionParams::AtIndex(destinationIndex).Pinned(); + MoveTabToBrowser(tabInfo.tabID, self.browser, params); return; } base::UmaHistogramEnumeration(kUmaPinnedViewDragOrigin,
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm index 33c539e..d5998e58 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm
@@ -1480,12 +1480,6 @@ if (!self.viewVisible || self.currentPage != TabGridPageRegularTabs) { return; } - - if (UIAccessibilityIsVoiceOverRunning()) { - // TODO(crbug.com/1467873): Add a voiceover announcement to the IPH view - // instead of returning. - return; - } // Check whether the user should see the IPH. if (![self.delegate tabGridIsUserEligibleForSwipeToIncognitoIPH]) { return; @@ -1505,12 +1499,16 @@ } expectedSize.width = regularGridView.bounds.size.width; GestureInProductHelpView* gestureIPHView = [[GestureInProductHelpView alloc] - initWithText:l10n_util::GetNSString( - UseRTLLayout() - ? IDS_IOS_SWIPE_LEFT_TO_INCOGNITO_IPH - : IDS_IOS_SWIPE_RIGHT_TO_INCOGNITO_IPH) - bubbleBoundingSize:expectedSize - arrowDirection:BubbleArrowDirectionLeading]; + initWithText:l10n_util::GetNSString( + UseRTLLayout() + ? IDS_IOS_SWIPE_LEFT_TO_INCOGNITO_IPH + : IDS_IOS_SWIPE_RIGHT_TO_INCOGNITO_IPH) + bubbleBoundingSize:expectedSize + arrowDirection:BubbleArrowDirectionLeading + voiceOverAnnouncement: + l10n_util::GetNSString( + UseRTLLayout() ? IDS_IOS_SWIPE_LEFT_TO_INCOGNITO_IPH_VOICEOVER + : IDS_IOS_SWIPE_RIGHT_TO_INCOGNITO_IPH_VOICEOVER)]; [gestureIPHView setTranslatesAutoresizingMaskIntoConstraints:NO]; // Return if the view does NOT fit in the regular tab grid.
diff --git a/ios/chrome/browser/ui/whats_new/data_source/resources/m122/BottomOmnibox.json b/ios/chrome/browser/ui/whats_new/data_source/resources/m122/BottomOmnibox.json index 327b5cf..2c91ff43 100644 --- a/ios/chrome/browser/ui/whats_new/data_source/resources/m122/BottomOmnibox.json +++ b/ios/chrome/browser/ui/whats_new/data_source/resources/m122/BottomOmnibox.json
@@ -1 +1 @@ -{"v":"4.8.0","meta":{"g":"LottieFiles AE 3.5.2","a":"","k":"","d":"","tc":""},"fr":60,"ip":0,"op":3600,"w":549,"h":830,"nm":"CreateCalendar_Light – 5","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 184","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.72,11.276,0],"ix":2},"a":{"a":0,"k":[4.683,6.77,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0.998],[0,0],[-0.711,0.109],[0,0],[-1.818,0],[0,-2.597],[0,0],[0,-0.902],[0,0],[0.916,0]],"o":[[-0.916,0],[0,0],[0,-0.855],[0,0],[0,-2.597],[1.818,0],[0,0],[0.767,0.074],[0,0],[0,0.998],[0,0]],"v":[[1.367,13.54],[0,12.091],[0,6.972],[1.135,5.557],[1.135,3.848],[4.682,0],[8.23,3.848],[8.23,5.537],[9.366,6.972],[9.366,12.091],[7.999,13.54]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,-1.593],[0,0],[0,0],[0,0],[1.218,0]],"o":[[0,0],[0,0],[0,0],[0,-1.593],[-1.223,0]],"v":[[2.447,3.725],[2.447,5.529],[6.918,5.523],[6.918,3.725],[4.682,1.257]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 184","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_1","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 183","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16.536,16.011,0],"ix":2},"a":{"a":0,"k":[11.944,15.116,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.732,0.722],[0,1.419],[0,0],[-0.732,0.724],[-1.427,0],[0,0],[0,0],[0,0],[0.326,-0.326],[0,-0.644],[0,0],[-0.318,-0.316],[-0.615,0],[0,0],[-0.326,0.326],[0,0.642],[0,0],[0.336,0.316],[0.609,0],[0,0],[0,0],[0,0],[-0.732,-0.73],[0,-1.408],[0,0],[0.732,-0.722],[1.427,0]],"o":[[-1.427,0],[-0.732,-0.724],[0,0],[0,-1.408],[0.732,-0.73],[0,0],[0,0],[0,0],[-0.615,0],[-0.318,0.316],[0,0],[0,0.642],[0.326,0.326],[0,0],[0.609,0],[0.336,-0.316],[0,0],[0,-0.644],[-0.326,-0.326],[0,0],[0,0],[0,0],[1.427,0],[0.732,0.724],[0,0],[0,1.41],[-0.732,0.732],[0,0]],"v":[[4.334,30.231],[1.097,29.149],[0,25.936],[0,12.935],[1.097,9.737],[4.334,8.641],[8.165,8.641],[8.165,11.244],[4.491,11.244],[3.079,11.734],[2.603,13.173],[2.603,25.713],[3.079,27.152],[4.491,27.642],[19.383,27.642],[20.783,27.152],[21.285,25.713],[21.285,13.173],[20.783,11.734],[19.383,11.244],[15.723,11.244],[15.723,8.641],[19.555,8.641],[22.792,9.737],[23.888,12.935],[23.888,25.936],[22.792,29.134],[19.555,30.231]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.336,0],[0.246,0.238],[0,0.326],[0,0],[0,0],[0,0],[0,0],[0.334,0],[0.211,0.195],[0,0.307],[-0.219,0.238],[0,0],[-0.15,0.062],[-0.158,0],[-0.15,-0.062],[-0.16,-0.158],[0,0],[0,-0.283],[0.219,-0.201],[0.299,0],[0.221,0.238],[0,0],[0,0],[0,0],[0,0],[0.248,-0.238]],"o":[[-0.334,0],[-0.238,-0.238],[0,0],[0,0],[0,0],[0,0],[-0.211,0.238],[-0.31,0],[-0.201,-0.201],[0,-0.283],[0,0],[0.166,-0.158],[0.15,-0.062],[0.16,0],[0.15,0.062],[0,0],[0.23,0.238],[0,0.307],[-0.211,0.195],[-0.326,0],[0,0],[0,0],[0,0],[0,0],[0,0.326],[-0.238,0.238]],"v":[[11.943,19.7],[11.072,19.344],[10.715,18.499],[10.715,5.193],[10.822,3.225],[9.99,4.188],[8.138,6.17],[7.32,6.527],[6.539,6.236],[6.236,5.471],[6.566,4.69],[11.006,0.422],[11.482,0.092],[11.943,0],[12.406,0.092],[12.87,0.422],[17.308,4.69],[17.652,5.471],[17.322,6.236],[16.556,6.527],[15.736,6.17],[13.887,4.188],[13.067,3.225],[13.173,5.193],[13.173,18.499],[12.802,19.344]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.741176470588,0.756862745098,0.776470588235,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 183","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_2","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 181","sr":1,"ks":{"o":{"a":0,"k":40,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[22.743,22.253,0],"ix":2},"a":{"a":0,"k":[14.429,11.826,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-0.479],[0.356,-0.356],[0,0],[0.448,0],[0.316,0.304],[0,0.458],[-0.082,0.204],[-0.153,0.154],[0,0],[0,0],[0,0],[0,0],[0,0],[0.316,0.306],[0,0.487],[-0.305,0.306],[-0.509,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0.092,0.194],[0,0.246],[-0.306,0.306],[-0.468,0],[-0.204,-0.092],[-0.183,-0.183],[0,0]],"o":[[0,0.477],[0,0],[-0.356,0.348],[-0.468,0],[-0.306,-0.306],[0,-0.235],[0.092,-0.204],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.509,0],[-0.305,-0.314],[0,-0.5],[0.316,-0.316],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.153,-0.154],[-0.082,-0.204],[0,-0.458],[0.316,-0.306],[0.224,0],[0.204,0.092],[0,0],[0.356,0.356]],"v":[[28.858,11.834],[28.324,13.085],[18.246,23.132],[17.04,23.652],[15.864,23.194],[15.406,22.049],[15.529,21.392],[15.895,20.857],[19.315,17.406],[25.01,12.215],[25.545,13.193],[20.247,13.497],[1.695,13.497],[0.458,13.039],[0,11.834],[0.458,10.627],[1.695,10.155],[20.247,10.155],[25.545,10.475],[25.01,11.468],[19.315,6.261],[15.895,2.795],[15.529,2.275],[15.406,1.603],[15.864,0.458],[17.04,0],[17.681,0.137],[18.262,0.549],[28.324,10.581]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.741176470588,0.756862745098,0.776470588235,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 181","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_3","layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Group 72","refId":"comp_4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,25.585,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_4","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 180","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.583,25.586,0],"ix":2},"a":{"a":0,"k":[11.542,11.543,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.13,0],[0,1.13],[0,0],[0,0],[0,1.13],[1.13,0],[0,0],[0,0],[1.132,0],[0,-1.13],[0,0],[0,0],[0,-1.132],[-1.13,0],[0,0]],"o":[[0,1.13],[1.132,0],[0,0],[0,0],[1.13,0],[0,-1.132],[0,0],[0,0],[0,-1.13],[-1.13,0],[0,0],[0,0],[-1.13,0],[0,1.13],[0,0],[0,0]],"v":[[9.497,21.038],[11.543,23.086],[13.591,21.038],[13.591,13.589],[21.038,13.589],[23.084,11.543],[21.038,9.495],[13.591,9.495],[13.591,2.048],[11.543,0],[9.497,2.048],[9.497,9.495],[2.046,9.495],[0,11.543],[2.046,13.589],[9.497,13.589]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 180","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path 179","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,25.585,0],"ix":2},"a":{"a":0,"k":[25.585,25.585,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.087,-1.32],[3.501,0],[3.085,1.338],[2.358,2.36],[1.336,3.087],[0,3.499],[-1.336,3.089],[-2.344,2.346],[-3.07,1.336],[-3.499,0],[-3.087,-1.338],[-2.358,-2.36],[-1.338,-3.087],[0,-3.501],[1.336,-3.089],[2.36,-2.362]],"o":[[-3.087,1.338],[-3.499,0],[-3.087,-1.32],[-2.344,-2.362],[-1.336,-3.089],[0,-3.501],[1.336,-3.087],[2.358,-2.36],[3.087,-1.338],[3.515,0],[3.087,1.336],[2.36,2.346],[1.336,3.089],[0,3.499],[-1.338,3.087],[-2.358,2.36]],"v":[[35.449,49.163],[25.571,51.169],[15.695,49.163],[7.526,43.641],[2.004,35.468],[0,25.586],[2.004,15.701],[7.526,7.553],[15.67,2.006],[25.548,0],[35.449,2.006],[43.618,7.553],[49.165,15.701],[51.169,25.586],[49.165,35.468],[43.618,43.641]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549019608,0.388235294118,0.407843137255,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 179","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_5","layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Group 70","refId":"comp_6","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,25.585,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_6","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 176","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,26.432,0],"ix":2},"a":{"a":0,"k":[14.506,3.092,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.56,0],[0.468,0.275],[0.275,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275],[-0.581,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.275,-0.468],[0.468,-0.285]],"o":[[-0.581,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.275,-0.468],[0.468,-0.285],[0.56,0],[0.468,0.275],[0.275,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275]],"v":[[3.099,6.184],[1.528,5.771],[0.412,4.641],[0,3.099],[0.412,1.542],[1.528,0.427],[3.099,0],[4.641,0.427],[5.757,1.542],[6.169,3.099],[5.757,4.641],[4.641,5.771]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.57,0],[0.468,0.275],[0.285,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275],[-0.568,0],[-0.458,-0.285],[-0.275,-0.468],[0,-0.57],[0.285,-0.468],[0.468,-0.285]],"o":[[-0.568,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.285,-0.468],[0.468,-0.285],[0.57,0],[0.468,0.275],[0.285,0.468],[0,0.56],[-0.275,0.468],[-0.458,0.275]],"v":[[14.505,6.184],[12.948,5.771],[11.818,4.641],[11.406,3.099],[11.818,1.542],[12.948,0.427],[14.505,0],[16.047,0.427],[17.163,1.542],[17.589,3.099],[17.163,4.641],[16.047,5.771]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0.568,0],[0.468,0.275],[0.275,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275],[-0.57,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.285,-0.468],[0.468,-0.285]],"o":[[-0.57,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.275,-0.468],[0.468,-0.285],[0.568,0],[0.468,0.275],[0.285,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275]],"v":[[25.912,6.184],[24.354,5.771],[23.24,4.641],[22.828,3.099],[23.24,1.542],[24.354,0.427],[25.912,0],[27.469,0.427],[28.583,1.542],[29.012,3.099],[28.583,4.641],[27.469,5.771]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 176","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]}],"fonts":{"list":[{"fName":"SF Pro","fFamily":"SF Pro","fStyle":"Regular","ascent":71.8994140625}]},"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Group 82","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[275,599,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,92],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path 193","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[114.877,24.95,0],"ix":2},"a":{"a":0,"k":[8.488,10.442,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.426,0.437],[-0.857,0],[0,0],[-0.354,-0.127],[-0.293,-0.304],[0,0],[-0.122,-0.354],[0,-0.509],[0,0],[0.432,-0.437],[0.858,0],[0,0],[0,0],[0,0],[-0.221,0.222],[0,0.416],[0,0],[0,0],[0.238,0.232],[0,0.481],[0,0],[0,0],[0.222,-0.227],[0,-0.416],[0,0]],"o":[[0,0],[0,-0.864],[0.432,-0.437],[0,0],[0.448,0],[0.354,0.122],[0,0],[0.31,0.32],[0.122,0.354],[0,0],[0,0.864],[-0.426,0.437],[0,0],[0,0],[0,0],[0.432,0],[0.221,-0.227],[0,0],[0,0],[-0.476,0],[-0.232,-0.233],[0,0],[0,0],[-0.432,0],[-0.215,0.221],[0,0],[0,0]],"v":[[4.026,4.599],[4.026,2.607],[4.665,0.656],[6.599,0],[9.779,0],[10.982,0.191],[11.953,0.83],[16.145,5.089],[16.793,6.101],[16.975,7.396],[16.975,14.136],[16.328,16.087],[14.402,16.743],[12.692,16.743],[12.692,15.406],[14.327,15.406],[15.307,15.074],[15.639,14.111],[15.639,7.014],[11.754,7.014],[10.683,6.666],[10.335,5.595],[10.335,1.337],[6.666,1.337],[5.686,1.677],[5.363,2.632],[5.363,4.599]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-0.061,-0.066],[-0.144,0],[0,0],[0,0]],"o":[[0,0.149],[0.066,0.061],[0,0],[0,0],[0,0]],"v":[[11.538,5.396],[11.63,5.719],[11.945,5.811],[15.29,5.811],[11.538,1.992]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0.869],[0,0],[-0.426,0.437],[-0.858,0],[0,0],[-0.305,-0.1],[-0.315,-0.327],[0,0],[-0.111,-0.205],[-0.038,-0.243],[0,-0.355],[0,0],[0.432,-0.437],[0.858,0],[0,0],[0.432,0.437]],"o":[[0,0],[0,-0.864],[0.432,-0.437],[0,0],[0.465,0],[0.304,0.099],[0,0],[0.221,0.226],[0.116,0.199],[0.039,0.244],[0,0],[0,0.864],[-0.426,0.437],[0,0],[-0.858,0],[-0.426,-0.431]],"v":[[0,18.278],[0,6.749],[0.639,4.798],[2.574,4.142],[5.504,4.142],[6.658,4.292],[7.587,4.931],[12.161,9.588],[12.659,10.235],[12.891,10.899],[12.95,11.796],[12.95,18.278],[12.302,20.229],[10.376,20.885],[2.574,20.885],[0.639,20.229]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[-0.215,-0.221],[-0.426,0],[0,0],[-0.221,0.227],[0,0.415],[0,0],[0,0],[0.265,0.26],[0,0.526],[0,0],[0,0],[0.222,-0.227],[0,-0.409]],"o":[[0,0.415],[0.222,0.227],[0,0],[0.426,0],[0.221,-0.221],[0,0],[0,0],[-0.514,0],[-0.26,-0.26],[0,0],[0,0],[-0.432,0],[-0.215,0.221],[0,0]],"v":[[1.337,18.254],[1.66,19.208],[2.632,19.548],[10.31,19.548],[11.281,19.208],[11.613,18.254],[11.613,11.862],[6.923,11.862],[5.753,11.472],[5.363,10.293],[5.363,5.479],[2.64,5.479],[1.66,5.819],[1.337,6.765]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[-0.166,0],[0,0],[0,0],[0,0],[-0.072,-0.072]],"o":[[0,0],[0,0],[0,0],[0,0.166],[0.072,0.072]],"v":[[7.081,10.609],[11.356,10.609],[6.616,5.786],[6.616,10.144],[6.724,10.501]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 193","np":7,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Path 192","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[113.061,-25.5,0],"ix":2},"a":{"a":0,"k":[6.672,10.992,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0.166],[-0.09,0.096],[0,0],[-0.159,0],[-0.124,-0.131],[0,0],[0,-0.165],[0.104,-0.104],[0.16,0],[0.124,0.118],[0,0],[0,0],[0,0],[0,0],[0.104,-0.111],[0.166,0],[0.111,0.104],[0,0.159],[0,0],[0,0],[0,0],[0,0],[0.146,0.008],[0.104,0.098]],"o":[[0,-0.165],[0,0],[0.133,-0.131],[0.159,0],[0,0],[0.098,0.096],[0,0.166],[-0.104,0.098],[-0.145,0.008],[0,0],[0,0],[0,0],[0,0],[0,0.159],[-0.104,0.104],[-0.166,0],[-0.104,-0.111],[0,0],[0,0],[0,0],[0,0],[-0.125,0.118],[-0.159,0],[-0.098,-0.104]],"v":[[3.801,9.844],[3.936,9.45],[6.24,7.166],[6.677,6.968],[7.102,7.166],[9.408,9.45],[9.553,9.844],[9.398,10.25],[9.002,10.395],[8.598,10.23],[7.768,9.399],[7.196,8.682],[7.237,10.011],[7.237,12.939],[7.082,13.345],[6.677,13.5],[6.261,13.345],[6.105,12.939],[6.105,10.011],[6.158,8.682],[5.586,9.399],[4.745,10.23],[4.34,10.395],[3.946,10.25]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0.166,0.166],[0,0.291],[0,0],[-0.166,0.174],[-0.284,0],[0,0],[-0.166,-0.173],[0,-0.284],[0,0],[0.173,-0.173],[0.276,0]],"o":[[-0.284,0],[-0.166,-0.173],[0,0],[0,-0.284],[0.166,-0.173],[0,0],[0.276,0],[0.173,0.174],[0,0],[0,0.291],[-0.166,0.166],[0,0]],"v":[[3.924,6.116],[3.25,5.867],[3.001,5.172],[3.001,3.936],[3.25,3.25],[3.924,2.991],[9.429,2.991],[10.093,3.25],[10.352,3.936],[10.352,5.172],[10.093,5.867],[9.429,6.116]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0.809],[0,0],[-0.519,0.492],[-0.844,0],[0,0],[-0.513,-0.498],[0,-0.811],[0,0],[0.519,-0.49],[0.852,0],[0,0],[0.519,0.499]],"o":[[0,0],[0,-0.811],[0.519,-0.498],[0,0],[0.852,0],[0.519,0.492],[0,0],[0,0.809],[-0.513,0.499],[0,0],[-0.844,0],[-0.519,-0.49]],"v":[[0,19.285],[0,2.701],[0.778,0.748],[2.824,0],[10.519,0],[12.565,0.748],[13.343,2.701],[13.343,19.285],[12.565,21.236],[10.519,21.984],[2.824,21.984],[0.778,21.236]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[-0.235,-0.221],[-0.443,0],[0,0],[-0.235,0.228],[0,0.415],[0,0],[0.236,0.221],[0.437,0],[0,0],[0.235,-0.229],[0,-0.415]],"o":[[0,0.415],[0.235,0.228],[0,0],[0.437,0],[0.236,-0.221],[0,0],[0,-0.415],[-0.235,-0.229],[0,0],[-0.443,0],[-0.235,0.221],[0,0]],"v":[[1.671,19.014],[2.024,19.97],[3.043,20.313],[10.311,20.313],[11.318,19.97],[11.672,19.014],[11.672,2.97],[11.318,2.015],[10.311,1.673],[3.043,1.673],[2.024,2.015],[1.671,2.97]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 192","np":6,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":5,"nm":"Copy Link","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-124,31,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"t":{"d":{"k":[{"s":{"s":16,"f":"SF Pro","t":"Copy Link","j":0,"tr":0,"lh":19.2,"ls":0,"fc":[1,1,1]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[{"nm":"Animators","s":{"t":0,"xe":{"k":0},"ne":{"k":0},"a":{"k":100},"b":1,"sh":0,"s":{"k":0},"e":{"k":100},"o":{"k":0}},"a":{"fo":{"a":0,"k":100,"ix":10},"so":{"a":0,"k":100,"ix":11}}}]},"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":5,"nm":"Move Address Bar","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-124,-20,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"t":{"d":{"k":[{"s":{"s":16,"f":"SF Pro","t":"Move Address Bar","j":0,"tr":0,"lh":19.2,"ls":0,"fc":[1,1,1]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[{"nm":"Animators","s":{"t":0,"xe":{"k":0},"ne":{"k":0},"a":{"k":100},"b":1,"sh":0,"s":{"k":0},"e":{"k":100},"o":{"k":0}},"a":{"fo":{"a":0,"k":100,"ix":10},"so":{"a":0,"k":100,"ix":11}}}]},"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Rectangle 91","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,10],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 91 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,10],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549019608,0.388235294118,0.407843137255,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 91 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Rectangle 90","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":41,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":3,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":20,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,92],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":13,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 90 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,92],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":13,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 90 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Rectangle 86","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,380,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,546],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 86 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,546],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":20,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 86 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Group 77","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,688.115,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,70],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Path 185","parent":9,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[11.406,2.343,0],"ix":2},"a":{"a":0,"k":[69.753,10.842,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.523,1.105],[0,0],[2.743,0],[0,3.963],[-3.44,0],[0,-3.893],[0,0],[0,0],[0,0],[-2.128,0]],"o":[[0,0],[-0.582,2.14],[-3.475,0],[0,-3.938],[3.382,0],[0,0],[0,0],[0,0],[0.105,2.476],[1.615,0]],"v":[[8.926,14.258],[10.924,14.258],[5.648,17.722],[0,11.248],[5.648,4.752],[11.086,11.051],[11.086,11.818],[2.081,11.818],[2.081,11.91],[5.695,15.955]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[1.986,0],[0.152,-2.22],[0,0]],"o":[[-1.999,0],[0,0],[-0.047,-2.22]],"v":[[5.625,6.519],[2.081,10.203],[8.983,10.203]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[17.615,12.806],[17.431,12.806],[14.454,17.536],[12.189,17.536],[16.478,11.273],[12.142,5.008],[14.524,5.008],[17.501,9.668],[17.685,9.668],[20.625,5.008],[22.892,5.008],[18.638,11.191],[22.95,17.536],[20.58,17.536]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[1.673,0],[0,2.29],[-2.917,0.174],[0,0],[0,0],[1.872,0],[0.281,-0.988],[0,0],[-2.673,0],[0,-2.601],[0,0],[0,0],[0,0],[0,0]],"o":[[-2.429,0],[0,-2.243],[0,0],[0,0],[0,-1.544],[-1.499,0],[0,0],[0.266,-2.009],[3.057,0],[0,0],[0,0],[0,0],[0,0],[-0.814,1.337]],"v":[[28.585,17.722],[24.354,13.991],[28.921,10.285],[32.535,10.063],[32.535,8.924],[29.7,6.531],[26.875,8.087],[24.854,8.087],[29.77,4.752],[34.534,8.924],[34.534,17.501],[32.63,17.501],[32.63,15.654],[32.443,15.654]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[-1.451,0],[0,1.79],[0,0],[0,0],[0,-1.255]],"o":[[2.058,0],[0,0],[0,0],[-1.904,0.127],[0,1.279]],"v":[[28.956,15.967],[32.535,12.829],[32.535,11.679],[29.165,11.9],[26.422,13.944]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[-1.673,0],[-0.58,-1.302],[0,0],[-1.732,0],[0,-2.626],[0,0],[0,0],[0,0],[1.767,0],[0,-1.593],[0,0],[0,0],[0,0],[1.581,0],[0,-1.765],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0.568,-1.394],[1.697,0],[0,0],[0.674,-1.324],[2.556,0],[0,0],[0,0],[0,0],[0,-1.849],[-1.742,0],[0,0],[0,0],[0,0],[0,-1.486],[-1.64,0],[0,0],[0,0]],"v":[[37.658,17.501],[37.658,4.973],[39.565,4.973],[39.565,6.949],[39.751,6.949],[43.248,4.752],[46.711,6.949],[46.897,6.949],[50.733,4.752],[54.718,8.844],[54.718,17.501],[52.719,17.501],[52.719,9.309],[50.081,6.554],[47.176,9.448],[47.176,17.501],[45.178,17.501],[45.178,8.993],[42.564,6.554],[39.657,9.737],[39.657,17.501]],"c":true},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ind":6,"ty":"sh","ix":7,"ks":{"a":0,"k":{"i":[[-1.71,0],[0,-3.94],[3.184,0],[0.687,1.324],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[3.196,0],[0,3.915],[-1.79,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0.802,-1.439]],"v":[[63.898,4.752],[69.162,11.238],[63.898,17.722],[59.98,15.619],[59.796,15.619],[59.796,21.685],[57.797,21.685],[57.797,4.973],[59.702,4.973],[59.702,7.064],[59.888,7.064]],"c":true},"ix":2},"nm":"Path 7","mn":"ADBE Vector Shape - Group","hd":false},{"ind":7,"ty":"sh","ix":8,"ks":{"a":0,"k":{"i":[[-2.253,0],[0,2.927],[2.29,0],[0,-2.882]],"o":[[2.302,0],[0,-2.929],[-2.265,0],[0,2.87]],"v":[[63.42,15.92],[67.094,11.238],[63.433,6.554],[59.736,11.238]],"c":true},"ix":2},"nm":"Path 8","mn":"ADBE Vector Shape - Group","hd":false},{"ind":8,"ty":"sh","ix":9,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[71.844,17.501],[71.844,0],[73.842,0],[73.842,17.501]],"c":true},"ix":2},"nm":"Path 9","mn":"ADBE Vector Shape - Group","hd":false},{"ind":9,"ty":"sh","ix":10,"ks":{"a":0,"k":{"i":[[-0.523,1.105],[0,0],[2.743,0],[0,3.963],[-3.44,0],[0,-3.893],[0,0],[0,0],[0,0],[-2.128,0]],"o":[[0,0],[-0.582,2.14],[-3.475,0],[0,-3.938],[3.382,0],[0,0],[0,0],[0,0],[0.105,2.476],[1.615,0]],"v":[[85.451,14.258],[87.45,14.258],[82.174,17.722],[76.526,11.248],[82.174,4.752],[87.612,11.051],[87.612,11.818],[78.607,11.818],[78.607,11.91],[82.221,15.955]],"c":true},"ix":2},"nm":"Path 10","mn":"ADBE Vector Shape - Group","hd":false},{"ind":10,"ty":"sh","ix":11,"ks":{"a":0,"k":{"i":[[1.986,0],[0.152,-2.22],[0,0]],"o":[[-1.999,0],[0,0],[-0.047,-2.22]],"v":[[82.151,6.519],[78.607,10.203],[85.509,10.203]],"c":true},"ix":2},"nm":"Path 11","mn":"ADBE Vector Shape - Group","hd":false},{"ind":11,"ty":"sh","ix":12,"ks":{"a":0,"k":{"i":[[0.836,0],[0,0.824],[-0.824,0],[0,-0.836]],"o":[[-0.824,0],[0,-0.836],[0.836,0],[0,0.824]],"v":[[91.829,17.618],[90.318,16.107],[91.829,14.596],[93.34,16.107]],"c":true},"ix":2},"nm":"Path 12","mn":"ADBE Vector Shape - Group","hd":false},{"ind":12,"ty":"sh","ix":13,"ks":{"a":0,"k":{"i":[[-0.349,-2.232],[0,0],[1.8,0],[0,-2.835],[-2.232,0],[-0.373,1.417],[0,0],[3.011,0],[0,3.985],[-3.51,0]],"o":[[0,0],[-0.326,-1.244],[-2.255,0],[0,2.892],[1.685,0],[0,0],[-0.361,2.3],[-3.51,0],[0,-3.905],[3.044,0]],"v":[[106.574,8.809],[104.553,8.809],[101.322,6.554],[97.649,11.191],[101.322,15.92],[104.553,13.725],[106.574,13.725],[101.333,17.722],[95.58,11.191],[101.322,4.752]],"c":true},"ix":2},"nm":"Path 13","mn":"ADBE Vector Shape - Group","hd":false},{"ind":13,"ty":"sh","ix":14,"ks":{"a":0,"k":{"i":[[3.567,0],[0,4.02],[-3.569,0],[0,-4.034]],"o":[[-3.569,0],[0,-4.034],[3.567,0],[0,4.02]],"v":[[114.104,17.722],[108.327,11.238],[114.104,4.752],[119.879,11.238]],"c":true},"ix":2},"nm":"Path 14","mn":"ADBE Vector Shape - Group","hd":false},{"ind":14,"ty":"sh","ix":15,"ks":{"a":0,"k":{"i":[[-2.372,0],[0,2.962],[2.37,0],[0,-2.977]],"o":[[2.37,0],[0,-2.977],[-2.372,0],[0,2.962]],"v":[[114.104,15.92],[117.81,11.238],[114.104,6.554],[110.396,11.238]],"c":true},"ix":2},"nm":"Path 15","mn":"ADBE Vector Shape - Group","hd":false},{"ind":15,"ty":"sh","ix":16,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[-1.675,0],[-0.58,-1.302],[0,0],[-1.732,0],[0,-2.626],[0,0],[0,0],[0,0],[1.767,0],[0,-1.593],[0,0],[0,0],[0,0],[1.581,0],[0,-1.765],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0.57,-1.394],[1.695,0],[0,0],[0.674,-1.324],[2.556,0],[0,0],[0,0],[0,0],[0,-1.849],[-1.742,0],[0,0],[0,0],[0,0],[0,-1.486],[-1.638,0],[0,0],[0,0]],"v":[[122.445,17.501],[122.445,4.973],[124.352,4.973],[124.352,6.949],[124.536,6.949],[128.036,4.752],[131.498,6.949],[131.685,6.949],[135.52,4.752],[139.505,8.844],[139.505,17.501],[137.507,17.501],[137.507,9.309],[134.868,6.554],[131.963,9.448],[131.963,17.501],[129.965,17.501],[129.965,8.993],[127.349,6.554],[124.444,9.737],[124.444,17.501]],"c":true},"ix":2},"nm":"Path 16","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 185","np":18,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":0,"nm":"Group 76","parent":9,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-71.782,0.382,0],"ix":2},"a":{"a":0,"k":[7,11.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[13.44,0],[13.44,22.4],[0,22.4]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":14,"h":23,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":0,"nm":"Group 75","parent":9,"refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[216.796,0.801,0],"ix":2},"a":{"a":0,"k":[15.5,15.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[30.8,0],[30.8,30.8],[0,30.8]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":31,"h":31,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Rectangle 70","parent":9,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.452,0.801,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[496.096,50.4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":25,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549019608,0.388235294118,0.407843137255,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 70","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Rectangle 69","parent":9,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,70],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 69","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Path 182","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[52.054,748.211,0],"ix":2},"a":{"a":0,"k":[14.429,11.826,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0.477],[-0.367,0.356],[0,0],[-0.204,0.092],[-0.224,0],[-0.316,-0.306],[0,-0.458],[0.092,-0.204],[0.153,-0.154],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.305,-0.316],[0,-0.5],[0.316,-0.314],[0.509,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.092,-0.204],[0,-0.235],[0.316,-0.306],[0.468,0],[0.356,0.348],[0,0]],"o":[[0,-0.479],[0,0],[0.183,-0.183],[0.204,-0.092],[0.468,0],[0.316,0.306],[0,0.246],[-0.092,0.194],[0,0],[0,0],[0,0],[0,0],[0,0],[0.509,0],[0.316,0.306],[0,0.487],[-0.305,0.306],[0,0],[0,0],[0,0],[0,0],[0,0],[0.153,0.154],[0.092,0.204],[0,0.458],[-0.316,0.304],[-0.448,0],[0,0],[-0.367,-0.356]],"v":[[0,11.834],[0.55,10.581],[10.597,0.549],[11.177,0.137],[11.818,0],[12.994,0.458],[13.467,1.603],[13.33,2.275],[12.963,2.795],[9.543,6.261],[3.863,11.468],[3.313,10.475],[8.612,10.155],[27.164,10.155],[28.385,10.627],[28.858,11.834],[28.385,13.039],[27.164,13.497],[8.612,13.497],[3.313,13.193],[3.863,12.215],[9.543,17.406],[12.963,20.857],[13.33,21.392],[13.467,22.049],[12.994,23.194],[11.818,23.652],[10.612,23.132],[0.55,13.085]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 182","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":0,"nm":"Group 74","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[167.187,748.7,0],"ix":2},"a":{"a":0,"k":[23,23,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[45.485,0],[45.485,45.485],[0,45.485]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":46,"h":46,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":17,"ty":0,"nm":"Group 73","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[276.636,748.7,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":"Path 178","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[386.126,749.23,0],"ix":2},"a":{"a":0,"k":[9.438,6.275,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0.633],[-0.508,0.466],[0,0],[0,0.866],[1.074,0],[0.433,-0.968],[0.541,0],[0,0.624],[-0.058,0.177],[-2.275,0],[0,-2.067],[1.965,-1.857],[0,0],[0,0],[0,0],[0,-0.608],[0.649,0]],"o":[[-0.791,0],[0,-0.475],[0,0],[1.482,-1.424],[0,-0.991],[-0.968,0],[-0.283,0.5],[-0.674,0],[0,-0.191],[0.408,-1.332],[2.548,0],[0,1.465],[0,0],[0,0],[0,0],[0.649,0],[0,0.591],[0,0]],"v":[[1.182,12.284],[0,11.21],[0.691,9.953],[4.273,6.529],[6.138,3.657],[4.298,1.956],[2.231,3.407],[1.116,4.14],[0.042,3.116],[0.133,2.573],[4.323,0],[8.585,3.499],[5.905,7.736],[3.305,10.236],[3.305,10.286],[7.836,10.286],[8.877,11.285],[7.836,12.284]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[2.789,0],[0.566,1.182],[0,0.25],[-0.691,0],[-0.25,-0.458],[-1.249,0],[0,0.999],[1.457,0],[0,0],[0,0.541],[-0.608,0],[0,0],[0,0.982],[1.215,0],[0.393,-0.851],[0.566,0],[0,0.608],[-0.125,0.283],[-2.125,0],[0,-1.925],[1.415,-0.291],[0,0],[0,-1.659]],"o":[[-2.292,0],[-0.133,-0.275],[0,-0.649],[0.5,0],[0.427,0.841],[1.232,0],[0.008,-1.168],[0,0],[-0.608,0],[0,-0.524],[0,0],[1.257,0],[0,-0.968],[-1.016,0],[-0.275,0.566],[-0.699,0],[0,-0.283],[0.533,-1.174],[2.539,0],[0,1.523],[0,0],[1.792,0.167],[0,2.181]],"v":[[14.195,12.55],[9.93,10.377],[9.738,9.586],[10.846,8.529],[11.911,9.187],[14.236,10.527],[16.318,8.812],[14.011,6.995],[13.487,6.995],[12.53,6.096],[13.487,5.205],[13.978,5.205],[16.051,3.54],[14.186,1.931],[12.161,3.207],[11.029,3.982],[9.972,2.966],[10.155,2.156],[14.178,0],[18.434,3.182],[15.926,5.996],[15.926,6.046],[18.876,8.92]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 178","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":19,"ty":0,"nm":"Group 71","refId":"comp_5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[487.004,748.7,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":"Rectangle 77","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,737,0],"ix":2},"a":{"a":0,"k":[262.5,65,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,66],[461,130],[64,130],[0,66]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 77 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,66],[461,130],[64,130],[0,66]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 77 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":"Rectangle 83","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,278,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 83 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509803922,0.290196078431,0.305882352941,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 83 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":"Rectangle 81","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,320,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 81 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509803922,0.290196078431,0.305882352941,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 81 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":23,"ty":4,"nm":"Rectangle 80","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,362,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 80 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509803922,0.290196078431,0.305882352941,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 80 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":24,"ty":4,"nm":"Rectangle 79","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[177,404,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[296,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 79 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[296,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509803922,0.290196078431,0.305882352941,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 79 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":25,"ty":4,"nm":"Rectangle 84","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,179,0],"ix":2},"a":{"a":0,"k":[245.5,72,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[11.046,0],[0,0],[0,11.046]],"o":[[0,0],[0,0],[0,0],[0,0],[0,11.046],[0,0],[-11.046,0],[0,0]],"v":[[0,0],[0,0],[491,0],[491,0],[491,124],[471,144],[20,144],[0,124]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 84 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[11.046,0],[0,0],[0,11.046]],"o":[[0,0],[0,0],[0,0],[0,0],[0,11.046],[0,0],[-11.046,0],[0,0]],"v":[[0,0],[0,0],[491,0],[491,0],[491,124],[471,144],[20,144],[0,124]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509803922,0.290196078431,0.305882352941,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 84 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":26,"ty":4,"nm":"Rectangle 78","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,575,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,266],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 78 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,266],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509803922,0.290196078431,0.305882352941,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 78 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":27,"ty":4,"nm":"Rectangle 76","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,454.5,0],"ix":2},"a":{"a":0,"k":[262.5,347.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,631],[461,695],[64,695],[0,631]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 76 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,631],[461,695],[64,695],[0,631]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.207843137255,0.21568627451,0.223529411765,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 76 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":28,"ty":4,"nm":"Path 161","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":0,"k":[274.5,460.628,0],"ix":2},"a":{"a":0,"k":[274.5,353.372,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-39.692,0],[0,0],[0,-38.817],[0,0],[0,0]],"o":[[0,-38.817],[0,0],[39.692,0],[0,0],[0,0],[0,0]],"v":[[0,70.284],[71.869,0],[477.131,0],[549,70.284],[549,706.744],[0,706.744]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 161","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}],"markers":[],"chars":[{"ch":"M","size":16,"style":"Regular","w":83.3,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0.098,3.597],[0,1.758],[0,0],[0,0],[0,0],[0,0],[0.065,-3.385],[0,-1.465],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,-1.692],[-0.098,-3.596],[0,0],[0,0],[0,0],[0,0],[0,3.874],[-0.066,3.386],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[7.373,0],[16.65,0],[16.65,-42.334],[16.504,-50.269],[16.357,-58.301],[16.357,-60.498],[37.032,0],[46.66,0],[67.139,-60.498],[67.041,-49.609],[66.943,-42.334],[66.943,0],[76.221,0],[76.221,-71.729],[62.398,-71.729],[41.919,-11.084],[21.294,-71.729],[7.373,-71.729]],"c":true},"ix":2},"nm":"M","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"M","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"o","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[5.761,0],[2.414,3.706],[0,5.56],[-2.414,4.097],[-5.312,0],[-2.446,-4.812],[0,-4.877],[2.141,-4.405]],"o":[[-5.247,0],[-2.414,-3.706],[0,-5.787],[2.414,-4.097],[5.987,0],[1.545,3.056],[0,5.397],[-2.141,4.405]],"v":[[27.026,-5.713],[15.535,-11.272],[11.914,-25.172],[15.535,-39.997],[27.122,-46.143],[39.772,-38.924],[42.09,-27.025],[38.879,-12.321]],"c":true},"ix":2},"nm":"o","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[6.691,0],[4.428,-5.203],[0,-8.781],[-4.202,-4.862],[-7.144,0],[-4.073,5.496],[0,8.424],[4.622,4.488]],"o":[[-7.467,0],[-4.428,5.204],[0,8.196],[4.202,4.862],[8.566,0],[4.073,-5.496],[0,-8.716],[-4.623,-4.488]],"v":[[27.366,-53.809],[9.523,-46.003],[2.881,-25.025],[9.184,-5.437],[26.202,1.855],[45.16,-6.389],[51.27,-27.27],[44.336,-47.076]],"c":true},"ix":2},"nm":"o","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"o","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"v","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.562,-52.295],[19.849,0],[29.214,0],[48.901,-52.295],[39.282,-52.295],[24.731,-9.717],[10.767,-52.295]],"c":true},"ix":2},"nm":"v","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"v","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"e","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.688,0],[4.529,-5.241],[0,-8.398],[-4.497,-4.736],[-6.47,0],[-2.1,0.52],[-2.65,2.605],[-1.286,2.361],[-0.228,1.921],[0,0],[1.518,-1.765],[4.554,0],[2.325,3.215],[0.162,5.321],[0,0],[0.517,2.409],[1.747,2.637],[3.461,1.742]],"o":[[-7.312,0],[-4.53,5.241],[0,8.529],[4.497,4.736],[2.649,0],[3.909,-0.912],[1.582,-1.497],[1.286,-2.36],[0,0],[-0.633,2.322],[-2.713,3.041],[-4.877,0],[-2.325,-3.215],[0,0],[0,-5.273],[-0.583,-3.516],[-1.812,-2.766],[-3.462,-1.741]],"v":[[28.022,-53.467],[10.261,-45.605],[3.467,-25.146],[10.211,-5.249],[26.661,1.855],[33.784,1.074],[43.622,-4.199],[47.925,-9.985],[50.195,-16.406],[41.553,-16.406],[38.326,-10.275],[27.425,-5.713],[16.621,-10.535],[12.891,-23.34],[50.928,-23.34],[50.151,-34.863],[46.657,-44.092],[38.747,-50.854]],"c":true},"ix":2},"nm":"e","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-2.711,2.914],[-4.002,0],[-2.389,-4.231],[-0.356,-3.809]],"o":[[0.161,-4.492],[2.711,-2.913],[5.584,0],[1.291,2.279],[0,0]],"v":[[13.086,-30.322],[17.395,-41.431],[27.466,-45.801],[39.425,-39.453],[41.895,-30.322]],"c":true},"ix":2},"nm":"e","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"e","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":" ","size":16,"style":"Regular","w":27.78,"data":{},"fFamily":"SF Pro"},{"ch":"A","size":16,"style":"Regular","w":66.7,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[21.973,-29.395],[33.545,-61.084],[44.434,-29.395]],"c":true},"ix":2},"nm":"A","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[1.465,0],[11.426,0],[19.189,-21.484],[47.559,-21.484],[54.834,0],[65.479,0],[39.453,-71.729],[28.467,-71.729]],"c":true},"ix":2},"nm":"A","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"A","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"d","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,5.599],[-2.737,3.386],[-4.405,0],[-2.689,-3.174],[0,-6.608],[2.607,-3.499],[4.048,0],[2.364,3.777]],"o":[[0,-6.575],[2.737,-3.385],[3.951,0],[2.688,3.174],[0,6.543],[-2.608,3.5],[-5.215,0],[-2.364,-3.776]],"v":[[12.012,-25.537],[16.116,-40.479],[26.829,-45.557],[36.788,-40.796],[40.82,-26.123],[36.909,-11.06],[26.926,-5.811],[15.558,-11.475]],"c":true},"ix":2},"nm":"d","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[3.989,0],[3.875,-5.582],[0,-7.617],[-4.248,-4.899],[-5.804,0],[-2.789,1.432],[-2.043,3.223],[0,0],[0,0],[0,0],[0,0],[0,0],[1.556,0.977]],"o":[[-7.199,0],[-3.875,5.583],[0,8.138],[4.248,4.9],[3.6,0],[2.789,-1.432],[0,0],[0,0],[0,0],[0,0],[0,0],[-1.978,-2.441],[-2.692,-1.692]],"v":[[25.157,-53.223],[8.546,-44.849],[2.734,-25.049],[9.106,-5.493],[24.185,1.855],[33.768,-0.293],[41.016,-7.275],[41.016,0],[48.926,0],[48.926,-71.973],[40.479,-71.973],[40.479,-45.557],[35.177,-50.684]],"c":true},"ix":2},"nm":"d","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"d","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"r","size":16,"style":"Regular","w":33.3,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-2.377,2.849],[-4.427,0],[-0.439,-0.032],[-0.521,-0.098],[0,0],[0.391,0.033],[0.163,0],[2.669,-2.522],[0.684,-1.758],[0,0],[0,0]],"o":[[0,0],[0,0],[0,-3.711],[2.376,-2.848],[0.52,0],[0.439,0.033],[0,0],[-0.945,-0.098],[-0.391,-0.032],[-3.484,0],[-2.67,2.523],[0,0],[0,0],[0,0]],"v":[[6.689,0],[15.479,0],[15.479,-30.078],[19.043,-39.917],[29.248,-44.189],[30.688,-44.141],[32.129,-43.945],[32.129,-53.223],[30.127,-53.418],[29.297,-53.467],[20.068,-49.683],[15.039,-43.262],[15.039,-52.295],[6.689,-52.295]],"c":true},"ix":2},"nm":"r","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"r","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"s","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-3.279,-3.532],[-7.877,0],[-3.576,3.385],[0,4.655],[3.418,2.246],[6.434,1.53],[0,0],[1.326,0.811],[0,2.271],[-1.749,1.265],[-3.399,0],[-2.066,-2.298],[-0.167,-1.974],[0,0],[2.21,2.93],[7.983,0],[3.612,-3.059],[0,-4.948],[-3.838,-2.376],[-4.532,-1.106],[0,0],[-1.291,-0.716],[0,-2.246],[2.525,-1.416],[3.322,0],[2.259,2.832],[0.266,2.93]],"o":[[0.23,5.209],[3.279,3.532],[7.317,0],[3.576,-3.385],[0,-4.817],[-2.19,-1.432],[0,0],[-2.587,-0.618],[-2.299,-1.363],[0,-2.075],[1.749,-1.265],[5.098,0],[1.266,1.619],[0,0],[0.065,-3.385],[-3.529,-4.622],[-6.104,0],[-3.613,3.06],[0,4.199],[2.15,1.367],[0,0],[3.804,0.945],[2.018,1.172],[0,2.962],[-2.525,1.416],[-5.582,0],[-1.23,-1.562],[0,0]],"v":[[3.223,-16.406],[8.488,-3.296],[25.221,2.002],[41.56,-3.076],[46.924,-15.137],[41.797,-25.732],[28.862,-30.176],[22.942,-31.592],[17.072,-33.736],[13.623,-39.185],[16.247,-44.196],[23.969,-46.094],[34.716,-42.646],[36.865,-37.256],[45.166,-37.256],[41.948,-46.729],[24.679,-53.662],[10.106,-49.072],[4.688,-37.061],[10.444,-27.197],[20.467,-23.486],[27.563,-21.729],[35.205,-19.238],[38.232,-14.111],[34.444,-7.544],[25.674,-5.42],[13.912,-9.668],[11.67,-16.406]],"c":true},"ix":2},"nm":"s","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"s","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"B","size":16,"style":"Regular","w":66.7,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-2.171,-0.911],[0,-4.688],[3.618,-1.79],[4.144,0]],"o":[[0,0],[0,0],[4.276,0],[3.848,1.628],[0,4.655],[-2.303,1.14],[0,0]],"v":[[16.895,-41.406],[16.895,-63.623],[34.41,-63.623],[44.081,-62.256],[49.854,-52.783],[44.426,-43.115],[34.756,-41.406]],"c":true},"ix":2},"nm":"B","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-2.498,-1.009],[0,-5.208],[1.61,-2.18],[6.013,0]],"o":[[0,0],[0,0],[4.108,0],[4.699,1.888],[0,3.093],[-2.563,3.451],[0,0]],"v":[[16.895,-8.301],[16.895,-33.545],[36.364,-33.545],[46.272,-32.031],[53.32,-21.387],[50.905,-13.477],[38.04,-8.301]],"c":true},"ix":2},"nm":"B","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-4.356,5.599],[0,4.623],[3.223,3.125],[3.678,1.4],[-1.335,1.53],[0,4.525],[2.097,2.962],[8.453,0],[0,0]],"o":[[0,0],[9.498,0],[2.914,-3.743],[0,-5.501],[-1.823,-1.758],[2.506,-1.27],[2.571,-2.897],[0,-3.873],[-3.572,-5.013],[0,0],[0,0]],"v":[[7.373,0],[37.883,0],[58.665,-8.398],[63.037,-20.947],[58.203,-33.887],[49.951,-38.623],[55.713,-42.822],[59.57,-53.955],[56.425,-64.209],[38.387,-71.729],[7.373,-71.729]],"c":true},"ix":2},"nm":"B","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"B","np":6,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"a","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,2.533],[-2.718,1.527],[-3.184,0.423],[0,0],[-1.689,0.458],[-1.073,0.686],[0,0],[4.883,-2.373],[3.092,0],[1.855,1.462]],"o":[[0,-3.345],[1.604,-0.909],[0,0],[1.624,-0.195],[1.689,-0.457],[0,0],[0,5.396],[-2.898,1.43],[-2.539,0],[-1.855,-1.462]],"v":[[13.184,-13.897],[17.261,-21.204],[24.443,-23.203],[29.755,-23.885],[34.725,-24.863],[38.867,-26.578],[38.867,-19.509],[31.543,-7.858],[22.559,-5.713],[15.967,-7.905]],"c":true},"ix":2},"nm":"a","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[3.027,-2.666],[0,-4.844],[-3.076,-2.942],[-4.851,0],[-3.353,1.724],[-1.791,2.344],[-0.716,-1.139],[-3.027,0],[-0.716,0.098],[-1.367,0.391],[0,0],[0.488,-0.049],[0.391,0],[0.374,0.552],[0,0.912],[0,0],[3.804,2.344],[6.145,0],[4.015,-2.53],[0.163,-6.464],[0,0],[-1.072,1.375],[-4.581,0],[-2.128,-1.356],[0,-3.006],[0.39,-0.784],[2.018,-0.259]],"o":[[-4.916,0.618],[-3.027,2.666],[0,4.422],[3.076,2.942],[4.036,0],[3.352,-1.725],[0.293,2.083],[1.367,2.148],[1.237,0],[0.716,-0.098],[0,0],[-0.554,0.098],[-0.488,0.049],[-1.205,0],[-0.375,-0.552],[0,0],[0,-4.948],[-3.837,-2.344],[-5.299,0],[-4.015,2.53],[0,0],[0.325,-2.715],[1.917,-2.486],[3.963,0],[2.128,1.357],[0,1.471],[-0.684,1.43],[0,0]],"v":[[20.459,-29.893],[8.545,-24.966],[4.004,-13.702],[8.618,-2.656],[20.508,1.758],[31.592,-0.829],[39.307,-6.932],[40.82,-2.099],[47.412,1.123],[50.342,0.977],[53.467,0.244],[53.467,-6.249],[51.904,-6.03],[50.586,-5.957],[48.218,-6.786],[47.656,-8.982],[47.656,-39.111],[41.95,-50.049],[26.978,-53.564],[13.005,-49.77],[6.738,-36.279],[14.941,-36.279],[17.036,-42.413],[26.783,-46.143],[35.919,-44.109],[39.111,-37.565],[38.526,-34.183],[34.473,-31.648]],"c":true},"ix":2},"nm":"a","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"a","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"C","size":16,"style":"Regular","w":72.22,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[8.976,0],[5.984,-7.361],[0,-10.586],[-7.368,-6.677],[-8.237,0],[-5.631,6.152],[-0.837,7.552],[0,0],[1.95,-2.897],[7.035,0],[3.853,5.229],[0,8.406],[-4.268,4.968],[-6.937,0],[-3.149,-2.702],[-1.055,-4.622],[0,0],[4.955,4.785]],"o":[[-10.521,0],[-5.534,6.776],[0,13.942],[5.598,5.049],[9.557,0],[4.697,-5.11],[0,0],[-0.96,4.72],[-3.677,5.502],[-7.642,0],[-3.854,-5.229],[0,-10.262],[4.268,-4.968],[5.69,0],[3.149,2.702],[0,0],[-0.547,-6.087],[-4.955,-4.785]],"v":[[37.453,-73.682],[12.695,-62.64],[4.395,-36.597],[15.447,-5.669],[36.201,1.904],[58.984,-7.324],[67.285,-26.318],[57.812,-26.318],[53.448,-14.893],[37.379,-6.641],[20.135,-14.484],[14.355,-34.936],[20.757,-57.782],[37.564,-65.234],[50.823,-61.182],[57.129,-50.195],[66.602,-50.195],[58.349,-66.504]],"c":true},"ix":2},"nm":"C","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"C","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"p","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[4.115,0],[2.286,5.404],[0,4.037],[-1.208,3.255],[-6.108,0],[-2.287,-5.762],[0,-4.166],[2.727,-3.434]],"o":[[-6.076,0],[-1.208,-2.832],[0,-5.013],[2.254,-6.087],[6.075,0],[1.208,2.995],[0,6.836],[-2.728,3.435]],"v":[[28.516,-5.908],[15.973,-14.014],[14.16,-24.316],[15.973,-36.719],[28.516,-45.85],[41.058,-37.207],[42.871,-26.465],[38.78,-11.06]],"c":true},"ix":2},"nm":"p","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-1.569,-0.977],[-3.954,0],[-3.791,3.092],[0,11.394],[4.144,4.541],[5.94,0],[2.969,-1.953],[1.762,-2.376],[0,0],[0,0]],"o":[[0,0],[0,0],[1.928,2.377],[2.679,1.725],[5.032,0],[5.98,-4.883],[0,-8.43],[-4.145,-4.541],[-4.015,0],[-2.089,1.302],[0,0],[0,0],[0,0]],"v":[[5.713,20.85],[14.502,20.85],[14.502,-5.859],[19.747,-0.83],[29.698,1.758],[42.934,-2.881],[51.904,-27.295],[45.687,-46.753],[30.56,-53.564],[20.084,-50.635],[14.307,-45.117],[14.307,-52.051],[5.713,-52.051]],"c":true},"ix":2},"nm":"p","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"p","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"y","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[1.007,-2.405],[0.162,-0.26],[0.764,-0.536],[1.624,0],[0.682,0.098],[1.527,0.423],[0,0],[-0.667,-0.098],[-1.236,0],[-2.081,2.927],[-5.074,13.336],[-3.191,8.989],[-1.237,3.355],[0,0]],"o":[[0,0],[0,0],[0,0],[-0.455,1.169],[-1.007,2.403],[-0.52,0.78],[-0.764,0.536],[-0.52,0],[-0.682,-0.098],[0,0],[0.975,0.26],[0.667,0.098],[5.074,0],[2.081,-2.928],[2.148,-5.666],[4.264,-11.952],[0,0],[0,0]],"v":[[25.024,-9.698],[11.011,-52.295],[1.05,-52.295],[20.386,1.538],[18.192,6.898],[16.438,10.894],[14.511,12.868],[10.929,13.672],[9.125,13.525],[5.811,12.744],[5.811,20.752],[8.274,21.289],[11.128,21.436],[21.861,17.044],[32.593,-7.352],[40.601,-29.335],[48.853,-52.295],[39.136,-52.295]],"c":true},"ix":2},"nm":"y","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"y","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"L","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[7.617,0],[53.32,0],[53.32,-8.545],[17.334,-8.545],[17.334,-71.729],[7.617,-71.729]],"c":true},"ix":2},"nm":"L","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"L","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"i","size":16,"style":"Regular","w":22.22,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[6.445,0],[15.381,0],[15.381,-52.051],[6.445,-52.051]],"c":true},"ix":2},"nm":"i","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[6.445,-61.768],[15.381,-61.768],[15.381,-71.729],[6.445,-71.729]],"c":true},"ix":2},"nm":"i","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"i","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"n","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-0.439,1.839],[-1.465,1.726],[-2.409,0.716],[-2.084,0],[-1.562,-3.255],[0,-3.19],[0,0],[0,0],[0,0],[1.432,2.832],[7.422,0],[2.766,-1.334],[2.473,-3.059],[0,0],[0,0]],"o":[[0,0],[0,0],[0,-3.418],[0.439,-1.839],[1.823,-2.148],[1.334,-0.423],[4.102,0],[0.944,1.953],[0,0],[0,0],[0,0],[0,-5.273],[-2.605,-5.176],[-3.386,0],[-2.767,1.335],[0,0],[0,0],[0,0]],"v":[[6.445,0],[15.234,0],[15.234,-27.393],[15.894,-35.278],[18.75,-40.625],[25.098,-44.922],[30.225,-45.557],[38.721,-40.674],[40.137,-32.959],[40.137,0],[49.072,0],[49.072,-33.545],[46.924,-45.703],[31.885,-53.467],[22.656,-51.465],[14.795,-44.873],[14.795,-52.295],[6.445,-52.295]],"c":true},"ix":2},"nm":"n","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"n","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"k","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[6.25,0],[14.697,0],[14.697,-19.629],[21.914,-26.611],[38.362,0],[49.59,0],[28.364,-32.851],[48.463,-52.295],[37.235,-52.295],[14.697,-30.083],[14.697,-71.729],[6.25,-71.729]],"c":true},"ix":2},"nm":"k","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"k","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"}]} \ No newline at end of file +{"v":"4.8.0","meta":{"g":"LottieFiles AE 3.5.2","a":"","k":"","d":"","tc":""},"fr":60,"ip":0,"op":3600,"w":549,"h":830,"nm":"CreateCalendar_Light","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 184","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.72,11.276,0],"ix":2},"a":{"a":0,"k":[4.683,6.77,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0.998],[0,0],[-0.711,0.109],[0,0],[-1.818,0],[0,-2.597],[0,0],[0,-0.902],[0,0],[0.916,0]],"o":[[-0.916,0],[0,0],[0,-0.855],[0,0],[0,-2.597],[1.818,0],[0,0],[0.767,0.074],[0,0],[0,0.998],[0,0]],"v":[[1.367,13.54],[0,12.091],[0,6.972],[1.135,5.557],[1.135,3.848],[4.682,0],[8.23,3.848],[8.23,5.537],[9.366,6.972],[9.366,12.091],[7.999,13.54]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,-1.593],[0,0],[0,0],[0,0],[1.218,0]],"o":[[0,0],[0,0],[0,0],[0,-1.593],[-1.223,0]],"v":[[2.447,3.725],[2.447,5.529],[6.918,5.523],[6.918,3.725],[4.682,1.257]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 184","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_1","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 183","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16.536,16.011,0],"ix":2},"a":{"a":0,"k":[11.944,15.116,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.732,0.722],[0,1.419],[0,0],[-0.732,0.724],[-1.427,0],[0,0],[0,0],[0,0],[0.326,-0.326],[0,-0.644],[0,0],[-0.318,-0.316],[-0.615,0],[0,0],[-0.326,0.326],[0,0.642],[0,0],[0.336,0.316],[0.609,0],[0,0],[0,0],[0,0],[-0.732,-0.73],[0,-1.408],[0,0],[0.732,-0.722],[1.427,0]],"o":[[-1.427,0],[-0.732,-0.724],[0,0],[0,-1.408],[0.732,-0.73],[0,0],[0,0],[0,0],[-0.615,0],[-0.318,0.316],[0,0],[0,0.642],[0.326,0.326],[0,0],[0.609,0],[0.336,-0.316],[0,0],[0,-0.644],[-0.326,-0.326],[0,0],[0,0],[0,0],[1.427,0],[0.732,0.724],[0,0],[0,1.41],[-0.732,0.732],[0,0]],"v":[[4.334,30.231],[1.097,29.149],[0,25.936],[0,12.935],[1.097,9.737],[4.334,8.641],[8.165,8.641],[8.165,11.244],[4.491,11.244],[3.079,11.734],[2.603,13.173],[2.603,25.713],[3.079,27.152],[4.491,27.642],[19.383,27.642],[20.783,27.152],[21.285,25.713],[21.285,13.173],[20.783,11.734],[19.383,11.244],[15.723,11.244],[15.723,8.641],[19.555,8.641],[22.792,9.737],[23.888,12.935],[23.888,25.936],[22.792,29.134],[19.555,30.231]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.336,0],[0.246,0.238],[0,0.326],[0,0],[0,0],[0,0],[0,0],[0.334,0],[0.211,0.195],[0,0.307],[-0.219,0.238],[0,0],[-0.15,0.062],[-0.158,0],[-0.15,-0.062],[-0.16,-0.158],[0,0],[0,-0.283],[0.219,-0.201],[0.299,0],[0.221,0.238],[0,0],[0,0],[0,0],[0,0],[0.248,-0.238]],"o":[[-0.334,0],[-0.238,-0.238],[0,0],[0,0],[0,0],[0,0],[-0.211,0.238],[-0.31,0],[-0.201,-0.201],[0,-0.283],[0,0],[0.166,-0.158],[0.15,-0.062],[0.16,0],[0.15,0.062],[0,0],[0.23,0.238],[0,0.307],[-0.211,0.195],[-0.326,0],[0,0],[0,0],[0,0],[0,0],[0,0.326],[-0.238,0.238]],"v":[[11.943,19.7],[11.072,19.344],[10.715,18.499],[10.715,5.193],[10.822,3.225],[9.99,4.188],[8.138,6.17],[7.32,6.527],[6.539,6.236],[6.236,5.471],[6.566,4.69],[11.006,0.422],[11.482,0.092],[11.943,0],[12.406,0.092],[12.87,0.422],[17.308,4.69],[17.652,5.471],[17.322,6.236],[16.556,6.527],[15.736,6.17],[13.887,4.188],[13.067,3.225],[13.173,5.193],[13.173,18.499],[12.802,19.344]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 183","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_2","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 181","sr":1,"ks":{"o":{"a":0,"k":40,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[22.743,22.253,0],"ix":2},"a":{"a":0,"k":[14.429,11.826,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-0.479],[0.356,-0.356],[0,0],[0.448,0],[0.316,0.304],[0,0.458],[-0.082,0.204],[-0.153,0.154],[0,0],[0,0],[0,0],[0,0],[0,0],[0.316,0.306],[0,0.487],[-0.305,0.306],[-0.509,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0.092,0.194],[0,0.246],[-0.306,0.306],[-0.468,0],[-0.204,-0.092],[-0.183,-0.183],[0,0]],"o":[[0,0.477],[0,0],[-0.356,0.348],[-0.468,0],[-0.306,-0.306],[0,-0.235],[0.092,-0.204],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.509,0],[-0.305,-0.314],[0,-0.5],[0.316,-0.316],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.153,-0.154],[-0.082,-0.204],[0,-0.458],[0.316,-0.306],[0.224,0],[0.204,0.092],[0,0],[0.356,0.356]],"v":[[28.858,11.834],[28.324,13.085],[18.246,23.132],[17.04,23.652],[15.864,23.194],[15.406,22.049],[15.529,21.392],[15.895,20.857],[19.315,17.406],[25.01,12.215],[25.545,13.193],[20.247,13.497],[1.695,13.497],[0.458,13.039],[0,11.834],[0.458,10.627],[1.695,10.155],[20.247,10.155],[25.545,10.475],[25.01,11.468],[19.315,6.261],[15.895,2.795],[15.529,2.275],[15.406,1.603],[15.864,0.458],[17.04,0],[17.681,0.137],[18.262,0.549],[28.324,10.581]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 181","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_3","layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Group 72","refId":"comp_4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,25.585,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_4","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 180","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.583,25.586,0],"ix":2},"a":{"a":0,"k":[11.542,11.543,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.13,0],[0,1.13],[0,0],[0,0],[0,1.13],[1.13,0],[0,0],[0,0],[1.132,0],[0,-1.13],[0,0],[0,0],[0,-1.132],[-1.13,0],[0,0]],"o":[[0,1.13],[1.132,0],[0,0],[0,0],[1.13,0],[0,-1.132],[0,0],[0,0],[0,-1.13],[-1.13,0],[0,0],[0,0],[-1.13,0],[0,1.13],[0,0],[0,0]],"v":[[9.497,21.038],[11.543,23.086],[13.591,21.038],[13.591,13.589],[21.038,13.589],[23.084,11.543],[21.038,9.495],[13.591,9.495],[13.591,2.048],[11.543,0],[9.497,2.048],[9.497,9.495],[2.046,9.495],[0,11.543],[2.046,13.589],[9.497,13.589]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 180","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path 179","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,25.585,0],"ix":2},"a":{"a":0,"k":[25.585,25.585,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.087,-1.32],[3.501,0],[3.085,1.338],[2.358,2.36],[1.336,3.087],[0,3.499],[-1.336,3.089],[-2.344,2.346],[-3.07,1.336],[-3.499,0],[-3.087,-1.338],[-2.358,-2.36],[-1.338,-3.087],[0,-3.501],[1.336,-3.089],[2.36,-2.362]],"o":[[-3.087,1.338],[-3.499,0],[-3.087,-1.32],[-2.344,-2.362],[-1.336,-3.089],[0,-3.501],[1.336,-3.087],[2.358,-2.36],[3.087,-1.338],[3.515,0],[3.087,1.336],[2.36,2.346],[1.336,3.089],[0,3.499],[-1.338,3.087],[-2.358,2.36]],"v":[[35.449,49.163],[25.571,51.169],[15.695,49.163],[7.526,43.641],[2.004,35.468],[0,25.586],[2.004,15.701],[7.526,7.553],[15.67,2.006],[25.548,0],[35.449,2.006],[43.618,7.553],[49.165,15.701],[51.169,25.586],[49.165,35.468],[43.618,43.641]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.909803921569,0.917647058824,0.929411764706,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 179","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_5","layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Group 70","refId":"comp_6","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,25.585,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_6","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 176","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,26.432,0],"ix":2},"a":{"a":0,"k":[14.506,3.092,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.56,0],[0.468,0.275],[0.275,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275],[-0.581,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.275,-0.468],[0.468,-0.285]],"o":[[-0.581,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.275,-0.468],[0.468,-0.285],[0.56,0],[0.468,0.275],[0.275,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275]],"v":[[3.099,6.184],[1.528,5.771],[0.412,4.641],[0,3.099],[0.412,1.542],[1.528,0.427],[3.099,0],[4.641,0.427],[5.757,1.542],[6.169,3.099],[5.757,4.641],[4.641,5.771]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.57,0],[0.468,0.275],[0.285,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275],[-0.568,0],[-0.458,-0.285],[-0.275,-0.468],[0,-0.57],[0.285,-0.468],[0.468,-0.285]],"o":[[-0.568,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.285,-0.468],[0.468,-0.285],[0.57,0],[0.468,0.275],[0.285,0.468],[0,0.56],[-0.275,0.468],[-0.458,0.275]],"v":[[14.505,6.184],[12.948,5.771],[11.818,4.641],[11.406,3.099],[11.818,1.542],[12.948,0.427],[14.505,0],[16.047,0.427],[17.163,1.542],[17.589,3.099],[17.163,4.641],[16.047,5.771]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0.568,0],[0.468,0.275],[0.275,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275],[-0.57,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.285,-0.468],[0.468,-0.285]],"o":[[-0.57,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.275,-0.468],[0.468,-0.285],[0.568,0],[0.468,0.275],[0.285,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275]],"v":[[25.912,6.184],[24.354,5.771],[23.24,4.641],[22.828,3.099],[23.24,1.542],[24.354,0.427],[25.912,0],[27.469,0.427],[28.583,1.542],[29.012,3.099],[28.583,4.641],[27.469,5.771]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 176","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]}],"fonts":{"list":[{"fName":"SF Pro","fFamily":"SF Pro","fStyle":"Regular","ascent":71.8994140625}]},"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[273.5,415.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[36.201,36.201],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[112.601,333.101],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Group 81","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[275,599,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,92],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Path 193","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[115.143,24.95,0],"ix":2},"a":{"a":0,"k":[8.488,10.442,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.426,0.437],[-0.857,0],[0,0],[-0.354,-0.127],[-0.293,-0.304],[0,0],[-0.122,-0.354],[0,-0.509],[0,0],[0.432,-0.437],[0.858,0],[0,0],[0,0],[0,0],[-0.221,0.222],[0,0.416],[0,0],[0,0],[0.238,0.232],[0,0.481],[0,0],[0,0],[0.222,-0.227],[0,-0.416],[0,0]],"o":[[0,0],[0,-0.864],[0.432,-0.437],[0,0],[0.448,0],[0.354,0.122],[0,0],[0.31,0.32],[0.122,0.354],[0,0],[0,0.864],[-0.426,0.437],[0,0],[0,0],[0,0],[0.432,0],[0.221,-0.227],[0,0],[0,0],[-0.476,0],[-0.232,-0.233],[0,0],[0,0],[-0.432,0],[-0.215,0.221],[0,0],[0,0]],"v":[[4.026,4.599],[4.026,2.607],[4.665,0.656],[6.599,0],[9.779,0],[10.982,0.191],[11.953,0.83],[16.145,5.089],[16.793,6.101],[16.975,7.396],[16.975,14.136],[16.328,16.087],[14.402,16.743],[12.692,16.743],[12.692,15.406],[14.327,15.406],[15.307,15.074],[15.639,14.111],[15.639,7.014],[11.754,7.014],[10.683,6.666],[10.335,5.595],[10.335,1.337],[6.666,1.337],[5.686,1.677],[5.363,2.632],[5.363,4.599]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-0.061,-0.066],[-0.144,0],[0,0],[0,0]],"o":[[0,0.149],[0.066,0.061],[0,0],[0,0],[0,0]],"v":[[11.538,5.396],[11.63,5.719],[11.945,5.811],[15.29,5.811],[11.538,1.992]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0.869],[0,0],[-0.426,0.437],[-0.858,0],[0,0],[-0.305,-0.1],[-0.315,-0.327],[0,0],[-0.111,-0.205],[-0.038,-0.243],[0,-0.355],[0,0],[0.432,-0.437],[0.858,0],[0,0],[0.432,0.437]],"o":[[0,0],[0,-0.864],[0.432,-0.437],[0,0],[0.465,0],[0.304,0.099],[0,0],[0.221,0.226],[0.116,0.199],[0.039,0.244],[0,0],[0,0.864],[-0.426,0.437],[0,0],[-0.858,0],[-0.426,-0.431]],"v":[[0,18.278],[0,6.749],[0.639,4.798],[2.574,4.142],[5.504,4.142],[6.658,4.292],[7.587,4.931],[12.161,9.588],[12.659,10.235],[12.891,10.899],[12.95,11.796],[12.95,18.278],[12.302,20.229],[10.376,20.885],[2.574,20.885],[0.639,20.229]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[-0.215,-0.221],[-0.426,0],[0,0],[-0.221,0.227],[0,0.415],[0,0],[0,0],[0.265,0.26],[0,0.526],[0,0],[0,0],[0.222,-0.227],[0,-0.409]],"o":[[0,0.415],[0.222,0.227],[0,0],[0.426,0],[0.221,-0.221],[0,0],[0,0],[-0.514,0],[-0.26,-0.26],[0,0],[0,0],[-0.432,0],[-0.215,0.221],[0,0]],"v":[[1.337,18.254],[1.66,19.208],[2.632,19.548],[10.31,19.548],[11.281,19.208],[11.613,18.254],[11.613,11.862],[6.923,11.862],[5.753,11.472],[5.363,10.293],[5.363,5.479],[2.64,5.479],[1.66,5.819],[1.337,6.765]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[-0.166,0],[0,0],[0,0],[0,0],[-0.072,-0.072]],"o":[[0,0],[0,0],[0,0],[0,0.166],[0.072,0.072]],"v":[[7.081,10.609],[11.356,10.609],[6.616,5.786],[6.616,10.144],[6.724,10.501]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 193","np":7,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Path 192","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[113.327,-25.5,0],"ix":2},"a":{"a":0,"k":[6.672,10.992,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0.166],[-0.09,0.096],[0,0],[-0.159,0],[-0.124,-0.131],[0,0],[0,-0.165],[0.104,-0.104],[0.16,0],[0.124,0.118],[0,0],[0,0],[0,0],[0,0],[0.104,-0.111],[0.166,0],[0.111,0.104],[0,0.159],[0,0],[0,0],[0,0],[0,0],[0.146,0.008],[0.104,0.098]],"o":[[0,-0.165],[0,0],[0.133,-0.131],[0.159,0],[0,0],[0.098,0.096],[0,0.166],[-0.104,0.098],[-0.145,0.008],[0,0],[0,0],[0,0],[0,0],[0,0.159],[-0.104,0.104],[-0.166,0],[-0.104,-0.111],[0,0],[0,0],[0,0],[0,0],[-0.125,0.118],[-0.159,0],[-0.098,-0.104]],"v":[[3.801,9.844],[3.936,9.45],[6.24,7.166],[6.677,6.968],[7.102,7.166],[9.408,9.45],[9.553,9.844],[9.398,10.25],[9.002,10.395],[8.598,10.23],[7.768,9.399],[7.196,8.682],[7.237,10.011],[7.237,12.939],[7.082,13.345],[6.677,13.5],[6.261,13.345],[6.105,12.939],[6.105,10.011],[6.158,8.682],[5.586,9.399],[4.745,10.23],[4.34,10.395],[3.946,10.25]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0.166,0.166],[0,0.291],[0,0],[-0.166,0.174],[-0.284,0],[0,0],[-0.166,-0.173],[0,-0.284],[0,0],[0.173,-0.173],[0.276,0]],"o":[[-0.284,0],[-0.166,-0.173],[0,0],[0,-0.284],[0.166,-0.173],[0,0],[0.276,0],[0.173,0.174],[0,0],[0,0.291],[-0.166,0.166],[0,0]],"v":[[3.924,6.116],[3.25,5.867],[3.001,5.172],[3.001,3.936],[3.25,3.25],[3.924,2.991],[9.429,2.991],[10.093,3.25],[10.352,3.936],[10.352,5.172],[10.093,5.867],[9.429,6.116]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0.809],[0,0],[-0.519,0.492],[-0.844,0],[0,0],[-0.513,-0.498],[0,-0.811],[0,0],[0.519,-0.49],[0.852,0],[0,0],[0.519,0.499]],"o":[[0,0],[0,-0.811],[0.519,-0.498],[0,0],[0.852,0],[0.519,0.492],[0,0],[0,0.809],[-0.513,0.499],[0,0],[-0.844,0],[-0.519,-0.49]],"v":[[0,19.285],[0,2.701],[0.778,0.748],[2.824,0],[10.519,0],[12.565,0.748],[13.343,2.701],[13.343,19.285],[12.565,21.236],[10.519,21.984],[2.824,21.984],[0.778,21.236]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[-0.235,-0.221],[-0.443,0],[0,0],[-0.235,0.228],[0,0.415],[0,0],[0.236,0.221],[0.437,0],[0,0],[0.235,-0.229],[0,-0.415]],"o":[[0,0.415],[0.235,0.228],[0,0],[0.437,0],[0.236,-0.221],[0,0],[0,-0.415],[-0.235,-0.229],[0,0],[-0.443,0],[-0.235,0.221],[0,0]],"v":[[1.671,19.014],[2.024,19.97],[3.043,20.313],[10.311,20.313],[11.318,19.97],[11.672,19.014],[11.672,2.97],[11.318,2.015],[10.311,1.673],[3.043,1.673],[2.024,2.015],[1.671,2.97]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 192","np":6,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":5,"nm":"Copy Link","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-124,31,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"t":{"d":{"k":[{"s":{"s":16,"f":"SF Pro","t":"Copy Link","j":0,"tr":0,"lh":19.2,"ls":0,"fc":[0,0,0]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[{"nm":"Animators","s":{"t":0,"xe":{"k":0},"ne":{"k":0},"a":{"k":100},"b":1,"sh":0,"s":{"k":0},"e":{"k":100},"o":{"k":0}},"a":{"fo":{"a":0,"k":100,"ix":10},"so":{"a":0,"k":100,"ix":11}}}]},"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":5,"nm":"Move Address Bar","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-124,-20,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"t":{"d":{"k":[{"s":{"s":16,"f":"SF Pro","t":"Move Address Bar","j":0,"tr":0,"lh":19.2,"ls":0,"fc":[0,0,0]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[{"nm":"Animators","s":{"t":0,"xe":{"k":0},"ne":{"k":0},"a":{"k":100},"b":1,"sh":0,"s":{"k":0},"e":{"k":100},"o":{"k":0}},"a":{"fo":{"a":0,"k":100,"ix":10},"so":{"a":0,"k":100,"ix":11}}}]},"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Rectangle 91","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,10],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 91 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,10],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.878431372549,0.878431372549,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 91 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Rectangle 90","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":26,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":3,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":20,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,92],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":13,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 90 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,92],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":13,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.952941176471,0.952941176471,0.952941176471,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 90 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Rectangle 85","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,380,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,546],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 85 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,546],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294117647,0.235294117647,0.235294117647,1],"ix":4},"o":{"a":0,"k":20,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 85 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Group 77","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,688.115,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,70],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Path 185","parent":10,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[11.406,2.343,0],"ix":2},"a":{"a":0,"k":[69.753,10.842,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.523,1.105],[0,0],[2.743,0],[0,3.963],[-3.44,0],[0,-3.893],[0,0],[0,0],[0,0],[-2.128,0]],"o":[[0,0],[-0.582,2.14],[-3.475,0],[0,-3.938],[3.382,0],[0,0],[0,0],[0,0],[0.105,2.476],[1.615,0]],"v":[[8.926,14.258],[10.924,14.258],[5.648,17.722],[0,11.248],[5.648,4.752],[11.086,11.051],[11.086,11.818],[2.081,11.818],[2.081,11.91],[5.695,15.955]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[1.986,0],[0.152,-2.22],[0,0]],"o":[[-1.999,0],[0,0],[-0.047,-2.22]],"v":[[5.625,6.519],[2.081,10.203],[8.983,10.203]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[17.615,12.806],[17.431,12.806],[14.454,17.536],[12.189,17.536],[16.478,11.273],[12.142,5.008],[14.524,5.008],[17.501,9.668],[17.685,9.668],[20.625,5.008],[22.892,5.008],[18.638,11.191],[22.95,17.536],[20.58,17.536]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[1.673,0],[0,2.29],[-2.917,0.174],[0,0],[0,0],[1.872,0],[0.281,-0.988],[0,0],[-2.673,0],[0,-2.601],[0,0],[0,0],[0,0],[0,0]],"o":[[-2.429,0],[0,-2.243],[0,0],[0,0],[0,-1.544],[-1.499,0],[0,0],[0.266,-2.009],[3.057,0],[0,0],[0,0],[0,0],[0,0],[-0.814,1.337]],"v":[[28.585,17.722],[24.354,13.991],[28.921,10.285],[32.535,10.063],[32.535,8.924],[29.7,6.531],[26.875,8.087],[24.854,8.087],[29.77,4.752],[34.534,8.924],[34.534,17.501],[32.63,17.501],[32.63,15.654],[32.443,15.654]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[-1.451,0],[0,1.79],[0,0],[0,0],[0,-1.255]],"o":[[2.058,0],[0,0],[0,0],[-1.904,0.127],[0,1.279]],"v":[[28.956,15.967],[32.535,12.829],[32.535,11.679],[29.165,11.9],[26.422,13.944]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[-1.673,0],[-0.58,-1.302],[0,0],[-1.732,0],[0,-2.626],[0,0],[0,0],[0,0],[1.767,0],[0,-1.593],[0,0],[0,0],[0,0],[1.581,0],[0,-1.765],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0.568,-1.394],[1.697,0],[0,0],[0.674,-1.324],[2.556,0],[0,0],[0,0],[0,0],[0,-1.849],[-1.742,0],[0,0],[0,0],[0,0],[0,-1.486],[-1.64,0],[0,0],[0,0]],"v":[[37.658,17.501],[37.658,4.973],[39.565,4.973],[39.565,6.949],[39.751,6.949],[43.248,4.752],[46.711,6.949],[46.897,6.949],[50.733,4.752],[54.718,8.844],[54.718,17.501],[52.719,17.501],[52.719,9.309],[50.081,6.554],[47.176,9.448],[47.176,17.501],[45.178,17.501],[45.178,8.993],[42.564,6.554],[39.657,9.737],[39.657,17.501]],"c":true},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ind":6,"ty":"sh","ix":7,"ks":{"a":0,"k":{"i":[[-1.71,0],[0,-3.94],[3.184,0],[0.687,1.324],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[3.196,0],[0,3.915],[-1.79,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0.802,-1.439]],"v":[[63.898,4.752],[69.162,11.238],[63.898,17.722],[59.98,15.619],[59.796,15.619],[59.796,21.685],[57.797,21.685],[57.797,4.973],[59.702,4.973],[59.702,7.064],[59.888,7.064]],"c":true},"ix":2},"nm":"Path 7","mn":"ADBE Vector Shape - Group","hd":false},{"ind":7,"ty":"sh","ix":8,"ks":{"a":0,"k":{"i":[[-2.253,0],[0,2.927],[2.29,0],[0,-2.882]],"o":[[2.302,0],[0,-2.929],[-2.265,0],[0,2.87]],"v":[[63.42,15.92],[67.094,11.238],[63.433,6.554],[59.736,11.238]],"c":true},"ix":2},"nm":"Path 8","mn":"ADBE Vector Shape - Group","hd":false},{"ind":8,"ty":"sh","ix":9,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[71.844,17.501],[71.844,0],[73.842,0],[73.842,17.501]],"c":true},"ix":2},"nm":"Path 9","mn":"ADBE Vector Shape - Group","hd":false},{"ind":9,"ty":"sh","ix":10,"ks":{"a":0,"k":{"i":[[-0.523,1.105],[0,0],[2.743,0],[0,3.963],[-3.44,0],[0,-3.893],[0,0],[0,0],[0,0],[-2.128,0]],"o":[[0,0],[-0.582,2.14],[-3.475,0],[0,-3.938],[3.382,0],[0,0],[0,0],[0,0],[0.105,2.476],[1.615,0]],"v":[[85.451,14.258],[87.45,14.258],[82.174,17.722],[76.526,11.248],[82.174,4.752],[87.612,11.051],[87.612,11.818],[78.607,11.818],[78.607,11.91],[82.221,15.955]],"c":true},"ix":2},"nm":"Path 10","mn":"ADBE Vector Shape - Group","hd":false},{"ind":10,"ty":"sh","ix":11,"ks":{"a":0,"k":{"i":[[1.986,0],[0.152,-2.22],[0,0]],"o":[[-1.999,0],[0,0],[-0.047,-2.22]],"v":[[82.151,6.519],[78.607,10.203],[85.509,10.203]],"c":true},"ix":2},"nm":"Path 11","mn":"ADBE Vector Shape - Group","hd":false},{"ind":11,"ty":"sh","ix":12,"ks":{"a":0,"k":{"i":[[0.836,0],[0,0.824],[-0.824,0],[0,-0.836]],"o":[[-0.824,0],[0,-0.836],[0.836,0],[0,0.824]],"v":[[91.829,17.618],[90.318,16.107],[91.829,14.596],[93.34,16.107]],"c":true},"ix":2},"nm":"Path 12","mn":"ADBE Vector Shape - Group","hd":false},{"ind":12,"ty":"sh","ix":13,"ks":{"a":0,"k":{"i":[[-0.349,-2.232],[0,0],[1.8,0],[0,-2.835],[-2.232,0],[-0.373,1.417],[0,0],[3.011,0],[0,3.985],[-3.51,0]],"o":[[0,0],[-0.326,-1.244],[-2.255,0],[0,2.892],[1.685,0],[0,0],[-0.361,2.3],[-3.51,0],[0,-3.905],[3.044,0]],"v":[[106.574,8.809],[104.553,8.809],[101.322,6.554],[97.649,11.191],[101.322,15.92],[104.553,13.725],[106.574,13.725],[101.333,17.722],[95.58,11.191],[101.322,4.752]],"c":true},"ix":2},"nm":"Path 13","mn":"ADBE Vector Shape - Group","hd":false},{"ind":13,"ty":"sh","ix":14,"ks":{"a":0,"k":{"i":[[3.567,0],[0,4.02],[-3.569,0],[0,-4.034]],"o":[[-3.569,0],[0,-4.034],[3.567,0],[0,4.02]],"v":[[114.104,17.722],[108.327,11.238],[114.104,4.752],[119.879,11.238]],"c":true},"ix":2},"nm":"Path 14","mn":"ADBE Vector Shape - Group","hd":false},{"ind":14,"ty":"sh","ix":15,"ks":{"a":0,"k":{"i":[[-2.372,0],[0,2.962],[2.37,0],[0,-2.977]],"o":[[2.37,0],[0,-2.977],[-2.372,0],[0,2.962]],"v":[[114.104,15.92],[117.81,11.238],[114.104,6.554],[110.396,11.238]],"c":true},"ix":2},"nm":"Path 15","mn":"ADBE Vector Shape - Group","hd":false},{"ind":15,"ty":"sh","ix":16,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[-1.675,0],[-0.58,-1.302],[0,0],[-1.732,0],[0,-2.626],[0,0],[0,0],[0,0],[1.767,0],[0,-1.593],[0,0],[0,0],[0,0],[1.581,0],[0,-1.765],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0.57,-1.394],[1.695,0],[0,0],[0.674,-1.324],[2.556,0],[0,0],[0,0],[0,0],[0,-1.849],[-1.742,0],[0,0],[0,0],[0,0],[0,-1.486],[-1.638,0],[0,0],[0,0]],"v":[[122.445,17.501],[122.445,4.973],[124.352,4.973],[124.352,6.949],[124.536,6.949],[128.036,4.752],[131.498,6.949],[131.685,6.949],[135.52,4.752],[139.505,8.844],[139.505,17.501],[137.507,17.501],[137.507,9.309],[134.868,6.554],[131.963,9.448],[131.963,17.501],[129.965,17.501],[129.965,8.993],[127.349,6.554],[124.444,9.737],[124.444,17.501]],"c":true},"ix":2},"nm":"Path 16","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 185","np":18,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":0,"nm":"Group 76","parent":10,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-71.782,0.382,0],"ix":2},"a":{"a":0,"k":[7,11.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[13.44,0],[13.44,22.4],[0,22.4]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":14,"h":23,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":0,"nm":"Group 75","parent":10,"refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[216.796,0.801,0],"ix":2},"a":{"a":0,"k":[15.5,15.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[30.8,0],[30.8,30.8],[0,30.8]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":31,"h":31,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Rectangle 70","parent":10,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.452,0.801,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[496.096,50.4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":25,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.909803921569,0.917647058824,0.929411764706,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 70","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Rectangle 69","parent":10,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,70],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 69","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"Path 182","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[52.054,748.211,0],"ix":2},"a":{"a":0,"k":[14.429,11.826,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0.477],[-0.367,0.356],[0,0],[-0.204,0.092],[-0.224,0],[-0.316,-0.306],[0,-0.458],[0.092,-0.204],[0.153,-0.154],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.305,-0.316],[0,-0.5],[0.316,-0.314],[0.509,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.092,-0.204],[0,-0.235],[0.316,-0.306],[0.468,0],[0.356,0.348],[0,0]],"o":[[0,-0.479],[0,0],[0.183,-0.183],[0.204,-0.092],[0.468,0],[0.316,0.306],[0,0.246],[-0.092,0.194],[0,0],[0,0],[0,0],[0,0],[0,0],[0.509,0],[0.316,0.306],[0,0.487],[-0.305,0.306],[0,0],[0,0],[0,0],[0,0],[0,0],[0.153,0.154],[0.092,0.204],[0,0.458],[-0.316,0.304],[-0.448,0],[0,0],[-0.367,-0.356]],"v":[[0,11.834],[0.55,10.581],[10.597,0.549],[11.177,0.137],[11.818,0],[12.994,0.458],[13.467,1.603],[13.33,2.275],[12.963,2.795],[9.543,6.261],[3.863,11.468],[3.313,10.475],[8.612,10.155],[27.164,10.155],[28.385,10.627],[28.858,11.834],[28.385,13.039],[27.164,13.497],[8.612,13.497],[3.313,13.193],[3.863,12.215],[9.543,17.406],[12.963,20.857],[13.33,21.392],[13.467,22.049],[12.994,23.194],[11.818,23.652],[10.612,23.132],[0.55,13.085]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 182","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":17,"ty":0,"nm":"Group 74","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[167.187,748.7,0],"ix":2},"a":{"a":0,"k":[23,23,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[45.485,0],[45.485,45.485],[0,45.485]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":46,"h":46,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":18,"ty":0,"nm":"Group 73","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[276.636,748.7,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":"Path 178","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[386.126,749.23,0],"ix":2},"a":{"a":0,"k":[9.438,6.275,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0.633],[-0.508,0.466],[0,0],[0,0.866],[1.074,0],[0.433,-0.968],[0.541,0],[0,0.624],[-0.058,0.177],[-2.275,0],[0,-2.067],[1.965,-1.857],[0,0],[0,0],[0,0],[0,-0.608],[0.649,0]],"o":[[-0.791,0],[0,-0.475],[0,0],[1.482,-1.424],[0,-0.991],[-0.968,0],[-0.283,0.5],[-0.674,0],[0,-0.191],[0.408,-1.332],[2.548,0],[0,1.465],[0,0],[0,0],[0,0],[0.649,0],[0,0.591],[0,0]],"v":[[1.182,12.284],[0,11.21],[0.691,9.953],[4.273,6.529],[6.138,3.657],[4.298,1.956],[2.231,3.407],[1.116,4.14],[0.042,3.116],[0.133,2.573],[4.323,0],[8.585,3.499],[5.905,7.736],[3.305,10.236],[3.305,10.286],[7.836,10.286],[8.877,11.285],[7.836,12.284]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[2.789,0],[0.566,1.182],[0,0.25],[-0.691,0],[-0.25,-0.458],[-1.249,0],[0,0.999],[1.457,0],[0,0],[0,0.541],[-0.608,0],[0,0],[0,0.982],[1.215,0],[0.393,-0.851],[0.566,0],[0,0.608],[-0.125,0.283],[-2.125,0],[0,-1.925],[1.415,-0.291],[0,0],[0,-1.659]],"o":[[-2.292,0],[-0.133,-0.275],[0,-0.649],[0.5,0],[0.427,0.841],[1.232,0],[0.008,-1.168],[0,0],[-0.608,0],[0,-0.524],[0,0],[1.257,0],[0,-0.968],[-1.016,0],[-0.275,0.566],[-0.699,0],[0,-0.283],[0.533,-1.174],[2.539,0],[0,1.523],[0,0],[1.792,0.167],[0,2.181]],"v":[[14.195,12.55],[9.93,10.377],[9.738,9.586],[10.846,8.529],[11.911,9.187],[14.236,10.527],[16.318,8.812],[14.011,6.995],[13.487,6.995],[12.53,6.096],[13.487,5.205],[13.978,5.205],[16.051,3.54],[14.186,1.931],[12.161,3.207],[11.029,3.982],[9.972,2.966],[10.155,2.156],[14.178,0],[18.434,3.182],[15.926,5.996],[15.926,6.046],[18.876,8.92]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 178","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":20,"ty":0,"nm":"Group 71","refId":"comp_5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[487.004,748.7,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":"Rectangle 77","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,737,0],"ix":2},"a":{"a":0,"k":[262.5,65,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,66],[461,130],[64,130],[0,66]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 77 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,66],[461,130],[64,130],[0,66]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 77 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":"Rectangle 83","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,278,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 83 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 83 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":23,"ty":4,"nm":"Rectangle 81","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,320,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 81 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 81 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":24,"ty":4,"nm":"Rectangle 80","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,362,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 80 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 80 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":25,"ty":4,"nm":"Rectangle 79","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[177,404,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[296,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 79 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[296,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 79 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":26,"ty":4,"nm":"Rectangle 84","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,179,0],"ix":2},"a":{"a":0,"k":[245.5,72,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[11.046,0],[0,0],[0,11.046]],"o":[[0,0],[0,0],[0,0],[0,0],[0,11.046],[0,0],[-11.046,0],[0,0]],"v":[[0,0],[0,0],[491,0],[491,0],[491,124],[471,144],[20,144],[0,124]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 84 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[11.046,0],[0,0],[0,11.046]],"o":[[0,0],[0,0],[0,0],[0,0],[0,11.046],[0,0],[-11.046,0],[0,0]],"v":[[0,0],[0,0],[491,0],[491,0],[491,124],[471,144],[20,144],[0,124]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 84 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":27,"ty":4,"nm":"Rectangle 78","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,575,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,266],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 78 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,266],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 78 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":28,"ty":4,"nm":"Rectangle 76","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,454.5,0],"ix":2},"a":{"a":0,"k":[262.5,347.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,631],[461,695],[64,695],[0,631]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 76 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,631],[461,695],[64,695],[0,631]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 76 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":29,"ty":4,"nm":"Path 161","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":0,"k":[274.5,460.628,0],"ix":2},"a":{"a":0,"k":[274.5,353.372,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-39.692,0],[0,0],[0,-38.817],[0,0],[0,0]],"o":[[0,-38.817],[0,0],[39.692,0],[0,0],[0,0],[0,0]],"v":[[0,70.284],[71.869,0],[477.131,0],[549,70.284],[549,706.744],[0,706.744]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 161","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}],"markers":[],"chars":[{"ch":"M","size":16,"style":"Regular","w":83.3,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0.098,3.597],[0,1.758],[0,0],[0,0],[0,0],[0,0],[0.065,-3.385],[0,-1.465],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,-1.692],[-0.098,-3.596],[0,0],[0,0],[0,0],[0,0],[0,3.874],[-0.066,3.386],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[7.373,0],[16.65,0],[16.65,-42.334],[16.504,-50.269],[16.357,-58.301],[16.357,-60.498],[37.032,0],[46.66,0],[67.139,-60.498],[67.041,-49.609],[66.943,-42.334],[66.943,0],[76.221,0],[76.221,-71.729],[62.398,-71.729],[41.919,-11.084],[21.294,-71.729],[7.373,-71.729]],"c":true},"ix":2},"nm":"M","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"M","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"o","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[5.761,0],[2.414,3.706],[0,5.56],[-2.414,4.097],[-5.312,0],[-2.446,-4.812],[0,-4.877],[2.141,-4.405]],"o":[[-5.247,0],[-2.414,-3.706],[0,-5.787],[2.414,-4.097],[5.987,0],[1.545,3.056],[0,5.397],[-2.141,4.405]],"v":[[27.026,-5.713],[15.535,-11.272],[11.914,-25.172],[15.535,-39.997],[27.122,-46.143],[39.772,-38.924],[42.09,-27.025],[38.879,-12.321]],"c":true},"ix":2},"nm":"o","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[6.691,0],[4.428,-5.203],[0,-8.781],[-4.202,-4.862],[-7.144,0],[-4.073,5.496],[0,8.424],[4.622,4.488]],"o":[[-7.467,0],[-4.428,5.204],[0,8.196],[4.202,4.862],[8.566,0],[4.073,-5.496],[0,-8.716],[-4.623,-4.488]],"v":[[27.366,-53.809],[9.523,-46.003],[2.881,-25.025],[9.184,-5.437],[26.202,1.855],[45.16,-6.389],[51.27,-27.27],[44.336,-47.076]],"c":true},"ix":2},"nm":"o","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"o","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"v","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.562,-52.295],[19.849,0],[29.214,0],[48.901,-52.295],[39.282,-52.295],[24.731,-9.717],[10.767,-52.295]],"c":true},"ix":2},"nm":"v","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"v","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"e","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.688,0],[4.529,-5.241],[0,-8.398],[-4.497,-4.736],[-6.47,0],[-2.1,0.52],[-2.65,2.605],[-1.286,2.361],[-0.228,1.921],[0,0],[1.518,-1.765],[4.554,0],[2.325,3.215],[0.162,5.321],[0,0],[0.517,2.409],[1.747,2.637],[3.461,1.742]],"o":[[-7.312,0],[-4.53,5.241],[0,8.529],[4.497,4.736],[2.649,0],[3.909,-0.912],[1.582,-1.497],[1.286,-2.36],[0,0],[-0.633,2.322],[-2.713,3.041],[-4.877,0],[-2.325,-3.215],[0,0],[0,-5.273],[-0.583,-3.516],[-1.812,-2.766],[-3.462,-1.741]],"v":[[28.022,-53.467],[10.261,-45.605],[3.467,-25.146],[10.211,-5.249],[26.661,1.855],[33.784,1.074],[43.622,-4.199],[47.925,-9.985],[50.195,-16.406],[41.553,-16.406],[38.326,-10.275],[27.425,-5.713],[16.621,-10.535],[12.891,-23.34],[50.928,-23.34],[50.151,-34.863],[46.657,-44.092],[38.747,-50.854]],"c":true},"ix":2},"nm":"e","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-2.711,2.914],[-4.002,0],[-2.389,-4.231],[-0.356,-3.809]],"o":[[0.161,-4.492],[2.711,-2.913],[5.584,0],[1.291,2.279],[0,0]],"v":[[13.086,-30.322],[17.395,-41.431],[27.466,-45.801],[39.425,-39.453],[41.895,-30.322]],"c":true},"ix":2},"nm":"e","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"e","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":" ","size":16,"style":"Regular","w":27.78,"data":{},"fFamily":"SF Pro"},{"ch":"A","size":16,"style":"Regular","w":66.7,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[21.973,-29.395],[33.545,-61.084],[44.434,-29.395]],"c":true},"ix":2},"nm":"A","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[1.465,0],[11.426,0],[19.189,-21.484],[47.559,-21.484],[54.834,0],[65.479,0],[39.453,-71.729],[28.467,-71.729]],"c":true},"ix":2},"nm":"A","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"A","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"d","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,5.599],[-2.737,3.386],[-4.405,0],[-2.689,-3.174],[0,-6.608],[2.607,-3.499],[4.048,0],[2.364,3.777]],"o":[[0,-6.575],[2.737,-3.385],[3.951,0],[2.688,3.174],[0,6.543],[-2.608,3.5],[-5.215,0],[-2.364,-3.776]],"v":[[12.012,-25.537],[16.116,-40.479],[26.829,-45.557],[36.788,-40.796],[40.82,-26.123],[36.909,-11.06],[26.926,-5.811],[15.558,-11.475]],"c":true},"ix":2},"nm":"d","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[3.989,0],[3.875,-5.582],[0,-7.617],[-4.248,-4.899],[-5.804,0],[-2.789,1.432],[-2.043,3.223],[0,0],[0,0],[0,0],[0,0],[0,0],[1.556,0.977]],"o":[[-7.199,0],[-3.875,5.583],[0,8.138],[4.248,4.9],[3.6,0],[2.789,-1.432],[0,0],[0,0],[0,0],[0,0],[0,0],[-1.978,-2.441],[-2.692,-1.692]],"v":[[25.157,-53.223],[8.546,-44.849],[2.734,-25.049],[9.106,-5.493],[24.185,1.855],[33.768,-0.293],[41.016,-7.275],[41.016,0],[48.926,0],[48.926,-71.973],[40.479,-71.973],[40.479,-45.557],[35.177,-50.684]],"c":true},"ix":2},"nm":"d","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"d","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"r","size":16,"style":"Regular","w":33.3,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-2.377,2.849],[-4.427,0],[-0.439,-0.032],[-0.521,-0.098],[0,0],[0.391,0.033],[0.163,0],[2.669,-2.522],[0.684,-1.758],[0,0],[0,0]],"o":[[0,0],[0,0],[0,-3.711],[2.376,-2.848],[0.52,0],[0.439,0.033],[0,0],[-0.945,-0.098],[-0.391,-0.032],[-3.484,0],[-2.67,2.523],[0,0],[0,0],[0,0]],"v":[[6.689,0],[15.479,0],[15.479,-30.078],[19.043,-39.917],[29.248,-44.189],[30.688,-44.141],[32.129,-43.945],[32.129,-53.223],[30.127,-53.418],[29.297,-53.467],[20.068,-49.683],[15.039,-43.262],[15.039,-52.295],[6.689,-52.295]],"c":true},"ix":2},"nm":"r","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"r","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"s","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-3.279,-3.532],[-7.877,0],[-3.576,3.385],[0,4.655],[3.418,2.246],[6.434,1.53],[0,0],[1.326,0.811],[0,2.271],[-1.749,1.265],[-3.399,0],[-2.066,-2.298],[-0.167,-1.974],[0,0],[2.21,2.93],[7.983,0],[3.612,-3.059],[0,-4.948],[-3.838,-2.376],[-4.532,-1.106],[0,0],[-1.291,-0.716],[0,-2.246],[2.525,-1.416],[3.322,0],[2.259,2.832],[0.266,2.93]],"o":[[0.23,5.209],[3.279,3.532],[7.317,0],[3.576,-3.385],[0,-4.817],[-2.19,-1.432],[0,0],[-2.587,-0.618],[-2.299,-1.363],[0,-2.075],[1.749,-1.265],[5.098,0],[1.266,1.619],[0,0],[0.065,-3.385],[-3.529,-4.622],[-6.104,0],[-3.613,3.06],[0,4.199],[2.15,1.367],[0,0],[3.804,0.945],[2.018,1.172],[0,2.962],[-2.525,1.416],[-5.582,0],[-1.23,-1.562],[0,0]],"v":[[3.223,-16.406],[8.488,-3.296],[25.221,2.002],[41.56,-3.076],[46.924,-15.137],[41.797,-25.732],[28.862,-30.176],[22.942,-31.592],[17.072,-33.736],[13.623,-39.185],[16.247,-44.196],[23.969,-46.094],[34.716,-42.646],[36.865,-37.256],[45.166,-37.256],[41.948,-46.729],[24.679,-53.662],[10.106,-49.072],[4.688,-37.061],[10.444,-27.197],[20.467,-23.486],[27.563,-21.729],[35.205,-19.238],[38.232,-14.111],[34.444,-7.544],[25.674,-5.42],[13.912,-9.668],[11.67,-16.406]],"c":true},"ix":2},"nm":"s","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"s","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"B","size":16,"style":"Regular","w":66.7,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-2.171,-0.911],[0,-4.688],[3.618,-1.79],[4.144,0]],"o":[[0,0],[0,0],[4.276,0],[3.848,1.628],[0,4.655],[-2.303,1.14],[0,0]],"v":[[16.895,-41.406],[16.895,-63.623],[34.41,-63.623],[44.081,-62.256],[49.854,-52.783],[44.426,-43.115],[34.756,-41.406]],"c":true},"ix":2},"nm":"B","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-2.498,-1.009],[0,-5.208],[1.61,-2.18],[6.013,0]],"o":[[0,0],[0,0],[4.108,0],[4.699,1.888],[0,3.093],[-2.563,3.451],[0,0]],"v":[[16.895,-8.301],[16.895,-33.545],[36.364,-33.545],[46.272,-32.031],[53.32,-21.387],[50.905,-13.477],[38.04,-8.301]],"c":true},"ix":2},"nm":"B","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-4.356,5.599],[0,4.623],[3.223,3.125],[3.678,1.4],[-1.335,1.53],[0,4.525],[2.097,2.962],[8.453,0],[0,0]],"o":[[0,0],[9.498,0],[2.914,-3.743],[0,-5.501],[-1.823,-1.758],[2.506,-1.27],[2.571,-2.897],[0,-3.873],[-3.572,-5.013],[0,0],[0,0]],"v":[[7.373,0],[37.883,0],[58.665,-8.398],[63.037,-20.947],[58.203,-33.887],[49.951,-38.623],[55.713,-42.822],[59.57,-53.955],[56.425,-64.209],[38.387,-71.729],[7.373,-71.729]],"c":true},"ix":2},"nm":"B","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"B","np":6,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"a","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,2.533],[-2.718,1.527],[-3.184,0.423],[0,0],[-1.689,0.458],[-1.073,0.686],[0,0],[4.883,-2.373],[3.092,0],[1.855,1.462]],"o":[[0,-3.345],[1.604,-0.909],[0,0],[1.624,-0.195],[1.689,-0.457],[0,0],[0,5.396],[-2.898,1.43],[-2.539,0],[-1.855,-1.462]],"v":[[13.184,-13.897],[17.261,-21.204],[24.443,-23.203],[29.755,-23.885],[34.725,-24.863],[38.867,-26.578],[38.867,-19.509],[31.543,-7.858],[22.559,-5.713],[15.967,-7.905]],"c":true},"ix":2},"nm":"a","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[3.027,-2.666],[0,-4.844],[-3.076,-2.942],[-4.851,0],[-3.353,1.724],[-1.791,2.344],[-0.716,-1.139],[-3.027,0],[-0.716,0.098],[-1.367,0.391],[0,0],[0.488,-0.049],[0.391,0],[0.374,0.552],[0,0.912],[0,0],[3.804,2.344],[6.145,0],[4.015,-2.53],[0.163,-6.464],[0,0],[-1.072,1.375],[-4.581,0],[-2.128,-1.356],[0,-3.006],[0.39,-0.784],[2.018,-0.259]],"o":[[-4.916,0.618],[-3.027,2.666],[0,4.422],[3.076,2.942],[4.036,0],[3.352,-1.725],[0.293,2.083],[1.367,2.148],[1.237,0],[0.716,-0.098],[0,0],[-0.554,0.098],[-0.488,0.049],[-1.205,0],[-0.375,-0.552],[0,0],[0,-4.948],[-3.837,-2.344],[-5.299,0],[-4.015,2.53],[0,0],[0.325,-2.715],[1.917,-2.486],[3.963,0],[2.128,1.357],[0,1.471],[-0.684,1.43],[0,0]],"v":[[20.459,-29.893],[8.545,-24.966],[4.004,-13.702],[8.618,-2.656],[20.508,1.758],[31.592,-0.829],[39.307,-6.932],[40.82,-2.099],[47.412,1.123],[50.342,0.977],[53.467,0.244],[53.467,-6.249],[51.904,-6.03],[50.586,-5.957],[48.218,-6.786],[47.656,-8.982],[47.656,-39.111],[41.95,-50.049],[26.978,-53.564],[13.005,-49.77],[6.738,-36.279],[14.941,-36.279],[17.036,-42.413],[26.783,-46.143],[35.919,-44.109],[39.111,-37.565],[38.526,-34.183],[34.473,-31.648]],"c":true},"ix":2},"nm":"a","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"a","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"C","size":16,"style":"Regular","w":72.22,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[8.976,0],[5.984,-7.361],[0,-10.586],[-7.368,-6.677],[-8.237,0],[-5.631,6.152],[-0.837,7.552],[0,0],[1.95,-2.897],[7.035,0],[3.853,5.229],[0,8.406],[-4.268,4.968],[-6.937,0],[-3.149,-2.702],[-1.055,-4.622],[0,0],[4.955,4.785]],"o":[[-10.521,0],[-5.534,6.776],[0,13.942],[5.598,5.049],[9.557,0],[4.697,-5.11],[0,0],[-0.96,4.72],[-3.677,5.502],[-7.642,0],[-3.854,-5.229],[0,-10.262],[4.268,-4.968],[5.69,0],[3.149,2.702],[0,0],[-0.547,-6.087],[-4.955,-4.785]],"v":[[37.453,-73.682],[12.695,-62.64],[4.395,-36.597],[15.447,-5.669],[36.201,1.904],[58.984,-7.324],[67.285,-26.318],[57.812,-26.318],[53.448,-14.893],[37.379,-6.641],[20.135,-14.484],[14.355,-34.936],[20.757,-57.782],[37.564,-65.234],[50.823,-61.182],[57.129,-50.195],[66.602,-50.195],[58.349,-66.504]],"c":true},"ix":2},"nm":"C","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"C","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"p","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[4.115,0],[2.286,5.404],[0,4.037],[-1.208,3.255],[-6.108,0],[-2.287,-5.762],[0,-4.166],[2.727,-3.434]],"o":[[-6.076,0],[-1.208,-2.832],[0,-5.013],[2.254,-6.087],[6.075,0],[1.208,2.995],[0,6.836],[-2.728,3.435]],"v":[[28.516,-5.908],[15.973,-14.014],[14.16,-24.316],[15.973,-36.719],[28.516,-45.85],[41.058,-37.207],[42.871,-26.465],[38.78,-11.06]],"c":true},"ix":2},"nm":"p","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-1.569,-0.977],[-3.954,0],[-3.791,3.092],[0,11.394],[4.144,4.541],[5.94,0],[2.969,-1.953],[1.762,-2.376],[0,0],[0,0]],"o":[[0,0],[0,0],[1.928,2.377],[2.679,1.725],[5.032,0],[5.98,-4.883],[0,-8.43],[-4.145,-4.541],[-4.015,0],[-2.089,1.302],[0,0],[0,0],[0,0]],"v":[[5.713,20.85],[14.502,20.85],[14.502,-5.859],[19.747,-0.83],[29.698,1.758],[42.934,-2.881],[51.904,-27.295],[45.687,-46.753],[30.56,-53.564],[20.084,-50.635],[14.307,-45.117],[14.307,-52.051],[5.713,-52.051]],"c":true},"ix":2},"nm":"p","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"p","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"y","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[1.007,-2.405],[0.162,-0.26],[0.764,-0.536],[1.624,0],[0.682,0.098],[1.527,0.423],[0,0],[-0.667,-0.098],[-1.236,0],[-2.081,2.927],[-5.074,13.336],[-3.191,8.989],[-1.237,3.355],[0,0]],"o":[[0,0],[0,0],[0,0],[-0.455,1.169],[-1.007,2.403],[-0.52,0.78],[-0.764,0.536],[-0.52,0],[-0.682,-0.098],[0,0],[0.975,0.26],[0.667,0.098],[5.074,0],[2.081,-2.928],[2.148,-5.666],[4.264,-11.952],[0,0],[0,0]],"v":[[25.024,-9.698],[11.011,-52.295],[1.05,-52.295],[20.386,1.538],[18.192,6.898],[16.438,10.894],[14.511,12.868],[10.929,13.672],[9.125,13.525],[5.811,12.744],[5.811,20.752],[8.274,21.289],[11.128,21.436],[21.861,17.044],[32.593,-7.352],[40.601,-29.335],[48.853,-52.295],[39.136,-52.295]],"c":true},"ix":2},"nm":"y","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"y","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"L","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[7.617,0],[53.32,0],[53.32,-8.545],[17.334,-8.545],[17.334,-71.729],[7.617,-71.729]],"c":true},"ix":2},"nm":"L","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"L","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"i","size":16,"style":"Regular","w":22.22,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[6.445,0],[15.381,0],[15.381,-52.051],[6.445,-52.051]],"c":true},"ix":2},"nm":"i","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[6.445,-61.768],[15.381,-61.768],[15.381,-71.729],[6.445,-71.729]],"c":true},"ix":2},"nm":"i","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"i","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"n","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-0.439,1.839],[-1.465,1.726],[-2.409,0.716],[-2.084,0],[-1.562,-3.255],[0,-3.19],[0,0],[0,0],[0,0],[1.432,2.832],[7.422,0],[2.766,-1.334],[2.473,-3.059],[0,0],[0,0]],"o":[[0,0],[0,0],[0,-3.418],[0.439,-1.839],[1.823,-2.148],[1.334,-0.423],[4.102,0],[0.944,1.953],[0,0],[0,0],[0,0],[0,-5.273],[-2.605,-5.176],[-3.386,0],[-2.767,1.335],[0,0],[0,0],[0,0]],"v":[[6.445,0],[15.234,0],[15.234,-27.393],[15.894,-35.278],[18.75,-40.625],[25.098,-44.922],[30.225,-45.557],[38.721,-40.674],[40.137,-32.959],[40.137,0],[49.072,0],[49.072,-33.545],[46.924,-45.703],[31.885,-53.467],[22.656,-51.465],[14.795,-44.873],[14.795,-52.295],[6.445,-52.295]],"c":true},"ix":2},"nm":"n","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"n","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"k","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[6.25,0],[14.697,0],[14.697,-19.629],[21.914,-26.611],[38.362,0],[49.59,0],[28.364,-32.851],[48.463,-52.295],[37.235,-52.295],[14.697,-30.083],[14.697,-71.729],[6.25,-71.729]],"c":true},"ix":2},"nm":"k","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"k","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"}]} \ No newline at end of file
diff --git a/ios/chrome/browser/ui/whats_new/data_source/resources/m122/BottomOmnibox_darkmode.json b/ios/chrome/browser/ui/whats_new/data_source/resources/m122/BottomOmnibox_darkmode.json index 5830581..e344d47 100644 --- a/ios/chrome/browser/ui/whats_new/data_source/resources/m122/BottomOmnibox_darkmode.json +++ b/ios/chrome/browser/ui/whats_new/data_source/resources/m122/BottomOmnibox_darkmode.json
@@ -1 +1 @@ -{"v":"4.8.0","meta":{"g":"LottieFiles AE 3.5.2","a":"","k":"","d":"","tc":""},"fr":60,"ip":0,"op":3600,"w":549,"h":830,"nm":"CreateCalendar_Light – 3","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 184","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.72,11.276,0],"ix":2},"a":{"a":0,"k":[4.683,6.77,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0.998],[0,0],[-0.711,0.109],[0,0],[-1.818,0],[0,-2.597],[0,0],[0,-0.902],[0,0],[0.916,0]],"o":[[-0.916,0],[0,0],[0,-0.855],[0,0],[0,-2.597],[1.818,0],[0,0],[0.767,0.074],[0,0],[0,0.998],[0,0]],"v":[[1.367,13.54],[0,12.091],[0,6.972],[1.135,5.557],[1.135,3.848],[4.682,0],[8.23,3.848],[8.23,5.537],[9.366,6.972],[9.366,12.091],[7.999,13.54]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,-1.593],[0,0],[0,0],[0,0],[1.218,0]],"o":[[0,0],[0,0],[0,0],[0,-1.593],[-1.223,0]],"v":[[2.447,3.725],[2.447,5.529],[6.918,5.523],[6.918,3.725],[4.682,1.257]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 184","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_1","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 183","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16.536,16.011,0],"ix":2},"a":{"a":0,"k":[11.944,15.116,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.732,0.722],[0,1.419],[0,0],[-0.732,0.724],[-1.427,0],[0,0],[0,0],[0,0],[0.326,-0.326],[0,-0.644],[0,0],[-0.318,-0.316],[-0.615,0],[0,0],[-0.326,0.326],[0,0.642],[0,0],[0.336,0.316],[0.609,0],[0,0],[0,0],[0,0],[-0.732,-0.73],[0,-1.408],[0,0],[0.732,-0.722],[1.427,0]],"o":[[-1.427,0],[-0.732,-0.724],[0,0],[0,-1.408],[0.732,-0.73],[0,0],[0,0],[0,0],[-0.615,0],[-0.318,0.316],[0,0],[0,0.642],[0.326,0.326],[0,0],[0.609,0],[0.336,-0.316],[0,0],[0,-0.644],[-0.326,-0.326],[0,0],[0,0],[0,0],[1.427,0],[0.732,0.724],[0,0],[0,1.41],[-0.732,0.732],[0,0]],"v":[[4.334,30.231],[1.097,29.149],[0,25.936],[0,12.935],[1.097,9.737],[4.334,8.641],[8.165,8.641],[8.165,11.244],[4.491,11.244],[3.079,11.734],[2.603,13.173],[2.603,25.713],[3.079,27.152],[4.491,27.642],[19.383,27.642],[20.783,27.152],[21.285,25.713],[21.285,13.173],[20.783,11.734],[19.383,11.244],[15.723,11.244],[15.723,8.641],[19.555,8.641],[22.792,9.737],[23.888,12.935],[23.888,25.936],[22.792,29.134],[19.555,30.231]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.336,0],[0.246,0.238],[0,0.326],[0,0],[0,0],[0,0],[0,0],[0.334,0],[0.211,0.195],[0,0.307],[-0.219,0.238],[0,0],[-0.15,0.062],[-0.158,0],[-0.15,-0.062],[-0.16,-0.158],[0,0],[0,-0.283],[0.219,-0.201],[0.299,0],[0.221,0.238],[0,0],[0,0],[0,0],[0,0],[0.248,-0.238]],"o":[[-0.334,0],[-0.238,-0.238],[0,0],[0,0],[0,0],[0,0],[-0.211,0.238],[-0.31,0],[-0.201,-0.201],[0,-0.283],[0,0],[0.166,-0.158],[0.15,-0.062],[0.16,0],[0.15,0.062],[0,0],[0.23,0.238],[0,0.307],[-0.211,0.195],[-0.326,0],[0,0],[0,0],[0,0],[0,0],[0,0.326],[-0.238,0.238]],"v":[[11.943,19.7],[11.072,19.344],[10.715,18.499],[10.715,5.193],[10.822,3.225],[9.99,4.188],[8.138,6.17],[7.32,6.527],[6.539,6.236],[6.236,5.471],[6.566,4.69],[11.006,0.422],[11.482,0.092],[11.943,0],[12.406,0.092],[12.87,0.422],[17.308,4.69],[17.652,5.471],[17.322,6.236],[16.556,6.527],[15.736,6.17],[13.887,4.188],[13.067,3.225],[13.173,5.193],[13.173,18.499],[12.802,19.344]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 183","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_2","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 181","sr":1,"ks":{"o":{"a":0,"k":40,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[22.743,22.253,0],"ix":2},"a":{"a":0,"k":[14.429,11.826,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-0.479],[0.356,-0.356],[0,0],[0.448,0],[0.316,0.304],[0,0.458],[-0.082,0.204],[-0.153,0.154],[0,0],[0,0],[0,0],[0,0],[0,0],[0.316,0.306],[0,0.487],[-0.305,0.306],[-0.509,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0.092,0.194],[0,0.246],[-0.306,0.306],[-0.468,0],[-0.204,-0.092],[-0.183,-0.183],[0,0]],"o":[[0,0.477],[0,0],[-0.356,0.348],[-0.468,0],[-0.306,-0.306],[0,-0.235],[0.092,-0.204],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.509,0],[-0.305,-0.314],[0,-0.5],[0.316,-0.316],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.153,-0.154],[-0.082,-0.204],[0,-0.458],[0.316,-0.306],[0.224,0],[0.204,0.092],[0,0],[0.356,0.356]],"v":[[28.858,11.834],[28.324,13.085],[18.246,23.132],[17.04,23.652],[15.864,23.194],[15.406,22.049],[15.529,21.392],[15.895,20.857],[19.315,17.406],[25.01,12.215],[25.545,13.193],[20.247,13.497],[1.695,13.497],[0.458,13.039],[0,11.834],[0.458,10.627],[1.695,10.155],[20.247,10.155],[25.545,10.475],[25.01,11.468],[19.315,6.261],[15.895,2.795],[15.529,2.275],[15.406,1.603],[15.864,0.458],[17.04,0],[17.681,0.137],[18.262,0.549],[28.324,10.581]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 181","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_3","layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Group 72","refId":"comp_4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,25.585,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_4","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 180","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.583,25.586,0],"ix":2},"a":{"a":0,"k":[11.542,11.543,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.13,0],[0,1.13],[0,0],[0,0],[0,1.13],[1.13,0],[0,0],[0,0],[1.132,0],[0,-1.13],[0,0],[0,0],[0,-1.132],[-1.13,0],[0,0]],"o":[[0,1.13],[1.132,0],[0,0],[0,0],[1.13,0],[0,-1.132],[0,0],[0,0],[0,-1.13],[-1.13,0],[0,0],[0,0],[-1.13,0],[0,1.13],[0,0],[0,0]],"v":[[9.497,21.038],[11.543,23.086],[13.591,21.038],[13.591,13.589],[21.038,13.589],[23.084,11.543],[21.038,9.495],[13.591,9.495],[13.591,2.048],[11.543,0],[9.497,2.048],[9.497,9.495],[2.046,9.495],[0,11.543],[2.046,13.589],[9.497,13.589]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 180","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path 179","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,25.585,0],"ix":2},"a":{"a":0,"k":[25.585,25.585,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.087,-1.32],[3.501,0],[3.085,1.338],[2.358,2.36],[1.336,3.087],[0,3.499],[-1.336,3.089],[-2.344,2.346],[-3.07,1.336],[-3.499,0],[-3.087,-1.338],[-2.358,-2.36],[-1.338,-3.087],[0,-3.501],[1.336,-3.089],[2.36,-2.362]],"o":[[-3.087,1.338],[-3.499,0],[-3.087,-1.32],[-2.344,-2.362],[-1.336,-3.089],[0,-3.501],[1.336,-3.087],[2.358,-2.36],[3.087,-1.338],[3.515,0],[3.087,1.336],[2.36,2.346],[1.336,3.089],[0,3.499],[-1.338,3.087],[-2.358,2.36]],"v":[[35.449,49.163],[25.571,51.169],[15.695,49.163],[7.526,43.641],[2.004,35.468],[0,25.586],[2.004,15.701],[7.526,7.553],[15.67,2.006],[25.548,0],[35.449,2.006],[43.618,7.553],[49.165,15.701],[51.169,25.586],[49.165,35.468],[43.618,43.641]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.909803921569,0.917647058824,0.929411764706,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 179","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_5","layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Group 70","refId":"comp_6","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,25.585,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_6","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 176","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,26.432,0],"ix":2},"a":{"a":0,"k":[14.506,3.092,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.56,0],[0.468,0.275],[0.275,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275],[-0.581,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.275,-0.468],[0.468,-0.285]],"o":[[-0.581,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.275,-0.468],[0.468,-0.285],[0.56,0],[0.468,0.275],[0.275,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275]],"v":[[3.099,6.184],[1.528,5.771],[0.412,4.641],[0,3.099],[0.412,1.542],[1.528,0.427],[3.099,0],[4.641,0.427],[5.757,1.542],[6.169,3.099],[5.757,4.641],[4.641,5.771]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.57,0],[0.468,0.275],[0.285,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275],[-0.568,0],[-0.458,-0.285],[-0.275,-0.468],[0,-0.57],[0.285,-0.468],[0.468,-0.285]],"o":[[-0.568,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.285,-0.468],[0.468,-0.285],[0.57,0],[0.468,0.275],[0.285,0.468],[0,0.56],[-0.275,0.468],[-0.458,0.275]],"v":[[14.505,6.184],[12.948,5.771],[11.818,4.641],[11.406,3.099],[11.818,1.542],[12.948,0.427],[14.505,0],[16.047,0.427],[17.163,1.542],[17.589,3.099],[17.163,4.641],[16.047,5.771]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0.568,0],[0.468,0.275],[0.275,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275],[-0.57,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.285,-0.468],[0.468,-0.285]],"o":[[-0.57,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.275,-0.468],[0.468,-0.285],[0.568,0],[0.468,0.275],[0.285,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275]],"v":[[25.912,6.184],[24.354,5.771],[23.24,4.641],[22.828,3.099],[23.24,1.542],[24.354,0.427],[25.912,0],[27.469,0.427],[28.583,1.542],[29.012,3.099],[28.583,4.641],[27.469,5.771]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 176","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]}],"fonts":{"list":[{"fName":"SF Pro","fFamily":"SF Pro","fStyle":"Regular","ascent":71.8994140625}]},"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Group 81","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[275,599,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,92],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path 193","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[115.143,24.95,0],"ix":2},"a":{"a":0,"k":[8.488,10.442,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.426,0.437],[-0.857,0],[0,0],[-0.354,-0.127],[-0.293,-0.304],[0,0],[-0.122,-0.354],[0,-0.509],[0,0],[0.432,-0.437],[0.858,0],[0,0],[0,0],[0,0],[-0.221,0.222],[0,0.416],[0,0],[0,0],[0.238,0.232],[0,0.481],[0,0],[0,0],[0.222,-0.227],[0,-0.416],[0,0]],"o":[[0,0],[0,-0.864],[0.432,-0.437],[0,0],[0.448,0],[0.354,0.122],[0,0],[0.31,0.32],[0.122,0.354],[0,0],[0,0.864],[-0.426,0.437],[0,0],[0,0],[0,0],[0.432,0],[0.221,-0.227],[0,0],[0,0],[-0.476,0],[-0.232,-0.233],[0,0],[0,0],[-0.432,0],[-0.215,0.221],[0,0],[0,0]],"v":[[4.026,4.599],[4.026,2.607],[4.665,0.656],[6.599,0],[9.779,0],[10.982,0.191],[11.953,0.83],[16.145,5.089],[16.793,6.101],[16.975,7.396],[16.975,14.136],[16.328,16.087],[14.402,16.743],[12.692,16.743],[12.692,15.406],[14.327,15.406],[15.307,15.074],[15.639,14.111],[15.639,7.014],[11.754,7.014],[10.683,6.666],[10.335,5.595],[10.335,1.337],[6.666,1.337],[5.686,1.677],[5.363,2.632],[5.363,4.599]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-0.061,-0.066],[-0.144,0],[0,0],[0,0]],"o":[[0,0.149],[0.066,0.061],[0,0],[0,0],[0,0]],"v":[[11.538,5.396],[11.63,5.719],[11.945,5.811],[15.29,5.811],[11.538,1.992]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0.869],[0,0],[-0.426,0.437],[-0.858,0],[0,0],[-0.305,-0.1],[-0.315,-0.327],[0,0],[-0.111,-0.205],[-0.038,-0.243],[0,-0.355],[0,0],[0.432,-0.437],[0.858,0],[0,0],[0.432,0.437]],"o":[[0,0],[0,-0.864],[0.432,-0.437],[0,0],[0.465,0],[0.304,0.099],[0,0],[0.221,0.226],[0.116,0.199],[0.039,0.244],[0,0],[0,0.864],[-0.426,0.437],[0,0],[-0.858,0],[-0.426,-0.431]],"v":[[0,18.278],[0,6.749],[0.639,4.798],[2.574,4.142],[5.504,4.142],[6.658,4.292],[7.587,4.931],[12.161,9.588],[12.659,10.235],[12.891,10.899],[12.95,11.796],[12.95,18.278],[12.302,20.229],[10.376,20.885],[2.574,20.885],[0.639,20.229]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[-0.215,-0.221],[-0.426,0],[0,0],[-0.221,0.227],[0,0.415],[0,0],[0,0],[0.265,0.26],[0,0.526],[0,0],[0,0],[0.222,-0.227],[0,-0.409]],"o":[[0,0.415],[0.222,0.227],[0,0],[0.426,0],[0.221,-0.221],[0,0],[0,0],[-0.514,0],[-0.26,-0.26],[0,0],[0,0],[-0.432,0],[-0.215,0.221],[0,0]],"v":[[1.337,18.254],[1.66,19.208],[2.632,19.548],[10.31,19.548],[11.281,19.208],[11.613,18.254],[11.613,11.862],[6.923,11.862],[5.753,11.472],[5.363,10.293],[5.363,5.479],[2.64,5.479],[1.66,5.819],[1.337,6.765]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[-0.166,0],[0,0],[0,0],[0,0],[-0.072,-0.072]],"o":[[0,0],[0,0],[0,0],[0,0.166],[0.072,0.072]],"v":[[7.081,10.609],[11.356,10.609],[6.616,5.786],[6.616,10.144],[6.724,10.501]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 193","np":7,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Path 192","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[113.327,-25.5,0],"ix":2},"a":{"a":0,"k":[6.672,10.992,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0.166],[-0.09,0.096],[0,0],[-0.159,0],[-0.124,-0.131],[0,0],[0,-0.165],[0.104,-0.104],[0.16,0],[0.124,0.118],[0,0],[0,0],[0,0],[0,0],[0.104,-0.111],[0.166,0],[0.111,0.104],[0,0.159],[0,0],[0,0],[0,0],[0,0],[0.146,0.008],[0.104,0.098]],"o":[[0,-0.165],[0,0],[0.133,-0.131],[0.159,0],[0,0],[0.098,0.096],[0,0.166],[-0.104,0.098],[-0.145,0.008],[0,0],[0,0],[0,0],[0,0],[0,0.159],[-0.104,0.104],[-0.166,0],[-0.104,-0.111],[0,0],[0,0],[0,0],[0,0],[-0.125,0.118],[-0.159,0],[-0.098,-0.104]],"v":[[3.801,9.844],[3.936,9.45],[6.24,7.166],[6.677,6.968],[7.102,7.166],[9.408,9.45],[9.553,9.844],[9.398,10.25],[9.002,10.395],[8.598,10.23],[7.768,9.399],[7.196,8.682],[7.237,10.011],[7.237,12.939],[7.082,13.345],[6.677,13.5],[6.261,13.345],[6.105,12.939],[6.105,10.011],[6.158,8.682],[5.586,9.399],[4.745,10.23],[4.34,10.395],[3.946,10.25]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0.166,0.166],[0,0.291],[0,0],[-0.166,0.174],[-0.284,0],[0,0],[-0.166,-0.173],[0,-0.284],[0,0],[0.173,-0.173],[0.276,0]],"o":[[-0.284,0],[-0.166,-0.173],[0,0],[0,-0.284],[0.166,-0.173],[0,0],[0.276,0],[0.173,0.174],[0,0],[0,0.291],[-0.166,0.166],[0,0]],"v":[[3.924,6.116],[3.25,5.867],[3.001,5.172],[3.001,3.936],[3.25,3.25],[3.924,2.991],[9.429,2.991],[10.093,3.25],[10.352,3.936],[10.352,5.172],[10.093,5.867],[9.429,6.116]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0.809],[0,0],[-0.519,0.492],[-0.844,0],[0,0],[-0.513,-0.498],[0,-0.811],[0,0],[0.519,-0.49],[0.852,0],[0,0],[0.519,0.499]],"o":[[0,0],[0,-0.811],[0.519,-0.498],[0,0],[0.852,0],[0.519,0.492],[0,0],[0,0.809],[-0.513,0.499],[0,0],[-0.844,0],[-0.519,-0.49]],"v":[[0,19.285],[0,2.701],[0.778,0.748],[2.824,0],[10.519,0],[12.565,0.748],[13.343,2.701],[13.343,19.285],[12.565,21.236],[10.519,21.984],[2.824,21.984],[0.778,21.236]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[-0.235,-0.221],[-0.443,0],[0,0],[-0.235,0.228],[0,0.415],[0,0],[0.236,0.221],[0.437,0],[0,0],[0.235,-0.229],[0,-0.415]],"o":[[0,0.415],[0.235,0.228],[0,0],[0.437,0],[0.236,-0.221],[0,0],[0,-0.415],[-0.235,-0.229],[0,0],[-0.443,0],[-0.235,0.221],[0,0]],"v":[[1.671,19.014],[2.024,19.97],[3.043,20.313],[10.311,20.313],[11.318,19.97],[11.672,19.014],[11.672,2.97],[11.318,2.015],[10.311,1.673],[3.043,1.673],[2.024,2.015],[1.671,2.97]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 192","np":6,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":5,"nm":"Copy Link","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-124,31,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"t":{"d":{"k":[{"s":{"s":16,"f":"SF Pro","t":"Copy Link","j":0,"tr":0,"lh":19.2,"ls":0,"fc":[0,0,0]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[{"nm":"Animators","s":{"t":0,"xe":{"k":0},"ne":{"k":0},"a":{"k":100},"b":1,"sh":0,"s":{"k":0},"e":{"k":100},"o":{"k":0}},"a":{"fo":{"a":0,"k":100,"ix":10},"so":{"a":0,"k":100,"ix":11}}}]},"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":5,"nm":"Move Address Bar","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-124,-20,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"t":{"d":{"k":[{"s":{"s":16,"f":"SF Pro","t":"Move Address Bar","j":0,"tr":0,"lh":19.2,"ls":0,"fc":[0,0,0]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[{"nm":"Animators","s":{"t":0,"xe":{"k":0},"ne":{"k":0},"a":{"k":100},"b":1,"sh":0,"s":{"k":0},"e":{"k":100},"o":{"k":0}},"a":{"fo":{"a":0,"k":100,"ix":10},"so":{"a":0,"k":100,"ix":11}}}]},"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Rectangle 91","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,10],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 91 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,10],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.878431372549,0.878431372549,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 91 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Rectangle 90","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":26,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":3,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":20,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,92],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":13,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 90 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,92],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":13,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.952941176471,0.952941176471,0.952941176471,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 90 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Rectangle 85","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,380,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,546],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 85 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,546],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294117647,0.235294117647,0.235294117647,1],"ix":4},"o":{"a":0,"k":20,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 85 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Group 77","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,688.115,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,70],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Path 185","parent":9,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[11.406,2.343,0],"ix":2},"a":{"a":0,"k":[69.753,10.842,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.523,1.105],[0,0],[2.743,0],[0,3.963],[-3.44,0],[0,-3.893],[0,0],[0,0],[0,0],[-2.128,0]],"o":[[0,0],[-0.582,2.14],[-3.475,0],[0,-3.938],[3.382,0],[0,0],[0,0],[0,0],[0.105,2.476],[1.615,0]],"v":[[8.926,14.258],[10.924,14.258],[5.648,17.722],[0,11.248],[5.648,4.752],[11.086,11.051],[11.086,11.818],[2.081,11.818],[2.081,11.91],[5.695,15.955]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[1.986,0],[0.152,-2.22],[0,0]],"o":[[-1.999,0],[0,0],[-0.047,-2.22]],"v":[[5.625,6.519],[2.081,10.203],[8.983,10.203]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[17.615,12.806],[17.431,12.806],[14.454,17.536],[12.189,17.536],[16.478,11.273],[12.142,5.008],[14.524,5.008],[17.501,9.668],[17.685,9.668],[20.625,5.008],[22.892,5.008],[18.638,11.191],[22.95,17.536],[20.58,17.536]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[1.673,0],[0,2.29],[-2.917,0.174],[0,0],[0,0],[1.872,0],[0.281,-0.988],[0,0],[-2.673,0],[0,-2.601],[0,0],[0,0],[0,0],[0,0]],"o":[[-2.429,0],[0,-2.243],[0,0],[0,0],[0,-1.544],[-1.499,0],[0,0],[0.266,-2.009],[3.057,0],[0,0],[0,0],[0,0],[0,0],[-0.814,1.337]],"v":[[28.585,17.722],[24.354,13.991],[28.921,10.285],[32.535,10.063],[32.535,8.924],[29.7,6.531],[26.875,8.087],[24.854,8.087],[29.77,4.752],[34.534,8.924],[34.534,17.501],[32.63,17.501],[32.63,15.654],[32.443,15.654]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[-1.451,0],[0,1.79],[0,0],[0,0],[0,-1.255]],"o":[[2.058,0],[0,0],[0,0],[-1.904,0.127],[0,1.279]],"v":[[28.956,15.967],[32.535,12.829],[32.535,11.679],[29.165,11.9],[26.422,13.944]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[-1.673,0],[-0.58,-1.302],[0,0],[-1.732,0],[0,-2.626],[0,0],[0,0],[0,0],[1.767,0],[0,-1.593],[0,0],[0,0],[0,0],[1.581,0],[0,-1.765],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0.568,-1.394],[1.697,0],[0,0],[0.674,-1.324],[2.556,0],[0,0],[0,0],[0,0],[0,-1.849],[-1.742,0],[0,0],[0,0],[0,0],[0,-1.486],[-1.64,0],[0,0],[0,0]],"v":[[37.658,17.501],[37.658,4.973],[39.565,4.973],[39.565,6.949],[39.751,6.949],[43.248,4.752],[46.711,6.949],[46.897,6.949],[50.733,4.752],[54.718,8.844],[54.718,17.501],[52.719,17.501],[52.719,9.309],[50.081,6.554],[47.176,9.448],[47.176,17.501],[45.178,17.501],[45.178,8.993],[42.564,6.554],[39.657,9.737],[39.657,17.501]],"c":true},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ind":6,"ty":"sh","ix":7,"ks":{"a":0,"k":{"i":[[-1.71,0],[0,-3.94],[3.184,0],[0.687,1.324],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[3.196,0],[0,3.915],[-1.79,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0.802,-1.439]],"v":[[63.898,4.752],[69.162,11.238],[63.898,17.722],[59.98,15.619],[59.796,15.619],[59.796,21.685],[57.797,21.685],[57.797,4.973],[59.702,4.973],[59.702,7.064],[59.888,7.064]],"c":true},"ix":2},"nm":"Path 7","mn":"ADBE Vector Shape - Group","hd":false},{"ind":7,"ty":"sh","ix":8,"ks":{"a":0,"k":{"i":[[-2.253,0],[0,2.927],[2.29,0],[0,-2.882]],"o":[[2.302,0],[0,-2.929],[-2.265,0],[0,2.87]],"v":[[63.42,15.92],[67.094,11.238],[63.433,6.554],[59.736,11.238]],"c":true},"ix":2},"nm":"Path 8","mn":"ADBE Vector Shape - Group","hd":false},{"ind":8,"ty":"sh","ix":9,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[71.844,17.501],[71.844,0],[73.842,0],[73.842,17.501]],"c":true},"ix":2},"nm":"Path 9","mn":"ADBE Vector Shape - Group","hd":false},{"ind":9,"ty":"sh","ix":10,"ks":{"a":0,"k":{"i":[[-0.523,1.105],[0,0],[2.743,0],[0,3.963],[-3.44,0],[0,-3.893],[0,0],[0,0],[0,0],[-2.128,0]],"o":[[0,0],[-0.582,2.14],[-3.475,0],[0,-3.938],[3.382,0],[0,0],[0,0],[0,0],[0.105,2.476],[1.615,0]],"v":[[85.451,14.258],[87.45,14.258],[82.174,17.722],[76.526,11.248],[82.174,4.752],[87.612,11.051],[87.612,11.818],[78.607,11.818],[78.607,11.91],[82.221,15.955]],"c":true},"ix":2},"nm":"Path 10","mn":"ADBE Vector Shape - Group","hd":false},{"ind":10,"ty":"sh","ix":11,"ks":{"a":0,"k":{"i":[[1.986,0],[0.152,-2.22],[0,0]],"o":[[-1.999,0],[0,0],[-0.047,-2.22]],"v":[[82.151,6.519],[78.607,10.203],[85.509,10.203]],"c":true},"ix":2},"nm":"Path 11","mn":"ADBE Vector Shape - Group","hd":false},{"ind":11,"ty":"sh","ix":12,"ks":{"a":0,"k":{"i":[[0.836,0],[0,0.824],[-0.824,0],[0,-0.836]],"o":[[-0.824,0],[0,-0.836],[0.836,0],[0,0.824]],"v":[[91.829,17.618],[90.318,16.107],[91.829,14.596],[93.34,16.107]],"c":true},"ix":2},"nm":"Path 12","mn":"ADBE Vector Shape - Group","hd":false},{"ind":12,"ty":"sh","ix":13,"ks":{"a":0,"k":{"i":[[-0.349,-2.232],[0,0],[1.8,0],[0,-2.835],[-2.232,0],[-0.373,1.417],[0,0],[3.011,0],[0,3.985],[-3.51,0]],"o":[[0,0],[-0.326,-1.244],[-2.255,0],[0,2.892],[1.685,0],[0,0],[-0.361,2.3],[-3.51,0],[0,-3.905],[3.044,0]],"v":[[106.574,8.809],[104.553,8.809],[101.322,6.554],[97.649,11.191],[101.322,15.92],[104.553,13.725],[106.574,13.725],[101.333,17.722],[95.58,11.191],[101.322,4.752]],"c":true},"ix":2},"nm":"Path 13","mn":"ADBE Vector Shape - Group","hd":false},{"ind":13,"ty":"sh","ix":14,"ks":{"a":0,"k":{"i":[[3.567,0],[0,4.02],[-3.569,0],[0,-4.034]],"o":[[-3.569,0],[0,-4.034],[3.567,0],[0,4.02]],"v":[[114.104,17.722],[108.327,11.238],[114.104,4.752],[119.879,11.238]],"c":true},"ix":2},"nm":"Path 14","mn":"ADBE Vector Shape - Group","hd":false},{"ind":14,"ty":"sh","ix":15,"ks":{"a":0,"k":{"i":[[-2.372,0],[0,2.962],[2.37,0],[0,-2.977]],"o":[[2.37,0],[0,-2.977],[-2.372,0],[0,2.962]],"v":[[114.104,15.92],[117.81,11.238],[114.104,6.554],[110.396,11.238]],"c":true},"ix":2},"nm":"Path 15","mn":"ADBE Vector Shape - Group","hd":false},{"ind":15,"ty":"sh","ix":16,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[-1.675,0],[-0.58,-1.302],[0,0],[-1.732,0],[0,-2.626],[0,0],[0,0],[0,0],[1.767,0],[0,-1.593],[0,0],[0,0],[0,0],[1.581,0],[0,-1.765],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0.57,-1.394],[1.695,0],[0,0],[0.674,-1.324],[2.556,0],[0,0],[0,0],[0,0],[0,-1.849],[-1.742,0],[0,0],[0,0],[0,0],[0,-1.486],[-1.638,0],[0,0],[0,0]],"v":[[122.445,17.501],[122.445,4.973],[124.352,4.973],[124.352,6.949],[124.536,6.949],[128.036,4.752],[131.498,6.949],[131.685,6.949],[135.52,4.752],[139.505,8.844],[139.505,17.501],[137.507,17.501],[137.507,9.309],[134.868,6.554],[131.963,9.448],[131.963,17.501],[129.965,17.501],[129.965,8.993],[127.349,6.554],[124.444,9.737],[124.444,17.501]],"c":true},"ix":2},"nm":"Path 16","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 185","np":18,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":0,"nm":"Group 76","parent":9,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-71.782,0.382,0],"ix":2},"a":{"a":0,"k":[7,11.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[13.44,0],[13.44,22.4],[0,22.4]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":14,"h":23,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":0,"nm":"Group 75","parent":9,"refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[216.796,0.801,0],"ix":2},"a":{"a":0,"k":[15.5,15.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[30.8,0],[30.8,30.8],[0,30.8]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":31,"h":31,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Rectangle 70","parent":9,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.452,0.801,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[496.096,50.4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":25,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.909803921569,0.917647058824,0.929411764706,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 70","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Rectangle 69","parent":9,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,70],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 69","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Path 182","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[52.054,748.211,0],"ix":2},"a":{"a":0,"k":[14.429,11.826,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0.477],[-0.367,0.356],[0,0],[-0.204,0.092],[-0.224,0],[-0.316,-0.306],[0,-0.458],[0.092,-0.204],[0.153,-0.154],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.305,-0.316],[0,-0.5],[0.316,-0.314],[0.509,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.092,-0.204],[0,-0.235],[0.316,-0.306],[0.468,0],[0.356,0.348],[0,0]],"o":[[0,-0.479],[0,0],[0.183,-0.183],[0.204,-0.092],[0.468,0],[0.316,0.306],[0,0.246],[-0.092,0.194],[0,0],[0,0],[0,0],[0,0],[0,0],[0.509,0],[0.316,0.306],[0,0.487],[-0.305,0.306],[0,0],[0,0],[0,0],[0,0],[0,0],[0.153,0.154],[0.092,0.204],[0,0.458],[-0.316,0.304],[-0.448,0],[0,0],[-0.367,-0.356]],"v":[[0,11.834],[0.55,10.581],[10.597,0.549],[11.177,0.137],[11.818,0],[12.994,0.458],[13.467,1.603],[13.33,2.275],[12.963,2.795],[9.543,6.261],[3.863,11.468],[3.313,10.475],[8.612,10.155],[27.164,10.155],[28.385,10.627],[28.858,11.834],[28.385,13.039],[27.164,13.497],[8.612,13.497],[3.313,13.193],[3.863,12.215],[9.543,17.406],[12.963,20.857],[13.33,21.392],[13.467,22.049],[12.994,23.194],[11.818,23.652],[10.612,23.132],[0.55,13.085]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 182","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":0,"nm":"Group 74","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[167.187,748.7,0],"ix":2},"a":{"a":0,"k":[23,23,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[45.485,0],[45.485,45.485],[0,45.485]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":46,"h":46,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":17,"ty":0,"nm":"Group 73","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[276.636,748.7,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":"Path 178","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[386.126,749.23,0],"ix":2},"a":{"a":0,"k":[9.438,6.275,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0.633],[-0.508,0.466],[0,0],[0,0.866],[1.074,0],[0.433,-0.968],[0.541,0],[0,0.624],[-0.058,0.177],[-2.275,0],[0,-2.067],[1.965,-1.857],[0,0],[0,0],[0,0],[0,-0.608],[0.649,0]],"o":[[-0.791,0],[0,-0.475],[0,0],[1.482,-1.424],[0,-0.991],[-0.968,0],[-0.283,0.5],[-0.674,0],[0,-0.191],[0.408,-1.332],[2.548,0],[0,1.465],[0,0],[0,0],[0,0],[0.649,0],[0,0.591],[0,0]],"v":[[1.182,12.284],[0,11.21],[0.691,9.953],[4.273,6.529],[6.138,3.657],[4.298,1.956],[2.231,3.407],[1.116,4.14],[0.042,3.116],[0.133,2.573],[4.323,0],[8.585,3.499],[5.905,7.736],[3.305,10.236],[3.305,10.286],[7.836,10.286],[8.877,11.285],[7.836,12.284]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[2.789,0],[0.566,1.182],[0,0.25],[-0.691,0],[-0.25,-0.458],[-1.249,0],[0,0.999],[1.457,0],[0,0],[0,0.541],[-0.608,0],[0,0],[0,0.982],[1.215,0],[0.393,-0.851],[0.566,0],[0,0.608],[-0.125,0.283],[-2.125,0],[0,-1.925],[1.415,-0.291],[0,0],[0,-1.659]],"o":[[-2.292,0],[-0.133,-0.275],[0,-0.649],[0.5,0],[0.427,0.841],[1.232,0],[0.008,-1.168],[0,0],[-0.608,0],[0,-0.524],[0,0],[1.257,0],[0,-0.968],[-1.016,0],[-0.275,0.566],[-0.699,0],[0,-0.283],[0.533,-1.174],[2.539,0],[0,1.523],[0,0],[1.792,0.167],[0,2.181]],"v":[[14.195,12.55],[9.93,10.377],[9.738,9.586],[10.846,8.529],[11.911,9.187],[14.236,10.527],[16.318,8.812],[14.011,6.995],[13.487,6.995],[12.53,6.096],[13.487,5.205],[13.978,5.205],[16.051,3.54],[14.186,1.931],[12.161,3.207],[11.029,3.982],[9.972,2.966],[10.155,2.156],[14.178,0],[18.434,3.182],[15.926,5.996],[15.926,6.046],[18.876,8.92]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 178","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":"Path 177","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[386.083,748.699,0],"ix":2},"a":{"a":0,"k":[17.36,17.359,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.847,0],[0,0],[1.509,-0.123],[0.56,-0.283],[0.66,-1.297],[0.121,-1.474],[0,-2.847],[0,0],[-0.123,-1.509],[-0.283,-0.558],[-1.295,-0.66],[-1.474,-0.121],[-2.845,0],[0,0],[-1.509,0.123],[-0.558,0.283],[-0.66,1.297],[-0.119,1.474],[0,2.845],[0,0],[0.125,1.509],[0.285,0.558],[1.295,0.662],[1.471,0.121]],"o":[[0,0],[-2.845,0],[-1.474,0.121],[-1.295,0.662],[-0.283,0.558],[-0.123,1.509],[0,0],[0,2.845],[0.121,1.474],[0.66,1.297],[0.56,0.283],[1.509,0.123],[0,0],[2.847,0],[1.471,-0.121],[1.295,-0.66],[0.285,-0.558],[0.125,-1.509],[0,0],[0,-2.847],[-0.119,-1.474],[-0.66,-1.297],[-0.558,-0.283],[-1.509,-0.123]],"v":[[18.751,3.097],[15.97,3.097],[9.668,3.222],[6.856,3.846],[3.848,6.856],[3.224,9.666],[3.099,15.97],[3.099,18.751],[3.224,25.053],[3.848,27.863],[6.856,30.872],[9.668,31.497],[15.97,31.621],[18.751,31.621],[25.055,31.497],[27.865,30.872],[30.872,27.863],[31.497,25.053],[31.624,18.751],[31.624,15.97],[31.497,9.666],[30.872,6.856],[27.865,3.846],[25.055,3.222]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.957,-1.877],[0,-5.59],[0,0],[-1.089,-2.135],[-1.879,-0.957],[-5.59,0],[0,0],[-2.135,1.086],[-0.955,1.877],[0,5.588],[0,0],[1.089,2.135],[1.877,0.957],[5.59,0],[0,0],[2.135,-1.086]],"o":[[-1.089,2.135],[0,0],[0,5.588],[0.957,1.877],[2.135,1.086],[0,0],[5.59,0],[1.877,-0.957],[1.089,-2.135],[0,0],[0,-5.59],[-0.955,-1.877],[-2.135,-1.086],[0,0],[-5.59,0],[-1.879,0.957]],"v":[[1.089,5.449],[0,15.97],[0,18.751],[1.089,29.27],[5.451,33.632],[15.97,34.718],[18.751,34.718],[29.272,33.632],[33.632,29.27],[34.721,18.751],[34.721,15.97],[33.632,5.449],[29.272,1.086],[18.751,0],[15.97,0],[5.451,1.086]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 177","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":20,"ty":0,"nm":"Group 71","refId":"comp_5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[487.004,748.7,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":"Rectangle 77","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,737,0],"ix":2},"a":{"a":0,"k":[262.5,65,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,66],[461,130],[64,130],[0,66]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 77 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,66],[461,130],[64,130],[0,66]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 77 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":"Rectangle 83","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,278,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 83 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 83 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":23,"ty":4,"nm":"Rectangle 81","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,320,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 81 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 81 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":24,"ty":4,"nm":"Rectangle 80","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,362,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 80 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 80 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":25,"ty":4,"nm":"Rectangle 79","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[177,404,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[296,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 79 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[296,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 79 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":26,"ty":4,"nm":"Rectangle 84","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,179,0],"ix":2},"a":{"a":0,"k":[245.5,72,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[11.046,0],[0,0],[0,11.046]],"o":[[0,0],[0,0],[0,0],[0,0],[0,11.046],[0,0],[-11.046,0],[0,0]],"v":[[0,0],[0,0],[491,0],[491,0],[491,124],[471,144],[20,144],[0,124]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 84 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[11.046,0],[0,0],[0,11.046]],"o":[[0,0],[0,0],[0,0],[0,0],[0,11.046],[0,0],[-11.046,0],[0,0]],"v":[[0,0],[0,0],[491,0],[491,0],[491,124],[471,144],[20,144],[0,124]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 84 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":27,"ty":4,"nm":"Rectangle 78","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,575,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,266],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 78 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,266],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098039216,0.952941176471,0.956862745098,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 78 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":28,"ty":4,"nm":"Rectangle 76","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,454.5,0],"ix":2},"a":{"a":0,"k":[262.5,347.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,631],[461,695],[64,695],[0,631]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 76 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,631],[461,695],[64,695],[0,631]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 76 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":29,"ty":4,"nm":"Path 161","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":0,"k":[274.5,460.628,0],"ix":2},"a":{"a":0,"k":[274.5,353.372,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-39.692,0],[0,0],[0,-38.817],[0,0],[0,0]],"o":[[0,-38.817],[0,0],[39.692,0],[0,0],[0,0],[0,0]],"v":[[0,70.284],[71.869,0],[477.131,0],[549,70.284],[549,706.744],[0,706.744]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 161","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}],"markers":[],"chars":[{"ch":"M","size":16,"style":"Regular","w":83.3,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0.098,3.597],[0,1.758],[0,0],[0,0],[0,0],[0,0],[0.065,-3.385],[0,-1.465],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,-1.692],[-0.098,-3.596],[0,0],[0,0],[0,0],[0,0],[0,3.874],[-0.066,3.386],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[7.373,0],[16.65,0],[16.65,-42.334],[16.504,-50.269],[16.357,-58.301],[16.357,-60.498],[37.032,0],[46.66,0],[67.139,-60.498],[67.041,-49.609],[66.943,-42.334],[66.943,0],[76.221,0],[76.221,-71.729],[62.398,-71.729],[41.919,-11.084],[21.294,-71.729],[7.373,-71.729]],"c":true},"ix":2},"nm":"M","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"M","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"o","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[5.761,0],[2.414,3.706],[0,5.56],[-2.414,4.097],[-5.312,0],[-2.446,-4.812],[0,-4.877],[2.141,-4.405]],"o":[[-5.247,0],[-2.414,-3.706],[0,-5.787],[2.414,-4.097],[5.987,0],[1.545,3.056],[0,5.397],[-2.141,4.405]],"v":[[27.026,-5.713],[15.535,-11.272],[11.914,-25.172],[15.535,-39.997],[27.122,-46.143],[39.772,-38.924],[42.09,-27.025],[38.879,-12.321]],"c":true},"ix":2},"nm":"o","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[6.691,0],[4.428,-5.203],[0,-8.781],[-4.202,-4.862],[-7.144,0],[-4.073,5.496],[0,8.424],[4.622,4.488]],"o":[[-7.467,0],[-4.428,5.204],[0,8.196],[4.202,4.862],[8.566,0],[4.073,-5.496],[0,-8.716],[-4.623,-4.488]],"v":[[27.366,-53.809],[9.523,-46.003],[2.881,-25.025],[9.184,-5.437],[26.202,1.855],[45.16,-6.389],[51.27,-27.27],[44.336,-47.076]],"c":true},"ix":2},"nm":"o","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"o","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"v","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.562,-52.295],[19.849,0],[29.214,0],[48.901,-52.295],[39.282,-52.295],[24.731,-9.717],[10.767,-52.295]],"c":true},"ix":2},"nm":"v","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"v","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"e","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.688,0],[4.529,-5.241],[0,-8.398],[-4.497,-4.736],[-6.47,0],[-2.1,0.52],[-2.65,2.605],[-1.286,2.361],[-0.228,1.921],[0,0],[1.518,-1.765],[4.554,0],[2.325,3.215],[0.162,5.321],[0,0],[0.517,2.409],[1.747,2.637],[3.461,1.742]],"o":[[-7.312,0],[-4.53,5.241],[0,8.529],[4.497,4.736],[2.649,0],[3.909,-0.912],[1.582,-1.497],[1.286,-2.36],[0,0],[-0.633,2.322],[-2.713,3.041],[-4.877,0],[-2.325,-3.215],[0,0],[0,-5.273],[-0.583,-3.516],[-1.812,-2.766],[-3.462,-1.741]],"v":[[28.022,-53.467],[10.261,-45.605],[3.467,-25.146],[10.211,-5.249],[26.661,1.855],[33.784,1.074],[43.622,-4.199],[47.925,-9.985],[50.195,-16.406],[41.553,-16.406],[38.326,-10.275],[27.425,-5.713],[16.621,-10.535],[12.891,-23.34],[50.928,-23.34],[50.151,-34.863],[46.657,-44.092],[38.747,-50.854]],"c":true},"ix":2},"nm":"e","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-2.711,2.914],[-4.002,0],[-2.389,-4.231],[-0.356,-3.809]],"o":[[0.161,-4.492],[2.711,-2.913],[5.584,0],[1.291,2.279],[0,0]],"v":[[13.086,-30.322],[17.395,-41.431],[27.466,-45.801],[39.425,-39.453],[41.895,-30.322]],"c":true},"ix":2},"nm":"e","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"e","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":" ","size":16,"style":"Regular","w":27.78,"data":{},"fFamily":"SF Pro"},{"ch":"A","size":16,"style":"Regular","w":66.7,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[21.973,-29.395],[33.545,-61.084],[44.434,-29.395]],"c":true},"ix":2},"nm":"A","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[1.465,0],[11.426,0],[19.189,-21.484],[47.559,-21.484],[54.834,0],[65.479,0],[39.453,-71.729],[28.467,-71.729]],"c":true},"ix":2},"nm":"A","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"A","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"d","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,5.599],[-2.737,3.386],[-4.405,0],[-2.689,-3.174],[0,-6.608],[2.607,-3.499],[4.048,0],[2.364,3.777]],"o":[[0,-6.575],[2.737,-3.385],[3.951,0],[2.688,3.174],[0,6.543],[-2.608,3.5],[-5.215,0],[-2.364,-3.776]],"v":[[12.012,-25.537],[16.116,-40.479],[26.829,-45.557],[36.788,-40.796],[40.82,-26.123],[36.909,-11.06],[26.926,-5.811],[15.558,-11.475]],"c":true},"ix":2},"nm":"d","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[3.989,0],[3.875,-5.582],[0,-7.617],[-4.248,-4.899],[-5.804,0],[-2.789,1.432],[-2.043,3.223],[0,0],[0,0],[0,0],[0,0],[0,0],[1.556,0.977]],"o":[[-7.199,0],[-3.875,5.583],[0,8.138],[4.248,4.9],[3.6,0],[2.789,-1.432],[0,0],[0,0],[0,0],[0,0],[0,0],[-1.978,-2.441],[-2.692,-1.692]],"v":[[25.157,-53.223],[8.546,-44.849],[2.734,-25.049],[9.106,-5.493],[24.185,1.855],[33.768,-0.293],[41.016,-7.275],[41.016,0],[48.926,0],[48.926,-71.973],[40.479,-71.973],[40.479,-45.557],[35.177,-50.684]],"c":true},"ix":2},"nm":"d","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"d","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"r","size":16,"style":"Regular","w":33.3,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-2.377,2.849],[-4.427,0],[-0.439,-0.032],[-0.521,-0.098],[0,0],[0.391,0.033],[0.163,0],[2.669,-2.522],[0.684,-1.758],[0,0],[0,0]],"o":[[0,0],[0,0],[0,-3.711],[2.376,-2.848],[0.52,0],[0.439,0.033],[0,0],[-0.945,-0.098],[-0.391,-0.032],[-3.484,0],[-2.67,2.523],[0,0],[0,0],[0,0]],"v":[[6.689,0],[15.479,0],[15.479,-30.078],[19.043,-39.917],[29.248,-44.189],[30.688,-44.141],[32.129,-43.945],[32.129,-53.223],[30.127,-53.418],[29.297,-53.467],[20.068,-49.683],[15.039,-43.262],[15.039,-52.295],[6.689,-52.295]],"c":true},"ix":2},"nm":"r","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"r","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"s","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-3.279,-3.532],[-7.877,0],[-3.576,3.385],[0,4.655],[3.418,2.246],[6.434,1.53],[0,0],[1.326,0.811],[0,2.271],[-1.749,1.265],[-3.399,0],[-2.066,-2.298],[-0.167,-1.974],[0,0],[2.21,2.93],[7.983,0],[3.612,-3.059],[0,-4.948],[-3.838,-2.376],[-4.532,-1.106],[0,0],[-1.291,-0.716],[0,-2.246],[2.525,-1.416],[3.322,0],[2.259,2.832],[0.266,2.93]],"o":[[0.23,5.209],[3.279,3.532],[7.317,0],[3.576,-3.385],[0,-4.817],[-2.19,-1.432],[0,0],[-2.587,-0.618],[-2.299,-1.363],[0,-2.075],[1.749,-1.265],[5.098,0],[1.266,1.619],[0,0],[0.065,-3.385],[-3.529,-4.622],[-6.104,0],[-3.613,3.06],[0,4.199],[2.15,1.367],[0,0],[3.804,0.945],[2.018,1.172],[0,2.962],[-2.525,1.416],[-5.582,0],[-1.23,-1.562],[0,0]],"v":[[3.223,-16.406],[8.488,-3.296],[25.221,2.002],[41.56,-3.076],[46.924,-15.137],[41.797,-25.732],[28.862,-30.176],[22.942,-31.592],[17.072,-33.736],[13.623,-39.185],[16.247,-44.196],[23.969,-46.094],[34.716,-42.646],[36.865,-37.256],[45.166,-37.256],[41.948,-46.729],[24.679,-53.662],[10.106,-49.072],[4.688,-37.061],[10.444,-27.197],[20.467,-23.486],[27.563,-21.729],[35.205,-19.238],[38.232,-14.111],[34.444,-7.544],[25.674,-5.42],[13.912,-9.668],[11.67,-16.406]],"c":true},"ix":2},"nm":"s","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"s","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"B","size":16,"style":"Regular","w":66.7,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-2.171,-0.911],[0,-4.688],[3.618,-1.79],[4.144,0]],"o":[[0,0],[0,0],[4.276,0],[3.848,1.628],[0,4.655],[-2.303,1.14],[0,0]],"v":[[16.895,-41.406],[16.895,-63.623],[34.41,-63.623],[44.081,-62.256],[49.854,-52.783],[44.426,-43.115],[34.756,-41.406]],"c":true},"ix":2},"nm":"B","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-2.498,-1.009],[0,-5.208],[1.61,-2.18],[6.013,0]],"o":[[0,0],[0,0],[4.108,0],[4.699,1.888],[0,3.093],[-2.563,3.451],[0,0]],"v":[[16.895,-8.301],[16.895,-33.545],[36.364,-33.545],[46.272,-32.031],[53.32,-21.387],[50.905,-13.477],[38.04,-8.301]],"c":true},"ix":2},"nm":"B","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-4.356,5.599],[0,4.623],[3.223,3.125],[3.678,1.4],[-1.335,1.53],[0,4.525],[2.097,2.962],[8.453,0],[0,0]],"o":[[0,0],[9.498,0],[2.914,-3.743],[0,-5.501],[-1.823,-1.758],[2.506,-1.27],[2.571,-2.897],[0,-3.873],[-3.572,-5.013],[0,0],[0,0]],"v":[[7.373,0],[37.883,0],[58.665,-8.398],[63.037,-20.947],[58.203,-33.887],[49.951,-38.623],[55.713,-42.822],[59.57,-53.955],[56.425,-64.209],[38.387,-71.729],[7.373,-71.729]],"c":true},"ix":2},"nm":"B","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"B","np":6,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"a","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,2.533],[-2.718,1.527],[-3.184,0.423],[0,0],[-1.689,0.458],[-1.073,0.686],[0,0],[4.883,-2.373],[3.092,0],[1.855,1.462]],"o":[[0,-3.345],[1.604,-0.909],[0,0],[1.624,-0.195],[1.689,-0.457],[0,0],[0,5.396],[-2.898,1.43],[-2.539,0],[-1.855,-1.462]],"v":[[13.184,-13.897],[17.261,-21.204],[24.443,-23.203],[29.755,-23.885],[34.725,-24.863],[38.867,-26.578],[38.867,-19.509],[31.543,-7.858],[22.559,-5.713],[15.967,-7.905]],"c":true},"ix":2},"nm":"a","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[3.027,-2.666],[0,-4.844],[-3.076,-2.942],[-4.851,0],[-3.353,1.724],[-1.791,2.344],[-0.716,-1.139],[-3.027,0],[-0.716,0.098],[-1.367,0.391],[0,0],[0.488,-0.049],[0.391,0],[0.374,0.552],[0,0.912],[0,0],[3.804,2.344],[6.145,0],[4.015,-2.53],[0.163,-6.464],[0,0],[-1.072,1.375],[-4.581,0],[-2.128,-1.356],[0,-3.006],[0.39,-0.784],[2.018,-0.259]],"o":[[-4.916,0.618],[-3.027,2.666],[0,4.422],[3.076,2.942],[4.036,0],[3.352,-1.725],[0.293,2.083],[1.367,2.148],[1.237,0],[0.716,-0.098],[0,0],[-0.554,0.098],[-0.488,0.049],[-1.205,0],[-0.375,-0.552],[0,0],[0,-4.948],[-3.837,-2.344],[-5.299,0],[-4.015,2.53],[0,0],[0.325,-2.715],[1.917,-2.486],[3.963,0],[2.128,1.357],[0,1.471],[-0.684,1.43],[0,0]],"v":[[20.459,-29.893],[8.545,-24.966],[4.004,-13.702],[8.618,-2.656],[20.508,1.758],[31.592,-0.829],[39.307,-6.932],[40.82,-2.099],[47.412,1.123],[50.342,0.977],[53.467,0.244],[53.467,-6.249],[51.904,-6.03],[50.586,-5.957],[48.218,-6.786],[47.656,-8.982],[47.656,-39.111],[41.95,-50.049],[26.978,-53.564],[13.005,-49.77],[6.738,-36.279],[14.941,-36.279],[17.036,-42.413],[26.783,-46.143],[35.919,-44.109],[39.111,-37.565],[38.526,-34.183],[34.473,-31.648]],"c":true},"ix":2},"nm":"a","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"a","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"C","size":16,"style":"Regular","w":72.22,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[8.976,0],[5.984,-7.361],[0,-10.586],[-7.368,-6.677],[-8.237,0],[-5.631,6.152],[-0.837,7.552],[0,0],[1.95,-2.897],[7.035,0],[3.853,5.229],[0,8.406],[-4.268,4.968],[-6.937,0],[-3.149,-2.702],[-1.055,-4.622],[0,0],[4.955,4.785]],"o":[[-10.521,0],[-5.534,6.776],[0,13.942],[5.598,5.049],[9.557,0],[4.697,-5.11],[0,0],[-0.96,4.72],[-3.677,5.502],[-7.642,0],[-3.854,-5.229],[0,-10.262],[4.268,-4.968],[5.69,0],[3.149,2.702],[0,0],[-0.547,-6.087],[-4.955,-4.785]],"v":[[37.453,-73.682],[12.695,-62.64],[4.395,-36.597],[15.447,-5.669],[36.201,1.904],[58.984,-7.324],[67.285,-26.318],[57.812,-26.318],[53.448,-14.893],[37.379,-6.641],[20.135,-14.484],[14.355,-34.936],[20.757,-57.782],[37.564,-65.234],[50.823,-61.182],[57.129,-50.195],[66.602,-50.195],[58.349,-66.504]],"c":true},"ix":2},"nm":"C","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"C","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"p","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[4.115,0],[2.286,5.404],[0,4.037],[-1.208,3.255],[-6.108,0],[-2.287,-5.762],[0,-4.166],[2.727,-3.434]],"o":[[-6.076,0],[-1.208,-2.832],[0,-5.013],[2.254,-6.087],[6.075,0],[1.208,2.995],[0,6.836],[-2.728,3.435]],"v":[[28.516,-5.908],[15.973,-14.014],[14.16,-24.316],[15.973,-36.719],[28.516,-45.85],[41.058,-37.207],[42.871,-26.465],[38.78,-11.06]],"c":true},"ix":2},"nm":"p","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-1.569,-0.977],[-3.954,0],[-3.791,3.092],[0,11.394],[4.144,4.541],[5.94,0],[2.969,-1.953],[1.762,-2.376],[0,0],[0,0]],"o":[[0,0],[0,0],[1.928,2.377],[2.679,1.725],[5.032,0],[5.98,-4.883],[0,-8.43],[-4.145,-4.541],[-4.015,0],[-2.089,1.302],[0,0],[0,0],[0,0]],"v":[[5.713,20.85],[14.502,20.85],[14.502,-5.859],[19.747,-0.83],[29.698,1.758],[42.934,-2.881],[51.904,-27.295],[45.687,-46.753],[30.56,-53.564],[20.084,-50.635],[14.307,-45.117],[14.307,-52.051],[5.713,-52.051]],"c":true},"ix":2},"nm":"p","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"p","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"y","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[1.007,-2.405],[0.162,-0.26],[0.764,-0.536],[1.624,0],[0.682,0.098],[1.527,0.423],[0,0],[-0.667,-0.098],[-1.236,0],[-2.081,2.927],[-5.074,13.336],[-3.191,8.989],[-1.237,3.355],[0,0]],"o":[[0,0],[0,0],[0,0],[-0.455,1.169],[-1.007,2.403],[-0.52,0.78],[-0.764,0.536],[-0.52,0],[-0.682,-0.098],[0,0],[0.975,0.26],[0.667,0.098],[5.074,0],[2.081,-2.928],[2.148,-5.666],[4.264,-11.952],[0,0],[0,0]],"v":[[25.024,-9.698],[11.011,-52.295],[1.05,-52.295],[20.386,1.538],[18.192,6.898],[16.438,10.894],[14.511,12.868],[10.929,13.672],[9.125,13.525],[5.811,12.744],[5.811,20.752],[8.274,21.289],[11.128,21.436],[21.861,17.044],[32.593,-7.352],[40.601,-29.335],[48.853,-52.295],[39.136,-52.295]],"c":true},"ix":2},"nm":"y","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"y","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"L","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[7.617,0],[53.32,0],[53.32,-8.545],[17.334,-8.545],[17.334,-71.729],[7.617,-71.729]],"c":true},"ix":2},"nm":"L","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"L","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"i","size":16,"style":"Regular","w":22.22,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[6.445,0],[15.381,0],[15.381,-52.051],[6.445,-52.051]],"c":true},"ix":2},"nm":"i","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[6.445,-61.768],[15.381,-61.768],[15.381,-71.729],[6.445,-71.729]],"c":true},"ix":2},"nm":"i","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"i","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"n","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-0.439,1.839],[-1.465,1.726],[-2.409,0.716],[-2.084,0],[-1.562,-3.255],[0,-3.19],[0,0],[0,0],[0,0],[1.432,2.832],[7.422,0],[2.766,-1.334],[2.473,-3.059],[0,0],[0,0]],"o":[[0,0],[0,0],[0,-3.418],[0.439,-1.839],[1.823,-2.148],[1.334,-0.423],[4.102,0],[0.944,1.953],[0,0],[0,0],[0,0],[0,-5.273],[-2.605,-5.176],[-3.386,0],[-2.767,1.335],[0,0],[0,0],[0,0]],"v":[[6.445,0],[15.234,0],[15.234,-27.393],[15.894,-35.278],[18.75,-40.625],[25.098,-44.922],[30.225,-45.557],[38.721,-40.674],[40.137,-32.959],[40.137,0],[49.072,0],[49.072,-33.545],[46.924,-45.703],[31.885,-53.467],[22.656,-51.465],[14.795,-44.873],[14.795,-52.295],[6.445,-52.295]],"c":true},"ix":2},"nm":"n","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"n","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"k","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[6.25,0],[14.697,0],[14.697,-19.629],[21.914,-26.611],[38.362,0],[49.59,0],[28.364,-32.851],[48.463,-52.295],[37.235,-52.295],[14.697,-30.083],[14.697,-71.729],[6.25,-71.729]],"c":true},"ix":2},"nm":"k","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"k","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"}]} \ No newline at end of file +{"v":"4.8.0","meta":{"g":"LottieFiles AE 3.5.2","a":"","k":"","d":"","tc":""},"fr":60,"ip":0,"op":3600,"w":549,"h":830,"nm":"CreateCalendar_Dark","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 184","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6.72,11.276,0],"ix":2},"a":{"a":0,"k":[4.683,6.77,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0.998],[0,0],[-0.711,0.109],[0,0],[-1.818,0],[0,-2.597],[0,0],[0,-0.902],[0,0],[0.916,0]],"o":[[-0.916,0],[0,0],[0,-0.855],[0,0],[0,-2.597],[1.818,0],[0,0],[0.767,0.074],[0,0],[0,0.998],[0,0]],"v":[[1.367,13.54],[0,12.091],[0,6.972],[1.135,5.557],[1.135,3.848],[4.682,0],[8.23,3.848],[8.23,5.537],[9.366,6.972],[9.366,12.091],[7.999,13.54]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,-1.593],[0,0],[0,0],[0,0],[1.218,0]],"o":[[0,0],[0,0],[0,0],[0,-1.593],[-1.223,0]],"v":[[2.447,3.725],[2.447,5.529],[6.918,5.523],[6.918,3.725],[4.682,1.257]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 184","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_1","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 183","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16.536,16.011,0],"ix":2},"a":{"a":0,"k":[11.944,15.116,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.732,0.722],[0,1.419],[0,0],[-0.732,0.724],[-1.427,0],[0,0],[0,0],[0,0],[0.326,-0.326],[0,-0.644],[0,0],[-0.318,-0.316],[-0.615,0],[0,0],[-0.326,0.326],[0,0.642],[0,0],[0.336,0.316],[0.609,0],[0,0],[0,0],[0,0],[-0.732,-0.73],[0,-1.408],[0,0],[0.732,-0.722],[1.427,0]],"o":[[-1.427,0],[-0.732,-0.724],[0,0],[0,-1.408],[0.732,-0.73],[0,0],[0,0],[0,0],[-0.615,0],[-0.318,0.316],[0,0],[0,0.642],[0.326,0.326],[0,0],[0.609,0],[0.336,-0.316],[0,0],[0,-0.644],[-0.326,-0.326],[0,0],[0,0],[0,0],[1.427,0],[0.732,0.724],[0,0],[0,1.41],[-0.732,0.732],[0,0]],"v":[[4.334,30.231],[1.097,29.149],[0,25.936],[0,12.935],[1.097,9.737],[4.334,8.641],[8.165,8.641],[8.165,11.244],[4.491,11.244],[3.079,11.734],[2.603,13.173],[2.603,25.713],[3.079,27.152],[4.491,27.642],[19.383,27.642],[20.783,27.152],[21.285,25.713],[21.285,13.173],[20.783,11.734],[19.383,11.244],[15.723,11.244],[15.723,8.641],[19.555,8.641],[22.792,9.737],[23.888,12.935],[23.888,25.936],[22.792,29.134],[19.555,30.231]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.336,0],[0.246,0.238],[0,0.326],[0,0],[0,0],[0,0],[0,0],[0.334,0],[0.211,0.195],[0,0.307],[-0.219,0.238],[0,0],[-0.15,0.062],[-0.158,0],[-0.15,-0.062],[-0.16,-0.158],[0,0],[0,-0.283],[0.219,-0.201],[0.299,0],[0.221,0.238],[0,0],[0,0],[0,0],[0,0],[0.248,-0.238]],"o":[[-0.334,0],[-0.238,-0.238],[0,0],[0,0],[0,0],[0,0],[-0.211,0.238],[-0.31,0],[-0.201,-0.201],[0,-0.283],[0,0],[0.166,-0.158],[0.15,-0.062],[0.16,0],[0.15,0.062],[0,0],[0.23,0.238],[0,0.307],[-0.211,0.195],[-0.326,0],[0,0],[0,0],[0,0],[0,0],[0,0.326],[-0.238,0.238]],"v":[[11.943,19.7],[11.072,19.344],[10.715,18.499],[10.715,5.193],[10.822,3.225],[9.99,4.188],[8.138,6.17],[7.32,6.527],[6.539,6.236],[6.236,5.471],[6.566,4.69],[11.006,0.422],[11.482,0.092],[11.943,0],[12.406,0.092],[12.87,0.422],[17.308,4.69],[17.652,5.471],[17.322,6.236],[16.556,6.527],[15.736,6.17],[13.887,4.188],[13.067,3.225],[13.173,5.193],[13.173,18.499],[12.802,19.344]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.741176470588,0.756862745098,0.776470588235,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 183","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_2","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 181","sr":1,"ks":{"o":{"a":0,"k":40,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[22.743,22.253,0],"ix":2},"a":{"a":0,"k":[14.429,11.826,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-0.479],[0.356,-0.356],[0,0],[0.448,0],[0.316,0.304],[0,0.458],[-0.082,0.204],[-0.153,0.154],[0,0],[0,0],[0,0],[0,0],[0,0],[0.316,0.306],[0,0.487],[-0.305,0.306],[-0.509,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0.092,0.194],[0,0.246],[-0.306,0.306],[-0.468,0],[-0.204,-0.092],[-0.183,-0.183],[0,0]],"o":[[0,0.477],[0,0],[-0.356,0.348],[-0.468,0],[-0.306,-0.306],[0,-0.235],[0.092,-0.204],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.509,0],[-0.305,-0.314],[0,-0.5],[0.316,-0.316],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.153,-0.154],[-0.082,-0.204],[0,-0.458],[0.316,-0.306],[0.224,0],[0.204,0.092],[0,0],[0.356,0.356]],"v":[[28.858,11.834],[28.324,13.085],[18.246,23.132],[17.04,23.652],[15.864,23.194],[15.406,22.049],[15.529,21.392],[15.895,20.857],[19.315,17.406],[25.01,12.215],[25.545,13.193],[20.247,13.497],[1.695,13.497],[0.458,13.039],[0,11.834],[0.458,10.627],[1.695,10.155],[20.247,10.155],[25.545,10.475],[25.01,11.468],[19.315,6.261],[15.895,2.795],[15.529,2.275],[15.406,1.603],[15.864,0.458],[17.04,0],[17.681,0.137],[18.262,0.549],[28.324,10.581]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.741176470588,0.756862745098,0.776470588235,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 181","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_3","layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Group 72","refId":"comp_4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,25.585,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_4","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 180","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.583,25.586,0],"ix":2},"a":{"a":0,"k":[11.542,11.543,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.13,0],[0,1.13],[0,0],[0,0],[0,1.13],[1.13,0],[0,0],[0,0],[1.132,0],[0,-1.13],[0,0],[0,0],[0,-1.132],[-1.13,0],[0,0]],"o":[[0,1.13],[1.132,0],[0,0],[0,0],[1.13,0],[0,-1.132],[0,0],[0,0],[0,-1.13],[-1.13,0],[0,0],[0,0],[-1.13,0],[0,1.13],[0,0],[0,0]],"v":[[9.497,21.038],[11.543,23.086],[13.591,21.038],[13.591,13.589],[21.038,13.589],[23.084,11.543],[21.038,9.495],[13.591,9.495],[13.591,2.048],[11.543,0],[9.497,2.048],[9.497,9.495],[2.046,9.495],[0,11.543],[2.046,13.589],[9.497,13.589]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 180","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path 179","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,25.585,0],"ix":2},"a":{"a":0,"k":[25.585,25.585,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.087,-1.32],[3.501,0],[3.085,1.338],[2.358,2.36],[1.336,3.087],[0,3.499],[-1.336,3.089],[-2.344,2.346],[-3.07,1.336],[-3.499,0],[-3.087,-1.338],[-2.358,-2.36],[-1.338,-3.087],[0,-3.501],[1.336,-3.089],[2.36,-2.362]],"o":[[-3.087,1.338],[-3.499,0],[-3.087,-1.32],[-2.344,-2.362],[-1.336,-3.089],[0,-3.501],[1.336,-3.087],[2.358,-2.36],[3.087,-1.338],[3.515,0],[3.087,1.336],[2.36,2.346],[1.336,3.089],[0,3.499],[-1.338,3.087],[-2.358,2.36]],"v":[[35.449,49.163],[25.571,51.169],[15.695,49.163],[7.526,43.641],[2.004,35.468],[0,25.586],[2.004,15.701],[7.526,7.553],[15.67,2.006],[25.548,0],[35.449,2.006],[43.618,7.553],[49.165,15.701],[51.169,25.586],[49.165,35.468],[43.618,43.641]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549019608,0.388235294118,0.407843137255,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 179","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_5","layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Group 70","refId":"comp_6","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,25.585,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0}]},{"id":"comp_6","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 176","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.585,26.432,0],"ix":2},"a":{"a":0,"k":[14.506,3.092,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.56,0],[0.468,0.275],[0.275,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275],[-0.581,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.275,-0.468],[0.468,-0.285]],"o":[[-0.581,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.275,-0.468],[0.468,-0.285],[0.56,0],[0.468,0.275],[0.275,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275]],"v":[[3.099,6.184],[1.528,5.771],[0.412,4.641],[0,3.099],[0.412,1.542],[1.528,0.427],[3.099,0],[4.641,0.427],[5.757,1.542],[6.169,3.099],[5.757,4.641],[4.641,5.771]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.57,0],[0.468,0.275],[0.285,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275],[-0.568,0],[-0.458,-0.285],[-0.275,-0.468],[0,-0.57],[0.285,-0.468],[0.468,-0.285]],"o":[[-0.568,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.285,-0.468],[0.468,-0.285],[0.57,0],[0.468,0.275],[0.285,0.468],[0,0.56],[-0.275,0.468],[-0.458,0.275]],"v":[[14.505,6.184],[12.948,5.771],[11.818,4.641],[11.406,3.099],[11.818,1.542],[12.948,0.427],[14.505,0],[16.047,0.427],[17.163,1.542],[17.589,3.099],[17.163,4.641],[16.047,5.771]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0.568,0],[0.468,0.275],[0.275,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275],[-0.57,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.285,-0.468],[0.468,-0.285]],"o":[[-0.57,0],[-0.468,-0.285],[-0.275,-0.468],[0,-0.57],[0.275,-0.468],[0.468,-0.285],[0.568,0],[0.468,0.275],[0.285,0.468],[0,0.56],[-0.275,0.468],[-0.468,0.275]],"v":[[25.912,6.184],[24.354,5.771],[23.24,4.641],[22.828,3.099],[23.24,1.542],[24.354,0.427],[25.912,0],[27.469,0.427],[28.583,1.542],[29.012,3.099],[28.583,4.641],[27.469,5.771]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 176","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}]}],"fonts":{"list":[{"fName":"SF Pro","fFamily":"SF Pro","fStyle":"Regular","ascent":71.8994140625}]},"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[273.5,415.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[36.201,36.201],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.854902029037,0.862745165825,0.8784314394,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[112.601,333.101],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path 177","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[386.083,748.699,0],"ix":2},"a":{"a":0,"k":[17.36,17.359,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Group 82","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[275,599,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,92],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Path 193","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[114.877,24.95,0],"ix":2},"a":{"a":0,"k":[8.488,10.442,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.426,0.437],[-0.857,0],[0,0],[-0.354,-0.127],[-0.293,-0.304],[0,0],[-0.122,-0.354],[0,-0.509],[0,0],[0.432,-0.437],[0.858,0],[0,0],[0,0],[0,0],[-0.221,0.222],[0,0.416],[0,0],[0,0],[0.238,0.232],[0,0.481],[0,0],[0,0],[0.222,-0.227],[0,-0.416],[0,0]],"o":[[0,0],[0,-0.864],[0.432,-0.437],[0,0],[0.448,0],[0.354,0.122],[0,0],[0.31,0.32],[0.122,0.354],[0,0],[0,0.864],[-0.426,0.437],[0,0],[0,0],[0,0],[0.432,0],[0.221,-0.227],[0,0],[0,0],[-0.476,0],[-0.232,-0.233],[0,0],[0,0],[-0.432,0],[-0.215,0.221],[0,0],[0,0]],"v":[[4.026,4.599],[4.026,2.607],[4.665,0.656],[6.599,0],[9.779,0],[10.982,0.191],[11.953,0.83],[16.145,5.089],[16.793,6.101],[16.975,7.396],[16.975,14.136],[16.328,16.087],[14.402,16.743],[12.692,16.743],[12.692,15.406],[14.327,15.406],[15.307,15.074],[15.639,14.111],[15.639,7.014],[11.754,7.014],[10.683,6.666],[10.335,5.595],[10.335,1.337],[6.666,1.337],[5.686,1.677],[5.363,2.632],[5.363,4.599]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-0.061,-0.066],[-0.144,0],[0,0],[0,0]],"o":[[0,0.149],[0.066,0.061],[0,0],[0,0],[0,0]],"v":[[11.538,5.396],[11.63,5.719],[11.945,5.811],[15.29,5.811],[11.538,1.992]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0.869],[0,0],[-0.426,0.437],[-0.858,0],[0,0],[-0.305,-0.1],[-0.315,-0.327],[0,0],[-0.111,-0.205],[-0.038,-0.243],[0,-0.355],[0,0],[0.432,-0.437],[0.858,0],[0,0],[0.432,0.437]],"o":[[0,0],[0,-0.864],[0.432,-0.437],[0,0],[0.465,0],[0.304,0.099],[0,0],[0.221,0.226],[0.116,0.199],[0.039,0.244],[0,0],[0,0.864],[-0.426,0.437],[0,0],[-0.858,0],[-0.426,-0.431]],"v":[[0,18.278],[0,6.749],[0.639,4.798],[2.574,4.142],[5.504,4.142],[6.658,4.292],[7.587,4.931],[12.161,9.588],[12.659,10.235],[12.891,10.899],[12.95,11.796],[12.95,18.278],[12.302,20.229],[10.376,20.885],[2.574,20.885],[0.639,20.229]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[-0.215,-0.221],[-0.426,0],[0,0],[-0.221,0.227],[0,0.415],[0,0],[0,0],[0.265,0.26],[0,0.526],[0,0],[0,0],[0.222,-0.227],[0,-0.409]],"o":[[0,0.415],[0.222,0.227],[0,0],[0.426,0],[0.221,-0.221],[0,0],[0,0],[-0.514,0],[-0.26,-0.26],[0,0],[0,0],[-0.432,0],[-0.215,0.221],[0,0]],"v":[[1.337,18.254],[1.66,19.208],[2.632,19.548],[10.31,19.548],[11.281,19.208],[11.613,18.254],[11.613,11.862],[6.923,11.862],[5.753,11.472],[5.363,10.293],[5.363,5.479],[2.64,5.479],[1.66,5.819],[1.337,6.765]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[-0.166,0],[0,0],[0,0],[0,0],[-0.072,-0.072]],"o":[[0,0],[0,0],[0,0],[0,0.166],[0.072,0.072]],"v":[[7.081,10.609],[11.356,10.609],[6.616,5.786],[6.616,10.144],[6.724,10.501]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 193","np":7,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Path 192","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[113.061,-25.5,0],"ix":2},"a":{"a":0,"k":[6.672,10.992,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0.166],[-0.09,0.096],[0,0],[-0.159,0],[-0.124,-0.131],[0,0],[0,-0.165],[0.104,-0.104],[0.16,0],[0.124,0.118],[0,0],[0,0],[0,0],[0,0],[0.104,-0.111],[0.166,0],[0.111,0.104],[0,0.159],[0,0],[0,0],[0,0],[0,0],[0.146,0.008],[0.104,0.098]],"o":[[0,-0.165],[0,0],[0.133,-0.131],[0.159,0],[0,0],[0.098,0.096],[0,0.166],[-0.104,0.098],[-0.145,0.008],[0,0],[0,0],[0,0],[0,0],[0,0.159],[-0.104,0.104],[-0.166,0],[-0.104,-0.111],[0,0],[0,0],[0,0],[0,0],[-0.125,0.118],[-0.159,0],[-0.098,-0.104]],"v":[[3.801,9.844],[3.936,9.45],[6.24,7.166],[6.677,6.968],[7.102,7.166],[9.408,9.45],[9.553,9.844],[9.398,10.25],[9.002,10.395],[8.598,10.23],[7.768,9.399],[7.196,8.682],[7.237,10.011],[7.237,12.939],[7.082,13.345],[6.677,13.5],[6.261,13.345],[6.105,12.939],[6.105,10.011],[6.158,8.682],[5.586,9.399],[4.745,10.23],[4.34,10.395],[3.946,10.25]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0.166,0.166],[0,0.291],[0,0],[-0.166,0.174],[-0.284,0],[0,0],[-0.166,-0.173],[0,-0.284],[0,0],[0.173,-0.173],[0.276,0]],"o":[[-0.284,0],[-0.166,-0.173],[0,0],[0,-0.284],[0.166,-0.173],[0,0],[0.276,0],[0.173,0.174],[0,0],[0,0.291],[-0.166,0.166],[0,0]],"v":[[3.924,6.116],[3.25,5.867],[3.001,5.172],[3.001,3.936],[3.25,3.25],[3.924,2.991],[9.429,2.991],[10.093,3.25],[10.352,3.936],[10.352,5.172],[10.093,5.867],[9.429,6.116]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0.809],[0,0],[-0.519,0.492],[-0.844,0],[0,0],[-0.513,-0.498],[0,-0.811],[0,0],[0.519,-0.49],[0.852,0],[0,0],[0.519,0.499]],"o":[[0,0],[0,-0.811],[0.519,-0.498],[0,0],[0.852,0],[0.519,0.492],[0,0],[0,0.809],[-0.513,0.499],[0,0],[-0.844,0],[-0.519,-0.49]],"v":[[0,19.285],[0,2.701],[0.778,0.748],[2.824,0],[10.519,0],[12.565,0.748],[13.343,2.701],[13.343,19.285],[12.565,21.236],[10.519,21.984],[2.824,21.984],[0.778,21.236]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[-0.235,-0.221],[-0.443,0],[0,0],[-0.235,0.228],[0,0.415],[0,0],[0.236,0.221],[0.437,0],[0,0],[0.235,-0.229],[0,-0.415]],"o":[[0,0.415],[0.235,0.228],[0,0],[0.437,0],[0.236,-0.221],[0,0],[0,-0.415],[-0.235,-0.229],[0,0],[-0.443,0],[-0.235,0.221],[0,0]],"v":[[1.671,19.014],[2.024,19.97],[3.043,20.313],[10.311,20.313],[11.318,19.97],[11.672,19.014],[11.672,2.97],[11.318,2.015],[10.311,1.673],[3.043,1.673],[2.024,2.015],[1.671,2.97]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 192","np":6,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":5,"nm":"Copy Link","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-124,31,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"t":{"d":{"k":[{"s":{"s":16,"f":"SF Pro","t":"Copy Link","j":0,"tr":0,"lh":19.2,"ls":0,"fc":[1,1,1]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[{"nm":"Animators","s":{"t":0,"xe":{"k":0},"ne":{"k":0},"a":{"k":100},"b":1,"sh":0,"s":{"k":0},"e":{"k":100},"o":{"k":0}},"a":{"fo":{"a":0,"k":100,"ix":10},"so":{"a":0,"k":100,"ix":11}}}]},"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":5,"nm":"Move Address Bar","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-124,-20,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"t":{"d":{"k":[{"s":{"s":16,"f":"SF Pro","t":"Move Address Bar","j":0,"tr":0,"lh":19.2,"ls":0,"fc":[1,1,1]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[{"nm":"Animators","s":{"t":0,"xe":{"k":0},"ne":{"k":0},"a":{"k":100},"b":1,"sh":0,"s":{"k":0},"e":{"k":100},"o":{"k":0}},"a":{"fo":{"a":0,"k":100,"ix":10},"so":{"a":0,"k":100,"ix":11}}}]},"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Rectangle 91","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,10],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 91 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,10],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549019608,0.388235294118,0.407843137255,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 91 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Rectangle 90","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,0,0,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":41,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":180,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":3,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":20,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,92],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":13,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 90 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[282,92],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":13,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 90 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Rectangle 86","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,380,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,546],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 86 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,546],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":20,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 86 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Group 77","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,688.115,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,70],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Path 185","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[11.406,2.343,0],"ix":2},"a":{"a":0,"k":[69.753,10.842,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.523,1.105],[0,0],[2.743,0],[0,3.963],[-3.44,0],[0,-3.893],[0,0],[0,0],[0,0],[-2.128,0]],"o":[[0,0],[-0.582,2.14],[-3.475,0],[0,-3.938],[3.382,0],[0,0],[0,0],[0,0],[0.105,2.476],[1.615,0]],"v":[[8.926,14.258],[10.924,14.258],[5.648,17.722],[0,11.248],[5.648,4.752],[11.086,11.051],[11.086,11.818],[2.081,11.818],[2.081,11.91],[5.695,15.955]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[1.986,0],[0.152,-2.22],[0,0]],"o":[[-1.999,0],[0,0],[-0.047,-2.22]],"v":[[5.625,6.519],[2.081,10.203],[8.983,10.203]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[17.615,12.806],[17.431,12.806],[14.454,17.536],[12.189,17.536],[16.478,11.273],[12.142,5.008],[14.524,5.008],[17.501,9.668],[17.685,9.668],[20.625,5.008],[22.892,5.008],[18.638,11.191],[22.95,17.536],[20.58,17.536]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[1.673,0],[0,2.29],[-2.917,0.174],[0,0],[0,0],[1.872,0],[0.281,-0.988],[0,0],[-2.673,0],[0,-2.601],[0,0],[0,0],[0,0],[0,0]],"o":[[-2.429,0],[0,-2.243],[0,0],[0,0],[0,-1.544],[-1.499,0],[0,0],[0.266,-2.009],[3.057,0],[0,0],[0,0],[0,0],[0,0],[-0.814,1.337]],"v":[[28.585,17.722],[24.354,13.991],[28.921,10.285],[32.535,10.063],[32.535,8.924],[29.7,6.531],[26.875,8.087],[24.854,8.087],[29.77,4.752],[34.534,8.924],[34.534,17.501],[32.63,17.501],[32.63,15.654],[32.443,15.654]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[-1.451,0],[0,1.79],[0,0],[0,0],[0,-1.255]],"o":[[2.058,0],[0,0],[0,0],[-1.904,0.127],[0,1.279]],"v":[[28.956,15.967],[32.535,12.829],[32.535,11.679],[29.165,11.9],[26.422,13.944]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[-1.673,0],[-0.58,-1.302],[0,0],[-1.732,0],[0,-2.626],[0,0],[0,0],[0,0],[1.767,0],[0,-1.593],[0,0],[0,0],[0,0],[1.581,0],[0,-1.765],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0.568,-1.394],[1.697,0],[0,0],[0.674,-1.324],[2.556,0],[0,0],[0,0],[0,0],[0,-1.849],[-1.742,0],[0,0],[0,0],[0,0],[0,-1.486],[-1.64,0],[0,0],[0,0]],"v":[[37.658,17.501],[37.658,4.973],[39.565,4.973],[39.565,6.949],[39.751,6.949],[43.248,4.752],[46.711,6.949],[46.897,6.949],[50.733,4.752],[54.718,8.844],[54.718,17.501],[52.719,17.501],[52.719,9.309],[50.081,6.554],[47.176,9.448],[47.176,17.501],[45.178,17.501],[45.178,8.993],[42.564,6.554],[39.657,9.737],[39.657,17.501]],"c":true},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ind":6,"ty":"sh","ix":7,"ks":{"a":0,"k":{"i":[[-1.71,0],[0,-3.94],[3.184,0],[0.687,1.324],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[3.196,0],[0,3.915],[-1.79,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0.802,-1.439]],"v":[[63.898,4.752],[69.162,11.238],[63.898,17.722],[59.98,15.619],[59.796,15.619],[59.796,21.685],[57.797,21.685],[57.797,4.973],[59.702,4.973],[59.702,7.064],[59.888,7.064]],"c":true},"ix":2},"nm":"Path 7","mn":"ADBE Vector Shape - Group","hd":false},{"ind":7,"ty":"sh","ix":8,"ks":{"a":0,"k":{"i":[[-2.253,0],[0,2.927],[2.29,0],[0,-2.882]],"o":[[2.302,0],[0,-2.929],[-2.265,0],[0,2.87]],"v":[[63.42,15.92],[67.094,11.238],[63.433,6.554],[59.736,11.238]],"c":true},"ix":2},"nm":"Path 8","mn":"ADBE Vector Shape - Group","hd":false},{"ind":8,"ty":"sh","ix":9,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[71.844,17.501],[71.844,0],[73.842,0],[73.842,17.501]],"c":true},"ix":2},"nm":"Path 9","mn":"ADBE Vector Shape - Group","hd":false},{"ind":9,"ty":"sh","ix":10,"ks":{"a":0,"k":{"i":[[-0.523,1.105],[0,0],[2.743,0],[0,3.963],[-3.44,0],[0,-3.893],[0,0],[0,0],[0,0],[-2.128,0]],"o":[[0,0],[-0.582,2.14],[-3.475,0],[0,-3.938],[3.382,0],[0,0],[0,0],[0,0],[0.105,2.476],[1.615,0]],"v":[[85.451,14.258],[87.45,14.258],[82.174,17.722],[76.526,11.248],[82.174,4.752],[87.612,11.051],[87.612,11.818],[78.607,11.818],[78.607,11.91],[82.221,15.955]],"c":true},"ix":2},"nm":"Path 10","mn":"ADBE Vector Shape - Group","hd":false},{"ind":10,"ty":"sh","ix":11,"ks":{"a":0,"k":{"i":[[1.986,0],[0.152,-2.22],[0,0]],"o":[[-1.999,0],[0,0],[-0.047,-2.22]],"v":[[82.151,6.519],[78.607,10.203],[85.509,10.203]],"c":true},"ix":2},"nm":"Path 11","mn":"ADBE Vector Shape - Group","hd":false},{"ind":11,"ty":"sh","ix":12,"ks":{"a":0,"k":{"i":[[0.836,0],[0,0.824],[-0.824,0],[0,-0.836]],"o":[[-0.824,0],[0,-0.836],[0.836,0],[0,0.824]],"v":[[91.829,17.618],[90.318,16.107],[91.829,14.596],[93.34,16.107]],"c":true},"ix":2},"nm":"Path 12","mn":"ADBE Vector Shape - Group","hd":false},{"ind":12,"ty":"sh","ix":13,"ks":{"a":0,"k":{"i":[[-0.349,-2.232],[0,0],[1.8,0],[0,-2.835],[-2.232,0],[-0.373,1.417],[0,0],[3.011,0],[0,3.985],[-3.51,0]],"o":[[0,0],[-0.326,-1.244],[-2.255,0],[0,2.892],[1.685,0],[0,0],[-0.361,2.3],[-3.51,0],[0,-3.905],[3.044,0]],"v":[[106.574,8.809],[104.553,8.809],[101.322,6.554],[97.649,11.191],[101.322,15.92],[104.553,13.725],[106.574,13.725],[101.333,17.722],[95.58,11.191],[101.322,4.752]],"c":true},"ix":2},"nm":"Path 13","mn":"ADBE Vector Shape - Group","hd":false},{"ind":13,"ty":"sh","ix":14,"ks":{"a":0,"k":{"i":[[3.567,0],[0,4.02],[-3.569,0],[0,-4.034]],"o":[[-3.569,0],[0,-4.034],[3.567,0],[0,4.02]],"v":[[114.104,17.722],[108.327,11.238],[114.104,4.752],[119.879,11.238]],"c":true},"ix":2},"nm":"Path 14","mn":"ADBE Vector Shape - Group","hd":false},{"ind":14,"ty":"sh","ix":15,"ks":{"a":0,"k":{"i":[[-2.372,0],[0,2.962],[2.37,0],[0,-2.977]],"o":[[2.37,0],[0,-2.977],[-2.372,0],[0,2.962]],"v":[[114.104,15.92],[117.81,11.238],[114.104,6.554],[110.396,11.238]],"c":true},"ix":2},"nm":"Path 15","mn":"ADBE Vector Shape - Group","hd":false},{"ind":15,"ty":"sh","ix":16,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[-1.675,0],[-0.58,-1.302],[0,0],[-1.732,0],[0,-2.626],[0,0],[0,0],[0,0],[1.767,0],[0,-1.593],[0,0],[0,0],[0,0],[1.581,0],[0,-1.765],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0.57,-1.394],[1.695,0],[0,0],[0.674,-1.324],[2.556,0],[0,0],[0,0],[0,0],[0,-1.849],[-1.742,0],[0,0],[0,0],[0,0],[0,-1.486],[-1.638,0],[0,0],[0,0]],"v":[[122.445,17.501],[122.445,4.973],[124.352,4.973],[124.352,6.949],[124.536,6.949],[128.036,4.752],[131.498,6.949],[131.685,6.949],[135.52,4.752],[139.505,8.844],[139.505,17.501],[137.507,17.501],[137.507,9.309],[134.868,6.554],[131.963,9.448],[131.963,17.501],[129.965,17.501],[129.965,8.993],[127.349,6.554],[124.444,9.737],[124.444,17.501]],"c":true},"ix":2},"nm":"Path 16","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 185","np":18,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":0,"nm":"Group 76","parent":11,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-71.782,0.382,0],"ix":2},"a":{"a":0,"k":[7,11.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[13.44,0],[13.44,22.4],[0,22.4]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":14,"h":23,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":0,"nm":"Group 75","parent":11,"refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[216.796,0.801,0],"ix":2},"a":{"a":0,"k":[15.5,15.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[30.8,0],[30.8,30.8],[0,30.8]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":31,"h":31,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Rectangle 70","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.452,0.801,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[496.096,50.4],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":25,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549019608,0.388235294118,0.407843137255,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 70","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"Rectangle 69","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[525,70],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 69","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":"Path 182","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[52.054,748.211,0],"ix":2},"a":{"a":0,"k":[14.429,11.826,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0.477],[-0.367,0.356],[0,0],[-0.204,0.092],[-0.224,0],[-0.316,-0.306],[0,-0.458],[0.092,-0.204],[0.153,-0.154],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.305,-0.316],[0,-0.5],[0.316,-0.314],[0.509,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.092,-0.204],[0,-0.235],[0.316,-0.306],[0.468,0],[0.356,0.348],[0,0]],"o":[[0,-0.479],[0,0],[0.183,-0.183],[0.204,-0.092],[0.468,0],[0.316,0.306],[0,0.246],[-0.092,0.194],[0,0],[0,0],[0,0],[0,0],[0,0],[0.509,0],[0.316,0.306],[0,0.487],[-0.305,0.306],[0,0],[0,0],[0,0],[0,0],[0,0],[0.153,0.154],[0.092,0.204],[0,0.458],[-0.316,0.304],[-0.448,0],[0,0],[-0.367,-0.356]],"v":[[0,11.834],[0.55,10.581],[10.597,0.549],[11.177,0.137],[11.818,0],[12.994,0.458],[13.467,1.603],[13.33,2.275],[12.963,2.795],[9.543,6.261],[3.863,11.468],[3.313,10.475],[8.612,10.155],[27.164,10.155],[28.385,10.627],[28.858,11.834],[28.385,13.039],[27.164,13.497],[8.612,13.497],[3.313,13.193],[3.863,12.215],[9.543,17.406],[12.963,20.857],[13.33,21.392],[13.467,22.049],[12.994,23.194],[11.818,23.652],[10.612,23.132],[0.55,13.085]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 182","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":18,"ty":0,"nm":"Group 74","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[167.187,748.7,0],"ix":2},"a":{"a":0,"k":[23,23,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[45.485,0],[45.485,45.485],[0,45.485]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":46,"h":46,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":19,"ty":0,"nm":"Group 73","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[276.636,748.7,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":"Path 178","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[386.126,749.23,0],"ix":2},"a":{"a":0,"k":[9.438,6.275,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0.633],[-0.508,0.466],[0,0],[0,0.866],[1.074,0],[0.433,-0.968],[0.541,0],[0,0.624],[-0.058,0.177],[-2.275,0],[0,-2.067],[1.965,-1.857],[0,0],[0,0],[0,0],[0,-0.608],[0.649,0]],"o":[[-0.791,0],[0,-0.475],[0,0],[1.482,-1.424],[0,-0.991],[-0.968,0],[-0.283,0.5],[-0.674,0],[0,-0.191],[0.408,-1.332],[2.548,0],[0,1.465],[0,0],[0,0],[0,0],[0.649,0],[0,0.591],[0,0]],"v":[[1.182,12.284],[0,11.21],[0.691,9.953],[4.273,6.529],[6.138,3.657],[4.298,1.956],[2.231,3.407],[1.116,4.14],[0.042,3.116],[0.133,2.573],[4.323,0],[8.585,3.499],[5.905,7.736],[3.305,10.236],[3.305,10.286],[7.836,10.286],[8.877,11.285],[7.836,12.284]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[2.789,0],[0.566,1.182],[0,0.25],[-0.691,0],[-0.25,-0.458],[-1.249,0],[0,0.999],[1.457,0],[0,0],[0,0.541],[-0.608,0],[0,0],[0,0.982],[1.215,0],[0.393,-0.851],[0.566,0],[0,0.608],[-0.125,0.283],[-2.125,0],[0,-1.925],[1.415,-0.291],[0,0],[0,-1.659]],"o":[[-2.292,0],[-0.133,-0.275],[0,-0.649],[0.5,0],[0.427,0.841],[1.232,0],[0.008,-1.168],[0,0],[-0.608,0],[0,-0.524],[0,0],[1.257,0],[0,-0.968],[-1.016,0],[-0.275,0.566],[-0.699,0],[0,-0.283],[0.533,-1.174],[2.539,0],[0,1.523],[0,0],[1.792,0.167],[0,2.181]],"v":[[14.195,12.55],[9.93,10.377],[9.738,9.586],[10.846,8.529],[11.911,9.187],[14.236,10.527],[16.318,8.812],[14.011,6.995],[13.487,6.995],[12.53,6.096],[13.487,5.205],[13.978,5.205],[16.051,3.54],[14.186,1.931],[12.161,3.207],[11.029,3.982],[9.972,2.966],[10.155,2.156],[14.178,0],[18.434,3.182],[15.926,5.996],[15.926,6.046],[18.876,8.92]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.854901960784,0.862745098039,0.878431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 178","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":21,"ty":0,"nm":"Group 71","refId":"comp_5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[487.004,748.7,0],"ix":2},"a":{"a":0,"k":[26,26,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,0],[51.171,0],[51.171,51.17],[0,51.17]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":52,"h":52,"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":"Rectangle 77","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,737,0],"ix":2},"a":{"a":0,"k":[262.5,65,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,66],[461,130],[64,130],[0,66]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 77 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,66],[461,130],[64,130],[0,66]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 77 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":23,"ty":4,"nm":"Rectangle 83","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,278,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 83 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509803922,0.290196078431,0.305882352941,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 83 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":24,"ty":4,"nm":"Rectangle 81","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,320,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 81 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509803922,0.290196078431,0.305882352941,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 81 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":25,"ty":4,"nm":"Rectangle 80","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,362,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 80 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509803922,0.290196078431,0.305882352941,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 80 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":26,"ty":4,"nm":"Rectangle 79","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[177,404,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[296,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 79 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[296,30],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509803922,0.290196078431,0.305882352941,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 79 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":27,"ty":4,"nm":"Rectangle 84","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,179,0],"ix":2},"a":{"a":0,"k":[245.5,72,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[11.046,0],[0,0],[0,11.046]],"o":[[0,0],[0,0],[0,0],[0,0],[0,11.046],[0,0],[-11.046,0],[0,0]],"v":[[0,0],[0,0],[491,0],[491,0],[491,124],[471,144],[20,144],[0,124]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 84 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[11.046,0],[0,0],[0,11.046]],"o":[[0,0],[0,0],[0,0],[0,0],[0,11.046],[0,0],[-11.046,0],[0,0]],"v":[[0,0],[0,0],[491,0],[491,0],[491,124],[471,144],[20,144],[0,124]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509803922,0.290196078431,0.305882352941,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 84 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":28,"ty":4,"nm":"Rectangle 78","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,575,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,266],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 78 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[491,266],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.274509803922,0.290196078431,0.305882352941,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 78 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":29,"ty":4,"nm":"Rectangle 76","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[274.5,454.5,0],"ix":2},"a":{"a":0,"k":[262.5,347.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,631],[461,695],[64,695],[0,631]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"op","nm":"Offset Paths 1","a":{"a":0,"k":-0.5,"ix":1},"lj":1,"ml":{"a":0,"k":4,"ix":3},"ix":3,"mn":"ADBE Vector Filter - Offset","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 76 Stroke","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[35.346,0],[0,0],[0,35.346]],"o":[[0,0],[0,0],[0,0],[0,0],[0,35.346],[0,0],[-35.346,0],[0,0]],"v":[[0,0],[0,0],[525,0],[525,0],[525,631],[461,695],[64,695],[0,631]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.207843137255,0.21568627451,0.223529411765,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 76 Fill","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0},{"ddd":0,"ind":30,"ty":4,"nm":"Path 161","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":0,"k":[274.5,460.628,0],"ix":2},"a":{"a":0,"k":[274.5,353.372,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-39.692,0],[0,0],[0,-38.817],[0,0],[0,0]],"o":[[0,-38.817],[0,0],[39.692,0],[0,0],[0,0],[0,0]],"v":[[0,70.284],[71.869,0],[477.131,0],[549,70.284],[549,706.744],[0,706.744]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 161","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":3600,"st":0,"bm":0}],"markers":[],"chars":[{"ch":"M","size":16,"style":"Regular","w":83.3,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0.098,3.597],[0,1.758],[0,0],[0,0],[0,0],[0,0],[0.065,-3.385],[0,-1.465],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,-1.692],[-0.098,-3.596],[0,0],[0,0],[0,0],[0,0],[0,3.874],[-0.066,3.386],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[7.373,0],[16.65,0],[16.65,-42.334],[16.504,-50.269],[16.357,-58.301],[16.357,-60.498],[37.032,0],[46.66,0],[67.139,-60.498],[67.041,-49.609],[66.943,-42.334],[66.943,0],[76.221,0],[76.221,-71.729],[62.398,-71.729],[41.919,-11.084],[21.294,-71.729],[7.373,-71.729]],"c":true},"ix":2},"nm":"M","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"M","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"o","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[5.761,0],[2.414,3.706],[0,5.56],[-2.414,4.097],[-5.312,0],[-2.446,-4.812],[0,-4.877],[2.141,-4.405]],"o":[[-5.247,0],[-2.414,-3.706],[0,-5.787],[2.414,-4.097],[5.987,0],[1.545,3.056],[0,5.397],[-2.141,4.405]],"v":[[27.026,-5.713],[15.535,-11.272],[11.914,-25.172],[15.535,-39.997],[27.122,-46.143],[39.772,-38.924],[42.09,-27.025],[38.879,-12.321]],"c":true},"ix":2},"nm":"o","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[6.691,0],[4.428,-5.203],[0,-8.781],[-4.202,-4.862],[-7.144,0],[-4.073,5.496],[0,8.424],[4.622,4.488]],"o":[[-7.467,0],[-4.428,5.204],[0,8.196],[4.202,4.862],[8.566,0],[4.073,-5.496],[0,-8.716],[-4.623,-4.488]],"v":[[27.366,-53.809],[9.523,-46.003],[2.881,-25.025],[9.184,-5.437],[26.202,1.855],[45.16,-6.389],[51.27,-27.27],[44.336,-47.076]],"c":true},"ix":2},"nm":"o","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"o","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"v","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.562,-52.295],[19.849,0],[29.214,0],[48.901,-52.295],[39.282,-52.295],[24.731,-9.717],[10.767,-52.295]],"c":true},"ix":2},"nm":"v","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"v","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"e","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.688,0],[4.529,-5.241],[0,-8.398],[-4.497,-4.736],[-6.47,0],[-2.1,0.52],[-2.65,2.605],[-1.286,2.361],[-0.228,1.921],[0,0],[1.518,-1.765],[4.554,0],[2.325,3.215],[0.162,5.321],[0,0],[0.517,2.409],[1.747,2.637],[3.461,1.742]],"o":[[-7.312,0],[-4.53,5.241],[0,8.529],[4.497,4.736],[2.649,0],[3.909,-0.912],[1.582,-1.497],[1.286,-2.36],[0,0],[-0.633,2.322],[-2.713,3.041],[-4.877,0],[-2.325,-3.215],[0,0],[0,-5.273],[-0.583,-3.516],[-1.812,-2.766],[-3.462,-1.741]],"v":[[28.022,-53.467],[10.261,-45.605],[3.467,-25.146],[10.211,-5.249],[26.661,1.855],[33.784,1.074],[43.622,-4.199],[47.925,-9.985],[50.195,-16.406],[41.553,-16.406],[38.326,-10.275],[27.425,-5.713],[16.621,-10.535],[12.891,-23.34],[50.928,-23.34],[50.151,-34.863],[46.657,-44.092],[38.747,-50.854]],"c":true},"ix":2},"nm":"e","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-2.711,2.914],[-4.002,0],[-2.389,-4.231],[-0.356,-3.809]],"o":[[0.161,-4.492],[2.711,-2.913],[5.584,0],[1.291,2.279],[0,0]],"v":[[13.086,-30.322],[17.395,-41.431],[27.466,-45.801],[39.425,-39.453],[41.895,-30.322]],"c":true},"ix":2},"nm":"e","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"e","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":" ","size":16,"style":"Regular","w":27.78,"data":{},"fFamily":"SF Pro"},{"ch":"A","size":16,"style":"Regular","w":66.7,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[21.973,-29.395],[33.545,-61.084],[44.434,-29.395]],"c":true},"ix":2},"nm":"A","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[1.465,0],[11.426,0],[19.189,-21.484],[47.559,-21.484],[54.834,0],[65.479,0],[39.453,-71.729],[28.467,-71.729]],"c":true},"ix":2},"nm":"A","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"A","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"d","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,5.599],[-2.737,3.386],[-4.405,0],[-2.689,-3.174],[0,-6.608],[2.607,-3.499],[4.048,0],[2.364,3.777]],"o":[[0,-6.575],[2.737,-3.385],[3.951,0],[2.688,3.174],[0,6.543],[-2.608,3.5],[-5.215,0],[-2.364,-3.776]],"v":[[12.012,-25.537],[16.116,-40.479],[26.829,-45.557],[36.788,-40.796],[40.82,-26.123],[36.909,-11.06],[26.926,-5.811],[15.558,-11.475]],"c":true},"ix":2},"nm":"d","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[3.989,0],[3.875,-5.582],[0,-7.617],[-4.248,-4.899],[-5.804,0],[-2.789,1.432],[-2.043,3.223],[0,0],[0,0],[0,0],[0,0],[0,0],[1.556,0.977]],"o":[[-7.199,0],[-3.875,5.583],[0,8.138],[4.248,4.9],[3.6,0],[2.789,-1.432],[0,0],[0,0],[0,0],[0,0],[0,0],[-1.978,-2.441],[-2.692,-1.692]],"v":[[25.157,-53.223],[8.546,-44.849],[2.734,-25.049],[9.106,-5.493],[24.185,1.855],[33.768,-0.293],[41.016,-7.275],[41.016,0],[48.926,0],[48.926,-71.973],[40.479,-71.973],[40.479,-45.557],[35.177,-50.684]],"c":true},"ix":2},"nm":"d","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"d","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"r","size":16,"style":"Regular","w":33.3,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-2.377,2.849],[-4.427,0],[-0.439,-0.032],[-0.521,-0.098],[0,0],[0.391,0.033],[0.163,0],[2.669,-2.522],[0.684,-1.758],[0,0],[0,0]],"o":[[0,0],[0,0],[0,-3.711],[2.376,-2.848],[0.52,0],[0.439,0.033],[0,0],[-0.945,-0.098],[-0.391,-0.032],[-3.484,0],[-2.67,2.523],[0,0],[0,0],[0,0]],"v":[[6.689,0],[15.479,0],[15.479,-30.078],[19.043,-39.917],[29.248,-44.189],[30.688,-44.141],[32.129,-43.945],[32.129,-53.223],[30.127,-53.418],[29.297,-53.467],[20.068,-49.683],[15.039,-43.262],[15.039,-52.295],[6.689,-52.295]],"c":true},"ix":2},"nm":"r","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"r","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"s","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-3.279,-3.532],[-7.877,0],[-3.576,3.385],[0,4.655],[3.418,2.246],[6.434,1.53],[0,0],[1.326,0.811],[0,2.271],[-1.749,1.265],[-3.399,0],[-2.066,-2.298],[-0.167,-1.974],[0,0],[2.21,2.93],[7.983,0],[3.612,-3.059],[0,-4.948],[-3.838,-2.376],[-4.532,-1.106],[0,0],[-1.291,-0.716],[0,-2.246],[2.525,-1.416],[3.322,0],[2.259,2.832],[0.266,2.93]],"o":[[0.23,5.209],[3.279,3.532],[7.317,0],[3.576,-3.385],[0,-4.817],[-2.19,-1.432],[0,0],[-2.587,-0.618],[-2.299,-1.363],[0,-2.075],[1.749,-1.265],[5.098,0],[1.266,1.619],[0,0],[0.065,-3.385],[-3.529,-4.622],[-6.104,0],[-3.613,3.06],[0,4.199],[2.15,1.367],[0,0],[3.804,0.945],[2.018,1.172],[0,2.962],[-2.525,1.416],[-5.582,0],[-1.23,-1.562],[0,0]],"v":[[3.223,-16.406],[8.488,-3.296],[25.221,2.002],[41.56,-3.076],[46.924,-15.137],[41.797,-25.732],[28.862,-30.176],[22.942,-31.592],[17.072,-33.736],[13.623,-39.185],[16.247,-44.196],[23.969,-46.094],[34.716,-42.646],[36.865,-37.256],[45.166,-37.256],[41.948,-46.729],[24.679,-53.662],[10.106,-49.072],[4.688,-37.061],[10.444,-27.197],[20.467,-23.486],[27.563,-21.729],[35.205,-19.238],[38.232,-14.111],[34.444,-7.544],[25.674,-5.42],[13.912,-9.668],[11.67,-16.406]],"c":true},"ix":2},"nm":"s","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"s","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"B","size":16,"style":"Regular","w":66.7,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-2.171,-0.911],[0,-4.688],[3.618,-1.79],[4.144,0]],"o":[[0,0],[0,0],[4.276,0],[3.848,1.628],[0,4.655],[-2.303,1.14],[0,0]],"v":[[16.895,-41.406],[16.895,-63.623],[34.41,-63.623],[44.081,-62.256],[49.854,-52.783],[44.426,-43.115],[34.756,-41.406]],"c":true},"ix":2},"nm":"B","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-2.498,-1.009],[0,-5.208],[1.61,-2.18],[6.013,0]],"o":[[0,0],[0,0],[4.108,0],[4.699,1.888],[0,3.093],[-2.563,3.451],[0,0]],"v":[[16.895,-8.301],[16.895,-33.545],[36.364,-33.545],[46.272,-32.031],[53.32,-21.387],[50.905,-13.477],[38.04,-8.301]],"c":true},"ix":2},"nm":"B","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-4.356,5.599],[0,4.623],[3.223,3.125],[3.678,1.4],[-1.335,1.53],[0,4.525],[2.097,2.962],[8.453,0],[0,0]],"o":[[0,0],[9.498,0],[2.914,-3.743],[0,-5.501],[-1.823,-1.758],[2.506,-1.27],[2.571,-2.897],[0,-3.873],[-3.572,-5.013],[0,0],[0,0]],"v":[[7.373,0],[37.883,0],[58.665,-8.398],[63.037,-20.947],[58.203,-33.887],[49.951,-38.623],[55.713,-42.822],[59.57,-53.955],[56.425,-64.209],[38.387,-71.729],[7.373,-71.729]],"c":true},"ix":2},"nm":"B","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"B","np":6,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"a","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,2.533],[-2.718,1.527],[-3.184,0.423],[0,0],[-1.689,0.458],[-1.073,0.686],[0,0],[4.883,-2.373],[3.092,0],[1.855,1.462]],"o":[[0,-3.345],[1.604,-0.909],[0,0],[1.624,-0.195],[1.689,-0.457],[0,0],[0,5.396],[-2.898,1.43],[-2.539,0],[-1.855,-1.462]],"v":[[13.184,-13.897],[17.261,-21.204],[24.443,-23.203],[29.755,-23.885],[34.725,-24.863],[38.867,-26.578],[38.867,-19.509],[31.543,-7.858],[22.559,-5.713],[15.967,-7.905]],"c":true},"ix":2},"nm":"a","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[3.027,-2.666],[0,-4.844],[-3.076,-2.942],[-4.851,0],[-3.353,1.724],[-1.791,2.344],[-0.716,-1.139],[-3.027,0],[-0.716,0.098],[-1.367,0.391],[0,0],[0.488,-0.049],[0.391,0],[0.374,0.552],[0,0.912],[0,0],[3.804,2.344],[6.145,0],[4.015,-2.53],[0.163,-6.464],[0,0],[-1.072,1.375],[-4.581,0],[-2.128,-1.356],[0,-3.006],[0.39,-0.784],[2.018,-0.259]],"o":[[-4.916,0.618],[-3.027,2.666],[0,4.422],[3.076,2.942],[4.036,0],[3.352,-1.725],[0.293,2.083],[1.367,2.148],[1.237,0],[0.716,-0.098],[0,0],[-0.554,0.098],[-0.488,0.049],[-1.205,0],[-0.375,-0.552],[0,0],[0,-4.948],[-3.837,-2.344],[-5.299,0],[-4.015,2.53],[0,0],[0.325,-2.715],[1.917,-2.486],[3.963,0],[2.128,1.357],[0,1.471],[-0.684,1.43],[0,0]],"v":[[20.459,-29.893],[8.545,-24.966],[4.004,-13.702],[8.618,-2.656],[20.508,1.758],[31.592,-0.829],[39.307,-6.932],[40.82,-2.099],[47.412,1.123],[50.342,0.977],[53.467,0.244],[53.467,-6.249],[51.904,-6.03],[50.586,-5.957],[48.218,-6.786],[47.656,-8.982],[47.656,-39.111],[41.95,-50.049],[26.978,-53.564],[13.005,-49.77],[6.738,-36.279],[14.941,-36.279],[17.036,-42.413],[26.783,-46.143],[35.919,-44.109],[39.111,-37.565],[38.526,-34.183],[34.473,-31.648]],"c":true},"ix":2},"nm":"a","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"a","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"C","size":16,"style":"Regular","w":72.22,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[8.976,0],[5.984,-7.361],[0,-10.586],[-7.368,-6.677],[-8.237,0],[-5.631,6.152],[-0.837,7.552],[0,0],[1.95,-2.897],[7.035,0],[3.853,5.229],[0,8.406],[-4.268,4.968],[-6.937,0],[-3.149,-2.702],[-1.055,-4.622],[0,0],[4.955,4.785]],"o":[[-10.521,0],[-5.534,6.776],[0,13.942],[5.598,5.049],[9.557,0],[4.697,-5.11],[0,0],[-0.96,4.72],[-3.677,5.502],[-7.642,0],[-3.854,-5.229],[0,-10.262],[4.268,-4.968],[5.69,0],[3.149,2.702],[0,0],[-0.547,-6.087],[-4.955,-4.785]],"v":[[37.453,-73.682],[12.695,-62.64],[4.395,-36.597],[15.447,-5.669],[36.201,1.904],[58.984,-7.324],[67.285,-26.318],[57.812,-26.318],[53.448,-14.893],[37.379,-6.641],[20.135,-14.484],[14.355,-34.936],[20.757,-57.782],[37.564,-65.234],[50.823,-61.182],[57.129,-50.195],[66.602,-50.195],[58.349,-66.504]],"c":true},"ix":2},"nm":"C","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"C","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"p","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[4.115,0],[2.286,5.404],[0,4.037],[-1.208,3.255],[-6.108,0],[-2.287,-5.762],[0,-4.166],[2.727,-3.434]],"o":[[-6.076,0],[-1.208,-2.832],[0,-5.013],[2.254,-6.087],[6.075,0],[1.208,2.995],[0,6.836],[-2.728,3.435]],"v":[[28.516,-5.908],[15.973,-14.014],[14.16,-24.316],[15.973,-36.719],[28.516,-45.85],[41.058,-37.207],[42.871,-26.465],[38.78,-11.06]],"c":true},"ix":2},"nm":"p","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-1.569,-0.977],[-3.954,0],[-3.791,3.092],[0,11.394],[4.144,4.541],[5.94,0],[2.969,-1.953],[1.762,-2.376],[0,0],[0,0]],"o":[[0,0],[0,0],[1.928,2.377],[2.679,1.725],[5.032,0],[5.98,-4.883],[0,-8.43],[-4.145,-4.541],[-4.015,0],[-2.089,1.302],[0,0],[0,0],[0,0]],"v":[[5.713,20.85],[14.502,20.85],[14.502,-5.859],[19.747,-0.83],[29.698,1.758],[42.934,-2.881],[51.904,-27.295],[45.687,-46.753],[30.56,-53.564],[20.084,-50.635],[14.307,-45.117],[14.307,-52.051],[5.713,-52.051]],"c":true},"ix":2},"nm":"p","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"p","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"y","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[1.007,-2.405],[0.162,-0.26],[0.764,-0.536],[1.624,0],[0.682,0.098],[1.527,0.423],[0,0],[-0.667,-0.098],[-1.236,0],[-2.081,2.927],[-5.074,13.336],[-3.191,8.989],[-1.237,3.355],[0,0]],"o":[[0,0],[0,0],[0,0],[-0.455,1.169],[-1.007,2.403],[-0.52,0.78],[-0.764,0.536],[-0.52,0],[-0.682,-0.098],[0,0],[0.975,0.26],[0.667,0.098],[5.074,0],[2.081,-2.928],[2.148,-5.666],[4.264,-11.952],[0,0],[0,0]],"v":[[25.024,-9.698],[11.011,-52.295],[1.05,-52.295],[20.386,1.538],[18.192,6.898],[16.438,10.894],[14.511,12.868],[10.929,13.672],[9.125,13.525],[5.811,12.744],[5.811,20.752],[8.274,21.289],[11.128,21.436],[21.861,17.044],[32.593,-7.352],[40.601,-29.335],[48.853,-52.295],[39.136,-52.295]],"c":true},"ix":2},"nm":"y","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"y","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"L","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[7.617,0],[53.32,0],[53.32,-8.545],[17.334,-8.545],[17.334,-71.729],[7.617,-71.729]],"c":true},"ix":2},"nm":"L","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"L","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"i","size":16,"style":"Regular","w":22.22,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[6.445,0],[15.381,0],[15.381,-52.051],[6.445,-52.051]],"c":true},"ix":2},"nm":"i","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[6.445,-61.768],[15.381,-61.768],[15.381,-71.729],[6.445,-71.729]],"c":true},"ix":2},"nm":"i","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"i","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"n","size":16,"style":"Regular","w":55.62,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-0.439,1.839],[-1.465,1.726],[-2.409,0.716],[-2.084,0],[-1.562,-3.255],[0,-3.19],[0,0],[0,0],[0,0],[1.432,2.832],[7.422,0],[2.766,-1.334],[2.473,-3.059],[0,0],[0,0]],"o":[[0,0],[0,0],[0,-3.418],[0.439,-1.839],[1.823,-2.148],[1.334,-0.423],[4.102,0],[0.944,1.953],[0,0],[0,0],[0,0],[0,-5.273],[-2.605,-5.176],[-3.386,0],[-2.767,1.335],[0,0],[0,0],[0,0]],"v":[[6.445,0],[15.234,0],[15.234,-27.393],[15.894,-35.278],[18.75,-40.625],[25.098,-44.922],[30.225,-45.557],[38.721,-40.674],[40.137,-32.959],[40.137,0],[49.072,0],[49.072,-33.545],[46.924,-45.703],[31.885,-53.467],[22.656,-51.465],[14.795,-44.873],[14.795,-52.295],[6.445,-52.295]],"c":true},"ix":2},"nm":"n","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"n","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"},{"ch":"k","size":16,"style":"Regular","w":50,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[6.25,0],[14.697,0],[14.697,-19.629],[21.914,-26.611],[38.362,0],[49.59,0],[28.364,-32.851],[48.463,-52.295],[37.235,-52.295],[14.697,-30.083],[14.697,-71.729],[6.25,-71.729]],"c":true},"ix":2},"nm":"k","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"k","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"SF Pro"}]} \ No newline at end of file
diff --git a/ios/chrome/browser/ui/whats_new/data_source/resources/whats_new_entries.plist b/ios/chrome/browser/ui/whats_new/data_source/resources/whats_new_entries.plist index 8e454d72..b5e2b37a 100644 --- a/ios/chrome/browser/ui/whats_new/data_source/resources/whats_new_entries.plist +++ b/ios/chrome/browser/ui/whats_new/data_source/resources/whats_new_entries.plist
@@ -51,7 +51,7 @@ <string>IDS_IOS_WHATS_NEW_BOTTOMOMNIBOX_SCREENSHOT_TEXT_2</string> </dict> <key>IconImageName</key> - <string>circle</string> + <string>globe.americas.fill</string> <key>IconBackgroundColor</key> <string>blue</string> <key>IsSymbol</key>
diff --git a/ios/chrome/common/BUILD.gn b/ios/chrome/common/BUILD.gn index e9201d8..315b8839 100644 --- a/ios/chrome/common/BUILD.gn +++ b/ios/chrome/common/BUILD.gn
@@ -25,14 +25,6 @@ public_deps = [ ":timing" ] } -source_set("button_config") { - sources = [ - "button_configuration_util.h", - "button_configuration_util.mm", - ] - frameworks = [ "UIKit.framework" ] -} - source_set("constants") { sources = [ "constants.h",
diff --git a/ios/chrome/common/button_configuration_util.h b/ios/chrome/common/button_configuration_util.h deleted file mode 100644 index 85c6294..0000000 --- a/ios/chrome/common/button_configuration_util.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_COMMON_BUTTON_CONFIGURATION_UTIL_H_ -#define IOS_CHROME_COMMON_BUTTON_CONFIGURATION_UTIL_H_ - -#import <UIKit/UIKit.h> - -// Sets ContentEdgeInsets for the button. -void SetContentEdgeInsets(UIButton* button, UIEdgeInsets insets); - -// Sets ImageEdgeInsets for the button. -void SetImageEdgeInsets(UIButton* button, UIEdgeInsets insets); - -// Sets TitleEdgeInsets for the button. -void SetTitleEdgeInsets(UIButton* button, UIEdgeInsets insets); - -// Sets AdjustsImageWhenHighlighted for the button. -void SetAdjustsImageWhenHighlighted(UIButton* button, bool isHighlighted); - -#endif // IOS_CHROME_COMMON_BUTTON_CONFIGURATION_UTIL_H_
diff --git a/ios/chrome/common/button_configuration_util.mm b/ios/chrome/common/button_configuration_util.mm deleted file mode 100644 index 841dfbc..0000000 --- a/ios/chrome/common/button_configuration_util.mm +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/common/button_configuration_util.h" - -// TODO(crbug.com/1423432): Reenable warning by removing method when it's no -// longer needed. -void SetContentEdgeInsets(UIButton* button, UIEdgeInsets insets) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - button.contentEdgeInsets = insets; -#pragma clang diagnostic pop -} - -// TODO(crbug.com/1423432): Reenable warning by removing method when it's no -// longer needed. -void SetImageEdgeInsets(UIButton* button, UIEdgeInsets insets) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - button.imageEdgeInsets = insets; -#pragma clang diagnostic pop -} - -// TODO(crbug.com/1423432): Reenable warning by removing method when it's no -// longer needed. -void SetTitleEdgeInsets(UIButton* button, UIEdgeInsets insets) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - button.titleEdgeInsets = insets; -#pragma clang diagnostic pop -} - -// TODO(crbug.com/1423432): Reenable warning by removing method when it's no -// longer needed. -void SetAdjustsImageWhenHighlighted(UIButton* button, bool isHighlighted) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - button.adjustsImageWhenHighlighted = isHighlighted; -#pragma clang diagnostic pop -}
diff --git a/ios/chrome/test/earl_grey/eg_tests_hook.mm b/ios/chrome/test/earl_grey/eg_tests_hook.mm index 28dcb26..87d2bab 100644 --- a/ios/chrome/test/earl_grey/eg_tests_hook.mm +++ b/ios/chrome/test/earl_grey/eg_tests_hook.mm
@@ -175,6 +175,10 @@ // No-op for Earl Grey. } +void SignalAppLaunched() { + // No-op for Earl Grey. +} + base::TimeDelta PasswordCheckMinimumDuration() { // No delays for eg tests. return base::Seconds(0);
diff --git a/ios/chrome/test/earl_grey2/BUILD.gn b/ios/chrome/test/earl_grey2/BUILD.gn index 561f9d63..996f08b 100644 --- a/ios/chrome/test/earl_grey2/BUILD.gn +++ b/ios/chrome/test/earl_grey2/BUILD.gn
@@ -98,6 +98,7 @@ "//ios/chrome/browser/ssl/model:eg2_tests", "//ios/chrome/browser/supervised_user/model:eg2_tests", "//ios/chrome/browser/sync/model/prefs:eg2_tests", + "//ios/chrome/browser/tips_notifications/eg_test:eg2_tests", "//ios/chrome/browser/ui/autofill:eg2_tests", "//ios/chrome/browser/ui/autofill/branding:eg2_tests", "//ios/chrome/browser/ui/autofill/manual_fill:eg2_tests",
diff --git a/ios/chrome/test/wpt/cwt_tests_hook.mm b/ios/chrome/test/wpt/cwt_tests_hook.mm index 87c708c..32fdbf1 100644 --- a/ios/chrome/test/wpt/cwt_tests_hook.mm +++ b/ios/chrome/test/wpt/cwt_tests_hook.mm
@@ -77,6 +77,8 @@ void RunTestsIfPresent() {} +void SignalAppLaunched() {} + base::TimeDelta PasswordCheckMinimumDuration() { // No artificial delays for tests. return base::Seconds(0);
diff --git a/ios/chrome/test/xcuitest/xcuitests_hook.mm b/ios/chrome/test/xcuitest/xcuitests_hook.mm index 39131c8d..f6c60f3 100644 --- a/ios/chrome/test/xcuitest/xcuitests_hook.mm +++ b/ios/chrome/test/xcuitest/xcuitests_hook.mm
@@ -89,6 +89,10 @@ // No-op for XCUITest. } +void SignalAppLaunched() { + // No-op for XCUITest. +} + base::TimeDelta PasswordCheckMinimumDuration() { // No artificial delays for tests. return base::Seconds(0);
diff --git a/ios/components/security_interstitials/safe_browsing/fake_safe_browsing_service.mm b/ios/components/security_interstitials/safe_browsing/fake_safe_browsing_service.mm index 8d64d3c..495263a9 100644 --- a/ios/components/security_interstitials/safe_browsing/fake_safe_browsing_service.mm +++ b/ios/components/security_interstitials/safe_browsing/fake_safe_browsing_service.mm
@@ -37,11 +37,9 @@ security_interstitials::UnsafeResource::kNoFrameTreeNodeId, /*navigation_id=*/std::nullopt, /*url_real_time_lookup_enabled=*/false, - /*can_urt_check_subresource_url=*/false, /*can_check_db=*/true, /*can_check_high_confidence_allowlist=*/true, /*url_lookup_service_metric_suffix=*/"", - /*last_committed_url=*/GURL(), web::GetUIThreadTaskRunner({}), /*url_lookup_service_on_ui=*/nullptr, /*hash_realtime_service_on_ui=*/nullptr,
diff --git a/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm b/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm index a0c7981a..7d5c7ec 100644 --- a/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm +++ b/ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.mm
@@ -148,8 +148,6 @@ client->GetRealTimeUrlLookupService(); bool can_perform_full_url_lookup = url_lookup_service && url_lookup_service->CanPerformFullURLLookup(); - bool can_url_realtime_check_subresource_url = - url_lookup_service && url_lookup_service->CanCheckSubresourceURL(); scoped_refptr<safe_browsing::UrlCheckerDelegate> url_checker_delegate = base::MakeRefCounted<UrlCheckerDelegateImpl>(safe_browsing_db_manager_, client->AsWeakPtr()); @@ -177,10 +175,8 @@ /*frame_tree_node_id=*/ security_interstitials::UnsafeResource::kNoFrameTreeNodeId, /*navigation_id=*/std::nullopt, can_perform_full_url_lookup, - can_url_realtime_check_subresource_url, /*can_check_db=*/true, /*can_check_high_confidence_allowlist=*/true, /*url_lookup_service_metric_suffix=*/"", - /*last_committed_url=*/web_state->GetLastCommittedURL(), web::GetUIThreadTaskRunner({}), url_lookup_service ? url_lookup_service->GetWeakPtr() : nullptr, hash_real_time_service ? hash_real_time_service->GetWeakPtr() : nullptr,
diff --git a/ios/components/security_interstitials/safe_browsing/safe_browsing_service_unittest.mm b/ios/components/security_interstitials/safe_browsing/safe_browsing_service_unittest.mm index 7979d92d..ac99af4 100644 --- a/ios/components/security_interstitials/safe_browsing/safe_browsing_service_unittest.mm +++ b/ios/components/security_interstitials/safe_browsing/safe_browsing_service_unittest.mm
@@ -418,7 +418,7 @@ client.CheckUrl(safe_url); client.WaitForResult(); - // Opt into real-time checks and also does real-time checks for subframe url. + // Opt into real-time checks. pref_service_->SetBoolean(prefs::kSafeBrowsingEnhanced, true); MarkUrlAsRealTimeSafe(safe_url); @@ -443,12 +443,13 @@ EXPECT_FALSE(client.result_pending()); EXPECT_TRUE(client.url_is_unsafe()); + // Subframe URL should not be checked. MarkUrlAsRealTimeUnsafe(unsafe_url); client.CheckSubFrameUrl(unsafe_url); EXPECT_TRUE(client.result_pending()); client.WaitForResult(); EXPECT_FALSE(client.result_pending()); - EXPECT_TRUE(client.url_is_unsafe()); + EXPECT_FALSE(client.url_is_unsafe()); // Opt out of real-time checks, and ensure that unsafe URLs are no longer // flagged. @@ -460,14 +461,6 @@ } EXPECT_FALSE(client.result_pending()); EXPECT_FALSE(client.url_is_unsafe()); - - client.CheckSubFrameUrl(unsafe_url); - if (!base::FeatureList::IsEnabled(safe_browsing::kSafeBrowsingOnUIThread)) { - EXPECT_TRUE(client.result_pending()); - client.WaitForResult(); - } - EXPECT_FALSE(client.result_pending()); - EXPECT_FALSE(client.url_is_unsafe()); } // Verifies that cookies are persisted across calls to
diff --git a/ios/web/web_state/ui/crw_web_controller_container_view.mm b/ios/web/web_state/ui/crw_web_controller_container_view.mm index 9b18ff9..7d5d9ad57 100644 --- a/ios/web/web_state/ui/crw_web_controller_container_view.mm +++ b/ios/web/web_state/ui/crw_web_controller_container_view.mm
@@ -190,11 +190,15 @@ // Update the content view frame. - (void)updateWebViewContentViewFrame { - if (self.cover) { + if (base::FeatureList::IsEnabled(web::features::kSmoothScrollingDefault)) { [self.webViewContentView setFrame:self.bounds]; } else { - [self.webViewContentView - setFrame:UIEdgeInsetsInsetRect(self.bounds, self.safeAreaInsets)]; + if (self.cover) { + [self.webViewContentView setFrame:self.bounds]; + } else { + [self.webViewContentView + setFrame:UIEdgeInsetsInsetRect(self.bounds, self.safeAreaInsets)]; + } } }
diff --git a/ios_internal b/ios_internal index ee8bfec..4bc68c8 160000 --- a/ios_internal +++ b/ios_internal
@@ -1 +1 @@ -Subproject commit ee8bfecb9125511f41a7f526b5d1cd83157622f1 +Subproject commit 4bc68c8a54b6e0b2778a9779b5270fdaef88a30e
diff --git a/media/gpu/chromeos/image_processor_backend.cc b/media/gpu/chromeos/image_processor_backend.cc index 0e3637b4..e3e0ff0 100644 --- a/media/gpu/chromeos/image_processor_backend.cc +++ b/media/gpu/chromeos/image_processor_backend.cc
@@ -45,8 +45,6 @@ } // namespace -ImageProcessorBackend::PortConfig::PortConfig() = default; - ImageProcessorBackend::PortConfig::PortConfig(const PortConfig&) = default; ImageProcessorBackend::PortConfig::PortConfig(
diff --git a/media/gpu/chromeos/image_processor_backend.h b/media/gpu/chromeos/image_processor_backend.h index f05ecc93..699c7b6 100644 --- a/media/gpu/chromeos/image_processor_backend.h +++ b/media/gpu/chromeos/image_processor_backend.h
@@ -50,7 +50,7 @@ // Encapsulates ImageProcessor input / output configurations. struct MEDIA_GPU_EXPORT PortConfig { - PortConfig(); + PortConfig() = delete; PortConfig(const PortConfig&); PortConfig( Fourcc fourcc,
diff --git a/media/gpu/chromeos/image_processor_factory.cc b/media/gpu/chromeos/image_processor_factory.cc index 0dd3d23..adfb95e 100644 --- a/media/gpu/chromeos/image_processor_factory.cc +++ b/media/gpu/chromeos/image_processor_factory.cc
@@ -245,34 +245,23 @@ } // namespace // static -std::unique_ptr<ImageProcessor> -ImageProcessorFactory::CreateWithInputCandidates( - const std::vector<PixelLayoutCandidate>& input_candidates, - const gfx::Rect& input_visible_rect, - const gfx::Size& output_size, - size_t num_buffers, - scoped_refptr<base::SequencedTaskRunner> client_task_runner, - PickFormatCB out_format_picker, - ImageProcessor::ErrorCB error_cb, +std::unique_ptr<ImageProcessor> ImageProcessorFactory::Create( const ImageProcessor::PortConfig& input_config, - const ImageProcessor::PortConfig& output_config) { - const bool is_input_config_defined = input_config.fourcc != Fourcc(); - const bool is_output_config_defined = output_config.fourcc != Fourcc(); - CHECK_EQ(is_input_config_defined, is_output_config_defined) - << "|input_config| and |output_config| must both be defined or not"; - DCHECK_NE(is_input_config_defined, !input_candidates.empty()) - << "|input_candidates| cannot be defined if |input_config| is defined"; + const ImageProcessor::PortConfig& output_config, + size_t num_buffers, + ImageProcessor::ErrorCB error_cb, + scoped_refptr<base::SequencedTaskRunner> client_task_runner) { + CHECK(input_config.fourcc != Fourcc()); + CHECK(output_config.fourcc != Fourcc()); - if (is_input_config_defined) { - std::vector<ImageProcessor::CreateBackendCB> create_funcs = { + std::vector<ImageProcessor::CreateBackendCB> create_funcs = { #if BUILDFLAG(USE_VAAPI) base::BindRepeating(&VaapiImageProcessorBackend::Create), #elif BUILDFLAG(USE_V4L2_CODEC) base::BindRepeating(&V4L2ImageProcessorBackend::Create, base::MakeRefCounted<V4L2Device>(), num_buffers), #endif - base::BindRepeating(&LibYUVImageProcessorBackend::Create) - }; + base::BindRepeating(&LibYUVImageProcessorBackend::Create)}; #if defined(ARCH_CPU_ARM_FAMILY) if (base::FeatureList::IsEnabled(media::kUseGLForScaling)) { @@ -291,8 +280,18 @@ } } return nullptr; - } +} +// static +std::unique_ptr<ImageProcessor> +ImageProcessorFactory::CreateWithInputCandidates( + const std::vector<PixelLayoutCandidate>& input_candidates, + const gfx::Rect& input_visible_rect, + const gfx::Size& output_size, + size_t num_buffers, + scoped_refptr<base::SequencedTaskRunner> client_task_runner, + PickFormatCB out_format_picker, + ImageProcessor::ErrorCB error_cb) { #if BUILDFLAG(USE_VAAPI) auto processor = CreateVaapiImageProcessorWithInputCandidates( input_candidates, input_visible_rect, output_size, client_task_runner, @@ -312,24 +311,22 @@ } #endif // defined(ARCH_CPU_ARM_FAMILY) - auto processor = CreateLibYUVImageProcessorWithInputCandidates( - input_candidates, input_visible_rect, output_size, client_task_runner, - out_format_picker, error_cb); - if (processor) - return processor; + auto processor = CreateLibYUVImageProcessorWithInputCandidates( + input_candidates, input_visible_rect, output_size, client_task_runner, + out_format_picker, error_cb); + if (processor) { + return processor; + } - processor = CreateV4L2ImageProcessorWithInputCandidates( - input_candidates, input_visible_rect, num_buffers, client_task_runner, - out_format_picker, error_cb); - if (processor) - return processor; + processor = CreateV4L2ImageProcessorWithInputCandidates( + input_candidates, input_visible_rect, num_buffers, client_task_runner, + out_format_picker, error_cb); + if (processor) { + return processor; + } #endif - // TODO(crbug.com/1004727): Implement LibYUVImageProcessorBackend. When doing - // so, we must keep in mind that it might not be desirable to fallback to - // libyuv if the hardware image processor fails (e.g., in the case of - // protected content). return nullptr; }
diff --git a/media/gpu/chromeos/image_processor_factory.h b/media/gpu/chromeos/image_processor_factory.h index e7590f2..92ea200 100644 --- a/media/gpu/chromeos/image_processor_factory.h +++ b/media/gpu/chromeos/image_processor_factory.h
@@ -28,14 +28,23 @@ const std::vector<Fourcc>& /* candidates */, std::optional<Fourcc> /* preferred_fourcc */)>; + // Factory method to create ImageProcessor. + // Given input and output PortConfig, it tries to find out the most suitable + // ImageProcessor to be used for the current platform. + // + // Returns: + // Most suitable ImageProcessor instance. nullptr if no ImageProcessor + // is available for given parameters on current platform. + static std::unique_ptr<ImageProcessor> Create( + const ImageProcessor::PortConfig& input_config, + const ImageProcessor::PortConfig& output_config, + size_t num_buffers, + ImageProcessor::ErrorCB error_cb, + scoped_refptr<base::SequencedTaskRunner> client_task_runner); + // Factory method to create an ImageProcessor. - // The caller will either pass in a list of supported inputs, - // |input_candidates| or a pair of PortConfig objects, - // |input_config| and |output_config|. If the caller passes - // in the pair of PortConfig objects, the function will try - // to find the most suitable ImageProcessor to be used for the current - // platform. Conversely, if the caller passes a list of supported input, - // they will also need to pass the |input_visible_rect| and the desired + // Unlike Create(), the caller passes a list of supported inputs, + // |input_candidates|. It also passes the |input_visible_rect| and the desired // |output_size|. |out_format_picker| allows us to negotiate the output // format: we'll call it with a list of supported formats and (possibly) a // preferred one and the callback picks one. With the rest of the parameters @@ -48,11 +57,7 @@ size_t num_buffers, scoped_refptr<base::SequencedTaskRunner> client_task_runner, PickFormatCB out_format_picker, - ImageProcessor::ErrorCB error_cb, - const ImageProcessor::PortConfig& input_config = - ImageProcessor::PortConfig(), - const ImageProcessor::PortConfig& output_config = - ImageProcessor::PortConfig()); + ImageProcessor::ErrorCB error_cb); #if BUILDFLAG(USE_V4L2_CODEC) static std::unique_ptr<ImageProcessor>
diff --git a/media/gpu/test/image_processor/image_processor_client.cc b/media/gpu/test/image_processor/image_processor_client.cc index 9968173..85c3a2b8 100644 --- a/media/gpu/test/image_processor/image_processor_client.cc +++ b/media/gpu/test/image_processor/image_processor_client.cc
@@ -129,24 +129,14 @@ &ImageProcessorClient::NotifyError, base::Unretained(this)); if (create_backend_cb) { - // Note: We aren't really missing anything by using the callback directly - // versus calling ImageProcessorFactory::CreateWithInputCandidates since the - // candidates list is empty in the else branch. image_processor_ = ImageProcessor::Create(*create_backend_cb, input_config, output_config, ImageProcessor::OutputMode::IMPORT, error_cb, image_processor_client_thread_.task_runner()); } else { - ImageProcessorFactory::PickFormatCB pick_format_cb = - base::BindRepeating([](const std::vector<Fourcc>& fourcc_config, - std::optional<Fourcc> fourcc) { - return std::make_optional<Fourcc>(fourcc_config[0]); - }); - - image_processor_ = ImageProcessorFactory::CreateWithInputCandidates( - {}, gfx::Rect(input_config.size), output_config.size, num_buffers, - image_processor_client_thread_.task_runner(), pick_format_cb, error_cb, - input_config, output_config); + image_processor_ = ImageProcessorFactory::Create( + input_config, output_config, num_buffers, error_cb, + image_processor_client_thread_.task_runner()); } done->Signal();
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc index 12fba345f..0c0ff31 100644 --- a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc +++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
@@ -460,17 +460,11 @@ LOG(ERROR) << "Failed to create ImageProcessor output config"; return false; } - ImageProcessorFactory::PickFormatCB pick_format_cb = - base::BindRepeating([](const std::vector<Fourcc>& fourcc_config, - std::optional<Fourcc> fourcc) { - return std::make_optional<Fourcc>(fourcc_config[0]); - }); - image_processor_ = ImageProcessorFactory::CreateWithInputCandidates( - {}, gfx::Rect(input_config->size), output_config->size, - kImageProcBufferCount, encoder_task_runner_, pick_format_cb, + image_processor_ = ImageProcessorFactory::Create( + *input_config, *output_config, kImageProcBufferCount, base::BindRepeating(&V4L2VideoEncodeAccelerator::ImageProcessorError, weak_this_), - *input_config, *output_config); + encoder_task_runner_); if (!image_processor_) { LOG(ERROR) << "Failed initializing image processor";
diff --git a/media/remoting/remoting_constants.h b/media/remoting/remoting_constants.h index 41664fa..91c5c90 100644 --- a/media/remoting/remoting_constants.h +++ b/media/remoting/remoting_constants.h
@@ -11,9 +11,7 @@ // The URL format is "media-remoting:<id>", e.g. "media-remoting:test". constexpr char kRemotingScheme[] = "media-remoting"; -// The minimum media element duration that is allowed for media remoting. Note -// that RendererController needs at least `kPixelRateCalInSec` to calculate the -// pixel rate before remoting can start. +// The minimum media element duration that is allowed for media remoting. constexpr double kMinRemotingMediaDurationInSec = 15; // The minimum media element duration that is allowed for switching from @@ -24,6 +22,8 @@ // The duration to wait and calculate the pixel rate of the media element and to // ensure that all preconditions are held stable before starting media remoting. +// Note that RendererController needs at least `kPixelRateCalInSec` to calculate +// the pixel rate before remoting can start. constexpr double kPixelRateCalInSec = 5; } // namespace media::remoting
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins index 51a21a7..4084ae5f 100644 --- a/net/http/transport_security_state_static.pins +++ b/net/http/transport_security_state_static.pins
@@ -43,9 +43,9 @@ # hash function for preloaded entries again (we have already done so once). # -# Last updated: 2024-02-07 12:54 UTC +# Last updated: 2024-02-08 12:56 UTC PinsListTimestamp -1707310493 +1707396974 TestSPKI sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/net/http/transport_security_state_static_pins.json b/net/http/transport_security_state_static_pins.json index 84d0e2d..090e932 100644 --- a/net/http/transport_security_state_static_pins.json +++ b/net/http/transport_security_state_static_pins.json
@@ -31,7 +31,7 @@ // the 'static_spki_hashes' and 'bad_static_spki_hashes' fields in 'pinsets' // refer to, and the timestamp at which the pins list was last updated. // -// Last updated: 2024-02-07 12:54 UTC +// Last updated: 2024-02-08 12:56 UTC // { "pinsets": [
diff --git a/net/quic/quic_session_pool_test.cc b/net/quic/quic_session_pool_test.cc index 6f985e9..0f7ce2a 100644 --- a/net/quic/quic_session_pool_test.cc +++ b/net/quic/quic_session_pool_test.cc
@@ -128,6 +128,8 @@ const size_t kMinRetryTimeForDefaultNetworkSecs = 1; const size_t kWaitTimeForNewNetworkSecs = 10; const quic::QuicConnectionId kNewCID = quic::test::TestConnectionId(12345678); +const url::SchemeHostPort kDefaultDestination{ + url::kHttpsScheme, kDefaultServerHostName, kDefaultServerPort}; // Run QuicSessionPoolTest instances with all value combinations of version // and enable_connection_racting. @@ -338,6 +340,60 @@ session->connection()->OnNewConnectionIdFrame(new_cid_frame); } + // Helper for building requests and invoking `QuicSessionRequest::Request`. + // This `Request` method has lots of arguments, most of which are always at + // their default values, so this helper supports specifying only the + // non-default arguments relevant to a specific test. + struct RequestBuilder { + RequestBuilder(QuicSessionPoolTestBase* test, QuicSessionPool* pool) + : quic_version(test->version_), + net_log(test->net_log_), + failed_on_default_network_callback( + test->failed_on_default_network_callback_), + callback(test->callback_.callback()), + request(pool) {} + explicit RequestBuilder(QuicSessionPoolTestBase* test) + : RequestBuilder(test, test->factory_.get()) {} + + RequestBuilder(const RequestBuilder&) = delete; + RequestBuilder& operator=(const RequestBuilder&) = delete; + + // Call the request's `Request` method with the parameters in the builder. + // The builder becomes invalid after this call. + int CallRequest() { + return request.Request( + std::move(destination), quic_version, proxy_chain, + std::move(proxy_annotation_tag), session_usage, privacy_mode, + priority, socket_tag, network_anonymization_key, secure_dns_policy, + require_dns_https_alpn, cert_verify_flags, url, net_log, + &net_error_details, std::move(failed_on_default_network_callback), + std::move(callback)); + } + + // Arguments to request.Request(). + url::SchemeHostPort destination = kDefaultDestination; + quic::ParsedQuicVersion quic_version; + ProxyChain proxy_chain = ProxyChain::Direct(); + absl::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag = + TRAFFIC_ANNOTATION_FOR_TESTS; + SessionUsage session_usage = SessionUsage::kDestination; + PrivacyMode privacy_mode = PRIVACY_MODE_DISABLED; + RequestPriority priority = DEFAULT_PRIORITY; + SocketTag socket_tag = SocketTag(); + NetworkAnonymizationKey network_anonymization_key; + SecureDnsPolicy secure_dns_policy = SecureDnsPolicy::kAllow; + bool require_dns_https_alpn = false; + int cert_verify_flags = 0; + GURL url = GURL(kDefaultUrl); + NetLogWithSource net_log; + NetErrorDetails net_error_details; + CompletionOnceCallback failed_on_default_network_callback; + CompletionOnceCallback callback; + + // The resulting request. + QuicSessionRequest request; + }; + std::unique_ptr<HttpStream> CreateStream(QuicSessionRequest* request) { std::unique_ptr<QuicChromiumClientSession::Handle> session = request->ReleaseSessionHandle(); @@ -411,20 +467,13 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); GURL url("https://" + destination.host() + "/"); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - destination, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + builder.destination = destination; + builder.url = url; EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); stream.reset(); @@ -554,24 +603,15 @@ socket_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); // Run QuicChromiumClientSession::WriteToNewSocket() // posted by QuicChromiumClientSession::MigrateToSocket(). base::RunLoop().RunUntilIdle(); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -584,9 +624,9 @@ EXPECT_EQ(OK, stream->InitializeStream(true, DEFAULT_PRIORITY, net_log_, CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); IPEndPoint actual_address; session->GetDefaultSocket()->GetPeerAddress(&actual_address); @@ -644,7 +684,7 @@ QuicSessionPoolPeer::SetTaskRunner(factory_.get(), runner_.get()); const AlternativeService alternative_service1( - kProtoQUIC, scheme_host_port_.host(), scheme_host_port_.port()); + kProtoQUIC, kDefaultServerHostName, kDefaultServerPort); AlternativeServiceInfoVector alternative_service_info_vector; base::Time expiration = base::Time::Now() + base::Days(1); alternative_service_info_vector.push_back( @@ -762,7 +802,7 @@ ++quic_server_info_map_it; EXPECT_EQ(quic_server_info_map_it->first.server_id, quic_server_id1); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); // Create a session and verify that the cached state is loaded. @@ -772,18 +812,11 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ( - ERR_IO_PENDING, - request.Request( - url::SchemeHostPort(url::kHttpsScheme, quic_server_id1.host(), - quic_server_id1.port()), - version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), network_anonymization_key1, SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + builder.destination = url::SchemeHostPort( + url::kHttpsScheme, quic_server_id1.host(), quic_server_id1.port()); + builder.network_anonymization_key = network_anonymization_key1; + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); EXPECT_FALSE(QuicSessionPoolPeer::CryptoConfigCacheIsEmpty( @@ -814,24 +847,17 @@ socket_data2.AddSocketDataToFactory(socket_factory_.get()); host_resolver_->rules()->ClearRules(); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.2", ""); - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ( - ERR_IO_PENDING, - request2.Request( - url::SchemeHostPort(url::kHttpsScheme, quic_server_id2.host(), - quic_server_id2.port()), - version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), network_anonymization_key2, SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, - vary_network_anonymization_key ? url_ - : GURL("https://mail.example.org/"), - net_log_, &net_error_details_, failed_on_default_network_callback_, - callback_.callback())); + RequestBuilder builder2(this); + builder2.destination = url::SchemeHostPort( + url::kHttpsScheme, quic_server_id2.host(), quic_server_id2.port()); + builder2.network_anonymization_key = network_anonymization_key2; + builder2.url = vary_network_anonymization_key + ? GURL(kDefaultUrl) + : GURL("https://mail.example.org/"); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); EXPECT_FALSE(QuicSessionPoolPeer::CryptoConfigCacheIsEmpty( @@ -970,15 +996,7 @@ std::unique_ptr<ScopedMockNetworkChangeNotifier> scoped_mock_network_change_notifier_; std::unique_ptr<QuicSessionPool> factory_; - url::SchemeHostPort scheme_host_port_{ - url::kHttpsScheme, kDefaultServerHostName, kDefaultServerPort}; - GURL url_{kDefaultUrl}; - GURL url2_{kServer2Url}; - GURL url3_{kServer3Url}; - GURL url4_{kServer4Url}; - GURL url5_{kServer5Url}; - PrivacyMode privacy_mode_ = PRIVACY_MODE_DISABLED; NetLogWithSource net_log_; TestCompletionCallback callback_; const CompletionRepeatingCallback failed_on_default_network_callback_; @@ -1021,52 +1039,28 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); EXPECT_EQ(DEFAULT_PRIORITY, host_resolver_->last_request_priority()); - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(OK, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder2(this); + EXPECT_EQ(OK, builder2.CallRequest()); // Will reset stream 3. - stream = CreateStream(&request2); + stream = CreateStream(&builder2.request); EXPECT_TRUE(stream.get()); // TODO(rtenneti): We should probably have a tests that HTTP and HTTPS result // in streams on different sessions. - QuicSessionRequest request3(factory_.get()); - EXPECT_EQ(OK, - request3.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - stream = CreateStream(&request3); // Will reset stream 5. - stream.reset(); // Will reset stream 7. + RequestBuilder builder3(this); + EXPECT_EQ(OK, builder3.CallRequest()); + stream = CreateStream(&builder3.request); // Will reset stream 5. + stream.reset(); // Will reset stream 7. EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -1082,52 +1076,26 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); EXPECT_EQ(DEFAULT_PRIORITY, host_resolver_->last_request_priority()); - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(OK, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder2(this); + EXPECT_EQ(OK, builder2.CallRequest()); // Will reset stream 3. - stream = CreateStream(&request2); - + stream = CreateStream(&builder2.request); EXPECT_TRUE(stream.get()); // TODO(rtenneti): We should probably have a tests that HTTP and HTTPS result // in streams on different sessions. - QuicSessionRequest request3(factory_.get()); - EXPECT_EQ(OK, - request3.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - stream = CreateStream(&request3); // Will reset stream 5. - stream.reset(); // Will reset stream 7. + RequestBuilder builder3(this); + EXPECT_EQ(OK, builder3.CallRequest()); + stream = CreateStream(&builder3.request); // Will reset stream 5. + stream.reset(); // Will reset stream 7. EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -1151,21 +1119,12 @@ crypto_client_stream_factory_.set_handshake_mode( MockCryptoClientStream::ZERO_RTT); host_resolver_->set_synchronous_mode(true); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(OK, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - - std::unique_ptr<HttpStream> stream = CreateStream(&request); + RequestBuilder builder(this); + EXPECT_EQ(OK, builder.CallRequest()); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -1186,23 +1145,15 @@ crypto_client_stream_factory_.set_handshake_mode( MockCryptoClientStream::ZERO_RTT); host_resolver_->set_synchronous_mode(true); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); - QuicSessionRequest request(factory_.get()); - int rv = request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, privacy_mode_, - DEFAULT_PRIORITY, SocketTag(), NetworkAnonymizationKey(), - SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback()); - EXPECT_EQ(ERR_IO_PENDING, rv); - rv = callback_.WaitForResult(); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); + int rv = callback_.WaitForResult(); EXPECT_EQ(OK, rv); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -1225,28 +1176,20 @@ crypto_client_stream_factory_.set_handshake_mode( MockCryptoClientStream::ASYNC_ZERO_RTT); host_resolver_->set_synchronous_mode(true); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_EQ(nullptr, CreateStream(&request)); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_EQ(nullptr, CreateStream(&builder.request)); base::RunLoop().RunUntilIdle(); crypto_client_stream_factory_.last_stream()->NotifySessionZeroRttComplete(); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -1262,22 +1205,13 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(session->require_confirmation()); EXPECT_EQ(100000u, session->connection()->GetStats().srtt_us); ASSERT_FALSE(session->config()->HasInitialRoundTripTimeUsToSend()); @@ -1293,18 +1227,10 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - auto request = std::make_unique<QuicSessionRequest>(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request->Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - request.reset(); - EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); + auto builder = std::make_unique<RequestBuilder>(this); + EXPECT_EQ(ERR_IO_PENDING, builder->CallRequest()); + builder.reset(); + EXPECT_TRUE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); // Tearing down a QuicSessionPool with a pending Job should not cause any // crash. crbug.com/768343. factory_.reset(); @@ -1316,7 +1242,7 @@ crypto_client_stream_factory_.set_handshake_mode( MockCryptoClientStream::ZERO_RTT); host_resolver_->set_synchronous_mode(true); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); Initialize(); factory_->set_is_quic_known_to_work_on_current_network(false); @@ -1329,17 +1255,8 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_FALSE(http_server_properties_->HasLastLocalAddressWhenQuicWorked()); crypto_client_stream_factory_.last_stream() @@ -1348,10 +1265,10 @@ EXPECT_TRUE(http_server_properties_->HasLastLocalAddressWhenQuicWorked()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(session->require_confirmation()); } @@ -1359,7 +1276,7 @@ crypto_client_stream_factory_.set_handshake_mode( MockCryptoClientStream::ZERO_RTT); host_resolver_->set_synchronous_mode(true); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); Initialize(); factory_->set_is_quic_known_to_work_on_current_network(false); @@ -1372,17 +1289,8 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_FALSE(http_server_properties_->HasLastLocalAddressWhenQuicWorked()); base::RunLoop().RunUntilIdle(); @@ -1392,10 +1300,10 @@ EXPECT_TRUE(http_server_properties_->HasLastLocalAddressWhenQuicWorked()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(session->require_confirmation()); } @@ -1403,7 +1311,7 @@ crypto_client_stream_factory_.set_handshake_mode( MockCryptoClientStream::ZERO_RTT); host_resolver_->set_synchronous_mode(true); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); Initialize(); factory_->set_is_quic_known_to_work_on_current_network(false); @@ -1419,24 +1327,15 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); EXPECT_FALSE(http_server_properties_->HasLastLocalAddressWhenQuicWorked()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_FALSE(session->require_confirmation()); crypto_client_stream_factory_.last_stream() @@ -1448,7 +1347,7 @@ ServerNetworkStats stats; stats.srtt = base::Milliseconds(10); http_server_properties_->SetServerNetworkStats( - url::SchemeHostPort(url_), NetworkAnonymizationKey(), stats); + url::SchemeHostPort(GURL(kDefaultUrl)), NetworkAnonymizationKey(), stats); quic_params_->estimate_initial_rtt = true; Initialize(); @@ -1460,22 +1359,13 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_EQ(10000u, session->connection()->GetStats().srtt_us); ASSERT_TRUE(session->config()->HasInitialRoundTripTimeUsToSend()); EXPECT_EQ(10000u, session->config()->GetInitialRoundTripTimeUsToSend()); @@ -1507,7 +1397,7 @@ ServerNetworkStats stats; stats.srtt = base::Milliseconds(10); http_server_properties_->SetServerNetworkStats( - url::SchemeHostPort(url_), kNetworkAnonymizationKey1, stats); + url::SchemeHostPort(GURL(kDefaultUrl)), kNetworkAnonymizationKey1, stats); quic_params_->estimate_initial_rtt = true; Initialize(); @@ -1531,23 +1421,15 @@ packet_maker.MakeInitialSettingsPacket(1)); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - network_anonymization_key, SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + builder.network_anonymization_key = network_anonymization_key; + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); QuicChromiumClientSession* session = - GetActiveSession(scheme_host_port_, network_anonymization_key); + GetActiveSession(kDefaultDestination, network_anonymization_key); if (network_anonymization_key == kNetworkAnonymizationKey1) { EXPECT_EQ(10000, session->connection()->GetStats().srtt_us); ASSERT_TRUE(session->config()->HasInitialRoundTripTimeUsToSend()); @@ -1575,22 +1457,13 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_EQ(1000000u, session->connection()->GetStats().srtt_us); ASSERT_TRUE(session->config()->HasInitialRoundTripTimeUsToSend()); EXPECT_EQ(1200000u, session->config()->GetInitialRoundTripTimeUsToSend()); @@ -1611,22 +1484,13 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_EQ(400000u, session->connection()->GetStats().srtt_us); ASSERT_TRUE(session->config()->HasInitialRoundTripTimeUsToSend()); EXPECT_EQ(400000u, session->config()->GetInitialRoundTripTimeUsToSend()); @@ -1642,26 +1506,17 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); session->OnHttp3GoAway(0); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -1716,28 +1571,20 @@ packet_maker.MakeInitialSettingsPacket(1)); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - kNetworkAnonymizationKeys[i], SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + builder.network_anonymization_key = kNetworkAnonymizationKeys[i]; + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); QuicChromiumClientSession* session = - GetActiveSession(scheme_host_port_, kNetworkAnonymizationKeys[i]); + GetActiveSession(kDefaultDestination, kNetworkAnonymizationKeys[i]); session->OnHttp3GoAway(0); EXPECT_FALSE( - HasActiveSession(scheme_host_port_, kNetworkAnonymizationKeys[i])); + HasActiveSession(kDefaultDestination, kNetworkAnonymizationKeys[i])); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -1747,10 +1594,12 @@ // all others should remain empty. if (j <= i) { EXPECT_TRUE(http_server_properties_->GetServerNetworkStats( - url::SchemeHostPort(url_), kNetworkAnonymizationKeys[j])); + url::SchemeHostPort(GURL(kDefaultUrl)), + kNetworkAnonymizationKeys[j])); } else { EXPECT_FALSE(http_server_properties_->GetServerNetworkStats( - url::SchemeHostPort(url_), kNetworkAnonymizationKeys[j])); + url::SchemeHostPort(GURL(kDefaultUrl)), + kNetworkAnonymizationKeys[j])); } } } @@ -1772,31 +1621,25 @@ socket_data.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - kNetworkAnonymizationKeys[i], SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + builder.network_anonymization_key = kNetworkAnonymizationKeys[i]; + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsError(ERR_QUIC_HANDSHAKE_FAILED)); EXPECT_FALSE( - HasActiveSession(scheme_host_port_, kNetworkAnonymizationKeys[i])); + HasActiveSession(kDefaultDestination, kNetworkAnonymizationKeys[i])); for (size_t j = 0; j < std::size(kNetworkAnonymizationKeys); ++j) { // Stats up to kNetworkAnonymizationKeys[j] should have been deleted, all // others should still be populated. if (j <= i) { EXPECT_FALSE(http_server_properties_->GetServerNetworkStats( - url::SchemeHostPort(url_), kNetworkAnonymizationKeys[j])); + url::SchemeHostPort(GURL(kDefaultUrl)), + kNetworkAnonymizationKeys[j])); } else { EXPECT_TRUE(http_server_properties_->GetServerNetworkStats( - url::SchemeHostPort(url_), kNetworkAnonymizationKeys[j])); + url::SchemeHostPort(GURL(kDefaultUrl)), + kNetworkAnonymizationKeys[j])); } } } @@ -1835,7 +1678,7 @@ url::SchemeHostPort server5(url::kHttpsScheme, kServer5HostName, kDefaultServerPort); host_resolver_->set_synchronous_mode(true); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); // `server2` resolves to the same IP address via A/AAAA records, i.e. without @@ -1867,70 +1710,44 @@ host_resolver_->rules()->AddIPLiteralRule(server5.host(), "192.168.0.1", ""); // Establish a QUIC session to pool against. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // `server2` can pool with the existing session. Although the endpoint does // not specify ALPN, we connect here with preexisting knowledge of the version // (from Alt-Svc), so an A/AAAA match is sufficient. TestCompletionCallback callback; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ( - OK, - request2.Request( - server2, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback.callback())); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + RequestBuilder builder2(this); + builder2.destination = server2; + builder2.url = GURL(kServer2Url); + EXPECT_EQ(OK, builder2.CallRequest()); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); - EXPECT_EQ(GetActiveSession(scheme_host_port_), GetActiveSession(server2)); + EXPECT_EQ(GetActiveSession(kDefaultDestination), GetActiveSession(server2)); // `server3` can pool with the existing session. The endpoint's ALPN protocol // matches. - QuicSessionRequest request3(factory_.get()); - EXPECT_EQ( - OK, - request3.Request( - server3, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url3_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback.callback())); - std::unique_ptr<HttpStream> stream3 = CreateStream(&request3); + RequestBuilder builder3(this); + builder3.destination = server3; + builder3.url = GURL(kServer3Url); + EXPECT_EQ(OK, builder3.CallRequest()); + std::unique_ptr<HttpStream> stream3 = CreateStream(&builder3.request); EXPECT_TRUE(stream3.get()); - EXPECT_EQ(GetActiveSession(scheme_host_port_), GetActiveSession(server3)); + EXPECT_EQ(GetActiveSession(kDefaultDestination), GetActiveSession(server3)); // `server4` cannot pool with the existing session. No endpoint matches both // IP and ALPN protocol. - QuicSessionRequest request4(factory_.get()); - EXPECT_EQ( - ERR_IO_PENDING, - request4.Request( - server4, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url4_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder4(this); + builder4.destination = server4; + builder4.url = GURL(kServer4Url); + EXPECT_EQ(ERR_IO_PENDING, builder4.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream4 = CreateStream(&request4); + std::unique_ptr<HttpStream> stream4 = CreateStream(&builder4.request); EXPECT_TRUE(stream4.get()); - EXPECT_NE(GetActiveSession(scheme_host_port_), GetActiveSession(server4)); + EXPECT_NE(GetActiveSession(kDefaultDestination), GetActiveSession(server4)); // `server5` cannot pool with the existing session. Although the IP address // matches, if we connect without prior knowledge of QUIC support, endpoints @@ -1938,16 +1755,12 @@ // // Without pooling, the DNS response is insufficient to start a QUIC // connection, so the connection will fail. - QuicSessionRequest request5(factory_.get()); - EXPECT_EQ(ERR_DNS_NO_MATCHING_SUPPORTED_ALPN, - request5.Request( - server5, quic::ParsedQuicVersion::Unsupported(), - ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/true, - /*cert_verify_flags=*/0, url5_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder5(this); + builder5.destination = server5; + builder5.quic_version = quic::ParsedQuicVersion::Unsupported(); + builder5.require_dns_https_alpn = true; + builder5.url = GURL(kServer5Url); + EXPECT_EQ(ERR_DNS_NO_MATCHING_SUPPORTED_ALPN, builder5.CallRequest()); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -1958,7 +1771,7 @@ // Regression test for https://crbug.com/639916. TEST_P(QuicSessionPoolTest, PoolingWithServerMigration) { // Set up session to migrate. - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); IPEndPoint alt_address = IPEndPoint(IPAddress(1, 2, 3, 4), 443); quic::QuicConfig config; @@ -1970,10 +1783,10 @@ VerifyServerMigration(config, alt_address); // Close server-migrated session. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); session->CloseSessionOnError(0u, quic::QUIC_NO_ERROR, quic::ConnectionCloseBehavior::SILENT_CLOSE); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); client_maker_.Reset(); // Set up server IP, socket, proof, and config for new session. @@ -1994,18 +1807,13 @@ // Create new request to cause new session creation. TestCompletionCallback callback; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ( - ERR_IO_PENDING, - request2.Request( - server2, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback.callback())); + RequestBuilder builder2(this); + builder2.destination = server2; + builder2.url = GURL(kServer2Url); + builder2.callback = callback.callback(); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_EQ(OK, callback.WaitForResult()); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); EXPECT_TRUE(socket_data1.AllReadDataConsumed()); @@ -2014,7 +1822,7 @@ EXPECT_TRUE(HasActiveSession(server2)); // No zombie entry in session map. - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); } TEST_P(QuicSessionPoolTest, NoPoolingAfterGoAway) { @@ -2036,56 +1844,38 @@ url::SchemeHostPort server2(url::kHttpsScheme, kServer2HostName, kDefaultServerPort); host_resolver_->set_synchronous_mode(true); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); host_resolver_->rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", ""); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); TestCompletionCallback callback; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ( - OK, - request2.Request( - server2, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback.callback())); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + RequestBuilder builder2(this); + builder2.destination = server2; + builder2.url = GURL(kServer2Url); + builder2.callback = callback.callback(); + EXPECT_EQ(OK, builder2.CallRequest()); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); - factory_->OnSessionGoingAway(GetActiveSession(scheme_host_port_)); + factory_->OnSessionGoingAway(GetActiveSession(kDefaultDestination)); base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); EXPECT_FALSE(HasActiveSession(server2)); TestCompletionCallback callback3; - QuicSessionRequest request3(factory_.get()); - EXPECT_EQ( - ERR_IO_PENDING, - request3.Request( - server2, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback3.callback())); + RequestBuilder builder3(this); + builder3.destination = server2; + builder3.url = GURL(kServer2Url); + builder3.callback = callback3.callback(); + EXPECT_EQ(ERR_IO_PENDING, builder3.CallRequest()); EXPECT_THAT(callback3.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream3 = CreateStream(&request3); + std::unique_ptr<HttpStream> stream3 = CreateStream(&builder3.request); EXPECT_TRUE(stream3.get()); EXPECT_TRUE(HasActiveSession(server2)); @@ -2114,31 +1904,18 @@ host_resolver_->rules()->AddIPLiteralRule(server1.host(), "192.168.0.1", ""); host_resolver_->rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", ""); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ( - ERR_IO_PENDING, - request.Request( - server1, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + builder.destination = server1; + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ( - OK, - request2.Request( - server2, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + RequestBuilder builder2(this); + builder2.destination = server2; + builder2.url = GURL(kServer2Url); + EXPECT_EQ(OK, builder2.CallRequest()); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); EXPECT_EQ(GetActiveSession(server1), GetActiveSession(server2)); @@ -2170,31 +1947,18 @@ host_resolver_->rules()->AddIPLiteralRule(server1.host(), "192.168.0.1", ""); host_resolver_->rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", ""); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ( - ERR_IO_PENDING, - request.Request( - server1, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + builder.destination = server1; + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ( - OK, - request2.Request( - server2, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + RequestBuilder builder2(this); + builder2.destination = server2; + builder2.url = GURL(kServer2Url); + EXPECT_EQ(OK, builder2.CallRequest()); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); EXPECT_EQ(GetActiveSession(server1), GetActiveSession(server2)); @@ -2242,33 +2006,19 @@ host_resolver_->rules()->AddIPLiteralRule(server1.host(), "192.168.0.1", ""); host_resolver_->rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", ""); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ( - ERR_IO_PENDING, - request.Request( - server1, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + builder.destination = server1; + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); - TestCompletionCallback callback; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ( - ERR_IO_PENDING, - request2.Request( - server2, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder2(this); + builder2.destination = server2; + builder2.url = GURL(kServer2Url); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); EXPECT_NE(GetActiveSession(server1), GetActiveSession(server2)); @@ -2295,46 +2045,29 @@ socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data2.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Mark the session as going away. Ensure that while it is still alive // that it is no longer active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); factory_->OnSessionGoingAway(session); EXPECT_EQ(true, QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); // Create a new request for the same destination and verify that a // new session is created. - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder2(this); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); - EXPECT_NE(session, GetActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); + EXPECT_NE(session, GetActiveSession(kDefaultDestination)); EXPECT_EQ(true, QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); stream2.reset(); @@ -2384,22 +2117,15 @@ // The MockCryptoClientStream sets max_open_streams to be // quic::kDefaultMaxStreamsPerConnection / 2. for (size_t i = 0; i < quic::kDefaultMaxStreamsPerConnection / 2; i++) { - QuicSessionRequest request(factory_.get()); - int rv = request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, privacy_mode_, - DEFAULT_PRIORITY, SocketTag(), NetworkAnonymizationKey(), - SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback()); + RequestBuilder builder(this); + int rv = builder.CallRequest(); if (i == 0) { EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); EXPECT_THAT(callback_.WaitForResult(), IsOk()); } else { EXPECT_THAT(rv, IsOk()); } - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream); stream->RegisterRequest(&request_info); EXPECT_EQ(OK, stream->InitializeStream(false, DEFAULT_PRIORITY, net_log_, @@ -2407,17 +2133,10 @@ streams.push_back(std::move(stream)); } - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(OK, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, CompletionOnceCallback())); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + RequestBuilder builder(this); + builder.callback = CompletionOnceCallback(); + EXPECT_EQ(OK, builder.CallRequest()); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream); stream->RegisterRequest(&request_info); EXPECT_EQ(ERR_IO_PENDING, @@ -2437,7 +2156,7 @@ // Force close of the connection to suppress the generation of RST // packets when streams are torn down, which wouldn't be relevant to // this test anyway. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); session->connection()->CloseConnection( quic::QUIC_PUBLIC_RESET, "test", quic::ConnectionCloseBehavior::SILENT_CLOSE); @@ -2450,17 +2169,8 @@ host_resolver_->rules()->AddSimulatedFailure(kDefaultServerHostName); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED)); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -2477,17 +2187,8 @@ socket_data.AddConnect(SYNCHRONOUS, ERR_ADDRESS_IN_USE); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsError(ERR_ADDRESS_IN_USE)); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -2501,17 +2202,8 @@ socket_data.AddConnect(SYNCHRONOUS, ERR_ADDRESS_IN_USE); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsError(ERR_ADDRESS_IN_USE)); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -2528,31 +2220,15 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); { - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); } base::RunLoop().RunUntilIdle(); - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(OK, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - std::unique_ptr<HttpStream> stream = CreateStream(&request2); + RequestBuilder builder2(this); + EXPECT_EQ(OK, builder2.CallRequest()); + std::unique_ptr<HttpStream> stream = CreateStream(&builder2.request); EXPECT_TRUE(stream.get()); stream.reset(); @@ -2568,31 +2244,15 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); { - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); } base::RunLoop().RunUntilIdle(); - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(OK, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - std::unique_ptr<HttpStream> stream = CreateStream(&request2); + RequestBuilder builder2(this); + EXPECT_EQ(OK, builder2.CallRequest()); + std::unique_ptr<HttpStream> stream = CreateStream(&builder2.request); EXPECT_TRUE(stream.get()); stream.reset(); @@ -2623,19 +2283,10 @@ socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data2.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); HttpRequestInfo request_info; request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); @@ -2652,19 +2303,10 @@ // Now attempting to request a stream to the same origin should create // a new session. - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder2(this); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - stream = CreateStream(&request2); + stream = CreateStream(&builder2.request); stream.reset(); // Will reset stream 3. EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -2693,19 +2335,11 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request, should fail after the write of the CHLO fails. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(ERR_QUIC_HANDSHAKE_FAILED, callback_.WaitForResult()); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_FALSE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); // Verify new requests can be sent normally without hanging. crypto_client_stream_factory_.set_handshake_mode( @@ -2718,18 +2352,10 @@ socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data2.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); + RequestBuilder builder2(this); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_TRUE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); // Run the message loop to complete host resolution. base::RunLoop().RunUntilIdle(); @@ -2737,11 +2363,11 @@ crypto_client_stream_factory_.last_stream() ->NotifySessionOneRttKeyAvailable(); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); - EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); + EXPECT_FALSE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); // Create QuicHttpStream. - std::unique_ptr<HttpStream> stream = CreateStream(&request2); + std::unique_ptr<HttpStream> stream = CreateStream(&builder2.request); EXPECT_TRUE(stream.get()); stream.reset(); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -2764,19 +2390,11 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request, should fail after the write of the CHLO fails. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(ERR_QUIC_HANDSHAKE_FAILED, callback_.WaitForResult()); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_FALSE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); // Verify new requests can be sent normally without hanging. crypto_client_stream_factory_.set_handshake_mode( @@ -2789,18 +2407,10 @@ socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data2.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); + RequestBuilder builder2(this); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_TRUE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); // Run the message loop to complete host resolution. base::RunLoop().RunUntilIdle(); @@ -2808,11 +2418,11 @@ crypto_client_stream_factory_.last_stream() ->NotifySessionOneRttKeyAvailable(); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); - EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); + EXPECT_FALSE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); // Create QuicHttpStream. - std::unique_ptr<HttpStream> stream = CreateStream(&request2); + std::unique_ptr<HttpStream> stream = CreateStream(&builder2.request); EXPECT_TRUE(stream.get()); stream.reset(); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -2830,7 +2440,7 @@ crypto_client_stream_factory_.set_handshake_mode( MockCryptoClientStream::COLD_START_WITH_CHLO_SENT); host_resolver_->set_synchronous_mode(true); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); MockQuicData socket_data(version_); @@ -2840,19 +2450,11 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request, should fail immediately. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_QUIC_HANDSHAKE_FAILED, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_QUIC_HANDSHAKE_FAILED, builder.CallRequest()); // Check no active session, or active jobs left for this server. - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_FALSE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); // Verify new requests can be sent normally without hanging. crypto_client_stream_factory_.set_handshake_mode( @@ -2865,29 +2467,21 @@ socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data2.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); + RequestBuilder builder2(this); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_TRUE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); base::RunLoop().RunUntilIdle(); // Complete handshake. crypto_client_stream_factory_.last_stream() ->NotifySessionOneRttKeyAvailable(); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); - EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); + EXPECT_FALSE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); // Create QuicHttpStream. - std::unique_ptr<HttpStream> stream = CreateStream(&request2); + std::unique_ptr<HttpStream> stream = CreateStream(&builder2.request); EXPECT_TRUE(stream.get()); stream.reset(); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -2903,7 +2497,7 @@ crypto_client_stream_factory_.set_handshake_mode( MockCryptoClientStream::COLD_START_WITH_CHLO_SENT); host_resolver_->set_synchronous_mode(true); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); MockQuicData socket_data(version_); @@ -2913,20 +2507,12 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request, should fail immediately. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(ERR_QUIC_HANDSHAKE_FAILED, callback_.WaitForResult()); // Check no active session, or active jobs left for this server. - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_FALSE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); // Verify new requests can be sent normally without hanging. crypto_client_stream_factory_.set_handshake_mode( @@ -2939,29 +2525,21 @@ socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data2.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); + RequestBuilder builder2(this); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_TRUE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); base::RunLoop().RunUntilIdle(); // Complete handshake. crypto_client_stream_factory_.last_stream() ->NotifySessionOneRttKeyAvailable(); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); - EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); + EXPECT_FALSE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); // Create QuicHttpStream. - std::unique_ptr<HttpStream> stream = CreateStream(&request2); + std::unique_ptr<HttpStream> stream = CreateStream(&builder2.request); EXPECT_TRUE(stream.get()); stream.reset(); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -3000,16 +2578,8 @@ packet_num, quic::QUIC_IP_ADDRESS_CHANGED, "net error")); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(&factory); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this, &factory); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); // QuicSessionPool should be notified of IP address change after // FinishConnectAndConfigureSocket runs FinishCreateSession. @@ -3020,8 +2590,8 @@ // Session should have been created before the factory is notified of IP // address change. EXPECT_THAT(callback_.WaitForResult(), IsOk()); - quic::QuicServerId server_id(scheme_host_port_.host(), - scheme_host_port_.port(), false); + quic::QuicServerId server_id(kDefaultServerHostName, kDefaultServerPort, + false); EXPECT_TRUE(QuicSessionPoolPeer::HasActiveSession(&factory, server_id, NetworkAnonymizationKey())); QuicChromiumClientSession* session = QuicSessionPoolPeer::GetActiveSession( @@ -3061,19 +2631,10 @@ socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data2.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); HttpRequestInfo request_info; request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); @@ -3082,8 +2643,8 @@ CompletionOnceCallback())); // Check an active session exists for the destination. - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); EXPECT_TRUE(http_server_properties_->HasLastLocalAddressWhenQuicWorked()); @@ -3095,28 +2656,19 @@ EXPECT_FALSE(factory_->is_quic_known_to_work_on_current_network()); EXPECT_FALSE(http_server_properties_->HasLastLocalAddressWhenQuicWorked()); // Check no active session exists for the destination. - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); // Now attempting to request a stream to the same origin should create // a new session. - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder2(this); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - stream = CreateStream(&request2); + stream = CreateStream(&builder2.request); // Check a new active session exists for the destination and the old session // is no longer live. - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); - QuicChromiumClientSession* session2 = GetActiveSession(scheme_host_port_); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); + QuicChromiumClientSession* session2 = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session2)); stream.reset(); // Will reset stream 3. @@ -3161,24 +2713,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -3186,9 +2730,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Send GET request on stream. HttpResponseInfo response; @@ -3200,7 +2744,7 @@ NotifyIPAddressChanged(); // The connection should still be alive, but marked as going away. - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); EXPECT_EQ(1u, session->GetNumActiveStreams()); @@ -3211,24 +2755,16 @@ EXPECT_EQ(0u, session->GetNumActiveStreams()); // Second request should be sent on a new connection. - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder2(this); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); // Check an active session exists for the destination. - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - QuicChromiumClientSession* session2 = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session2 = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session2)); stream.reset(); @@ -3260,19 +2796,10 @@ ConstructClientRstPacket(packet_num, quic::QUIC_STREAM_CANCELLED)); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); HttpRequestInfo request_info; request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); @@ -3288,17 +2815,9 @@ EXPECT_TRUE(http_server_properties_->HasLastLocalAddressWhenQuicWorked()); // Attempting a new request to the same origin uses the same connection. - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(OK, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - stream = CreateStream(&request2); + RequestBuilder builder2(this); + EXPECT_EQ(OK, builder2.CallRequest()); + stream = CreateStream(&builder2.request); stream.reset(); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -3376,24 +2895,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -3401,9 +2912,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Send GET request on stream. @@ -3430,7 +2941,7 @@ // The connection should still be alive, and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); @@ -3440,7 +2951,7 @@ quic_data2.Resume(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // There should be a task that will complete the migration to the new network. @@ -3452,7 +2963,7 @@ // Verify that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); stream.reset(); EXPECT_TRUE(quic_data1.AllReadDataConsumed()); @@ -3536,24 +3047,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -3561,9 +3064,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Send GET request on stream. @@ -3600,7 +3103,7 @@ // The connection should still be alive, and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); @@ -3616,7 +3119,7 @@ // Verify that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); stream.reset(); EXPECT_TRUE(quic_data1.AllReadDataConsumed()); @@ -3647,18 +3150,10 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -3670,9 +3165,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Trigger connection migration. Since there are no networks // to migrate to, this should cause the session to wait for a new network. @@ -3681,7 +3176,7 @@ // The migration will not fail until the migration alarm timeout. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); EXPECT_EQ(true, session->connection()->writer()->IsWriteBlocked()); @@ -3692,7 +3187,7 @@ // The connection should now be closed. A request for response // headers should fail. EXPECT_FALSE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(ERR_INTERNET_DISCONNECTED, callback_.WaitForResult()); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -3777,18 +3272,10 @@ quic_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created, but marked as non-migratable. @@ -3801,9 +3288,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Trigger connection migration. Session will start to probe the alternative @@ -3813,14 +3300,14 @@ ->NotifyNetworkMadeDefault(kNewNetworkForTests); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Resume data to read a connectivity probing response, which will cause // non-migtable streams to be closed. quic_data1.Resume(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_EQ(migrate_idle_sessions, HasActiveSession(scheme_host_port_)); + EXPECT_EQ(migrate_idle_sessions, HasActiveSession(kDefaultDestination)); EXPECT_EQ(0u, session->GetNumActiveStreams()); base::RunLoop().RunUntilIdle(); @@ -3854,18 +3341,10 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -3877,9 +3356,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Set session config to have connection migration disabled. quic::test::QuicConfigPeer::SetReceivedDisableConnectionMigration( @@ -3893,7 +3372,7 @@ base::RunLoop().RunUntilIdle(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); stream.reset(); @@ -3975,18 +3454,10 @@ } // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created, but marked as non-migratable. @@ -3999,9 +3470,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Trigger connection migration. Since there is a non-migratable stream, @@ -4014,7 +3485,7 @@ EXPECT_EQ(migrate_idle_sessions, QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_EQ(migrate_idle_sessions, HasActiveSession(scheme_host_port_)); + EXPECT_EQ(migrate_idle_sessions, HasActiveSession(kDefaultDestination)); if (migrate_idle_sessions) { EXPECT_EQ(0u, session->GetNumActiveStreams()); @@ -4041,18 +3512,10 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -4064,9 +3527,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Set session config to have connection migration disabled. quic::test::QuicConfigPeer::SetReceivedDisableConnectionMigration( @@ -4078,7 +3541,7 @@ ->NotifyNetworkDisconnected(kDefaultNetworkForTests); EXPECT_FALSE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -4140,31 +3603,23 @@ } // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_FALSE(session->HasActiveRequestStreams()); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Trigger connection migration. scoped_mock_network_change_notifier_->mock_network_change_notifier() ->NotifyNetworkMadeDefault(kNewNetworkForTests); - EXPECT_EQ(migrate_idle_sessions, HasActiveSession(scheme_host_port_)); + EXPECT_EQ(migrate_idle_sessions, HasActiveSession(kDefaultDestination)); if (migrate_idle_sessions) { quic_data1.Resume(); @@ -4222,22 +3677,14 @@ } // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Ensure that session is active. - auto* session = GetActiveSession(scheme_host_port_); + auto* session = GetActiveSession(kDefaultDestination); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Trigger connection migration. Since there are no active streams, @@ -4245,7 +3692,7 @@ scoped_mock_network_change_notifier_->mock_network_change_notifier() ->NotifyNetworkDisconnected(kDefaultNetworkForTests); - EXPECT_EQ(migrate_idle_sessions, HasActiveSession(scheme_host_port_)); + EXPECT_EQ(migrate_idle_sessions, HasActiveSession(kDefaultDestination)); EXPECT_TRUE(default_socket_data.AllReadDataConsumed()); EXPECT_TRUE(default_socket_data.AllWriteDataConsumed()); @@ -4297,24 +3744,16 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -4322,9 +3761,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); quic::QuicConnectionId cid_on_new_path = quic::test::TestConnectionId(12345678); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -4372,13 +3811,13 @@ base::RunLoop().RunUntilIdle(); // The connection should still be alive, not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); // Ensure that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Run the message loop so that data queued in the new socket is read by the @@ -4391,7 +3830,7 @@ // Check that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // There should be posted tasks not executed, which is to migrate back to // default network. @@ -4434,24 +3873,16 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -4459,9 +3890,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); quic::QuicConnectionId cid_on_new_path = quic::test::TestConnectionId(12345678); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -4479,7 +3910,7 @@ // The connection should still be alive, not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); @@ -4519,7 +3950,7 @@ // Ensure that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Run the message loop so that data queued in the new socket is read by the @@ -4532,7 +3963,7 @@ // Check that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // There should posted tasks not executed, which is to migrate back to default // network. @@ -4621,24 +4052,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -4646,9 +4069,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Send GET request on stream. @@ -4666,7 +4089,7 @@ // The connection should still be alive, and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); @@ -4675,7 +4098,7 @@ quic_data2.Resume(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // There should be a task that will complete the migration to the new network. @@ -4698,7 +4121,7 @@ // Verify that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); stream.reset(); EXPECT_TRUE(quic_data1.AllReadDataConsumed()); @@ -4787,24 +4210,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -4812,9 +4227,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Send GET request on stream. @@ -4836,7 +4251,7 @@ // The connection should still be alive, and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); @@ -4845,7 +4260,7 @@ quic_data2.Resume(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // There should be a task that will complete the migration to the new network. @@ -4870,7 +4285,7 @@ // Verify that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); stream.reset(); EXPECT_TRUE(quic_data1.AllReadDataConsumed()); @@ -4930,24 +4345,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -4955,9 +4362,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Send GET request on stream. @@ -4977,7 +4384,7 @@ // The connection should still be alive, and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); @@ -4999,7 +4406,7 @@ // Verify that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); stream.reset(); EXPECT_TRUE(quic_data1.AllReadDataConsumed()); @@ -5067,24 +4474,16 @@ quic_data3.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -5092,9 +4491,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_path2, session); base::RunLoop().RunUntilIdle(); // Send GET request on stream. @@ -5114,7 +4513,7 @@ // The connection should still be alive, and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); @@ -5146,7 +4545,7 @@ base::RunLoop().RunUntilIdle(); // Verify that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); base::RunLoop().RunUntilIdle(); stream.reset(); EXPECT_TRUE(quic_data1.AllReadDataConsumed()); @@ -5212,24 +4611,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -5237,9 +4628,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Manually initialize the connection's self address. In real life, the // initialization will be done during crypto handshake. IPEndPoint ip; @@ -5287,7 +4678,7 @@ base::RunLoop().RunUntilIdle(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Receives an ack from the server, this will be considered forward progress. @@ -5347,27 +4738,19 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_TRUE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); base::RunLoop().RunUntilIdle(); crypto_client_stream_factory_.last_stream() ->NotifySessionOneRttKeyAvailable(); base::RunLoop().RunUntilIdle(); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - ASSERT_TRUE(HasActiveSession(scheme_host_port_)); - EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + ASSERT_TRUE(HasActiveSession(kDefaultDestination)); + EXPECT_FALSE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_FALSE( session->connection()->GetStats().server_preferred_address_validated); EXPECT_FALSE(session->connection() @@ -5436,27 +4819,19 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_TRUE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); base::RunLoop().RunUntilIdle(); crypto_client_stream_factory_.last_stream() ->NotifySessionOneRttKeyAvailable(); base::RunLoop().RunUntilIdle(); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - ASSERT_TRUE(HasActiveSession(scheme_host_port_)); - EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + ASSERT_TRUE(HasActiveSession(kDefaultDestination)); + EXPECT_FALSE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_FALSE( session->connection()->GetStats().server_preferred_address_validated); EXPECT_FALSE(session->connection() @@ -5524,24 +4899,16 @@ quic_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -5549,9 +4916,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Send GET request on stream. HttpResponseInfo response; @@ -5589,7 +4956,7 @@ // The session should stay alive as if nothing happened. EXPECT_EQ(1u, QuicSessionPoolPeer::GetNumDegradingSessions(factory_.get())); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); stream.reset(); @@ -5643,24 +5010,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -5668,9 +5027,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Send GET request on stream. @@ -5697,7 +5056,7 @@ // The connection should still be alive, and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); @@ -5708,7 +5067,7 @@ // Verify that the session is still active, and the request stream is active. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); stream.reset(); @@ -5801,33 +5160,20 @@ host_resolver_->rules()->AddIPLiteralRule(server2.host(), "192.168.0.2", ""); // Create request and QuicHttpStream to create session1. - QuicSessionRequest request1(factory_.get()); - EXPECT_EQ( - ERR_IO_PENDING, - request1.Request( - server1, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder1(this); + builder1.destination = server1; + EXPECT_EQ(ERR_IO_PENDING, builder1.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream1 = CreateStream(&request1); + std::unique_ptr<HttpStream> stream1 = CreateStream(&builder1.request); EXPECT_TRUE(stream1.get()); // Create request and QuicHttpStream to create session2. - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ( - ERR_IO_PENDING, - request2.Request( - server2, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder2(this); + builder2.destination = server2; + builder2.url = GURL(kServer2Url); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); QuicChromiumClientSession* session1 = GetActiveSession(server1); @@ -5838,7 +5184,7 @@ // stream. HttpRequestInfo request_info1; request_info1.method = "GET"; - request_info1.url = url_; + request_info1.url = GURL(kDefaultUrl); request_info1.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream1->RegisterRequest(&request_info1); @@ -5853,7 +5199,7 @@ // stream. HttpRequestInfo request_info2; request_info2.method = "GET"; - request_info2.url = url_; + request_info2.url = GURL(kDefaultUrl); request_info2.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream2->RegisterRequest(&request_info2); @@ -5917,27 +5263,19 @@ quic_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); crypto_client_stream_factory_.last_stream()->setHandshakeConfirmedForce( false); std::unique_ptr<QuicChromiumClientSession::Handle> handle = - session->CreateHandle(scheme_host_port_); + session->CreateHandle(kDefaultDestination); mock_ncn->NotifyNetworkDisconnected(kDefaultNetworkForTests); mock_ncn->NotifyNetworkConnected(kNewNetworkForTests); mock_ncn->NotifyNetworkMadeDefault(kNewNetworkForTests); @@ -5984,28 +5322,20 @@ quic_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_FALSE(session->HasActiveRequestStreams()); std::unique_ptr<QuicChromiumClientSession::Handle> handle = - session->CreateHandle(scheme_host_port_); + session->CreateHandle(kDefaultDestination); mock_ncn->NotifyNetworkDisconnected(kDefaultNetworkForTests); mock_ncn->NotifyNetworkConnected(kNewNetworkForTests); mock_ncn->NotifyNetworkMadeDefault(kNewNetworkForTests); @@ -6056,24 +5386,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -6081,9 +5403,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Send GET request on stream. HttpResponseInfo response; @@ -6092,7 +5414,7 @@ callback_.callback())); std::unique_ptr<QuicChromiumClientSession::Handle> handle = - session->CreateHandle(scheme_host_port_); + session->CreateHandle(kDefaultDestination); mock_ncn->NotifyNetworkDisconnected(kDefaultNetworkForTests); mock_ncn->NotifyNetworkConnected(kNewNetworkForTests); mock_ncn->NotifyNetworkMadeDefault(kNewNetworkForTests); @@ -6141,24 +5463,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -6166,9 +5480,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Send GET request on stream. HttpResponseInfo response; @@ -6177,7 +5491,7 @@ callback_.callback())); std::unique_ptr<QuicChromiumClientSession::Handle> handle = - session->CreateHandle(scheme_host_port_); + session->CreateHandle(kDefaultDestination); mock_ncn->NotifyNetworkDisconnected(kDefaultNetworkForTests); mock_ncn->NotifyNetworkConnected(kNewNetworkForTests); mock_ncn->NotifyNetworkMadeDefault(kNewNetworkForTests); @@ -6223,24 +5537,16 @@ quic_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -6248,9 +5554,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Send GET request on stream. HttpResponseInfo response; @@ -6300,24 +5606,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -6325,9 +5623,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Send GET request on stream. HttpResponseInfo response; @@ -6413,24 +5711,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -6438,9 +5728,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Send GET request on stream. HttpResponseInfo response; @@ -6564,24 +5854,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -6589,9 +5871,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Send GET request on stream. @@ -6631,7 +5913,7 @@ // The connection should still be alive, and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); @@ -6640,7 +5922,7 @@ quic_data2.Resume(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Successful port migration causes the path no longer degrading on the same // network. @@ -6666,7 +5948,7 @@ // Verify that the session is still alive, and the request stream is still // alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); chrome_stream = static_cast<QuicChromiumClientStream*>( quic::test::QuicSessionPeer::GetStream( session, GetNthClientInitiatedBidirectionalStreamId(0))); @@ -6703,24 +5985,16 @@ quic_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -6728,9 +6002,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Send GET request on stream. HttpResponseInfo response; @@ -6815,7 +6089,7 @@ // The connection should still be alive, and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Resume quic data and a connectivity probe response will be read on the @@ -6824,7 +6098,7 @@ base::RunLoop().RunUntilIdle(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); if (i < 4) { @@ -6844,7 +6118,7 @@ // Verify that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); stream.reset(); EXPECT_TRUE(quic_data1.AllReadDataConsumed()); @@ -6917,24 +6191,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -6942,9 +6208,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Send GET request on stream. @@ -6993,14 +6259,14 @@ // The connection should still be alive, and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Resume quic data and a connectivity probe response will be read on the new // socket. quic_data2.Resume(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Successful port migration causes the path no longer degrading on the same // network. EXPECT_EQ(0u, QuicSessionPoolPeer::GetNumDegradingSessions(factory_.get())); @@ -7018,7 +6284,7 @@ // Verify that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_TRUE(quic_data1.AllReadDataConsumed()); EXPECT_TRUE(quic_data1.AllWriteDataConsumed()); @@ -7073,24 +6339,16 @@ socket_factory_->AddSocketDataProvider(&socket_data); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -7098,9 +6356,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Send GET request on stream. HttpResponseInfo response; @@ -7117,7 +6375,7 @@ // The connection should still be alive, and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); @@ -7131,7 +6389,7 @@ // Verify that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); stream.reset(); EXPECT_TRUE(quic_data.AllReadDataConsumed()); @@ -7218,24 +6476,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -7243,9 +6493,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Send GET request on stream. @@ -7264,7 +6514,7 @@ // Session should still start to probe the alternate network. session->connection()->OnPathDegradingDetected(); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, QuicSessionPoolPeer::GetNumDegradingSessions(factory_.get())); // The connection should still be alive, and not marked as going away. @@ -7275,7 +6525,7 @@ quic_data2.Resume(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(0u, session->GetNumActiveStreams()); EXPECT_TRUE(session->HasActiveRequestStreams()); @@ -7291,7 +6541,7 @@ // Verify that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback())); stream.reset(); @@ -7365,24 +6615,16 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -7390,9 +6632,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Send GET request on stream. @@ -7424,7 +6666,7 @@ // The connection should still be alive, and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); @@ -7433,7 +6675,7 @@ quic_data2.Resume(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // There should be a task that will complete the migration to the new network. @@ -7457,7 +6699,7 @@ // Verify that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); stream.reset(); EXPECT_TRUE(quic_data1.AllReadDataConsumed()); @@ -7496,33 +6738,20 @@ host_resolver_->rules()->AddIPLiteralRule(server2.host(), "192.168.0.2", ""); // Create request and QuicHttpStream to create session1. - QuicSessionRequest request1(factory_.get()); - EXPECT_EQ( - ERR_IO_PENDING, - request1.Request( - server1, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder1(this); + builder1.destination = server1; + EXPECT_EQ(ERR_IO_PENDING, builder1.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream1 = CreateStream(&request1); + std::unique_ptr<HttpStream> stream1 = CreateStream(&builder1.request); EXPECT_TRUE(stream1.get()); // Create request and QuicHttpStream to create session2. - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ( - ERR_IO_PENDING, - request2.Request( - server2, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder2(this); + builder2.destination = server2; + builder2.url = GURL(kServer2Url); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); QuicChromiumClientSession* session1 = GetActiveSession(server1); @@ -7533,7 +6762,7 @@ // stream. HttpRequestInfo request_info1; request_info1.method = "GET"; - request_info1.url = url_; + request_info1.url = GURL(kDefaultUrl); request_info1.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream1->RegisterRequest(&request_info1); @@ -7548,7 +6777,7 @@ // stream. HttpRequestInfo request_info2; request_info2.method = "GET"; - request_info2.url = url_; + request_info2.url = GURL(kDefaultUrl); request_info2.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream2->RegisterRequest(&request_info2); @@ -7633,24 +6862,16 @@ quic_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -7658,9 +6879,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Send GET request on stream. HttpResponseInfo response; @@ -7677,7 +6898,7 @@ EXPECT_TRUE(session->connection()->IsPathDegrading()); EXPECT_EQ(1u, QuicSessionPoolPeer::GetNumDegradingSessions(factory_.get())); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); @@ -7686,7 +6907,7 @@ quic_data.Resume(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); stream.reset(); @@ -7768,18 +6989,10 @@ quic_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created, but marked as non-migratable. @@ -7792,9 +7005,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Trigger connection migration. Since there is a non-migratable stream, @@ -7805,7 +7018,7 @@ // packet reader. base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Resume the data to read the connectivity probing response to declare probe @@ -7815,7 +7028,7 @@ base::RunLoop().RunUntilIdle(); } - EXPECT_EQ(migrate_idle_sessions, HasActiveSession(scheme_host_port_)); + EXPECT_EQ(migrate_idle_sessions, HasActiveSession(kDefaultDestination)); EXPECT_EQ(0u, session->GetNumActiveStreams()); EXPECT_TRUE(quic_data1.AllReadDataConsumed()); @@ -7847,18 +7060,10 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -7870,9 +7075,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Set session config to have connection migration disabled. quic::test::QuicConfigPeer::SetReceivedDisableConnectionMigration( @@ -7888,7 +7093,7 @@ base::RunLoop().RunUntilIdle(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); stream.reset(); @@ -7977,18 +7182,10 @@ socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request #1 and QuicHttpStream. - QuicSessionRequest request1(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request1.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder1(this); + EXPECT_EQ(ERR_IO_PENDING, builder1.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream1 = CreateStream(&request1); + std::unique_ptr<HttpStream> stream1 = CreateStream(&builder1.request); EXPECT_TRUE(stream1.get()); HttpRequestInfo request_info1; @@ -8002,17 +7199,10 @@ // Request #2 returns synchronously because it pools to existing session. TestCompletionCallback callback2; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(OK, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback2.callback())); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + RequestBuilder builder2(this); + builder2.callback = callback2.callback(); + EXPECT_EQ(OK, builder2.CallRequest()); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); HttpRequestInfo request_info2; @@ -8025,9 +7215,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(2u, session->GetNumActiveStreams()); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -8058,7 +7248,7 @@ // Verify the session is still alive and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(2u, session->GetNumActiveStreams()); // There should be one task posted to migrate back to the default network in // kMinRetryTimeForDefaultNetworkSecs. @@ -8142,18 +7332,10 @@ quic_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request QuicHttpStream. - QuicSessionRequest request1(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request1.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder1(this); + EXPECT_EQ(ERR_IO_PENDING, builder1.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream1 = CreateStream(&request1); + std::unique_ptr<HttpStream> stream1 = CreateStream(&builder1.request); EXPECT_TRUE(stream1.get()); HttpRequestInfo request_info1; @@ -8166,9 +7348,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); MaybeMakeNewConnectionIdAvailableToSession(cid1, session); @@ -8192,7 +7374,7 @@ // Verify the session is still alive and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // There should be one task posted to migrate back to the default network in // kMinRetryTimeForDefaultNetworkSecs. @@ -8242,7 +7424,7 @@ // Verify the session is still alive and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // There should be one task posted to one will resend a connectivity probe and @@ -8251,7 +7433,7 @@ // Verify the session is still alive and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); stream1.reset(); @@ -8286,23 +7468,15 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); base::RunLoop().RunUntilIdle(); // Ensure that session is alive but not active. - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); - QuicChromiumClientSession* session = GetPendingSession(scheme_host_port_); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_TRUE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); + QuicChromiumClientSession* session = GetPendingSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); EXPECT_EQ(0u, task_runner->GetPendingTaskCount()); @@ -8314,8 +7488,8 @@ EXPECT_EQ(0u, task_runner->GetPendingTaskCount()); EXPECT_EQ(1u, QuicSessionPoolPeer::GetNumDegradingSessions(factory_.get())); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_TRUE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); } @@ -8354,23 +7528,15 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); base::RunLoop().RunUntilIdle(); // Ensure that session is alive but not active. - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); - QuicChromiumClientSession* session = GetPendingSession(scheme_host_port_); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_TRUE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); + QuicChromiumClientSession* session = GetPendingSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); EXPECT_EQ(0u, task_runner->GetPendingTaskCount()); @@ -8381,8 +7547,8 @@ base::RunLoop().RunUntilIdle(); EXPECT_EQ(1u, QuicSessionPoolPeer::GetNumDegradingSessions(factory_.get())); EXPECT_EQ(0u, task_runner->GetPendingTaskCount()); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_TRUE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); // Cause the connection to close due to |quic_error| before handshake. std::string error_details; @@ -8399,8 +7565,8 @@ task_runner->FastForwardUntilNoTasksRemain(); // No new session should be created as there is no alternate network. - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_FALSE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); } @@ -8500,23 +7666,15 @@ probing_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); base::RunLoop().RunUntilIdle(); // Ensure that session is alive but not active. - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); - QuicChromiumClientSession* session = GetPendingSession(scheme_host_port_); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_TRUE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); + QuicChromiumClientSession* session = GetPendingSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); EXPECT_EQ(0u, task_runner->GetPendingTaskCount()); EXPECT_FALSE(failed_on_default_network_); @@ -8535,9 +7693,9 @@ task_runner->FastForwardUntilNoTasksRemain(); // Verify a new session is created on the alternate network. - EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - QuicChromiumClientSession* session2 = GetPendingSession(scheme_host_port_); + EXPECT_TRUE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + QuicChromiumClientSession* session2 = GetPendingSession(kDefaultDestination); EXPECT_NE(session, session2); EXPECT_TRUE(failed_on_default_network_); @@ -8545,13 +7703,13 @@ crypto_client_stream_factory_.last_stream() ->NotifySessionOneRttKeyAvailable(); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_path1, session2); // Resume the data now so that data can be sent and read. socket_data2.Resume(); // Create the stream. - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); HttpRequestInfo request_info; request_info.method = "GET"; @@ -8614,19 +7772,11 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request, should fail after the write of the CHLO fails. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(ERR_QUIC_HANDSHAKE_FAILED, callback_.WaitForResult()); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_FALSE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); // Verify new requests can be sent normally. crypto_client_stream_factory_.set_handshake_mode( @@ -8639,18 +7789,10 @@ socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data2.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); + RequestBuilder builder2(this); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_TRUE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); // Run the message loop to complete host resolution. base::RunLoop().RunUntilIdle(); @@ -8658,11 +7800,11 @@ crypto_client_stream_factory_.last_stream() ->NotifySessionOneRttKeyAvailable(); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); - EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); + EXPECT_FALSE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); // Create QuicHttpStream. - std::unique_ptr<HttpStream> stream = CreateStream(&request2); + std::unique_ptr<HttpStream> stream = CreateStream(&builder2.request); EXPECT_TRUE(stream.get()); stream.reset(); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -8721,34 +7863,26 @@ socket_data2.AddSocketDataToFactory(socket_factory_.get()); // Create request, should fail after the write of the CHLO fails. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); // Ensure that the session is alive but not active. - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_TRUE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); base::RunLoop().RunUntilIdle(); - QuicChromiumClientSession* session = GetPendingSession(scheme_host_port_); + QuicChromiumClientSession* session = GetPendingSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); // Confirm the handshake on the alternate network. crypto_client_stream_factory_.last_stream() ->NotifySessionOneRttKeyAvailable(); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Resume the data now so that data can be sent and read. socket_data2.Resume(); // Create the stream. - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); HttpRequestInfo request_info; request_info.method = "GET"; @@ -8796,18 +7930,10 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -8821,9 +7947,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); quic::QuicConnectionId cid_on_new_path = quic::test::TestConnectionId(12345678); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -8874,7 +8000,7 @@ // Verify that session is alive and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Verify that response headers on the migrated socket were delivered to the @@ -8914,18 +8040,10 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -8939,9 +8057,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Send GET request on stream. This causes a write error, which triggers // a connection migration attempt. Since there are no networks @@ -8962,13 +8080,13 @@ // Migration has not yet failed. The session should be alive and active. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_TRUE(session->connection()->writer()->IsWriteBlocked()); // The migration will not fail until the migration alarm timeout. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); @@ -8978,7 +8096,7 @@ // The connection should be closed. A request for response headers // should fail. EXPECT_FALSE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(ERR_NETWORK_CHANGED, callback_.WaitForResult()); EXPECT_EQ(ERR_NETWORK_CHANGED, stream->ReadResponseHeaders(callback_.callback())); @@ -9080,18 +8198,10 @@ socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request #1 and QuicHttpStream. - QuicSessionRequest request1(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request1.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder1(this); + EXPECT_EQ(ERR_IO_PENDING, builder1.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream1 = CreateStream(&request1); + std::unique_ptr<HttpStream> stream1 = CreateStream(&builder1.request); EXPECT_TRUE(stream1.get()); HttpRequestInfo request_info1; @@ -9105,17 +8215,9 @@ // Second request returns synchronously because it pools to existing session. TestCompletionCallback callback2; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(OK, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback2.callback())); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + RequestBuilder builder2(this); + EXPECT_EQ(OK, builder2.CallRequest()); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); HttpRequestInfo request_info2; request_info2.method = "GET"; @@ -9127,9 +8229,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(2u, session->GetNumActiveStreams()); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -9146,7 +8248,7 @@ // Verify session is still alive and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(2u, session->GetNumActiveStreams()); // Verify that response headers on the migrated socket were delivered to the @@ -9236,18 +8338,10 @@ socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request #1 and QuicHttpStream. - QuicSessionRequest request1(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request1.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder1(this); + EXPECT_EQ(ERR_IO_PENDING, builder1.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream1 = CreateStream(&request1); + std::unique_ptr<HttpStream> stream1 = CreateStream(&builder1.request); EXPECT_TRUE(stream1.get()); HttpRequestInfo request_info1; @@ -9261,17 +8355,10 @@ // Second request returns synchronously because it pools to existing session. TestCompletionCallback callback2; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(OK, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback2.callback())); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + RequestBuilder builder2(this); + builder2.callback = callback2.callback(); + EXPECT_EQ(OK, builder2.CallRequest()); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); HttpRequestInfo request_info2; @@ -9285,9 +8372,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(2u, session->GetNumActiveStreams()); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -9305,7 +8392,7 @@ // Verify that the session is still alive and not marked as going away. // Non-migratable stream should be closed due to migration. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Verify that response headers on the migrated socket were delivered to the @@ -9403,18 +8490,10 @@ socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request #1 and QuicHttpStream. - QuicSessionRequest request1(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request1.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder1(this); + EXPECT_EQ(ERR_IO_PENDING, builder1.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream1 = CreateStream(&request1); + std::unique_ptr<HttpStream> stream1 = CreateStream(&builder1.request); EXPECT_TRUE(stream1.get()); HttpRequestInfo request_info1; @@ -9428,17 +8507,10 @@ // Second request returns synchronously because it pools to existing session. TestCompletionCallback callback2; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(OK, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback2.callback())); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + RequestBuilder builder2(this); + builder2.callback = callback2.callback(); + EXPECT_EQ(OK, builder2.CallRequest()); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); HttpRequestInfo request_info2; @@ -9452,9 +8524,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(2u, session->GetNumActiveStreams()); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -9471,7 +8543,7 @@ // closed. base::RunLoop().RunUntilIdle(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Send GET request on stream 1. @@ -9554,18 +8626,10 @@ } // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created, but marked as non-migratable. @@ -9580,9 +8644,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Send GET request on stream. This should cause a write error, which triggers @@ -9600,7 +8664,7 @@ // successfully; otherwise the connection is closed. EXPECT_EQ(migrate_idle_sessions, QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_EQ(migrate_idle_sessions, HasActiveSession(scheme_host_port_)); + EXPECT_EQ(migrate_idle_sessions, HasActiveSession(kDefaultDestination)); if (migrate_idle_sessions) { EXPECT_TRUE(failed_socket_data.AllReadDataConsumed()); @@ -9646,18 +8710,10 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -9671,9 +8727,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Set session config to have connection migration disabled. quic::test::QuicConfigPeer::SetReceivedDisableConnectionMigration( @@ -9690,7 +8746,7 @@ base::RunLoop().RunUntilIdle(); // Migration fails, and session is closed and deleted. EXPECT_FALSE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); } @@ -9755,18 +8811,10 @@ failed_quic_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -9780,9 +8828,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); // Send GET request on stream. @@ -9853,24 +8901,16 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); // Deliver the network notification, which should cause the connection to be // closed. scoped_mock_network_change_notifier_->mock_network_change_notifier() ->NotifyNetworkDisconnected(kDefaultNetworkForTests); EXPECT_EQ(ERR_NETWORK_CHANGED, callback_.WaitForResult()); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); - EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); + EXPECT_FALSE(HasActiveJob(kDefaultDestination, PRIVACY_MODE_DISABLED)); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); } @@ -9896,18 +8936,10 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -9921,9 +8953,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); quic::QuicConnectionId cid_on_new_path = quic::test::TestConnectionId(12345678); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -9984,7 +9016,7 @@ // Verify the session is still alive and not marked as going away post // migration. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Verify that response headers on the migrated socket were delivered to the // stream. @@ -10054,18 +9086,10 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -10079,9 +9103,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); quic::QuicConnectionId cid_on_new_path = quic::test::TestConnectionId(12345678); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -10144,7 +9168,7 @@ // Verify session is still alive and not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Verify that response headers on the migrated socket were delivered to the @@ -10220,24 +9244,16 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. HttpRequestInfo request_info; request_info.method = "GET"; - request_info.url = url_; + request_info.url = GURL(kDefaultUrl); request_info.traffic_annotation = MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); stream->RegisterRequest(&request_info); @@ -10245,9 +9261,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); quic::QuicConnectionId cid_on_new_path = quic::test::TestConnectionId(12345678); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -10260,7 +9276,7 @@ // The connection should still be alive, not marked as going away. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); @@ -10309,7 +9325,7 @@ // Ensure that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Run the message loop migration for write error can finish. @@ -10321,7 +9337,7 @@ // Check that the session is still alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // There should be no posted tasks not executed, no way to migrate back to // default network. @@ -10377,18 +9393,10 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -10402,9 +9410,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); quic::QuicConnectionId cid_on_new_path = quic::test::TestConnectionId(12345678); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -10455,7 +9463,7 @@ EXPECT_EQ(1u, task_runner->GetPendingTaskCount()); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Verify that response headers on the migrated socket were delivered to the @@ -10498,18 +9506,10 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -10523,9 +9523,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); quic::QuicConnectionId cid_on_new_path = quic::test::TestConnectionId(12345678); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -10577,7 +9577,7 @@ EXPECT_EQ(1u, task_runner->GetPendingTaskCount()); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Send GET request on stream. @@ -10597,7 +9597,7 @@ socket_data.Resume(); EXPECT_EQ(1u, task_runner->GetPendingTaskCount()); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); stream.reset(); @@ -10631,18 +9631,10 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -10656,9 +9648,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); quic::QuicConnectionId cid_on_new_path = quic::test::TestConnectionId(12345678); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -10711,7 +9703,7 @@ socket_data.Resume(); EXPECT_EQ(2u, task_runner->GetPendingTaskCount()); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Complete migration. @@ -10719,7 +9711,7 @@ EXPECT_EQ(1u, task_runner->GetPendingTaskCount()); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Send GET request on stream. @@ -10830,18 +9822,10 @@ socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -10855,8 +9839,8 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Now notify network is disconnected, cause the migration to complete // immediately. @@ -10866,7 +9850,7 @@ // Complete migration. task_runner->RunUntilIdle(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Send GET request on stream. @@ -10894,7 +9878,7 @@ // packet reader. Verify that the session is not affected. socket_data.Resume(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); stream.reset(); @@ -10996,18 +9980,10 @@ socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -11021,8 +9997,8 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Now notify network is disconnected, cause the migration to complete // immediately. @@ -11032,7 +10008,7 @@ // Complete migration. task_runner->RunUntilIdle(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Send GET request on stream. @@ -11060,7 +10036,7 @@ // packet reader. Verify that the session is not affected. socket_data.Resume(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); stream.reset(); @@ -11130,18 +10106,10 @@ socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -11155,13 +10123,13 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Complete migration. task_runner->RunUntilIdle(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Send GET request on stream. @@ -11188,7 +10156,7 @@ // Resume the old socket data, a read error will be delivered to the old // packet reader. Verify that the session is not affected. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); stream.reset(); @@ -11206,7 +10174,7 @@ ServerNetworkStats stats; stats.srtt = base::Milliseconds(200); http_server_properties_->SetServerNetworkStats( - url::SchemeHostPort(url_), NetworkAnonymizationKey(), stats); + url::SchemeHostPort(GURL(kDefaultUrl)), NetworkAnonymizationKey(), stats); quic_params_->estimate_initial_rtt = true; Initialize(); @@ -11259,18 +10227,10 @@ socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -11284,13 +10244,13 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Complete migration. task_runner->RunUntilIdle(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Send GET request on stream. @@ -11320,7 +10280,7 @@ // Resume the old socket data, a read error will be delivered to the old // packet reader. Verify that the session is not affected. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); stream.reset(); @@ -11390,18 +10350,10 @@ socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -11415,13 +10367,13 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Complete migration. task_runner->RunUntilIdle(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Send GET request on stream. @@ -11448,7 +10400,7 @@ // Resume the old socket data, a read error will be delivered to the old // packet reader. Verify that the session is not affected. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); stream.reset(); @@ -11467,7 +10419,7 @@ ServerNetworkStats stats; stats.srtt = base::Milliseconds(200); http_server_properties_->SetServerNetworkStats( - url::SchemeHostPort(url_), NetworkAnonymizationKey(), stats); + url::SchemeHostPort(GURL(kDefaultUrl)), NetworkAnonymizationKey(), stats); quic_params_->estimate_initial_rtt = true; quic_params_->migrate_sessions_on_network_change_v2 = true; Initialize(); @@ -11521,18 +10473,10 @@ socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -11546,13 +10490,13 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Complete migration. task_runner->RunUntilIdle(); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Send GET request on stream. @@ -11582,7 +10526,7 @@ // Resume the old socket data, a read error will be delivered to the old // packet reader. Verify that the session is not affected. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); stream.reset(); @@ -11615,18 +10559,10 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -11640,9 +10576,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); quic::QuicConnectionId cid_on_new_path = quic::test::TestConnectionId(12345678); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -11678,7 +10614,7 @@ // Verify session is not closed with read error. EXPECT_EQ(1u, task_runner->GetPendingTaskCount()); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Complete migration. @@ -11687,7 +10623,7 @@ // default network. EXPECT_EQ(1u, task_runner->GetPendingTaskCount()); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // Verify that response headers on the migrated socket were delivered to the @@ -11770,18 +10706,10 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -11795,9 +10723,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); quic::QuicConnectionId cid_on_new_path = quic::test::TestConnectionId(12345678); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -11815,7 +10743,7 @@ // In this particular code path, the network will not yet be marked // as going away and the session will still be alive. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback())); @@ -11872,7 +10800,7 @@ ->NotifyNetworkDisconnected(kDefaultNetworkForTests); } EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); // This is the callback for the response headers that returned @@ -11885,21 +10813,13 @@ scoped_mock_network_change_notifier_->mock_network_change_notifier() ->NotifyNetworkMadeDefault(kNewNetworkForTests); - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(OK, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + RequestBuilder builder2(this); + EXPECT_EQ(OK, builder2.CallRequest()); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); - EXPECT_EQ(session, GetActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); + EXPECT_EQ(session, GetActiveSession(kDefaultDestination)); stream.reset(); stream2.reset(); @@ -12064,22 +10984,14 @@ quic_data5.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Ensure that session is active. - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Trigger connection migration. Since there are no active streams, // the session will be closed. @@ -12115,7 +11027,7 @@ base::RunLoop().RunUntilIdle(); // Make new connection ID available. alternate_socket_data.Resume(); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // A task is posted to migrate back to the default network in 2^i seconds. EXPECT_EQ(1u, task_runner->GetPendingTaskCount()); EXPECT_EQ(base::Seconds(UINT64_C(1) << i), @@ -12252,22 +11164,14 @@ quic_data4.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Ensure that session is active. - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Trigger connection migration. Since there are no active streams, // the session will be closed. @@ -12303,7 +11207,7 @@ base::RunLoop().RunUntilIdle(); // Make new connection ID available. alternate_socket_data.Resume(); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // A task is posted to migrate back to the default network in 2^i seconds. EXPECT_EQ(1u, task_runner->GetPendingTaskCount()); EXPECT_EQ(base::Seconds(UINT64_C(1) << i), @@ -12338,18 +11242,10 @@ socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -12363,9 +11259,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); quic::QuicConnectionId cid_on_new_path = quic::test::TestConnectionId(12345678); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -12433,7 +11329,7 @@ // The session should be alive and active. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_EQ(1u, session->GetNumActiveStreams()); session->PopulateNetErrorDetails(&details); @@ -12485,18 +11381,10 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -12510,9 +11398,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); quic::QuicConnectionId cid_on_new_path = quic::test::TestConnectionId(12345678); MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session); @@ -12554,7 +11442,7 @@ // The session should exist but no longer be active since its only stream has // been reset. EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); session->PopulateNetErrorDetails(&details); EXPECT_TRUE(details.quic_connection_migration_attempted); @@ -12588,7 +11476,7 @@ TEST_P(QuicSessionPoolTest, ServerMigrationIPv6ToIPv6) { // Add a resolver rule to make initial connection to an IPv6 address. - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "fe80::aebc:32ff:febb:1e33", ""); // Add alternate IPv6 server address to config. IPEndPoint alt_address = IPEndPoint( @@ -12605,7 +11493,7 @@ Initialize(); // Add a resolver rule to make initial connection to an IPv6 address. - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "fe80::aebc:32ff:febb:1e33", ""); // Add alternate IPv4 server address to config. IPEndPoint alt_address = IPEndPoint(IPAddress(1, 2, 3, 4), 123); @@ -12636,18 +11524,10 @@ socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -12661,9 +11541,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); IPEndPoint actual_address; session->GetDefaultSocket()->GetPeerAddress(&actual_address); @@ -12688,7 +11568,7 @@ Initialize(); // Add a resolver rule to make initial connection to an IPv4 address. - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), "1.2.3.4", + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "1.2.3.4", ""); // Add alternate IPv6 server address to config. IPEndPoint alt_address = IPEndPoint( @@ -12720,18 +11600,10 @@ socket_data1.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -12745,9 +11617,9 @@ CompletionOnceCallback())); // Ensure that session is alive and active. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); IPEndPoint actual_address; session->GetDefaultSocket()->GetPeerAddress(&actual_address); @@ -12782,21 +11654,13 @@ socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data2.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); // Synthesize a CertDatabase change notification and verify that stream saw // the event. @@ -12805,27 +11669,19 @@ EXPECT_TRUE(factory_->is_quic_known_to_work_on_current_network()); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); // Now attempting to request a stream to the same origin should create // a new session. - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder2(this); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2); - QuicChromiumClientSession* session2 = GetActiveSession(scheme_host_port_); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + QuicChromiumClientSession* session2 = GetActiveSession(kDefaultDestination); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_NE(session, session2); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session2)); @@ -12856,21 +11712,13 @@ socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data2.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); // Synthesize a CertVerifier change notification and verify that stream saw // the event. @@ -12879,27 +11727,19 @@ EXPECT_TRUE(factory_->is_quic_known_to_work_on_current_network()); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); // Now attempting to request a stream to the same origin should create // a new session. - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder2(this); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2); - QuicChromiumClientSession* session2 = GetActiveSession(scheme_host_port_); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + QuicChromiumClientSession* session2 = GetActiveSession(kDefaultDestination); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); EXPECT_NE(session, session2); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session2)); @@ -12933,7 +11773,8 @@ QuicSessionPoolPeer::GetCryptoConfig(factory_.get(), NetworkAnonymizationKey()); quic::QuicServerId server_id1(scheme_host_port1.host(), - scheme_host_port1.port(), privacy_mode_); + scheme_host_port1.port(), + PRIVACY_MODE_DISABLED); quic::QuicCryptoClientConfig::CachedState* cached1 = crypto_config_handle->GetConfig()->LookupOrCreate(server_id1); EXPECT_FALSE(cached1->proof_valid()); @@ -12946,7 +11787,8 @@ url::SchemeHostPort scheme_host_port2(url::kHttpsScheme, r2_host_name, 80); quic::QuicServerId server_id2(scheme_host_port2.host(), - scheme_host_port2.port(), privacy_mode_); + scheme_host_port2.port(), + PRIVACY_MODE_DISABLED); quic::QuicCryptoClientConfig::CachedState* cached2 = crypto_config_handle->GetConfig()->LookupOrCreate(server_id2); EXPECT_EQ(cached1->source_address_token(), cached2->source_address_token()); @@ -12973,7 +11815,8 @@ QuicSessionPoolPeer::GetCryptoConfig(factory_.get(), NetworkAnonymizationKey()); quic::QuicServerId server_id1(scheme_host_port1.host(), - scheme_host_port1.port(), privacy_mode_); + scheme_host_port1.port(), + PRIVACY_MODE_DISABLED); quic::QuicCryptoClientConfig::CachedState* cached1 = crypto_config_handle->GetConfig()->LookupOrCreate(server_id1); EXPECT_FALSE(cached1->proof_valid()); @@ -12986,7 +11829,8 @@ url::SchemeHostPort scheme_host_port2(url::kHttpsScheme, r4_host_name, 80); quic::QuicServerId server_id2(scheme_host_port2.host(), - scheme_host_port2.port(), privacy_mode_); + scheme_host_port2.port(), + PRIVACY_MODE_DISABLED); quic::QuicCryptoClientConfig::CachedState* cached2 = crypto_config_handle->GetConfig()->LookupOrCreate(server_id2); EXPECT_NE(cached1->source_address_token(), cached2->source_address_token()); @@ -13012,26 +11856,18 @@ crypto_client_stream_factory_.set_handshake_mode( MockCryptoClientStream::ZERO_RTT); host_resolver_->set_synchronous_mode(true); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); // If we are waiting for disk cache, we would have posted a task. Verify that // the CancelWaitForDataReady task hasn't been posted. ASSERT_EQ(0u, runner_->GetPostedTasks().size()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -13063,7 +11899,7 @@ crypto_client_stream_factory_.set_handshake_mode( MockCryptoClientStream::CONFIRM_HANDSHAKE); host_resolver_->set_synchronous_mode(true); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); host_resolver_->rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", ""); @@ -13071,21 +11907,13 @@ // with open stream. EXPECT_EQ(quic::QuicTime::Delta::FromSeconds(quic::kPingTimeoutSecs), QuicSessionPoolPeer::GetPingTimeout(factory_.get())); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); HttpRequestInfo request_info; request_info.traffic_annotation = @@ -13112,20 +11940,15 @@ // Test two-in-a-row timeouts with open streams. DVLOG(1) << "Create 2nd session and timeout with open stream"; TestCompletionCallback callback2; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ( - ERR_IO_PENDING, - request2.Request( - server2, version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback2.callback())); + RequestBuilder builder2(this); + builder2.destination = server2; + builder2.url = GURL(kServer2Url); + builder2.callback = callback2.callback(); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_THAT(callback2.WaitForResult(), IsOk()); QuicChromiumClientSession* session2 = GetActiveSession(server2); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); stream2->RegisterRequest(&request_info); EXPECT_EQ(OK, stream2->InitializeStream(false, DEFAULT_PRIORITY, net_log_, @@ -13427,14 +12250,14 @@ QuicSessionPoolPeer::SetTaskRunner(factory_.get(), runner_.get()); const AlternativeService alternative_service1( - kProtoQUIC, scheme_host_port_.host(), scheme_host_port_.port()); + kProtoQUIC, kDefaultServerHostName, kDefaultServerPort); AlternativeServiceInfoVector alternative_service_info_vector; base::Time expiration = base::Time::Now() + base::Days(1); alternative_service_info_vector.push_back( AlternativeServiceInfo::CreateQuicAlternativeServiceInfo( alternative_service1, expiration, {version_})); http_server_properties_->SetAlternativeServices( - url::SchemeHostPort(url_), network_anonymization_keys[i], + url::SchemeHostPort(GURL(kDefaultUrl)), network_anonymization_keys[i], alternative_service_info_vector); http_server_properties_->SetMaxServerConfigsStoredInProperties( @@ -13489,16 +12312,11 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); client_maker_.Reset(); - QuicSessionRequest request(factory_.get()); - int rv = request.Request( - url::SchemeHostPort(url::kHttpsScheme, kDefaultServerHostName, - kDefaultServerPort), - version_, ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), network_anonymization_keys[i], SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback()); + RequestBuilder builder(this); + builder.destination = url::SchemeHostPort( + url::kHttpsScheme, kDefaultServerHostName, kDefaultServerPort); + builder.network_anonymization_key = network_anonymization_keys[i]; + int rv = builder.CallRequest(); EXPECT_THAT(callback_.GetResult(rv), IsOk()); // While the session is still alive, there should be @@ -13544,7 +12362,7 @@ crypto_client_stream_factory_.set_handshake_mode( MockCryptoClientStream::ZERO_RTT); host_resolver_->set_synchronous_mode(true); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); // Set up the TaskObserver to verify QuicChromiumPacketReader::StartReading @@ -13553,16 +12371,8 @@ SpdySessionTestTaskObserver observer("quic_chromium_packet_reader.cc", "StartReading"); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); // Call run_loop so that QuicChromiumPacketReader::OnReadComplete() gets // called. @@ -13573,7 +12383,7 @@ // yielded the read. EXPECT_EQ(1u, observer.executed_count()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_FALSE(stream.get()); // Session is already closed. EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -13596,7 +12406,7 @@ crypto_client_stream_factory_.set_handshake_mode( MockCryptoClientStream::ZERO_RTT); host_resolver_->set_synchronous_mode(true); - host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + host_resolver_->rules()->AddIPLiteralRule(kDefaultServerHostName, "192.168.0.1", ""); // Set up the TaskObserver to verify QuicChromiumPacketReader::StartReading @@ -13605,17 +12415,8 @@ SpdySessionTestTaskObserver observer("quic_chromium_packet_reader.cc", "StartReading"); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); // Call run_loop so that QuicChromiumPacketReader::OnReadComplete() gets // called. @@ -13626,7 +12427,7 @@ // yielded the read. EXPECT_EQ(1u, observer.executed_count()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_FALSE(stream.get()); // Session is already closed. EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -13649,34 +12450,21 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request1(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request1.Request( - destination1, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder1(this); + builder1.destination = destination1; + EXPECT_EQ(ERR_IO_PENDING, builder1.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream1 = CreateStream(&request1); + std::unique_ptr<HttpStream> stream1 = CreateStream(&builder1.request); EXPECT_TRUE(stream1.get()); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Second request returns synchronously because it pools to existing session. TestCompletionCallback callback2; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(OK, - request2.Request( - destination2, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback2.callback())); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + RequestBuilder builder2(this); + builder2.destination = destination2; + builder2.callback = callback2.callback(); + EXPECT_EQ(OK, builder2.CallRequest()); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); QuicChromiumClientSession::Handle* session1 = @@ -13684,10 +12472,9 @@ QuicChromiumClientSession::Handle* session2 = QuicHttpStreamPeer::GetSessionHandle(stream2.get()); EXPECT_TRUE(session1->SharesSameSession(*session2)); - EXPECT_EQ( - quic::QuicServerId(scheme_host_port_.host(), scheme_host_port_.port(), - privacy_mode_ == PRIVACY_MODE_ENABLED), - session1->server_id()); + EXPECT_EQ(quic::QuicServerId(kDefaultServerHostName, kDefaultServerPort, + /*privacy_mode_enabled=*/false), + session1->server_id()); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -13811,8 +12598,6 @@ // is valid for the hostname of the alternative service. origin2_ = url::SchemeHostPort(url::kHttpsScheme, "mail.example.org", 433); - url::SchemeHostPort destination = GetDestination(); - scoped_refptr<X509Certificate> cert( ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem")); ASSERT_FALSE(cert->VerifyNameMatch(origin1_.host())); @@ -13825,17 +12610,10 @@ AddHangingSocketData(); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - destination, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + builder.destination = GetDestination(); + builder.url = url; + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsError(ERR_QUIC_HANDSHAKE_FAILED)); EXPECT_TRUE(AllDataConsumed()); @@ -13850,8 +12628,6 @@ origin1_ = url::SchemeHostPort(url1); origin2_ = url::SchemeHostPort(url2); - url::SchemeHostPort destination = GetDestination(); - scoped_refptr<X509Certificate> cert( ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem")); ASSERT_TRUE(cert->VerifyNameMatch(origin1_.host())); @@ -13868,35 +12644,24 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request1(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request1.Request( - destination, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url1, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder1(this); + builder1.destination = GetDestination(); + builder1.url = url1; + EXPECT_EQ(ERR_IO_PENDING, builder1.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream1 = CreateStream(&request1); + std::unique_ptr<HttpStream> stream1 = CreateStream(&builder1.request); EXPECT_TRUE(stream1.get()); EXPECT_TRUE(HasActiveSession(origin1_)); // Second request returns synchronously because it pools to existing session. TestCompletionCallback callback2; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(OK, - request2.Request( - destination, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback2.callback())); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + RequestBuilder builder2(this); + builder2.destination = GetDestination(); + builder2.url = url2; + builder2.callback = callback2.callback(); + EXPECT_EQ(OK, builder2.CallRequest()); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); QuicChromiumClientSession::Handle* session1 = @@ -13906,7 +12671,7 @@ EXPECT_TRUE(session1->SharesSameSession(*session2)); EXPECT_EQ(quic::QuicServerId(origin1_.host(), origin1_.port(), - privacy_mode_ == PRIVACY_MODE_ENABLED), + /*privacy_mode_enabled=*/false), session1->server_id()); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -13950,34 +12715,25 @@ socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data2.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request1(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request1.Request( - destination, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - PRIVACY_MODE_DISABLED, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url1, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder1(this); + builder1.destination = destination; + builder1.privacy_mode = PRIVACY_MODE_DISABLED; + builder1.url = url1; + EXPECT_EQ(ERR_IO_PENDING, builder1.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream1 = CreateStream(&request1); + std::unique_ptr<HttpStream> stream1 = CreateStream(&builder1.request); EXPECT_TRUE(stream1.get()); EXPECT_TRUE(HasActiveSession(origin1_)); TestCompletionCallback callback2; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - destination, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - PRIVACY_MODE_ENABLED, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback2.callback())); + RequestBuilder builder2(this); + builder2.destination = destination; + builder2.privacy_mode = PRIVACY_MODE_ENABLED; + builder2.url = url2; + builder2.callback = callback2.callback(); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_EQ(OK, callback2.WaitForResult()); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); // |request2| does not pool to the first session, because PrivacyMode does not @@ -13989,9 +12745,11 @@ QuicHttpStreamPeer::GetSessionHandle(stream2.get()); EXPECT_FALSE(session1->SharesSameSession(*session2)); - EXPECT_EQ(quic::QuicServerId(origin1_.host(), origin1_.port(), false), + EXPECT_EQ(quic::QuicServerId(origin1_.host(), origin1_.port(), + /*privacy_mode_enabled=*/false), session1->server_id()); - EXPECT_EQ(quic::QuicServerId(origin2_.host(), origin2_.port(), true), + EXPECT_EQ(quic::QuicServerId(origin2_.host(), origin2_.port(), + /*privacy_mode_enabled=*/true), session2->server_id()); EXPECT_TRUE(socket_data1.AllReadDataConsumed()); @@ -14037,34 +12795,25 @@ socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data2.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request1(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request1.Request( - destination, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - PRIVACY_MODE_DISABLED, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url1, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder1(this); + builder1.destination = destination; + builder1.secure_dns_policy = SecureDnsPolicy::kAllow; + builder1.url = url1; + EXPECT_EQ(ERR_IO_PENDING, builder1.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream1 = CreateStream(&request1); + std::unique_ptr<HttpStream> stream1 = CreateStream(&builder1.request); EXPECT_TRUE(stream1.get()); EXPECT_TRUE(HasActiveSession(origin1_)); TestCompletionCallback callback2; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - destination, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - PRIVACY_MODE_DISABLED, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kDisable, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback2.callback())); + RequestBuilder builder2(this); + builder2.destination = destination; + builder2.secure_dns_policy = SecureDnsPolicy::kDisable; + builder2.url = url2; + builder2.callback = callback2.callback(); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_EQ(OK, callback2.WaitForResult()); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); // |request2| does not pool to the first session, because |secure_dns_policy| @@ -14117,39 +12866,32 @@ socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data2.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request1(factory_.get()); auto proxy_chain1 = ProxyChain::FromSchemeHostAndPort( ProxyServer::SCHEME_QUIC, "proxy1", 443); - EXPECT_EQ( - ERR_IO_PENDING, - request1.Request( - destination, version_, proxy_chain1, TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, PRIVACY_MODE_DISABLED, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url1, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder1(this); + builder1.destination = destination; + builder1.proxy_chain = proxy_chain1; + builder1.secure_dns_policy = SecureDnsPolicy::kAllow; + builder1.url = url1; + EXPECT_EQ(ERR_IO_PENDING, builder1.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream1 = CreateStream(&request1); + std::unique_ptr<HttpStream> stream1 = CreateStream(&builder1.request); EXPECT_TRUE(stream1.get()); EXPECT_TRUE( HasActiveSession(origin1_, NetworkAnonymizationKey(), proxy_chain1)); TestCompletionCallback callback2; - QuicSessionRequest request2(factory_.get()); auto proxy_chain2 = ProxyChain::FromSchemeHostAndPort( ProxyServer::SCHEME_QUIC, "proxy2", 443); - EXPECT_EQ( - ERR_IO_PENDING, - request2.Request( - destination, version_, proxy_chain2, TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, PRIVACY_MODE_DISABLED, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kDisable, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback2.callback())); + RequestBuilder builder2(this); + builder2.destination = destination; + builder2.proxy_chain = proxy_chain2; + builder2.secure_dns_policy = SecureDnsPolicy::kDisable; + builder2.url = url2; + builder2.callback = callback2.callback(); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_EQ(OK, callback2.WaitForResult()); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); // `request2` does not pool to the first session, because `proxy_chain` does @@ -14202,34 +12944,27 @@ socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data2.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request1(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request1.Request( - destination, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - PRIVACY_MODE_DISABLED, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url1, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder1(this); + builder1.destination = destination; + builder1.session_usage = SessionUsage::kDestination; + builder1.secure_dns_policy = SecureDnsPolicy::kAllow; + builder1.url = url1; + EXPECT_EQ(ERR_IO_PENDING, builder1.CallRequest()); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<HttpStream> stream1 = CreateStream(&request1); + std::unique_ptr<HttpStream> stream1 = CreateStream(&builder1.request); EXPECT_TRUE(stream1.get()); EXPECT_TRUE(HasActiveSession(origin1_)); TestCompletionCallback callback2; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - destination, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kProxy, - PRIVACY_MODE_DISABLED, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kDisable, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback2.callback())); + RequestBuilder builder2(this); + builder2.destination = destination; + builder2.session_usage = SessionUsage::kProxy; + builder2.secure_dns_policy = SecureDnsPolicy::kDisable; + builder2.url = url2; + builder2.callback = callback2.callback(); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_EQ(OK, callback2.WaitForResult()); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); // `request2` does not pool to the first session, because `session_usage` @@ -14287,34 +13022,23 @@ socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data2.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request1(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request1.Request( - destination, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url1, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder1(this); + builder1.destination = destination; + builder1.url = url1; + EXPECT_EQ(ERR_IO_PENDING, builder1.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream1 = CreateStream(&request1); + std::unique_ptr<HttpStream> stream1 = CreateStream(&builder1.request); EXPECT_TRUE(stream1.get()); EXPECT_TRUE(HasActiveSession(origin1_)); TestCompletionCallback callback2; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - destination, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback2.callback())); + RequestBuilder builder2(this); + builder2.destination = destination; + builder2.url = url2; + builder2.callback = callback2.callback(); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_THAT(callback2.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); // |request2| does not pool to the first session, because the certificate does @@ -14327,10 +13051,10 @@ EXPECT_FALSE(session1->SharesSameSession(*session2)); EXPECT_EQ(quic::QuicServerId(origin1_.host(), origin1_.port(), - privacy_mode_ == PRIVACY_MODE_ENABLED), + /*privacy_mode_enabled=*/false), session1->server_id()); EXPECT_EQ(quic::QuicServerId(origin2_.host(), origin2_.port(), - privacy_mode_ == PRIVACY_MODE_ENABLED), + /*privacy_mode_enabled=*/false), session2->server_id()); EXPECT_TRUE(socket_data1.AllReadDataConsumed()); @@ -14368,11 +13092,11 @@ quic::QuicServerId server_id; raw_ptr<quic::QuicCryptoClientConfig::CachedState> state; - } test_cases[] = {TestCase("www.google.com", 443, privacy_mode_, + } test_cases[] = {TestCase("www.google.com", 443, PRIVACY_MODE_DISABLED, crypto_config_handle->GetConfig()), - TestCase("www.example.com", 443, privacy_mode_, + TestCase("www.example.com", 443, PRIVACY_MODE_DISABLED, crypto_config_handle->GetConfig()), - TestCase("www.example.com", 4433, privacy_mode_, + TestCase("www.example.com", 4433, PRIVACY_MODE_DISABLED, crypto_config_handle->GetConfig())}; // Clear cached states for the origin https://www.example.com:4433. @@ -14424,19 +13148,11 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, MAXIMUM_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + builder.priority = MAXIMUM_PRIORITY; + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); EXPECT_EQ(MAXIMUM_PRIORITY, host_resolver_->last_request_priority()); @@ -14455,34 +13171,20 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, MAXIMUM_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + builder.priority = MAXIMUM_PRIORITY; + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_EQ(MAXIMUM_PRIORITY, host_resolver_->last_request_priority()); EXPECT_EQ(MAXIMUM_PRIORITY, host_resolver_->request_priority(1)); - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url2_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder2(this); + builder2.priority = DEFAULT_PRIORITY; + builder2.url = GURL(kServer2Url); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_EQ(DEFAULT_PRIORITY, host_resolver_->last_request_priority()); EXPECT_EQ(DEFAULT_PRIORITY, host_resolver_->request_priority(2)); - request.SetPriority(LOWEST); + builder.request.SetPriority(LOWEST); EXPECT_EQ(LOWEST, host_resolver_->request_priority(1)); EXPECT_EQ(DEFAULT_PRIORITY, host_resolver_->request_priority(2)); } @@ -14511,19 +13213,12 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - kNetworkAnonymizationKey, SecureDnsPolicy::kDisable, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + builder.network_anonymization_key = kNetworkAnonymizationKey; + builder.secure_dns_policy = SecureDnsPolicy::kDisable; + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); EXPECT_EQ(net::SecureDnsPolicy::kDisable, @@ -14562,20 +13257,12 @@ socket_data.AddWrite(SYNCHRONOUS, ERR_FAILED); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); TestCompletionCallback quic_session_callback; - EXPECT_TRUE( - request.WaitForQuicSessionCreation(quic_session_callback.callback())); + EXPECT_TRUE(builder.request.WaitForQuicSessionCreation( + quic_session_callback.callback())); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(quic_session_callback.have_result()); @@ -14583,8 +13270,8 @@ // Calling WaitForQuicSessionCreation() a second time should return // false since the session has been created. - EXPECT_FALSE( - request.WaitForQuicSessionCreation(quic_session_callback.callback())); + EXPECT_FALSE(builder.request.WaitForQuicSessionCreation( + quic_session_callback.callback())); EXPECT_TRUE(callback_.have_result()); EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult()); @@ -14602,27 +13289,19 @@ socket_data.AddWrite(SYNCHRONOUS, OK); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); TestCompletionCallback quic_session_callback; - EXPECT_TRUE( - request.WaitForQuicSessionCreation(quic_session_callback.callback())); + EXPECT_TRUE(builder.request.WaitForQuicSessionCreation( + quic_session_callback.callback())); EXPECT_EQ(OK, quic_session_callback.WaitForResult()); // Calling WaitForQuicSessionCreation() a second time should return // false since the session has been created. - EXPECT_FALSE( - request.WaitForQuicSessionCreation(quic_session_callback.callback())); + EXPECT_FALSE(builder.request.WaitForQuicSessionCreation( + quic_session_callback.callback())); EXPECT_TRUE(callback_.have_result()); EXPECT_EQ(OK, callback_.WaitForResult()); @@ -14644,20 +13323,12 @@ socket_data.AddWrite(SYNCHRONOUS, OK); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); TestCompletionCallback quic_session_callback; - EXPECT_TRUE( - request.WaitForQuicSessionCreation(quic_session_callback.callback())); + EXPECT_TRUE(builder.request.WaitForQuicSessionCreation( + quic_session_callback.callback())); EXPECT_EQ(ERR_IO_PENDING, quic_session_callback.WaitForResult()); @@ -14666,8 +13337,8 @@ ->NotifySessionOneRttKeyAvailable(); // Calling WaitForQuicSessionCreation() a second time should return // false since the session has been created. - EXPECT_FALSE( - request.WaitForQuicSessionCreation(quic_session_callback.callback())); + EXPECT_FALSE(builder.request.WaitForQuicSessionCreation( + quic_session_callback.callback())); EXPECT_EQ(OK, callback_.WaitForResult()); } @@ -14686,20 +13357,12 @@ socket_data.AddWrite(SYNCHRONOUS, ERR_FAILED); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); TestCompletionCallback host_resolution_callback; - EXPECT_TRUE( - request.WaitForHostResolution(host_resolution_callback.callback())); + EXPECT_TRUE(builder.request.WaitForHostResolution( + host_resolution_callback.callback())); // |host_resolver_| has not finished host resolution at this point, so // |host_resolution_callback| should not have a result. @@ -14718,8 +13381,8 @@ // Calling WaitForHostResolution() a second time should return // false since host resolution has finished already. - EXPECT_FALSE( - request.WaitForHostResolution(host_resolution_callback.callback())); + EXPECT_FALSE(builder.request.WaitForHostResolution( + host_resolution_callback.callback())); EXPECT_TRUE(callback_.have_result()); EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult()); @@ -14743,20 +13406,12 @@ socket_data.AddWrite(ASYNC, ERR_FAILED); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); TestCompletionCallback host_resolution_callback; - EXPECT_TRUE( - request.WaitForHostResolution(host_resolution_callback.callback())); + EXPECT_TRUE(builder.request.WaitForHostResolution( + host_resolution_callback.callback())); // |host_resolver_| has not finished host resolution at this point, so // |host_resolution_callback| should not have a result. @@ -14773,8 +13428,8 @@ // Calling WaitForHostResolution() a second time should return // false since host resolution has finished already. - EXPECT_FALSE( - request.WaitForHostResolution(host_resolution_callback.callback())); + EXPECT_FALSE(builder.request.WaitForHostResolution( + host_resolution_callback.callback())); EXPECT_FALSE(callback_.have_result()); socket_data.GetSequencedSocketData()->Resume(); @@ -14797,22 +13452,14 @@ socket_data.AddWrite(SYNCHRONOUS, ERR_FAILED); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); // WaitForHostResolution() should return false since host // resolution has finished already. TestCompletionCallback host_resolution_callback; - EXPECT_FALSE( - request.WaitForHostResolution(host_resolution_callback.callback())); + EXPECT_FALSE(builder.request.WaitForHostResolution( + host_resolution_callback.callback())); base::RunLoop().RunUntilIdle(); EXPECT_FALSE(host_resolution_callback.have_result()); EXPECT_TRUE(callback_.have_result()); @@ -14839,22 +13486,14 @@ socket_data.AddWrite(ASYNC, ERR_FAILED); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); // WaitForHostResolution() should return false since host // resolution has finished already. TestCompletionCallback host_resolution_callback; - EXPECT_FALSE( - request.WaitForHostResolution(host_resolution_callback.callback())); + EXPECT_FALSE(builder.request.WaitForHostResolution( + host_resolution_callback.callback())); base::RunLoop().RunUntilIdle(); EXPECT_FALSE(host_resolution_callback.have_result()); @@ -14873,25 +13512,17 @@ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); // Host resolution will fail synchronously. - host_resolver_->rules()->AddSimulatedFailure(scheme_host_port_.host()); + host_resolver_->rules()->AddSimulatedFailure(kDefaultServerHostName); host_resolver_->set_synchronous_mode(true); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, builder.CallRequest()); // WaitForHostResolution() should return false since host // resolution has failed already. TestCompletionCallback host_resolution_callback; - EXPECT_FALSE( - request.WaitForHostResolution(host_resolution_callback.callback())); + EXPECT_FALSE(builder.request.WaitForHostResolution( + host_resolution_callback.callback())); base::RunLoop().RunUntilIdle(); EXPECT_FALSE(host_resolution_callback.have_result()); } @@ -14903,22 +13534,14 @@ ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); - host_resolver_->rules()->AddSimulatedFailure(scheme_host_port_.host()); + host_resolver_->rules()->AddSimulatedFailure(kDefaultServerHostName); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); TestCompletionCallback host_resolution_callback; - EXPECT_TRUE( - request.WaitForHostResolution(host_resolution_callback.callback())); + EXPECT_TRUE(builder.request.WaitForHostResolution( + host_resolution_callback.callback())); // Allow |host_resolver_| to fail host resolution. |host_resolution_callback| // Should run with ERR_NAME_NOT_RESOLVED since that's the error host @@ -14961,57 +13584,39 @@ #endif // Request a stream with |tag1|. - QuicSessionRequest request1(factory_.get()); - int rv = request1.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, privacy_mode_, - DEFAULT_PRIORITY, tag1, NetworkAnonymizationKey(), - SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback()); + RequestBuilder builder1(this); + builder1.socket_tag = tag1; + int rv = builder1.CallRequest(); EXPECT_THAT(callback_.GetResult(rv), IsOk()); EXPECT_EQ(socket_factory->GetLastProducedUDPSocket()->tag(), tag1); EXPECT_TRUE(socket_factory->GetLastProducedUDPSocket() ->tagged_before_data_transferred()); std::unique_ptr<QuicChromiumClientSession::Handle> stream1 = - request1.ReleaseSessionHandle(); + builder1.request.ReleaseSessionHandle(); EXPECT_TRUE(stream1); EXPECT_TRUE(stream1->IsConnected()); // Request a stream with |tag1| and verify underlying session is reused. - QuicSessionRequest request2(factory_.get()); - rv = request2.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, privacy_mode_, - DEFAULT_PRIORITY, tag1, NetworkAnonymizationKey(), - SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback()); + RequestBuilder builder2(this); + builder2.socket_tag = tag1; + rv = builder2.CallRequest(); EXPECT_THAT(callback_.GetResult(rv), IsOk()); std::unique_ptr<QuicChromiumClientSession::Handle> stream2 = - request2.ReleaseSessionHandle(); + builder2.request.ReleaseSessionHandle(); EXPECT_TRUE(stream2); EXPECT_TRUE(stream2->IsConnected()); EXPECT_TRUE(stream2->SharesSameSession(*stream1)); // Request a stream with |tag2| and verify a new session is created. - QuicSessionRequest request3(factory_.get()); - rv = request3.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, privacy_mode_, - DEFAULT_PRIORITY, tag2, NetworkAnonymizationKey(), - SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback()); + RequestBuilder builder3(this); + builder3.socket_tag = tag2; + rv = builder3.CallRequest(); EXPECT_THAT(callback_.GetResult(rv), IsOk()); EXPECT_EQ(socket_factory->GetLastProducedUDPSocket()->tag(), tag2); EXPECT_TRUE(socket_factory->GetLastProducedUDPSocket() ->tagged_before_data_transferred()); std::unique_ptr<QuicChromiumClientSession::Handle> stream3 = - request3.ReleaseSessionHandle(); + builder3.request.ReleaseSessionHandle(); EXPECT_TRUE(stream3); EXPECT_TRUE(stream3->IsConnected()); #if BUILDFLAG(IS_ANDROID) @@ -15034,29 +13639,21 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream to trigger creation of the session. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Ensure that the session is alive and active before we read the error. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Resume the socket data to get the read error delivered. socket_data.Resume(); // Ensure that the session is no longer active. - EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveSession(kDefaultDestination)); } TEST_P(QuicSessionPoolTest, MessageTooBigReadErrorDoesNotCloseConnection) { @@ -15071,29 +13668,21 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream to trigger creation of the session. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Ensure that the session is alive and active before we read the error. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Resume the socket data to get the read error delivered. socket_data.Resume(); // Ensure that the session is still active. - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); } TEST_P(QuicSessionPoolTest, ZeroLengthReadDoesNotCloseConnection) { @@ -15108,36 +13697,28 @@ socket_data.AddSocketDataToFactory(socket_factory_.get()); // Create request and QuicHttpStream to trigger creation of the session. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); // Ensure that the session is alive and active before we read the error. - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); EXPECT_TRUE(QuicSessionPoolPeer::IsLiveSession(factory_.get(), session)); - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); // Resume the socket data to get the zero-length read delivered. socket_data.Resume(); // Ensure that the session is still active. - EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveSession(kDefaultDestination)); } TEST_P(QuicSessionPoolTest, DnsAliasesCanBeAccessedFromStream) { std::vector<std::string> dns_aliases( - {"alias1", "alias2", scheme_host_port_.host()}); + {"alias1", "alias2", kDefaultServerHostName}); host_resolver_->rules()->AddIPLiteralRuleWithDnsAliases( - scheme_host_port_.host(), "192.168.0.1", std::move(dns_aliases)); + kDefaultServerHostName, "192.168.0.1", std::move(dns_aliases)); Initialize(); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); @@ -15148,58 +13729,10 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); - EXPECT_TRUE(stream.get()); - - EXPECT_EQ(DEFAULT_PRIORITY, host_resolver_->last_request_priority()); - - EXPECT_TRUE(socket_data.AllReadDataConsumed()); - EXPECT_TRUE(socket_data.AllWriteDataConsumed()); - - EXPECT_THAT( - stream->GetDnsAliases(), - testing::ElementsAre("alias1", "alias2", scheme_host_port_.host())); -} - -TEST_P(QuicSessionPoolTest, NoAdditionalDnsAliases) { - std::vector<std::string> dns_aliases; - host_resolver_->rules()->AddIPLiteralRuleWithDnsAliases( - scheme_host_port_.host(), "192.168.0.1", std::move(dns_aliases)); - - Initialize(); - ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); - crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); - - MockQuicData socket_data(version_); - socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); - socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); - socket_data.AddSocketDataToFactory(socket_factory_.get()); - - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - - EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); EXPECT_EQ(DEFAULT_PRIORITY, host_resolver_->last_request_priority()); @@ -15208,13 +13741,42 @@ EXPECT_TRUE(socket_data.AllWriteDataConsumed()); EXPECT_THAT(stream->GetDnsAliases(), - testing::ElementsAre(scheme_host_port_.host())); + testing::ElementsAre("alias1", "alias2", kDefaultServerHostName)); +} + +TEST_P(QuicSessionPoolTest, NoAdditionalDnsAliases) { + std::vector<std::string> dns_aliases; + host_resolver_->rules()->AddIPLiteralRuleWithDnsAliases( + kDefaultServerHostName, "192.168.0.1", std::move(dns_aliases)); + + Initialize(); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + MockQuicData socket_data(version_); + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); + EXPECT_THAT(callback_.WaitForResult(), IsOk()); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); + EXPECT_TRUE(stream.get()); + + EXPECT_EQ(DEFAULT_PRIORITY, host_resolver_->last_request_priority()); + + EXPECT_TRUE(socket_data.AllReadDataConsumed()); + EXPECT_TRUE(socket_data.AllWriteDataConsumed()); + + EXPECT_THAT(stream->GetDnsAliases(), + testing::ElementsAre(kDefaultServerHostName)); } TEST_P(QuicSessionPoolTest, DoNotUseDnsAliases) { std::vector<std::string> dns_aliases({"alias1", "alias2"}); host_resolver_->rules()->AddIPLiteralRuleWithDnsAliases( - scheme_host_port_.host(), "192.168.0.1", std::move(dns_aliases)); + kDefaultServerHostName, "192.168.0.1", std::move(dns_aliases)); Initialize(); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); @@ -15227,19 +13789,11 @@ // By indicating that this is a request to a proxy server, DNS aliasing will // not be performed. - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kProxy, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + builder.session_usage = SessionUsage::kProxy; + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream = CreateStream(&request); + std::unique_ptr<HttpStream> stream = CreateStream(&builder.request); EXPECT_TRUE(stream.get()); EXPECT_EQ(DEFAULT_PRIORITY, host_resolver_->last_request_priority()); @@ -15253,7 +13807,7 @@ TEST_P(QuicSessionPoolTest, ConnectErrorInCreateWithDnsAliases) { std::vector<std::string> dns_aliases({"alias1", "alias2"}); host_resolver_->rules()->AddIPLiteralRuleWithDnsAliases( - scheme_host_port_.host(), "192.168.0.1", std::move(dns_aliases)); + kDefaultServerHostName, "192.168.0.1", std::move(dns_aliases)); Initialize(); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); @@ -15263,17 +13817,8 @@ socket_data.AddConnect(SYNCHRONOUS, ERR_ADDRESS_IN_USE); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsError(ERR_ADDRESS_IN_USE)); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -15344,10 +13889,10 @@ quic_params_->supported_versions = {version_}; host_resolver_ = std::make_unique<MockHostResolver>(); host_resolver_->rules()->AddRule( - scheme_host_port_.host(), + kDefaultServerHostName, MockHostResolverBase::RuleResolver::RuleResult( std::move(endpoints), - /*aliases=*/std::set<std::string>{scheme_host_port_.host()})); + /*aliases=*/std::set<std::string>{kDefaultServerHostName})); Initialize(); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); @@ -15358,17 +13903,10 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, quic::ParsedQuicVersion::Unsupported(), - ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/true, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + builder.quic_version = quic::ParsedQuicVersion::Unsupported(); + builder.require_dns_https_alpn = true; + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); if (expect_success) { EXPECT_THAT(callback_.WaitForResult(), IsOk()); } else { @@ -15528,43 +14066,34 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request1(factory_.get()); SessionUsage session_usage; if (use_dns_aliases_) { session_usage = SessionUsage::kDestination; } else { session_usage = SessionUsage::kProxy; } - EXPECT_EQ(ERR_IO_PENDING, - request1.Request( - kOrigin1, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, session_usage, privacy_mode_, - DEFAULT_PRIORITY, SocketTag(), NetworkAnonymizationKey(), - SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, /*cert_verify_flags=*/0, - kUrl1, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder1(this); + builder1.destination = kOrigin1; + builder1.session_usage = session_usage; + builder1.url = kUrl1; + EXPECT_EQ(ERR_IO_PENDING, builder1.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream1 = CreateStream(&request1); + std::unique_ptr<HttpStream> stream1 = CreateStream(&builder1.request); EXPECT_TRUE(stream1.get()); EXPECT_TRUE(HasActiveSession(kOrigin1, NetworkAnonymizationKey(), ProxyChain::Direct(), session_usage)); TestCompletionCallback callback2; - QuicSessionRequest request2(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request2.Request( - kOrigin2, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, session_usage, privacy_mode_, - DEFAULT_PRIORITY, SocketTag(), NetworkAnonymizationKey(), - SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, /*cert_verify_flags=*/0, - kUrl2, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback2.callback())); + RequestBuilder builder2(this); + builder2.destination = kOrigin2; + builder2.session_usage = session_usage; + builder2.url = kUrl2; + builder2.callback = callback2.callback(); + EXPECT_EQ(ERR_IO_PENDING, builder2.CallRequest()); EXPECT_THAT(callback2.WaitForResult(), IsOk()); - std::unique_ptr<HttpStream> stream2 = CreateStream(&request2); + std::unique_ptr<HttpStream> stream2 = CreateStream(&builder2.request); EXPECT_TRUE(stream2.get()); EXPECT_TRUE(HasActiveSession(kOrigin2, NetworkAnonymizationKey(), ProxyChain::Direct(), session_usage)); @@ -15576,7 +14105,7 @@ EXPECT_TRUE(session1->SharesSameSession(*session2)); EXPECT_EQ(quic::QuicServerId(kOrigin1.host(), kOrigin1.port(), - privacy_mode_ == PRIVACY_MODE_ENABLED), + /*privacy_mode_enabled=*/false), session1->server_id()); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -15597,20 +14126,11 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); - + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); ASSERT_TRUE(session); quic::QuicSSLConfig config = session->GetSSLConfig(); EXPECT_TRUE(config.ech_grease_enabled); @@ -15627,7 +14147,7 @@ host_resolver_ = std::make_unique<MockHostResolver>(); host_resolver_->rules()->AddRule( - scheme_host_port_.host(), + kDefaultServerHostName, MockHostResolverBase::RuleResolver::RuleResult({endpoint})); Initialize(); @@ -15639,19 +14159,11 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); ASSERT_THAT(callback_.WaitForResult(), IsOk()); - QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + QuicChromiumClientSession* session = GetActiveSession(kDefaultDestination); ASSERT_TRUE(session); quic::QuicSSLConfig config = session->GetSSLConfig(); EXPECT_EQ(std::string(endpoint.metadata.ech_config_list.begin(), @@ -15670,7 +14182,7 @@ host_resolver_ = std::make_unique<MockHostResolver>(); host_resolver_->rules()->AddRule( - scheme_host_port_.host(), + kDefaultServerHostName, MockHostResolverBase::RuleResolver::RuleResult({endpoint})); Initialize(); @@ -15682,20 +14194,14 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, quic::ParsedQuicVersion::Unsupported(), - ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/true, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + builder.quic_version = quic::ParsedQuicVersion::Unsupported(); + builder.require_dns_https_alpn = true; + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); ASSERT_THAT(callback_.WaitForResult(), IsOk()); QuicChromiumClientSession* session = - GetActiveSession(scheme_host_port_, NetworkAnonymizationKey(), + GetActiveSession(kDefaultDestination, NetworkAnonymizationKey(), /*require_dns_https_alpn=*/true); ASSERT_TRUE(session); quic::QuicSSLConfig config = session->GetSSLConfig(); @@ -15714,7 +14220,7 @@ host_resolver_ = std::make_unique<MockHostResolver>(); host_resolver_->rules()->AddRule( - scheme_host_port_.host(), + kDefaultServerHostName, MockHostResolverBase::RuleResolver::RuleResult({endpoint})); SSLContextConfig ssl_config; @@ -15730,20 +14236,14 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, quic::ParsedQuicVersion::Unsupported(), - ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS, - SessionUsage::kDestination, privacy_mode_, DEFAULT_PRIORITY, - SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/true, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + builder.quic_version = quic::ParsedQuicVersion::Unsupported(); + builder.require_dns_https_alpn = true; + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); ASSERT_THAT(callback_.WaitForResult(), IsOk()); QuicChromiumClientSession* session = - GetActiveSession(scheme_host_port_, NetworkAnonymizationKey(), + GetActiveSession(kDefaultDestination, NetworkAnonymizationKey(), /*require_dns_https_alpn=*/true); ASSERT_TRUE(session); quic::QuicSSLConfig config = session->GetSSLConfig(); @@ -15765,7 +14265,7 @@ host_resolver_ = std::make_unique<MockHostResolver>(); host_resolver_->rules()->AddRule( - scheme_host_port_.host(), + kDefaultServerHostName, MockHostResolverBase::RuleResolver::RuleResult(std::move(endpoints))); Initialize(); @@ -15777,16 +14277,8 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsError(ERR_DNS_NO_MATCHING_SUPPORTED_ALPN)); } @@ -15804,7 +14296,7 @@ host_resolver_ = std::make_unique<MockHostResolver>(); host_resolver_->rules()->AddRule( - scheme_host_port_.host(), + kDefaultServerHostName, MockHostResolverBase::RuleResolver::RuleResult(std::move(endpoints))); // But this client is not ECH-capable, so the connection should succeed. @@ -15821,16 +14313,8 @@ socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); socket_data.AddSocketDataToFactory(socket_factory_.get()); - QuicSessionRequest request(factory_.get()); - EXPECT_EQ(ERR_IO_PENDING, - request.Request( - scheme_host_port_, version_, ProxyChain::Direct(), - TRAFFIC_ANNOTATION_FOR_TESTS, SessionUsage::kDestination, - privacy_mode_, DEFAULT_PRIORITY, SocketTag(), - NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false, - /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, - failed_on_default_network_callback_, callback_.callback())); + RequestBuilder builder(this); + EXPECT_EQ(ERR_IO_PENDING, builder.CallRequest()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); }
diff --git a/sandbox/win/src/process_mitigations_unittest.cc b/sandbox/win/src/process_mitigations_unittest.cc index 47eab9b..bfdfebd 100644 --- a/sandbox/win/src/process_mitigations_unittest.cc +++ b/sandbox/win/src/process_mitigations_unittest.cc
@@ -717,9 +717,10 @@ // This test validates that setting the MITIGATION_FORCE_MS_SIGNED_BINS // mitigation enables the setting on a process when non-delayed. - -// Disabled due to crbug.com/1081080 -TEST(ProcessMitigationsTest, DISABLED_CheckWin10MsSignedPolicySuccess) { +TEST(ProcessMitigationsTest, CheckWin10MsSignedPolicySuccess) { + // AllowExtraDlls shims may run before ASAN has a chance to initialize its + // internal state, namely __asan_shadow_memory_dynamic_address. +#if !defined(ADDRESS_SANITIZER) if (base::win::GetVersion() < base::win::Version::WIN10_TH2) return; @@ -749,6 +750,96 @@ #endif // defined(COMPONENT_BUILD) EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(test_command.c_str())); +#endif // !defined(ADDRESS_SANITIZER) +} + +// This test attempts to load an unsigned dll, which should succeed only if +// allowed by the CIG shims, and validate that the MicrosoftSignedOnly CIG +// mitigation is applied. +SBOX_TESTS_COMMAND int TestMsSignedLoadUnsignedDll(int argc, wchar_t** argv) { + PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY policy = {}; + if (!::GetProcessMitigationPolicy(::GetCurrentProcess(), + ProcessSignaturePolicy, &policy, + sizeof(policy))) { + return SBOX_TEST_NOT_FOUND; + } + if (!policy.MicrosoftSignedOnly) { + return SBOX_TEST_FIRST_ERROR; + } + + base::FilePath hook_dll_path(hooking_dll::g_hook_dll_file); + base::ScopedNativeLibrary dll(hook_dll_path); + if (!dll.is_valid()) { + return SBOX_TEST_SECOND_ERROR; + } + + return SBOX_TEST_SUCCEEDED; +} + +// This test validates that setting the MITIGATION_FORCE_MS_SIGNED_BINS +// mitigation enables the setting on a process when non-delayed, and that +// process fails load a dll not signed by Microsoft. +TEST(ProcessMitigationsTest, CheckWin10MsSignedPolicyAndDllLoadFailure) { + // AllowExtraDlls shims may run before ASAN has a chance to initialize its + // internal state, namely __asan_shadow_memory_dynamic_address. + // With component build we would have to allow all DLLs to load, which + // invalidates the test. +#if !defined(ADDRESS_SANITIZER) && !defined(COMPONENT_BUILD) + if (base::win::GetVersion() < base::win::Version::WIN10_TH2) { + return; + } + + std::wstring test_command = L"TestMsSignedLoadUnsignedDll"; + + TestRunner runner; + // After the sandbox is applied, the sandbox will prevent DLL loads. CIG + // should prevent the DLL load as well. + runner.SetTestState(BEFORE_REVERT); + sandbox::TargetConfig* config = runner.GetPolicy()->GetConfig(); + + EXPECT_EQ(config->SetProcessMitigations(MITIGATION_FORCE_MS_SIGNED_BINS), + SBOX_ALL_OK); + + EXPECT_EQ(SBOX_TEST_SECOND_ERROR, runner.RunTest(test_command.c_str())); +#endif // !defined(ADDRESS_SANITIZER) && !defined(COMPONENT_BUILD) +} + +// This test validates that setting the MITIGATION_FORCE_MS_SIGNED_BINS +// mitigation enables the setting on a process when non-delayed, and that +// process can load a dll. +TEST(ProcessMitigationsTest, CheckWin10MsSignedPolicyAndDllLoadSuccess) { + // AllowExtraDlls shims may run before ASAN has a chance to initialize its + // internal state, namely __asan_shadow_memory_dynamic_address. +#if !defined(ADDRESS_SANITIZER) + if (base::win::GetVersion() < base::win::Version::WIN10_TH2) { + return; + } + + std::wstring test_command = L"TestMsSignedLoadUnsignedDll"; + + TestRunner runner; + // After the sandbox is applied, the sandbox will prevent DLL loads. Validate + // we can load a DLL specified in AllowExtraDlls before sandbox is applied. + runner.SetTestState(BEFORE_REVERT); + sandbox::TargetConfig* config = runner.GetPolicy()->GetConfig(); + + EXPECT_EQ(config->SetProcessMitigations(MITIGATION_FORCE_MS_SIGNED_BINS), + SBOX_ALL_OK); + // In a component build, allow all *.dll in current directory to load. On a + // release build, specify the name of the hooking dll that the test tries to + // load. + base::FilePath exe_path; + EXPECT_TRUE(base::PathService::Get(base::DIR_EXE, &exe_path)); + EXPECT_EQ(sandbox::SBOX_ALL_OK, + config->AllowExtraDlls( +#if defined(COMPONENT_BUILD) + exe_path.DirName().AppendASCII("*.dll").value().c_str())); +#else + exe_path.Append(hooking_dll::g_hook_dll_file).value().c_str())); +#endif + + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str())); +#endif // !defined(ADDRESS_SANITIZER) } //------------------------------------------------------------------------------
diff --git a/sandbox/win/src/sandbox_nt_util.cc b/sandbox/win/src/sandbox_nt_util.cc index 27942c9..41dcc5fc 100644 --- a/sandbox/win/src/sandbox_nt_util.cc +++ b/sandbox/win/src/sandbox_nt_util.cc
@@ -692,41 +692,6 @@ return true; } -bool NtGetPathFromHandle(HANDLE handle, - std::unique_ptr<wchar_t, NtAllocDeleter>* path) { - OBJECT_NAME_INFORMATION initial_buffer; - OBJECT_NAME_INFORMATION* name; - ULONG size = 0; - // Query the name information a first time to get the size of the name. - NTSTATUS status = GetNtExports()->QueryObject(handle, ObjectNameInformation, - &initial_buffer, size, &size); - - if (!NT_SUCCESS(status) && status != STATUS_INFO_LENGTH_MISMATCH) - return false; - - std::unique_ptr<BYTE[], NtAllocDeleter> name_ptr; - if (!size) - return false; - name_ptr.reset(new (NT_ALLOC) BYTE[size]); - name = reinterpret_cast<OBJECT_NAME_INFORMATION*>(name_ptr.get()); - - // Query the name information a second time to get the name of the - // object referenced by the handle. - status = GetNtExports()->QueryObject(handle, ObjectNameInformation, name, - size, &size); - - if (STATUS_SUCCESS != status) - return false; - size_t num_path_wchars = (name->ObjectName.Length / sizeof(wchar_t)) + 1; - path->reset(new (NT_ALLOC) wchar_t[num_path_wchars]); - status = - CopyData(path->get(), name->ObjectName.Buffer, name->ObjectName.Length); - path->get()[num_path_wchars - 1] = L'\0'; - if (STATUS_SUCCESS != status) - return false; - return true; -} - CLIENT_ID GetCurrentClientId() { return reinterpret_cast<PARTIAL_TEB*>(NtCurrentTeb())->ClientId; }
diff --git a/sandbox/win/src/sandbox_nt_util.h b/sandbox/win/src/sandbox_nt_util.h index 999c989..371f1719 100644 --- a/sandbox/win/src/sandbox_nt_util.h +++ b/sandbox/win/src/sandbox_nt_util.h
@@ -184,10 +184,6 @@ // Converts an ansi string to an UNICODE_STRING. UNICODE_STRING* AnsiToUnicode(const char* string); -// Resolves a handle to an nt path. Returns true if the handle can be resolved. -bool NtGetPathFromHandle(HANDLE handle, - std::unique_ptr<wchar_t, NtAllocDeleter>* path); - // Provides a simple way to temporarily change the protection of a memory page. class AutoProtectMemory { public: @@ -223,6 +219,14 @@ // Get the CLIENT_ID from the current TEB. CLIENT_ID GetCurrentClientId(); +// Version of memset that can be called before the CRT is initialized. +__forceinline void Memset(void* ptr, int value, size_t num_bytes) { + unsigned char* byte_ptr = static_cast<unsigned char*>(ptr); + while (num_bytes--) { + *byte_ptr++ = static_cast<unsigned char>(value); + } +} + } // namespace sandbox #endif // SANDBOX_WIN_SRC_SANDBOX_NT_UTIL_H_
diff --git a/sandbox/win/src/sandbox_nt_util_unittest.cc b/sandbox/win/src/sandbox_nt_util_unittest.cc index 86c0513..18bcc5f 100644 --- a/sandbox/win/src/sandbox_nt_util_unittest.cc +++ b/sandbox/win/src/sandbox_nt_util_unittest.cc
@@ -241,26 +241,6 @@ EXPECT_TRUE(verify_buffer()); } -TEST(SandboxNtUtil, NtGetPathFromHandle) { - base::FilePath exe; - ASSERT_TRUE(base::PathService::Get(base::FILE_EXE, &exe)); - base::File exe_file(exe, base::File::FLAG_OPEN); - ASSERT_TRUE(exe_file.IsValid()); - std::unique_ptr<wchar_t, NtAllocDeleter> path; - EXPECT_TRUE(NtGetPathFromHandle(exe_file.GetPlatformFile(), &path)); - - // Basic sanity test, the functionality of NtGetPathFromHandle to return - // the correct value is already tested from win_utils_unittest.cc. - EXPECT_TRUE(base::EndsWith(base::AsStringPiece16(path.get()), - base::AsStringPiece16(exe.BaseName().value()), - base::CompareCase::INSENSITIVE_ASCII)); - - // Compare to GetNtPathFromWin32Path for extra check. - auto nt_path = GetNtPathFromWin32Path(exe.value()); - EXPECT_TRUE(nt_path); - EXPECT_STREQ(path.get(), nt_path->c_str()); -} - TEST(SandboxNtUtil, CopyNameAndAttributes) { OBJECT_ATTRIBUTES object_attributes; InitializeObjectAttributes(&object_attributes, nullptr, 0, nullptr, nullptr);
diff --git a/sandbox/win/src/signed_interception.cc b/sandbox/win/src/signed_interception.cc index 25f636f..05581224d 100644 --- a/sandbox/win/src/signed_interception.cc +++ b/sandbox/win/src/signed_interception.cc
@@ -18,6 +18,9 @@ namespace sandbox { +// Note that this shim may be called before the heap is available, we must get +// as far as |QueryBroker| without using the heap, for example when AppVerifier +// is enabled. NTSTATUS WINAPI TargetNtCreateSection(NtCreateSectionFunction orig_CreateSection, PHANDLE section_handle, @@ -48,15 +51,25 @@ if (!memory) break; - std::unique_ptr<wchar_t, NtAllocDeleter> path; + // As mentioned at the top of the function, we need to use the stack here + // because the heap may not be available. + constexpr ULONG path_buffer_size = + (MAX_PATH * sizeof(wchar_t)) + sizeof(OBJECT_NAME_INFORMATION); + // Avoid memset inserted by -ftrivial-auto-var-init=pattern. + STACK_UNINITIALIZED char path_buffer[path_buffer_size]; + OBJECT_NAME_INFORMATION* path = + reinterpret_cast<OBJECT_NAME_INFORMATION*>(path_buffer); + ULONG out_buffer_size = 0; + NTSTATUS status = + GetNtExports()->QueryObject(file_handle, ObjectNameInformation, path, + path_buffer_size, &out_buffer_size); - if (!NtGetPathFromHandle(file_handle, &path)) + if (!NT_SUCCESS(status)) { break; - - const wchar_t* const_name = path.get(); + } CountedParameterSet<NameBased> params; - params[NameBased::NAME] = ParamPickerMake(const_name); + params[NameBased::NAME] = ParamPickerMake(path->ObjectName.Buffer); // Check if this will be sent to the broker. if (!QueryBroker(IpcTag::NTCREATESECTION, params.GetBase())) @@ -65,7 +78,10 @@ if (!ValidParameter(section_handle, sizeof(HANDLE), WRITE)) break; - CrossCallReturn answer = {0}; + // Avoid memset inserted by -ftrivial-auto-var-init=pattern on debug builds. + STACK_UNINITIALIZED CrossCallReturn answer; + Memset(&answer, 0, sizeof(answer)); + answer.nt_status = STATUS_INVALID_IMAGE_HASH; SharedMemIPCClient ipc(memory); ResultCode code =
diff --git a/sandbox/win/src/target_interceptions.cc b/sandbox/win/src/target_interceptions.cc index 0befe25..e6e5a94 100644 --- a/sandbox/win/src/target_interceptions.cc +++ b/sandbox/win/src/target_interceptions.cc
@@ -46,8 +46,6 @@ if (!IsSameProcess(process)) break; - // Only check for verifier.dll or kernel32.dll loading if we haven't moved - // past that state yet. if (s_state == kBeforeKernel32) { const char* ansi_module_name = GetAnsiImageInfoFromModule(reinterpret_cast<HMODULE>(*base)); @@ -56,17 +54,6 @@ // find what looks like a valid export directory for a PE module but the // pointer to the module name will be pointing to invalid memory. __try { - // Don't initialize the heap if verifier.dll is being loaded. This - // indicates Application Verifier is enabled and we should wait until - // the next module is loaded. - if (ansi_module_name && - (GetNtExports()->_strnicmp( - ansi_module_name, base::win::kApplicationVerifierDllName, - GetNtExports()->strlen( - base::win::kApplicationVerifierDllName) + - 1) == 0)) { - break; - } if (ansi_module_name && (GetNtExports()->_strnicmp(ansi_module_name, KERNEL32_DLL_NAME, sizeof(KERNEL32_DLL_NAME)) == 0)) { @@ -76,6 +63,12 @@ } } + // Assume the heap may not be initialized before kernel32 loads, which is + // the case when AppVerifier is enabled. + if (s_state == kBeforeKernel32) { + break; + } + if (!InitHeap()) break;
diff --git a/services/device/generic_sensor/platform_sensor.cc b/services/device/generic_sensor/platform_sensor.cc index 96505a4a..6bc7c60 100644 --- a/services/device/generic_sensor/platform_sensor.cc +++ b/services/device/generic_sensor/platform_sensor.cc
@@ -247,7 +247,7 @@ } } -bool PlatformSensor::is_active() const { +bool PlatformSensor::IsActiveForTesting() const { base::AutoLock auto_lock(lock_); return is_active_; }
diff --git a/services/device/generic_sensor/platform_sensor.h b/services/device/generic_sensor/platform_sensor.h index 17a2510c..c8d671d 100644 --- a/services/device/generic_sensor/platform_sensor.h +++ b/services/device/generic_sensor/platform_sensor.h
@@ -92,7 +92,7 @@ // Return the last raw (i.e. unrounded) sensor reading. bool GetLatestRawReading(SensorReading* result) const; // Returns 'true' if the sensor is started; returns 'false' otherwise. - bool is_active() const; + bool IsActiveForTesting() const; using ConfigMap = std::map<Client*, std::list<PlatformSensorConfiguration>>; const ConfigMap& GetConfigMapForTesting() const;
diff --git a/services/device/generic_sensor/platform_sensor_and_provider_unittest.cc b/services/device/generic_sensor/platform_sensor_and_provider_unittest.cc index 1e48b87..bd34bd8d 100644 --- a/services/device/generic_sensor/platform_sensor_and_provider_unittest.cc +++ b/services/device/generic_sensor/platform_sensor_and_provider_unittest.cc
@@ -258,11 +258,11 @@ auto client = std::make_unique<MockPlatformSensorClient>(fake_sensor); EXPECT_TRUE(fake_sensor->StartListening(client.get(), PlatformSensorConfiguration(10))); - EXPECT_TRUE(fake_sensor->is_active()); + EXPECT_TRUE(fake_sensor->IsActiveForTesting()); ON_CALL(*client, IsSuspended()).WillByDefault(Return(true)); fake_sensor->UpdateSensor(); - EXPECT_FALSE(fake_sensor->is_active()); + EXPECT_FALSE(fake_sensor->IsActiveForTesting()); SensorReading reading; reading.raw.timestamp = 1.0; @@ -272,7 +272,7 @@ ON_CALL(*client, IsSuspended()).WillByDefault(Return(false)); fake_sensor->UpdateSensor(); - EXPECT_TRUE(fake_sensor->is_active()); + EXPECT_TRUE(fake_sensor->IsActiveForTesting()); // Set the exact same readings. They should be stored because // |last_raw_reading_| and |last_rounded_reading_| should not have been
diff --git a/services/device/generic_sensor/platform_sensor_chromeos_unittest.cc b/services/device/generic_sensor/platform_sensor_chromeos_unittest.cc index f338dca..851e748 100644 --- a/services/device/generic_sensor/platform_sensor_chromeos_unittest.cc +++ b/services/device/generic_sensor/platform_sensor_chromeos_unittest.cc
@@ -170,7 +170,7 @@ sensor_->StartListening(client.get(), PlatformSensorConfiguration( GetSensorMaxAllowedFrequency(GetParam().first))); - EXPECT_TRUE(sensor_->is_active()); + EXPECT_TRUE(sensor_->IsActiveForTesting()); EXPECT_CALL(*client.get(), OnSensorReadingChanged(GetParam().first)).Times(0); // Wait until all tasks done and no samples updated. @@ -186,7 +186,7 @@ sensor_->AddClient(client.get()); double frequency = GetSensorMaxAllowedFrequency(GetParam().first); sensor_->StartListening(client.get(), PlatformSensorConfiguration(frequency)); - EXPECT_TRUE(sensor_->is_active()); + EXPECT_TRUE(sensor_->IsActiveForTesting()); WaitForAndCheckReading(client.get()); @@ -227,7 +227,7 @@ sensor_->StartListening(client.get(), PlatformSensorConfiguration( GetSensorMaxAllowedFrequency(GetParam().first))); - EXPECT_TRUE(sensor_->is_active()); + EXPECT_TRUE(sensor_->IsActiveForTesting()); WaitForAndCheckReading(client.get()); @@ -364,7 +364,7 @@ sensor_->StartListening(client.get(), PlatformSensorConfiguration( GetSensorMaxAllowedFrequency(GetParam().first))); - EXPECT_TRUE(sensor_->is_active()); + EXPECT_TRUE(sensor_->IsActiveForTesting()); EXPECT_CALL(*client.get(), OnSensorReadingChanged(GetParam().first)).Times(0); // Wait until all tasks done and no samples updated. @@ -380,7 +380,7 @@ sensor_->AddClient(client.get()); double frequency = GetSensorMaxAllowedFrequency(GetParam().first); sensor_->StartListening(client.get(), PlatformSensorConfiguration(frequency)); - EXPECT_TRUE(sensor_->is_active()); + EXPECT_TRUE(sensor_->IsActiveForTesting()); WaitForAndCheckReading(client.get());
diff --git a/services/device/generic_sensor/platform_sensor_fusion_unittest.cc b/services/device/generic_sensor/platform_sensor_fusion_unittest.cc index b457c0530..0fdc0d8f 100644 --- a/services/device/generic_sensor/platform_sensor_fusion_unittest.cc +++ b/services/device/generic_sensor/platform_sensor_fusion_unittest.cc
@@ -194,29 +194,29 @@ TEST_F(PlatformSensorFusionTest, SourceSensorWorksSeparately) { CreateAccelerometer(); EXPECT_TRUE(accelerometer_); - EXPECT_FALSE(accelerometer_->is_active()); + EXPECT_FALSE(accelerometer_->IsActiveForTesting()); auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>(); accelerometer_->AddClient(client.get()); accelerometer_->StartListening(client.get(), PlatformSensorConfiguration(10)); - EXPECT_TRUE(accelerometer_->is_active()); + EXPECT_TRUE(accelerometer_->IsActiveForTesting()); CreateLinearAccelerationFusionSensor(); EXPECT_TRUE(fusion_sensor_); EXPECT_EQ(SensorType::LINEAR_ACCELERATION, fusion_sensor_->GetType()); - EXPECT_FALSE(fusion_sensor_->is_active()); + EXPECT_FALSE(fusion_sensor_->IsActiveForTesting()); fusion_sensor_->AddClient(client.get()); fusion_sensor_->StartListening(client.get(), PlatformSensorConfiguration(10)); - EXPECT_TRUE(fusion_sensor_->is_active()); + EXPECT_TRUE(fusion_sensor_->IsActiveForTesting()); fusion_sensor_->StopListening(client.get(), PlatformSensorConfiguration(10)); - EXPECT_FALSE(fusion_sensor_->is_active()); + EXPECT_FALSE(fusion_sensor_->IsActiveForTesting()); - EXPECT_TRUE(accelerometer_->is_active()); + EXPECT_TRUE(accelerometer_->IsActiveForTesting()); accelerometer_->RemoveClient(client.get()); - EXPECT_FALSE(accelerometer_->is_active()); + EXPECT_FALSE(accelerometer_->IsActiveForTesting()); fusion_sensor_->RemoveClient(client.get()); } @@ -289,9 +289,9 @@ fusion_sensor_); fusion_sensor_->StartListening(client.get(), PlatformSensorConfiguration(10)); - EXPECT_FALSE(fusion_sensor_->is_active()); - EXPECT_FALSE(accelerometer_->is_active()); - EXPECT_FALSE(magnetometer_->is_active()); + EXPECT_FALSE(fusion_sensor_->IsActiveForTesting()); + EXPECT_FALSE(accelerometer_->IsActiveForTesting()); + EXPECT_FALSE(magnetometer_->IsActiveForTesting()); } TEST_F(PlatformSensorFusionTest, SourceSensorNeedsToBeCreated) {
diff --git a/services/device/generic_sensor/virtual_platform_sensor.cc b/services/device/generic_sensor/virtual_platform_sensor.cc index bc6b1c3..3524d13 100644 --- a/services/device/generic_sensor/virtual_platform_sensor.cc +++ b/services/device/generic_sensor/virtual_platform_sensor.cc
@@ -21,7 +21,7 @@ minimum_supported_frequency_(metadata.minimum_frequency), maximum_supported_frequency_(metadata.maximum_frequency), reporting_mode_(metadata.reporting_mode), - pending_reading_(std::move(pending_reading)) {} + current_reading_(std::move(pending_reading)) {} VirtualPlatformSensor::~VirtualPlatformSensor() = default; @@ -41,12 +41,8 @@ } void VirtualPlatformSensor::DoAddReadingSync(const SensorReading& reading) { - if (is_active()) { - UpdateSharedBufferAndNotifyClients(reading); - pending_reading_.reset(); - } else { - pending_reading_ = reading; - } + current_reading_ = reading; + UpdateSharedBufferAndNotifyClients(reading); } void VirtualPlatformSensor::SimulateSensorRemoval() { @@ -60,8 +56,8 @@ bool VirtualPlatformSensor::StartSensor( const PlatformSensorConfiguration& optimal_configuration) { optimal_configuration_ = optimal_configuration; - if (pending_reading_.has_value()) { - AddReading(*pending_reading_); + if (current_reading_.has_value()) { + AddReading(*current_reading_); } return true; }
diff --git a/services/device/generic_sensor/virtual_platform_sensor.h b/services/device/generic_sensor/virtual_platform_sensor.h index 7146066..1c76328 100644 --- a/services/device/generic_sensor/virtual_platform_sensor.h +++ b/services/device/generic_sensor/virtual_platform_sensor.h
@@ -18,6 +18,14 @@ // OS-agnostic PlatformSensor implementation used in (web) tests. New instances // are created by VirtualPlatformSensorProvider via GetSensor() calls. +// +// A VirtualPlatformSensor respects two invariants when it comes to readings +// added in the constructor or with AddReading(): +// 1. Once a reading is set, it will remain set until it is replaced with +// another reading. +// 2. Said reading will be added to the shared buffer (which may choose to +// ignore it) and, on success, clients will be notified whenever the sensor +// is activated (i.e. StartSensor() is called). class VirtualPlatformSensor : public PlatformSensor { public: VirtualPlatformSensor(mojom::SensorType type, @@ -69,7 +77,14 @@ std::optional<PlatformSensorConfiguration> optimal_configuration_; std::optional<mojom::ReportingMode> reporting_mode_; - std::optional<SensorReading> pending_reading_; + // The latest reading passed to this sensor by either the constructor or + // AddReading(). + // + // It may or may not be stored into the shared buffer by + // PlatformSensor depending on e.g. whether the sensor is active, + // rounding/threshold checks etc. Nonetheless, it remains saved and will be + // added again once StartSensor() is called. + std::optional<SensorReading> current_reading_; base::WeakPtrFactory<VirtualPlatformSensor> weak_ptr_factory_{this}; };
diff --git a/services/device/generic_sensor/virtual_platform_sensor_provider.cc b/services/device/generic_sensor/virtual_platform_sensor_provider.cc index ad5a5ab..477b2a0 100644 --- a/services/device/generic_sensor/virtual_platform_sensor_provider.cc +++ b/services/device/generic_sensor/virtual_platform_sensor_provider.cc
@@ -110,11 +110,8 @@ return; } - std::optional<SensorReading> pending_reading; - metadata->pending_reading.swap(pending_reading); - auto sensor = base::MakeRefCounted<VirtualPlatformSensor>( - type, reading_buffer, this, std::move(pending_reading), + type, reading_buffer, this, metadata->pending_reading, *metadata->mojo_metadata); std::move(callback).Run(std::move(sensor)); }
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json index 553b00c1..7b9eb0a 100644 --- a/testing/buildbot/chrome.json +++ b/testing/buildbot/chrome.json
@@ -1964,7 +1964,7 @@ { "autotest_name": "chromium", "cros_board": "brya", - "cros_img": "brya-release/R121-15699.40.0", + "cros_img": "brya-release/R121-15699.54.0", "dut_pool": "chrome", "name": "chromeos_integration_tests BRYA_RELEASE_BETA", "test": "chromeos_integration_tests", @@ -1974,7 +1974,7 @@ { "autotest_name": "chromium", "cros_board": "brya", - "cros_img": "brya-release/R122-15748.0.0", + "cros_img": "brya-release/R123-15770.0.0", "dut_pool": "chrome", "name": "chromeos_integration_tests BRYA_RELEASE_DEV", "test": "chromeos_integration_tests", @@ -1994,7 +1994,7 @@ { "autotest_name": "chromium", "cros_board": "brya", - "cros_img": "brya-release/R120-15662.76.0", + "cros_img": "brya-release/R121-15699.58.0", "dut_pool": "chrome", "name": "chromeos_integration_tests BRYA_RELEASE_STABLE", "test": "chromeos_integration_tests", @@ -2004,7 +2004,7 @@ { "autotest_name": "chromium", "cros_board": "fizz", - "cros_img": "fizz-release/R121-15699.40.0", + "cros_img": "fizz-release/R122-15753.13.0", "dut_pool": "chrome", "name": "chromeos_integration_tests FIZZ_RELEASE_BETA", "test": "chromeos_integration_tests", @@ -2014,7 +2014,7 @@ { "autotest_name": "chromium", "cros_board": "fizz", - "cros_img": "fizz-release/R122-15748.0.0", + "cros_img": "fizz-release/R123-15770.0.0", "dut_pool": "chrome", "name": "chromeos_integration_tests FIZZ_RELEASE_DEV", "test": "chromeos_integration_tests", @@ -2034,7 +2034,7 @@ { "autotest_name": "chromium", "cros_board": "fizz", - "cros_img": "fizz-release/R120-15662.76.0", + "cros_img": "fizz-release/R121-15699.58.0", "dut_pool": "chrome", "name": "chromeos_integration_tests FIZZ_RELEASE_STABLE", "test": "chromeos_integration_tests", @@ -2044,7 +2044,7 @@ { "autotest_name": "chromium", "cros_board": "guybrush", - "cros_img": "guybrush-release/R121-15699.40.0", + "cros_img": "guybrush-release/R122-15753.13.0", "dut_pool": "chrome", "name": "chromeos_integration_tests GUYBRUSH_RELEASE_BETA", "test": "chromeos_integration_tests", @@ -2054,7 +2054,7 @@ { "autotest_name": "chromium", "cros_board": "guybrush", - "cros_img": "guybrush-release/R122-15748.0.0", + "cros_img": "guybrush-release/R123-15770.0.0", "dut_pool": "chrome", "name": "chromeos_integration_tests GUYBRUSH_RELEASE_DEV", "test": "chromeos_integration_tests", @@ -2074,7 +2074,7 @@ { "autotest_name": "chromium", "cros_board": "guybrush", - "cros_img": "guybrush-release/R120-15662.76.0", + "cros_img": "guybrush-release/R121-15699.58.0", "dut_pool": "chrome", "name": "chromeos_integration_tests GUYBRUSH_RELEASE_STABLE", "test": "chromeos_integration_tests", @@ -2084,7 +2084,7 @@ { "autotest_name": "chromium", "cros_board": "puff", - "cros_img": "puff-release/R121-15699.40.0", + "cros_img": "puff-release/R122-15753.13.0", "dut_pool": "chrome", "name": "chromeos_integration_tests PUFF_RELEASE_BETA", "test": "chromeos_integration_tests", @@ -2094,7 +2094,7 @@ { "autotest_name": "chromium", "cros_board": "puff", - "cros_img": "puff-release/R122-15748.0.0", + "cros_img": "puff-release/R123-15770.0.0", "dut_pool": "chrome", "name": "chromeos_integration_tests PUFF_RELEASE_DEV", "test": "chromeos_integration_tests", @@ -2114,7 +2114,7 @@ { "autotest_name": "chromium", "cros_board": "puff", - "cros_img": "puff-release/R120-15662.76.0", + "cros_img": "puff-release/R121-15699.58.0", "dut_pool": "chrome", "name": "chromeos_integration_tests PUFF_RELEASE_STABLE", "test": "chromeos_integration_tests", @@ -2124,7 +2124,7 @@ { "autotest_name": "tast.lacros-from-gcs", "cros_board": "brya", - "cros_img": "brya-release/R121-15699.40.0", + "cros_img": "brya-release/R121-15699.54.0", "dut_pool": "chrome", "name": "lacros_all_tast_tests BRYA_RELEASE_BETA", "resultdb": { @@ -2142,7 +2142,7 @@ { "autotest_name": "tast.lacros-from-gcs", "cros_board": "brya", - "cros_img": "brya-release/R122-15748.0.0", + "cros_img": "brya-release/R123-15770.0.0", "dut_pool": "chrome", "name": "lacros_all_tast_tests BRYA_RELEASE_DEV", "resultdb": { @@ -2178,7 +2178,7 @@ { "autotest_name": "tast.lacros-from-gcs", "cros_board": "brya", - "cros_img": "brya-release/R120-15662.76.0", + "cros_img": "brya-release/R121-15699.58.0", "dut_pool": "chrome", "name": "lacros_all_tast_tests BRYA_RELEASE_STABLE", "resultdb": { @@ -2196,7 +2196,7 @@ { "autotest_name": "tast.lacros-from-gcs", "cros_board": "fizz", - "cros_img": "fizz-release/R121-15699.40.0", + "cros_img": "fizz-release/R122-15753.13.0", "dut_pool": "chrome", "name": "lacros_all_tast_tests FIZZ_RELEASE_BETA", "resultdb": { @@ -2214,7 +2214,7 @@ { "autotest_name": "tast.lacros-from-gcs", "cros_board": "fizz", - "cros_img": "fizz-release/R122-15748.0.0", + "cros_img": "fizz-release/R123-15770.0.0", "dut_pool": "chrome", "name": "lacros_all_tast_tests FIZZ_RELEASE_DEV", "resultdb": { @@ -2250,7 +2250,7 @@ { "autotest_name": "tast.lacros-from-gcs", "cros_board": "fizz", - "cros_img": "fizz-release/R120-15662.76.0", + "cros_img": "fizz-release/R121-15699.58.0", "dut_pool": "chrome", "name": "lacros_all_tast_tests FIZZ_RELEASE_STABLE", "resultdb": { @@ -2268,7 +2268,7 @@ { "autotest_name": "tast.lacros-from-gcs", "cros_board": "guybrush", - "cros_img": "guybrush-release/R121-15699.40.0", + "cros_img": "guybrush-release/R122-15753.13.0", "dut_pool": "chrome", "name": "lacros_all_tast_tests GUYBRUSH_RELEASE_BETA", "resultdb": { @@ -2286,7 +2286,7 @@ { "autotest_name": "tast.lacros-from-gcs", "cros_board": "guybrush", - "cros_img": "guybrush-release/R122-15748.0.0", + "cros_img": "guybrush-release/R123-15770.0.0", "dut_pool": "chrome", "name": "lacros_all_tast_tests GUYBRUSH_RELEASE_DEV", "resultdb": { @@ -2322,7 +2322,7 @@ { "autotest_name": "tast.lacros-from-gcs", "cros_board": "guybrush", - "cros_img": "guybrush-release/R120-15662.76.0", + "cros_img": "guybrush-release/R121-15699.58.0", "dut_pool": "chrome", "name": "lacros_all_tast_tests GUYBRUSH_RELEASE_STABLE", "resultdb": { @@ -2340,7 +2340,7 @@ { "autotest_name": "tast.lacros-from-gcs", "cros_board": "puff", - "cros_img": "puff-release/R121-15699.40.0", + "cros_img": "puff-release/R122-15753.13.0", "dut_pool": "chrome", "name": "lacros_all_tast_tests PUFF_RELEASE_BETA", "resultdb": { @@ -2358,7 +2358,7 @@ { "autotest_name": "tast.lacros-from-gcs", "cros_board": "puff", - "cros_img": "puff-release/R122-15748.0.0", + "cros_img": "puff-release/R123-15770.0.0", "dut_pool": "chrome", "name": "lacros_all_tast_tests PUFF_RELEASE_DEV", "resultdb": { @@ -2394,7 +2394,7 @@ { "autotest_name": "tast.lacros-from-gcs", "cros_board": "puff", - "cros_img": "puff-release/R120-15662.76.0", + "cros_img": "puff-release/R121-15699.58.0", "dut_pool": "chrome", "name": "lacros_all_tast_tests PUFF_RELEASE_STABLE", "resultdb": {
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index b34e3b66..9b18176 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -5311,9 +5311,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6289.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6288.0", + "description": "Run with ash-chrome version 123.0.6289.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5323,8 +5323,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6288.0", - "revision": "version:123.0.6288.0" + "location": "lacros_version_skew_tests_v123.0.6289.0", + "revision": "version:123.0.6289.0" } ], "dimensions": { @@ -5467,9 +5467,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6289.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6288.0", + "description": "Run with ash-chrome version 123.0.6289.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5479,8 +5479,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6288.0", - "revision": "version:123.0.6288.0" + "location": "lacros_version_skew_tests_v123.0.6289.0", + "revision": "version:123.0.6289.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json index 40b112c..bb12831 100644 --- a/testing/buildbot/chromium.coverage.json +++ b/testing/buildbot/chromium.coverage.json
@@ -20464,9 +20464,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6289.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6288.0", + "description": "Run with ash-chrome version 123.0.6289.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -20476,8 +20476,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6288.0", - "revision": "version:123.0.6288.0" + "location": "lacros_version_skew_tests_v123.0.6289.0", + "revision": "version:123.0.6289.0" } ], "dimensions": { @@ -20614,9 +20614,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6289.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6288.0", + "description": "Run with ash-chrome version 123.0.6289.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -20626,8 +20626,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6288.0", - "revision": "version:123.0.6288.0" + "location": "lacros_version_skew_tests_v123.0.6289.0", + "revision": "version:123.0.6289.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 75956db..ef5bd610 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -41458,9 +41458,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6289.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6288.0", + "description": "Run with ash-chrome version 123.0.6289.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41469,8 +41469,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6288.0", - "revision": "version:123.0.6288.0" + "location": "lacros_version_skew_tests_v123.0.6289.0", + "revision": "version:123.0.6289.0" } ], "dimensions": { @@ -41608,9 +41608,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6289.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6288.0", + "description": "Run with ash-chrome version 123.0.6289.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41619,8 +41619,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6288.0", - "revision": "version:123.0.6288.0" + "location": "lacros_version_skew_tests_v123.0.6289.0", + "revision": "version:123.0.6289.0" } ], "dimensions": { @@ -42940,9 +42940,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6289.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6288.0", + "description": "Run with ash-chrome version 123.0.6289.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -42951,8 +42951,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6288.0", - "revision": "version:123.0.6288.0" + "location": "lacros_version_skew_tests_v123.0.6289.0", + "revision": "version:123.0.6289.0" } ], "dimensions": { @@ -43090,9 +43090,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6289.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 123.0.6288.0", + "description": "Run with ash-chrome version 123.0.6289.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -43101,8 +43101,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6288.0", - "revision": "version:123.0.6288.0" + "location": "lacros_version_skew_tests_v123.0.6289.0", + "revision": "version:123.0.6289.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index f1ee887..973fdc89 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -16507,12 +16507,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6289.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 123.0.6288.0", + "description": "Run with ash-chrome version 123.0.6289.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -16522,8 +16522,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6288.0", - "revision": "version:123.0.6288.0" + "location": "lacros_version_skew_tests_v123.0.6289.0", + "revision": "version:123.0.6289.0" } ], "dimensions": { @@ -16683,12 +16683,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6289.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 123.0.6288.0", + "description": "Run with ash-chrome version 123.0.6289.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -16698,8 +16698,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v123.0.6288.0", - "revision": "version:123.0.6288.0" + "location": "lacros_version_skew_tests_v123.0.6289.0", + "revision": "version:123.0.6289.0" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index 834d261e..02031bf 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -1474,7 +1474,7 @@ "dimensions": { "cpu": "x86-64", "gpu": "1002:6821-4.0.20-3.2.8", - "os": "Mac-12.6.1", + "os": "Mac-12", "pool": "chrome.tests.perf", "synthetic_product_name": "MacBookPro11,5_x86-64-i7-4870HQ_AMD Radeon R8 M370X 4.0.20 [3.2.8]_Intel Haswell Iris Pro Graphics 5200 4.0.20 [3.2.8]_16384_APPLE SSD SM0512G" }, @@ -1531,7 +1531,7 @@ "dimensions": { "cpu": "x86-64", "gpu": "8086:1626", - "os": "Mac-12.6.1", + "os": "Mac-12", "pool": "chrome.tests.perf", "synthetic_product_name": "MacBookAir7,2_x86-64-i5-5350U_Intel Broadwell HD Graphics 6000_8192_APPLE SSD SM0128G" }, @@ -1576,7 +1576,7 @@ "dimensions": { "cpu": "x86-64", "gpu": "8086:1626", - "os": "Mac-12.6.1", + "os": "Mac-12", "pool": "chrome.tests.perf", "synthetic_product_name": "MacBookAir7,2_x86-64-i5-5350U_Intel Broadwell HD Graphics 6000_8192_APPLE SSD SM0128G" },
diff --git a/testing/buildbot/chromium.perf.pinpoint.json b/testing/buildbot/chromium.perf.pinpoint.json index 1ac12fe2..96c1f1f 100644 --- a/testing/buildbot/chromium.perf.pinpoint.json +++ b/testing/buildbot/chromium.perf.pinpoint.json
@@ -1136,7 +1136,7 @@ "dimensions": { "cpu": "x86-64", "gpu": "1002:6821-4.0.20-3.2.8", - "os": "Mac-12.6.1", + "os": "Mac-12", "pool": "chrome.tests.perf", "synthetic_product_name": "MacBookPro11,5_x86-64-i7-4870HQ_AMD Radeon R8 M370X 4.0.20 [3.2.8]_Intel Haswell Iris Pro Graphics 5200 4.0.20 [3.2.8]_16384_APPLE SSD SM0512G" }, @@ -1193,7 +1193,7 @@ "dimensions": { "cpu": "x86-64", "gpu": "8086:1626", - "os": "Mac-12.6.1", + "os": "Mac-12", "pool": "chrome.tests.perf", "synthetic_product_name": "MacBookAir7,2_x86-64-i5-5350U_Intel Broadwell HD Graphics 6000_8192_APPLE SSD SM0128G" }, @@ -1238,7 +1238,7 @@ "dimensions": { "cpu": "x86-64", "gpu": "8086:1626", - "os": "Mac-12.6.1", + "os": "Mac-12", "pool": "chrome.tests.perf", "synthetic_product_name": "MacBookAir7,2_x86-64-i5-5350U_Intel Broadwell HD Graphics 6000_8192_APPLE SSD SM0128G" },
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index f4ef9ab9..7d6c4a1 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -23,7 +23,7 @@ 'identifier': 'BRYA_RELEASE_BETA', 'skylab': { 'cros_board': 'brya', - 'cros_img': 'brya-release/R121-15699.40.0', + 'cros_img': 'brya-release/R121-15699.54.0', 'dut_pool': 'chrome', }, }, @@ -31,7 +31,7 @@ 'identifier': 'BRYA_RELEASE_DEV', 'skylab': { 'cros_board': 'brya', - 'cros_img': 'brya-release/R122-15748.0.0', + 'cros_img': 'brya-release/R123-15770.0.0', 'dut_pool': 'chrome', }, }, @@ -47,7 +47,7 @@ 'identifier': 'BRYA_RELEASE_STABLE', 'skylab': { 'cros_board': 'brya', - 'cros_img': 'brya-release/R120-15662.76.0', + 'cros_img': 'brya-release/R121-15699.58.0', 'dut_pool': 'chrome', }, }, @@ -55,7 +55,7 @@ 'identifier': 'FIZZ_RELEASE_BETA', 'skylab': { 'cros_board': 'fizz', - 'cros_img': 'fizz-release/R121-15699.40.0', + 'cros_img': 'fizz-release/R122-15753.13.0', 'dut_pool': 'chrome', }, }, @@ -63,7 +63,7 @@ 'identifier': 'FIZZ_RELEASE_DEV', 'skylab': { 'cros_board': 'fizz', - 'cros_img': 'fizz-release/R122-15748.0.0', + 'cros_img': 'fizz-release/R123-15770.0.0', 'dut_pool': 'chrome', }, }, @@ -79,7 +79,7 @@ 'identifier': 'FIZZ_RELEASE_STABLE', 'skylab': { 'cros_board': 'fizz', - 'cros_img': 'fizz-release/R120-15662.76.0', + 'cros_img': 'fizz-release/R121-15699.58.0', 'dut_pool': 'chrome', }, }, @@ -87,7 +87,7 @@ 'identifier': 'GUYBRUSH_RELEASE_BETA', 'skylab': { 'cros_board': 'guybrush', - 'cros_img': 'guybrush-release/R121-15699.40.0', + 'cros_img': 'guybrush-release/R122-15753.13.0', 'dut_pool': 'chrome', }, }, @@ -95,7 +95,7 @@ 'identifier': 'GUYBRUSH_RELEASE_DEV', 'skylab': { 'cros_board': 'guybrush', - 'cros_img': 'guybrush-release/R122-15748.0.0', + 'cros_img': 'guybrush-release/R123-15770.0.0', 'dut_pool': 'chrome', }, }, @@ -111,7 +111,7 @@ 'identifier': 'GUYBRUSH_RELEASE_STABLE', 'skylab': { 'cros_board': 'guybrush', - 'cros_img': 'guybrush-release/R120-15662.76.0', + 'cros_img': 'guybrush-release/R121-15699.58.0', 'dut_pool': 'chrome', }, }, @@ -159,7 +159,7 @@ 'identifier': 'PUFF_RELEASE_BETA', 'skylab': { 'cros_board': 'puff', - 'cros_img': 'puff-release/R121-15699.40.0', + 'cros_img': 'puff-release/R122-15753.13.0', 'dut_pool': 'chrome', }, }, @@ -167,7 +167,7 @@ 'identifier': 'PUFF_RELEASE_DEV', 'skylab': { 'cros_board': 'puff', - 'cros_img': 'puff-release/R122-15748.0.0', + 'cros_img': 'puff-release/R123-15770.0.0', 'dut_pool': 'chrome', }, }, @@ -183,7 +183,7 @@ 'identifier': 'PUFF_RELEASE_STABLE', 'skylab': { 'cros_board': 'puff', - 'cros_img': 'puff-release/R120-15662.76.0', + 'cros_img': 'puff-release/R121-15699.58.0', 'dut_pool': 'chrome', }, }, @@ -307,16 +307,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 123.0.6288.0', + 'description': 'Run with ash-chrome version 123.0.6289.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6288.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v123.0.6289.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v123.0.6288.0', - 'revision': 'version:123.0.6288.0', + 'location': 'lacros_version_skew_tests_v123.0.6289.0', + 'revision': 'version:123.0.6289.0', }, ], },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 83f6f49..c693c71 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -12955,6 +12955,70 @@ ] } ], + "OneTimePermissionClank": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "EnabledWithNormalLanguage", + "params": { + "experimental_custom_invitation_arm_trigger_id": "tZMcjst2x0tK1KeaPYj0VbPmvceJ,bpnHbhSrK0tK1KeaPYj0RBC9zv7H,ZDjpUDFx20tK1KeaPYj0WbM2hHXy", + "probability": "1", + "probability_vector": "0.5,1.0,1.0", + "prompt_disposition_reason_filter": "DefaultFallback", + "request_type_filter": "Geolocation,VideoCapture,AudioCapture", + "survey_display_time": "OnPromptResolved", + "trigger_id": "xTNFzsgeH0tK1KeaPYj0VueEfPNg,rMwYPzTTj0tK1KeaPYj0XB5xXsRF,5XkVTH91f0tK1KeaPYj0SJhtw5pX", + "use_stronger_prompt_language": "false" + }, + "enable_features": [ + "ActiveContentSettingExpiry", + "OneTimePermission", + "PermissionsPromptSurvey" + ] + }, + { + "name": "HatsControl_20240208", + "params": { + "experimental_custom_invitation_arm_trigger_id": "Db6NddebR0tK1KeaPYj0UzKHA4zC,sRE9DYcBN0tK1KeaPYj0PtzgM3xw,t6mgdAXqK0tK1KeaPYj0VHRxVpBT", + "probability": "1", + "probability_vector": "0.5,1.0,1.0", + "prompt_disposition_reason_filter": "DefaultFallback", + "request_type_filter": "Geolocation,VideoCapture,AudioCapture", + "survey_display_time": "OnPromptResolved", + "trigger_id": "ZhVFvGaem0tK1KeaPYj0YXx2ouZy,pwU6FSjhZ0tK1KeaPYj0U8h8dv8e,wGFymXxYr0tK1KeaPYj0SxPYLBBc" + }, + "enable_features": [ + "PermissionsPromptSurvey" + ], + "disable_features": [ + "ActiveContentSettingExpiry", + "OneTimePermission" + ] + }, + { + "name": "EnabledWithStrongLanguage_20240208", + "params": { + "experimental_custom_invitation_arm_trigger_id": "eaHr88umj0tK1KeaPYj0YkhJEi1Y,8U6CRfLYU0tK1KeaPYj0RbTHRpNZ,qrWTeaJaK0tK1KeaPYj0XjFWabba", + "probability": "1", + "probability_vector": "0.5,1.0,1.0", + "prompt_disposition_reason_filter": "DefaultFallback", + "request_type_filter": "Geolocation,VideoCapture,AudioCapture", + "survey_display_time": "OnPromptResolved", + "trigger_id": "hCatPbt6B0tK1KeaPYj0WXqMjcvX,89BwvKxbJ0tK1KeaPYj0NtK7Ybn8,3fTPt7XMF0tK1KeaPYj0TXd8QN47", + "use_stronger_prompt_language": "true" + }, + "enable_features": [ + "ActiveContentSettingExpiry", + "OneTimePermission", + "PermissionsPromptSurvey" + ] + } + ] + } + ], "OpaqueResponseBlockingV02": [ { "platforms": [
diff --git a/third_party/angle b/third_party/angle index f431641..c603a4f 160000 --- a/third_party/angle +++ b/third_party/angle
@@ -1 +1 @@ -Subproject commit f431641a948660f5e1709aa7cd89b16ccf93f1de +Subproject commit c603a4f199affd54b338ec1db405e01775c9c57e
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 965c78b..ebcc2e4 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -1188,7 +1188,7 @@ base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kAttributionReportingInBrowserMigration, - "kAttributionReportingInBrowserMigration", + "AttributionReportingInBrowserMigration", base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kLCPCriticalPathPredictor, @@ -2355,11 +2355,6 @@ base::FEATURE_ENABLED_BY_DEFAULT); #endif // BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS) -// Exposes non-standard stats in the WebRTC getStats() API. -BASE_FEATURE(kWebRtcExposeNonStandardStats, - "WebRtc-ExposeNonStandardStats", - base::FEATURE_DISABLED_BY_DEFAULT); - // Causes WebRTC to replace host ICE candidate IP addresses with generated // names ending in ".local" and resolve them using mDNS. // http://crbug.com/878465
diff --git a/third_party/blink/common/frame/view_transition_state_mojom_traits.cc b/third_party/blink/common/frame/view_transition_state_mojom_traits.cc index ec4b929..d06cd96 100644 --- a/third_party/blink/common/frame/view_transition_state_mojom_traits.cc +++ b/third_party/blink/common/frame/view_transition_state_mojom_traits.cc
@@ -22,7 +22,8 @@ !data.ReadSnapshotId(&out->snapshot_id) || !data.ReadCapturedRectInLayoutSpace( &out->captured_rect_in_layout_space) || - !data.ReadCapturedCssProperties(&out->captured_css_properties)) { + !data.ReadCapturedCssProperties(&out->captured_css_properties) || + !data.ReadClassList(&out->class_list)) { return false; }
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 2918f24..8f88aecf 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -1506,8 +1506,6 @@ // Combine WebRTC Network and Worker threads. More info at crbug.com/1373439. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kWebRtcCombinedNetworkAndWorkerThread); -// If enabled, expose non-standard stats in the WebRTC getStats API. -BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kWebRtcExposeNonStandardStats); #if BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS) BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kWebRtcH264WithOpenH264FFmpeg); #endif // BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
diff --git a/third_party/blink/public/common/frame/view_transition_state.h b/third_party/blink/public/common/frame/view_transition_state.h index 6d40050f79..966ea8b 100644 --- a/third_party/blink/public/common/frame/view_transition_state.h +++ b/third_party/blink/public/common/frame/view_transition_state.h
@@ -43,6 +43,8 @@ std::optional<gfx::RectF> captured_rect_in_layout_space; base::flat_map<blink::mojom::ViewTransitionPropertyId, std::string> captured_css_properties; + + std::vector<std::string> class_list; }; struct BLINK_COMMON_EXPORT ViewTransitionState {
diff --git a/third_party/blink/public/common/frame/view_transition_state_mojom_traits.h b/third_party/blink/public/common/frame/view_transition_state_mojom_traits.h index c30871f4..5af0f59 100644 --- a/third_party/blink/public/common/frame/view_transition_state_mojom_traits.h +++ b/third_party/blink/public/common/frame/view_transition_state_mojom_traits.h
@@ -59,6 +59,11 @@ return r.captured_css_properties; } + static const std::vector<std::string>& class_list( + const blink::ViewTransitionElement& r) { + return r.class_list; + } + static bool Read(blink::mojom::ViewTransitionElementDataView r, blink::ViewTransitionElement* out); };
diff --git a/third_party/blink/public/mojom/frame/view_transition_state.mojom b/third_party/blink/public/mojom/frame/view_transition_state.mojom index 45a737f..28c7f4a 100644 --- a/third_party/blink/public/mojom/frame/view_transition_state.mojom +++ b/third_party/blink/public/mojom/frame/view_transition_state.mojom
@@ -40,6 +40,11 @@ // shared element. The map is from (a subset of) CSSPropertyIDs to the css // computed value (as string). map<ViewTransitionPropertyId, string> captured_css_properties; + + // https://drafts.csswg.org/css-view-transitions-2/#captured-element-class-list + // The class-list needs to be serialized between documents, because exit transitions + // would use the class list from the old document. + array<string> class_list; }; // This represents a document state necessary to initiate a view transition for
diff --git a/third_party/blink/public/mojom/peerconnection/peer_connection_tracker.mojom b/third_party/blink/public/mojom/peerconnection/peer_connection_tracker.mojom index 905cb73..a252e7ed 100644 --- a/third_party/blink/public/mojom/peerconnection/peer_connection_tracker.mojom +++ b/third_party/blink/public/mojom/peerconnection/peer_connection_tracker.mojom
@@ -25,9 +25,6 @@ // Serialized version of RTCConfiguration. string rtc_configuration; - // Serialized version of blink::WebMediaConstraints. - string constraints; - // The URL of the blink::WebLocalFrame within which this peer connection // lives. Used for debugging purposes (displayed by WebRTC-Internals). // May be null for eg pages with opaque URLs.
diff --git a/third_party/blink/public/mojom/webid/digital_identity_request.mojom b/third_party/blink/public/mojom/webid/digital_identity_request.mojom index 7ea3092..f71efa6b 100644 --- a/third_party/blink/public/mojom/webid/digital_identity_request.mojom +++ b/third_party/blink/public/mojom/webid/digital_identity_request.mojom
@@ -4,14 +4,34 @@ module blink.mojom; -import "third_party/blink/public/mojom/webid/federated_auth_request.mojom"; - // Implementation of the proposed Digital Identity Credential API. // // Proposal: https://wicg.github.io/digital-identities -// TODO(crbug.com/324115589) Move DigitalCredentialProvider from -// federated_auth_request.mojom here. +// The specification of the query to digital credentials. +struct DigitalCredentialProvider { + map<string, string>? params; + DigitalCredentialSelector? selector; + string? protocol; + string? request; + string? publicKey; +}; + +// The requirements of the credentials that are being requested. +struct DigitalCredentialSelector { + array<string> format; + string? doctype; + array<DigitalCredentialFieldRequirement> fields; +}; + +// The requirements that the verifier needs on specific fields. +struct DigitalCredentialFieldRequirement { + // The name of the field (e.g. "org.iso.18013.5.1.family_name"). + string name; + + // Optionally, whether the field's value is equal to a specific value or not. + string? equals; +}; // Represents the fetch result from a digital identity request. It is // used to determine whether a JavaScript exception should be thrown, and what
diff --git a/third_party/blink/public/mojom/webid/federated_auth_request.mojom b/third_party/blink/public/mojom/webid/federated_auth_request.mojom index fdb621e..c5af795 100644 --- a/third_party/blink/public/mojom/webid/federated_auth_request.mojom +++ b/third_party/blink/public/mojom/webid/federated_auth_request.mojom
@@ -58,40 +58,6 @@ kWidget }; -// The details of different mechanisms that allows the browser -// to intermediate the exchange of the user's entities. -// Currently, federated identities are supported, and digital credentials -// are being prototyped. -union IdentityProvider { - IdentityProviderRequestOptions federated; - DigitalCredentialProvider holder; -}; - -// The specification of the query to digital credentials. -struct DigitalCredentialProvider { - map<string, string>? params; - DigitalCredentialSelector? selector; - string? protocol; - string? request; - string? publicKey; -}; - -// The requirements of the credentials that are being requested. -struct DigitalCredentialSelector { - array<string> format; - string? doctype; - array<DigitalCredentialFieldRequirement> fields; -}; - -// The requirements that the verifier needs on specific fields. -struct DigitalCredentialFieldRequirement { - // The name of the field (e.g. "org.iso.18013.5.1.family_name"). - string name; - - // Optionally, whether the field's value is equal to a specific value or not. - string? equals; -}; - // The details of a federated identity provider. struct IdentityProviderConfig { // Explicitly references a specific provider by a Config URL. @@ -156,7 +122,7 @@ // The parameters for a get call for identity provider(s). struct IdentityProviderGetParameters { // Details of identity provider(s). - array<IdentityProvider> providers; + array<IdentityProviderRequestOptions> providers; // Controls the wording of the FedCM prompt. RpContext context;
diff --git a/third_party/blink/public/platform/modules/remoteplayback/remote_playback_source.h b/third_party/blink/public/platform/modules/remoteplayback/remote_playback_source.h index ec403d15..a48b76c3 100644 --- a/third_party/blink/public/platform/modules/remoteplayback/remote_playback_source.h +++ b/third_party/blink/public/platform/modules/remoteplayback/remote_playback_source.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_REMOTEPLAYBACK_REMOTE_PLAYBACK_SOURCE_H_ namespace blink { + inline constexpr char kRemotePlaybackPresentationUrlScheme[] = "remote-playback"; // The path for RemotePlayback Urls on both Android and Desktop. @@ -17,6 +18,11 @@ // The format for RemotePlayback Urls on desktop. inline constexpr char kRemotePlaybackDesktopUrlFormat[] = "remote-playback:media-session?video_codec=%s&audio_codec=%s&tab_id=%d"; + +// The minimum media element duration that is allowed for media remoting. +// Needs to be in sync with media/remoting/remoting_constants.h +inline constexpr double kMinRemotingMediaDurationInSec = 15; + } // namespace blink #endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_REMOTEPLAYBACK_REMOTE_PLAYBACK_SOURCE_H_
diff --git a/third_party/blink/renderer/core/css/selector_checker.cc b/third_party/blink/renderer/core/css/selector_checker.cc index fdda60ea..aa0be4f8 100644 --- a/third_party/blink/renderer/core/css/selector_checker.cc +++ b/third_party/blink/renderer/core/css/selector_checker.cc
@@ -2169,8 +2169,30 @@ CHECK(!selector.IdentList().empty()); const AtomicString& name_or_wildcard = selector.IdentList()[0]; - return name_or_wildcard == CSSSelector::UniversalSelectorAtom() || - name_or_wildcard == pseudo_argument_; + + // note that the pseudo_ident_list_ is the class list, and + // pseudo_argument_ is the name, while in the selector the IdentList() is + // both the name and the classes. + if (name_or_wildcard != CSSSelector::UniversalSelectorAtom() && + name_or_wildcard != pseudo_argument_) { + return false; + } + + // https://drafts.csswg.org/css-view-transitions-2/#typedef-pt-class-selector + // A named view transition pseudo-element selector which has one or more + // <custom-ident> values in its <pt-class-selector> would only match an + // element if the class list value in named elements for the + // pseudo-element’s view-transition-name contains all of those values. + + // selector.IdentList() is equivalent to + // <pt-name-selector><pt-class-selector>, as in [name, class, class, ...] + // so we check that all of its items excluding the first one are + // contained in the pseudo element's classes (pseudo_ident_list_). + return base::ranges::all_of( + selector.IdentList().begin() + 1, selector.IdentList().end(), + [&](const AtomicString& class_from_selector) { + return base::Contains(pseudo_ident_list_, class_from_selector); + }); } case CSSSelector::kPseudoScrollbarButton: case CSSSelector::kPseudoScrollbarCorner:
diff --git a/third_party/blink/renderer/core/css/selector_checker.h b/third_party/blink/renderer/core/css/selector_checker.h index 7c1c680..c8edc627 100644 --- a/third_party/blink/renderer/core/css/selector_checker.h +++ b/third_party/blink/renderer/core/css/selector_checker.h
@@ -98,6 +98,7 @@ : scrollbar_(style_request.scrollbar), part_names_(part_names), pseudo_argument_(style_request.pseudo_argument), + pseudo_ident_list_(style_request.pseudo_ident_list), scrollbar_part_(style_request.scrollbar_part), mode_(mode), is_ua_rule_(is_ua_rule) {} @@ -364,6 +365,7 @@ CustomScrollbar* scrollbar_; PartNames* part_names_; const String pseudo_argument_; + const Vector<AtomicString> pseudo_ident_list_; ScrollbarPart scrollbar_part_; Mode mode_; bool is_ua_rule_;
diff --git a/third_party/blink/renderer/core/css/style_request.h b/third_party/blink/renderer/core/css/style_request.h index e31944b..3c722b3 100644 --- a/third_party/blink/renderer/core/css/style_request.h +++ b/third_party/blink/renderer/core/css/style_request.h
@@ -62,6 +62,7 @@ ScrollbarPart scrollbar_part{kNoPart}; CustomScrollbar* scrollbar{nullptr}; AtomicString pseudo_argument{g_null_atom}; + Vector<AtomicString> pseudo_ident_list; RulesToInclude rules_to_include{kAll}; bool can_trigger_animations{true};
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index cc35083..0464200 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -3167,6 +3167,13 @@ resource_coordinator_.reset(); + // Because the document view transition supplement can get destroyed before + // the execution context notification, we should clean up the transition + // object here. + if (auto* transition = ViewTransitionUtils::GetTransition(*this)) { + transition->SkipTransition(); + } + // This is required, as our LocalFrame might delete itself as soon as it // detaches us. However, this violates Node::detachLayoutTree() semantics, as // it's never possible to re-attach. Eventually Document::detachLayoutTree()
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index 8f3cffa3..3637beaed 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -4323,13 +4323,16 @@ void LocalFrameView::SetIntersectionObservationState( IntersectionObservationState state) { + if (state >= kDesired) { + // Disable MinScrollDeltaToUpdate optimization and schedule update for + // all intersection observers. + accumulated_scroll_delta_since_last_intersection_update_ = + IntersectionGeometry::kInfiniteScrollDelta; + } + if (intersection_observation_state_ >= state) return; intersection_observation_state_ = state; - // Disable scroll delta optimization on any change other than pure scroll - // (see UpdateIntersectionObservationStateOnScroll). - accumulated_scroll_delta_since_last_intersection_update_ = - IntersectionGeometry::kInfiniteScrollDelta; // If an intersection observation is required, force all ancestors to update. // Otherwise, an update could stop at a throttled frame before reaching this. @@ -4346,24 +4349,7 @@ gfx::Vector2dF scroll_delta) { accumulated_scroll_delta_since_last_intersection_update_ += gfx::Vector2dF(std::abs(scroll_delta.x()), std::abs(scroll_delta.y())); - intersection_observation_state_ = - std::max(intersection_observation_state_, kDesired); -} - -void LocalFrameView::InvalidateIntersectionObservations() { - if (!RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { - return; - } - DCHECK_EQ(Lifecycle().GetState(), DocumentLifecycle::kInPrePaint); - DCHECK(GetFrame().IsLocalRoot() || !IsAttached()); - ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) { - if (auto* controller = frame_view.GetFrame() - .GetDocument() - ->GetIntersectionObserverController()) { - controller->InvalidateCachedRectsIfPaintPropertiesChanged(); - frame_view.SetIntersectionObservationState(LocalFrameView::kDesired); - } - }); + SetIntersectionObservationState(kScrollAndVisibilityOnly); } void LocalFrameView::SetVisualViewportOrOverlayNeedsRepaint() {
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h index 63c1cd3a..43115be9 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.h +++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -215,11 +215,16 @@ enum IntersectionObservationState { // The next painting frame does not need an intersection observation. kNotNeeded = 0, - // The next painting frame needs an intersection observation. - kDesired = 1, + // The next painting frame needs to update + // - intersection observations whose MinScrollDeltaToUpdate is exceeded by + // the accumulated scroll delta in the frame. + // - intersection observers that trackVisibility. + kScrollAndVisibilityOnly = 1, + // The next painting frame needs to update all intersection observations. + kDesired = 2, // The next painting frame must be generated up to intersection observation // (even if frame is throttled). - kRequired = 2 + kRequired = 3 }; // Sets the internal IntersectionObservationState to the max of the @@ -230,7 +235,6 @@ const { return intersection_observation_state_; } - void InvalidateIntersectionObservations(); // Get the InstersectionObservation::ComputeFlags for target elements in this // view.
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc b/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc index e4cfa61b..b794709 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc
@@ -530,6 +530,11 @@ cached_rects->valid = false; + if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { + // TODO(crbug.com/40883761): Evaluate performance. + return; + } + if (root_and_target.relationship == RootAndTarget::kInvalid) { return; } @@ -541,34 +546,21 @@ return; } - if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { - // Cached rects can only be used if there are no scrollable objects in the - // hierarchy between target and root (a scrollable root is ok). The reason - // is that a scroll change in an intermediate scroller would change the - // intersection geometry, but we intentionally don't invalidate cached - // rects and schedule intersection update to enable the minimul-scroll- - // delta-to-update optimization. - if (root_and_target.relationship != RootAndTarget::kNotScrollable && - root_and_target.relationship != RootAndTarget::kScrollableByRootOnly) { - return; - } - } else { - if (RootIsImplicit()) { - return; - } - // Cached rects can only be used if there are no scrollable objects in the - // hierarchy between target and root (a scrollable root is ok). The reason - // is that a scroll change in an intermediate scroller would change the - // intersection geometry, but it would not properly trigger an invalidation - // of the cached rects. - PaintLayer* root_layer = root_and_target.target->View()->Layer(); - if (!root_layer) { - return; - } - if (root_and_target.target->DeprecatedEnclosingScrollableBox() != - root_and_target.root) { - return; - } + if (RootIsImplicit()) { + return; + } + // Cached rects can only be used if there are no scrollable objects in the + // hierarchy between target and root (a scrollable root is ok). The reason + // is that a scroll change in an intermediate scroller would change the + // intersection geometry, but it would not properly trigger an invalidation + // of the cached rects. + PaintLayer* root_layer = root_and_target.target->View()->Layer(); + if (!root_layer) { + return; + } + if (root_and_target.target->DeprecatedEnclosingScrollableBox() != + root_and_target.root) { + return; } flags_ |= kShouldUseCachedRects;
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc index 6aa2dad..a712eda 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc
@@ -132,49 +132,6 @@ observer_.Clear(); } -void IntersectionObservation::InvalidateCachedRectsIfPaintPropertiesChanged() { - DCHECK(RuntimeEnabledFeatures::IntersectionOptimizationEnabled()); - if (cached_rects_.valid && PaintPropertiesChanged()) { - InvalidateCachedRects(); - } -} - -bool IntersectionObservation::PaintPropertiesChanged() const { - DCHECK(cached_rects_.valid); - if (observer_->trackVisibility()) { - return true; - } - const LayoutObject* target_object = - IntersectionGeometry::GetTargetLayoutObject(*target_); - if (!target_object || - !IntersectionGeometry::CanUseGeometryMapper(*target_object)) { - return true; - } - const LayoutObject* root_object = nullptr; - PropertyTreeStateOrAlias root_state = PropertyTreeState::Root(); - if (!observer_->RootIsImplicit()) { - root_object = - IntersectionGeometry::GetExplicitRootLayoutObject(*observer_->root()); - if (!root_object || root_object == target_object) { - return true; - } - const auto* root_property_container = - root_object->GetPropertyContainer(nullptr); - if (!root_property_container) { - return true; - } - root_state = root_property_container->FirstFragment().ContentsProperties(); - } - PropertyTreeStateOrAlias target_state = PropertyTreeState::Uninitialized(); - LayoutObject::AncestorSkipInfo skip_info(root_object); - if (!target_object->GetPropertyContainer(&skip_info, &target_state)) { - return true; - } - return target_state.ChangedExceptScrollAndEffect( - PaintPropertyChangeType::kChangedOnlyCompositedValues, - root_state.Unalias()); -} - void IntersectionObservation::Trace(Visitor* visitor) const { visitor->Trace(observer_); visitor->Trace(entries_);
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observation.h b/third_party/blink/renderer/core/intersection_observer/intersection_observation.h index 5f1bd10..5613674 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observation.h +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observation.h
@@ -73,7 +73,6 @@ void TakeRecords(HeapVector<Member<IntersectionObserverEntry>>&); void Disconnect(); void InvalidateCachedRects() { cached_rects_.valid = false; } - void InvalidateCachedRectsIfPaintPropertiesChanged(); void Trace(Visitor*) const; @@ -87,7 +86,6 @@ // generate a notification and schedule it for delivery. void ProcessIntersectionGeometry(const IntersectionGeometry& geometry, DOMHighResTimeStamp timestamp); - bool PaintPropertiesChanged() const; Member<IntersectionObserver> observer_; WeakMember<Element> target_;
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.cc index 1d17beb..af045315 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.cc
@@ -182,19 +182,6 @@ tracked_implicit_root_observations_.erase(&observation); } -void IntersectionObserverController:: - InvalidateCachedRectsIfPaintPropertiesChanged() { - DCHECK(RuntimeEnabledFeatures::IntersectionOptimizationEnabled()); - for (auto& observer : tracked_explicit_root_observers_) { - for (auto& observation : observer->Observations()) { - observation->InvalidateCachedRectsIfPaintPropertiesChanged(); - } - } - for (auto& observation : tracked_implicit_root_observations_) { - observation->InvalidateCachedRectsIfPaintPropertiesChanged(); - } -} - void IntersectionObserverController::Trace(Visitor* visitor) const { visitor->Trace(tracked_explicit_root_observers_); visitor->Trace(tracked_implicit_root_observations_);
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h b/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h index 599581b2..15a388f05 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h
@@ -64,8 +64,6 @@ return tracked_implicit_root_observations_.size(); } - void InvalidateCachedRectsIfPaintPropertiesChanged(); - private: void PostTaskToDeliverNotifications();
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc index 4c72ece05..14055ab 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc
@@ -187,7 +187,7 @@ root->scrollTo(0, 50); EXPECT_EQ(gfx::Vector2dF(50, 100), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -197,7 +197,7 @@ root->scrollTo(0, 100); EXPECT_EQ(gfx::Vector2dF(50, 50), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -210,7 +210,7 @@ root->scrollTo(0, 101); EXPECT_EQ(gfx::Vector2dF(), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -979,6 +979,10 @@ } TEST_P(IntersectionObserverTest, CachedRectsWithScrollers) { + if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { + return; + } + WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600)); SimRequest main_resource("https://example.com/", "text/html"); LoadURL("https://example.com/"); @@ -1046,11 +1050,7 @@ // observation2 can't use cached rects because the observer's root is not // the target's enclosing scroller. EXPECT_FALSE(observation2->CanUseCachedRectsForTesting()); - if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { - EXPECT_FALSE(observation3->CanUseCachedRectsForTesting()); - } else { - EXPECT_TRUE(observation3->CanUseCachedRectsForTesting()); - } + EXPECT_TRUE(observation3->CanUseCachedRectsForTesting()); // Scrolling the root should not invalidate. root->scrollTo(0, 100); @@ -1074,12 +1074,8 @@ DocumentUpdateReason::kTest); EXPECT_TRUE(observation1->CanUseCachedRectsForTesting()); EXPECT_FALSE(observation2->CanUseCachedRectsForTesting()); - if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { - EXPECT_FALSE(observation3->CanUseCachedRectsForTesting()); - } else { - // This is incorrect. - EXPECT_TRUE(observation3->CanUseCachedRectsForTesting()); - } + // This is incorrect. + EXPECT_TRUE(observation3->CanUseCachedRectsForTesting()); // Changing layout between root and target should invalidate. target1->parentElement()->SetInlineStyleProperty(CSSPropertyID::kMarginLeft, @@ -1106,6 +1102,10 @@ } TEST_P(IntersectionObserverTest, CachedRectsWithOverflowHidden) { + if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { + return; + } + WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600)); SimRequest main_resource("https://example.com/", "text/html"); LoadURL("https://example.com/"); @@ -1169,11 +1169,7 @@ Compositor().BeginFrame(); test::RunPendingTasks(); - if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { - EXPECT_TRUE(observation1->CanUseCachedRectsForTesting()); - } else { - EXPECT_FALSE(observation3->CanUseCachedRectsForTesting()); - } + EXPECT_FALSE(observation3->CanUseCachedRectsForTesting()); // observation2 can't use cached rects because the observer's root is not // the target's enclosing scroller. EXPECT_FALSE(observation2->CanUseCachedRectsForTesting()); @@ -1200,11 +1196,7 @@ target3->parentElement()->scrollTo(0, 200); GetDocument().View()->UpdateLifecycleToPrePaintClean( DocumentUpdateReason::kTest); - if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { - EXPECT_TRUE(observation1->CanUseCachedRectsForTesting()); - } else { - EXPECT_FALSE(observation3->CanUseCachedRectsForTesting()); - } + EXPECT_FALSE(observation3->CanUseCachedRectsForTesting()); EXPECT_FALSE(observation2->CanUseCachedRectsForTesting()); EXPECT_FALSE(observation3->CanUseCachedRectsForTesting()); @@ -1227,18 +1219,16 @@ Compositor().BeginFrame(); test::RunPendingTasks(); - if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { - EXPECT_TRUE(observation1->CanUseCachedRectsForTesting()); - EXPECT_TRUE(observation2->CanUseCachedRectsForTesting()); - EXPECT_TRUE(observation3->CanUseCachedRectsForTesting()); - } else { - EXPECT_FALSE(observation1->CanUseCachedRectsForTesting()); - EXPECT_FALSE(observation2->CanUseCachedRectsForTesting()); - EXPECT_FALSE(observation3->CanUseCachedRectsForTesting()); - } + EXPECT_FALSE(observation1->CanUseCachedRectsForTesting()); + EXPECT_FALSE(observation2->CanUseCachedRectsForTesting()); + EXPECT_FALSE(observation3->CanUseCachedRectsForTesting()); } TEST_P(IntersectionObserverTest, CachedRectsWithoutIntermediateScrollable) { + if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { + return; + } + WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600)); SimRequest main_resource("https://example.com/", "text/html"); LoadURL("https://example.com/"); @@ -1310,20 +1300,18 @@ Compositor().BeginFrame(); test::RunPendingTasks(); - if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { - EXPECT_TRUE(observation1->CanUseCachedRectsForTesting()); - EXPECT_TRUE(observation2->CanUseCachedRectsForTesting()); - EXPECT_TRUE(observation3->CanUseCachedRectsForTesting()); - } else { - EXPECT_FALSE(observation1->CanUseCachedRectsForTesting()); - EXPECT_FALSE(observation2->CanUseCachedRectsForTesting()); - EXPECT_FALSE(observation3->CanUseCachedRectsForTesting()); - } + EXPECT_FALSE(observation1->CanUseCachedRectsForTesting()); + EXPECT_FALSE(observation2->CanUseCachedRectsForTesting()); + EXPECT_FALSE(observation3->CanUseCachedRectsForTesting()); // scroller3 is an intermediate scroller between root and target4. EXPECT_FALSE(observation4->CanUseCachedRectsForTesting()); } TEST_P(IntersectionObserverTest, CachedRectsWithPaintPropertyChange) { + if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { + return; + } + WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600)); SimRequest main_resource("https://example.com/", "text/html"); LoadURL("https://example.com/"); @@ -1360,21 +1348,13 @@ // Generate initial notifications and populate cache. Compositor().BeginFrame(); test::RunPendingTasks(); - if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { - EXPECT_TRUE(observation->CanUseCachedRectsForTesting()); - } else { - EXPECT_FALSE(observation->CanUseCachedRectsForTesting()); - } + EXPECT_FALSE(observation->CanUseCachedRectsForTesting()); // Change of opacity doesn't invalidate cached rects. container->SetInlineStyleProperty(CSSPropertyID::kOpacity, "0.6"); GetDocument().View()->UpdateLifecycleToPrePaintClean( DocumentUpdateReason::kTest); - if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { - EXPECT_TRUE(observation->CanUseCachedRectsForTesting()); - } else { - EXPECT_FALSE(observation->CanUseCachedRectsForTesting()); - } + EXPECT_FALSE(observation->CanUseCachedRectsForTesting()); container->SetInlineStyleProperty(CSSPropertyID::kTransform, "translateY(20px)"); @@ -1384,6 +1364,10 @@ } TEST_P(IntersectionObserverTest, CachedRectsDisplayNone) { + if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { + return; + } + WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600)); SimRequest main_resource("https://example.com/", "text/html"); LoadURL("https://example.com/"); @@ -1412,11 +1396,7 @@ Compositor().BeginFrame(); test::RunPendingTasks(); - if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { - EXPECT_TRUE(observation->CanUseCachedRectsForTesting()); - } else { - EXPECT_FALSE(observation->CanUseCachedRectsForTesting()); - } + EXPECT_FALSE(observation->CanUseCachedRectsForTesting()); target->setAttribute(html_names::kStyleAttr, AtomicString("display: none")); GetDocument().View()->UpdateLifecycleToPrePaintClean( @@ -1464,24 +1444,14 @@ Compositor().BeginFrame(); test::RunPendingTasks(); - if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { - EXPECT_TRUE(observation1->CanUseCachedRectsForTesting()); - EXPECT_TRUE(observation2->CanUseCachedRectsForTesting()); - } else { - EXPECT_FALSE(observation1->CanUseCachedRectsForTesting()); - EXPECT_FALSE(observation2->CanUseCachedRectsForTesting()); - } + EXPECT_FALSE(observation1->CanUseCachedRectsForTesting()); + EXPECT_FALSE(observation2->CanUseCachedRectsForTesting()); GetDocument().domWindow()->scrollTo(0, 100); GetDocument().View()->UpdateLifecycleToPrePaintClean( DocumentUpdateReason::kTest); - if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { - EXPECT_TRUE(observation1->CanUseCachedRectsForTesting()); - EXPECT_TRUE(observation2->CanUseCachedRectsForTesting()); - } else { - EXPECT_FALSE(observation1->CanUseCachedRectsForTesting()); - EXPECT_FALSE(observation2->CanUseCachedRectsForTesting()); - } + EXPECT_FALSE(observation1->CanUseCachedRectsForTesting()); + EXPECT_FALSE(observation2->CanUseCachedRectsForTesting()); } TEST_P(IntersectionObserverTest, MinScrollDeltaToUpdateNotScrollable) { @@ -1709,7 +1679,7 @@ root->scrollTo(0, 50); EXPECT_EQ(gfx::Vector2dF(50, 100), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -1719,7 +1689,7 @@ root->scrollTo(0, 100); EXPECT_EQ(gfx::Vector2dF(50, 50), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -1732,7 +1702,7 @@ root->scrollTo(0, 101); EXPECT_EQ(gfx::Vector2dF(50, 0), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -1745,7 +1715,7 @@ root->scrollTo(51, 101); EXPECT_EQ(gfx::Vector2dF(50, 1), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -1808,7 +1778,7 @@ root->scrollTo(0, 50); // While our internal geometries are zoomed. EXPECT_EQ(gfx::Vector2dF(100, 200), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -1818,7 +1788,7 @@ root->scrollTo(0, 100); EXPECT_EQ(gfx::Vector2dF(100, 100), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -1831,7 +1801,7 @@ root->scrollTo(0, 101); EXPECT_EQ(gfx::Vector2dF(100, 0), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -1844,7 +1814,7 @@ root->scrollTo(51, 101); EXPECT_EQ(gfx::Vector2dF(100, 2), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -1900,7 +1870,7 @@ window.scrollTo(0, 50); EXPECT_EQ(gfx::Vector2dF(50, 100), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -1913,7 +1883,7 @@ window.scrollTo(0, 100); EXPECT_EQ(gfx::Vector2dF(50, 50), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -1926,7 +1896,7 @@ window.scrollTo(0, 101); EXPECT_EQ(gfx::Vector2dF(50, 0), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -1939,7 +1909,7 @@ window.scrollTo(51, 101); EXPECT_EQ(gfx::Vector2dF(50, 1), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -2062,7 +2032,7 @@ root->scrollTo(0, 50); EXPECT_EQ(gfx::Vector2dF(50, 100), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -2072,7 +2042,7 @@ root->scrollTo(0, 100); EXPECT_EQ(gfx::Vector2dF(50, 50), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -2085,7 +2055,7 @@ root->scrollTo(0, 101); EXPECT_EQ(gfx::Vector2dF(50, 0), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -2098,7 +2068,7 @@ root->scrollTo(51, 101); EXPECT_EQ(gfx::Vector2dF(50, 1), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -2158,7 +2128,7 @@ root->scrollTo(0, 50); EXPECT_EQ(gfx::Vector2dF(50, 100), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -2169,7 +2139,7 @@ root->scrollTo(0, 100); EXPECT_EQ(gfx::Vector2dF(50, 50), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -2182,7 +2152,7 @@ root->scrollTo(0, 101); EXPECT_EQ(gfx::Vector2dF(), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -2195,7 +2165,7 @@ root->scrollTo(0, 151); EXPECT_EQ(gfx::Vector2dF(), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -2256,7 +2226,7 @@ root->scrollTo(0, 100); EXPECT_EQ(gfx::Vector2dF(20, 200), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -2267,7 +2237,7 @@ root->scrollTo(0, 200); EXPECT_EQ(gfx::Vector2dF(20, 100), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -2280,7 +2250,7 @@ root->scrollTo(20, 200); EXPECT_EQ(gfx::Vector2dF(20, 0), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -2353,7 +2323,7 @@ root->scrollTo(0, 100); EXPECT_EQ(gfx::Vector2dF(30, 200), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks(); @@ -2364,7 +2334,7 @@ root->scrollTo(30, 200); EXPECT_EQ(gfx::Vector2dF(30, 100), observation->MinScrollDeltaToUpdate()); - EXPECT_EQ(LocalFrameView::kDesired, + EXPECT_EQ(LocalFrameView::kScrollAndVisibilityOnly, frame_view->GetIntersectionObservationStateForTesting()); Compositor().BeginFrame(); test::RunPendingTasks();
diff --git a/third_party/blink/renderer/core/paint/paint_invalidator.cc b/third_party/blink/renderer/core/paint/paint_invalidator.cc index 902b9b3..e7764ec 100644 --- a/third_party/blink/renderer/core/paint/paint_invalidator.cc +++ b/third_party/blink/renderer/core/paint/paint_invalidator.cc
@@ -260,8 +260,8 @@ UpdateLayoutShiftTracking(object, fragment_tree_builder_context, context); if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled() && object.ShouldCheckLayoutForPaintInvalidation()) { - object.GetMutableForPainting() - .InvalidateIntersectionObserverCachedRects(); + object.GetFrameView()->SetIntersectionObservationState( + LocalFrameView::kDesired); } } else { context.old_paint_offset = context.fragment_data->PaintOffset();
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index a7e34aa..8a64e97 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -116,8 +116,7 @@ was_layout_shift_root(false), global_main_thread_scrolling_reasons(0), composited_scrolling_preference( - static_cast<unsigned>(CompositedScrollingPreference::kDefault)), - transform_or_clip_added_or_removed(false) {} + static_cast<unsigned>(CompositedScrollingPreference::kDefault)) {} void VisualViewportPaintPropertyTreeBuilder::Update( LocalFrameView& main_frame_view, @@ -348,11 +347,17 @@ void OnUpdateTransform(PaintPropertyChangeType change) { properties_changed_.transform_changed = std::max(properties_changed_.transform_changed, change); + properties_changed_.transform_change_is_scroll_translation_only = false; + } + void OnUpdateScrollTranslation(PaintPropertyChangeType change) { + properties_changed_.transform_changed = + std::max(properties_changed_.transform_changed, change); } void OnClearTransform(bool cleared) { if (cleared) { properties_changed_.transform_changed = PaintPropertyChangeType::kNodeAddedOrRemoved; + properties_changed_.transform_change_is_scroll_translation_only = false; } } @@ -2115,6 +2120,7 @@ if (old_transform != new_transform) { properties_changed_.transform_changed = PaintPropertyChangeType::kNodeAddedOrRemoved; + properties_changed_.transform_change_is_scroll_translation_only = false; } if (old_clip != new_clip) { properties_changed_.clip_changed = @@ -2705,7 +2711,7 @@ } } } - OnUpdateTransform(effective_change_type); + OnUpdateScrollTranslation(effective_change_type); } else { OnClearTransform(properties_->ClearScrollTranslation()); } @@ -3241,6 +3247,7 @@ if (properties->HasTransformNode()) { properties_changed_.transform_changed = PaintPropertyChangeType::kNodeAddedOrRemoved; + properties_changed_.transform_change_is_scroll_translation_only = false; } if (properties->HasClipNode()) { properties_changed_.clip_changed = @@ -3378,21 +3385,10 @@ GetFragmentData()); builder.UpdateForSelf(); properties_changed_.Merge(builder.PropertiesChanged()); - context_.transform_or_clip_added_or_removed |= - properties_changed_.TransformOrClipAddedOrRemoved(); if (!PrePaintDisableSideEffectsScope::IsDisabled()) { object_.GetMutableForPainting() .SetShouldAssumePaintOffsetTranslationForLayoutShiftTracking(false); - - if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled() && - context_.transform_or_clip_added_or_removed) { - // Some of such changes can't be captured by IntersectionObservation:: - // InvalidateCachedRectsIfNeeded(), e.g. when if LocalBorderBoxProperties - // now points to the parent of a removed paint property. - object_.GetMutableForPainting() - .InvalidateIntersectionObserverCachedRects(); - } } } @@ -3474,13 +3470,22 @@ PaintPropertyTreeBuilderContext::kSubtreeUpdateIsolationBlocked; } } + + if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled() && + (properties_changed_.transform_changed > + (properties_changed_.transform_change_is_scroll_translation_only + ? PaintPropertyChangeType::kChangedOnlySimpleValues + : PaintPropertyChangeType::kUnchanged) || + properties_changed_.clip_changed > PaintPropertyChangeType::kUnchanged || + properties_changed_.scroll_changed > + PaintPropertyChangeType::kUnchanged)) { + object_.GetFrameView()->SetIntersectionObservationState( + LocalFrameView::kDesired); + } + if (is_isolated) { context_.force_subtree_update_reasons &= ~PaintPropertyTreeBuilderContext::kSubtreeUpdateIsolationBlocked; - context_.transform_or_clip_added_or_removed = false; - } else { - context_.transform_or_clip_added_or_removed |= - properties_changed_.TransformOrClipAddedOrRemoved(); } } @@ -3533,14 +3538,21 @@ std::move(transform_and_origin), animation_state); DirectlyUpdateCcTransform(*transform, object, effective_change_type); + if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled() && + effective_change_type > PaintPropertyChangeType::kUnchanged) { + object.GetFrameView()->SetIntersectionObservationState( + LocalFrameView::kDesired); + } + if (effective_change_type >= PaintPropertyChangeType::kChangedOnlySimpleValues) { object.GetFrameView()->SetPaintArtifactCompositorNeedsUpdate(); } - PaintPropertiesChangeInfo properties_changed; - properties_changed.transform_changed = effective_change_type; - + PaintPropertiesChangeInfo properties_changed{ + .transform_changed = effective_change_type, + .transform_change_is_scroll_translation_only = false, + }; CullRectUpdater::PaintPropertiesChanged(object, properties_changed); }
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h index 38ff665..c7f6c14 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
@@ -231,11 +231,6 @@ unsigned composited_scrolling_preference : 2; - // This propagates to descendants (but not through isolations) to capture - // the situation of added/removed transform/clip affecting property tree - // states. - unsigned transform_or_clip_added_or_removed : 1; - // This is always recalculated in PaintPropertyTreeBuilder::UpdateForSelf() // which overrides the inherited value. CompositingReasons direct_compositing_reasons = CompositingReason::kNone; @@ -303,12 +298,15 @@ public: PaintPropertyChangeType transform_changed = PaintPropertyChangeType::kUnchanged; + bool transform_change_is_scroll_translation_only = true; PaintPropertyChangeType clip_changed = PaintPropertyChangeType::kUnchanged; PaintPropertyChangeType effect_changed = PaintPropertyChangeType::kUnchanged; PaintPropertyChangeType scroll_changed = PaintPropertyChangeType::kUnchanged; void Merge(const PaintPropertiesChangeInfo& other) { transform_changed = std::max(transform_changed, other.transform_changed); + transform_change_is_scroll_translation_only &= + other.transform_change_is_scroll_translation_only; clip_changed = std::max(clip_changed, other.clip_changed); effect_changed = std::max(effect_changed, other.effect_changed); scroll_changed = std::max(scroll_changed, other.scroll_changed); @@ -318,11 +316,6 @@ return std::max( {transform_changed, clip_changed, effect_changed, scroll_changed}); } - - bool TransformOrClipAddedOrRemoved() const { - return transform_changed >= PaintPropertyChangeType::kNodeAddedOrRemoved || - clip_changed >= PaintPropertyChangeType::kNodeAddedOrRemoved; - } }; // Creates paint property tree nodes for non-local effects in the layout tree.
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc index 34a1306..858c304 100644 --- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc +++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -93,11 +93,13 @@ if (auto* client = root_frame_view.GetChromeClient()) { client->InvalidateContainer(); } - // TODO(wangxianzhu): For now we call this whenever there has been any - // paint property change or paint invalidation. If this shows up as a - // performance issue, we should exclude scroll, effect and non-layout - // paint invalidations for v1 intersection observations. - root_frame_view.InvalidateIntersectionObservations(); + // If any change needs a more significant intersection update in a frame + // view, we should have set the state on that frame view during the tree + // walk or earlier. + if (RuntimeEnabledFeatures::IntersectionOptimizationEnabled()) { + root_frame_view.SetIntersectionObservationState( + LocalFrameView::kScrollAndVisibilityOnly); + } } }
diff --git a/third_party/blink/renderer/core/view_transition/view_transition.cc b/third_party/blink/renderer/core/view_transition/view_transition.cc index 5df8fe37..313998f 100644 --- a/third_party/blink/renderer/core/view_transition/view_transition.cc +++ b/third_party/blink/renderer/core/view_transition/view_transition.cc
@@ -530,6 +530,14 @@ } ResumeRendering(); + + // Animation and subsequent steps require us to have a view. If after + // running the callbacks, we don't have a view, skip the transition. + if (!document_->View()) { + SkipTransition(); + break; + } + process_next_state = AdvanceTo(State::kAnimateTagDiscovery); DCHECK(process_next_state); break;
diff --git a/third_party/blink/renderer/core/view_transition/view_transition_pseudo_element_base.cc b/third_party/blink/renderer/core/view_transition/view_transition_pseudo_element_base.cc index 1d06d97..a57772d5 100644 --- a/third_party/blink/renderer/core/view_transition/view_transition_pseudo_element_base.cc +++ b/third_party/blink/renderer/core/view_transition/view_transition_pseudo_element_base.cc
@@ -46,10 +46,14 @@ const StyleRecalcContext& style_recalc_context) { // Set the parent style to the style of our parent. There is no use // for an originating element for a view transition pseudo. - auto style_request = StyleRequest( + StyleRequest style_request( GetPseudoId(), ParentOrShadowHostElement()->GetComputedStyle(), /* originating_element_style */ nullptr, view_transition_name()); style_request.rules_to_include = style_tracker_->StyleRulesToInclude(); + if (GetPseudoId() != kPseudoIdViewTransition) { + style_request.pseudo_ident_list = + style_tracker_->GetViewTransitionClassList(view_transition_name()); + } // Use the document element to get the style for the pseudo element, since the // documentElement is the originating element for the view transition pseudo // elements.
diff --git a/third_party/blink/renderer/core/view_transition/view_transition_pseudo_element_base.h b/third_party/blink/renderer/core/view_transition/view_transition_pseudo_element_base.h index 0d6eb35..55219965 100644 --- a/third_party/blink/renderer/core/view_transition/view_transition_pseudo_element_base.h +++ b/third_party/blink/renderer/core/view_transition/view_transition_pseudo_element_base.h
@@ -29,6 +29,7 @@ void Trace(Visitor* visitor) const override; protected: + Vector<AtomicString> view_transition_class_; Member<const ViewTransitionStyleTracker> style_tracker_; };
diff --git a/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.cc b/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.cc index 428069b..9a20707 100644 --- a/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.cc +++ b/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.cc
@@ -479,6 +479,11 @@ element_data->captured_css_properties = std::move(css_property_builder).Finish(); + for (const auto& class_name : transition_state_element.class_list) { + element_data->class_list.push_back( + AtomicString::FromUTF8(class_name.c_str())); + } + element_data->CacheStateForOldSnapshot(); element_data_map_.insert(name, std::move(element_data)); @@ -736,6 +741,8 @@ element_data->target_element = element; element_data->element_index = next_index++; element_data->old_snapshot_id = snapshot_id; + element_data->class_list = + element->ComputedStyleRef().ViewTransitionClass(); element_data_map_.insert(name, std::move(element_data)); if (element->IsDocumentElement()) { @@ -806,6 +813,13 @@ return result; } +const Vector<AtomicString>& +ViewTransitionStyleTracker::GetViewTransitionClassList( + const AtomicString& name) const { + CHECK(element_data_map_.Contains(name)); + return element_data_map_.at(name)->class_list; +} + bool ViewTransitionStyleTracker::Start() { DCHECK_EQ(state_, State::kCaptured); @@ -860,6 +874,9 @@ DCHECK(!element_data->target_element); element_data->target_element = element; element_data->new_snapshot_id = snapshot_id; + element_data->class_list = + element->ComputedStyleRef().ViewTransitionClass(); + // Verify that the element_index assigned in Capture is less than next_index // here, just as a sanity check. DCHECK_LT(element_data->element_index, next_index); @@ -1602,6 +1619,9 @@ css_property_builder.Insert(ToTranstionPropertyId(id), value.Utf8()); } element.captured_css_properties = std::move(css_property_builder).Finish(); + for (const auto& class_name : element_data->class_list) { + element.class_list.push_back(class_name.Utf8()); + } } // TODO(khushalsagar): Need to send offsets to retain positioning of
diff --git a/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.h b/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.h index 0f8db48..33b5dd37 100644 --- a/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.h +++ b/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.h
@@ -201,6 +201,11 @@ // the initial capture was taken. bool SnapshotRootDidChangeSize() const; + // https://drafts.csswg.org/css-view-transitions-2/#captured-element-class-list + // Returns the class list for a captured element by name. + const Vector<AtomicString>& GetViewTransitionClassList( + const AtomicString& name) const; + private: class ImageWrapperPseudoElement; @@ -270,6 +275,9 @@ // This only contains properties that need to be animated, which is a // subset of `captured_css_properties`. base::flat_map<CSSPropertyID, String> cached_animated_css_properties; + + // https://drafts.csswg.org/css-view-transitions-2/#captured-element-class-list + Vector<AtomicString> class_list; }; // In physical pixels. Returns the snapshot root rect, relative to the
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc index c89695c..a0d950c4 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc +++ b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc
@@ -10,6 +10,7 @@ #include "base/numerics/safe_conversions.h" #include "build/build_config.h" #include "third_party/blink/public/mojom/webauthn/authenticator.mojom-blink.h" +#include "third_party/blink/public/mojom/webid/digital_identity_request.mojom-blink.h" #include "third_party/blink/public/mojom/webid/federated_auth_request.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h" #include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h" @@ -76,10 +77,8 @@ using blink::mojom::blink::Hint; using blink::mojom::blink::IdentityCredentialDisconnectOptions; using blink::mojom::blink::IdentityCredentialDisconnectOptionsPtr; -using blink::mojom::blink::IdentityProvider; using blink::mojom::blink::IdentityProviderConfig; using blink::mojom::blink::IdentityProviderConfigPtr; -using blink::mojom::blink::IdentityProviderPtr; using blink::mojom::blink::IdentityProviderRequestOptions; using blink::mojom::blink::IdentityProviderRequestOptionsPtr; using blink::mojom::blink::IdentityUserInfo; @@ -898,22 +897,6 @@ } // static -IdentityProviderPtr -TypeConverter<IdentityProviderPtr, blink::IdentityProviderRequestOptions>:: - Convert(const blink::IdentityProviderRequestOptions& provider) { - if (provider.hasHolder() && - // TODO(https://crbug.com/1416939): make sure the Digital Credentials API - // works well with the Multiple IdP API. - !blink::RuntimeEnabledFeatures::FedCmMultipleIdentityProvidersEnabled()) { - auto mojo_provider = DigitalCredentialProvider::From(*provider.holder()); - return IdentityProvider::NewHolder(std::move(mojo_provider)); - } else { - auto config = IdentityProviderRequestOptions::From(provider); - return IdentityProvider::NewFederated(std::move(config)); - } -} - -// static DigitalCredentialProviderPtr TypeConverter<DigitalCredentialProviderPtr, blink::DigitalCredentialProvider>:: Convert(const blink::DigitalCredentialProvider& provider) {
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h index 1949a01b..e59bfa7 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h +++ b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h
@@ -10,6 +10,7 @@ #include "mojo/public/cpp/bindings/type_converter.h" #include "third_party/blink/public/mojom/credentialmanagement/credential_manager.mojom-blink.h" #include "third_party/blink/public/mojom/webauthn/authenticator.mojom-blink-forward.h" +#include "third_party/blink/public/mojom/webid/digital_identity_request.mojom-blink-forward.h" #include "third_party/blink/public/mojom/webid/federated_auth_request.mojom-blink-forward.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -228,13 +229,6 @@ }; template <> -struct TypeConverter<blink::mojom::blink::IdentityProviderPtr, - blink::IdentityProviderRequestOptions> { - static blink::mojom::blink::IdentityProviderPtr Convert( - const blink::IdentityProviderRequestOptions&); -}; - -template <> struct TypeConverter<blink::mojom::blink::DigitalCredentialProviderPtr, blink::DigitalCredentialProvider> { static blink::mojom::blink::DigitalCredentialProviderPtr Convert(
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc index d8a55a6..dad464e 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc +++ b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
@@ -2100,7 +2100,8 @@ WebFeature::kFedCmIdpSigninStatusApi); } int provider_index = 0; - Vector<mojom::blink::IdentityProviderPtr> identity_provider_ptrs; + Vector<mojom::blink::IdentityProviderRequestOptionsPtr> + identity_provider_ptrs; for (const auto& provider : identity_options.providers()) { if (provider->hasLoginHint()) { UseCounter::Count(resolver->GetExecutionContext(), @@ -2114,8 +2115,8 @@ if (blink::RuntimeEnabledFeatures::FedCmIdPRegistrationEnabled() && provider->hasConfigURL() && provider->configURL() == "any") { - mojom::blink::IdentityProviderPtr identity_provider = - blink::mojom::blink::IdentityProvider::From(*provider); + mojom::blink::IdentityProviderRequestOptionsPtr identity_provider = + blink::mojom::blink::IdentityProviderRequestOptions::From(*provider); identity_provider_ptrs.push_back(std::move(identity_provider)); continue; } @@ -2154,8 +2155,8 @@ return promise; } - mojom::blink::IdentityProviderPtr identity_provider = - blink::mojom::blink::IdentityProvider::From(*provider); + mojom::blink::IdentityProviderRequestOptionsPtr identity_provider = + blink::mojom::blink::IdentityProviderRequestOptions::From(*provider); identity_provider_ptrs.push_back(std::move(identity_provider)); }
diff --git a/third_party/blink/renderer/modules/credentialmanagement/web_identity_requester.cc b/third_party/blink/renderer/modules/credentialmanagement/web_identity_requester.cc index 8fab330..2eb8a50 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/web_identity_requester.cc +++ b/third_party/blink/renderer/modules/credentialmanagement/web_identity_requester.cc
@@ -110,7 +110,7 @@ return; } - Vector<mojom::blink::IdentityProviderPtr> idp_ptrs; + Vector<mojom::blink::IdentityProviderRequestOptionsPtr> idp_ptrs; Vector<KURL> idp_urls; for (const auto& provider : providers) { mojom::blink::IdentityProviderRequestOptionsPtr options = @@ -126,9 +126,7 @@ } } idp_urls.push_back(options->config->config_url); - mojom::blink::IdentityProviderPtr idp = - mojom::blink::IdentityProvider::NewFederated(std::move(options)); - idp_ptrs.push_back(std::move(idp)); + idp_ptrs.push_back(std::move(options)); } resolvers_and_providers_.emplace_back(
diff --git a/third_party/blink/renderer/modules/ml/ml_trace_unittest.cc b/third_party/blink/renderer/modules/ml/ml_trace_unittest.cc index fb4fc214..c70c8c2 100644 --- a/third_party/blink/renderer/modules/ml/ml_trace_unittest.cc +++ b/third_party/blink/renderer/modules/ml/ml_trace_unittest.cc
@@ -86,7 +86,10 @@ const std::string* trace_type = dict.FindString("ph"); CHECK(trace_type); // Count both the "BEGIN" and "END" traces. - if (*trace_type != "E" && *trace_type != "e") { + if (*trace_type == "n") { + ((event_counts)[*name].first)++; + ((event_counts)[*name].second)++; + } else if (*trace_type != "E" && *trace_type != "e") { ((event_counts)[*name].first)++; } else { ((event_counts)[*name].second)++;
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc index 61abafd1..89bf136 100644 --- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc +++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
@@ -726,9 +726,6 @@ info->rtc_configuration = SerializeConfiguration(config, pc_handler->encoded_insertable_streams()); - // TODO(https://crbug.com/1318448): Remove this line when mojo is updated. - info->constraints = ""; - if (frame) info->url = frame->GetDocument().Url().GetString(); else
diff --git a/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc b/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc index 00ff8f0..188214ce 100644 --- a/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc +++ b/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
@@ -467,6 +467,15 @@ return; } + // If the video is too short, it's unlikely to be cast. Disable availability + // monitoring so that the cast buttons are hidden from the video player. + if (!media_element_ || std::isnan(media_element_->duration()) || + media_element_->duration() <= kMinRemotingMediaDurationInSec) { + StopListeningForAvailability(); + availability_urls_.clear(); + return; + } + KURL current_url = availability_urls_.empty() ? KURL() : availability_urls_[0]; KURL new_url = GetAvailabilityUrl(source_, is_source_supported_, video_codec_,
diff --git a/third_party/blink/renderer/modules/remoteplayback/remote_playback_test.cc b/third_party/blink/renderer/modules/remoteplayback/remote_playback_test.cc index c2d9094..442ad5c 100644 --- a/third_party/blink/renderer/modules/remoteplayback/remote_playback_test.cc +++ b/third_party/blink/renderer/modules/remoteplayback/remote_playback_test.cc
@@ -62,6 +62,7 @@ page_holder_ = std::make_unique<DummyPageHolder>(); element_ = MakeGarbageCollected<HTMLVideoElement>(page_holder_->GetDocument()); + ChangeMediaElementDuration(60); } protected: @@ -89,6 +90,14 @@ *element_, html_names::kDisableremoteplaybackAttr, true); } + void ChangeMediaElementDuration(double duration) { + element_->DurationChanged(duration, false); + } + + void UpdateAvailabilityUrlsAndStartListening() { + get_remote_playback().UpdateAvailabilityUrlsAndStartListening(); + } + RemotePlayback& get_remote_playback() { return RemotePlayback::From(*element_); } @@ -341,10 +350,10 @@ EXPECT_CALL(*mock_controller, AddAvailabilityObserver(testing::Eq(&remote_playback))) - .Times(2); + .Times(3); EXPECT_CALL(*mock_controller, RemoveAvailabilityObserver(testing::Eq(&remote_playback))) - .Times(2); + .Times(3); MockFunction* callback_function = MakeGarbageCollected<MockFunction>(); V8RemotePlaybackAvailabilityCallback* availability_callback = @@ -379,6 +388,18 @@ ASSERT_TRUE(IsListening(remote_playback)); remote_playback.AvailabilityChanged(mojom::ScreenAvailability::AVAILABLE); + // Background monitoring is disabled for short videos. + ChangeMediaElementDuration(10); + UpdateAvailabilityUrlsAndStartListening(); + ASSERT_TRUE(remote_playback.Urls().empty()); + ASSERT_FALSE(IsListening(remote_playback)); + + ChangeMediaElementDuration(60); + UpdateAvailabilityUrlsAndStartListening(); + ASSERT_EQ((size_t)1, remote_playback.Urls().size()); + ASSERT_TRUE(IsListening(remote_playback)); + + // Background monitoring is disabled for invalid sources. remote_playback.SourceChanged(WebURL(), false); ASSERT_TRUE(remote_playback.Urls().empty()); ASSERT_FALSE(IsListening(remote_playback));
diff --git a/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.cc b/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.cc index d0e676f..a1560d2 100644 --- a/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.cc +++ b/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.cc
@@ -68,15 +68,6 @@ change, relative_to_state, transform_not_to_check); } -bool ClipPaintPropertyNodeOrAlias::ChangedExceptScroll( - PaintPropertyChangeType change, - const PropertyTreeState& relative_to_state, - const TransformPaintPropertyNodeOrAlias* transform_not_to_check) const { - return ChangedInternal< - &TransformPaintPropertyNodeOrAlias::ChangedExceptScroll>( - change, relative_to_state, transform_not_to_check); -} - void ClipPaintPropertyNodeOrAlias::ClearChangedToRoot( int sequence_number) const { for (auto* n = this; n && n->ChangedSequenceNumber() != sequence_number;
diff --git a/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h b/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h index f3de0c1..9defe95 100644 --- a/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h +++ b/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h
@@ -49,10 +49,6 @@ PaintPropertyChangeType change, const PropertyTreeState& relative_to_state, const TransformPaintPropertyNodeOrAlias* transform_not_to_check) const; - bool ChangedExceptScroll( - PaintPropertyChangeType change, - const PropertyTreeState& relative_to_state, - const TransformPaintPropertyNodeOrAlias* transform_not_to_check) const; void ClearChangedToRoot(int sequence_number) const;
diff --git a/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc b/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc index 62db6f3..f796682 100644 --- a/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc +++ b/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc
@@ -83,13 +83,6 @@ Effect().Changed(change, relative_to, &Transform()); } -bool PropertyTreeStateOrAlias::ChangedExceptScrollAndEffect( - PaintPropertyChangeType change, - const PropertyTreeState& relative_to) const { - return Transform().ChangedExceptScroll(change, relative_to.Transform()) || - Clip().ChangedExceptScroll(change, relative_to, &Transform()); -} - std::optional<PropertyTreeState> PropertyTreeState::CanUpcastWith( const PropertyTreeState& guest, IsCompositedScrollFunction is_composited_scroll) const {
diff --git a/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h b/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h index e06984fc..05d5a30 100644 --- a/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h +++ b/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h
@@ -84,8 +84,6 @@ bool ChangedToRoot(PaintPropertyChangeType change) const { return Changed(change, Root()); } - bool ChangedExceptScrollAndEffect(PaintPropertyChangeType change, - const PropertyTreeState& relative_to) const; String ToString() const; #if DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc b/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc index d64c4ee..9eb1862 100644 --- a/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc +++ b/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc
@@ -152,27 +152,6 @@ return relative_to_node.Changed(change, TransformPaintPropertyNode::Root()); } -bool TransformPaintPropertyNodeOrAlias::ChangedExceptScroll( - PaintPropertyChangeType change, - const TransformPaintPropertyNodeOrAlias& relative_to_node) const { - for (const auto* node = this; node; node = node->Parent()) { - if (node == &relative_to_node) { - return false; - } - if (!node->IsParentAlias() && - static_cast<const TransformPaintPropertyNode*>(node)->ScrollNode()) { - continue; - } - if (node->NodeChanged() >= change) { - return true; - } - } - - // |this| is not a descendant of |relative_to_node|. We have seen no changed - // flag from |this| to the root. Now check |relative_to_node| to the root. - return relative_to_node.Changed(change, TransformPaintPropertyNode::Root()); -} - std::unique_ptr<JSONObject> TransformPaintPropertyNode::ToJSON() const { auto json = ToJSONBase(); if (IsIdentityOr2dTranslation()) {
diff --git a/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h b/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h index 1614730..436bf27 100644 --- a/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h +++ b/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h
@@ -46,9 +46,6 @@ // changed status of the paths from |this| and |relative_to_node| to the root. bool Changed(PaintPropertyChangeType change, const TransformPaintPropertyNodeOrAlias& relative_to_node) const; - bool ChangedExceptScroll( - PaintPropertyChangeType change, - const TransformPaintPropertyNodeOrAlias& relative_to_node) const; void AddChanged(PaintPropertyChangeType changed) { DCHECK_NE(PaintPropertyChangeType::kUnchanged, changed);
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 3d52308..d5076ad 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -249,6 +249,7 @@ crbug.com/1412910 [ Mac ] virtual/view-transition/external/wpt/css/css-view-transitions/fractional-translation-from-transform.html [ Failure ] crbug.com/1430357 [ Mac ] virtual/view-transition/external/wpt/css/css-view-transitions/massive-element-* [ Failure Pass ] crbug.com/1430357 [ Mac ] virtual/view-transition-wide-gamut/external/wpt/css/css-view-transitions/massive-element-* [ Failure Pass ] +crbug.com/1430357 [ Win ] virtual/view-transition-wide-gamut/external/wpt/css/css-view-transitions/pseudo-with-classes-* [ Failure ] # View transition SPA failures with MPA serialization. crbug.com/1443559 [ Mac ] virtual/view-transition-mpa-serialization/external/wpt/css/css-view-transitions/fractional-translation-from-transform.html [ Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 266014a..325b759 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -175,7 +175,7 @@ "platforms": ["Linux", "Mac", "Win"], "bases": ["http/tests/inspector-protocol/attribution-reporting"], "exclusive_tests": "ALL", - "args": ["--enable-features=KeepAliveInBrowserMigration,kAttributionReportingInBrowserMigration,AttributionReportingCrossAppWeb,PrivacySandboxAdsAPIsOverride", + "args": ["--enable-features=KeepAliveInBrowserMigration,AttributionReportingInBrowserMigration,AttributionReportingCrossAppWeb,PrivacySandboxAdsAPIsOverride", "--disable-threaded-compositing", "--disable-threaded-animation"], "owners": ["anthonygarant@chromium.org"], "expires": "May 30, 2024"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/iframe-transition-destroyed-document-crash.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/iframe-transition-destroyed-document-crash.html new file mode 100644 index 0000000..31f6a10e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/iframe-transition-destroyed-document-crash.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transitions: crash test</title> +<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/"> +<link rel="author" href="mailto:vmpstr@chromium.org"> +<script src="/common/reftest-wait.js"></script> +<html> +<head> +<script> +function eventhandler1() { + var var00106 = htmlvar00011.contentDocument; + var var00228 = var00106.startViewTransition(); + requestAnimationFrame(() => { + requestAnimationFrame(() => { + requestAnimationFrame(takeScreenshot); + }) + }); +} + +</script> +</head> +<body> +<iframe id="htmlvar00011" onunload="eventhandler3()" border="0" srcdoc="A#:^;<gV<>8" style=":{,J" referrerpolicy="unsafe-url" background="!xp>" nohref="nohref" nonce="nonce" inputEncoding="s" offsetX="0.3538512271910753">:+j&;&-^>.7xf\jZ1,xb</iframe> +<style id="htmlvar00014" nonce="nonce" media="screen and (min-width:0px)" onerror="eventhandler1()" onload="eventhandler1()" dir="N5!" updateRangeEnd="0" abbr="4IvGMN[Wxd" symbols="=d##y#)DA4V8ya}KO.cv" frameBorder="^b*]&:|#lB:" search="N">ynFXo*</style> +</body> +</html> +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-entry.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-entry.html new file mode 100644 index 0000000..44f95dc --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-entry.html
@@ -0,0 +1,54 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transition classes: entry animation should consider view-transition-class from new state</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions-2/"> +<link rel="author" href="mailto:nrosenthal@chromium.org"> +<link rel="match" href="pseudo-with-classes-ref.html"> +<script src="/common/rendering-utils.js"></script> +<script src="/common/reftest-wait.js"></script> + +<style> +div { + width: 100px; + height: 100px; + position: absolute; +} + +#target { + background: green; +} + +#target.new-state { + view-transition-class: cls; + view-transition-name: target; +} + +@keyframes jump { + from { opacity: 1;} + to { opacity: 1;} +} + +::view-transition-group(*), +::view-transition-image-pair(*), +::view-transition-new(*) { + animation-name: jump; + animation-timing-function: step-start; + animation-duration: 1s; +} + +::view-transition-new(*.cls) { + left: 100px; +} + +</style> +<div id=target></div> + +<script> +failIfNot(document.startViewTransition, "Missing document.startViewTransition"); + +window.addEventListener("load", () => { + document.startViewTransition(() => { + document.getElementById("target").classList.add("new-state"); + }).ready.then(takeScreenshot); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-exit.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-exit.html new file mode 100644 index 0000000..c687461 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-exit.html
@@ -0,0 +1,54 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transition classes: exit animation should consider view-transition-class from old state</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions-2/"> +<link rel="author" href="mailto:nrosenthal@chromium.org"> +<link rel="match" href="pseudo-with-classes-ref.html"> +<script src="/common/rendering-utils.js"></script> +<script src="/common/reftest-wait.js"></script> + +<style> +div { + width: 100px; + height: 100px; + position: absolute; +} + +#target { + background: green; +} + +#target:not(.new-state) { + view-transition-class: cls; + view-transition-name: target; +} + +@keyframes jump { + from { opacity: 1;} + to { opacity: 1;} +} + +::view-transition-group(*), +::view-transition-image-pair(*), +::view-transition-old(*) { + animation-name: jump; + animation-timing-function: step-start; + animation-duration: 1s; +} + +::view-transition-old(*.cls) { + left: 100px; +} + +</style> +<div id=target></div> + +<script> +failIfNot(document.startViewTransition, "Missing document.startViewTransition"); + +window.addEventListener("load", () => { + document.startViewTransition(() => { + document.getElementById("target").classList.add("new-state"); + }).ready.then(takeScreenshot); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-ident.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-ident.html new file mode 100644 index 0000000..1418a90 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-ident.html
@@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transition classes: selector should match ident.class</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions-2/"> +<link rel="author" href="mailto:nrosenthal@chromium.org"> +<link rel="match" href="pseudo-with-classes-ref.html"> +<script src="/common/rendering-utils.js"></script> +<script src="/common/reftest-wait.js"></script> + +<style> +div { + width: 100px; + height: 100px; + position: absolute; +} + +#target { + background: green; + view-transition-name: target; + view-transition-class: cls; +} + +::view-transition-group(*) { + animation-duration: 1s; +} + +::view-transition-new(target.cls), +::view-transition-old(target.cls) { + left: 100px; +} + +</style> +<div id=target></div> + +<script> +failIfNot(document.startViewTransition, "Missing document.startViewTransition"); + +window.addEventListener("load", () => { + document.startViewTransition().ready.then(takeScreenshot); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-multiple-wildcard.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-multiple-wildcard.html new file mode 100644 index 0000000..53eaacf --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-multiple-wildcard.html
@@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transition classes: selector should match with wildcard and multiple classes</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions-2/"> +<link rel="author" href="mailto:nrosenthal@chromium.org"> +<link rel="match" href="pseudo-with-classes-ref.html"> +<script src="/common/rendering-utils.js"></script> +<script src="/common/reftest-wait.js"></script> + +<style> +div { + width: 100px; + height: 100px; + position: absolute; +} + +#target { + background: green; + view-transition-name: target; + view-transition-class: cls some-div; +} + +::view-transition-group(*) { + animation-duration: 1s; +} + +::view-transition-new(*.cls.some-div), +::view-transition-old(*.cls.some-div) { + left: 100px; +} + +</style> +<div id=target></div> + +<script> +failIfNot(document.startViewTransition, "Missing document.startViewTransition"); + +window.addEventListener("load", () => { + document.startViewTransition().ready.then(takeScreenshot); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-multiple.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-multiple.html new file mode 100644 index 0000000..1ab69340 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-multiple.html
@@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transition classes: selector should match with multiple classes</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions-2/"> +<link rel="author" href="mailto:nrosenthal@chromium.org"> +<link rel="match" href="pseudo-with-classes-ref.html"> +<script src="/common/rendering-utils.js"></script> +<script src="/common/reftest-wait.js"></script> + +<style> +div { + width: 100px; + height: 100px; + position: absolute; + view-transition-class: cls some-div; +} + +#target { + background: green; + view-transition-name: target; +} + +::view-transition-group(*) { + animation-duration: 1s; +} + +::view-transition-new(target.cls.some-div), +::view-transition-old(target.cls.some-div) { + left: 100px; +} + +</style> +<div id=target></div> + +<script> +failIfNot(document.startViewTransition, "Missing document.startViewTransition"); + +window.addEventListener("load", () => { + document.startViewTransition().ready.then(takeScreenshot); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-wildard.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-wildard.html new file mode 100644 index 0000000..13490d5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-wildard.html
@@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transition classes: selector should match with wildcard</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions-2/"> +<link rel="author" href="mailto:nrosenthal@chromium.org"> +<link rel="match" href="pseudo-with-classes-ref.html"> +<script src="/common/rendering-utils.js"></script> +<script src="/common/reftest-wait.js"></script> + +<style> +div { + width: 100px; + height: 100px; + position: absolute; +} + +#target { + background: green; + view-transition-name: target; + view-transition-class: cls; +} + +::view-transition-group(*) { + animation-duration: 1s; +} + +::view-transition-new(*.cls), +::view-transition-old(*.cls) { + left: 100px; +} + +</style> +<div id=target></div> + +<script> +failIfNot(document.startViewTransition, "Missing document.startViewTransition"); + +window.addEventListener("load", () => { + document.startViewTransition().ready.then(takeScreenshot); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-mismatch-ident.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-mismatch-ident.html new file mode 100644 index 0000000..97db64f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-mismatch-ident.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transition classes: selector should not match different ident</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions-2/"> +<link rel="author" href="mailto:nrosenthal@chromium.org"> +<link rel="match" href="pseudo-with-classes-ref.html"> +<script src="/common/rendering-utils.js"></script> +<script src="/common/reftest-wait.js"></script> + +<style> +div { + width: 100px; + height: 100px; + position: absolute; +} + +#target { + background: green; + view-transition-name: target; + view-transition-class: cls; +} + +::view-transition-group(*) { + animation-duration: 1s; +} + +::view-transition-new(*), +::view-transition-old(*) { + left: 100px; +} + +::view-transition-new(target.other), +::view-transition-old(target.other) { + left: 0; +} + +</style> +<div id=target></div> + +<script> +failIfNot(document.startViewTransition, "Missing document.startViewTransition"); + +window.addEventListener("load", () => { + document.startViewTransition().ready.then(takeScreenshot); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-mismatch-partial.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-mismatch-partial.html new file mode 100644 index 0000000..9d98380 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-mismatch-partial.html
@@ -0,0 +1,45 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transition classes: selector should not match if only some classes match</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions-2/"> +<link rel="author" href="mailto:nrosenthal@chromium.org"> +<link rel="match" href="pseudo-with-classes-ref.html"> +<script src="/common/rendering-utils.js"></script> +<script src="/common/reftest-wait.js"></script> + +<style> +div { + width: 100px; + height: 100px; + position: absolute; +} + +#target { + background: green; + view-transition-name: target; + view-transition-class: cls; +} + +::view-transition-group(*) { + animation-duration: 1s; +} + +::view-transition-new(*), +::view-transition-old(*) { + left: 100px; +} +::view-transition-new(target.cls.other), +::view-transition-old(target.cls.other) { + left: 0; +} + +</style> +<div id=target></div> + +<script> +failIfNot(document.startViewTransition, "Missing document.startViewTransition"); + +window.addEventListener("load", () => { + document.startViewTransition().ready.then(takeScreenshot); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-mismatch-wildcard.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-mismatch-wildcard.html new file mode 100644 index 0000000..722e413 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-mismatch-wildcard.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transition classes: selector should not match if only some classes match (with *)</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions-2/"> +<link rel="author" href="mailto:nrosenthal@chromium.org"> +<link rel="match" href="pseudo-with-classes-ref.html"> +<script src="/common/rendering-utils.js"></script> +<script src="/common/reftest-wait.js"></script> + +<style> +div { + width: 100px; + height: 100px; + position: absolute; +} + +#target { + background: green; + view-transition-name: target; + view-transition-class: cls; +} + +::view-transition-group(*) { + animation-duration: 1s; +} + +::view-transition-new(*), +::view-transition-old(*) { + left: 100px; +} + +::view-transition-new(*.other), +::view-transition-old(*.other) { + left: 0; +} + +</style> +<div id=target></div> + +<script> +failIfNot(document.startViewTransition, "Missing document.startViewTransition"); + +window.addEventListener("load", () => { + document.startViewTransition().ready.then(takeScreenshot); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-multiple-vt-classes.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-multiple-vt-classes.html new file mode 100644 index 0000000..d7ca0a0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-multiple-vt-classes.html
@@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transition classes: selector should match when view-transition-class has multiple idents</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions-2/"> +<link rel="author" href="mailto:nrosenthal@chromium.org"> +<link rel="match" href="pseudo-with-classes-ref.html"> +<script src="/common/rendering-utils.js"></script> +<script src="/common/reftest-wait.js"></script> + +<style> +div { + width: 100px; + height: 100px; + position: absolute; + view-transition-class: cls some-div; +} + +#target { + background: green; + view-transition-name: target; +} + +::view-transition-group(*) { + animation-duration: 1s; +} + +::view-transition-new(target.cls), +::view-transition-old(target.cls) { + left: 100px; +} + +</style> +<div id=target></div> + +<script> +failIfNot(document.startViewTransition, "Missing document.startViewTransition"); + +window.addEventListener("load", () => { + document.startViewTransition().ready.then(takeScreenshot); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-new-with-class-old-without.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-new-with-class-old-without.html new file mode 100644 index 0000000..5aedc33 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-new-with-class-old-without.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transition classes: view-transition-class should apply if applied only in new state</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions-2/"> +<link rel="author" href="mailto:nrosenthal@chromium.org"> +<link rel="match" href="pseudo-with-classes-ref.html"> +<script src="/common/rendering-utils.js"></script> +<script src="/common/reftest-wait.js"></script> + +<style> +div { + width: 100px; + height: 100px; + position: absolute; +} + +#target { + background: green; + view-transition-name: target; +} + +#target.new-state { + view-transition-class: cls; +} + +::view-transition-group(*) { + animation-duration: 1s; +} + +::view-transition-new(*.cls), +::view-transition-old(*.cls) { + left: 100px; +} + +</style> +<div id=target></div> + +<script> +failIfNot(document.startViewTransition, "Missing document.startViewTransition"); + +window.addEventListener("load", () => { + document.startViewTransition(() => { + document.getElementById("target").classList.add("new-state"); + }).ready.then(takeScreenshot); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-old-with-class-new-without.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-old-with-class-new-without.html new file mode 100644 index 0000000..6c15325 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-old-with-class-new-without.html
@@ -0,0 +1,51 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transition classes: view-transition-class should not apply if applied only in old state</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions-2/"> +<link rel="author" href="mailto:nrosenthal@chromium.org"> +<link rel="match" href="pseudo-with-classes-ref.html"> +<script src="/common/rendering-utils.js"></script> +<script src="/common/reftest-wait.js"></script> + +<style> +div { + width: 100px; + height: 100px; + position: absolute; +} + +#target { + background: green; + view-transition-name: target; +} + +#target:not(.new-state) { + view-transition-class: cls; +} + +::view-transition-group(*) { + animation-duration: 1s; +} + +::view-transition-new(*), +::view-transition-old(*) { + left: 100px; +} + +::view-transition-new(*.cls), +::view-transition-old(*.cls) { + left: 0; +} + +</style> +<div id=target></div> + +<script> +failIfNot(document.startViewTransition, "Missing document.startViewTransition"); + +window.addEventListener("load", () => { + document.startViewTransition(() => { + document.querySelector("#target").classList.add("new-state"); + }).ready.then(takeScreenshot); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-ref.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-ref.html new file mode 100644 index 0000000..89b3a8a7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-ref.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<title>View transitions: reference expectation</title> +<style> +div { + position: relative; + left: 100px; + width: 100px; + height: 100px; + background: green; +} +</style> +<body> +<div></div> +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-view-transition-group.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-view-transition-group.html new file mode 100644 index 0000000..3e4dbb3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-view-transition-group.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transition classes: group selectors should respect classes</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions-2/"> +<link rel="author" href="mailto:nrosenthal@chromium.org"> +<link rel="match" href="pseudo-with-classes-ref.html"> +<script src="/common/rendering-utils.js"></script> +<script src="/common/reftest-wait.js"></script> + +<style> +#target { + width: 100px; + height: 100px; + position: absolute; + background: green; + view-transition-name: target; + view-transition-class: cls; +} + +:root::view-transition-group(*) { + animation-duration: 1s; +} + +:root::view-transition-group(target.cls) { + left: 100px; +} + +</style> +<div id=target></div> + +<script> +failIfNot(document.startViewTransition, "Missing document.startViewTransition"); + +window.addEventListener("load", () => { + document.startViewTransition().ready.then(requestAnimationFrame(() => takeScreenshot())); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-view-transition-image-pair.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-view-transition-image-pair.html new file mode 100644 index 0000000..8f0f2ef2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-view-transition-image-pair.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transition classes: group selectors should respect classes</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions-2/"> +<link rel="author" href="mailto:nrosenthal@chromium.org"> +<link rel="match" href="pseudo-with-classes-ref.html"> +<script src="/common/rendering-utils.js"></script> +<script src="/common/reftest-wait.js"></script> + +<style> +#target { + width: 100px; + height: 100px; + position: absolute; + background: green; + view-transition-name: target; + view-transition-class: cls; +} + +::view-transition-group(*) { + animation-duration: 1s; +} + +::view-transition-image-pair(target.cls) { + transform: translateX(100px); +} + +</style> +<div id=target></div> + +<script> +failIfNot(document.startViewTransition, "Missing document.startViewTransition"); + +window.addEventListener("load", () => { + document.startViewTransition().ready.then(requestAnimationFrame(() => takeScreenshot())); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/generic-sensor/generic-sensor-iframe-tests.sub.js b/third_party/blink/web_tests/external/wpt/generic-sensor/generic-sensor-iframe-tests.sub.js index 8f13bd77..ed3415e 100644 --- a/third_party/blink/web_tests/external/wpt/generic-sensor/generic-sensor-iframe-tests.sub.js +++ b/third_party/blink/web_tests/external/wpt/generic-sensor/generic-sensor-iframe-tests.sub.js
@@ -147,24 +147,21 @@ sensor.stop(); await send_message_to_iframe(iframe, {command: 'stop_sensor'}); + // The sensors are stopped; queue the same reading. The virtual sensor + // would send it anyway, but this update changes its timestamp. + await test_driver.update_virtual_sensor(testDriverName, reading); + // Now focus the cross-origin iframe. The situation should be the opposite: // the sensor in the main frame should not fire any "reading" events or // provide access to updated readings, but the sensor in the iframe should. iframe.contentWindow.focus(); - // Start both sensors. They should both have the same state: active, but no - // readings have been provided to them yet. - await send_message_to_iframe(iframe, {command: 'start_sensor'}); + // Start both sensors. Only the iframe sensor should receive a reading + // event and contain readings. sensor.start(); await sensorWatcher.wait_for('activate'); - assert_false( - await send_message_to_iframe(iframe, {command: 'has_reading'})); - assert_false(sensor.hasReading); - - const [serializedIframeSensor] = await Promise.all([ - iframeSensorWatcher.wait_for_reading(), - test_driver.update_virtual_sensor(testDriverName, reading), - ]); + await send_message_to_iframe(iframe, {command: 'start_sensor'}); + const serializedIframeSensor = await iframeSensorWatcher.wait_for_reading(); assert_true(await send_message_to_iframe(iframe, {command: 'has_reading'})); assert_false(sensor.hasReading); @@ -225,25 +222,17 @@ // Focus a different same-origin window each time and check that everything // works the same. for (const windowObject of [window, iframe.contentWindow]) { + await test_driver.update_virtual_sensor( + testDriverName, readings.next().value); + windowObject.focus(); iframeSensor.start(); sensor.start(); - await Promise.all([ - iframeSensorWatcher.wait_for('activate'), - sensorWatcher.wait_for('activate') - ]); - assert_false(sensor.hasReading); - assert_false(iframeSensor.hasReading); - - // We store `reading` here because we want to make sure the very same - // value is accepted later. - const reading = readings.next().value; await Promise.all([ - test_driver.update_virtual_sensor(testDriverName, reading), - iframeSensorWatcher.wait_for('reading'), - sensorWatcher.wait_for('reading') + iframeSensorWatcher.wait_for(['activate', 'reading']), + sensorWatcher.wait_for(['activate', 'reading']) ]); assert_greater_than(
diff --git a/third_party/blink/web_tests/external/wpt/generic-sensor/generic-sensor-tests.js b/third_party/blink/web_tests/external/wpt/generic-sensor/generic-sensor-tests.js index 292b562f..b4ed225 100644 --- a/third_party/blink/web_tests/external/wpt/generic-sensor/generic-sensor-tests.js +++ b/third_party/blink/web_tests/external/wpt/generic-sensor/generic-sensor-tests.js
@@ -429,16 +429,16 @@ assert_false(sensor.hasReading); assert_false(sensor.activated); + readings.reset(); + await test_driver.update_virtual_sensor( + testDriverName, readings.next().value); + sensor.start(); + // Starting |sensor| again will cause the backing virtual sensor to report + // the previous reading automatically. await sensorWatcher.wait_for('activate'); - assert_false(sensor.hasReading); - readings.reset(); - await Promise.all([ - test_driver.update_virtual_sensor(testDriverName, readings.next().value), - sensorWatcher.wait_for('reading') - ]); - assert_true(sensor.hasReading); + await sensorWatcher.wait_for('reading'); assert_sensor_reading_equals(sensor, expected); // Make sure that 'timestamp' is already initialized. @@ -607,7 +607,8 @@ const eventWatcher = new EventWatcher(t, sensor1, ['activate']); sensor1.start(); await eventWatcher.wait_for('activate'); - test_driver.update_virtual_sensor(testDriverName, readings.next().value); + await test_driver.update_virtual_sensor( + testDriverName, readings.next().value); }); }, `${sensorName}: Readings delivered by shared platform sensor are\ immediately accessible to all sensors.`);
diff --git a/third_party/blink/web_tests/virtual/attribution-reporting-in-browser-migration/README.md b/third_party/blink/web_tests/virtual/attribution-reporting-in-browser-migration/README.md index 8795acc..01243b6 100644 --- a/third_party/blink/web_tests/virtual/attribution-reporting-in-browser-migration/README.md +++ b/third_party/blink/web_tests/virtual/attribution-reporting-in-browser-migration/README.md
@@ -1,7 +1,7 @@ # Tests for Attribution Reporting APIs with the in-browser migration enabled This virtual test suite covers a subset of Attribution Reporting APIs tests with -the `KeepAliveInBrowserMigration` and `kAttributionReportingInBrowserMigration` +the `KeepAliveInBrowserMigration` and `AttributionReportingInBrowserMigration` flags enabled. These flags enable a new flow where attribution responses are processed in the
diff --git a/third_party/blink/web_tests/wpt_internal/generic-sensor/virtual-sensor-updates.https.window.js b/third_party/blink/web_tests/wpt_internal/generic-sensor/virtual-sensor-updates.https.window.js index b6bc7d3..6c54daed 100644 --- a/third_party/blink/web_tests/wpt_internal/generic-sensor/virtual-sensor-updates.https.window.js +++ b/third_party/blink/web_tests/wpt_internal/generic-sensor/virtual-sensor-updates.https.window.js
@@ -40,6 +40,36 @@ const sensorWatcher = new EventWatcher(t, sensor, ['activate', 'reading', 'error']); + await test_driver.update_virtual_sensor('accelerometer', {x: 1, y: 2, z: 3}); + + sensor.start(); + await sensorWatcher.wait_for(['activate', 'reading']); + + const timestamp = sensor.timestamp; + + sensor.stop(); + + assert_equals(sensor.timestamp, null); + + sensor.start(); + await sensorWatcher.wait_for(['activate', 'reading']); + + assert_sensor_reading_equals(sensor, {x: 1, y: 2, z: 3}); + assert_equals(sensor.timestamp, timestamp); +}, 'Updates are sent automatically on sensor reactivation'); + +promise_test(async t => { + await test_driver.set_permission({name: 'accelerometer'}, 'granted'); + await test_driver.create_virtual_sensor('accelerometer'); + + const sensor = new Accelerometer; + t.add_cleanup(async () => { + sensor.stop(); + await test_driver.remove_virtual_sensor('accelerometer'); + }); + const sensorWatcher = + new EventWatcher(t, sensor, ['activate', 'reading', 'error']); + sensor.start(); await sensorWatcher.wait_for('activate'); @@ -109,3 +139,45 @@ // before the virtual sensor was removed. await new Promise(resolve => {t.step_timeout(resolve, 700)}); }, 'Stashed readings do not persist across virtual sensor creations'); + +promise_test(async t => { + await test_driver.set_permission({name: 'accelerometer'}, 'granted'); + await test_driver.create_virtual_sensor('accelerometer'); + t.add_cleanup(async () => { + await test_driver.remove_virtual_sensor('accelerometer'); + }); + await test_driver.update_virtual_sensor('accelerometer', {x: 1, y: 2, z: 3}); + + const iframe = document.createElement('iframe'); + iframe.src = 'https://{{host}}:{{ports[https][0]}}/resources/blank.html'; + const iframeLoadWatcher = new EventWatcher(t, iframe, 'load'); + t.add_cleanup(() => { + if (iframe.parentNode) { + iframe.parentNode.removeChild(iframe); + } + }); + + async function createAndTestIframeSensor() { + document.body.appendChild(iframe); + await iframeLoadWatcher.wait_for('load'); + const iframeSensor = new iframe.contentWindow['Accelerometer'](); + t.add_cleanup(() => { + iframeSensor.stop(); + }); + const iframeSensorWatcher = + new EventWatcher(t, iframeSensor, ['activate', 'error', 'reading']); + + iframe.contentWindow.focus(); + iframeSensor.start(); + await iframeSensorWatcher.wait_for(['activate', 'reading']); + assert_sensor_reading_equals(iframeSensor, {x: 1, y: 2, z: 3}); + iframeSensor.stop(); + } + + // We want to test that virtual sensor readings persist until + // remove_virtual_sensor() is called, even if the entire frame that was using + // a Sensor is removed. + await createAndTestIframeSensor(); + iframe.parentNode.removeChild(iframe); + await createAndTestIframeSensor(); +}, 'Updates persist when frame with Sensor is removed');
diff --git a/third_party/chromite b/third_party/chromite index 0ab00d0..2569b03 160000 --- a/third_party/chromite +++ b/third_party/chromite
@@ -1 +1 @@ -Subproject commit 0ab00d0ab4c48eb09ff9a359365c55528ef2bbb5 +Subproject commit 2569b035e6b1b0e6106a918833d8c53b70fd35db
diff --git a/third_party/chromium-variations b/third_party/chromium-variations index 8460157..ba4353a 160000 --- a/third_party/chromium-variations +++ b/third_party/chromium-variations
@@ -1 +1 @@ -Subproject commit 8460157bc5ad13094b0e93276c7387b47932195d +Subproject commit ba4353a41f7f9074baa98a77f39e6be03bd26368
diff --git a/third_party/cros_system_api b/third_party/cros_system_api index e5f61ee..84b44fd 160000 --- a/third_party/cros_system_api +++ b/third_party/cros_system_api
@@ -1 +1 @@ -Subproject commit e5f61ee71226157479ebc9f10f5184af1c1b6ce6 +Subproject commit 84b44fd2f0decdc029779c1d12c0ed70a10c511e
diff --git a/third_party/depot_tools b/third_party/depot_tools index 74a6ca9..3569608 160000 --- a/third_party/depot_tools +++ b/third_party/depot_tools
@@ -1 +1 @@ -Subproject commit 74a6ca92bba677fc87328637bf573deb5944ac91 +Subproject commit 35696080284a2d59a8972ca27b509ebc1edc08ef
diff --git a/third_party/jni_zero/proguard.flags b/third_party/jni_zero/proguard.flags index cadffdd..3097917 100644 --- a/third_party/jni_zero/proguard.flags +++ b/third_party/jni_zero/proguard.flags
@@ -12,8 +12,3 @@ -keepclasseswithmembers,includedescriptorclasses,allowaccessmodification class ** { @org.jni_zero.CalledByNativeUnchecked <methods>; } - -# Allow unused native methods to be removed, but prevent renaming on those that are kept. --keepclasseswithmembernames,includedescriptorclasses,allowaccessmodification class org.jni_zero.*,J.N,J.*_N { - native <methods>; -}
diff --git a/third_party/libc++/src b/third_party/libc++/src index c51c9efb..9d119c1 160000 --- a/third_party/libc++/src +++ b/third_party/libc++/src
@@ -1 +1 @@ -Subproject commit c51c9efb6c5a83e0e25c1e30864449d2beadd7a8 +Subproject commit 9d119c1f4a097b7d27210874f4eba3fc91a83a4e
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium index ba18b21b..fe7d42a3 100644 --- a/third_party/libvpx/README.chromium +++ b/third_party/libvpx/README.chromium
@@ -1,7 +1,7 @@ Name: libvpx URL: https://chromium.googlesource.com/webm/libvpx Version: N/A -Revision: c35f3e9e3512d0012180ad8de8834d8813a80b73 +Revision: 96b64eaac5adbac59e43e34d87af3ba0fb06bca6 CPEPrefix: cpe:/a:webmproject:libvpx:1.14.0 License: BSD License File: source/libvpx/LICENSE
diff --git a/third_party/libvpx/libvpx_srcs.gni b/third_party/libvpx/libvpx_srcs.gni index e44a06bc..0d3afce 100644 --- a/third_party/libvpx/libvpx_srcs.gni +++ b/third_party/libvpx/libvpx_srcs.gni
@@ -2664,7 +2664,10 @@ libvpx_srcs_arm64_neon_i8mm = [ "//third_party/libvpx/source/libvpx/vpx_dsp/arm/vpx_convolve8_neon_i8mm.c", ] -libvpx_srcs_arm64_sve = [] +libvpx_srcs_arm64_sve = [ + "//third_party/libvpx/source/libvpx/vp9/encoder/arm/neon/vp9_error_sve.c", + "//third_party/libvpx/source/libvpx/vpx_dsp/arm/sum_squares_sve.c", +] libvpx_srcs_arm_neon_highbd = [ "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.c", "//third_party/libvpx/source/libvpx/vp8/common/arm/loopfilter_arm.c", @@ -3597,8 +3600,11 @@ libvpx_srcs_arm64_highbd_neon_i8mm = [ "//third_party/libvpx/source/libvpx/vpx_dsp/arm/vpx_convolve8_neon_i8mm.c", ] -libvpx_srcs_arm64_highbd_sve = - [ "//third_party/libvpx/source/libvpx/vpx_dsp/arm/highbd_variance_sve.c" ] +libvpx_srcs_arm64_highbd_sve = [ + "//third_party/libvpx/source/libvpx/vp9/encoder/arm/neon/vp9_error_sve.c", + "//third_party/libvpx/source/libvpx/vpx_dsp/arm/highbd_variance_sve.c", + "//third_party/libvpx/source/libvpx/vpx_dsp/arm/sum_squares_sve.c", +] libvpx_srcs_mips = [ "//third_party/libvpx/source/libvpx/vp8/common/alloccommon.c", "//third_party/libvpx/source/libvpx/vp8/common/blockd.c",
diff --git a/third_party/libvpx/source/config/ios/arm-neon/vpx_config.asm b/third_party/libvpx/source/config/ios/arm-neon/vpx_config.asm index cae979c..6d6bc0f 100644 --- a/third_party/libvpx/source/config/ios/arm-neon/vpx_config.asm +++ b/third_party/libvpx/source/config/ios/arm-neon/vpx_config.asm
@@ -48,6 +48,7 @@ .equ CONFIG_INSTALL_LIBS , 1 .equ CONFIG_INSTALL_SRCS , 0 .equ CONFIG_DEBUG , 0 +.equ CONFIG_PROFILE , 0 .equ CONFIG_GPROF , 0 .equ CONFIG_GCOV , 0 .equ CONFIG_RVCT , 0
diff --git a/third_party/libvpx/source/config/ios/arm-neon/vpx_config.h b/third_party/libvpx/source/config/ios/arm-neon/vpx_config.h index 524ade7b..11567da 100644 --- a/third_party/libvpx/source/config/ios/arm-neon/vpx_config.h +++ b/third_party/libvpx/source/config/ios/arm-neon/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/ios/arm64/vp9_rtcd.h b/third_party/libvpx/source/config/ios/arm64/vp9_rtcd.h index 4c2a4ada..d9c47be 100644 --- a/third_party/libvpx/source/config/ios/arm64/vp9_rtcd.h +++ b/third_party/libvpx/source/config/ios/arm64/vp9_rtcd.h
@@ -41,7 +41,14 @@ const tran_low_t* dqcoeff, intptr_t block_size, int64_t* ssz); -#define vp9_block_error vp9_block_error_neon +int64_t vp9_block_error_sve(const tran_low_t* coeff, + const tran_low_t* dqcoeff, + intptr_t block_size, + int64_t* ssz); +RTCD_EXTERN int64_t (*vp9_block_error)(const tran_low_t* coeff, + const tran_low_t* dqcoeff, + intptr_t block_size, + int64_t* ssz); int64_t vp9_block_error_fp_c(const tran_low_t* coeff, const tran_low_t* dqcoeff, @@ -49,7 +56,12 @@ int64_t vp9_block_error_fp_neon(const tran_low_t* coeff, const tran_low_t* dqcoeff, int block_size); -#define vp9_block_error_fp vp9_block_error_fp_neon +int64_t vp9_block_error_fp_sve(const tran_low_t* coeff, + const tran_low_t* dqcoeff, + int block_size); +RTCD_EXTERN int64_t (*vp9_block_error_fp)(const tran_low_t* coeff, + const tran_low_t* dqcoeff, + int block_size); int vp9_denoiser_filter_c(const uint8_t* sig, int sig_stride, @@ -226,6 +238,15 @@ int flags = arm_cpu_caps(); (void)flags; + + vp9_block_error = vp9_block_error_neon; + if (flags & HAS_SVE) { + vp9_block_error = vp9_block_error_sve; + } + vp9_block_error_fp = vp9_block_error_fp_neon; + if (flags & HAS_SVE) { + vp9_block_error_fp = vp9_block_error_fp_sve; + } } #endif
diff --git a/third_party/libvpx/source/config/ios/arm64/vpx_config.asm b/third_party/libvpx/source/config/ios/arm64/vpx_config.asm index 93f23af..67426f8 100644 --- a/third_party/libvpx/source/config/ios/arm64/vpx_config.asm +++ b/third_party/libvpx/source/config/ios/arm64/vpx_config.asm
@@ -48,6 +48,7 @@ .equ CONFIG_INSTALL_LIBS , 1 .equ CONFIG_INSTALL_SRCS , 0 .equ CONFIG_DEBUG , 0 +.equ CONFIG_PROFILE , 0 .equ CONFIG_GPROF , 0 .equ CONFIG_GCOV , 0 .equ CONFIG_RVCT , 0
diff --git a/third_party/libvpx/source/config/ios/arm64/vpx_config.h b/third_party/libvpx/source/config/ios/arm64/vpx_config.h index 7fd76e9..724dfecf5 100644 --- a/third_party/libvpx/source/config/ios/arm64/vpx_config.h +++ b/third_party/libvpx/source/config/ios/arm64/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h index 66121b7..0e5bfd9 100644 --- a/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h
@@ -3106,7 +3106,10 @@ uint64_t vpx_sum_squares_2d_i16_c(const int16_t* src, int stride, int size); uint64_t vpx_sum_squares_2d_i16_neon(const int16_t* src, int stride, int size); -#define vpx_sum_squares_2d_i16 vpx_sum_squares_2d_i16_neon +uint64_t vpx_sum_squares_2d_i16_sve(const int16_t* src, int stride, int size); +RTCD_EXTERN uint64_t (*vpx_sum_squares_2d_i16)(const int16_t* src, + int stride, + int size); void vpx_tm_predictor_16x16_c(uint8_t* dst, ptrdiff_t stride, @@ -3716,6 +3719,10 @@ if (flags & HAS_NEON_DOTPROD) { vpx_sse = vpx_sse_neon_dotprod; } + vpx_sum_squares_2d_i16 = vpx_sum_squares_2d_i16_neon; + if (flags & HAS_SVE) { + vpx_sum_squares_2d_i16 = vpx_sum_squares_2d_i16_sve; + } vpx_variance16x16 = vpx_variance16x16_neon; if (flags & HAS_NEON_DOTPROD) { vpx_variance16x16 = vpx_variance16x16_neon_dotprod;
diff --git a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.asm b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.asm index be8b95fe..ac58b44 100644 --- a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.asm +++ b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.asm
@@ -47,6 +47,7 @@ .equ CONFIG_INSTALL_LIBS , 1 .equ CONFIG_INSTALL_SRCS , 0 .equ CONFIG_DEBUG , 0 +.equ CONFIG_PROFILE , 0 .equ CONFIG_GPROF , 0 .equ CONFIG_GCOV , 0 .equ CONFIG_RVCT , 0
diff --git a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.h b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.h index 2795965..10fe24b 100644 --- a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.h +++ b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/linux/arm-neon-highbd/vpx_config.asm b/third_party/libvpx/source/config/linux/arm-neon-highbd/vpx_config.asm index 2234002..7e83e9f 100644 --- a/third_party/libvpx/source/config/linux/arm-neon-highbd/vpx_config.asm +++ b/third_party/libvpx/source/config/linux/arm-neon-highbd/vpx_config.asm
@@ -47,6 +47,7 @@ .equ CONFIG_INSTALL_LIBS , 1 .equ CONFIG_INSTALL_SRCS , 0 .equ CONFIG_DEBUG , 0 +.equ CONFIG_PROFILE , 0 .equ CONFIG_GPROF , 0 .equ CONFIG_GCOV , 0 .equ CONFIG_RVCT , 0
diff --git a/third_party/libvpx/source/config/linux/arm-neon-highbd/vpx_config.h b/third_party/libvpx/source/config/linux/arm-neon-highbd/vpx_config.h index 98113cf..4e100fb8 100644 --- a/third_party/libvpx/source/config/linux/arm-neon-highbd/vpx_config.h +++ b/third_party/libvpx/source/config/linux/arm-neon-highbd/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/linux/arm-neon/vpx_config.asm b/third_party/libvpx/source/config/linux/arm-neon/vpx_config.asm index 4858a5cc..45f8559 100644 --- a/third_party/libvpx/source/config/linux/arm-neon/vpx_config.asm +++ b/third_party/libvpx/source/config/linux/arm-neon/vpx_config.asm
@@ -47,6 +47,7 @@ .equ CONFIG_INSTALL_LIBS , 1 .equ CONFIG_INSTALL_SRCS , 0 .equ CONFIG_DEBUG , 0 +.equ CONFIG_PROFILE , 0 .equ CONFIG_GPROF , 0 .equ CONFIG_GCOV , 0 .equ CONFIG_RVCT , 0
diff --git a/third_party/libvpx/source/config/linux/arm-neon/vpx_config.h b/third_party/libvpx/source/config/linux/arm-neon/vpx_config.h index 524ade7b..11567da 100644 --- a/third_party/libvpx/source/config/linux/arm-neon/vpx_config.h +++ b/third_party/libvpx/source/config/linux/arm-neon/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/linux/arm/vpx_config.asm b/third_party/libvpx/source/config/linux/arm/vpx_config.asm index a96f04d..63a0971d 100644 --- a/third_party/libvpx/source/config/linux/arm/vpx_config.asm +++ b/third_party/libvpx/source/config/linux/arm/vpx_config.asm
@@ -47,6 +47,7 @@ .equ CONFIG_INSTALL_LIBS , 1 .equ CONFIG_INSTALL_SRCS , 0 .equ CONFIG_DEBUG , 0 +.equ CONFIG_PROFILE , 0 .equ CONFIG_GPROF , 0 .equ CONFIG_GCOV , 0 .equ CONFIG_RVCT , 0
diff --git a/third_party/libvpx/source/config/linux/arm/vpx_config.h b/third_party/libvpx/source/config/linux/arm/vpx_config.h index 36b136b..98d88da 100644 --- a/third_party/libvpx/source/config/linux/arm/vpx_config.h +++ b/third_party/libvpx/source/config/linux/arm/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/linux/arm64-highbd/vp9_rtcd.h b/third_party/libvpx/source/config/linux/arm64-highbd/vp9_rtcd.h index e64cb2c..53900f3 100644 --- a/third_party/libvpx/source/config/linux/arm64-highbd/vp9_rtcd.h +++ b/third_party/libvpx/source/config/linux/arm64-highbd/vp9_rtcd.h
@@ -41,7 +41,14 @@ const tran_low_t* dqcoeff, intptr_t block_size, int64_t* ssz); -#define vp9_block_error vp9_block_error_neon +int64_t vp9_block_error_sve(const tran_low_t* coeff, + const tran_low_t* dqcoeff, + intptr_t block_size, + int64_t* ssz); +RTCD_EXTERN int64_t (*vp9_block_error)(const tran_low_t* coeff, + const tran_low_t* dqcoeff, + intptr_t block_size, + int64_t* ssz); int64_t vp9_block_error_fp_c(const tran_low_t* coeff, const tran_low_t* dqcoeff, @@ -49,7 +56,12 @@ int64_t vp9_block_error_fp_neon(const tran_low_t* coeff, const tran_low_t* dqcoeff, int block_size); -#define vp9_block_error_fp vp9_block_error_fp_neon +int64_t vp9_block_error_fp_sve(const tran_low_t* coeff, + const tran_low_t* dqcoeff, + int block_size); +RTCD_EXTERN int64_t (*vp9_block_error_fp)(const tran_low_t* coeff, + const tran_low_t* dqcoeff, + int block_size); int vp9_denoiser_filter_c(const uint8_t* sig, int sig_stride, @@ -381,6 +393,15 @@ int flags = arm_cpu_caps(); (void)flags; + + vp9_block_error = vp9_block_error_neon; + if (flags & HAS_SVE) { + vp9_block_error = vp9_block_error_sve; + } + vp9_block_error_fp = vp9_block_error_fp_neon; + if (flags & HAS_SVE) { + vp9_block_error_fp = vp9_block_error_fp_sve; + } } #endif
diff --git a/third_party/libvpx/source/config/linux/arm64-highbd/vpx_config.asm b/third_party/libvpx/source/config/linux/arm64-highbd/vpx_config.asm index 8fd3212..1a91df6 100644 --- a/third_party/libvpx/source/config/linux/arm64-highbd/vpx_config.asm +++ b/third_party/libvpx/source/config/linux/arm64-highbd/vpx_config.asm
@@ -47,6 +47,7 @@ .equ CONFIG_INSTALL_LIBS , 1 .equ CONFIG_INSTALL_SRCS , 0 .equ CONFIG_DEBUG , 0 +.equ CONFIG_PROFILE , 0 .equ CONFIG_GPROF , 0 .equ CONFIG_GCOV , 0 .equ CONFIG_RVCT , 0
diff --git a/third_party/libvpx/source/config/linux/arm64-highbd/vpx_config.h b/third_party/libvpx/source/config/linux/arm64-highbd/vpx_config.h index 8c8fedb..90cb57dc 100644 --- a/third_party/libvpx/source/config/linux/arm64-highbd/vpx_config.h +++ b/third_party/libvpx/source/config/linux/arm64-highbd/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/linux/arm64-highbd/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm64-highbd/vpx_dsp_rtcd.h index 8d4ecda..2f918f6 100644 --- a/third_party/libvpx/source/config/linux/arm64-highbd/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/arm64-highbd/vpx_dsp_rtcd.h
@@ -7872,7 +7872,10 @@ uint64_t vpx_sum_squares_2d_i16_c(const int16_t* src, int stride, int size); uint64_t vpx_sum_squares_2d_i16_neon(const int16_t* src, int stride, int size); -#define vpx_sum_squares_2d_i16 vpx_sum_squares_2d_i16_neon +uint64_t vpx_sum_squares_2d_i16_sve(const int16_t* src, int stride, int size); +RTCD_EXTERN uint64_t (*vpx_sum_squares_2d_i16)(const int16_t* src, + int stride, + int size); void vpx_tm_predictor_16x16_c(uint8_t* dst, ptrdiff_t stride, @@ -8710,6 +8713,10 @@ if (flags & HAS_NEON_DOTPROD) { vpx_sse = vpx_sse_neon_dotprod; } + vpx_sum_squares_2d_i16 = vpx_sum_squares_2d_i16_neon; + if (flags & HAS_SVE) { + vpx_sum_squares_2d_i16 = vpx_sum_squares_2d_i16_sve; + } vpx_variance16x16 = vpx_variance16x16_neon; if (flags & HAS_NEON_DOTPROD) { vpx_variance16x16 = vpx_variance16x16_neon_dotprod;
diff --git a/third_party/libvpx/source/config/linux/arm64/vp9_rtcd.h b/third_party/libvpx/source/config/linux/arm64/vp9_rtcd.h index 4c2a4ada..d9c47be 100644 --- a/third_party/libvpx/source/config/linux/arm64/vp9_rtcd.h +++ b/third_party/libvpx/source/config/linux/arm64/vp9_rtcd.h
@@ -41,7 +41,14 @@ const tran_low_t* dqcoeff, intptr_t block_size, int64_t* ssz); -#define vp9_block_error vp9_block_error_neon +int64_t vp9_block_error_sve(const tran_low_t* coeff, + const tran_low_t* dqcoeff, + intptr_t block_size, + int64_t* ssz); +RTCD_EXTERN int64_t (*vp9_block_error)(const tran_low_t* coeff, + const tran_low_t* dqcoeff, + intptr_t block_size, + int64_t* ssz); int64_t vp9_block_error_fp_c(const tran_low_t* coeff, const tran_low_t* dqcoeff, @@ -49,7 +56,12 @@ int64_t vp9_block_error_fp_neon(const tran_low_t* coeff, const tran_low_t* dqcoeff, int block_size); -#define vp9_block_error_fp vp9_block_error_fp_neon +int64_t vp9_block_error_fp_sve(const tran_low_t* coeff, + const tran_low_t* dqcoeff, + int block_size); +RTCD_EXTERN int64_t (*vp9_block_error_fp)(const tran_low_t* coeff, + const tran_low_t* dqcoeff, + int block_size); int vp9_denoiser_filter_c(const uint8_t* sig, int sig_stride, @@ -226,6 +238,15 @@ int flags = arm_cpu_caps(); (void)flags; + + vp9_block_error = vp9_block_error_neon; + if (flags & HAS_SVE) { + vp9_block_error = vp9_block_error_sve; + } + vp9_block_error_fp = vp9_block_error_fp_neon; + if (flags & HAS_SVE) { + vp9_block_error_fp = vp9_block_error_fp_sve; + } } #endif
diff --git a/third_party/libvpx/source/config/linux/arm64/vpx_config.asm b/third_party/libvpx/source/config/linux/arm64/vpx_config.asm index df773c24..823d59e 100644 --- a/third_party/libvpx/source/config/linux/arm64/vpx_config.asm +++ b/third_party/libvpx/source/config/linux/arm64/vpx_config.asm
@@ -47,6 +47,7 @@ .equ CONFIG_INSTALL_LIBS , 1 .equ CONFIG_INSTALL_SRCS , 0 .equ CONFIG_DEBUG , 0 +.equ CONFIG_PROFILE , 0 .equ CONFIG_GPROF , 0 .equ CONFIG_GCOV , 0 .equ CONFIG_RVCT , 0
diff --git a/third_party/libvpx/source/config/linux/arm64/vpx_config.h b/third_party/libvpx/source/config/linux/arm64/vpx_config.h index 7fd76e9..724dfecf5 100644 --- a/third_party/libvpx/source/config/linux/arm64/vpx_config.h +++ b/third_party/libvpx/source/config/linux/arm64/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h index 66121b7..0e5bfd9 100644 --- a/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h
@@ -3106,7 +3106,10 @@ uint64_t vpx_sum_squares_2d_i16_c(const int16_t* src, int stride, int size); uint64_t vpx_sum_squares_2d_i16_neon(const int16_t* src, int stride, int size); -#define vpx_sum_squares_2d_i16 vpx_sum_squares_2d_i16_neon +uint64_t vpx_sum_squares_2d_i16_sve(const int16_t* src, int stride, int size); +RTCD_EXTERN uint64_t (*vpx_sum_squares_2d_i16)(const int16_t* src, + int stride, + int size); void vpx_tm_predictor_16x16_c(uint8_t* dst, ptrdiff_t stride, @@ -3716,6 +3719,10 @@ if (flags & HAS_NEON_DOTPROD) { vpx_sse = vpx_sse_neon_dotprod; } + vpx_sum_squares_2d_i16 = vpx_sum_squares_2d_i16_neon; + if (flags & HAS_SVE) { + vpx_sum_squares_2d_i16 = vpx_sum_squares_2d_i16_sve; + } vpx_variance16x16 = vpx_variance16x16_neon; if (flags & HAS_NEON_DOTPROD) { vpx_variance16x16 = vpx_variance16x16_neon_dotprod;
diff --git a/third_party/libvpx/source/config/linux/generic/vpx_config.asm b/third_party/libvpx/source/config/linux/generic/vpx_config.asm index bbba6ce..9f900e4 100644 --- a/third_party/libvpx/source/config/linux/generic/vpx_config.asm +++ b/third_party/libvpx/source/config/linux/generic/vpx_config.asm
@@ -47,6 +47,7 @@ .equ CONFIG_INSTALL_LIBS , 1 .equ CONFIG_INSTALL_SRCS , 0 .equ CONFIG_DEBUG , 0 +.equ CONFIG_PROFILE , 0 .equ CONFIG_GPROF , 0 .equ CONFIG_GCOV , 0 .equ CONFIG_RVCT , 0
diff --git a/third_party/libvpx/source/config/linux/generic/vpx_config.h b/third_party/libvpx/source/config/linux/generic/vpx_config.h index 959a351..4a7de9f 100644 --- a/third_party/libvpx/source/config/linux/generic/vpx_config.h +++ b/third_party/libvpx/source/config/linux/generic/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/linux/ia32/vpx_config.asm b/third_party/libvpx/source/config/linux/ia32/vpx_config.asm index 6236e61..4976b64 100644 --- a/third_party/libvpx/source/config/linux/ia32/vpx_config.asm +++ b/third_party/libvpx/source/config/linux/ia32/vpx_config.asm
@@ -44,6 +44,7 @@ %define CONFIG_INSTALL_LIBS 1 %define CONFIG_INSTALL_SRCS 0 %define CONFIG_DEBUG 0 +%define CONFIG_PROFILE 0 %define CONFIG_GPROF 0 %define CONFIG_GCOV 0 %define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/linux/ia32/vpx_config.h b/third_party/libvpx/source/config/linux/ia32/vpx_config.h index 1263633..8ba29c8 100644 --- a/third_party/libvpx/source/config/linux/ia32/vpx_config.h +++ b/third_party/libvpx/source/config/linux/ia32/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/linux/loongarch/vpx_config.h b/third_party/libvpx/source/config/linux/loongarch/vpx_config.h index 48ceaf7..92c162dc 100644 --- a/third_party/libvpx/source/config/linux/loongarch/vpx_config.h +++ b/third_party/libvpx/source/config/linux/loongarch/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/linux/mips64el/vpx_config.h b/third_party/libvpx/source/config/linux/mips64el/vpx_config.h index f8df3a4..596f338 100644 --- a/third_party/libvpx/source/config/linux/mips64el/vpx_config.h +++ b/third_party/libvpx/source/config/linux/mips64el/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/linux/mipsel/vpx_config.h b/third_party/libvpx/source/config/linux/mipsel/vpx_config.h index 27b886f..39c4c13 100644 --- a/third_party/libvpx/source/config/linux/mipsel/vpx_config.h +++ b/third_party/libvpx/source/config/linux/mipsel/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/linux/ppc64/vpx_config.asm b/third_party/libvpx/source/config/linux/ppc64/vpx_config.asm index cf14597..a6d4fb3b 100644 --- a/third_party/libvpx/source/config/linux/ppc64/vpx_config.asm +++ b/third_party/libvpx/source/config/linux/ppc64/vpx_config.asm
@@ -47,6 +47,7 @@ .equ CONFIG_INSTALL_LIBS , 1 .equ CONFIG_INSTALL_SRCS , 0 .equ CONFIG_DEBUG , 0 +.equ CONFIG_PROFILE , 0 .equ CONFIG_GPROF , 0 .equ CONFIG_GCOV , 0 .equ CONFIG_RVCT , 0
diff --git a/third_party/libvpx/source/config/linux/ppc64/vpx_config.h b/third_party/libvpx/source/config/linux/ppc64/vpx_config.h index 8be04cc..7f6244d 100644 --- a/third_party/libvpx/source/config/linux/ppc64/vpx_config.h +++ b/third_party/libvpx/source/config/linux/ppc64/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/linux/x64/vpx_config.asm b/third_party/libvpx/source/config/linux/x64/vpx_config.asm index df0d7b61..97cbf907 100644 --- a/third_party/libvpx/source/config/linux/x64/vpx_config.asm +++ b/third_party/libvpx/source/config/linux/x64/vpx_config.asm
@@ -44,6 +44,7 @@ %define CONFIG_INSTALL_LIBS 1 %define CONFIG_INSTALL_SRCS 0 %define CONFIG_DEBUG 0 +%define CONFIG_PROFILE 0 %define CONFIG_GPROF 0 %define CONFIG_GCOV 0 %define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/linux/x64/vpx_config.h b/third_party/libvpx/source/config/linux/x64/vpx_config.h index 7a069b8..c4eae4e 100644 --- a/third_party/libvpx/source/config/linux/x64/vpx_config.h +++ b/third_party/libvpx/source/config/linux/x64/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/mac/ia32/vpx_config.asm b/third_party/libvpx/source/config/mac/ia32/vpx_config.asm index 6236e61..4976b64 100644 --- a/third_party/libvpx/source/config/mac/ia32/vpx_config.asm +++ b/third_party/libvpx/source/config/mac/ia32/vpx_config.asm
@@ -44,6 +44,7 @@ %define CONFIG_INSTALL_LIBS 1 %define CONFIG_INSTALL_SRCS 0 %define CONFIG_DEBUG 0 +%define CONFIG_PROFILE 0 %define CONFIG_GPROF 0 %define CONFIG_GCOV 0 %define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/mac/ia32/vpx_config.h b/third_party/libvpx/source/config/mac/ia32/vpx_config.h index 1263633..8ba29c8 100644 --- a/third_party/libvpx/source/config/mac/ia32/vpx_config.h +++ b/third_party/libvpx/source/config/mac/ia32/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/mac/x64/vpx_config.asm b/third_party/libvpx/source/config/mac/x64/vpx_config.asm index df0d7b61..97cbf907 100644 --- a/third_party/libvpx/source/config/mac/x64/vpx_config.asm +++ b/third_party/libvpx/source/config/mac/x64/vpx_config.asm
@@ -44,6 +44,7 @@ %define CONFIG_INSTALL_LIBS 1 %define CONFIG_INSTALL_SRCS 0 %define CONFIG_DEBUG 0 +%define CONFIG_PROFILE 0 %define CONFIG_GPROF 0 %define CONFIG_GCOV 0 %define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/mac/x64/vpx_config.h b/third_party/libvpx/source/config/mac/x64/vpx_config.h index 7a069b8..c4eae4e 100644 --- a/third_party/libvpx/source/config/mac/x64/vpx_config.h +++ b/third_party/libvpx/source/config/mac/x64/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/nacl/vpx_config.h b/third_party/libvpx/source/config/nacl/vpx_config.h index 959a351..4a7de9f 100644 --- a/third_party/libvpx/source/config/nacl/vpx_config.h +++ b/third_party/libvpx/source/config/nacl/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h index e252e86..d9e2195 100644 --- a/third_party/libvpx/source/config/vpx_version.h +++ b/third_party/libvpx/source/config/vpx_version.h
@@ -2,8 +2,8 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 14 #define VERSION_PATCH 0 -#define VERSION_EXTRA "98-gc35f3e9e3" +#define VERSION_EXTRA "115-g96b64eaac" #define VERSION_PACKED \ ((VERSION_MAJOR << 16) | (VERSION_MINOR << 8) | (VERSION_PATCH)) -#define VERSION_STRING_NOSP "v1.14.0-98-gc35f3e9e3" -#define VERSION_STRING " v1.14.0-98-gc35f3e9e3" +#define VERSION_STRING_NOSP "v1.14.0-115-g96b64eaac" +#define VERSION_STRING " v1.14.0-115-g96b64eaac"
diff --git a/third_party/libvpx/source/config/win/arm64-highbd/vpx_config.asm b/third_party/libvpx/source/config/win/arm64-highbd/vpx_config.asm index b2d66f49..e587d82 100644 --- a/third_party/libvpx/source/config/win/arm64-highbd/vpx_config.asm +++ b/third_party/libvpx/source/config/win/arm64-highbd/vpx_config.asm
@@ -48,6 +48,7 @@ .equ CONFIG_INSTALL_LIBS , 1 .equ CONFIG_INSTALL_SRCS , 0 .equ CONFIG_DEBUG , 0 +.equ CONFIG_PROFILE , 0 .equ CONFIG_GPROF , 0 .equ CONFIG_GCOV , 0 .equ CONFIG_RVCT , 0
diff --git a/third_party/libvpx/source/config/win/arm64-highbd/vpx_config.h b/third_party/libvpx/source/config/win/arm64-highbd/vpx_config.h index 4ebb325..50e6a62 100644 --- a/third_party/libvpx/source/config/win/arm64-highbd/vpx_config.h +++ b/third_party/libvpx/source/config/win/arm64-highbd/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/win/ia32/vpx_config.asm b/third_party/libvpx/source/config/win/ia32/vpx_config.asm index 3d13c73..30b1692 100644 --- a/third_party/libvpx/source/config/win/ia32/vpx_config.asm +++ b/third_party/libvpx/source/config/win/ia32/vpx_config.asm
@@ -44,6 +44,7 @@ %define CONFIG_INSTALL_LIBS 1 %define CONFIG_INSTALL_SRCS 0 %define CONFIG_DEBUG 0 +%define CONFIG_PROFILE 0 %define CONFIG_GPROF 0 %define CONFIG_GCOV 0 %define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/win/ia32/vpx_config.h b/third_party/libvpx/source/config/win/ia32/vpx_config.h index a49bebd..d199c45 100644 --- a/third_party/libvpx/source/config/win/ia32/vpx_config.h +++ b/third_party/libvpx/source/config/win/ia32/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/win/x64/vpx_config.asm b/third_party/libvpx/source/config/win/x64/vpx_config.asm index 57f333cf..583155d 100644 --- a/third_party/libvpx/source/config/win/x64/vpx_config.asm +++ b/third_party/libvpx/source/config/win/x64/vpx_config.asm
@@ -44,6 +44,7 @@ %define CONFIG_INSTALL_LIBS 1 %define CONFIG_INSTALL_SRCS 0 %define CONFIG_DEBUG 0 +%define CONFIG_PROFILE 0 %define CONFIG_GPROF 0 %define CONFIG_GCOV 0 %define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/config/win/x64/vpx_config.h b/third_party/libvpx/source/config/win/x64/vpx_config.h index 8fd7e00..2a11bf8 100644 --- a/third_party/libvpx/source/config/win/x64/vpx_config.h +++ b/third_party/libvpx/source/config/win/x64/vpx_config.h
@@ -56,6 +56,7 @@ #define CONFIG_INSTALL_LIBS 1 #define CONFIG_INSTALL_SRCS 0 #define CONFIG_DEBUG 0 +#define CONFIG_PROFILE 0 #define CONFIG_GPROF 0 #define CONFIG_GCOV 0 #define CONFIG_RVCT 0
diff --git a/third_party/libvpx/source/libvpx b/third_party/libvpx/source/libvpx index c35f3e9..96b64ea 160000 --- a/third_party/libvpx/source/libvpx +++ b/third_party/libvpx/source/libvpx
@@ -1 +1 @@ -Subproject commit c35f3e9e3512d0012180ad8de8834d8813a80b73 +Subproject commit 96b64eaac5adbac59e43e34d87af3ba0fb06bca6
diff --git a/third_party/perfetto b/third_party/perfetto index 9b78d80d..b20333c 160000 --- a/third_party/perfetto +++ b/third_party/perfetto
@@ -1 +1 @@ -Subproject commit 9b78d80da79be8d58590a2c686d66748161a77ff +Subproject commit b20333c6f8b603fc3bf842a272126d83403f201f
diff --git a/third_party/skia b/third_party/skia index 59943f4..555cfc8 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit 59943f4e92b9728e8bac10903e195c8b9a037365 +Subproject commit 555cfc8d95c667b7d797914599f75124070b914c
diff --git a/third_party/webgpu-cts/src b/third_party/webgpu-cts/src index 6493b87..3f04968 160000 --- a/third_party/webgpu-cts/src +++ b/third_party/webgpu-cts/src
@@ -1 +1 @@ -Subproject commit 6493b876ade082dc4e4d883691e8900d5b42f01c +Subproject commit 3f04968bcc3bacf13aabf3c631a9459ffaddf262
diff --git a/third_party/webrtc b/third_party/webrtc index cea1c0b..9183fcd 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit cea1c0b9a91be940ec801ab84a7ca3b52e9fc930 +Subproject commit 9183fcdc5311f6b6236597ff725831686a34b8fa
diff --git a/tools/binary_size/libsupersize/linker_map_parser.py b/tools/binary_size/libsupersize/linker_map_parser.py index 0ae4257..99053580 100755 --- a/tools/binary_size/libsupersize/linker_map_parser.py +++ b/tools/binary_size/libsupersize/linker_map_parser.py
@@ -563,7 +563,8 @@ is_partial = False cur_obj = None - elif cur_obj == 'lto.tmp' or 'thinlto-cache' in cur_obj: + elif (cur_obj == 'lto.tmp' or 'thinlto-cache' in cur_obj + or '.lto.' in cur_obj): thin_map[address] = os.path.basename(cur_obj) cur_obj = None @@ -670,8 +671,8 @@ def _DetectLto(lines): """Scans LLD linker map file and returns whether LTO was used.""" # It's assumed that the first line in |lines| was consumed to determine that - # LLD was used. Seek 'thinlto-cache' prefix within an "indicator section" as - # indicator for LTO. + # LLD was used. Seek 'thinlto-cache' prefix or the string '.lto' within an + # "indicator section" as indicator for LTO. found_indicator_section = False # Potential names of "main section". Only one gets used. indicator_section_set = set(['.rodata', '.ARM.exidx']) @@ -695,7 +696,7 @@ found_indicator_section = True elif indent_size == 8: if found_indicator_section: - if tok.startswith('thinlto-cache'): + if tok.startswith('thinlto-cache') or '.lto.' in tok: return True return False
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index 12e332a4..865efa5 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -36,7 +36,7 @@ # Reverting problematic clang rolls is safe, though. # This is the output of `git describe` and is usable as a commit-ish. CLANG_REVISION = 'llvmorg-18-init-17730-gf670112a' -CLANG_SUB_REVISION = 2 +CLANG_SUB_REVISION = 3 PACKAGE_VERSION = '%s-%s' % (CLANG_REVISION, CLANG_SUB_REVISION) RELEASE_VERSION = '18'
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index 136b1cb0..5b732a3 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -249,10 +249,6 @@ "META": {"sizes": {"includes": [5]}}, "includes": [2980], }, - "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/commander/resources.grd": { - "META": {"sizes": {"includes": [15]}}, - "includes": [3020], - }, "chrome/browser/resources/component_extension_resources.grd": { "includes": [3040], "structures": [3060],
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index a692ff9..af36e0abf 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -41520,6 +41520,10 @@ label="For ShoppingListMenuItem feature."/> <suffix name="ShoppingListSaveFlow" label="For ShoppingListSaveFlow feature."/> + <suffix name="SidePanelGenericMenuFeature" + label="For Side Panel Pinning menu entries."/> + <suffix name="SidePanelGenericPinnableFeature" + label="For Side Panel Pinning pin feature."/> <suffix name="SideSearch" label="For the side search feature."/> <suffix name="SideSearchAutoTriggering" label="For side search feature automatic triggering."/>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 63dfba00..671ed67 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -13578,6 +13578,7 @@ <int value="6" label="Tapped Snooze"/> <int value="7" label="Tapped Outside IPH And Anchor View"/> <int value="8" label="Tapped Anchor View"/> + <int value="9" label="Voice Over Announcement Ended"/> </enum> <enum name="InProductHelpSnoozeAction">
diff --git a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml index 3e915a4..faa7bda 100644 --- a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml +++ b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
@@ -3721,7 +3721,6 @@ label="Records metrics for consumer real time URL lookup service."/> <suffix name="Enterprise" label="Records metrics for enterprise real time URL lookup service."/> - <affected-histogram name="SafeBrowsing.PageLoadToken.RealTimeCheckHasToken"/> <affected-histogram name="SafeBrowsing.RT.BackoffState"/> <affected-histogram name="SafeBrowsing.RT.GetCache.Time"/> <affected-histogram name="SafeBrowsing.RT.GetCacheResult"/>
diff --git a/tools/metrics/histograms/metadata/ios/enums.xml b/tools/metrics/histograms/metadata/ios/enums.xml index dd0a1906..ed3cf439 100644 --- a/tools/metrics/histograms/metadata/ios/enums.xml +++ b/tools/metrics/histograms/metadata/ios/enums.xml
@@ -319,11 +319,11 @@ <int value="5" label="Set Up List Compacted"/> <int value="6" label="Set Up List All Set"/> <int value="7" label="Safety Check"/> - <int value="8" label="Safety Check Multi Row"/> - <int value="9" label="Safety Check Multi Row Overflow"/> + <int value="8" label="Obsolete in M123 - Safety Check Multi Row"/> + <int value="9" label="Obsolete in M123 - Safety Check Multi Row Overflow"/> <int value="10" label="Tab Resumption"/> <int value="11" label="Parcel Tracking"/> - <int value="12" label="Parcel Tracking See More"/> + <int value="12" label="Obsolete in M123 - Parcel Tracking See More"/> <int value="13" label="Set Up List Notifications"/> <int value="14" label="Placeholder"/> </enum>
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml index 4a865bb..82c681b4 100644 --- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml +++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -1766,16 +1766,6 @@ </summary> </histogram> -<histogram name="SafeBrowsing.PageLoadToken.RealTimeCheckHasToken" - enum="BooleanExists" expires_after="2024-04-28"> - <owner>xinghuilu@chromium.org</owner> - <owner>chrome-counter-abuse-alerts@google.com</owner> - <summary> - Records whether a page load token is found before real time URL check - request is sent. Logged only when the check is on a subframe URL. - </summary> -</histogram> - <histogram name="SafeBrowsing.PageLoadToken.TokenCount" units="entries" expires_after="2024-08-04"> <owner>xinghuilu@chromium.org</owner> @@ -2167,24 +2157,20 @@ </summary> </histogram> -<histogram name="SafeBrowsing.RT.LocalMatch.Result.{IsMainframe}{UserCategory}" +<histogram name="SafeBrowsing.RT.LocalMatch.Result.{UserCategory}" enum="SafeBrowsingAllowlistAsyncMatch" expires_after="2024-07-14"> <owner>xinghuilu@chromium.org</owner> <owner>chrome-counter-abuse-alerts@google.com</owner> <summary> - Logs the result of checking the {IsMainframe} URL against the local Safe - Browsing high confidence allowlist for {UserCategory} real time URL check - request. Logged each time a top frame URL navigation happens for users who - have the real time URL lookups enabled. It can also be logged for - non-mainframe URL hits for EnhancedProtection users. + Logs the result of checking the URL against the local Safe Browsing high + confidence allowlist for {UserCategory} real time URL check request. Logged + each time a top frame URL navigation happens for users who have the real + time URL lookups enabled. It can also be logged for non-mainframe URL hits + for EnhancedProtection users. Until M117, this was being logged twice each time for iOS. Bucket ratios were still correct, just not total counts. </summary> - <token key="IsMainframe"> - <variant name="Mainframe" summary="mainframe"/> - <variant name="NonMainframe" summary="non mainframe"/> - </token> <token key="UserCategory" variants="RealTimeUrlCheckUserCategory"/> </histogram> @@ -2278,17 +2264,6 @@ </summary> </histogram> -<histogram name="SafeBrowsing.RT.RequestDestinations.Checked" - enum="RequestDestination" expires_after="2024-07-21"> - <owner>xinghuilu@chromium.org</owner> - <owner>chrome-counter-abuse-alerts@google.com</owner> - <summary> - Logs the request destination that was checked by Safe Browsing real time URL - lookup. Logged on each resource check that is eligible for real time URL - checks. - </summary> -</histogram> - <histogram name="SafeBrowsing.RT.RequestDestinations.Requested" enum="RequestDestination" expires_after="2024-07-21"> <owner>xinghuilu@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/settings/enums.xml b/tools/metrics/histograms/metadata/settings/enums.xml index 4044e5b3..8ebcbf4a 100644 --- a/tools/metrics/histograms/metadata/settings/enums.xml +++ b/tools/metrics/histograms/metadata/settings/enums.xml
@@ -58,6 +58,7 @@ <int value="2" label="External Intent"/> <int value="3" label="Set Up List"/> <int value="4" label="External Action"/> + <int value="5" label="Tips Notification"/> </enum> <enum name="LockScreenProgress">
diff --git a/tools/metrics/histograms/metadata/web_apk/histograms.xml b/tools/metrics/histograms/metadata/web_apk/histograms.xml index 529291f6..86fba9e 100644 --- a/tools/metrics/histograms/metadata/web_apk/histograms.xml +++ b/tools/metrics/histograms/metadata/web_apk/histograms.xml
@@ -218,7 +218,8 @@ <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records WebAPK "Shell APK version" when the WebAPK is launched. - The "Shell APK version" is documented in shell_apk_version.gni + The "Shell APK version" is documented in + chrome/android/webapk/shell_apk/current_version/current_version.gni {WebApkDistributorType} </summary> <token key="WebApkDistributorType" variants="WebApkDistributorType"/> @@ -297,6 +298,18 @@ </summary> </histogram> +<histogram name="WebApk.Update.ShellVersion" units="units" + expires_after="2025-01-01"> + <owner>eirage@chromium.org</owner> + <owner>src/chrome/android/webapk/OWNERS</owner> + <summary> + When a WebAPK update request was queued, records the current WebAPK's + "Shell APK version" The "Shell APK version" is + documented in + chrome/android/webapk/shell_apk/current_version/current_version.gni + </summary> +</histogram> + <histogram name="WebApk.Update.UniqueId{SameOrEmpty}.{LegacyIdentifierType}" enum="Boolean" expires_after="2024-04-28"> <owner>eirage@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/web_core/enums.xml b/tools/metrics/histograms/metadata/web_core/enums.xml index d395ae0..53740529 100644 --- a/tools/metrics/histograms/metadata/web_core/enums.xml +++ b/tools/metrics/histograms/metadata/web_core/enums.xml
@@ -54,24 +54,6 @@ </int> </enum> -<enum name="IDBContextForcedCloseReason"> - <int value="0" label="DeleteOrigin"> - A request was made to delete the data for an origin. - </int> - <int value="1" label="BackingStoreFailure"> - An unrecoverable error occurred accessing the backing store. - </int> - <int value="2" label="InternalsPage"> - A forced close was requested from the indexeddb-internals page. - </int> - <int value="3" label="CopyOrigin"> - The database is force closed so that it can be copied. - </int> - <int value="4" label="ForceSchemaDowngradeInternalsPage"> - A forced schema downgrade was requested from the indexeddb-internals page. - </int> -</enum> - <enum name="IDBException"> <int value="0" label="Unknown error"/> <int value="1" label="Constraint error"/>
diff --git a/tools/metrics/histograms/metadata/web_core/histograms.xml b/tools/metrics/histograms/metadata/web_core/histograms.xml index 756782e3..b0e6a6c1 100644 --- a/tools/metrics/histograms/metadata/web_core/histograms.xml +++ b/tools/metrics/histograms/metadata/web_core/histograms.xml
@@ -279,13 +279,6 @@ </summary> </histogram> -<histogram name="WebCore.IndexedDB.Context.ForceCloseReason" - enum="IDBContextForcedCloseReason" expires_after="2024-07-28"> - <owner>estade@chromium.org</owner> - <owner>chrome-owp-storage@google.com</owner> - <summary>The reason that a forced-close of a backing store occurred.</summary> -</histogram> - <histogram name="WebCore.IndexedDB.FoundBlobFileForValue" enum="Boolean" expires_after="2024-05-24"> <owner>estade@chromium.org</owner>
diff --git a/tools/perf/contrib/shared_storage/page_set.py b/tools/perf/contrib/shared_storage/page_set.py index c879396..50bafb9b 100644 --- a/tools/perf/contrib/shared_storage/page_set.py +++ b/tools/perf/contrib/shared_storage/page_set.py
@@ -13,7 +13,8 @@ from telemetry import story from telemetry.internal.backends.chrome_inspector import websocket from telemetry.page import page as page_module -from telemetry.page import shared_page_state + +from contrib.shared_storage import shared_storage_shared_page_state as state # Timeouts in seconds. _ACTION_TIMEOUT = 2 @@ -157,7 +158,7 @@ (self.NAME, _ACTION_TIMEOUT, repr(w))) # Reload the page if necessary. Otherwise, skip. - if self.RENAVIGATE_AFTER_ACTION: + if self.RENAVIGATE_AFTER_ACTION and index < self._iterations - 1: url = self.file_path_url_with_scheme if self.is_file else self.url action_runner.Navigate(url, self.script_to_evaluate_on_commit, @@ -193,10 +194,9 @@ action_runner.tab.ClearSharedStorageNotifications() def _RunSharedStorageAction(self, action_runner, index): - logging.info("".join([ - "running iteration ", - str(index + 1), ": ", self.ACTION_SCRIPT_TEMPLATE - ])) + logging.info("".join( + ["running iteration ", + str(index), ": ", self.ACTION_SCRIPT_TEMPLATE])) if self.ACTION_SCRIPT_TEMPLATE.find(_INDEX_PLACEHOLDER) != -1: action_runner.tab.EvaluateJavaScript(self.ACTION_SCRIPT_TEMPLATE, promise=True, @@ -257,9 +257,9 @@ verbosity=0): super(SharedStorageStorySet, self).__init__() if user_agent == 'mobile': - shared_page_state_class = shared_page_state.SharedMobilePageState + shared_page_state_class = state.SharedStorageSharedMobilePageState elif user_agent == 'desktop': - shared_page_state_class = shared_page_state.SharedDesktopPageState + shared_page_state_class = state.SharedStorageSharedDesktopPageState else: raise ValueError('user_agent %s is unrecognized' % user_agent)
diff --git a/tools/perf/contrib/shared_storage/shared_storage.py b/tools/perf/contrib/shared_storage/shared_storage.py index d8da0433..a8030d2 100644 --- a/tools/perf/contrib/shared_storage/shared_storage.py +++ b/tools/perf/contrib/shared_storage/shared_storage.py
@@ -3,6 +3,7 @@ # found in the LICENSE file. import logging +import os from benchmarks import memory from contrib.shared_storage import page_set @@ -54,6 +55,9 @@ # Use maximum allowed trace buffer size (in KB). _TRACE_BUFFER_SIZE = 2**32 - 1 +# Timeout in seconds allowed for the browser to shutdown when asked, before +# it is killed. +_SHUTDOWN_TIMEOUT = 90 class SharedStoragePerfBase(perf_benchmark.PerfBenchmark): URL = 'file://fresh_with_worklet.html' @@ -108,6 +112,9 @@ '--enable-privacy-sandbox-ads-apis' ]) + # Increase the default shutdown timeout due to some long-running tests. + os.environ['CHROME_SHUTDOWN_TIMEOUT'] = str(_SHUTDOWN_TIMEOUT) + def CustomizeOptions(self, finder_options, possible_browser=None): #`finder_options` is an instance of `browser_options.BrowserFinderOptions`. #
diff --git a/tools/perf/contrib/shared_storage/shared_storage_shared_page_state.py b/tools/perf/contrib/shared_storage/shared_storage_shared_page_state.py new file mode 100644 index 0000000..2d257ccc --- /dev/null +++ b/tools/perf/contrib/shared_storage/shared_storage_shared_page_state.py
@@ -0,0 +1,25 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from telemetry.page import shared_page_state + + +class SharedStorageSharedPageState(shared_page_state.SharedPageState): + + def RunStory(self, results): + # We use a print statement instead of logging here so that we can display + # the run index (i.e. which pageset repeat we are on) even if the logging + # level is non-verbose. Also, it's not necessary to persist to logs, as the + # index number is used in the directory path in which the log artifact is + # written. + print('[ RUN #%3d ]' % results.current_story_run.index) + super(SharedStorageSharedPageState, self).RunStory(results) + + +class SharedStorageSharedMobilePageState(SharedStorageSharedPageState): + _device_type = 'mobile' + + +class SharedStorageSharedDesktopPageState(SharedStorageSharedPageState): + _device_type = 'desktop'
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index 7ad3b026..9329bb3 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -978,7 +978,7 @@ 'gpu': '8086:1626', 'os': - 'Mac-12.6.1', + 'Mac-12', 'pool': 'chrome.tests.perf', 'synthetic_product_name': @@ -1002,7 +1002,7 @@ 'gpu': '8086:1626', 'os': - 'Mac-12.6.1', + 'Mac-12', 'pool': 'chrome.tests.perf', 'synthetic_product_name': @@ -1176,7 +1176,7 @@ 'gpu': '1002:6821-4.0.20-3.2.8', 'os': - 'Mac-12.6.1', + 'Mac-12', 'pool': 'chrome.tests.perf', 'synthetic_product_name':
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index ab38396..a7ef2965 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": "perfetto-luci-artifacts/v42.0/linux-arm64/trace_processor_shell" }, "win": { - "hash": "e18d4233630bb5be75250d161756fa286d65ba71", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/f82e76bda590f95122db33491eb3d46012bd4352/trace_processor_shell.exe" + "hash": "8757c4c1feb3009270a932fc5ba6c3c56a9343a9", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/e74424f065e34892c3d31a6409a72badcbaa13d0/trace_processor_shell.exe" }, "linux_arm": { "hash": "46739eeb4b8f2a65a8a0aac57743767e6407f7bb", "full_remote_path": "perfetto-luci-artifacts/v42.0/linux-arm/trace_processor_shell" }, "mac": { - "hash": "3451ae61d92dbf355168605b6e60c7b1030fdd95", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/f82e76bda590f95122db33491eb3d46012bd4352/trace_processor_shell" + "hash": "1dc85d515dd9f58b0bf633e5eab93fdc8494d4f8", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/e74424f065e34892c3d31a6409a72badcbaa13d0/trace_processor_shell" }, "mac_arm64": { "hash": "789f24a091d50faafdd5d7c5096bb923d073f138", "full_remote_path": "perfetto-luci-artifacts/v42.0/mac-arm64/trace_processor_shell" }, "linux": { - "hash": "2b3fbcdf11ac7cc617228e95dddea344eb639d13", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/f82e76bda590f95122db33491eb3d46012bd4352/trace_processor_shell" + "hash": "58a73d9154c13130e56c9a791e9c0d847f6d4db4", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/e74424f065e34892c3d31a6409a72badcbaa13d0/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/perf/process_perf_results.pydeps b/tools/perf/process_perf_results.pydeps index c84c7140..7b89759b 100644 --- a/tools/perf/process_perf_results.pydeps +++ b/tools/perf/process_perf_results.pydeps
@@ -556,6 +556,7 @@ contrib/shared_storage/page_set.py contrib/shared_storage/pages.py contrib/shared_storage/shared_storage.py +contrib/shared_storage/shared_storage_shared_page_state.py contrib/system_health_scroll_jank/__init__.py contrib/system_health_scroll_jank/janky_story_set.py contrib/system_health_scroll_jank/system_health_scroll_jank.py
diff --git a/ui/base/test/ns_ax_tree_validator.h b/ui/base/test/ns_ax_tree_validator.h index c05a141..22be2dd6 100644 --- a/ui/base/test/ns_ax_tree_validator.h +++ b/ui/base/test/ns_ax_tree_validator.h
@@ -5,6 +5,8 @@ #ifndef UI_BASE_TEST_NS_AX_TREE_VALIDATOR_H_ #define UI_BASE_TEST_NS_AX_TREE_VALIDATOR_H_ +#include <string> + #include "third_party/abseil-cpp/absl/types/optional.h" @protocol NSAccessibility;
diff --git a/ui/base/test/view_tree_validator.h b/ui/base/test/view_tree_validator.h index de8e5ae9..d1421da 100644 --- a/ui/base/test/view_tree_validator.h +++ b/ui/base/test/view_tree_validator.h
@@ -5,6 +5,8 @@ #ifndef UI_BASE_TEST_VIEW_TREE_VALIDATOR_H_ #define UI_BASE_TEST_VIEW_TREE_VALIDATOR_H_ +#include <string> + #include "third_party/abseil-cpp/absl/types/optional.h" @class NSView;
diff --git a/ui/gl/gl_surface_stub.cc b/ui/gl/gl_surface_stub.cc index d68f172..9d2b7dd58 100644 --- a/ui/gl/gl_surface_stub.cc +++ b/ui/gl/gl_surface_stub.cc
@@ -23,7 +23,7 @@ } bool GLSurfaceStub::IsOffscreen() { - return true; + return false; } gfx::SwapResult GLSurfaceStub::SwapBuffers(PresentationCallback callback,
diff --git a/ui/gl/init/gl_factory_android.cc b/ui/gl/init/gl_factory_android.cc index b12f931f..28b4dd1 100644 --- a/ui/gl/init/gl_factory_android.cc +++ b/ui/gl/init/gl_factory_android.cc
@@ -95,15 +95,11 @@ TRACE_EVENT0("gpu", "gl::init::CreateGLContext"); switch (GetGLImplementation()) { case kGLImplementationMockGL: + return scoped_refptr<GLContext>(new GLContextStub(share_group)); case kGLImplementationStubGL: { scoped_refptr<GLContextStub> stub_context = - MakeRefCounted<GLContextStub>(share_group); - if (GetGLImplementation() == kGLImplementationStubGL) { - stub_context->SetUseStubApi(true); - } - // The stub ctx needs to be initialized so that the gl::GLContext can - // store the |compatible_surface|. - stub_context->Initialize(compatible_surface, attribs); + new GLContextStub(share_group); + stub_context->SetUseStubApi(true); return stub_context; } case kGLImplementationDisabled:
diff --git a/ui/gl/init/gl_factory_mac.cc b/ui/gl/init/gl_factory_mac.cc index 2726747..64aee97 100644 --- a/ui/gl/init/gl_factory_mac.cc +++ b/ui/gl/init/gl_factory_mac.cc
@@ -45,15 +45,11 @@ return InitializeGLContext(new GLContextEGL(share_group), compatible_surface, attribs); case kGLImplementationMockGL: + return new GLContextStub(share_group); case kGLImplementationStubGL: { scoped_refptr<GLContextStub> stub_context = - base::MakeRefCounted<GLContextStub>(share_group); - if (GetGLImplementation() == kGLImplementationStubGL) { - stub_context->SetUseStubApi(true); - } - // The stub ctx needs to be initialized so that the gl::GLContext can - // store the |compatible_surface|. - stub_context->Initialize(compatible_surface, attribs); + new GLContextStub(share_group); + stub_context->SetUseStubApi(true); return stub_context; } default:
diff --git a/ui/gl/init/gl_factory_ozone.cc b/ui/gl/init/gl_factory_ozone.cc index 2d10c7c..2c02251b 100644 --- a/ui/gl/init/gl_factory_ozone.cc +++ b/ui/gl/init/gl_factory_ozone.cc
@@ -42,22 +42,17 @@ attribs); } - scoped_refptr<GLContextStub> context; switch (GetGLImplementation()) { case kGLImplementationMockGL: + return scoped_refptr<GLContext>(new GLContextStub(share_group)); case kGLImplementationStubGL: { scoped_refptr<GLContextStub> stub_context = - base::MakeRefCounted<GLContextStub>(share_group); - if (GetGLImplementation() == kGLImplementationStubGL) { - stub_context->SetUseStubApi(true); - } - // The stub ctx needs to be initialized so that the gl::GLContext can - // store the |compatible_surface|. - stub_context->Initialize(compatible_surface, attribs); + new GLContextStub(share_group); + stub_context->SetUseStubApi(true); return stub_context; } case kGLImplementationDisabled: - break; + return nullptr; default: NOTREACHED() << "Expected Mock or Stub, actual:" << GetGLImplementation(); }
diff --git a/ui/gl/init/gl_factory_win.cc b/ui/gl/init/gl_factory_win.cc index 2d6ba9d..3398765 100644 --- a/ui/gl/init/gl_factory_win.cc +++ b/ui/gl/init/gl_factory_win.cc
@@ -46,15 +46,11 @@ return InitializeGLContext(new GLContextEGL(share_group), compatible_surface, attribs); case kGLImplementationMockGL: + return new GLContextStub(share_group); case kGLImplementationStubGL: { scoped_refptr<GLContextStub> stub_context = - base::MakeRefCounted<GLContextStub>(share_group); - if (GetGLImplementation() == kGLImplementationStubGL) { - stub_context->SetUseStubApi(true); - } - // The stub ctx needs to be initialized so that the gl::GLContext can - // store the |compatible_surface|. - stub_context->Initialize(compatible_surface, attribs); + new GLContextStub(share_group); + stub_context->SetUseStubApi(true); return stub_context; } case kGLImplementationDisabled:
diff --git a/ui/message_center/public/cpp/notification_types.h b/ui/message_center/public/cpp/notification_types.h index ec113cb8..6b3a72a 100644 --- a/ui/message_center/public/cpp/notification_types.h +++ b/ui/message_center/public/cpp/notification_types.h
@@ -7,8 +7,8 @@ namespace message_center { -// Notification types. Note that the values in this enumeration are being -// recoded in a histogram, updates should not change the entries' values. +// Notification types. Used to determine the view that will represent a +// notification. enum NotificationType { NOTIFICATION_TYPE_SIMPLE = 0, DEPRECATED_NOTIFICATION_TYPE_BASE_FORMAT = @@ -17,9 +17,10 @@ NOTIFICATION_TYPE_MULTIPLE = 3, NOTIFICATION_TYPE_PROGRESS = 4, // Notification with progress bar. NOTIFICATION_TYPE_CUSTOM = 5, + NOTIFICATION_TYPE_CONVERSATION = 6, // Add new values before this line. - NOTIFICATION_TYPE_LAST = NOTIFICATION_TYPE_CUSTOM + NOTIFICATION_TYPE_LAST = NOTIFICATION_TYPE_CONVERSATION }; enum NotificationPriority {
diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc index a5ad22b..b8323a5 100644 --- a/ui/message_center/views/notification_view.cc +++ b/ui/message_center/views/notification_view.cc
@@ -630,6 +630,32 @@ void NotificationView::Layout(PassKey) { LayoutSuperclass<NotificationViewBase>(this); + // We need to call IsExpandable() after doing superclass layout, since whether + // we should show expand button or not depends on the current view layout. + // (e.g. Show expand button when `message_label_` exceeds one line.) + SetExpandButtonVisibility(IsExpandable()); + header_row()->DeprecatedLayoutImmediately(); + + // The notification background is rounded in MessageView layout, but we also + // have to round the actions row background here. + if (actions_row()->GetVisible()) { + constexpr SkScalar kCornerRadius = SkIntToScalar(kNotificationCornerRadius); + + // Use vertically larger clip path, so that actions row's top corners will + // not be rounded. + SkPath path; + gfx::Rect bounds = actions_row()->GetLocalBounds(); + bounds.set_y(bounds.y() - bounds.height()); + bounds.set_height(bounds.height() * 2); + path.addRoundRect(gfx::RectToSkRect(bounds), kCornerRadius, kCornerRadius); + + action_buttons_row()->SetClipPath(path); + + if (inline_reply()) { + inline_reply()->SetClipPath(path); + } + } + // The animation is needed to run inside of the border. ink_drop_container_->SetBoundsRect(GetLocalBounds()); }
diff --git a/ui/message_center/views/notification_view_base.cc b/ui/message_center/views/notification_view_base.cc index 3a88f0889..fe669d9d 100644 --- a/ui/message_center/views/notification_view_base.cc +++ b/ui/message_center/views/notification_view_base.cc
@@ -235,35 +235,6 @@ RemovePreTargetHandler(click_activator_.get()); } -void NotificationViewBase::Layout(PassKey) { - LayoutSuperclass<MessageView>(this); - - // We need to call IsExpandable() after doing superclass layout, since whether - // we should show expand button or not depends on the current view layout. - // (e.g. Show expand button when |message_label_| exceeds one line.) - SetExpandButtonVisibility(IsExpandable()); - header_row_->DeprecatedLayoutImmediately(); - - // The notification background is rounded in MessageView layout, but we also - // have to round the actions row background here. - if (actions_row_->GetVisible()) { - constexpr SkScalar kCornerRadius = SkIntToScalar(kNotificationCornerRadius); - - // Use vertically larger clip path, so that actions row's top corners will - // not be rounded. - SkPath path; - gfx::Rect bounds = actions_row_->GetLocalBounds(); - bounds.set_y(bounds.y() - bounds.height()); - bounds.set_height(bounds.height() * 2); - path.addRoundRect(gfx::RectToSkRect(bounds), kCornerRadius, kCornerRadius); - - action_buttons_row_->SetClipPath(path); - - if (inline_reply_) - inline_reply_->SetClipPath(path); - } -} - void NotificationViewBase::OnFocus() { MessageView::OnFocus(); ScrollRectToVisible(GetLocalBounds());
diff --git a/ui/message_center/views/notification_view_base.h b/ui/message_center/views/notification_view_base.h index c274adf2..3efa371b 100644 --- a/ui/message_center/views/notification_view_base.h +++ b/ui/message_center/views/notification_view_base.h
@@ -99,7 +99,6 @@ void Activate(); // MessageView: - void Layout(PassKey) override; void OnFocus() override; bool OnMousePressed(const ui::MouseEvent& event) override; bool OnMouseDragged(const ui::MouseEvent& event) override;
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index 1010939..9448138 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -1170,10 +1170,6 @@ ] } - if (is_chromeos_lacros) { - deps += [ "//chromeos/startup" ] - } - if (use_aura) { sources += [ "corewm/tooltip_controller_test_helper.cc",
diff --git a/ui/views/test/DEPS b/ui/views/test/DEPS index 38a40c7..220fb85d 100644 --- a/ui/views/test/DEPS +++ b/ui/views/test/DEPS
@@ -4,7 +4,6 @@ specific_include_rules = { "views_test_base\.cc": [ - "+chromeos/startup", "+mojo/core/embedder", "+ui/gl", ],
diff --git a/ui/views/test/views_test_base.cc b/ui/views/test/views_test_base.cc index 0cf5d36..aa715fd4 100644 --- a/ui/views/test/views_test_base.cc +++ b/ui/views/test/views_test_base.cc
@@ -30,10 +30,6 @@ #include "ui/views/widget/native_widget_mac.h" #endif -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chromeos/startup/browser_params_proxy.h" -#endif - namespace views { namespace { @@ -46,16 +42,7 @@ ViewsTestBase::ViewsTestBase( std::unique_ptr<base::test::TaskEnvironment> task_environment) - : task_environment_(std::move(task_environment)) { -#if BUILDFLAG(IS_CHROMEOS_LACROS) - // ViewsTestBase is also used by a number of Lacros interactive_ui_tests. - // Lacros interactive_ui_tests are expected to process the - // --lacros-mojo-socket-for-testing command line switch in order to set up - // crosapi. However, ViewsTestBase doesn't implement that as it's also used by - // other tests and doesn't need crosapi. Hence disable crosapi explicitly. - chromeos::BrowserParamsProxy::DisableCrosapiForTesting(); -#endif -} + : task_environment_(std::move(task_environment)) {} ViewsTestBase::~ViewsTestBase() { CHECK(setup_called_)
diff --git a/ui/views/view.h b/ui/views/view.h index 70f14b5..43be4fe 100644 --- a/ui/views/view.h +++ b/ui/views/view.h
@@ -255,16 +255,17 @@ // // For Views that expose properties which are intended to be dynamically // discoverable by other subsystems, each View and its descendants must -// include metadata. These other subsystems, such as dev tools or a delarative -// layout system, can then enumerate the properties on any given instance or -// class. Using the enumerated information, the actual values of the -// properties can be read or written. This will be done by getting and setting -// the values using string representations. The metadata can also be used to -// instantiate and initialize a View (or descendant) class from a declarative -// "script". +// include metadata. These other subsystems, such as dev tools or a +// declarative layout system, can then enumerate the properties on any given +// instance or class. Using the enumerated information, the actual values of +// the properties can be read or written. This will be done by getting and +// setting the values using string representations. The metadata can also be +// used to instantiate and initialize a View (or descendant) class from a +// declarative "script". // // For each View class in their respective header declaration, place the macro -// METADATA_HEADER(<classname>, <view ancestor class>) in the public section. +// METADATA_HEADER(<classname>, <view ancestor class>) in the initial private +// section. // // In the implementing .cc file, add the following macros to the same // namespace in which the class resides.