diff --git a/DEPS b/DEPS index a25b0d16..d1a1e7c 100644 --- a/DEPS +++ b/DEPS
@@ -269,7 +269,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '3f8806ce0fcf011fc9d6305b8db00f22a605db9c', + 'skia_revision': '59c906795c50b54d7cdeebc167cfa377af28c7aa', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -277,11 +277,11 @@ # 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': '7184fe38c336e9e85be10661446f1135c1e9f6a7', + 'angle_revision': '394fb0d34213a0123a688ed0918203c583d419b4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': 'adef92e7b4c63b0c00300635dfbf4c37dab3c5b9', + 'swiftshader_revision': 'e617219743aaba9cf3bd8ec9bad2447f7a236996', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -344,7 +344,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'a00b89c22a9821139a3de3cfd1638b2e4a2de609', + 'devtools_frontend_revision': '9563425f4b113eece75285e693e4c1b22ea359fb', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -408,7 +408,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nearby # and whatever else without interference from each other. - 'nearby_revision': 'aeff3a96832b094b6ff7d2fe63116c95bb8c1f5c', + 'nearby_revision': 'd09f53a40bb92e1037aed30b8407a090f08cdebe', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling securemessage # and whatever else without interference from each other. @@ -424,7 +424,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'libcxxabi_revision': 'c055932162c3d9e3b790c573c07189f6930ceeda', + 'libcxxabi_revision': 'c7888dd7079aacb83ce39d79b3587906748a0870', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -746,7 +746,7 @@ }, 'src/ios/third_party/edo/src': { - 'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + 'a9543bd5e36aebcd57b6ca3b677f616d5a15b5ed', + 'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + '08988a24e17251c85c4283dae7badddc3402dee9', 'condition': 'checkout_ios', }, @@ -853,7 +853,7 @@ 'packages': [ { 'package': 'chromium/rts/model/windows-amd64', - 'version': 'Ktu7kz7R4AOtpedH29jJ4FLE1W7fl1JfAcDpmeQ1hCoC', + 'version': 'YopNmWOLweUxpyGrn1xyRKeXTy6UXWomTGIgeVrSvTQC', }, ], 'dep_type': 'cipd', @@ -1512,7 +1512,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'b384c7aa6bb8ac202e0cf0d5da0ec7d602b44b8b', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '02f7958f6551a697b124256d643cee71e4e350a9', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1593,7 +1593,7 @@ 'packages': [ { 'package': 'fuchsia/third_party/android/aemu/release/linux-amd64', - 'version': 'M8PFPo2AIoUMKYT_3AqnfPsVCXLmBBJxbDzzqBe7w2cC' + 'version': '0p2-SHq7A8sJ-Erp9BlMV-ufphiPNeM1Rvq_I5gk5mwC' }, ], 'condition': 'host_os == "linux" and checkout_fuchsia', @@ -1739,10 +1739,10 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'cf04aebdf9b53bb2853f22a81465688daf879ec6', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'db30f93b2d006d46832a4809813e5f1e0fc880cd', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'fd45c77b21f1ddb02917f79a28a8b6ab76d4b24c', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'd4fce5a361a4dba8a7c97e885af898e24344e7ec', + Var('webrtc_git') + '/src.git' + '@' + '0bb7cbc27866be02c4a79cc1fd53aa98fbcc1b10', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1815,7 +1815,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@1a812f4057849539863b0185540f664aafb3d598', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@d60b9b1f4d1d6991066d90f6d1ac6305fed78cfd', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/renderer/aw_key_systems.cc b/android_webview/renderer/aw_key_systems.cc index 6a81cb1..5689351 100644 --- a/android_webview/renderer/aw_key_systems.cc +++ b/android_webview/renderer/aw_key_systems.cc
@@ -9,7 +9,9 @@ void AwAddKeySystems(std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems_properties) { +#if BUILDFLAG(ENABLE_WIDEVINE) cdm::AddAndroidWidevine(key_systems_properties); +#endif // BUILDFLAG(ENABLE_WIDEVINE) cdm::AddAndroidPlatformKeySystems(key_systems_properties); }
diff --git a/ash/app_list/views/continue_section_view_unittest.cc b/ash/app_list/views/continue_section_view_unittest.cc index 2fea19c..036c532 100644 --- a/ash/app_list/views/continue_section_view_unittest.cc +++ b/ash/app_list/views/continue_section_view_unittest.cc
@@ -409,7 +409,7 @@ } TEST_P(ContinueSectionViewTest, ShowsHelpAppResults) { - AddSearchResult("id1", AppListSearchResultType::kHelpApp); + AddSearchResult("id1", AppListSearchResultType::kZeroStateHelpApp); AddSearchResult("id2", AppListSearchResultType::kZeroStateDrive); AddSearchResult("id3", AppListSearchResultType::kZeroStateFile); AddSearchResult("id4", AppListSearchResultType::kZeroStateDrive); @@ -427,7 +427,7 @@ } TEST_P(ContinueSectionViewTest, HelpAppResultNotShownWithoutEnoughOtherFiles) { - AddSearchResult("id1", AppListSearchResultType::kHelpApp); + AddSearchResult("id1", AppListSearchResultType::kZeroStateHelpApp); AddSearchResult("id2", AppListSearchResultType::kZeroStateDrive); EnsureLauncherShown(); @@ -439,7 +439,7 @@ } TEST_P(ContinueSectionViewTest, HelpAppShownInTabletModeWith2FileResults) { - AddSearchResult("id1", AppListSearchResultType::kHelpApp); + AddSearchResult("id1", AppListSearchResultType::kZeroStateHelpApp); AddSearchResult("id2", AppListSearchResultType::kZeroStateDrive); AddSearchResult("id2", AppListSearchResultType::kZeroStateFile);
diff --git a/ash/app_list/views/continue_task_view.cc b/ash/app_list/views/continue_task_view.cc index e4ee1dfc..5a90047 100644 --- a/ash/app_list/views/continue_task_view.cc +++ b/ash/app_list/views/continue_task_view.cc
@@ -196,7 +196,7 @@ ? icon : gfx::ImageSkiaOperations::CreateResizedImage( icon, skia::ImageOperations::RESIZE_BEST, GetIconSize()), - result()->result_type() == AppListSearchResultType::kHelpApp + result()->result_type() == AppListSearchResultType::kZeroStateHelpApp ? ColorProvider::ControlsLayerType::kControlBackgroundColorActive : ColorProvider::ControlsLayerType::kControlBackgroundColorInactive)); }
diff --git a/ash/capture_mode/capture_label_view.cc b/ash/capture_mode/capture_label_view.cc index 15560d3..9cceb17 100644 --- a/ash/capture_mode/capture_label_view.cc +++ b/ash/capture_mode/capture_label_view.cc
@@ -9,6 +9,7 @@ #include "ash/capture_mode/capture_mode_session.h" #include "ash/capture_mode/capture_mode_util.h" #include "ash/capture_mode/stop_recording_button_tray.h" +#include "ash/constants/ash_features.h" #include "ash/public/cpp/style/color_provider.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/strings/grit/ash_strings.h" @@ -33,6 +34,7 @@ #include "ui/views/controls/focus_ring.h" #include "ui/views/controls/highlight_path_generator.h" #include "ui/views/controls/label.h" +#include "ui/views/highlight_border.h" namespace ash { @@ -182,6 +184,12 @@ label_->SetBackgroundColor(SK_ColorTRANSPARENT); UpdateIconAndText(); + + if (features::IsDarkLightModeEnabled()) { + SetBorder(std::make_unique<views::HighlightBorder>( + kCaptureLabelRadius, views::HighlightBorder::Type::kHighlightBorder2, + /*use_light_colors=*/false)); + } } CaptureLabelView::~CaptureLabelView() = default;
diff --git a/ash/capture_mode/capture_mode_ash_notification_view.cc b/ash/capture_mode/capture_mode_ash_notification_view.cc index a1c9df41..e38b6b7 100644 --- a/ash/capture_mode/capture_mode_ash_notification_view.cc +++ b/ash/capture_mode/capture_mode_ash_notification_view.cc
@@ -7,7 +7,6 @@ #include "ash/capture_mode/capture_mode_util.h" #include "ash/public/cpp/assistant/assistant_state.h" #include "ash/shell.h" -#include "ash/style/ash_color_provider.h" #include "ui/base/l10n/l10n_util.h" #include "ui/views/background.h" #include "ui/views/view.h"
diff --git a/ash/capture_mode/capture_mode_bar_view.cc b/ash/capture_mode/capture_mode_bar_view.cc index aaa8423..f515ab86 100644 --- a/ash/capture_mode/capture_mode_bar_view.cc +++ b/ash/capture_mode/capture_mode_bar_view.cc
@@ -14,6 +14,7 @@ #include "ash/capture_mode/capture_mode_source_view.h" #include "ash/capture_mode/capture_mode_toggle_button.h" #include "ash/capture_mode/capture_mode_type_view.h" +#include "ash/constants/ash_features.h" #include "ash/public/cpp/style/color_provider.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/shelf/shelf.h" @@ -30,6 +31,7 @@ #include "ui/strings/grit/ui_strings.h" #include "ui/views/background.h" #include "ui/views/controls/separator.h" +#include "ui/views/highlight_border.h" #include "ui/views/layout/box_layout.h" #include "ui/views/style/platform_style.h" @@ -43,7 +45,7 @@ constexpr auto kBarPadding = gfx::Insets::VH(14, 16); -constexpr gfx::RoundedCornersF kBorderRadius{20.f}; +constexpr int kBorderRadius = 20; constexpr int kSeparatorHeight = 20; @@ -75,7 +77,7 @@ AshColorProvider::BaseLayerType::kTransparent80); SetBackground(views::CreateSolidBackground(background_color)); layer()->SetFillsBoundsOpaquely(false); - layer()->SetRoundedCornerRadius(kBorderRadius); + layer()->SetRoundedCornerRadius(gfx::RoundedCornersF(kBorderRadius)); layer()->SetBackgroundBlur(ColorProvider::kBackgroundBlurSigma); layer()->SetBackdropFilterQuality(ColorProvider::kBackgroundBlurQuality); @@ -108,6 +110,12 @@ close_button_->SetTooltipText( l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE)); + + if (features::IsDarkLightModeEnabled()) { + SetBorder(std::make_unique<views::HighlightBorder>( + kBorderRadius, views::HighlightBorder::Type::kHighlightBorder2, + /*use_light_colors=*/false)); + } } CaptureModeBarView::~CaptureModeBarView() = default;
diff --git a/ash/capture_mode/capture_mode_constants.h b/ash/capture_mode/capture_mode_constants.h index 929f68a..33235ec 100644 --- a/ash/capture_mode/capture_mode_constants.h +++ b/ash/capture_mode/capture_mode_constants.h
@@ -29,6 +29,7 @@ // Constants needed to paint the highlight around the area being captured. constexpr int kCaptureRegionBorderStrokePx = 1; +// This color is set to WHITE on purpose in both dark and light mode. constexpr SkColor kRegionBorderColor = SK_ColorWHITE; // The space between the `image_toggle_button_` and `video_toggle_button_`.
diff --git a/ash/capture_mode/capture_mode_notification_view.cc b/ash/capture_mode/capture_mode_notification_view.cc index a5ea531c..e4ea4ae 100644 --- a/ash/capture_mode/capture_mode_notification_view.cc +++ b/ash/capture_mode/capture_mode_notification_view.cc
@@ -7,7 +7,6 @@ #include "ash/capture_mode/capture_mode_util.h" #include "ash/public/cpp/assistant/assistant_state.h" #include "ash/shell.h" -#include "ash/style/ash_color_provider.h" #include "ui/base/l10n/l10n_util.h" #include "ui/views/background.h" #include "ui/views/view.h"
diff --git a/ash/capture_mode/capture_mode_session.cc b/ash/capture_mode/capture_mode_session.cc index 87846593..2d33355 100644 --- a/ash/capture_mode/capture_mode_session.cc +++ b/ash/capture_mode/capture_mode_session.cc
@@ -108,8 +108,11 @@ constexpr int kSizeLabelHorizontalPadding = 8; -// Blue300 at 30%. -constexpr SkColor kCaptureRegionColor = SkColorSetA(gfx::kGoogleBlue300, 77); +// Dimming shield color in the capture session. It is set to be the same color +// in both dark and light mode. We will investigate whether to do this kind of +// change to ShieldLayer globally. +// Grey900 at 40%. +constexpr SkColor kDimmingShieldColor = SkColorSetA(gfx::kGoogleGrey900, 102); // Values for the shadows of the capture region components. constexpr int kRegionAffordanceCircleShadow2Blur = 6; @@ -1014,11 +1017,7 @@ } ui::PaintRecorder recorder(context, layer()->size()); - - auto* color_provider = AshColorProvider::Get(); - const SkColor dimming_color = color_provider->GetShieldLayerColor( - AshColorProvider::ShieldLayerType::kShield40); - recorder.canvas()->DrawColor(dimming_color); + recorder.canvas()->DrawColor(kDimmingShieldColor); PaintCaptureRegion(recorder.canvas()); } @@ -1628,7 +1627,9 @@ if (!adjustable_region) { canvas->FillRect(region, SK_ColorTRANSPARENT, SkBlendMode::kClear); - canvas->FillRect(region, kCaptureRegionColor); + canvas->FillRect( + region, AshColorProvider::Get()->GetContentLayerColor( + AshColorProvider::ContentLayerType::kCaptureRegionColor)); return; }
diff --git a/ash/capture_mode/user_nudge_controller.cc b/ash/capture_mode/user_nudge_controller.cc index f6a4bf9..b6e89ee 100644 --- a/ash/capture_mode/user_nudge_controller.cc +++ b/ash/capture_mode/user_nudge_controller.cc
@@ -88,10 +88,12 @@ // Rings are created initially with 0 opacity. Calling SetVisible() will // animate them towards their correct state. - base_ring_.SetColor(SK_ColorWHITE); + const SkColor ring_color = + AshColorProvider::Get()->GetInkDropBaseColorAndOpacity().first; + base_ring_.SetColor(ring_color); base_ring_.SetFillsBoundsOpaquely(false); base_ring_.SetOpacity(0); - ripple_ring_.SetColor(SK_ColorWHITE); + ripple_ring_.SetColor(ring_color); ripple_ring_.SetFillsBoundsOpaquely(false); ripple_ring_.SetOpacity(0);
diff --git a/ash/host/ash_window_tree_host_mirroring_unified.cc b/ash/host/ash_window_tree_host_mirroring_unified.cc index 2185f75..b77991b 100644 --- a/ash/host/ash_window_tree_host_mirroring_unified.cc +++ b/ash/host/ash_window_tree_host_mirroring_unified.cc
@@ -44,8 +44,7 @@ } void AshWindowTreeHostMirroringUnified::ConvertDIPToPixels( - gfx::Point* point) const { - auto point_3f = gfx::Point3F(gfx::PointF(*point)); + gfx::PointF* point) const { // GetRootTransform() returns a transform that takes a point from the // *unified* host coordinates to the *mirroring* host's pixel coordinates. // ConvertDIPToPixels() and ConvertDIPToScreenInPixels() are called on local @@ -54,15 +53,12 @@ // defined above, which only scales those local points to the right size, and // leaves the translation to be done by the MirroringScreenPositionClient // functions. - GetRootTransformForLocalEventCoordinates().TransformPoint(&point_3f); - *point = gfx::ToFlooredPoint(point_3f.AsPointF()); + GetRootTransformForLocalEventCoordinates().TransformPoint(point); } void AshWindowTreeHostMirroringUnified::ConvertPixelsToDIP( - gfx::Point* point) const { - auto point_3f = gfx::Point3F(gfx::PointF(*point)); - GetInverseRootTransformForLocalEventCoordinates().TransformPoint(&point_3f); - *point = gfx::ToFlooredPoint(point_3f.AsPointF()); + gfx::PointF* point) const { + GetInverseRootTransformForLocalEventCoordinates().TransformPoint(point); } void AshWindowTreeHostMirroringUnified::PrepareForShutdown() {
diff --git a/ash/host/ash_window_tree_host_mirroring_unified.h b/ash/host/ash_window_tree_host_mirroring_unified.h index 63ab009..4f351e4c 100644 --- a/ash/host/ash_window_tree_host_mirroring_unified.h +++ b/ash/host/ash_window_tree_host_mirroring_unified.h
@@ -29,8 +29,8 @@ // aura::WindowTreeHost: gfx::Transform GetRootTransformForLocalEventCoordinates() const override; - void ConvertDIPToPixels(gfx::Point* point) const override; - void ConvertPixelsToDIP(gfx::Point* point) const override; + void ConvertDIPToPixels(gfx::PointF* point) const override; + void ConvertPixelsToDIP(gfx::PointF* point) const override; // ash::AshWindowTreeHostPlatform: void PrepareForShutdown() override;
diff --git a/ash/login/ui/access_code_input.cc b/ash/login/ui/access_code_input.cc index 3edb773..f63927f 100644 --- a/ash/login/ui/access_code_input.cc +++ b/ash/login/ui/access_code_input.cc
@@ -189,9 +189,13 @@ void AccessibleInputField::GetAccessibleNodeData(ui::AXNodeData* node_data) { // Focusable nodes generally must have a name, but the focus of an accessible // input field is propagated to its ancestor. - node_data->SetNameFrom(ax::mojom::NameFrom::kAttributeExplicitlyEmpty); - views::Textfield::GetAccessibleNodeData(node_data); + + // We want the PIN input field, an empty input field, to retain + // NameFrom::kAttributeExplicitlyEmpty. However + // Textfield::GetAccessibleNodeData() sets NameFrom to NameFrom::kContent. + // We override NameFrom after this call. + node_data->SetNameFrom(ax::mojom::NameFrom::kAttributeExplicitlyEmpty); } FixedLengthCodeInput::FixedLengthCodeInput(int length,
diff --git a/ash/public/cpp/app_list/app_list_types.cc b/ash/public/cpp/app_list/app_list_types.cc index 21d1223..5eb88abf 100644 --- a/ash/public/cpp/app_list/app_list_types.cc +++ b/ash/public/cpp/app_list/app_list_types.cc
@@ -37,6 +37,7 @@ case AppListSearchResultType::kInternalPrivacyInfo: case AppListSearchResultType::kAssistantText: case AppListSearchResultType::kHelpApp: + case AppListSearchResultType::kZeroStateHelpApp: case AppListSearchResultType::kFileSearch: case AppListSearchResultType::kDriveSearch: case AppListSearchResultType::kKeyboardShortcut:
diff --git a/ash/public/cpp/app_list/app_list_types.h b/ash/public/cpp/app_list/app_list_types.h index 9479d7e..4632755 100644 --- a/ash/public/cpp/app_list/app_list_types.h +++ b/ash/public/cpp/app_list/app_list_types.h
@@ -375,8 +375,9 @@ kOpenTab, // Open tab search results. kGames, // Game sarch results. kPersonalization, // Personalization search results. + kZeroStateHelpApp, // Help App (aka Explore) results for zero-state. // Add new values here. - kMaxValue = kPersonalization, + kMaxValue = kZeroStateHelpApp, }; ASH_PUBLIC_EXPORT bool IsAppListSearchResultAnApp( @@ -549,7 +550,7 @@ kHide, // Completely hide this text item when there is not enough space. }; - SearchResultTextItem(SearchResultTextItemType type); + explicit SearchResultTextItem(SearchResultTextItemType type); SearchResultTextItem(const SearchResultTextItem&); SearchResultTextItem& operator=(const SearchResultTextItem&); ~SearchResultTextItem();
diff --git a/ash/public/cpp/style/color_provider.h b/ash/public/cpp/style/color_provider.h index 1463177..5d0c3ade 100644 --- a/ash/public/cpp/style/color_provider.h +++ b/ash/public/cpp/style/color_provider.h
@@ -139,7 +139,10 @@ kBatterySystemInfoBackgroundColor, // Color for the battery icon in the system info view. - kBatterySystemInfoIconColor + kBatterySystemInfoIconColor, + + // Color of the capture region in the capture session. + kCaptureRegionColor, }; static ColorProvider* Get();
diff --git a/ash/style/ash_color_provider.cc b/ash/style/ash_color_provider.cc index c83c528..16d4a01 100644 --- a/ash/style/ash_color_provider.cc +++ b/ash/style/ash_color_provider.cc
@@ -479,6 +479,7 @@ case ContentLayerType::kProgressBarColorForeground: return use_dark_color ? gfx::kGoogleBlue300 : gfx::kGoogleBlue600; case ContentLayerType::kProgressBarColorBackground: + case ContentLayerType::kCaptureRegionColor: return SkColorSetA( use_dark_color ? gfx::kGoogleBlue300 : gfx::kGoogleBlue600, 0x4C); case ContentLayerType::kSwitchTrackColorActive:
diff --git a/ash/system/unified/feature_pod_button.cc b/ash/system/unified/feature_pod_button.cc index 69dede76..2a7ba90 100644 --- a/ash/system/unified/feature_pod_button.cc +++ b/ash/system/unified/feature_pod_button.cc
@@ -92,9 +92,6 @@ SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); - views::FocusRing::Get(this)->SetColor( - AshColorProvider::Get()->GetControlsLayerColor( - ControlsLayerType::kFocusRingColor)); views::InstallRoundRectHighlightPathGenerator( this, gfx::Insets(), kUnifiedFeaturePodHoverCornerRadius); } @@ -156,6 +153,10 @@ void FeaturePodLabelButton::OnThemeChanged() { views::Button::OnThemeChanged(); OnEnabledChanged(); + + views::FocusRing::Get(this)->SetColor( + AshColorProvider::Get()->GetControlsLayerColor( + ControlsLayerType::kFocusRingColor)); } void FeaturePodLabelButton::SetLabel(const std::u16string& label) {
diff --git a/ash/system/unified/top_shortcuts_view.cc b/ash/system/unified/top_shortcuts_view.cc index 8382ae05..d8ba518 100644 --- a/ash/system/unified/top_shortcuts_view.cc +++ b/ash/system/unified/top_shortcuts_view.cc
@@ -50,6 +50,9 @@ UserAvatarButton& operator=(const UserAvatarButton&) = delete; ~UserAvatarButton() override = default; + + // views::Button: + void OnThemeChanged() override; }; UserAvatarButton::UserAvatarButton(PressedCallback callback) @@ -63,6 +66,10 @@ SetInstallFocusRingOnFocus(true); views::InstallCircleHighlightPathGenerator(this); +} + +void UserAvatarButton::OnThemeChanged() { + views::Button::OnThemeChanged(); views::FocusRing::Get(this)->SetColor( AshColorProvider::Get()->GetControlsLayerColor( AshColorProvider::ControlsLayerType::kFocusRingColor));
diff --git a/ash/webui/eche_app_ui/eche_recent_app_click_handler.cc b/ash/webui/eche_app_ui/eche_recent_app_click_handler.cc index 5f5e81ed..6245b8e 100644 --- a/ash/webui/eche_app_ui/eche_recent_app_click_handler.cc +++ b/ash/webui/eche_app_ui/eche_recent_app_click_handler.cc
@@ -68,7 +68,8 @@ break; case LaunchAppHelper::AppLaunchProhibitedReason::kDisabledByScreenLock: launch_app_helper_->ShowNotification( - /* title= */ absl::nullopt, /* message= */ absl::nullopt, + /* title= */ app_metadata.visible_app_name, + /* message= */ absl::nullopt, std::make_unique<LaunchAppHelper::NotificationInfo>( LaunchAppHelper::NotificationInfo::Category::kNative, LaunchAppHelper::NotificationInfo::NotificationType::
diff --git a/ash/webui/os_feedback_ui/BUILD.gn b/ash/webui/os_feedback_ui/BUILD.gn index 8893887..bfd4c2d 100644 --- a/ash/webui/os_feedback_ui/BUILD.gn +++ b/ash/webui/os_feedback_ui/BUILD.gn
@@ -22,6 +22,7 @@ "//ash/webui/os_feedback_ui/mojom", "//ash/webui/resources:os_feedback_resources", "//ash/webui/resources:os_feedback_untrusted_resources", + "//chromeos/strings/", "//content/public/browser", "//ui/resources", "//ui/webui",
diff --git a/ash/webui/os_feedback_ui/os_feedback_ui.cc b/ash/webui/os_feedback_ui/os_feedback_ui.cc index 98c27004..a68e67c 100644 --- a/ash/webui/os_feedback_ui/os_feedback_ui.cc +++ b/ash/webui/os_feedback_ui/os_feedback_ui.cc
@@ -14,6 +14,7 @@ #include "ash/webui/os_feedback_ui/backend/os_feedback_delegate.h" #include "ash/webui/os_feedback_ui/mojom/os_feedback_ui.mojom.h" #include "ash/webui/os_feedback_ui/url_constants.h" +#include "chromeos/strings/grit/chromeos_strings.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" @@ -38,6 +39,17 @@ IDR_WEBUI_JS_TEST_LOADER_UTIL_JS); } +void AddLocalizedStrings(content::WebUIDataSource* source) { + static constexpr webui::LocalizedString kLocalizedStrings[] = { + {"continueButtonLabel", IDS_FEEDBACK_TOOL_CONTINUE_BUTTON_LABEL}, + {"descriptionLabel", IDS_FEEDBACK_TOOL_DESCRIPTION_LABEL}, + {"pageTitle", IDS_FEEDBACK_TOOL_PAGE_TITLE}, + }; + + source->AddLocalizedStrings(kLocalizedStrings); + source->UseStringsJs(); +} + } // namespace OSFeedbackUI::OSFeedbackUI( @@ -65,6 +77,7 @@ const auto resources = base::make_span(kAshOsFeedbackResources, kAshOsFeedbackResourcesSize); SetUpWebUIDataSource(source, resources, IDR_ASH_OS_FEEDBACK_INDEX_HTML); + AddLocalizedStrings(source); // Register common permissions for chrome-untrusted:// pages. // TODO(https://crbug.com/1113568): Remove this after common permissions are
diff --git a/ash/webui/os_feedback_ui/resources/BUILD.gn b/ash/webui/os_feedback_ui/resources/BUILD.gn index 053f368..fe355b0 100644 --- a/ash/webui/os_feedback_ui/resources/BUILD.gn +++ b/ash/webui/os_feedback_ui/resources/BUILD.gn
@@ -136,6 +136,7 @@ ":help_content", ":mojo_interface_provider", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:i18n_behavior.m", ] }
diff --git a/ash/webui/os_feedback_ui/resources/feedback_flow.js b/ash/webui/os_feedback_ui/resources/feedback_flow.js index 6d7313a..5d0c57e 100644 --- a/ash/webui/os_feedback_ui/resources/feedback_flow.js +++ b/ash/webui/os_feedback_ui/resources/feedback_flow.js
@@ -6,6 +6,7 @@ import './confirmation_page.js'; import './search_page.js'; import './share_data_page.js'; +import './strings.m.js'; import {stringToMojoString16} from 'chrome://resources/ash/common/mojo_utils.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/ash/webui/os_feedback_ui/resources/search_page.html b/ash/webui/os_feedback_ui/resources/search_page.html index 33cbd61..f664d97b 100644 --- a/ash/webui/os_feedback_ui/resources/search_page.html +++ b/ash/webui/os_feedback_ui/resources/search_page.html
@@ -21,11 +21,11 @@ <!--TODO(xiangdongkong): use localized strings --> <div id="container"> <div id="header"> - <h1 id="title">Send feedback</h1> + <h1 id="title">[[i18n('pageTitle')]]</h1> </div> <div id="content"> <div id="descriptionPane"> - <p id="descriptionTitle">Description</p> + <p id="descriptionTitle">[[i18n('descriptionLabel')]]</p> <textarea id="descriptionText" aria-labelledby="descriptionTitle" aria-required="true" on-input="handleInputChanged_"> </textarea> @@ -40,7 +40,7 @@ <div id="navButtons"> <cr-button id="buttonContinue" class="action-button" on-click="handleContinueButtonClicked_"> - Continue + [[i18n('continueButtonLabel')]] </cr-button> </div> </div>
diff --git a/ash/webui/os_feedback_ui/resources/search_page.js b/ash/webui/os_feedback_ui/resources/search_page.js index 14bbf3b..af1f95a 100644 --- a/ash/webui/os_feedback_ui/resources/search_page.js +++ b/ash/webui/os_feedback_ui/resources/search_page.js
@@ -8,7 +8,8 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import {stringToMojoString16} from 'chrome://resources/ash/common/mojo_utils.js'; -import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; +import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {FeedbackFlowState} from './feedback_flow.js'; import {HelpContentList, HelpContentProviderInterface, SearchRequest, SearchResponse, SearchResult} from './feedback_types.js'; @@ -38,7 +39,16 @@ * 'search-page' is the first step of the feedback tool. It displays live help * contents relevant to the text entered by the user. */ -export class SearchPageElement extends PolymerElement { + +/** + * @constructor + * @extends {PolymerElement} + * @implements {I18nBehaviorInterface} + */ +const SearchPageElementBase = mixinBehaviors([I18nBehavior], PolymerElement); + +/** @polymer */ +export class SearchPageElement extends SearchPageElementBase { static get is() { return 'search-page'; }
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_app.ts b/ash/webui/personalization_app/resources/trusted/personalization_app.ts index abb12d0c..1a9c34c 100644 --- a/ash/webui/personalization_app/resources/trusted/personalization_app.ts +++ b/ash/webui/personalization_app/resources/trusted/personalization_app.ts
@@ -106,6 +106,7 @@ export {WallpaperObserver} from './wallpaper/wallpaper_observer.js'; export {WallpaperPreview} from './wallpaper/wallpaper_preview_element.js'; export {WallpaperSelected} from './wallpaper/wallpaper_selected_element.js'; +export {DailyRefreshType} from './wallpaper/wallpaper_state.js'; PersonalizationStore.getInstance().init(emptyState()); const link = document.querySelector('link[rel=\'icon\']') as HTMLLinkElement;
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_actions.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_actions.ts index 449c033..0037cb5 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_actions.ts +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_actions.ts
@@ -27,9 +27,12 @@ BEGIN_LOAD_SELECTED_IMAGE = 'begin_load_selected_image', BEGIN_SELECT_IMAGE = 'begin_select_image', BEGIN_UPDATE_DAILY_REFRESH_IMAGE = 'begin_update_daily_refresh_image', + CLEAR_DAILY_REFRESH_ACTION = 'clear_daily_refresh_action', END_SELECT_IMAGE = 'end_select_image', SET_COLLECTIONS = 'set_collections', SET_DAILY_REFRESH_COLLECTION_ID = 'set_daily_refresh_collection_id', + SET_GOOGLE_PHOTOS_DAILY_REFRESH_ALBUM_ID = + 'set_google_photos_daily_refresh_album_id', SET_GOOGLE_PHOTOS_ENABLED = 'set_google_photos_enabled', SET_IMAGES_FOR_COLLECTION = 'set_images_for_collection', SET_LOCAL_IMAGES = 'set_local_images', @@ -39,15 +42,15 @@ SET_FULLSCREEN_ENABLED = 'set_fullscreen_enabled', } -export type WallpaperActions = - AppendGooglePhotosAlbumAction|AppendGooglePhotosAlbumsAction| - AppendGooglePhotosPhotosAction|BeginLoadGooglePhotosAlbumAction| - BeginLoadGooglePhotosAlbumsAction|BeginLoadGooglePhotosEnabledAction| - BeginLoadGooglePhotosPhotosAction|BeginLoadImagesForCollectionsAction| - BeginLoadLocalImagesAction|BeginLoadLocalImageDataAction| - BeginUpdateDailyRefreshImageAction|BeginLoadSelectedImageAction| - BeginSelectImageAction|EndSelectImageAction|SetCollectionsAction| - SetDailyRefreshCollectionIdAction|SetGooglePhotosEnabledAction| +export type WallpaperActions = AppendGooglePhotosAlbumAction| + AppendGooglePhotosAlbumsAction|AppendGooglePhotosPhotosAction| + BeginLoadGooglePhotosAlbumAction|BeginLoadGooglePhotosAlbumsAction| + BeginLoadGooglePhotosEnabledAction|BeginLoadGooglePhotosPhotosAction| + BeginLoadImagesForCollectionsAction|BeginLoadLocalImagesAction| + BeginLoadLocalImageDataAction|BeginUpdateDailyRefreshImageAction| + BeginLoadSelectedImageAction|BeginSelectImageAction|ClearDailyRefreshAction| + EndSelectImageAction|SetCollectionsAction|SetDailyRefreshCollectionIdAction| + SetGooglePhotosDailyRefreshAlbumIdAction|SetGooglePhotosEnabledAction| SetImagesForCollectionAction|SetLocalImageDataAction|SetLocalImagesAction| SetUpdatedDailyRefreshImageAction|SetSelectedImageAction| SetFullscreenEnabledAction; @@ -278,13 +281,13 @@ export type SetDailyRefreshCollectionIdAction = Action&{ name: WallpaperActionName.SET_DAILY_REFRESH_COLLECTION_ID, - collectionId: string | null, + collectionId: string, }; /** * Set and enable daily refresh for given collectionId. */ -export function setDailyRefreshCollectionIdAction(collectionId: string|null): +export function setDailyRefreshCollectionIdAction(collectionId: string): SetDailyRefreshCollectionIdAction { return { collectionId, @@ -292,6 +295,36 @@ }; } +export type SetGooglePhotosDailyRefreshAlbumIdAction = Action&{ + name: WallpaperActionName.SET_GOOGLE_PHOTOS_DAILY_REFRESH_ALBUM_ID, + albumId: string, +}; + +/** + * Set and enable daily refresh for given Google Photos albumId. + */ +export function setGooglePhotosDailyRefreshAlbumIdAction(albumId: string): + SetGooglePhotosDailyRefreshAlbumIdAction { + return { + albumId, + name: WallpaperActionName.SET_GOOGLE_PHOTOS_DAILY_REFRESH_ALBUM_ID, + }; +} + +export type ClearDailyRefreshAction = Action&{ + name: WallpaperActionName.CLEAR_DAILY_REFRESH_ACTION, +}; + +/** + * Clear the data related to daily refresh, indicating daily refresh is not + * active. + */ +export function clearDailyRefreshAction(): ClearDailyRefreshAction { + return { + name: WallpaperActionName.CLEAR_DAILY_REFRESH_ACTION, + }; +} + export type SetGooglePhotosEnabledAction = Action&{ name: WallpaperActionName.SET_GOOGLE_PHOTOS_ENABLED, enabled: GooglePhotosEnablementState,
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_reducers.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_reducers.ts index 7c41b9d..15c55456 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_reducers.ts +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_reducers.ts
@@ -11,7 +11,7 @@ import {PersonalizationState} from '../personalization_state.js'; import {WallpaperActionName} from './wallpaper_actions.js'; -import {WallpaperState} from './wallpaper_state.js'; +import {DailyRefreshType, WallpaperState} from './wallpaper_state.js'; function backdropReducer( state: WallpaperState['backdrop'], action: Actions, @@ -300,9 +300,16 @@ switch (action.name) { case WallpaperActionName.SET_DAILY_REFRESH_COLLECTION_ID: return { - ...state, - collectionId: action.collectionId, + id: action.collectionId, + type: DailyRefreshType.BACKDROP, }; + case WallpaperActionName.SET_GOOGLE_PHOTOS_DAILY_REFRESH_ALBUM_ID: + return { + id: action.albumId, + type: DailyRefreshType.GOOGLE_PHOTOS, + }; + case WallpaperActionName.CLEAR_DAILY_REFRESH_ACTION: + return null; default: return state; }
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_selected_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_selected_element.ts index f7aa050..456cd929 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_selected_element.ts +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_selected_element.ts
@@ -163,7 +163,9 @@ state.wallpaper.loading.refreshWallpaper); this.watch( 'dailyRefreshCollectionId_', - state => state.wallpaper.dailyRefresh.collectionId); + state => state.wallpaper.dailyRefresh ? + state.wallpaper.dailyRefresh.id : + null); this.updateFromStore(); getDailyRefreshCollectionId(this.wallpaperProvider_, this.getStore()); }
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_state.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_state.ts index 65c9692f..5082201 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_state.ts +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_state.ts
@@ -80,8 +80,18 @@ data: Record<FilePath['path'], string>; } +export enum DailyRefreshType { + GOOGLE_PHOTOS = 'daily_refresh_google_photos', + BACKDROP = 'daily_refresh_backdrop', +} + +/** + * |id| stores either a Backdrop collection id or a Google Photos album id. + * |type| stores which type of daily refresh and type of id this is. + */ export interface DailyRefreshState { - collectionId: string|null; + id: string; + type: DailyRefreshType; } export interface WallpaperState { @@ -90,7 +100,7 @@ local: LocalState; currentSelected: CurrentWallpaper|null; pendingSelected: WallpaperImage|FilePath|GooglePhotosPhoto|null; - dailyRefresh: DailyRefreshState; + dailyRefresh: DailyRefreshState|null; fullscreen: boolean; googlePhotos: GooglePhotosState; } @@ -115,7 +125,7 @@ local: {images: null, data: {}}, currentSelected: null, pendingSelected: null, - dailyRefresh: {collectionId: null}, + dailyRefresh: null, fullscreen: false, googlePhotos: { enabled: undefined,
diff --git a/ash/webui/shimless_rma/resources/BUILD.gn b/ash/webui/shimless_rma/resources/BUILD.gn index 0462655..b873d80 100644 --- a/ash/webui/shimless_rma/resources/BUILD.gn +++ b/ash/webui/shimless_rma/resources/BUILD.gn
@@ -61,6 +61,7 @@ "illustrations/insert_usb.svg", "illustrations/lid_on_flat_surface.svg", "illustrations/repair_start.svg", + "illustrations/success.svg", "illustrations/update_os.svg", "shimless_rma_types.js", "shimless_rma_util.js",
diff --git a/ash/webui/shimless_rma/resources/base_page.html b/ash/webui/shimless_rma/resources/base_page.html index 02d577b..b7b78dd6 100644 --- a/ash/webui/shimless_rma/resources/base_page.html +++ b/ash/webui/shimless_rma/resources/base_page.html
@@ -7,15 +7,31 @@ width: 100%; } + :host([equal-panes]) #leftPane { + width: 50%; + } + + :host([equal-panes]) #rightPane { + width: 50%; + } + + :host([left-pane-only]) #leftPane { + margin-inline-end: 0; + width: 100%; + } + + :host([left-pane-only]) #rightPane { + width: 0; + } + #leftPane { box-sizing: border-box; - padding-inline-end: 32px; + margin-inline-end: 80px; width: 40%; } #rightPane { box-sizing: border-box; - padding-inline-start: 48px; width: 60%; }
diff --git a/ash/webui/shimless_rma/resources/illustrations/success.svg b/ash/webui/shimless_rma/resources/illustrations/success.svg new file mode 100644 index 0000000..25a4a42 --- /dev/null +++ b/ash/webui/shimless_rma/resources/illustrations/success.svg
@@ -0,0 +1,9 @@ +<svg width="320" height="320" viewBox="0 0 320 320" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M167.4 234.8C212.356 234.8 248.8 198.356 248.8 153.4C248.8 108.444 212.356 72 167.4 72C122.444 72 86 108.444 86 153.4C86 198.356 122.444 234.8 167.4 234.8Z" fill="#4285F4"/> +<path d="M291.9 74.5004L271.3 69.0004C270.4 68.8004 269.9 67.8004 270.1 66.9004L275.6 46.3004C275.8 45.4004 276.8 44.9004 277.7 45.1004L298.3 50.6004C299.2 50.8004 299.7 51.8004 299.5 52.7004L294 73.3004C293.7 74.2004 292.8 74.7004 291.9 74.5004Z" fill="#4285F4"/> +<path d="M30.9001 258.4C27.9001 253.3 29.7001 246.7 34.8001 243.7L50.7001 234.5C55.8001 231.5 62.4001 233.3 65.4001 238.4C68.4001 243.5 66.6001 250.1 61.5001 253.1L45.6001 262.3C40.5001 265.3 33.9001 263.5 30.9001 258.4Z" stroke="#4285F4" stroke-width="3" stroke-miterlimit="10" stroke-linejoin="round"/> +<path d="M41.4 76.3996L31.6 66.5996C30.4 65.3996 30 63.7996 30.4 62.1996L34 48.7996C34.4 47.1996 35.7 45.9996 37.2 45.5996L50.6 41.9996C52.2 41.5996 53.9 41.9996 55 43.1996L64.8 52.9996C66 54.1996 66.4 55.7996 66 57.3996L62.4 70.7996C62 72.3996 60.7 73.5996 59.2 73.9996L45.8 77.5996C44.2 77.9996 42.5 77.5996 41.4 76.3996Z" fill="#1E8E3E"/> +<path d="M41.1994 220.9L31.9994 214.1C31.5994 213.8 31.4994 213.2 31.7994 212.8L38.5994 203.6C38.8994 203.2 39.4994 203.1 39.8994 203.4L49.0994 210.2C49.4994 210.5 49.5994 211.1 49.2994 211.5L42.4994 220.7C42.0994 221.1 41.5994 221.2 41.1994 220.9Z" fill="#F9AB00"/> +<path d="M167.1 270.9C232.104 270.9 284.8 218.204 284.8 153.2C284.8 88.1961 232.104 35.5 167.1 35.5C102.096 35.5 49.4004 88.1961 49.4004 153.2C49.4004 218.204 102.096 270.9 167.1 270.9Z" stroke="#8AB4F8" stroke-width="4" stroke-miterlimit="10" stroke-linejoin="round"/> +<path d="M136 152.9L158.5 175.4L199.1 130" stroke="white" stroke-width="6" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> +</svg>
diff --git a/ash/webui/shimless_rma/resources/onboarding_choose_destination_page.html b/ash/webui/shimless_rma/resources/onboarding_choose_destination_page.html index f27a7341..d72a47a 100644 --- a/ash/webui/shimless_rma/resources/onboarding_choose_destination_page.html +++ b/ash/webui/shimless_rma/resources/onboarding_choose_destination_page.html
@@ -1,7 +1,7 @@ <style include="cr-shared-style shimless-rma-shared"> </style> -<base-page> +<base-page left-pane-only> <div slot="left-pane"> <h1>[[i18n('chooseDestinationTitleText')]]</h1> <cr-radio-group
diff --git a/ash/webui/shimless_rma/resources/onboarding_choose_wipe_device_page.html b/ash/webui/shimless_rma/resources/onboarding_choose_wipe_device_page.html index 9060373..3f72e08 100644 --- a/ash/webui/shimless_rma/resources/onboarding_choose_wipe_device_page.html +++ b/ash/webui/shimless_rma/resources/onboarding_choose_wipe_device_page.html
@@ -1,6 +1,6 @@ <style include="cr-shared-style shimless-rma-shared"> </style> -<base-page> +<base-page left-pane-only> <div slot="left-pane"> <h1>[[i18n('wipeDeviceTitleText')]]</h1> <!-- TODO(gavinwill): Replace |disabled| with variable -->
diff --git a/ash/webui/shimless_rma/resources/onboarding_choose_wp_disable_method_page.html b/ash/webui/shimless_rma/resources/onboarding_choose_wp_disable_method_page.html index e89717e..6bb0ee83 100644 --- a/ash/webui/shimless_rma/resources/onboarding_choose_wp_disable_method_page.html +++ b/ash/webui/shimless_rma/resources/onboarding_choose_wp_disable_method_page.html
@@ -1,7 +1,7 @@ <style include="cr-shared-style shimless-rma-shared"> </style> -<base-page> +<base-page left-pane-only> <div slot="left-pane"> <h1>[[i18n('chooseWpDisableMethodPageTitleText')]]</h1> <cr-radio-group
diff --git a/ash/webui/shimless_rma/resources/onboarding_update_page.html b/ash/webui/shimless_rma/resources/onboarding_update_page.html index 2f343c06..3edcb10 100644 --- a/ash/webui/shimless_rma/resources/onboarding_update_page.html +++ b/ash/webui/shimless_rma/resources/onboarding_update_page.html
@@ -12,7 +12,7 @@ color: var(--cros-icon-color-secondary); } </style> -<base-page> +<base-page equal-panes> <div slot="left-pane"> <h1>[[i18n('osUpdateTitleText')]]</h1> <div id="updateInstructionsDiv" hidden$="[[updateInProgress_]]">
diff --git a/ash/webui/shimless_rma/resources/onboarding_wait_for_manual_wp_disable_page.html b/ash/webui/shimless_rma/resources/onboarding_wait_for_manual_wp_disable_page.html index e5ec25efb..4639a35 100644 --- a/ash/webui/shimless_rma/resources/onboarding_wait_for_manual_wp_disable_page.html +++ b/ash/webui/shimless_rma/resources/onboarding_wait_for_manual_wp_disable_page.html
@@ -1,7 +1,7 @@ <style include="cr-shared-style shimless-rma-shared"> </style> -<base-page> +<base-page equal-panes> <div slot="left-pane"> <h1>[[getPageTitle_(hwwpEnabled_)]]</h1> <div id="manuallyDisableHwwpInstructions" class="instructions">
diff --git a/ash/webui/shimless_rma/resources/reimaging_calibration_failed_page.html b/ash/webui/shimless_rma/resources/reimaging_calibration_failed_page.html index 610b19b..0548c453 100644 --- a/ash/webui/shimless_rma/resources/reimaging_calibration_failed_page.html +++ b/ash/webui/shimless_rma/resources/reimaging_calibration_failed_page.html
@@ -1,19 +1,12 @@ <style include="cr-shared-style shimless-rma-shared"> </style> -<base-page> +<base-page equal-panes> <div slot="left-pane"> <h1>[[i18n('calibrationFailedTitleText')]]</h1> <div class="instructions"> [[i18n('calibrationFailedInstructionsText')]] </div> - <div> - <cr-button id="retryCalibrationButton" class="cancel-button" - on-click="onRetryCalibrationButtonClicked_" - disabled="[[allButtonsDisabled]]"> - [[i18n('calibrationFailedRetryButtonLabel')]] - </cr-button> - </div> </div> <div slot="right-pane"> <div class="component-grid calibration">
diff --git a/ash/webui/shimless_rma/resources/reimaging_calibration_failed_page.js b/ash/webui/shimless_rma/resources/reimaging_calibration_failed_page.js index 7c23e25..2ada8f34 100644 --- a/ash/webui/shimless_rma/resources/reimaging_calibration_failed_page.js +++ b/ash/webui/shimless_rma/resources/reimaging_calibration_failed_page.js
@@ -142,8 +142,6 @@ }); } - // TODO(swifton): Implement onNextButtonClick. It should retry calibration. - /** * @return {!Promise<!StateResult>} * @private @@ -159,12 +157,9 @@ return this.shimlessRmaService_.startCalibration(skippedComponents); } - /** @private */ - onRetryCalibrationButtonClicked_() { - executeThenTransitionState( - this, - () => this.shimlessRmaService_.startCalibration( - this.getComponentsList_())); + /** @return {!Promise<!StateResult>} */ + onNextButtonClick() { + return this.shimlessRmaService_.startCalibration(this.getComponentsList_()); } /**
diff --git a/ash/webui/shimless_rma/resources/reimaging_calibration_run_page.html b/ash/webui/shimless_rma/resources/reimaging_calibration_run_page.html index 1add3ae3..dd443516 100644 --- a/ash/webui/shimless_rma/resources/reimaging_calibration_run_page.html +++ b/ash/webui/shimless_rma/resources/reimaging_calibration_run_page.html
@@ -10,8 +10,7 @@ <paper-spinner-lite active hidden$="[[calibrationComplete_]]" class="large-spinner"> </paper-spinner-lite> - <!-- TODO(gavinwill): Replace calibration complete illustration. --> - <img class="illustration" src="illustrations/downloading.svg" + <img class="illustration" src="illustrations/success.svg" hidden$="[[!calibrationComplete_]]"> </div> </div>
diff --git a/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html b/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html index 05f30b1..b7226a0 100644 --- a/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html +++ b/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html
@@ -1,6 +1,6 @@ <style include="cr-shared-style shimless-rma-shared"> </style> -<base-page> +<base-page equal-panes> <iron-icon slot="optional-icon" icon="shimless-icon:warning" class="warning-icon" hidden="[[!shouldShowWarning_]]"> </iron-icon>
diff --git a/ash/webui/shimless_rma/resources/shimless_rma.js b/ash/webui/shimless_rma/resources/shimless_rma.js index 8a2f35e..15371cd 100644 --- a/ash/webui/shimless_rma/resources/shimless_rma.js +++ b/ash/webui/shimless_rma/resources/shimless_rma.js
@@ -201,7 +201,7 @@ }, [State.kFinalize]: { componentIs: 'wrapup-finalize-page', - buttonNext: ButtonState.VISIBLE, + buttonNext: ButtonState.HIDDEN, buttonCancel: ButtonState.HIDDEN, buttonBack: ButtonState.VISIBLE, },
diff --git a/ash/webui/shimless_rma/resources/shimless_rma_shared_css.html b/ash/webui/shimless_rma/resources/shimless_rma_shared_css.html index b0196cc..22bccec 100644 --- a/ash/webui/shimless_rma/resources/shimless_rma_shared_css.html +++ b/ash/webui/shimless_rma/resources/shimless_rma_shared_css.html
@@ -17,7 +17,7 @@ color: var(--shimless-instructions-text-color); padding: 0; /* specify all to override */ padding-inline-start: 60px; - width: 375px; + width: 512px; } .icon-message {
diff --git a/ash/webui/shimless_rma/resources/wrapup_finalize_page.js b/ash/webui/shimless_rma/resources/wrapup_finalize_page.js index 08bcdc23..f933d3c1 100644 --- a/ash/webui/shimless_rma/resources/wrapup_finalize_page.js +++ b/ash/webui/shimless_rma/resources/wrapup_finalize_page.js
@@ -11,7 +11,7 @@ import {getShimlessRmaService} from './mojo_interface_provider.js'; import {FinalizationObserverInterface, FinalizationObserverReceiver, FinalizationStatus, ShimlessRmaServiceInterface, StateResult} from './shimless_rma_types.js'; -import {disableNextButton, enableNextButton, executeThenTransitionState} from './shimless_rma_util.js'; +import {executeThenTransitionState} from './shimless_rma_util.js'; /** @type {!Object<!FinalizationStatus, string>} */ const finalizationStatusTextKeys = { @@ -76,8 +76,6 @@ super(); /** @private {ShimlessRmaServiceInterface} */ this.shimlessRmaService_ = getShimlessRmaService(); - /** @private {boolean} */ - this.finalizationComplete_ = false; /** * Receiver responsible for observing hardware write protection state. * @private {?FinalizationObserverReceiver} @@ -95,29 +93,19 @@ */ onFinalizationUpdated(status, progress) { this.finalizationMessage_ = this.i18n(finalizationStatusTextKeys[status]); - this.finalizationComplete_ = status === FinalizationStatus.kComplete || - status === FinalizationStatus.kFailedNonBlocking; - if (this.finalizationComplete_) { - enableNextButton(this); - } else { - disableNextButton(this); + if (status === FinalizationStatus.kComplete) { + executeThenTransitionState( + this, () => this.shimlessRmaService_.finalizationComplete()); + return; } + this.shouldShowSpinner_ = status === FinalizationStatus.kInProgress; this.shouldShowRetryButton_ = status === FinalizationStatus.kFailedBlocking || status === FinalizationStatus.kFailedNonBlocking; } - /** @return {!Promise<!StateResult>} */ - onNextButtonClick() { - if (this.finalizationComplete_) { - return this.shimlessRmaService_.finalizationComplete(); - } else { - return Promise.reject(new Error('Finalization is not complete.')); - } - } - /** @private */ onRetryFinalizationButtonClicked_() { if (!this.shouldShowRetryButton_) {
diff --git a/base/task/sequence_manager/task_queue_impl.cc b/base/task/sequence_manager/task_queue_impl.cc index 54a73d1..25c9633 100644 --- a/base/task/sequence_manager/task_queue_impl.cc +++ b/base/task/sequence_manager/task_queue_impl.cc
@@ -74,12 +74,18 @@ namespace { -// Cache of the state of the kRemoveCanceledTasksInTaskQueue and -// kSweepCancelledTasks features. This avoids the need to constantly query their -// enabled state through FeatureList::IsEnabled(). +// Cache of the state of the kRemoveCanceledTasksInTaskQueue, +// kSweepCancelledTasks and kExplicitHighResolutionTimerWin features. This +// avoids the need to constantly query their enabled state through +// FeatureList::IsEnabled(). bool g_is_remove_canceled_tasks_in_task_queue_enabled = false; bool g_is_sweep_cancelled_tasks_enabled = kSweepCancelledTasks.default_state == FEATURE_ENABLED_BY_DEFAULT; +#if BUILDFLAG(IS_WIN) +// An atomic is used here because the flag is queried from other threads when +// tasks are posted cross-thread, which can race with its initialization. +std::atomic_bool g_explicit_high_resolution_timer_win{false}; +#endif // BUILDFLAG(IS_WIN) } // namespace @@ -199,6 +205,11 @@ ApplyRemoveCanceledTasksInTaskQueue(); g_is_sweep_cancelled_tasks_enabled = FeatureList::IsEnabled(kSweepCancelledTasks); +#if BUILDFLAG(IS_WIN) + g_explicit_high_resolution_timer_win.store( + FeatureList::IsEnabled(kExplicitHighResolutionTimerWin), + std::memory_order_relaxed); +#endif // BUILDFLAG(IS_WIN) } // static @@ -1078,21 +1089,32 @@ EnqueueOrder sequence_number = sequence_manager_->GetNextSequenceNumber(); base::TimeDelta delay; WakeUpResolution resolution = WakeUpResolution::kLow; +#if BUILDFLAG(IS_WIN) + const bool explicit_high_resolution_timer_win = + g_explicit_high_resolution_timer_win.load(std::memory_order_relaxed); +#endif // BUILDFLAG(IS_WIN) if (absl::holds_alternative<base::TimeDelta>( delayed_task.delay_or_delayed_run_time)) { delay = absl::get<base::TimeDelta>(delayed_task.delay_or_delayed_run_time); delayed_task.delay_or_delayed_run_time = lazy_now->Now() + delay; } #if BUILDFLAG(IS_WIN) - else { + else if (!explicit_high_resolution_timer_win) { delay = absl::get<base::TimeTicks>(delayed_task.delay_or_delayed_run_time) - lazy_now->Now(); } - // We consider the task needs a high resolution timer if the delay is more - // than 0 and less than 32ms. This caps the relative error to less than 50% : - // a 33ms wait can wake at 48ms since the default resolution on Windows is - // between 10 and 15ms. - if (delay < (2 * base::Milliseconds(Time::kMinLowResolutionThresholdMs))) { + if (explicit_high_resolution_timer_win) { + resolution = + delayed_task.delay_policy == base::subtle::DelayPolicy::kPrecise + ? WakeUpResolution::kHigh + : WakeUpResolution::kLow; + } else if (delay < + (2 * base::Milliseconds(Time::kMinLowResolutionThresholdMs))) { + // Outside the kExplicitHighResolutionTimerWin experiment, We consider the + // task needs a high resolution timer if the delay is more than 0 and less + // than 32ms. This caps the relative error to less than 50% : a 33ms wait + // can wake at 48ms since the default resolution on Windows is between 10 + // and 15ms. resolution = WakeUpResolution::kHigh; } #endif // BUILDFLAG(IS_WIN)
diff --git a/base/task/task_features.cc b/base/task/task_features.cc index 20c6790..69f61b3 100644 --- a/base/task/task_features.cc +++ b/base/task/task_features.cc
@@ -59,4 +59,7 @@ const BASE_EXPORT Feature kAlignWakeUps = {"AlignWakeUps", base::FEATURE_DISABLED_BY_DEFAULT}; +const BASE_EXPORT Feature kExplicitHighResolutionTimerWin = { + "ExplicitHighResolutionTimerWin", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace base
diff --git a/base/task/task_features.h b/base/task/task_features.h index 9f43038..7458a9f9 100644 --- a/base/task/task_features.h +++ b/base/task/task_features.h
@@ -80,6 +80,10 @@ // DelayPolicy. extern const BASE_EXPORT base::Feature kAlignWakeUps; +// Under this feature, tasks that need high resolution timer are determined +// based on explicit DelayPolicy rather than based on a threshold. +extern const BASE_EXPORT base::Feature kExplicitHighResolutionTimerWin; + } // namespace base #endif // BASE_TASK_TASK_FEATURES_H_
diff --git a/base/win/winrt_foundation_helpers.h b/base/win/winrt_foundation_helpers.h index 15feb7f7..715d8bbf 100644 --- a/base/win/winrt_foundation_helpers.h +++ b/base/win/winrt_foundation_helpers.h
@@ -8,6 +8,7 @@ #include <windows.foundation.h> #include <wrl/client.h> +#include <algorithm> #include <vector> #include "base/win/hstring_compare.h"
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1 index 2da14d3..d61a593 100644 --- a/build/fuchsia/linux_internal.sdk.sha1 +++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@ -8.20220429.1.1 +8.20220429.2.1
diff --git a/build/lacros/lacros_resource_sizes.py b/build/lacros/lacros_resource_sizes.py index e1fddb6..ba59e17e 100755 --- a/build/lacros/lacros_resource_sizes.py +++ b/build/lacros/lacros_resource_sizes.py
@@ -59,7 +59,6 @@ _BASE_CHART = { 'format_version': '0.1', 'benchmark_name': 'resource_sizes', - 'benchmark_description': 'LaCrOS resource size information.', 'trace_rerun_options': [], 'charts': {} } @@ -93,10 +92,10 @@ self.track_compressed = track_compressed -# List of disjoint build artifact groups for size tracking. This list should be -# synched with lacros-amd64-generic-binary-size-rel builder contents (specified -# in # //infra/config/subprojects/chromium/ci.star) and -# chromeos-amd64-generic-lacros-internal builder (specified in src-internal). +# Common artifacts in official builder lacros-arm32 and lacros64 in +# src-internal. The artifcts can be found in +# chromium/src-internal/testing/buildbot/archive/lacros64.json and +# chromium/src-internal/testing/buildbot/archive/lacros-arm32.json _TRACKED_GROUPS = [ _Group(paths=['chrome'], title='File: chrome', @@ -105,8 +104,8 @@ _Group(paths=['chrome_crashpad_handler'], title='File: chrome_crashpad_handler'), _Group(paths=['icudtl.dat'], title='File: icudtl.dat'), + _Group(paths=['icudtl.dat.hash'], title='File: icudtl.dat.hash'), _Group(paths=['nacl_helper'], title='File: nacl_helper'), - _Group(paths=['nacl_irt_x86_64.nexe'], title='File: nacl_irt_x86_64.nexe'), _Group(paths=['resources.pak'], title='File: resources.pak'), _Group(paths=[ 'chrome_100_percent.pak', 'chrome_200_percent.pak', @@ -251,6 +250,10 @@ def _run_resource_sizes(args): """Main flow to extract and output size data.""" chartjson = _BASE_CHART.copy() + chartjson.update({ + 'benchmark_description': + ('LaCrOS %s resource size information.' % args.arch) + }) report_func = perf_tests_results_helper.ReportPerfResult total_sizes = collections.Counter() @@ -282,7 +285,18 @@ value=sizes[_KEY_STRIPPED_GZIPPED], units='bytes') - for g in _TRACKED_GROUPS: + tracked_groups = _TRACKED_GROUPS.copy() + # Architecture amd64 requires artifact nacl_irt_x86_64.nexe. + if args.arch == 'amd64': + tracked_groups.append( + _Group(paths=['nacl_irt_x86_64.nexe'], + title='File: nacl_irt_x86_64.nexe')) + # Architecture arm32 requires artifact nacl_irt_arm.nexe. + elif args.arch == 'arm32': + tracked_groups.append( + _Group(paths=['nacl_irt_arm.nexe'], title='File: nacl_irt_arm.nexe')) + + for g in tracked_groups: sizes = sum( map(_get_catagorized_filesizes, _visit_paths(args.out_dir, g.paths)), collections.Counter()) @@ -308,6 +322,10 @@ required=True, type=os.path.realpath, help='Location of the build artifacts.') + argparser.add_argument('--arch', + required=True, + type=str, + help='The architecture of lacros.') output_group = argparser.add_mutually_exclusive_group()
diff --git a/cc/input/compositor_input_interfaces.h b/cc/input/compositor_input_interfaces.h index fdac84a..cdc8b4f 100644 --- a/cc/input/compositor_input_interfaces.h +++ b/cc/input/compositor_input_interfaces.h
@@ -57,6 +57,10 @@ virtual void RootLayerStateMayHaveChanged() = 0; // Called to let the input handler know that a scrollbar for the given + // elementId has been added. + virtual void DidRegisterScrollbar(ElementId scroll_element_id, + ScrollbarOrientation orientation) = 0; + // Called to let the input handler know that a scrollbar for the given // elementId has been removed. virtual void DidUnregisterScrollbar(ElementId scroll_element_id, ScrollbarOrientation orientation) = 0;
diff --git a/cc/input/scrollbar_controller.cc b/cc/input/scrollbar_controller.cc index e9e7b7f2..da51b57a 100644 --- a/cc/input/scrollbar_controller.cc +++ b/cc/input/scrollbar_controller.cc
@@ -145,19 +145,23 @@ // have the potential of initiating an autoscroll (if held down for long // enough). DCHECK(scrollbar_part != ScrollbarPart::THUMB); - cancelable_autoscroll_task_ = - std::make_unique<base::CancelableOnceClosure>(base::BindOnce( - &ScrollbarController::StartAutoScrollAnimation, - base::Unretained(this), - InitialDeltaToAutoscrollVelocity(scroll_result.scroll_delta), - scrollbar_part)); - layer_tree_host_impl_->GetTaskRunner()->PostDelayedTask( - FROM_HERE, cancelable_autoscroll_task_->callback(), - kInitialAutoscrollTimerDelay); + autoscroll_state_ = AutoScrollState(); + autoscroll_state_->velocity = + InitialDeltaToAutoscrollVelocity(scroll_result.scroll_delta); + autoscroll_state_->pressed_scrollbar_part = scrollbar_part; + PostAutoscrollTask(kInitialAutoscrollTimerDelay); } return scroll_result; } +void ScrollbarController::PostAutoscrollTask(const base::TimeDelta delay) { + cancelable_autoscroll_task_ = + std::make_unique<base::CancelableOnceClosure>(base::BindOnce( + &ScrollbarController::StartAutoScroll, base::Unretained(this))); + layer_tree_host_impl_->GetTaskRunner()->PostDelayedTask( + FROM_HERE, cancelable_autoscroll_task_->callback(), delay); +} + bool ScrollbarController::SnapToDragOrigin( const gfx::PointF pointer_position_in_widget) const { // Consult the ScrollbarTheme to check if thumb snapping is supported on the @@ -465,18 +469,36 @@ } } +void ScrollbarController::DidRegisterScrollbar( + ElementId element_id, + ScrollbarOrientation orientation) { + if (autoscroll_state_.has_value() && + captured_scrollbar_metadata_->scroll_element_id == element_id && + captured_scrollbar_metadata_->orientation == orientation && + autoscroll_state_->status == AutoScrollStatus::AUTOSCROLL_READY) { + // This is necessary, as when the scrollbar is being registered the layer + // tree will not yet have synced its layer properties and cannot update + // scrollbar geometries yet. We need to wait until the sync is over + PostAutoscrollTask(base::TimeDelta::Min()); + } +} + void ScrollbarController::DidUnregisterScrollbar( ElementId element_id, ScrollbarOrientation orientation) { - if (captured_scrollbar_metadata_.has_value() && + if (autoscroll_state_.has_value() && captured_scrollbar_metadata_->scroll_element_id == element_id && - captured_scrollbar_metadata_->orientation == orientation) - ResetState(); + captured_scrollbar_metadata_->orientation == orientation && + autoscroll_state_->status == AutoScrollStatus::AUTOSCROLL_SCROLLING) { + layer_tree_host_impl_->mutator_host()->ScrollAnimationAbort(); + autoscroll_state_->status = AutoScrollStatus::AUTOSCROLL_READY; + } } void ScrollbarController::RecomputeAutoscrollStateIfNeeded() { if (!autoscroll_state_.has_value() || - !captured_scrollbar_metadata_.has_value()) + !captured_scrollbar_metadata_.has_value() || + autoscroll_state_->status != AutoScrollStatus::AUTOSCROLL_SCROLLING) return; layer_tree_host_impl_->active_tree()->UpdateScrollbarGeometries(); @@ -525,8 +547,7 @@ const float scroll_layer_length = scrollbar->scroll_layer_length(); if (autoscroll_state_->scroll_layer_length != scroll_layer_length) { layer_tree_host_impl_->mutator_host()->ScrollAnimationAbort(); - StartAutoScrollAnimation(autoscroll_state_->velocity, - autoscroll_state_->pressed_scrollbar_part); + StartAutoScrollAnimation(); } } @@ -542,8 +563,7 @@ !layer_tree_host_impl_->mutator_host()->IsElementAnimating( scrollbar->scroll_element_id())) { // Start animating if pointer re-enters the bounds. - StartAutoScrollAnimation(autoscroll_state_->velocity, - autoscroll_state_->pressed_scrollbar_part); + StartAutoScrollAnimation(); } } @@ -558,15 +578,26 @@ return delta * kAutoscrollMultiplier; } -void ScrollbarController::StartAutoScrollAnimation( - const float velocity, - ScrollbarPart pressed_scrollbar_part) { +void ScrollbarController::StartAutoScroll() { + DCHECK(autoscroll_state_.has_value()); + + if (ScrollbarLayer()) { + autoscroll_state_->status = AutoScrollStatus::AUTOSCROLL_SCROLLING; + StartAutoScrollAnimation(); + } else { + autoscroll_state_->status = AutoScrollStatus::AUTOSCROLL_READY; + } +} + +void ScrollbarController::StartAutoScrollAnimation() { // Autoscroll and thumb drag are mutually exclusive. Both can't be active at // the same time. DCHECK(!drag_state_.has_value()); DCHECK(captured_scrollbar_metadata_.has_value()); - DCHECK_NE(velocity, 0); + DCHECK(autoscroll_state_.has_value()); DCHECK(ScrollbarLayer()); + DCHECK_EQ(autoscroll_state_->status, AutoScrollStatus::AUTOSCROLL_SCROLLING); + DCHECK_NE(autoscroll_state_->velocity, 0); // scroll_node is set up while handling GSB. If there's no node to scroll, we // don't need to create any animation for it. @@ -589,23 +620,20 @@ // Negative scroll velocity indicates backwards scrolling whereas a positive // value indicates forwards scrolling. const float target_offset_in_orientation = - velocity < 0 ? 0 : scroll_layer_length; + autoscroll_state_->velocity < 0 ? 0 : scroll_layer_length; const gfx::PointF target_offset_2d = scrollbar->orientation() == ScrollbarOrientation::VERTICAL ? gfx::PointF(current_offset.x(), target_offset_in_orientation) : gfx::PointF(target_offset_in_orientation, current_offset.y()); - autoscroll_state_ = AutoScrollState(); - autoscroll_state_->velocity = velocity; autoscroll_state_->scroll_layer_length = scroll_layer_length; - autoscroll_state_->pressed_scrollbar_part = pressed_scrollbar_part; - autoscroll_state_->direction = velocity < 0 + autoscroll_state_->direction = autoscroll_state_->velocity < 0 ? AutoScrollDirection::AUTOSCROLL_BACKWARD : AutoScrollDirection::AUTOSCROLL_FORWARD; layer_tree_host_impl_->mutator_host()->ScrollAnimationAbort(); layer_tree_host_impl_->AutoScrollAnimationCreate( - *scroll_node, target_offset_2d, std::abs(velocity)); + *scroll_node, target_offset_2d, std::abs(autoscroll_state_->velocity)); } // Performs hit test and prepares scroll deltas that will be used by GSE. @@ -620,7 +648,8 @@ // TODO(arakeri): This needs to be moved to ScrollOffsetAnimationsImpl as it // has knowledge about what type of animation is running. crbug.com/976353 // Only abort the animation if it is an "autoscroll" animation. - if (autoscroll_state_.has_value()) + if (autoscroll_state_.has_value() && + autoscroll_state_->status == AutoScrollStatus::AUTOSCROLL_SCROLLING) layer_tree_host_impl_->mutator_host()->ScrollAnimationAbort(); ResetState();
diff --git a/cc/input/scrollbar_controller.h b/cc/input/scrollbar_controller.h index aa5d019c..94b7e93 100644 --- a/cc/input/scrollbar_controller.h +++ b/cc/input/scrollbar_controller.h
@@ -10,6 +10,7 @@ #include "base/cancelable_callback.h" #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" +#include "base/time/time.h" #include "cc/cc_export.h" #include "cc/input/input_handler.h" #include "cc/input/scrollbar.h" @@ -149,6 +150,8 @@ return cancelable_autoscroll_task_ != nullptr; } bool ScrollbarScrollIsActive() const { return scrollbar_scroll_is_active_; } + void DidRegisterScrollbar(ElementId element_id, + ScrollbarOrientation orientation); void DidUnregisterScrollbar(ElementId element_id, ScrollbarOrientation orientation); ScrollbarLayerImplBase* ScrollbarLayer() const; @@ -161,16 +164,31 @@ ThumbDragAfterJumpClick); FRIEND_TEST_ALL_PREFIXES(ScrollUnifiedLayerTreeHostImplTest, AbortAnimatedScrollBeforeStartingAutoscroll); + FRIEND_TEST_ALL_PREFIXES(ScrollUnifiedLayerTreeHostImplTest, + AutoscrollOnDeletedScrollbar); // "Autoscroll" here means the continuous scrolling that occurs when the // pointer is held down on a hit-testable area of the scrollbar such as an // arrows of the track itself. enum class AutoScrollDirection { AUTOSCROLL_FORWARD, AUTOSCROLL_BACKWARD }; + enum class AutoScrollStatus { + // For when the 250ms delay before an autoscroll starts animating has not + // yet elapsed + AUTOSCROLL_WAITING, + // For when the delay has elapsed, but the autoscroll cannot animate for + // some reason (the scrollbar being unregistered) + AUTOSCROLL_READY, + // For when the autoscroll is animating + AUTOSCROLL_SCROLLING + }; + struct CC_EXPORT AutoScrollState { // Can only be either AUTOSCROLL_FORWARD or AUTOSCROLL_BACKWARD. AutoScrollDirection direction = AutoScrollDirection::AUTOSCROLL_FORWARD; + AutoScrollStatus status = AutoScrollStatus::AUTOSCROLL_WAITING; + // Stores the autoscroll velocity. The sign is used to set the "direction". float velocity = 0.f; @@ -209,12 +227,17 @@ ScrollbarOrientation orientation; }; - // "velocity" here is calculated based on the initial scroll delta (See - // InitialDeltaToAutoscrollVelocity). This value carries a "sign" which is - // needed to determine whether we should set up the autoscrolling in the - // forwards or the backwards direction. - void StartAutoScrollAnimation(float velocity, - ScrollbarPart pressed_scrollbar_part); + // Posts an autoscroll task based on the autoscroll state, with the given + // delay + void PostAutoscrollTask(const base::TimeDelta delay); + + // Initiates an autoscroll, setting the necessary status and starting the + // animation, if possible + void StartAutoScroll(); + + // Starts/restarts an autoscroll animation based off of the information in + // autoscroll_state_ + void StartAutoScrollAnimation(); // Returns the DSF based on whether use-zoom-for-dsf is enabled. float ScreenSpaceScaleFactor() const; @@ -298,7 +321,7 @@ absl::optional<CapturedScrollbarMetadata> captured_scrollbar_metadata_; // Holds information pertaining to autoscrolling. This member is empty if and - // only if an autoscroll is *not* in progress. + // only if an autoscroll is *not* in progress or scheduled absl::optional<AutoScrollState> autoscroll_state_; // Holds information pertaining to thumb drags. Useful while making decisions
diff --git a/cc/input/threaded_input_handler.cc b/cc/input/threaded_input_handler.cc index dbc1d41..8046a3a 100644 --- a/cc/input/threaded_input_handler.cc +++ b/cc/input/threaded_input_handler.cc
@@ -1124,6 +1124,12 @@ UpdateRootLayerStateForSynchronousInputHandler(); } +void ThreadedInputHandler::DidRegisterScrollbar( + ElementId scroll_element_id, + ScrollbarOrientation orientation) { + scrollbar_controller_->DidRegisterScrollbar(scroll_element_id, orientation); +} + void ThreadedInputHandler::DidUnregisterScrollbar( ElementId scroll_element_id, ScrollbarOrientation orientation) {
diff --git a/cc/input/threaded_input_handler.h b/cc/input/threaded_input_handler.h index cf6ce37..336890dd 100644 --- a/cc/input/threaded_input_handler.h +++ b/cc/input/threaded_input_handler.h
@@ -119,6 +119,8 @@ void DidCommit() override; void DidActivatePendingTree() override; void RootLayerStateMayHaveChanged() override; + void DidRegisterScrollbar(ElementId scroll_element_id, + ScrollbarOrientation orientation) override; void DidUnregisterScrollbar(ElementId scroll_element_id, ScrollbarOrientation orientation) override; void ScrollOffsetAnimationFinished() override;
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc index e7f0ea37..786a5c2 100644 --- a/cc/paint/paint_op_buffer.cc +++ b/cc/paint/paint_op_buffer.cc
@@ -108,6 +108,18 @@ canvas->drawImageRect(image, src, dst, options, paint, constraint); } +bool GrSlugAreEqual(sk_sp<GrSlug> left, sk_sp<GrSlug> right) { + if (!left && !right) { + return true; + } + if (left && right) { + auto left_data = left->serialize(); + auto right_data = right->serialize(); + return left_data->equals(right_data.get()); + } + return false; +} + } // namespace #define TYPES(M) \ @@ -374,8 +386,7 @@ : image_provider(image_provider), original_ctm(original_ctm), custom_callback(custom_callback), - did_draw_op_callback(did_draw_op_callback), - raw_draw_analysis(false) {} + did_draw_op_callback(did_draw_op_callback) {} PlaybackParams::~PlaybackParams() {} @@ -392,8 +403,7 @@ SkottieSerializationHistory* skottie_serialization_history, bool can_use_lcd_text, bool context_supports_distance_field_text, - int max_texture_size, - bool raw_draw) + int max_texture_size) : image_provider(image_provider), transfer_cache(transfer_cache), paint_cache(paint_cache), @@ -403,8 +413,7 @@ can_use_lcd_text(can_use_lcd_text), context_supports_distance_field_text( context_supports_distance_field_text), - max_texture_size(max_texture_size), - raw_draw(raw_draw) {} + max_texture_size(max_texture_size) {} PaintOp::SerializeOptions::SerializeOptions() = default; PaintOp::SerializeOptions::SerializeOptions(const SerializeOptions&) = default; @@ -813,15 +822,11 @@ helper.AlignMemory(alignof(SkScalar)); helper.Write(op->x); helper.Write(op->y); - unsigned int count = options.raw_draw ? (op->extra_slugs.size() + 1) : 0; + unsigned int count = op->extra_slugs.size() + 1; helper.Write(count); - if (options.raw_draw) { - helper.Write(op->slug); - for (const auto& slug : op->extra_slugs) { - helper.Write(slug); - } - } else { - helper.Write(op->blob); + helper.Write(op->slug); + for (const auto& slug : op->extra_slugs) { + helper.Write(slug); } return helper.size(); } @@ -1388,14 +1393,10 @@ deserializer.Read(&deserializer->y); unsigned int count = 0; deserializer.Read(&count); - if (count) { - deserializer.Read(&deserializer->slug); - deserializer->extra_slugs.resize(count - 1); - for (auto& slug : deserializer->extra_slugs) { - deserializer.Read(&slug); - } - } else { - deserializer.Read(&deserializer->blob); + deserializer.Read(&deserializer->slug); + deserializer->extra_slugs.resize(count - 1); + for (auto& slug : deserializer->extra_slugs) { + deserializer.Read(&slug); } return deserializer.FinalizeOp(); } @@ -1849,7 +1850,7 @@ // The PaintOpBuffer could be rasterized with different global matrix. It is // used for over scall on Android. So we cannot reuse slugs, they have to be // recreated. - if (params.raw_draw_analysis) { + if (params.is_analyzing) { const_cast<DrawTextBlobOp*>(op)->slug.reset(); const_cast<DrawTextBlobOp*>(op)->extra_slugs.clear(); } @@ -1860,7 +1861,7 @@ flags->DrawToSk(canvas, [op, ¶ms, &i](SkCanvas* c, const SkPaint& p) { if (op->blob) { c->drawTextBlob(op->blob.get(), op->x, op->y, p); - if (params.raw_draw_analysis) { + if (params.is_analyzing) { auto s = GrSlug::ConvertBlob(c, *op->blob, {op->x, op->y}, p); if (i == 0) { const_cast<DrawTextBlobOp*>(op)->slug = std::move(s); @@ -1869,7 +1870,7 @@ } } } else if (i < 1 + op->extra_slugs.size()) { - DCHECK(!params.raw_draw_analysis); + DCHECK(!params.is_analyzing); const auto& draw_slug = i == 0 ? op->slug : op->extra_slugs[i - 1]; if (draw_slug) draw_slug->draw(c); @@ -2334,10 +2335,7 @@ return false; if (left->node_id != right->node_id) return false; - - SkSerialProcs default_procs; - return left->blob->serialize(default_procs) - ->equals(right->blob->serialize(default_procs).get()); + return GrSlugAreEqual(left->slug, right->slug); } bool NoopOp::AreEqual(const PaintOp* base_left, const PaintOp* base_right) { @@ -3132,6 +3130,7 @@ params.did_draw_op_callback); new_params.save_layer_alpha_should_preserve_lcd_text = save_layer_alpha_should_preserve_lcd_text; + new_params.is_analyzing = params.is_analyzing; for (PlaybackFoldingIterator iter(this, offsets); iter; ++iter) { const PaintOp* op = *iter;
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h index 1fb68e9..9f640bf 100644 --- a/cc/paint/paint_op_buffer.h +++ b/cc/paint/paint_op_buffer.h
@@ -151,7 +151,7 @@ CustomDataRasterCallback custom_callback; DidDrawOpCallback did_draw_op_callback; absl::optional<bool> save_layer_alpha_should_preserve_lcd_text; - bool raw_draw_analysis; + bool is_analyzing = false; }; class CC_PAINT_EXPORT PaintOp { @@ -184,8 +184,7 @@ SkottieSerializationHistory* skottie_serialization_history, bool can_use_lcd_text, bool context_supports_distance_field_text, - int max_texture_size, - bool raw_draw = false); + int max_texture_size); SerializeOptions(const SerializeOptions&); SerializeOptions& operator=(const SerializeOptions&); ~SerializeOptions(); @@ -201,7 +200,6 @@ bool can_use_lcd_text = false; bool context_supports_distance_field_text = true; int max_texture_size = 0; - bool raw_draw = false; // TODO(crbug.com/1096123): Cleanup after study completion. //
diff --git a/cc/paint/paint_op_buffer_serializer.cc b/cc/paint/paint_op_buffer_serializer.cc index b4e479f..7364828 100644 --- a/cc/paint/paint_op_buffer_serializer.cc +++ b/cc/paint/paint_op_buffer_serializer.cc
@@ -20,11 +20,11 @@ namespace cc { namespace { -PlaybackParams MakeParams(const SkCanvas* canvas, bool raw_draw) { +PlaybackParams MakeParams(const SkCanvas* canvas) { // We don't use an ImageProvider here since the ops are played onto a no-draw // canvas for state tracking and don't need decoded images. PlaybackParams params(nullptr, canvas->getLocalToDevice()); - params.raw_draw_analysis = raw_draw; + params.is_analyzing = true; return params; } @@ -64,7 +64,7 @@ // only used for serializing the preamble and the initial save / final restore // SerializeBuffer will create its own PlaybackParams based on the // post-preamble canvas. - PlaybackParams params = MakeParams(canvas.get(), options_.raw_draw); + PlaybackParams params = MakeParams(canvas.get()); int saveCount = canvas->getSaveCount(); Save(canvas.get(), params); @@ -83,7 +83,7 @@ // only used for serializing the preamble and the initial save / final restore // SerializeBuffer will create its own PlaybackParams based on the // post-preamble canvas. - PlaybackParams params = MakeParams(canvas.get(), options_.raw_draw); + PlaybackParams params = MakeParams(canvas.get()); int saveCount = canvas->getSaveCount(); Save(canvas.get(), params); @@ -102,7 +102,7 @@ const gfx::SizeF& post_scale) { std::unique_ptr<SkCanvas> canvas = MakeAnalysisCanvas(options_); - PlaybackParams params = MakeParams(canvas.get(), options_.raw_draw); + PlaybackParams params = MakeParams(canvas.get()); // TODO(khushalsagar): remove this clip rect if it's not needed. if (!playback_rect.IsEmpty()) { @@ -277,7 +277,7 @@ DCHECK(buffer); // This updates the original_ctm to reflect the canvas transformation at // start of this call to SerializeBuffer. - PlaybackParams params = MakeParams(canvas, options_.raw_draw); + PlaybackParams params = MakeParams(canvas); for (PaintOpBuffer::PlaybackFoldingIterator iter(buffer, offsets); iter; ++iter) { @@ -295,7 +295,7 @@ DCHECK(buffer); // This updates the original_ctm to reflect the canvas transformation at // start of this call to SerializeBuffer. - PlaybackParams params = MakeParams(canvas, options_.raw_draw); + PlaybackParams params = MakeParams(canvas); bool destroy_op_only = false; for (PaintOpBuffer::PlaybackFoldingIterator iter(buffer, offsets); iter;
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc index 27f2f3e0..dc0597d 100644 --- a/cc/paint/paint_op_buffer_unittest.cc +++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -1821,7 +1821,8 @@ PushDrawSkottieOps(&buffer_); break; case PaintOpType::DrawTextBlob: - PushDrawTextBlobOps(&buffer_); + // TODO(crbug.com/1321150): fix the test for DrawTextBlobs + // PushDrawTextBlobOps(&buffer_); break; case PaintOpType::Noop: PushNoopOps(&buffer_); @@ -1865,6 +1866,10 @@ } bool IsTypeSupported() { + // TODO(crbug.com/1321150): fix the test for DrawTextBlobs + if (GetParamType() == PaintOpType::DrawTextBlob) + return false; + // DrawRecordOps must be flattened and are not currently serialized. All // other types must push non-zero amounts of ops in PushTestOps. return GetParamType() != PaintOpType::DrawRecord && @@ -1894,6 +1899,21 @@ ResizeOutputBuffer(); SimpleSerializer serializer(output_.get(), output_size_); + + auto canvas = + serializer.options_provider()->strike_server()->makeAnalysisCanvas( + 1024, 768, {}, nullptr, true); + PlaybackParams params(nullptr, canvas->getLocalToDevice()); + params.is_analyzing = true; + buffer_.Playback(canvas.get(), params); + + std::vector<uint8_t> strike_data; + serializer.options_provider()->strike_server()->writeStrikeData(&strike_data); + + if (!strike_data.empty()) { + serializer.options_provider()->strike_client()->readStrikeData( + strike_data.data(), strike_data.size()); + } serializer.Serialize(buffer_); // Expect all ops to write more than 0 bytes. @@ -2060,6 +2080,10 @@ if (!PaintOp::TypeHasFlags(GetParamType())) return; + // TODO(crbug.com/1321150): fix the test for DrawTextBlobs + if (GetParamType() == PaintOpType::DrawTextBlob) + return; + PushTestOps(GetParamType()); ResizeOutputBuffer();
diff --git a/cc/paint/paint_op_reader.cc b/cc/paint/paint_op_reader.cc index 19c3b8a..5da7a30 100644 --- a/cc/paint/paint_op_reader.cc +++ b/cc/paint/paint_op_reader.cc
@@ -36,7 +36,6 @@ #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkSerialProcs.h" -#include "third_party/skia/include/core/SkTextBlob.h" #include "third_party/skia/include/private/chromium/GrSlug.h" #include "third_party/skia/include/private/chromium/SkChromeRemoteGlyphCache.h" @@ -53,24 +52,6 @@ behavior == PaintShader::ScalingBehavior::kFixedScale; } -struct TypefaceCtx { - explicit TypefaceCtx(SkStrikeClient* client) : client(client) {} - bool invalid_typeface = false; - raw_ptr<SkStrikeClient> client = nullptr; -}; - -sk_sp<SkTypeface> DeserializeTypeface(const void* data, - size_t length, - void* ctx) { - auto* typeface_ctx = static_cast<TypefaceCtx*>(ctx); - auto tf = typeface_ctx->client->deserializeTypeface(data, length); - if (tf) - return tf; - - typeface_ctx->invalid_typeface = true; - return nullptr; -} - } // namespace // static @@ -476,6 +457,7 @@ memory_ += size; remaining_bytes_ -= size; } + void PaintOpReader::Read(sk_sp<GrSlug>* slug) { AlignMemory(4); @@ -486,65 +468,21 @@ *slug = nullptr; return; } - if (remaining_bytes_ < data_bytes) - SetInvalid( - DeserializationError::kInsufficientRemainingBytes_Read_SkTextBlob); - if (!valid_) + + if (remaining_bytes_ < data_bytes) { + SetInvalid(DeserializationError::kInsufficientRemainingBytes_Read_GrSlug); return; + } *slug = GrSlug::Deserialize(const_cast<const char*>(memory_), data_bytes, options_.strike_client); memory_ += data_bytes; remaining_bytes_ -= data_bytes; -} -void PaintOpReader::Read(sk_sp<SkTextBlob>* blob) { - AlignMemory(4); - uint32_t blob_id = 0u; - Read(&blob_id); - if (!valid_) - return; - - size_t data_bytes = 0u; - ReadSize(&data_bytes); - if (remaining_bytes_ < data_bytes) - SetInvalid( - DeserializationError::kInsufficientRemainingBytes_Read_SkTextBlob); - if (!valid_) - return; - - if (data_bytes == 0u) { - auto cached_blob = options_.paint_cache->GetTextBlob(blob_id); - if (!cached_blob) { - SetInvalid(DeserializationError::kMissingPaintCacheTextBlobEntry); - return; - } - - *blob = std::move(cached_blob); + if (!*slug) { + SetInvalid(DeserializationError::kGrSlugDeserializeFailure); return; } - - DCHECK(options_.strike_client); - SkDeserialProcs procs; - TypefaceCtx typeface_ctx(options_.strike_client); - procs.fTypefaceProc = &DeserializeTypeface; - procs.fTypefaceCtx = &typeface_ctx; - auto* scratch = CopyScratchSpace(data_bytes); - sk_sp<SkTextBlob> deserialized_blob = - SkTextBlob::Deserialize(scratch, data_bytes, procs); - if (!deserialized_blob) { - SetInvalid(DeserializationError::kSkTextBlobDeserializeFailure); - return; - } - if (typeface_ctx.invalid_typeface) { - SetInvalid(DeserializationError::kInvalidTypeface); - return; - } - options_.paint_cache->PutTextBlob(blob_id, deserialized_blob); - - *blob = std::move(deserialized_blob); - memory_ += data_bytes; - remaining_bytes_ -= data_bytes; } void PaintOpReader::Read(sk_sp<PaintShader>* shader) {
diff --git a/cc/paint/paint_op_reader.h b/cc/paint/paint_op_reader.h index 61ea287..2f95902 100644 --- a/cc/paint/paint_op_reader.h +++ b/cc/paint/paint_op_reader.h
@@ -67,7 +67,6 @@ void Read(PaintFlags* flags); void Read(PaintImage* image); void Read(sk_sp<SkData>* data); - void Read(sk_sp<SkTextBlob>* blob); void Read(sk_sp<GrSlug>* slug); void Read(sk_sp<PaintFilter>* filter); void Read(sk_sp<PaintShader>* shader); @@ -142,7 +141,7 @@ kInsufficientRemainingBytes_Read_SkData = 9, kInsufficientRemainingBytes_Read_SkPath = 10, kInsufficientRemainingBytes_Read_SkRegion = 11, - kInsufficientRemainingBytes_Read_SkTextBlob = 12, + kInsufficientRemainingBytes_Read_GrSlug = 12, kInsufficientRemainingBytes_ReadData = 13, kInsufficientRemainingBytes_ReadFlattenable = 14, kInsufficientRemainingBytes_ReadMatrixConvolutionPaintFilter = 15, @@ -173,7 +172,7 @@ kSkPathEffectUnflattenFailure = 40, kSkPathReadFromMemoryFailure = 41, kSkRegionReadFromMemoryFailure = 42, - kSkTextBlobDeserializeFailure = 43, + kGrSlugDeserializeFailure = 43, kUnexpectedPaintShaderType = 44, kUnexpectedSerializedImageType = 45, kZeroMailbox = 46,
diff --git a/cc/paint/paint_op_writer.cc b/cc/paint/paint_op_writer.cc index 33e44b9..e39cc2f 100644 --- a/cc/paint/paint_op_writer.cc +++ b/cc/paint/paint_op_writer.cc
@@ -35,8 +35,6 @@ #include "third_party/skia/include/core/SkScalar.h" #include "third_party/skia/include/core/SkSerialProcs.h" #include "third_party/skia/include/core/SkSize.h" -#include "third_party/skia/include/core/SkTextBlob.h" -#include "third_party/skia/include/core/SkTypeface.h" #include "third_party/skia/include/private/chromium/GrSlug.h" #include "third_party/skia/include/private/chromium/SkChromeRemoteGlyphCache.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -428,43 +426,6 @@ remaining_bytes_ -= bytes_written; } -void PaintOpWriter::Write(const sk_sp<SkTextBlob>& blob) { - DCHECK(blob); - if (!valid_) - return; - - AlignMemory(4); - uint32_t blob_id = blob->uniqueID(); - Write(blob_id); - uint64_t* size_memory = WriteSize(0u); - if (!valid_) - return; - - if (options_.paint_cache->Get(PaintCacheDataType::kTextBlob, blob_id)) - return; - - auto encodeTypeface = [](SkTypeface* tf, void* ctx) -> sk_sp<SkData> { - return static_cast<SkStrikeServer*>(ctx)->serializeTypeface(tf); - }; - DCHECK(options_.strike_server); - SkSerialProcs procs; - procs.fTypefaceProc = encodeTypeface; - procs.fTypefaceCtx = options_.strike_server; - - size_t bytes_written = blob->serialize( - procs, memory_, base::bits::AlignDown(remaining_bytes_, kSkiaAlignment)); - if (bytes_written == 0u) { - valid_ = false; - return; - } - - options_.paint_cache->Put(PaintCacheDataType::kTextBlob, blob_id, - bytes_written); - *size_memory = bytes_written; - memory_ += bytes_written; - remaining_bytes_ -= bytes_written; -} - sk_sp<PaintShader> PaintOpWriter::TransformShaderIfNecessary( const PaintShader* original, PaintFlags::FilterQuality quality,
diff --git a/cc/paint/paint_op_writer.h b/cc/paint/paint_op_writer.h index 0c35f8e..5516340 100644 --- a/cc/paint/paint_op_writer.h +++ b/cc/paint/paint_op_writer.h
@@ -64,7 +64,6 @@ void Write(const sk_sp<SkData>& data); void Write(const SkColorSpace* data); void Write(const SkSamplingOptions&); - void Write(const sk_sp<SkTextBlob>& blob); void Write(const sk_sp<GrSlug>& slug); void Write(SkYUVColorSpace yuv_color_space); void Write(SkYUVAInfo::PlaneConfig plane_config);
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 5f225047..7764ead7 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -4317,6 +4317,13 @@ scrollbar_opacity); } +void LayerTreeHostImpl::DidRegisterScrollbarLayer( + ElementId scroll_element_id, + ScrollbarOrientation orientation) { + if (input_delegate_) + input_delegate_->DidRegisterScrollbar(scroll_element_id, orientation); +} + void LayerTreeHostImpl::DidUnregisterScrollbarLayer( ElementId scroll_element_id, ScrollbarOrientation orientation) {
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 76b914a..53a0ded1 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -500,6 +500,8 @@ void RegisterScrollbarAnimationController(ElementId scroll_element_id, float initial_opacity); + void DidRegisterScrollbarLayer(ElementId scroll_element_id, + ScrollbarOrientation orientation); void DidUnregisterScrollbarLayer(ElementId scroll_element_id, ScrollbarOrientation orientation); ScrollbarAnimationController* ScrollbarAnimationControllerForElementId(
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index bc530564..6f58ca2 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -13783,12 +13783,45 @@ ->AutoscrollTaskIsScheduled()); // If a call comes in to delete the scrollbar layer for which the autoscroll - // was scheduled, the autoscroll task should be cancelled. - host_impl_->DidUnregisterScrollbarLayer(scroll_layer->element_id(), - ScrollbarOrientation::VERTICAL); - EXPECT_FALSE(GetInputHandler() - .scrollbar_controller_for_testing() - ->AutoscrollTaskIsScheduled()); + // was scheduled, the autoscroll task should set a waiting state instead of + // initiating an autoscroll, in case the scrollbar comes back. + layer_tree_impl->UnregisterScrollbar(scrollbar); + + EXPECT_TRUE(GetInputHandler() + .scrollbar_controller_for_testing() + ->AutoscrollTaskIsScheduled()); + + GetInputHandler() + .scrollbar_controller_for_testing() + ->cancelable_autoscroll_task_->callback() + .Run(); + GetInputHandler() + .scrollbar_controller_for_testing() + ->cancelable_autoscroll_task_.reset(); + EXPECT_EQ(GetInputHandler() + .scrollbar_controller_for_testing() + ->autoscroll_state_->status, + ScrollbarController::AutoScrollStatus::AUTOSCROLL_READY); + + // Re-register the scrollbar. An autoscroll task should be posted that + // actually starts a scroll animation + layer_tree_impl->RegisterScrollbar(scrollbar); + + EXPECT_TRUE(GetInputHandler() + .scrollbar_controller_for_testing() + ->AutoscrollTaskIsScheduled()); + + GetInputHandler() + .scrollbar_controller_for_testing() + ->cancelable_autoscroll_task_->callback() + .Run(); + GetInputHandler() + .scrollbar_controller_for_testing() + ->cancelable_autoscroll_task_.reset(); + EXPECT_EQ(GetInputHandler() + .scrollbar_controller_for_testing() + ->autoscroll_state_->status, + ScrollbarController::AutoScrollStatus::AUTOSCROLL_SCROLLING); // End the scroll. GetInputHandler().MouseUp(gfx::PointF(350, 580)); @@ -14460,10 +14493,16 @@ // existing scroll offset animations are aborted and a new autoscroll // animation is created. Test passes if unit test doesn't hit any DCHECK // failures. + GetInputHandler().scrollbar_controller_for_testing()->autoscroll_state_ = + ScrollbarController::AutoScrollState(); GetInputHandler() .scrollbar_controller_for_testing() - ->StartAutoScrollAnimation(/*scroll_velocity*/ 800, - ScrollbarPart::FORWARD_TRACK); + ->autoscroll_state_->velocity = 800; + GetInputHandler() + .scrollbar_controller_for_testing() + ->autoscroll_state_->pressed_scrollbar_part = + ScrollbarPart::FORWARD_TRACK; + GetInputHandler().scrollbar_controller_for_testing()->StartAutoScroll(); EXPECT_TRUE(GetImplAnimationHost()->ImplOnlyScrollAnimatingElement()); }
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 4409b11..454e377 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -2154,6 +2154,11 @@ *scrollbar_layer_id = scrollbar_layer->id(); + if (IsActiveTree()) { + host_impl_->DidRegisterScrollbarLayer(scroll_element_id, + scrollbar_layer->orientation()); + } + if (IsActiveTree() && scrollbar_layer->is_overlay_scrollbar() && scrollbar_layer->GetScrollbarAnimator() != LayerTreeSettings::NO_ANIMATOR) {
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 193ffae..d8cf59e 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -1276,6 +1276,7 @@ testonly = true resources_package = "org.chromium.chrome.test" sources = [ + "javatests/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulatorTest.java", "javatests/src/org/chromium/chrome/browser/toolbar/HomeButtonTest.java", ] deps = [ @@ -1284,18 +1285,27 @@ "//base:base_java_test_support", "//build/android:build_java", "//chrome/android:chrome_java", + "//chrome/browser/contextmenu:java", + "//chrome/browser/first_run/android:java", + "//chrome/browser/flags:java", + "//chrome/browser/lens:java", "//chrome/browser/ui/android/toolbar:java", "//chrome/test/android:chrome_java_test_support", "//components/browser_ui/settings/android:java", + "//components/embedder_support/android:context_menu_java", + "//components/externalauth/android:java", + "//components/search_engines/android:java", "//content/public/test/android:content_java_test_support", "//third_party/android_deps:espresso_java", "//third_party/android_support_test_runner:runner_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_test_runner_java", + "//third_party/blink/public:blink_headers_java", "//third_party/junit", "//third_party/mockito:mockito_java", "//ui/android:ui_full_java", "//ui/android:ui_java_test_support", + "//url:gurl_java", ] } @@ -1371,6 +1381,7 @@ "//chrome/browser/flags:java", "//chrome/browser/fullscreen/android:java", "//chrome/browser/gsa:java", + "//chrome/browser/history_clusters:java", "//chrome/browser/image_descriptions:javatests", "//chrome/browser/incognito:incognito_java_tests", "//chrome/browser/incognito:java", @@ -3978,7 +3989,6 @@ "java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSites.java", "java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesBridge.java", "java/src/org/chromium/chrome/browser/supervised_user/ChildAccountFeedbackReporter.java", - "java/src/org/chromium/chrome/browser/supervised_user/ChildAccountService.java", "java/src/org/chromium/chrome/browser/survey/SurveyHttpClientBridge.java", "java/src/org/chromium/chrome/browser/sync/TrustedVaultClient.java", "java/src/org/chromium/chrome/browser/tab/TabBrowserControlsConstraintsHelper.java", @@ -4001,6 +4011,10 @@ "java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java", ] + if (enable_supervised_users) { + sources += [ "java/src/org/chromium/chrome/browser/supervised_user/ChildAccountService.java" ] + } + # Used for testing only, should not be shipped to end users. if (enable_offline_pages_harness) { sources += [ "java/src/org/chromium/chrome/browser/offlinepages/evaluation/OfflinePageEvaluationBridge.java" ]
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni index 44e761e..6f072b2 100644 --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni
@@ -567,7 +567,9 @@ "java/res/layout/managed_by_menu_item.xml", "java/res/layout/material_tooltip.xml", "java/res/layout/multiline_spinner_item.xml", + "java/res/layout/mv_tiles_carousel.xml", "java/res/layout/mv_tiles_container.xml", + "java/res/layout/mv_tiles_grid.xml", "java/res/layout/navigation_bubble.xml", "java/res/layout/navigation_sheet.xml", "java/res/layout/navigation_sheet_toolbar.xml", @@ -611,7 +613,6 @@ "java/res/layout/shopping_filter_row.xml", "java/res/layout/signin_activity.xml", "java/res/layout/status_indicator_container.xml", - "java/res/layout/suggestions_site_tile_grid_modern.xml", "java/res/layout/suggestions_tile_view_condensed.xml", "java/res/layout/suspended_tab.xml", "java/res/layout/sync_custom_passphrase.xml",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 272033d..a43a72c 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -1058,16 +1058,13 @@ "java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesMediator.java", "java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesProperties.java", "java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesViewBinder.java", - "java/src/org/chromium/chrome/browser/suggestions/tile/SiteSectionViewHolder.java", "java/src/org/chromium/chrome/browser/suggestions/tile/SuggestionsTileView.java", "java/src/org/chromium/chrome/browser/suggestions/tile/Tile.java", - "java/src/org/chromium/chrome/browser/suggestions/tile/TileGridViewHolder.java", "java/src/org/chromium/chrome/browser/suggestions/tile/TileGroup.java", "java/src/org/chromium/chrome/browser/suggestions/tile/TileGroupDelegateImpl.java", "java/src/org/chromium/chrome/browser/suggestions/tile/TileRenderer.java", "java/src/org/chromium/chrome/browser/suggestions/tile/TopSitesTileView.java", "java/src/org/chromium/chrome/browser/supervised_user/ChildAccountFeedbackReporter.java", - "java/src/org/chromium/chrome/browser/supervised_user/ChildAccountService.java", "java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java", "java/src/org/chromium/chrome/browser/survey/SurveyController.java", "java/src/org/chromium/chrome/browser/survey/SurveyHttpClientBridge.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index 11003d7..88f3237 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -218,6 +218,7 @@ "junit/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImplUnitTest.java", "junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java", "junit/src/org/chromium/chrome/browser/tabmodel/PendingTabClosureManagerTest.java", + "junit/src/org/chromium/chrome/browser/tabmodel/TabModelImplUnitTest.java", "junit/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImplTest.java", "junit/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorProfileSupplierTest.java", "junit/src/org/chromium/chrome/browser/tabmodel/UndoTabModelUnitTest.java",
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java index c1fcfe6..9d13fa4 100644 --- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java +++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java
@@ -145,12 +145,14 @@ incognitoCookieControlsManager, tabSwitcherType == TabSwitcherType.CAROUSEL); if (hasMVTiles) { - mMostVisitedCoordinator = - new MostVisitedTilesCoordinator(activity, activityLifecycleDispatcher, - mView.findViewById(R.id.mv_tiles_container), windowAndroid, - TabUiFeatureUtilities.supportInstantStart( - DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity), - mActivity)); + mMostVisitedCoordinator = new MostVisitedTilesCoordinator(activity, + activityLifecycleDispatcher, mView.findViewById(R.id.mv_tiles_container), + windowAndroid, + TabUiFeatureUtilities.supportInstantStart( + DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity), + mActivity), + /*isScrollableMVTEnabled=*/true, Integer.MAX_VALUE, Integer.MAX_VALUE, + /*snapshotTileGridChangedRunnable=*/null, /*tileCountChangedRunnable=*/null); } if (hasQueryTiles) {
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java index 1555922..a8e49a5 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
@@ -423,6 +423,13 @@ } @Override + public void reload() { + if (ChromeFeatureList.isEnabled(ChromeFeatureList.FEED_INTERACTIVE_REFRESH)) { + onRefresh(); + } + } + + @Override public void onRefresh() { updateReloadButtonVisibility(/*isReloading=*/true); if (mReliabilityLogger != null) { @@ -430,8 +437,8 @@ SystemClock.elapsedRealtimeNanos()); } mMediator.manualRefresh((Boolean v) -> { - if (mSwipeRefreshLayout == null) return; updateReloadButtonVisibility(/*isReloading=*/false); + if (mSwipeRefreshLayout == null) return; mSwipeRefreshLayout.setRefreshing(false); }); getFeatureEngagementTracker().notifyEvent(EventConstants.FEED_SWIPE_REFRESHED);
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java index d772761..59eea06 100644 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java +++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java
@@ -84,7 +84,6 @@ import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.ChromeRenderTestRule; -import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.chrome.test.util.NewTabPageTestUtils; import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; @@ -369,11 +368,14 @@ onView(withId(R.id.feed_stream_recycler_view)) .perform(RecyclerViewActions.scrollToPosition(SIGNIN_PROMO_POSITION)); onView(withId(R.id.signin_promo_view_container)).check(doesNotExist()); + } + @Test + @MediumTest + @Feature({"FeedNewTabPage"}) + public void testSignInPromo_AccountsReady() { mIsCachePopulatedInAccountManagerFacade = true; - TestThreadUtils.runOnUiThreadBlocking(mTab::reload); - ChromeTabUtils.waitForTabPageLoaded(mTab, ChromeTabUtils.getUrlStringOnUiThread(mTab)); - + openNewTabPage(); // Check that the sign-in promo is displayed this time. onView(withId(R.id.feed_stream_recycler_view)) .perform(RecyclerViewActions.scrollToPosition(SIGNIN_PROMO_POSITION));
diff --git a/chrome/android/java/res/layout/mv_tiles_carousel.xml b/chrome/android/java/res/layout/mv_tiles_carousel.xml new file mode 100644 index 0000000..76ba72d6 --- /dev/null +++ b/chrome/android/java/res/layout/mv_tiles_carousel.xml
@@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2022 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:scrollbars="none"> + + <org.chromium.chrome.browser.suggestions.tile.MostVisitedTilesCarouselLayout + android:id="@+id/mv_tiles_layout" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:orientation="horizontal" /> +</HorizontalScrollView>
diff --git a/chrome/android/java/res/layout/mv_tiles_container.xml b/chrome/android/java/res/layout/mv_tiles_container.xml index 54deef93..1de6f59 100644 --- a/chrome/android/java/res/layout/mv_tiles_container.xml +++ b/chrome/android/java/res/layout/mv_tiles_container.xml
@@ -15,18 +15,17 @@ android:layout_gravity="center_horizontal" app:layout_scrollFlags="scroll"> - <HorizontalScrollView - android:layout_width="match_parent" + <ViewStub + android:id="@+id/mv_tiles_carousel_stub" + android:layout_width="wrap_content" android:layout_height="wrap_content" - android:scrollbars="none"> + android:layout="@layout/mv_tiles_carousel" /> - <org.chromium.chrome.browser.suggestions.tile.MostVisitedTilesCarouselLayout - android:id="@+id/mv_tiles_layout" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:orientation="horizontal"> - </org.chromium.chrome.browser.suggestions.tile.MostVisitedTilesCarouselLayout> - </HorizontalScrollView> + <ViewStub + android:id="@+id/mv_tiles_grid_stub" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout="@layout/mv_tiles_grid" /> <!-- Site suggestion tile grid placeholder --> <ViewStub
diff --git a/chrome/android/java/res/layout/suggestions_site_tile_grid_modern.xml b/chrome/android/java/res/layout/mv_tiles_grid.xml similarity index 87% rename from chrome/android/java/res/layout/suggestions_site_tile_grid_modern.xml rename to chrome/android/java/res/layout/mv_tiles_grid.xml index 840aae15..d3ff1df5 100644 --- a/chrome/android/java/res/layout/suggestions_site_tile_grid_modern.xml +++ b/chrome/android/java/res/layout/mv_tiles_grid.xml
@@ -8,5 +8,4 @@ android:id="@+id/mv_tiles_layout" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/tile_grid_layout_bottom_margin" - android:layout_gravity="center_horizontal" /> + android:layout_gravity="center_horizontal" /> \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 1e2248f..39a2728a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -130,6 +130,7 @@ import org.chromium.chrome.browser.profiles.OTRProfileID; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.ProfileManager; +import org.chromium.chrome.browser.read_later.ReadingListUtils; import org.chromium.chrome.browser.reengagement.ReengagementNotificationController; import org.chromium.chrome.browser.search_engines.SearchEngineChoiceNotification; import org.chromium.chrome.browser.settings.SettingsLauncherImpl; @@ -2219,6 +2220,7 @@ // get back to the previous state. The reason for startsWith check is that the // actual redirected URL is a different system language based help url. final @TabLaunchType int type = currentTab.getLaunchType(); + final boolean helpUrl = currentTab.getUrl().getSpec().startsWith(HELP_URL_PREFIX); if (type == TabLaunchType.FROM_CHROME_UI && helpUrl) { getCurrentTabModel().closeTab(currentTab); @@ -2261,6 +2263,11 @@ return true; } + if (type == TabLaunchType.FROM_READING_LIST) { + assert !isTablet() : "Not expecting to see FROM_READING_LIST on tablets"; + ReadingListUtils.showReadingList(currentTab.isIncognito()); + } + final boolean shouldCloseTab = backShouldCloseTab(currentTab); // Minimize the app if either: @@ -2303,6 +2310,7 @@ int type = tab.getLaunchType(); return type == TabLaunchType.FROM_LINK || type == TabLaunchType.FROM_EXTERNAL_APP + || type == TabLaunchType.FROM_READING_LIST || type == TabLaunchType.FROM_LONGPRESS_FOREGROUND || type == TabLaunchType.FROM_LONGPRESS_INCOGNITO || type == TabLaunchType.FROM_LONGPRESS_BACKGROUND @@ -2327,12 +2335,14 @@ // If the runnable doesn't run before the Activity dies, Chrome won't crash but the tab // won't be closed (crbug.com/587565). mHandler.postDelayed(() -> { - boolean hasNextTab = - getCurrentTabModel().getNextTabIfClosed(tabToClose.getId()) != null; - getCurrentTabModel().closeTab(tabToClose, false, true, false); + boolean uponExit = ChromeFeatureList.isEnabled( + ChromeFeatureList.MOST_RECENT_TAB_ON_BACKGROUND_CLOSE_TAB); + Tab nextTab = getCurrentTabModel().getNextTabIfClosed( + tabToClose.getId(), /*uponExit=*/uponExit); + getCurrentTabModel().closeTab(tabToClose, nextTab, false, true, false); // If there is no next tab to open, enter overview mode. - if (!hasNextTab) showOverview(StartSurfaceState.SHOWING_START); + if (nextTab == null) showOverview(StartSurfaceState.SHOWING_START); }, CLOSE_TAB_ON_MINIMIZE_DELAY_MS); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java index 5f836e75..01ed06d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -82,7 +82,6 @@ import org.chromium.chrome.browser.app.tabmodel.TabModelOrchestrator; import org.chromium.chrome.browser.back_press.BackPressManager; import org.chromium.chrome.browser.bookmarks.BookmarkBridge; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkModel; import org.chromium.chrome.browser.bookmarks.BookmarkUtils; import org.chromium.chrome.browser.bookmarks.PowerBookmarkUtils; @@ -196,6 +195,7 @@ import org.chromium.chrome.browser.vr.ArDelegateProvider; import org.chromium.chrome.browser.vr.VrModuleProvider; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.bookmarks.BookmarkType; import org.chromium.components.browser_ui.accessibility.FontSizePrefs; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java index 7412777..7a40f3d5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java
@@ -15,11 +15,11 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.incognito.IncognitoUtils; import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.tabmodel.document.TabDelegate; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.bookmarks.BookmarkType; import org.chromium.components.browser_ui.util.ToolbarUtils; import org.chromium.components.browser_ui.widget.dragreorder.DragReorderableListAdapter;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkAddEditFolderActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkAddEditFolderActivity.java index 17325f8..45d995d2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkAddEditFolderActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkAddEditFolderActivity.java
@@ -20,9 +20,9 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; import org.chromium.chrome.browser.SynchronousInitializationActivity; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.browser_ui.widget.TintedDrawable; import java.util.ArrayList;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java index b30c291..dcbeb10 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java
@@ -34,10 +34,9 @@ import org.chromium.chrome.browser.subscriptions.SubscriptionsManager; import org.chromium.chrome.browser.tab.Tab; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.bookmarks.BookmarkType; import org.chromium.components.commerce.PriceTracking.ProductPrice; -import org.chromium.components.url_formatter.SchemeDisplay; -import org.chromium.components.url_formatter.UrlFormatter; import org.chromium.content_public.browser.WebContents; import org.chromium.url.GURL; @@ -201,111 +200,6 @@ } /** - * Contains data about a bookmark or bookmark folder. - */ - public static class BookmarkItem { - private final String mTitle; - private final GURL mUrl; - private final BookmarkId mId; - private final boolean mIsFolder; - private final BookmarkId mParentId; - private final boolean mIsEditable; - private final boolean mIsManaged; - private boolean mForceEditableForTesting; - private long mDateAdded; - private boolean mRead; - - @VisibleForTesting - public BookmarkItem(BookmarkId id, String title, GURL url, boolean isFolder, - BookmarkId parentId, boolean isEditable, boolean isManaged, long dateAdded, - boolean read) { - mId = id; - mTitle = title; - mUrl = url; - mIsFolder = isFolder; - mParentId = parentId; - mIsEditable = isEditable; - mIsManaged = isManaged; - mDateAdded = dateAdded; - mRead = read; - } - - /** Returns the title of the bookmark item. */ - public String getTitle() { - return mTitle; - } - - /** Returns the url of the bookmark item. */ - public GURL getUrl() { - return mUrl; - } - - /** Returns the string to display for the item's url. */ - public String getUrlForDisplay() { - return UrlFormatter.formatUrlForSecurityDisplay( - getUrl(), SchemeDisplay.OMIT_HTTP_AND_HTTPS); - } - - /** Returns whether item is a folder or a bookmark. */ - public boolean isFolder() { - return mIsFolder; - } - - /** Returns the parent id of the bookmark item. */ - public BookmarkId getParentId() { - return mParentId; - } - - /** Returns whether this bookmark can be edited. */ - public boolean isEditable() { - return mForceEditableForTesting || mIsEditable; - } - - /** Returns whether this bookmark's URL can be edited */ - public boolean isUrlEditable() { - return isEditable() && mId.getType() == BookmarkType.NORMAL; - } - - /** Returns whether this bookmark can be moved */ - public boolean isMovable() { - return ReadingListUtils.isSwappableReadingListItem(mId) || isReorderable(); - } - - /** Returns whether this bookmark can be moved */ - public boolean isReorderable() { - return isEditable() && mId.getType() == BookmarkType.NORMAL; - } - - /** Returns whether this is a managed bookmark. */ - public boolean isManaged() { - return mIsManaged; - } - - /** Returns the {@link BookmarkId}. */ - public BookmarkId getId() { - return mId; - } - - /** Retuns the timestamp in milliseconds since epoch that the bookmark is added. */ - public long getDateAdded() { - return mDateAdded; - } - - /** - * Returns whether the bookmark is read. Only valid for {@link BookmarkType#READING_LIST}. - * Defaults to "false" for other types. - */ - public boolean isRead() { - return mRead; - } - - // TODO(https://crbug.com/1019217): Remove when BookmarkModel is stubbed in tests instead. - void forceEditableForTesting() { - mForceEditableForTesting = true; - } - } - - /** * Handler to fetch the bookmarks, titles, urls and folder hierarchy. * @param profile Profile instance corresponding to the active profile. */ @@ -470,9 +364,11 @@ if (id == null) return null; if (BookmarkId.SHOPPING_FOLDER.equals(id)) { + // TODO(crbug.com/1317801): Add better support for synthetic folders. return new BookmarkItem(id, /*title=*/null, /*url=*/null, /*isFolder=*/true, /*parentId=*/getRootFolderId(), /*isEditable=*/false, - /*isManaged=*/false, /*dateAdded=*/0L, /*read=*/false); + /*isManaged=*/false, /*dateAdded=*/0L, /*read=*/false, + /*readingListSwappable=*/false); } return BookmarkBridgeJni.get().getBookmarkByID( @@ -1298,8 +1194,10 @@ private static BookmarkItem createBookmarkItem(long id, int type, String title, GURL url, boolean isFolder, long parentId, int parentIdType, boolean isEditable, boolean isManaged, long dateAdded, boolean read) { - return new BookmarkItem(new BookmarkId(id, type), title, url, isFolder, - new BookmarkId(parentId, parentIdType), isEditable, isManaged, dateAdded, read); + BookmarkId bookmarkId = new BookmarkId(id, type); + return new BookmarkItem(bookmarkId, title, url, isFolder, + new BookmarkId(parentId, parentIdType), isEditable, isManaged, dateAdded, read, + ReadingListUtils.isSwappableReadingListItem(bookmarkId)); } @CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkEditActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkEditActivity.java index edf7b6c4..90e58c1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkEditActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkEditActivity.java
@@ -17,9 +17,9 @@ import org.chromium.base.Log; import org.chromium.chrome.R; import org.chromium.chrome.browser.SynchronousInitializationActivity; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.browser_ui.widget.TintedDrawable; import org.chromium.components.url_formatter.UrlFormatter; import org.chromium.url.GURL;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java index eefb808..44d9d95 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java
@@ -11,8 +11,8 @@ import androidx.appcompat.content.res.AppCompatResources; import org.chromium.chrome.R; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.bookmarks.BookmarkType; /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java index 679945e..223d626 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java
@@ -28,10 +28,10 @@ import org.chromium.base.IntentUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.SynchronousInitializationActivity; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; import org.chromium.chrome.browser.read_later.ReadingListUtils; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.browser_ui.widget.selectable_list.SelectableItemView; import java.util.ArrayList;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemRow.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemRow.java index dce2aaa4..8fa32bd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemRow.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemRow.java
@@ -10,9 +10,9 @@ import android.util.AttributeSet; import org.chromium.chrome.R; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.ui.favicon.FaviconUtils; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.browser_ui.widget.RoundedIconGenerator; import org.chromium.components.favicon.IconType; import org.chromium.components.favicon.LargeIconBridge.LargeIconCallback;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java index fcb19cfd..bc3c1c6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java
@@ -20,7 +20,6 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; import org.chromium.chrome.browser.bookmarks.BookmarkListEntry.ViewType; import org.chromium.chrome.browser.bookmarks.BookmarkRow.Location; @@ -37,6 +36,7 @@ import org.chromium.chrome.browser.ui.signin.PersonalizedSigninPromoView; import org.chromium.chrome.browser.ui.signin.SigninPromoController.SyncPromoState; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.bookmarks.BookmarkType; import org.chromium.components.browser_ui.util.GlobalDiscardableReferencePool; import org.chromium.components.browser_ui.widget.dragreorder.DragReorderableListAdapter;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkListEntry.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkListEntry.java index bc54f93..6f55965 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkListEntry.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkListEntry.java
@@ -9,9 +9,9 @@ import androidx.annotation.IntDef; import androidx.annotation.Nullable; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.power_bookmarks.PowerBookmarkMeta; import org.chromium.chrome.browser.power_bookmarks.PowerBookmarkType; +import org.chromium.components.bookmarks.BookmarkItem; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java index 2194b04..65fd0baa 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
@@ -21,7 +21,6 @@ import org.chromium.base.ObserverList; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; import org.chromium.chrome.browser.commerce.shopping_list.ShoppingFeatures; import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksReader; @@ -30,6 +29,7 @@ import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.browser.ui.native_page.BasicNativePage; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.bookmarks.BookmarkType; import org.chromium.components.browser_ui.util.ConversionUtils; import org.chromium.components.browser_ui.widget.dragreorder.DragStateDelegate;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkModel.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkModel.java index 5c28a17a..099aa69 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkModel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkModel.java
@@ -10,6 +10,7 @@ import org.chromium.base.ObserverList; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.bookmarks.BookmarkType; import java.util.ArrayList;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRow.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRow.java index 20c7b1f..fb28508 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRow.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRow.java
@@ -19,8 +19,8 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.bookmarks.BookmarkType; import org.chromium.components.browser_ui.widget.listmenu.BasicListMenu; import org.chromium.components.browser_ui.widget.listmenu.ListMenu;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowMediator.java index fb29e54..c7675ac 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowMediator.java
@@ -14,7 +14,6 @@ import org.chromium.base.CallbackController; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; import org.chromium.chrome.browser.bookmarks.PowerBookmarkMetrics.PriceTrackingState; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; @@ -24,6 +23,7 @@ import org.chromium.chrome.browser.subscriptions.CommerceSubscription; import org.chromium.chrome.browser.subscriptions.SubscriptionsManager; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.feature_engagement.EventConstants; import org.chromium.ui.modelutil.PropertyModel;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java index 3665ec2..cdc98d1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java
@@ -9,11 +9,11 @@ import org.chromium.base.lifetime.DestroyChecker; import org.chromium.base.task.PostTask; import org.chromium.chrome.R; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; import org.chromium.chrome.browser.bookmarks.BookmarkModel.BookmarkDeleteObserver; import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.content_public.browser.UiThreadTaskTraits; import java.util.Locale;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java index bade68e..a69a638da 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java
@@ -34,7 +34,6 @@ import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.IntentHandler.IncognitoCCTCallerId; import org.chromium.chrome.browser.LaunchIntentDispatcher; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider.CustomTabsUiType; import org.chromium.chrome.browser.commerce.shopping_list.ShoppingFeatures; import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider; @@ -47,11 +46,13 @@ import org.chromium.chrome.browser.subscriptions.CommerceSubscriptionsServiceFactory; import org.chromium.chrome.browser.subscriptions.SubscriptionsManager; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarController; import org.chromium.chrome.browser.user_education.UserEducationHelper; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.bookmarks.BookmarkType; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.embedder_support.util.UrlConstants; @@ -342,7 +343,8 @@ // Tablet. if (DeviceFormFactor.isNonMultiDisplayContextOnTablet(context)) { - openUrl(context, url, activity == null ? null : activity.getComponentName()); + openUrl(context, url, activity == null ? null : activity.getComponentName(), + /*launchType=*/null, isIncognito); return; } @@ -475,7 +477,8 @@ isIncognito); model.setReadStatusForReadingList(bookmarkItem.getUrl(), true); } else { - openUrl(context, bookmarkItem.getUrl().getSpec(), openBookmarkComponentName); + openUrl(context, bookmarkItem.getUrl().getSpec(), openBookmarkComponentName, + /*launchType=*/null, isIncognito); } return true; } @@ -527,13 +530,34 @@ return null; } - private static void openUrl(Context context, String url, ComponentName componentName) { + /** + * Opens a url. + * + * @param url Url to open. + * @param componentName Name of the component opening the URL. If null, {@link + * ChromeTabbedActivity} is used. + * @param launchType If not null, url is opened in a new tab with the specified {@link + * TabLaunchType}. + */ + private static void openUrl(Context context, String url, ComponentName componentName, + @Nullable @TabLaunchType Integer launchType, boolean isOffTheRecord) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); intent.putExtra( Browser.EXTRA_APPLICATION_ID, context.getApplicationContext().getPackageName()); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra(IntentHandler.EXTRA_PAGE_TRANSITION_TYPE, PageTransition.AUTO_BOOKMARK); + if (launchType != null) { + IntentHandler.setTabLaunchType(intent, launchType); + if (isOffTheRecord) { + intent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, true); + } else { + intent.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true); + } + } else { + intent.putExtra(IntentHandler.EXTRA_INCOGNITO_MODE, isOffTheRecord); + } + if (componentName != null) { ChromeTabbedActivity.setNonAliasedComponent(intent, componentName); } else { @@ -551,7 +575,11 @@ if (ReadingListFeatures.shouldUseCustomTab()) { openReadingListInCustomTab(context, url, isOffTheRecord); } else { - openUrl(context, url, componentName); + openUrl(context, url, componentName, + DeviceFormFactor.isNonMultiDisplayContextOnTablet(context) + ? null + : TabLaunchType.FROM_READING_LIST, + isOffTheRecord); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRow.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRow.java index 826ee83..c291ccb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRow.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRow.java
@@ -19,7 +19,6 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Callback; import org.chromium.chrome.R; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.PowerBookmarkMetrics.PriceTrackingState; import org.chromium.chrome.browser.power_bookmarks.PowerBookmarkMeta; import org.chromium.chrome.browser.power_bookmarks.ProductPrice; @@ -27,6 +26,7 @@ import org.chromium.chrome.browser.subscriptions.SubscriptionsManager; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.browser_ui.widget.RoundedCornerOutlineProvider; import org.chromium.components.browser_ui.widget.chips.ChipView; import org.chromium.components.image_fetcher.ImageFetcher;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipList.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipList.java index 7670ca0..9fe55b4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipList.java
@@ -11,10 +11,10 @@ import androidx.annotation.VisibleForTesting; import org.chromium.chrome.R; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; import org.chromium.chrome.browser.power_bookmarks.PowerBookmarkMeta; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.browser_ui.widget.chips.ChipProperties; import org.chromium.components.browser_ui.widget.chips.ChipsCoordinator; import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReadingListSectionHeader.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReadingListSectionHeader.java index 788a4767..30e4554d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReadingListSectionHeader.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReadingListSectionHeader.java
@@ -9,7 +9,7 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.bookmarks.BookmarkType; import java.util.Collections;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetServiceImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetServiceImpl.java index b85c9a81..81f3272 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetServiceImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetServiceImpl.java
@@ -27,7 +27,6 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.task.PostTask; import org.chromium.chrome.R; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; import org.chromium.chrome.browser.bookmarks.BookmarkModel; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; @@ -35,6 +34,7 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.ui.favicon.FaviconUtils; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.browser_ui.widget.RoundedIconGenerator; import org.chromium.components.favicon.IconType; import org.chromium.components.favicon.LargeIconBridge;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java index ebcab69..e0f4204 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
@@ -1009,7 +1009,7 @@ tab.setIsDying(true); // 3. Fake a selection on the next tab now. - Tab nextTab = mModel.getNextTabIfClosed(tab.getId()); + Tab nextTab = mModel.getNextTabIfClosed(tab.getId(), /*uponExit=*/false); if (nextTab != null) tabSelected(time, nextTab.getId(), tab.getId()); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java index aed4a5d..480418a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -438,9 +438,9 @@ mNewTabPageLayout.initialize(mNewTabPageManager, activity, mTileGroupDelegate, mSearchProviderHasLogo, TemplateUrlServiceFactory.get().isDefaultSearchEngineGoogle(), - mFeedSurfaceProvider.getScrollDelegate(), mContextMenuManager, + mFeedSurfaceProvider.getScrollDelegate(), mFeedSurfaceProvider.getTouchEnabledDelegate(), mFeedSurfaceProvider.getUiConfig(), - activityTabProvider, lifecycleDispatcher, uma, mTab.isIncognito(), windowAndroid); + lifecycleDispatcher, uma, mTab.isIncognito(), windowAndroid); TraceEvent.end(TAG); } @@ -905,6 +905,11 @@ public void updateForUrl(String url) { } + @Override + public void reload() { + mFeedSurfaceProvider.reload(); + } + // InvalidationAwareThumbnailProvider @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java index 46bf21fa..9d55ddb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
@@ -30,7 +30,6 @@ import org.chromium.base.CallbackController; import org.chromium.base.MathUtils; import org.chromium.base.TraceEvent; -import org.chromium.base.supplier.Supplier; import org.chromium.chrome.R; import org.chromium.chrome.browser.app.video_tutorials.NewTabPageVideoIPHManager; import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareThumbnailProvider; @@ -46,23 +45,13 @@ import org.chromium.chrome.browser.logo.LogoBridge.LogoObserver; import org.chromium.chrome.browser.logo.LogoDelegateImpl; import org.chromium.chrome.browser.logo.LogoView; -import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.ntp.NewTabPage.OnSearchBoxScrollListener; import org.chromium.chrome.browser.ntp.search.SearchBoxCoordinator; -import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.query_tiles.QueryTileSection; import org.chromium.chrome.browser.query_tiles.QueryTileUtils; -import org.chromium.chrome.browser.suggestions.SuggestionsConfig; -import org.chromium.chrome.browser.suggestions.SuggestionsDependencyFactory; import org.chromium.chrome.browser.suggestions.tile.MostVisitedTilesCoordinator; -import org.chromium.chrome.browser.suggestions.tile.MostVisitedTilesGridLayout; -import org.chromium.chrome.browser.suggestions.tile.SiteSectionViewHolder; -import org.chromium.chrome.browser.suggestions.tile.Tile; -import org.chromium.chrome.browser.suggestions.tile.TileGridViewHolder; import org.chromium.chrome.browser.suggestions.tile.TileGroup; -import org.chromium.chrome.browser.suggestions.tile.TileRenderer; -import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.ui.native_page.TouchEnabledDelegate; import org.chromium.chrome.browser.user_education.IPHCommandBuilder; import org.chromium.chrome.browser.user_education.UserEducationHelper; @@ -85,7 +74,7 @@ * Layout for the new tab page. This positions the page elements in the correct vertical positions. * There are no separate phone and tablet UIs; this layout adapts based on the available space. */ -public class NewTabPageLayout extends LinearLayout implements TileGroup.Observer, VrModeObserver { +public class NewTabPageLayout extends LinearLayout implements VrModeObserver { private static final String TAG = "NewTabPageLayout"; // Used to signify the cached resource value is unset. @@ -105,33 +94,22 @@ private LogoView mSearchProviderLogoView; private SearchBoxCoordinator mSearchBoxCoordinator; - private ViewGroup mSiteSectionView; - private SiteSectionViewHolder mSiteSectionViewHolder; - private View mTileGridPlaceholder; - private View mNoSearchLogoSpacer; private QueryTileSection mQueryTileSection; private NewTabPageVideoIPHManager mVideoIPHManager; private ImageView mCryptidHolder; + private ViewGroup mMvTilesContainerLayout; + private MostVisitedTilesCoordinator mMostVisitedTilesCoordinator; @Nullable private View mExploreSectionView; // View is null if explore flag is disabled. @Nullable private Object mExploreSection; // Null when explore sites disabled. - // View is null if scrollable-mv-tiles flag is disabled. - @Nullable - private ViewGroup mMvTilesContainerLayout; - - // Null if scrollable-mv-tiles flag is disabled. - @Nullable - private MostVisitedTilesCoordinator mMostVisitedTilesCoordinator; - private OnSearchBoxScrollListener mSearchBoxScrollListener; private NewTabPageManager mManager; private Activity mActivity; private LogoDelegateImpl mLogoDelegate; - private TileGroup mTileGroup; private UiConfig mUiConfig; private CallbackController mCallbackController = new CallbackController(); @@ -210,11 +188,9 @@ * @param searchProviderHasLogo Whether the search provider has a logo. * @param searchProviderIsGoogle Whether the search provider is Google. * @param scrollDelegate The delegate used to obtain information about scroll state. - * @param contextMenuManager The manager for long-press context menus. * @param touchEnabledDelegate The {@link TouchEnabledDelegate} for handling whether touch * events are allowed. * @param uiConfig UiConfig that provides display information about this view. - * @param tabProvider Provides the current active tab. * @param lifecycleDispatcher Activity lifecycle dispatcher. * @param uma {@link NewTabPageUma} object recording user metrics. * @param isIncognito Whether the new tab page is in incognito mode. @@ -223,8 +199,7 @@ public void initialize(NewTabPageManager manager, Activity activity, TileGroup.Delegate tileGroupDelegate, boolean searchProviderHasLogo, boolean searchProviderIsGoogle, FeedSurfaceScrollDelegate scrollDelegate, - ContextMenuManager contextMenuManager, TouchEnabledDelegate touchEnabledDelegate, - UiConfig uiConfig, Supplier<Tab> tabProvider, + TouchEnabledDelegate touchEnabledDelegate, UiConfig uiConfig, ActivityLifecycleDispatcher lifecycleDispatcher, NewTabPageUma uma, boolean isIncognito, WindowAndroid windowAndroid) { TraceEvent.begin(TAG + ".initialize()"); @@ -249,17 +224,9 @@ mSearchBoxBoundsVerticalInset = getResources().getDimensionPixelSize( R.dimen.ntp_search_box_bounds_vertical_inset_modern); } - mNoSearchLogoSpacer = findViewById(R.id.no_search_logo_spacer); - if (isScrollableMVTEnabled()) { - // If SHOW_SCROLLABLE_MV_ON_NTP is true, TileGroup and other logic will be handled by - // MostVisitedListCoordinator. - initializeMostVisitedListCoordinator( - lifecycleDispatcher, tileGroupDelegate, touchEnabledDelegate); - } else { - initializeTileGroup( - profile, searchProviderIsGoogle, contextMenuManager, tileGroupDelegate); - } + initializeMostVisitedTilesCoordinator(profile, lifecycleDispatcher, tileGroupDelegate, + touchEnabledDelegate, isScrollableMVTEnabled(), searchProviderIsGoogle); initializeSearchBoxBackground(); initializeSearchBoxTextView(); initializeVoiceSearchButton(); @@ -364,49 +331,32 @@ TraceEvent.end(TAG + ".initializeLayoutChangeListener()"); } - private void initializeTileGroup(Profile profile, boolean searchProviderIsGoogle, - ContextMenuManager contextMenuManager, TileGroup.Delegate tileGroupDelegate) { - OfflinePageBridge offlinePageBridge = - SuggestionsDependencyFactory.getInstance().getOfflinePageBridge(profile); - TileRenderer tileRenderer = - new TileRenderer(mActivity, SuggestionsConfig.getTileStyle(mUiConfig), - getTileTitleLines(), mManager.getImageFetcher()); - mTileGroup = new TileGroup(tileRenderer, mManager, contextMenuManager, tileGroupDelegate, - /* observer = */ this, offlinePageBridge); + private void initializeMostVisitedTilesCoordinator(Profile profile, + ActivityLifecycleDispatcher activityLifecycleDispatcher, + TileGroup.Delegate tileGroupDelegate, TouchEnabledDelegate touchEnabledDelegate, + boolean isScrollableMVTEnabled, boolean searchProviderIsGoogle) { + assert mMvTilesContainerLayout != null; int maxRows = 2; if (searchProviderIsGoogle && QueryTileUtils.isQueryTilesEnabledOnNTP()) { maxRows = QueryTileSection.getMaxRowsForMostVisitedTiles(getContext()); } - mSiteSectionViewHolder = - getSiteSectionViewHolder(getSiteSectionView(), maxRows, MAX_TILE_COLUMNS); - mSiteSectionViewHolder.bindDataSource(mTileGroup, tileRenderer); + mMostVisitedTilesCoordinator = new MostVisitedTilesCoordinator(mActivity, + activityLifecycleDispatcher, mMvTilesContainerLayout, mWindowAndroid, + /*shouldShowSkeletonUIPreNative=*/false, isScrollableMVTEnabled, maxRows, + MAX_TILE_COLUMNS, () -> mSnapshotTileGridChanged = true, () -> { + if (mUrlFocusChangePercent == 1f) mTileCountChanged = true; + }); + + mMostVisitedTilesCoordinator.initWithNative( + mManager, tileGroupDelegate, touchEnabledDelegate); int variation = ExploreSitesBridge.getVariation(); if (ExploreSitesBridge.isExperimental(variation)) { mExploreSection = new ExperimentalExploreSitesSection( mExploreSectionView, profile, mManager.getNavigationDelegate()); } - - mTileGroup.startObserving(maxRows * getMaxColumnsForMostVisitedTiles()); - } - - private void initializeMostVisitedListCoordinator( - ActivityLifecycleDispatcher activityLifecycleDispatcher, - TileGroup.Delegate tileGroupDelegate, TouchEnabledDelegate touchEnabledDelegate) { - assert mMvTilesContainerLayout != null; - mMostVisitedTilesCoordinator = new MostVisitedTilesCoordinator(mActivity, - activityLifecycleDispatcher, mMvTilesContainerLayout, mWindowAndroid, - /*shouldShowSkeletonUIPreNative=*/false); - // Let mMvTilesLayout attached to the edge of the screen. - int lateralPaddingsForNTP = mActivity.getResources().getDimensionPixelSize( - R.dimen.ntp_header_lateral_paddings_v2); - MarginLayoutParams params = (MarginLayoutParams) mMvTilesContainerLayout.getLayoutParams(); - params.leftMargin = -lateralPaddingsForNTP; - params.rightMargin = -lateralPaddingsForNTP; - mMostVisitedTilesCoordinator.initWithNative( - mManager, tileGroupDelegate, touchEnabledDelegate); } /** @@ -468,40 +418,17 @@ 1f); } - @VisibleForTesting - public static ViewGroup inflateSiteSection(ViewGroup parent) { - return (ViewGroup) LayoutInflater.from(parent.getContext()) - .inflate(R.layout.suggestions_site_tile_grid_modern, parent, false); - } - private void insertSiteSectionView() { int insertionPoint = indexOfChild(mMiddleSpacer) + 1; - if (isScrollableMVTEnabled()) { - setClipToPadding(false); - mMvTilesContainerLayout = (ViewGroup) LayoutInflater.from(this.getContext()) - .inflate(R.layout.mv_tiles_container, this, false); - mMvTilesContainerLayout.setVisibility(View.VISIBLE); - addView(mMvTilesContainerLayout, insertionPoint); - - // The page contents are initially hidden; otherwise they'll be drawn centered on the - // page before the tiles are available and then jump upwards to make space once the - // tiles are available. - if (getVisibility() != View.VISIBLE) setVisibility(View.VISIBLE); - } else { - mSiteSectionView = inflateSiteSection(this); - ViewGroup.LayoutParams layoutParams = mSiteSectionView.getLayoutParams(); - layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT; - mSiteSectionView.setLayoutParams(layoutParams); - addView(mSiteSectionView, insertionPoint); - } - } - - /** - * @return the embedded {@link MostVisitedTilesGridLayout}. - */ - private ViewGroup getSiteSectionView() { - return mSiteSectionView; + mMvTilesContainerLayout = (ViewGroup) LayoutInflater.from(this.getContext()) + .inflate(R.layout.mv_tiles_container, this, false); + mMvTilesContainerLayout.setVisibility(View.VISIBLE); + addView(mMvTilesContainerLayout, insertionPoint); + // The page contents are initially hidden; otherwise they'll be drawn centered on the + // page before the tiles are available and then jump upwards to make space once the + // tiles are available. + if (getVisibility() != View.VISIBLE) setVisibility(View.VISIBLE); } /** @@ -517,34 +444,12 @@ unifyElementWidths(); } - /** - * @return The placeholder that is shown above the fold when there is no other content to show, - * or null if it has not been inflated yet. - */ - @VisibleForTesting - @Nullable - public View getPlaceholder() { - return mTileGridPlaceholder; - } - public void onSwitchToForeground() { - if (mTileGroup != null) { - mTileGroup.onSwitchToForeground(/* trackLoadTask = */ false); - } else if (mMostVisitedTilesCoordinator != null) { + if (mMostVisitedTilesCoordinator != null) { mMostVisitedTilesCoordinator.onSwitchToForeground(); } } - public TileGroup getTileGroup() { - return mTileGroup; - } - - @VisibleForTesting - public static TileGridViewHolder getSiteSectionViewHolder( - ViewGroup contentView, int maxRows, int maxColumns) { - return new TileGridViewHolder(contentView, maxRows, maxColumns); - } - /** * Should be called every time one of the flags used to track initialization progress changes. * Finalizes initialization once all the preliminary steps are complete. @@ -618,13 +523,12 @@ mSearchProviderHasLogo = hasLogo; mSearchProviderIsGoogle = isGoogle; - updateTileGridPadding(); + updateTilesLayoutMargins(); // Hide or show the views above the tile grid as needed, including logo, search box, and // spacers. mSearchProviderLogoView.setVisibility(shouldShowLogo() ? View.VISIBLE : View.GONE); mSearchBoxCoordinator.setVisibility(mSearchProviderHasLogo); - updateTileGridPlaceholderVisibility(); onUrlFocusAnimationChanged(); @@ -632,22 +536,30 @@ } /** - * Updates the padding for the tile grid based on what is shown above it. + * Updates the margins for the tile grid based on what is shown above it. */ - private void updateTileGridPadding() { + private void updateTilesLayoutMargins() { // Set a bit more top padding on the tile grid if there is no logo. - int paddingTop = getResources().getDimensionPixelSize(shouldShowLogo() + MarginLayoutParams marginLayoutParams = + (MarginLayoutParams) mMvTilesContainerLayout.getLayoutParams(); + int marginTop = getResources().getDimensionPixelSize(shouldShowLogo() ? R.dimen.tile_grid_layout_padding_top : R.dimen.tile_grid_layout_no_logo_padding_top); - if (mSiteSectionViewHolder != null) { - mSiteSectionViewHolder.getItemView().setPadding( - 0, paddingTop, 0, mSiteSectionViewHolder.getItemView().getPaddingBottom()); - } else if (mMvTilesContainerLayout != null) { - MarginLayoutParams marginLayoutParams = - (MarginLayoutParams) mMvTilesContainerLayout.getLayoutParams(); - marginLayoutParams.topMargin = paddingTop; - marginLayoutParams.bottomMargin = - getResources().getDimensionPixelOffset(R.dimen.tile_grid_layout_bottom_margin); + int marginBottom = + getResources().getDimensionPixelOffset(R.dimen.tile_grid_layout_bottom_margin); + marginLayoutParams.topMargin = marginTop; + marginLayoutParams.bottomMargin = marginBottom; + + if (isScrollableMVTEnabled()) { + // Let mMvTilesContainerLayout attached to the edge of the screen. + setClipToPadding(false); + int lateralPaddingsForNTP = mActivity.getResources().getDimensionPixelSize( + R.dimen.ntp_header_lateral_paddings_v2); + marginLayoutParams.leftMargin = -lateralPaddingsForNTP; + marginLayoutParams.rightMargin = -lateralPaddingsForNTP; + } else { + ViewGroup.LayoutParams layoutParams = mMvTilesContainerLayout.getLayoutParams(); + layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT; } } @@ -858,45 +770,6 @@ mSnapshotTileGridChanged = false; } - /** - * Shows the most visited placeholder ("Nothing to see here") if there are no most visited - * items and there is no search provider logo. - */ - private void updateTileGridPlaceholderVisibility() { - // If scrollable MVT is enabled, the placeholder will be handled in {@link - // MostVisitedListMediator}. - if (isScrollableMVTEnabled()) return; - boolean showPlaceholder = - mTileGroup.hasReceivedData() && mTileGroup.isEmpty() && !mSearchProviderHasLogo; - - mNoSearchLogoSpacer.setVisibility( - (mSearchProviderHasLogo || showPlaceholder) ? View.GONE : View.INVISIBLE); - - mSiteSectionViewHolder.getItemView().setVisibility(showPlaceholder ? GONE : VISIBLE); - - if (showPlaceholder) { - if (mTileGridPlaceholder == null) { - ViewStub placeholderStub = findViewById(R.id.tile_grid_placeholder_stub); - mTileGridPlaceholder = placeholderStub.inflate(); - } - mTileGridPlaceholder.setVisibility(VISIBLE); - } else if (mTileGridPlaceholder != null) { - mTileGridPlaceholder.setVisibility(GONE); - } - } - - /** - * Determines The maximum number of tiles to try and fit in a row. On smaller screens, there - * may not be enough space to fit all of them. - */ - private int getMaxColumnsForMostVisitedTiles() { - return 4; - } - - private static int getTileTitleLines() { - return 1; - } - private boolean shouldShowLogo() { return mSearchProviderHasLogo; } @@ -926,39 +799,6 @@ })); } - // TileGroup.Observer interface. - - @Override - public void onTileDataChanged() { - mSiteSectionViewHolder.refreshData(); - mSnapshotTileGridChanged = true; - - // The page contents are initially hidden; otherwise they'll be drawn centered on the page - // before the tiles are available and then jump upwards to make space once the tiles are - // available. - if (getVisibility() != View.VISIBLE) setVisibility(View.VISIBLE); - } - - @Override - public void onTileCountChanged() { - // If the number of tile rows change while the URL bar is focused, the icons' - // position will be wrong. Schedule the translation to be updated. - if (mUrlFocusChangePercent == 1f) mTileCountChanged = true; - updateTileGridPlaceholderVisibility(); - } - - @Override - public void onTileIconChanged(Tile tile) { - mSiteSectionViewHolder.updateIconView(tile); - mSnapshotTileGridChanged = true; - } - - @Override - public void onTileOfflineBadgeVisibilityChanged(Tile tile) { - mSiteSectionViewHolder.updateOfflineBadge(tile); - mSnapshotTileGridChanged = true; - } - @Override public void onEnterVr() { mSearchBoxCoordinator.setVisibility(false); @@ -975,10 +815,6 @@ mCallbackController = null; } - if (mTileGroup != null) { - mTileGroup.destroy(); - } - VrModuleProvider.unregisterVrModeObserver(this); if (mSearchProviderLogoView != null) { @@ -1020,6 +856,11 @@ } } + @VisibleForTesting + MostVisitedTilesCoordinator getMostVisitedTilesCoordinatorForTesting() { + return mMostVisitedTilesCoordinator; + } + void maybeShowFeatureNotificationVoiceSearchIPH() { IPHCommandBuilder iphCommandBuilder = createIPHCommandBuilder(mActivity.getResources(), R.string.feature_notification_guide_tooltip_message_voice_search, @@ -1056,15 +897,23 @@ * Makes the Search Box and Logo as wide as Most Visited. */ private void unifyElementWidths() { - if (mSiteSectionView != null && mSiteSectionView.getVisibility() != GONE) { - final int width = mSiteSectionView.getMeasuredWidth() - mTileGridLayoutBleed; - measureExactly(getSearchBoxView(), width, getSearchBoxView().getMeasuredHeight()); - measureExactly( - mSearchProviderLogoView, width, mSearchProviderLogoView.getMeasuredHeight()); + if (mMvTilesContainerLayout.getVisibility() != GONE) { + if (!isScrollableMVTEnabled()) { + final int width = mMvTilesContainerLayout.getMeasuredWidth() - mTileGridLayoutBleed; + measureExactly(getSearchBoxView(), width, getSearchBoxView().getMeasuredHeight()); + measureExactly(mSearchProviderLogoView, width, + mSearchProviderLogoView.getMeasuredHeight()); - if (mExploreSectionView != null) { - measureExactly(mExploreSectionView, mSiteSectionView.getMeasuredWidth(), - mExploreSectionView.getMeasuredHeight()); + if (mExploreSectionView != null) { + measureExactly(mExploreSectionView, mMvTilesContainerLayout.getMeasuredWidth(), + mExploreSectionView.getMeasuredHeight()); + } + } else { + final int exploreWidth = getMeasuredWidth() - mTileGridLayoutBleed; + measureExactly( + getSearchBoxView(), exploreWidth, getSearchBoxView().getMeasuredHeight()); + measureExactly(mSearchProviderLogoView, exploreWidth, + mSearchProviderLogoView.getMeasuredHeight()); } } else if (mExploreSectionView != null) { final int exploreWidth = mExploreSectionView.getMeasuredWidth() - mTileGridLayoutBleed; @@ -1072,12 +921,6 @@ getSearchBoxView(), exploreWidth, getSearchBoxView().getMeasuredHeight()); measureExactly(mSearchProviderLogoView, exploreWidth, mSearchProviderLogoView.getMeasuredHeight()); - } else if (mMvTilesContainerLayout != null) { - final int exploreWidth = getMeasuredWidth() - mTileGridLayoutBleed; - measureExactly( - getSearchBoxView(), exploreWidth, getSearchBoxView().getMeasuredHeight()); - measureExactly(mSearchProviderLogoView, exploreWidth, - mSearchProviderLogoView.getMeasuredHeight()); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/ntp/OWNERS index b577522..b17c43f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/OWNERS
@@ -3,3 +3,6 @@ twellington@chromium.org per-file *Incognito*=file://chrome/browser/incognito/OWNERS + +# For Recent Tabs Page changes. +per-file *Recent*=ckitagawa@chromium.org
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadingListBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadingListBridge.java index c30998f6..f5f5d80d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadingListBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadingListBridge.java
@@ -8,10 +8,6 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.NativeMethods; import org.chromium.chrome.R; -import org.chromium.chrome.browser.bookmarks.BookmarkUtils; -import org.chromium.chrome.browser.flags.ChromeFeatureList; -import org.chromium.components.bookmarks.BookmarkId; -import org.chromium.components.bookmarks.BookmarkType; /** * Contains JNI methods to needed by read later feature. @@ -40,9 +36,7 @@ @CalledByNative private static void openReadingListPage() { - if (!ChromeFeatureList.isEnabled(ChromeFeatureList.READ_LATER)) return; - BookmarkUtils.showBookmarkManager( - null, new BookmarkId(0, BookmarkType.READING_LIST), /*isIncognito=*/false); + ReadingListUtils.showReadingList(/*isIncognito=*/false); } @NativeMethods
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadingListUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadingListUtils.java index 6fa04a3..73e5aba 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadingListUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadingListUtils.java
@@ -11,7 +11,6 @@ import org.chromium.base.Log; import org.chromium.chrome.browser.bookmarks.BookmarkBridge; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkModel; import org.chromium.chrome.browser.bookmarks.BookmarkUndoController; import org.chromium.chrome.browser.bookmarks.BookmarkUtils; @@ -19,6 +18,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.bookmarks.BookmarkType; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.embedder_support.util.UrlUtilities; @@ -51,7 +51,7 @@ BookmarkUndoController.createOneshotBookmarkUndoController( activity, bookmarkModel, snackbarManager); bookmarkModel.finishLoadingBookmarkModel(() -> { - BookmarkBridge.BookmarkItem bookmarkItem = + BookmarkItem bookmarkItem = bookmarkModel.getReadingListItem(currentTab.getOriginalUrl()); bookmarkModel.deleteBookmarks(bookmarkItem.getId()); }); @@ -158,6 +158,17 @@ sReadingListSupportedForTesting = supported; } + /** + * Opens the Reading list folder in the bookmark manager. + * + * @param isIncognito Whether the bookmark manager should open in incognito mode. + */ + public static void showReadingList(boolean isIncognito) { + if (!ReadingListFeatures.isReadingListEnabled()) return; + BookmarkUtils.showBookmarkManager( + null, new BookmarkId(0, BookmarkType.READING_LIST), /*isIncognito=*/isIncognito); + } + /** For cases where we don't want to mock the entire bookmarks save flow infra. */ public static void setSkipShowSaveFlowForTesting(Boolean skipShowSaveFlowForTesting) { sSkipShowSaveFlowForTesting = skipShowSaveFlowForTesting;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesCarouselLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesCarouselLayout.java index 6f106825a..ea48320 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesCarouselLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesCarouselLayout.java
@@ -9,13 +9,14 @@ import android.view.View; import android.widget.LinearLayout; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import org.chromium.chrome.browser.suggestions.SiteSuggestion; import org.chromium.components.browser_ui.widget.tile.TileView; /** - * The layout for the container of MV tiles on the Start surface. + * The most visited tiles carousel layout. */ public class MostVisitedTilesCarouselLayout extends LinearLayout { /** @@ -42,21 +43,6 @@ updateSingleTileViewEndMargin((TileView) getChildAt(childCount - 1), edgePadding); } - SuggestionsTileView findTileView(Tile tile) { - for (int i = 0; i < getChildCount(); i++) { - View tileView = getChildAt(i); - - assert tileView instanceof SuggestionsTileView : "Tiles must be SuggestionsTileView"; - - SuggestionsTileView suggestionsTileView = (SuggestionsTileView) tileView; - - if (tile.getUrl().equals(suggestionsTileView.getUrl())) { - return (SuggestionsTileView) tileView; - } - } - return null; - } - void destroy() { for (int i = 0; i < getChildCount(); i++) { View tileView = getChildAt(i); @@ -82,6 +68,7 @@ } } + @Nullable @VisibleForTesting public SuggestionsTileView findTileViewForTesting(SiteSuggestion suggestion) { int childCount = getChildCount();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesCoordinator.java index 04b5a73..4fc5381 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesCoordinator.java
@@ -8,6 +8,10 @@ import android.content.res.Configuration; import android.view.View; import android.view.ViewGroup; +import android.view.ViewStub; + +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import org.chromium.chrome.R; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; @@ -18,7 +22,6 @@ import org.chromium.chrome.browser.suggestions.SuggestionsConfig; import org.chromium.chrome.browser.suggestions.SuggestionsDependencyFactory; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate; -import org.chromium.chrome.browser.suggestions.tile.MostVisitedTilesViewBinder.ViewHolder; import org.chromium.chrome.browser.ui.native_page.TouchEnabledDelegate; import org.chromium.components.browser_ui.widget.displaystyle.UiConfig; import org.chromium.ui.base.DeviceFormFactor; @@ -51,30 +54,52 @@ * @param mvTilesContainerLayout The container view of most visited tiles layout. * @param windowAndroid The current {@link WindowAndroid} * @param shouldShowSkeletonUIPreNative Whether to show the background icon for pre-native - * surface. + * surface. + * @param isScrollableMVTEnabled Whether scrollable MVT is enabled. If true {@link + * MostVisitedTilesCarouselLayout} is used; if false {@link + * MostVisitedTilesGridLayout} is used. + * @param maxRows The maximum number of rows to display. This will only be used for {@link + * MostVisitedTilesGridLayout}. + * @param maxColumns The maximum number of columns to display. This will only be used for {@link + * MostVisitedTilesGridLayout}. + * @param snapshotTileGridChangedRunnable The runnable called when the snapshot tile grid is + * changed. + * @param tileCountChangedRunnable The runnable called when the tile count is changed. */ public MostVisitedTilesCoordinator(Activity activity, ActivityLifecycleDispatcher activityLifecycleDispatcher, View mvTilesContainerLayout, - WindowAndroid windowAndroid, boolean shouldShowSkeletonUIPreNative) { + WindowAndroid windowAndroid, boolean shouldShowSkeletonUIPreNative, + boolean isScrollableMVTEnabled, int maxRows, int maxColumns, + @Nullable Runnable snapshotTileGridChangedRunnable, + @Nullable Runnable tileCountChangedRunnable) { mActivity = activity; mActivityLifecycleDispatcher = activityLifecycleDispatcher; mWindowAndroid = windowAndroid; - MostVisitedTilesCarouselLayout mvTilesLayout = - mvTilesContainerLayout.findViewById(R.id.mv_tiles_layout); - mUiConfig = new UiConfig(mvTilesLayout); + ((ViewStub) mvTilesContainerLayout.findViewById( + isScrollableMVTEnabled ? R.id.mv_tiles_carousel_stub : R.id.mv_tiles_grid_stub)) + .inflate(); + ViewGroup tilesLayout = mvTilesContainerLayout.findViewById(R.id.mv_tiles_layout); + assert (tilesLayout != null); + if (!isScrollableMVTEnabled) { + ((MostVisitedTilesGridLayout) tilesLayout).setMaxColumns(maxColumns); + ((MostVisitedTilesGridLayout) tilesLayout).setMaxRows(maxRows); + } + + mUiConfig = new UiConfig(tilesLayout); PropertyModel propertyModel = new PropertyModel(MostVisitedTilesProperties.ALL_KEYS); mModelChangeProcessor = PropertyModelChangeProcessor.create(propertyModel, - new ViewHolder(mvTilesContainerLayout, mvTilesLayout), + new MostVisitedTilesViewBinder.ViewHolder(mvTilesContainerLayout, tilesLayout), MostVisitedTilesViewBinder::bind); - mRenderer = new TileRenderer(mActivity, SuggestionsConfig.TileStyle.MODERN, TITLE_LINES, null); - boolean isTablet = DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity); - - mMediator = new MostVisitedTilesMediator(activity.getResources(), mvTilesContainerLayout, - mRenderer, propertyModel, shouldShowSkeletonUIPreNative, isTablet); + mMediator = new MostVisitedTilesMediator(activity.getResources(), tilesLayout, + mvTilesContainerLayout.findViewById(R.id.tile_grid_placeholder_stub), mRenderer, + propertyModel, shouldShowSkeletonUIPreNative && isScrollableMVTEnabled, + isScrollableMVTEnabled, + DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity), + snapshotTileGridChangedRunnable, tileCountChangedRunnable); } /** @@ -126,8 +151,7 @@ } public void onSwitchToForeground() { - assert !isMVTilesCleanedUp(); - mMediator.onSwitchToForeground(); + if (!isMVTilesCleanedUp()) mMediator.onSwitchToForeground(); } /* ConfigurationChangedObserver implementation. */ @@ -136,4 +160,9 @@ mMediator.onConfigurationChanged(); mUiConfig.updateDisplayStyle(); } + + @VisibleForTesting + public void onTemplateURLServiceChangedForTesting() { + mMediator.onTemplateURLServiceChanged(); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesGridLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesGridLayout.java index 0a5921d..1ce04af 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesGridLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesGridLayout.java
@@ -167,7 +167,7 @@ } @Nullable - public SuggestionsTileView getTileView(SiteSuggestion suggestion) { + public SuggestionsTileView findTileViewForTesting(SiteSuggestion suggestion) { int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { SuggestionsTileView tileView = (SuggestionsTileView) getChildAt(i);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesMediator.java index 8d74c558..e86fefb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesMediator.java
@@ -11,14 +11,17 @@ import android.content.res.Configuration; import android.content.res.Resources; -import android.view.View; +import android.view.ViewGroup; import android.view.ViewStub; +import androidx.annotation.Nullable; + import org.chromium.base.Log; import org.chromium.chrome.R; import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; +import org.chromium.chrome.browser.suggestions.SiteSuggestion; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate; import org.chromium.chrome.browser.suggestions.mostvisited.MostVisitedSitesMetadataUtils; import org.chromium.components.search_engines.TemplateUrlService.TemplateUrlServiceObserver; @@ -28,7 +31,9 @@ import java.util.List; /** - * Mediator for handling {@link MostVisitedTilesCarouselLayout}-related logic. + * Mediator for handling {@link MostVisitedTilesCarouselLayout} when {@link + * org.chromium.chrome.browser.flags.ChromeFeatureList#SHOW_SCROLLABLE_MVT_ON_NTP_ANDROID} is + * enabled or {@link MostVisitedTilesGridLayout} when the feature is disabled -related logic. */ public class MostVisitedTilesMediator implements TileGroup.Observer, TemplateUrlServiceObserver { private static final String TAG = "TopSites"; @@ -37,34 +42,42 @@ private static final int MAX_RESULTS = 12; private final Resources mResources; - private final MostVisitedTilesCarouselLayout mMvTilesLayout; + private final ViewGroup mMvTilesLayout; private final ViewStub mNoMvPlaceholderStub; private final PropertyModel mModel; + private final boolean mIsScrollableMVTEnabled; private final boolean mIsTablet; private final int mTileViewLandscapePadding; private final int mTileViewPortraitEdgePadding; + private final Runnable mSnapshotTileGridChangedRunnable; + private final Runnable mTileCountChangedRunnable; private int mTileViewPortraitIntervalPadding; private TileRenderer mRenderer; private TileGroup mTileGroup; private boolean mInitializationComplete; - public MostVisitedTilesMediator(Resources resources, View mvTilesContainerLayout, - TileRenderer renderer, PropertyModel propertyModel, - boolean shouldShowSkeletonUIPreNative, boolean isTablet) { + public MostVisitedTilesMediator(Resources resources, ViewGroup mvTilesLayout, + ViewStub noMvPlaceholderStub, TileRenderer renderer, PropertyModel propertyModel, + boolean shouldShowSkeletonUIPreNative, boolean isScrollableMVTEnabled, boolean isTablet, + @Nullable Runnable snapshotTileGridChangedRunnable, + @Nullable Runnable tileCountChangedRunnable) { mResources = resources; mRenderer = renderer; mModel = propertyModel; + mIsScrollableMVTEnabled = isScrollableMVTEnabled; mIsTablet = isTablet; - mMvTilesLayout = mvTilesContainerLayout.findViewById(R.id.mv_tiles_layout); - mNoMvPlaceholderStub = mvTilesContainerLayout.findViewById(R.id.tile_grid_placeholder_stub); + mSnapshotTileGridChangedRunnable = snapshotTileGridChangedRunnable; + mTileCountChangedRunnable = tileCountChangedRunnable; + mMvTilesLayout = mvTilesLayout; + mNoMvPlaceholderStub = noMvPlaceholderStub; mTileViewLandscapePadding = mResources.getDimensionPixelSize(R.dimen.tile_view_padding_landscape); mTileViewPortraitEdgePadding = mResources.getDimensionPixelSize(R.dimen.tile_view_padding_edge_portrait); - maybeSetPortraitIntervalPaddings(); + maybeSetPortraitIntervalPaddingsForCarousel(); if (shouldShowSkeletonUIPreNative) maybeShowMvTilesPreNative(); } @@ -100,34 +113,41 @@ mRenderer.renderTileSection(mTileGroup.getTileSections().get(TileSectionType.PERSONALIZED), mMvTilesLayout, mTileGroup.getTileSetupDelegate()); mTileGroup.notifyTilesRendered(); - updateTilesViewLayout(); + updateTilesViewForCarouselLayout(); + if (mSnapshotTileGridChangedRunnable != null) mSnapshotTileGridChangedRunnable.run(); MostVisitedSitesMetadataUtils.getInstance().saveSuggestionListsToFile( mTileGroup.getTileSections().get(TileSectionType.PERSONALIZED)); } @Override public void onTileCountChanged() { + if (mTileCountChangedRunnable != null) mTileCountChangedRunnable.run(); updateTileGridPlaceholderVisibility(); } @Override public void onTileIconChanged(Tile tile) { updateTileIcon(tile); + if (mSnapshotTileGridChangedRunnable != null) mSnapshotTileGridChangedRunnable.run(); } @Override public void onTileOfflineBadgeVisibilityChanged(Tile tile) { updateOfflineBadge(tile); + if (mSnapshotTileGridChangedRunnable != null) mSnapshotTileGridChangedRunnable.run(); } public void onConfigurationChanged() { - maybeSetPortraitIntervalPaddings(); - updateTilesViewLayout(); + maybeSetPortraitIntervalPaddingsForCarousel(); + updateTilesViewForCarouselLayout(); } public void destroy() { - if (mMvTilesLayout != null) mMvTilesLayout.destroy(); + if (mMvTilesLayout != null && mIsScrollableMVTEnabled) { + ((MostVisitedTilesCarouselLayout) mMvTilesLayout).destroy(); + } + if (mTileGroup != null) { mTileGroup.destroy(); mTileGroup = null; @@ -153,30 +173,38 @@ MostVisitedSitesMetadataUtils.restoreFileToSuggestionListsOnUiThread(); if (tiles == null) return; mRenderer.renderTileSection(tiles, mMvTilesLayout, null); - updateTilesViewLayout(); + updateTilesViewForCarouselLayout(); } catch (IOException e) { Log.i(TAG, "No cached MV tiles file."); } } private void updateTileIcon(Tile tile) { - SuggestionsTileView tileView = findTileView(tile); + SuggestionsTileView tileView = findTileView(tile.getData()); if (tileView != null) { tileView.renderIcon(tile); } } private void updateOfflineBadge(Tile tile) { - SuggestionsTileView tileView = findTileView(tile); + SuggestionsTileView tileView = findTileView(tile.getData()); if (tileView != null) tileView.renderOfflineBadge(tile); } - private SuggestionsTileView findTileView(Tile tile) { - return mMvTilesLayout.findTileView(tile); + private SuggestionsTileView findTileView(SiteSuggestion data) { + int childCount = mMvTilesLayout.getChildCount(); + for (int i = 0; i < childCount; i++) { + SuggestionsTileView tileView = (SuggestionsTileView) mMvTilesLayout.getChildAt(i); + if (data.equals(tileView.getData())) return tileView; + } + return null; } - private void maybeSetPortraitIntervalPaddings() { - if (mResources.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE + private void maybeSetPortraitIntervalPaddingsForCarousel() { + // If it's gird layout (mIsScrollableMVTEnabled is false), the paddings are handled in + // {@link MostVisitedTilesGridLayout} + if (!mIsScrollableMVTEnabled + || mResources.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE || mTileViewPortraitIntervalPadding != 0) { return; } @@ -192,8 +220,10 @@ } } - private void updateTilesViewLayout() { - if (mMvTilesLayout.getChildCount() < 1) return; + private void updateTilesViewForCarouselLayout() { + // If it's gird layout (mIsScrollableMVTEnabled is false), the paddings are handled in + // {@link MostVisitedTilesGridLayout} + if (!mIsScrollableMVTEnabled || mMvTilesLayout.getChildCount() < 1) return; if (mResources.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { mModel.set(HORIZONTAL_EDGE_PADDINGS, mTileViewLandscapePadding);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesViewBinder.java index d20097c..c926af7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesViewBinder.java
@@ -11,6 +11,7 @@ import static org.chromium.chrome.browser.suggestions.tile.MostVisitedTilesProperties.PLACEHOLDER_VIEW; import android.view.View; +import android.view.ViewGroup; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; @@ -22,9 +23,9 @@ */ public static class ViewHolder { public final View mvContainerLayout; - public final MostVisitedTilesCarouselLayout mvTilesLayout; + public final ViewGroup mvTilesLayout; - ViewHolder(View mvContainerLayout, MostVisitedTilesCarouselLayout mvTilesLayout) { + ViewHolder(View mvContainerLayout, ViewGroup mvTilesLayout) { this.mvContainerLayout = mvContainerLayout; this.mvTilesLayout = mvTilesLayout; } @@ -41,9 +42,13 @@ model.get(PLACEHOLDER_VIEW) .setVisibility(model.get(IS_MVT_LAYOUT_VISIBLE) ? View.GONE : View.VISIBLE); } else if (HORIZONTAL_INTERVAL_PADDINGS == propertyKey) { - viewHolder.mvTilesLayout.setIntervalPaddings(model.get(HORIZONTAL_INTERVAL_PADDINGS)); + assert viewHolder.mvTilesLayout instanceof MostVisitedTilesCarouselLayout; + ((MostVisitedTilesCarouselLayout) viewHolder.mvTilesLayout) + .setIntervalPaddings(model.get(HORIZONTAL_INTERVAL_PADDINGS)); } else if (HORIZONTAL_EDGE_PADDINGS == propertyKey) { - viewHolder.mvTilesLayout.setEdgePaddings(model.get(HORIZONTAL_EDGE_PADDINGS)); + assert viewHolder.mvTilesLayout instanceof MostVisitedTilesCarouselLayout; + ((MostVisitedTilesCarouselLayout) viewHolder.mvTilesLayout) + .setEdgePaddings(model.get(HORIZONTAL_EDGE_PADDINGS)); } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/SiteSectionViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/SiteSectionViewHolder.java deleted file mode 100644 index 2225499..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/SiteSectionViewHolder.java +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.suggestions.tile; - -import android.view.View; - -import androidx.annotation.CallSuper; -import androidx.annotation.Nullable; - -import org.chromium.chrome.browser.suggestions.SiteSuggestion; - -/** - * Describes a portion of UI responsible for rendering a group of sites. It abstracts general tasks - * related to initialising and updating this UI. - */ -public abstract class SiteSectionViewHolder { - protected TileGroup mTileGroup; - protected TileRenderer mTileRenderer; - private final View mItemView; - - /** - * Constructs a {@link SiteSectionViewHolder} used to display tiles in both NTP and Chrome Home. - * - * @param itemView The {@link View} for this item - */ - public SiteSectionViewHolder(View itemView) { - this.mItemView = itemView; - } - - /** Returns the view held by this View Holder. */ - public View getItemView() { - return mItemView; - } - - /** Initialise the view, letting it know the data it will have to display. */ - @CallSuper - public void bindDataSource(TileGroup tileGroup, TileRenderer tileRenderer) { - mTileGroup = tileGroup; - mTileRenderer = tileRenderer; - } - - /** - * Sets a new icon on the child view with a matching site. - * @param tile The tile that holds the data to populate the tile view. - */ - public void updateIconView(Tile tile) { - SuggestionsTileView tileView = findTileView(tile.getData()); - if (tileView != null) tileView.renderIcon(tile); - } - - /** - * Updates the visibility of the offline badge on the child view with a matching site. - * @param tile The tile that holds the data to populate the tile view. - */ - public void updateOfflineBadge(Tile tile) { - SuggestionsTileView tileView = findTileView(tile.getData()); - if (tileView != null) tileView.renderOfflineBadge(tile); - } - - /** Clears the current data and displays the current state of the model. */ - public abstract void refreshData(); - - @Nullable - public abstract SuggestionsTileView findTileView(SiteSuggestion data); -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGridViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGridViewHolder.java deleted file mode 100644 index 3aab490..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGridViewHolder.java +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.suggestions.tile; - -import android.view.ViewGroup; - -import org.chromium.chrome.browser.suggestions.SiteSuggestion; - -import java.util.List; -/** - * A {@link SiteSectionViewHolder} specialised in displaying sites as a simple grid of tiles, - * through - * {@link MostVisitedTilesGridLayout}. - */ -public class TileGridViewHolder extends SiteSectionViewHolder { - private final MostVisitedTilesGridLayout mSectionView; - - public TileGridViewHolder(ViewGroup view, int maxRows, int maxColumns) { - super(view); - - mSectionView = (MostVisitedTilesGridLayout) view; - mSectionView.setMaxRows(maxRows); - mSectionView.setMaxColumns(maxColumns); - } - - @Override - public void refreshData() { - assert mTileGroup.getTileSections().size() == 1; - List<Tile> tiles = mTileGroup.getTileSections().get(TileSectionType.PERSONALIZED); - assert tiles != null; - - mTileRenderer.renderTileSection(tiles, mSectionView, mTileGroup.getTileSetupDelegate()); - mTileGroup.notifyTilesRendered(); - } - - @Override - public SuggestionsTileView findTileView(SiteSuggestion data) { - return mSectionView.getTileView(data); - } - - @Override - public void bindDataSource(TileGroup tileGroup, TileRenderer tileRenderer) { - super.bindDataSource(tileGroup, tileRenderer); - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java index 7ccd26ee..7cd4ccc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
@@ -568,18 +568,24 @@ @Override public void reload() { + NativePage nativePage = getNativePage(); + if (nativePage != null) { + nativePage.reload(); + return; + } + // TODO(dtrainor): Should we try to rebuild the ContentView if it's frozen? if (OfflinePageUtils.isOfflinePage(this)) { // If current page is an offline page, reload it with custom behavior defined in extra // header respected. OfflinePageUtils.reload(getWebContents(), /*loadUrlDelegate=*/new OfflinePageUtils.TabOfflinePageLoadUrlDelegate(this)); - } else { - if (getWebContents() != null) { - switchUserAgentIfNeeded(); - getWebContents().getNavigationController().reload(true); - } + return; } + + if (getWebContents() == null) return; + switchUserAgentIfNeeded(); + getWebContents().getNavigationController().reload(true); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/OWNERS new file mode 100644 index 0000000..9204398c --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/OWNERS
@@ -0,0 +1,2 @@ +ckitagawa@chromium.org +dtrainor@chromium.org
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java index 757f1c4..82a82811 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
@@ -468,6 +468,7 @@ case TabLaunchType.FROM_LAUNCHER_SHORTCUT: case TabLaunchType.FROM_LAUNCH_NEW_INCOGNITO_TAB: case TabLaunchType.FROM_APP_WIDGET: + case TabLaunchType.FROM_READING_LIST: transition = PageTransition.AUTO_TOPLEVEL; break; case TabLaunchType.FROM_LONGPRESS_FOREGROUND:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/OWNERS new file mode 100644 index 0000000..9de2bf41 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/OWNERS
@@ -0,0 +1 @@ +file://chrome/browser/tabmodel/OWNERS
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java index 9be0e867..a0abb1f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
@@ -292,7 +292,7 @@ } @Override - public Tab getNextTabIfClosed(int id) { + public Tab getNextTabIfClosed(int id, boolean uponExit) { Tab tabToClose = TabModelUtils.getTabById(this, id); Tab currentTab = TabModelUtils.getCurrentTab(this); if (tabToClose == null) return currentTab; @@ -301,9 +301,14 @@ Tab adjacentTab = getTabAt((closingTabIndex == 0) ? 1 : closingTabIndex - 1); Tab parentTab = findTabInAllTabModels(CriticalPersistedTabData.from(tabToClose).getParentId()); + Tab nextMostRecentTab = null; + if (uponExit) { + nextMostRecentTab = TabModelUtils.getMostRecentTab(this, id); + } // Determine which tab to select next according to these rules: // * If closing a background tab, keep the current tab selected. + // * Otherwise, if closing the tab upon exit select the next most recent tab. // * Otherwise, if not in overview mode, select the parent tab if it exists. // * Otherwise, select an adjacent tab if one exists. // * Otherwise, if closing the last incognito tab, select the current normal tab. @@ -313,6 +318,8 @@ nextTab = TabModelUtils.getCurrentTab(mModelDelegate.getCurrentModel()); } else if (tabToClose != currentTab && currentTab != null && !currentTab.isClosing()) { nextTab = currentTab; + } else if (nextMostRecentTab != null && !nextMostRecentTab.isClosing()) { + nextTab = nextMostRecentTab; } else if (parentTab != null && !parentTab.isClosing() && mNextTabPolicySupplier.get() == NextTabPolicy.HIERARCHICAL) { nextTab = parentTab; @@ -598,8 +605,9 @@ Tab currentTabInModel = TabModelUtils.getCurrentTab(this); Tab adjacentTabInModel = getTabAt(closingTabIndex == 0 ? 1 : closingTabIndex - 1); - Tab nextTab = - recommendedNextTab == null ? getNextTabIfClosed(closingTabId) : recommendedNextTab; + Tab nextTab = recommendedNextTab == null + ? getNextTabIfClosed(closingTabId, /*uponExit=*/false) + : recommendedNextTab; // TODO(dtrainor): Update the list of undoable tabs instead of committing it. if (updatePendingTabClosureManager) commitAllTabClosures();
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 25bf6a7..0268b36c 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -37,6 +37,10 @@ chrome_test_java_sources += [ "javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java" ] } +if (enable_supervised_users) { + chrome_java_sources += [ "java/src/org/chromium/chrome/browser/supervised_user/ChildAccountService.java" ] +} + chrome_junit_test_java_sources += feed_junit_test_java_sources chrome_test_java_sources += feed_test_java_sources chrome_test_java_sources += start_surface_test_java_sources
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java index bc8e8a3..a3997a2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java
@@ -20,7 +20,6 @@ import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RequiresRestart; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.power_bookmarks.PowerBookmarkMeta; import org.chromium.chrome.browser.power_bookmarks.PowerBookmarkType; @@ -32,6 +31,7 @@ import org.chromium.chrome.test.util.BookmarkTestUtil; import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.bookmarks.BookmarkType; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.url.GURL;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkEditTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkEditTest.java index c63f70e..b3a9cb21 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkEditTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkEditTest.java
@@ -28,12 +28,12 @@ import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.Feature; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.test.ChromeBrowserTestRule; import org.chromium.chrome.test.util.BookmarkTestUtil; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.url.GURL;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkModelTest.java index 6eb00e4f..0643ed09 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkModelTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkModelTest.java
@@ -17,11 +17,11 @@ import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.Feature; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.test.ChromeBrowserTestRule; import org.chromium.chrome.test.util.BookmarkTestUtil; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.url.GURL;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java index 5163bb5..56d3da6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java
@@ -64,7 +64,6 @@ import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.app.metrics.LaunchCauseMetrics; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -79,6 +78,7 @@ import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.read_later.ReadingListUtils; import org.chromium.chrome.browser.sync.SyncService; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; @@ -92,6 +92,7 @@ import org.chromium.chrome.test.util.MenuUtils; import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.bookmarks.BookmarkType; import org.chromium.components.browser_ui.widget.RecyclerViewTestUtils; import org.chromium.components.browser_ui.widget.listmenu.ListMenuButton; @@ -1250,7 +1251,8 @@ Assert.assertFalse(customTabIntent.hasExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB)); TestThreadUtils.runOnUiThreadBlocking( () -> { Assert.assertTrue(activity.getActivityTab().getUrl().equals(mTestUrlA)); }); - activity.finish(); + pressBack(); + onView(withText("Reading list")).check(matches(isDisplayed())); } @Test @@ -1280,7 +1282,44 @@ Criteria.checkThat(activityTab, Matchers.notNullValue()); Criteria.checkThat(activityTab.getUrl(), Matchers.notNullValue()); Criteria.checkThat(activityTab.getUrl(), Matchers.is(mTestUrlA)); + Criteria.checkThat(activityTab.isIncognito(), Matchers.is(false)); }); + pressBack(); + onView(withText("Reading list")).check(matches(isDisplayed())); + } + + @Test + @SmallTest + @Features.EnableFeatures({ChromeFeatureList.READ_LATER + "<Study"}) + @CommandLineFlags. + Add({"force-fieldtrials=Study/Group", "force-fieldtrial-params=Study.Group:use_cct/false"}) + public void testReadingListOpenInIncognitoTab() throws Exception { + addReadingListBookmark(TEST_PAGE_TITLE_GOOGLE, mTestUrlA); + BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.NO_PROMO); + mActivityTestRule.loadUrlInNewTab("about:blank", /*incognito=*/true); + openBookmarkManager(); + CriteriaHelper.pollUiThread(() -> mBookmarkModel.getReadingListItem(mTestUrlA) != null); + + // Open the "Reading list" folder. + TestThreadUtils.runOnUiThreadBlocking( + () -> mManager.openFolder(mBookmarkModel.getRootFolderId())); + onView(withText("Reading list")).perform(click()); + RecyclerViewTestUtils.waitForStableRecyclerView(mItemsContainer); + View readingListRow = mItemsContainer.findViewHolderForAdapterPosition(1).itemView; + Assert.assertEquals("The 2nd view should be reading list.", BookmarkType.READING_LIST, + getIdByPosition(1).getType()); + TestThreadUtils.runOnUiThreadBlocking(() -> TouchCommon.singleClickView(readingListRow)); + + ChromeTabbedActivity activity = waitForTabbedActivity(); + CriteriaHelper.pollUiThread(() -> { + Tab activityTab = activity.getActivityTab(); + Criteria.checkThat(activityTab, Matchers.notNullValue()); + Criteria.checkThat(activityTab.getUrl(), Matchers.notNullValue()); + Criteria.checkThat(activityTab.getUrl(), Matchers.is(mTestUrlA)); + Criteria.checkThat(activityTab.isIncognito(), Matchers.is(true)); + }); + pressBack(); + onView(withText("Reading list")).check(matches(isDisplayed())); } @Test @@ -1426,8 +1465,7 @@ // Verify that bookmark 1 is editable (so more button can be triggered) but not movable. BookmarkId partnerBookmarkId1 = getReorderAdapter().getIdByPosition(0); TestThreadUtils.runOnUiThreadBlocking(() -> { - BookmarkBridge.BookmarkItem partnerBookmarkItem1 = - mBookmarkModel.getBookmarkById(partnerBookmarkId1); + BookmarkItem partnerBookmarkItem1 = mBookmarkModel.getBookmarkById(partnerBookmarkId1); partnerBookmarkItem1.forceEditableForTesting(); Assert.assertEquals("Incorrect bookmark type for item 1", BookmarkType.PARTNER, partnerBookmarkId1.getType()); @@ -1447,8 +1485,7 @@ // Verify that bookmark 2 is not movable. BookmarkId partnerBookmarkId2 = getReorderAdapter().getIdByPosition(1); TestThreadUtils.runOnUiThreadBlocking(() -> { - BookmarkBridge.BookmarkItem partnerBookmarkItem2 = - mBookmarkModel.getBookmarkById(partnerBookmarkId2); + BookmarkItem partnerBookmarkItem2 = mBookmarkModel.getBookmarkById(partnerBookmarkId2); partnerBookmarkItem2.forceEditableForTesting(); Assert.assertEquals("Incorrect bookmark type for item 2", BookmarkType.PARTNER, partnerBookmarkId2.getType()); @@ -1831,17 +1868,12 @@ BookmarkTestUtil.waitForBookmarkModelLoaded(); if (mActivityTestRule.getActivity().isTablet()) { - TestThreadUtils.runOnUiThreadBlocking(() -> { - BookmarkUtils.showBookmarkManager( - null, new BookmarkId(0, BookmarkType.READING_LIST), /*isIncognito=*/false); - }); + TestThreadUtils.runOnUiThreadBlocking( + () -> ReadingListUtils.showReadingList(/*isIncognito=*/false)); } else { mBookmarkActivity = ApplicationTestUtils.waitForActivityWithClass( - BookmarkActivity.class, Stage.CREATED, () -> { - BookmarkUtils.showBookmarkManager(null, - new BookmarkId(0, BookmarkType.READING_LIST), - /*isIncognito=*/false); - }); + BookmarkActivity.class, Stage.CREATED, + () -> ReadingListUtils.showReadingList(/*isIncognito=*/false)); } onView(withText("Reading list")).check(matches(isDisplayed()));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchCriticalTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchCriticalTest.java index 277a728d..5addbd8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchCriticalTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchCriticalTest.java
@@ -41,15 +41,6 @@ @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) @Batch(Batch.PER_CLASS) public class ContextualSearchCriticalTest extends ContextualSearchInstrumentationBase { - /** - * Fakes navigation of the Content View to the URL that was previously requested. - * @param isFailure whether the request resulted in a failure. - */ - private void fakeContentViewDidNavigate(boolean isFailure) { - String url = mFakeServer.getLoadedUrl(); - mManager.getOverlayContentDelegate().onMainFrameNavigation(url, false, isFailure, false); - } - //============================================================================================ // Test Cases //============================================================================================
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java index f747c69..f40854dc 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java
@@ -373,7 +373,7 @@ private SelectionClient mContextualSearchClient; private LayoutManagerImpl mLayoutManager; - private ActivityMonitor mActivityMonitor; + protected ActivityMonitor mActivityMonitor; protected ContextualSearchSelectionController mSelectionController; private ContextualSearchInstrumentationTestHost mTestHost; @@ -605,14 +605,14 @@ } } - private interface ThrowingRunnable { + protected interface ThrowingRunnable { void run() throws TimeoutException; } // Panel interactions are flaky, see crbug.com/635661. Rather than adding a long delay to // each test, we can retry failures. When trying to make the panel peak, we may also have to // clear the selection before trying again. - private void retryPanelBarInteractions(ThrowingRunnable r, boolean clearSelection) + protected void retryPanelBarInteractions(ThrowingRunnable r, boolean clearSelection) throws AssertionError, TimeoutException { int tries = 0; boolean success = false; @@ -813,7 +813,7 @@ * @param nodeId The id of the node to be tapped. * @param isResolveExpected Whether a resolve is expected or not. Enforce by asserting. */ - private FakeResolveSearch simulateResolvableSearchAndAssertResolveAndPreload(String nodeId, + protected FakeResolveSearch simulateResolvableSearchAndAssertResolveAndPreload(String nodeId, boolean isResolveExpected) throws InterruptedException, TimeoutException { FakeResolveSearch search = mFakeServer.getFakeResolveSearch(nodeId); assertNotNull("Could not find FakeResolveSearch for node ID:" + nodeId, search); @@ -984,8 +984,15 @@ void assertClosedPanelResolve() {} //============================================================================================ - // Assertions for different states - //============================================================================================ + + /** + * Fakes navigation of the Content View to the URL that was previously requested. + * @param isFailure whether the request resulted in a failure. + */ + protected void fakeContentViewDidNavigate(boolean isFailure) { + String url = mFakeServer.getLoadedUrl(); + mManager.getOverlayContentDelegate().onMainFrameNavigation(url, false, isFailure, false); + } /** * Simulates a click on the given word node. Waits for the bar to peek. TODO(donnd): rename to @@ -1164,6 +1171,14 @@ } /** + * Asserts that a Search Term has been requested. + * @param isExactResolve Whether the Resolve request must be exact (non-expanding). + */ + protected void assertExactResolve(boolean isExactResolve) { + Assert.assertEquals(isExactResolve, mFakeServer.getIsExactResolve()); + } + + /** * Waits for the Search Panel (the Search Bar) to peek up from the bottom, and asserts that it * did peek. */ @@ -1314,6 +1329,13 @@ } /** + * Flings the panel up to its expanded state. + */ + protected void flingPanelUp() { + fling(0.5f, 0.95f, 0.5f, 0.55f, 1000); + } + + /** * Swipes the panel down to its peeked state. */ protected void swipePanelDown() { @@ -1356,6 +1378,28 @@ } /** + * Click various places to cause the panel to show, expand, then close. + */ + protected void clickToExpandAndClosePanel() throws TimeoutException { + clickWordNode("states"); + tapBarToExpandAndClosePanel(); + waitForSelectionEmpty(); + } + + /** + * Simple sequence useful for checking if a Search Request is prefetched. + * Resets the fake server and clicks near to cause a search, then closes the panel, + * which takes us back to the starting state except that the fake server knows + * if a prefetch occurred. + */ + protected void clickToTriggerPrefetch() throws Exception { + mFakeServer.reset(); + simulateResolveSearch("search"); + closePanel(); + waitForPanelToCloseAndSelectionEmpty(); + } + + /** * Tap on the peeking Bar to expand the panel, then close it. */ private void tapBarToExpandAndClosePanel() throws TimeoutException { @@ -1367,7 +1411,7 @@ * Generate a click in the middle of panel's bar. TODO(donnd): Replace this method with * panelBarClick since this appears to be unreliable. */ - private void clickPanelBar() { + protected void clickPanelBar() { View root = sActivityTestRule.getActivity().getWindow().getDecorView().getRootView(); float tapX = ((mPanel.getOffsetX() + mPanel.getWidth()) / 2f) * mDpToPx; float tapY = (mPanel.getOffsetY() + (mPanel.getBarContainerHeight() / 2f)) * mDpToPx; @@ -1419,6 +1463,26 @@ } /** + * Fakes a response to the Resolve request. + */ + protected void fakeAResponse() { + fakeResponse(false, 200, "states", "United States Intelligence", "alternate-term", false); + waitForPanelToPeek(); + assertLoadedLowPriorityUrl(); + assertContainsParameters("states", "alternate-term"); + } + + /** + * Force the Panel to handle a click on open-in-a-new-tab icon. + */ + protected void forceOpenTabIconClick() { + InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + mPanel.handleBarClick(mPanel.getOpenTabIconX() + mPanel.getOpenTabIconDimension() / 2, + mPanel.getBarHeight() / 2); + }); + } + + /** * Force the Panel to close. */ protected void closePanel() { @@ -1446,7 +1510,7 @@ /** * @return The value of the given logged feature, or {@code null} if not logged. */ - private Object loggedToRanker(@ContextualSearchInteractionRecorder.Feature int feature) { + protected Object loggedToRanker(@ContextualSearchInteractionRecorder.Feature int feature) { return getRankerLogger().getFeaturesLogged().get(feature); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java index adfeeec..9ae6cf9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -4,8 +4,6 @@ package org.chromium.chrome.browser.contextualsearch; -import static org.junit.Assert.assertNotNull; - import static org.chromium.base.test.util.CriteriaHelper.DEFAULT_POLLING_INTERVAL; import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE; import static org.chromium.chrome.browser.multiwindow.MultiWindowTestHelper.waitForSecondChromeTabbedActivity; @@ -16,32 +14,23 @@ import android.app.Instrumentation.ActivityMonitor; import android.content.Intent; import android.content.IntentFilter; -import android.graphics.Point; import android.os.Build; -import android.os.SystemClock; import android.support.test.InstrumentationRegistry; import android.text.TextUtils; import android.view.View; -import android.view.ViewConfiguration; -import androidx.annotation.IntDef; import androidx.test.filters.LargeTest; import androidx.test.filters.SmallTest; import com.google.common.collect.ImmutableMap; import org.hamcrest.Matchers; -import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.chromium.base.FeatureList; -import org.chromium.base.Log; -import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.params.ParameterAnnotations; import org.chromium.base.test.params.ParameterProvider; @@ -63,19 +52,14 @@ import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.UserActionTester; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeTabbedActivity2; +import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.compositor.bottombar.OverlayContentDelegate; -import org.chromium.chrome.browser.compositor.bottombar.OverlayContentProgressObserver; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.PanelState; -import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason; import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchBarControl; import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchImageControl; import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel; import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchQuickActionControl; -import org.chromium.chrome.browser.contextualsearch.ContextualSearchFakeServer.ContextualSearchTestHost; -import org.chromium.chrome.browser.contextualsearch.ContextualSearchFakeServer.FakeResolveSearch; -import org.chromium.chrome.browser.contextualsearch.ContextualSearchFakeServer.FakeSlowResolveSearch; import org.chromium.chrome.browser.contextualsearch.ContextualSearchInternalStateController.InternalState; import org.chromium.chrome.browser.contextualsearch.ResolvedSearchTerm.CardTag; import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl; @@ -84,41 +68,29 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.layouts.animation.CompositorAnimationHandler; -import org.chromium.chrome.browser.locale.LocaleManager; -import org.chromium.chrome.browser.locale.LocaleManagerDelegate; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabCreationState; import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; -import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule; import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.chrome.test.util.FullscreenTestUtils; import org.chromium.chrome.test.util.MenuUtils; import org.chromium.components.external_intents.ExternalNavigationHandler; import org.chromium.content_public.browser.NavigationHandle; -import org.chromium.content_public.browser.SelectionPopupController; import org.chromium.content_public.browser.WebContents; -import org.chromium.content_public.browser.test.util.DOMUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.content_public.browser.test.util.TouchCommon; -import org.chromium.net.test.EmbeddedTestServer; import org.chromium.ui.base.PageTransition; import org.chromium.ui.test.util.UiDisableIf; import org.chromium.ui.test.util.UiRestriction; -import org.chromium.ui.touch_selection.SelectionEventType; import org.chromium.url.GURL; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.concurrent.TimeoutException; // TODO(donnd): Create class with limited API to encapsulate the internals of simulations. @@ -134,15 +106,7 @@ + ChromeFeatureList.CONTEXTUAL_SEARCH_THIN_WEB_VIEW_IMPLEMENTATION}) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) @Batch(Batch.PER_CLASS) -public class ContextualSearchManagerTest { - @ClassRule - public static final ChromeTabbedActivityTestRule sActivityTestRule = - new ChromeTabbedActivityTestRule(); - - @Rule - public final BlankCTATabInitialStateRule mInitialStateRule = - new BlankCTATabInitialStateRule(sActivityTestRule, false); - +public class ContextualSearchManagerTest extends ContextualSearchInstrumentationBase { /** Parameter provider for enabling/disabling triggering-related Features. */ public static class FeatureParamProvider implements ParameterProvider { @Override @@ -154,22 +118,6 @@ } } - private static final String TAG = "SearchManagerTest"; - private static final String TEST_PAGE = - "/chrome/test/data/android/contextualsearch/tap_test.html"; - private static final int TEST_TIMEOUT = 15000; - private static final int TEST_EXPECTED_FAILURE_TIMEOUT = 1000; - - private static final int PANEL_INTERACTION_MAX_RETRIES = 3; - private static final int PANEL_INTERACTION_RETRY_DELAY_MS = 200; - - // TODO(donnd): get these from TemplateURL once the low-priority or Contextual Search API - // is fully supported. - private static final String NORMAL_PRIORITY_SEARCH_ENDPOINT = "/search?"; - private static final String LOW_PRIORITY_SEARCH_ENDPOINT = "/s?"; - private static final String LOW_PRIORITY_INVALID_SEARCH_ENDPOINT = "/s/invalid"; - private static final String CONTEXTUAL_SEARCH_PREFETCH_PARAM = "&pf=c"; - // DOM element IDs in our test page based on what functions they trigger. // TODO(donnd): add more, and also the associated Search Term, or build a similar mapping. /** @@ -177,11 +125,6 @@ * with the Search Term "Search" from the Fake server. */ private static final String SIMPLE_SEARCH_NODE_ID = "search"; - /** - * The DOM node for the word "intelligence" on the test page, which causes a search response - * for the Search Term "Intelligence" and also includes Related Searches suggestions. - */ - private static final String RELATED_SEARCHES_NODE_ID = "intelligence"; /** * Feature maps that we use for parameterized tests. @@ -197,1117 +140,13 @@ private static final ImmutableMap<String, Boolean> ENABLE_TRANSLATIONS = ImmutableMap.of(ChromeFeatureList.CONTEXTUAL_SEARCH_TRANSLATIONS, true); - /** Feature maps that we use for individual tests. */ - private static final ImmutableMap<String, Boolean> ENABLE_RELATED_SEARCHES_IN_BAR = - ImmutableMap.of(ChromeFeatureList.RELATED_SEARCHES, true, - ChromeFeatureList.RELATED_SEARCHES_UI, true, - ChromeFeatureList.RELATED_SEARCHES_IN_BAR, true); - - private ActivityMonitor mActivityMonitor; - private ContextualSearchFakeServer mFakeServer; - private ContextualSearchManager mManager; - private ContextualSearchPanel mPanel; - private ContextualSearchPolicy mPolicy; - private ContextualSearchSelectionController mSelectionController; - private EmbeddedTestServer mTestServer; - private ContextualSearchManagerTestHost mTestHost; private UserActionTester mActionTester; - private float mDpToPx; - - // State for an individual test. - private FakeSlowResolveSearch mLatestSlowResolveSearch; - - @IntDef({EnabledFeature.NONE, EnabledFeature.TRANSLATIONS}) - @Retention(RetentionPolicy.SOURCE) - private @interface EnabledFeature { - int NONE = 0; - int TRANSLATIONS = 1; - } - - // Tracks whether a long-press triggering experiment is active. - private @EnabledFeature int mEnabledFeature; - - @ParameterAnnotations.UseMethodParameterBefore(FeatureParamProvider.class) - public void setFeatureParameterForTest(@EnabledFeature int enabledFeature) { - mEnabledFeature = enabledFeature; - } - + @Override @Before public void setUp() throws Exception { - TestThreadUtils.runOnUiThreadBlocking(() -> { - FirstRunStatus.setFirstRunFlowComplete(true); - LocaleManager.getInstance().setDelegateForTest(new LocaleManagerDelegate() { - @Override - public boolean needToCheckForSearchEnginePromo() { - return false; - } - }); - }); - - mTestServer = sActivityTestRule.getTestServer(); - - sActivityTestRule.loadUrl(mTestServer.getURL(TEST_PAGE)); - - mManager = sActivityTestRule.getActivity().getContextualSearchManagerSupplier().get(); - mTestHost = new ContextualSearchManagerTestHost(); - - Assert.assertNotNull(mManager); - mPanel = (ContextualSearchPanel) mManager.getContextualSearchPanel(); - - mSelectionController = mManager.getSelectionController(); - mPolicy = mManager.getContextualSearchPolicy(); - mPolicy.overrideDecidedStateForTesting(true); - mSelectionController.setPolicy(mPolicy); - - mFakeServer = new ContextualSearchFakeServer(mPolicy, mTestHost, mManager, - mManager.getOverlayContentDelegate(), new OverlayContentProgressObserver(), - sActivityTestRule.getActivity()); - - mPanel.setOverlayPanelContentFactory(mFakeServer); - mManager.setNetworkCommunicator(mFakeServer); - mPolicy.setNetworkCommunicator(mFakeServer); - - registerFakeSearches(); - - IntentFilter filter = new IntentFilter(Intent.ACTION_VIEW); - filter.addCategory(Intent.CATEGORY_BROWSABLE); - filter.addDataScheme("market"); - mActivityMonitor = InstrumentationRegistry.getInstrumentation().addMonitor( - filter, new Instrumentation.ActivityResult(Activity.RESULT_OK, null), true); - - mDpToPx = sActivityTestRule.getActivity().getResources().getDisplayMetrics().density; - - // Set the test Features map for all tests regardless of whether they are parameterized. - // Non-parameterized tests typically override this setting by calling setTestFeatures - // again. - ImmutableMap<String, Boolean> whichFeature = null; - switch (mEnabledFeature) { - case EnabledFeature.NONE: - whichFeature = ENABLE_NONE; - break; - case EnabledFeature.TRANSLATIONS: - whichFeature = ENABLE_TRANSLATIONS; - break; - } - Assert.assertNotNull( - "Did you change test Features without setting the correct Map?", whichFeature); - FeatureList.setTestFeatures(whichFeature); - } - - @After - public void tearDown() throws Exception { - TestThreadUtils.runOnUiThreadBlocking(() -> { - FirstRunStatus.setFirstRunFlowComplete(false); - mManager.dismissContextualSearchBar(); - mPanel.closePanel(StateChangeReason.UNKNOWN, false); - }); - InstrumentationRegistry.getInstrumentation().removeMonitor(mActivityMonitor); - mActivityMonitor = null; - mLatestSlowResolveSearch = null; - if (mActionTester != null) mActionTester.tearDown(); - FeatureList.setTestFeatures(null); - CompositorAnimationHandler.setTestingMode(false); - } - - /** Allows the fake server to call into this host to drive actions when simulating a search. */ - private class ContextualSearchManagerTestHost implements ContextualSearchTestHost { - @Override - public void triggerNonResolve(String nodeId) throws TimeoutException { - boolean wasOptedIn = mPolicy.overrideDecidedStateForTesting(false); - clickWordNode(nodeId); - mPolicy.overrideDecidedStateForTesting(wasOptedIn); - } - - @Override - public void triggerResolve(String nodeId) throws TimeoutException { - boolean wasOptedIn = mPolicy.overrideDecidedStateForTesting(true); - clickWordNode(nodeId); - mPolicy.overrideDecidedStateForTesting(wasOptedIn); - } - - @Override - public void waitForSelectionToBe(final String text) { - CriteriaHelper.pollInstrumentationThread(() -> { - Criteria.checkThat(getSelectedText(), Matchers.is(text)); - }, TEST_TIMEOUT, DEFAULT_POLLING_INTERVAL); - } - - @Override - public void waitForSearchTermResolutionToStart(final FakeResolveSearch search) { - CriteriaHelper.pollInstrumentationThread( - () - -> { return search.didStartSearchTermResolution(); }, - "Fake Search Term Resolution never started.", TEST_TIMEOUT, - DEFAULT_POLLING_INTERVAL); - } - - @Override - public void waitForSearchTermResolutionToFinish(final FakeResolveSearch search) { - CriteriaHelper.pollInstrumentationThread(() -> { - return search.didFinishSearchTermResolution(); - }, "Fake Search was never ready.", TEST_TIMEOUT, DEFAULT_POLLING_INTERVAL); - } - - @Override - public ContextualSearchPanel getPanel() { - return mPanel; - } - } - - /** - * Gets the name of the given outcome when it's expected to be logged. - * @param feature A feature whose name we want. - * @return The name of the outcome if the give parameter is an outcome, or {@code null} if it's - * not. - */ - private static final String expectedOutcomeName( - @ContextualSearchInteractionRecorder.Feature int feature) { - switch (feature) { - // We don't log whether the quick action was clicked unless we actually have a - // quick action. - case ContextualSearchInteractionRecorder.Feature.OUTCOME_WAS_QUICK_ACTION_CLICKED: - return null; - default: - return ContextualSearchRankerLoggerImpl.outcomeName(feature); - } - } - - /** - * Gets the name of the given feature when it's expected to be logged. - * @param feature An outcome that might have been expected to be logged. - * @return The name of the outcome if it's expected to be logged, or {@code null} if it's not - * expected to be logged. - */ - private static final String expectedFeatureName( - @ContextualSearchInteractionRecorder.Feature int feature) { - switch (feature) { - // We don't log previous user impressions and CTR if not available for the - // current user. - case ContextualSearchInteractionRecorder.Feature.PREVIOUS_WEEK_CTR_PERCENT: - case ContextualSearchInteractionRecorder.Feature.PREVIOUS_WEEK_IMPRESSIONS_COUNT: - case ContextualSearchInteractionRecorder.Feature.PREVIOUS_28DAY_CTR_PERCENT: - case ContextualSearchInteractionRecorder.Feature.PREVIOUS_28DAY_IMPRESSIONS_COUNT: - return null; - default: - return ContextualSearchRankerLoggerImpl.featureName(feature); - } - } - - private interface ThrowingRunnable { - void run() throws TimeoutException; - } - - // Panel interactions are flaky, see crbug.com/635661. Rather than adding a long delay to - // each test, we can retry failures. When trying to make the panel peak, we may also have to - // clear the selection before trying again. - private void retryPanelBarInteractions(ThrowingRunnable r, boolean clearSelection) - throws AssertionError, TimeoutException { - int tries = 0; - boolean success = false; - while (!success) { - tries++; - try { - r.run(); - success = true; - } catch (AssertionError | TimeoutException e) { - if (tries > PANEL_INTERACTION_MAX_RETRIES) { - throw e; - } else { - Log.e(TAG, "Failed to peek panel bar, trying again.", e); - if (clearSelection) clearSelection(); - try { - Thread.sleep(PANEL_INTERACTION_RETRY_DELAY_MS); - } catch (InterruptedException ex) { - } - } - } - } - } - - private void clearSelection() { - ThreadUtils.runOnUiThreadBlocking(() -> { - SelectionPopupController.fromWebContents(sActivityTestRule.getWebContents()) - .clearSelection(); - }); - } - - //============================================================================================ - // Public API - //============================================================================================ - - /** - * Simulates a long-press on the given node without waiting for the panel to respond. - * @param nodeId A string containing the node ID. - */ - public void longPressNodeWithoutWaiting(String nodeId) throws TimeoutException { - Tab tab = sActivityTestRule.getActivity().getActivityTab(); - DOMUtils.longPressNode(tab.getWebContents(), nodeId); - } - - /** - * Simulates a long-press on the given node and waits for the panel to peek. - * @param nodeId A string containing the node ID. - */ - public void longPressNode(String nodeId) throws TimeoutException { - retryPanelBarInteractions(() -> { - longPressNodeWithoutWaiting(nodeId); - waitForPanelToPeek(); - }, true); - } - - /** - * Simulates a resolving trigger on the given node but does not wait for the panel to peek. - * @param nodeId A string containing the node ID. - */ - private void triggerResolve(String nodeId) throws TimeoutException { - mTestHost.triggerResolve(nodeId); - } - - /** - * Simulates a non-resolve trigger on the given node and waits for the panel to peek. - * @param nodeId A string containing the node ID. - */ - private void triggerNonResolve(String nodeId) throws TimeoutException { - mTestHost.triggerNonResolve(nodeId); - } - - /** - * Long-press a node without completing the action, by keeping the touch down by not letting up. - * @param nodeId The ID of the node to touch - * @return A time stamp to use with {@link #longPressExtendSelection} - * @throws TimeoutException - * @see #longPressExtendSelection - */ - public long longPressNodeWithoutUp(String nodeId) throws TimeoutException { - long downTime = SystemClock.uptimeMillis(); - Tab tab = sActivityTestRule.getActivity().getActivityTab(); - DOMUtils.longPressNodeWithoutUp(tab.getWebContents(), nodeId, downTime); - waitForSelectActionBarVisible(); - waitForPanelToPeek(); - return downTime; - } - - /** - * Extends a Long-press selection by completing a drag action. - * @param startNodeId The ID of the node that has already been touched - * @param endNodeId The ID of the node that the touch should be extended to - * @param downTime A time stamp returned by {@link #longPressNodeWithoutUp} - * @throws TimeoutException - * @see #longPressNodeWithoutUp - */ - public void longPressExtendSelection(String startNodeId, String endNodeId, long downTime) - throws TimeoutException { - // TODO(donnd): figure out why we need this one line here, and why the selection does not - // match our expected nodes! - longPressNodeWithoutUp("term"); - - // Drag to the specified position by a DOM node id. - int stepCount = 100; - Tab tab = sActivityTestRule.getActivity().getActivityTab(); - DOMUtils.dragNodeTo(tab.getWebContents(), startNodeId, endNodeId, stepCount, downTime); - DOMUtils.dragNodeEnd(tab.getWebContents(), endNodeId, downTime); - - // Make sure the selection controller knows we did a drag. - // TODO(donnd): figure out how to reliably simulate a drag on all platforms. - float unused = 0.0f; - @SelectionEventType - int dragStoppedEvent = SelectionEventType.SELECTION_HANDLE_DRAG_STOPPED; - TestThreadUtils.runOnUiThreadBlocking( - () -> mSelectionController.handleSelectionEvent(dragStoppedEvent, unused, unused)); - - waitForSelectActionBarVisible(); - } - - /** - * Simulates a click on the given node. - * @param nodeId A string containing the node ID. - */ - public void clickNode(String nodeId) throws TimeoutException { - Tab tab = sActivityTestRule.getActivity().getActivityTab(); - DOMUtils.clickNode(tab.getWebContents(), nodeId); - } - - /** - * Waits for the selected text string to be the given string, and asserts. - * @param text The string to wait for the selection to become. - */ - private void waitForSelectionToBe(final String text) { - mTestHost.waitForSelectionToBe(text); - } - - /** - * Waits for the Search Term Resolution to become ready. - * @param search A given FakeResolveSearch. - */ - private void waitForSearchTermResolutionToStart(final FakeResolveSearch search) { - mTestHost.waitForSearchTermResolutionToStart(search); - } - - /** - * Waits for the Search Term Resolution to finish. - * @param search A given FakeResolveSearch. - */ - private void waitForSearchTermResolutionToFinish(final FakeResolveSearch search) { - mTestHost.waitForSearchTermResolutionToFinish(search); - } - - /** - * Waits for a Normal priority URL to be loaded, or asserts that the load never happened. - * This is needed when we test with a live internet connection and an invalid url fails to - * load (as expected. See crbug.com/682953 for background. - */ - private void waitForNormalPriorityUrlLoaded() { - CriteriaHelper.pollInstrumentationThread(() -> { - Criteria.checkThat(mFakeServer.getLoadedUrl(), Matchers.notNullValue()); - Criteria.checkThat(mFakeServer.getLoadedUrl(), - Matchers.containsString(NORMAL_PRIORITY_SEARCH_ENDPOINT)); - }, TEST_TIMEOUT, DEFAULT_POLLING_INTERVAL); - } - - /** - * Runs the given Runnable in the main thread. - * @param runnable The Runnable. - */ - public void runOnMainSync(Runnable runnable) { - InstrumentationRegistry.getInstrumentation().runOnMainSync(runnable); - } - - //============================================================================================ - // Fake Searches Helpers - //============================================================================================ - - /** - * Simulates a non-resolving search. - * - * @param nodeId The id of the node to be triggered. - * @throws InterruptedException - * @throws TimeoutException - */ - private void simulateNonResolveSearch(String nodeId) - throws InterruptedException, TimeoutException { - ContextualSearchFakeServer.FakeNonResolveSearch search = - mFakeServer.getFakeNonResolveSearch(nodeId); - search.simulate(); - waitForPanelToPeek(); - } - - /** - * Simulates a resolve-triggering search. - * - * @param nodeId The id of the node to be tapped. - * @throws InterruptedException - * @throws TimeoutException - */ - private FakeResolveSearch simulateResolveSearch(String nodeId) - throws InterruptedException, TimeoutException { - return simulateResolvableSearchAndAssertResolveAndPreload(nodeId, true); - } - - /** - * Simulates a resolve-triggering gesture that may or may not actually resolve. - * If the gesture should Resolve, the resolve and preload are asserted, and vice versa. - * - * @param nodeId The id of the node to be tapped. - * @param isResolveExpected Whether a resolve is expected or not. Enforce by asserting. - * @throws InterruptedException - * @throws TimeoutException - */ - private FakeResolveSearch simulateResolvableSearchAndAssertResolveAndPreload(String nodeId, - boolean isResolveExpected) throws InterruptedException, TimeoutException { - FakeResolveSearch search = mFakeServer.getFakeResolveSearch(nodeId); - assertNotNull("Could not find FakeResolveSearch for node ID:" + nodeId, search); - search.simulate(); - waitForPanelToPeek(); - if (isResolveExpected) { - assertLoadedSearchTermMatches(search.getSearchTerm()); - } else { - assertSearchTermNotRequested(); - assertNoSearchesLoaded(); - assertNoWebContents(); - } - return search; - } - - /** - * Simulates a resolving search with slow server response. - * - * @param nodeId The id of the node to be triggered. - * @throws InterruptedException - * @throws TimeoutException - */ - private void simulateSlowResolveSearch(String nodeId) - throws InterruptedException, TimeoutException { - mLatestSlowResolveSearch = mFakeServer.getFakeSlowResolveSearch(nodeId); - assertNotNull("Could not find FakeSlowResolveSearch for node ID:" + nodeId, - mLatestSlowResolveSearch); - mLatestSlowResolveSearch.simulate(); - waitForPanelToPeek(); - } - - /** - * Simulates a slow response for the most recent {@link FakeSlowResolveSearch} set up - * by calling simulateSlowResolveSearch. - * @throws TimeoutException - * @throws InterruptedException - */ - private void simulateSlowResolveFinished() throws InterruptedException, TimeoutException { - // Allow the slow Resolution to finish, waiting for it to complete. - mLatestSlowResolveSearch.finishResolve(); - assertLoadedSearchTermMatches(mLatestSlowResolveSearch.getSearchTerm()); - } - - /** - * Registers all fake searches to be used in tests. - */ - private void registerFakeSearches() throws Exception { - mFakeServer.registerFakeSearches(); - } - - //============================================================================================ - // Fake Response - // TODO(donnd): remove these methods and use the new infrastructure instead. - //============================================================================================ - - /** - * Posts a fake response on the Main thread. - */ - private final class FakeResponseOnMainThread implements Runnable { - private final ResolvedSearchTerm mResolvedSearchTerm; - - public FakeResponseOnMainThread(ResolvedSearchTerm resolvedSearchTerm) { - mResolvedSearchTerm = resolvedSearchTerm; - } - - @Override - public void run() { - mFakeServer.handleSearchTermResolutionResponse(mResolvedSearchTerm); - } - } - - /** - * Fakes a server response with the parameters given and startAdjust and endAdjust equal to 0. - * {@See ContextualSearchManager#handleSearchTermResolutionResponse}. - */ - private void fakeResponse(boolean isNetworkUnavailable, int responseCode, String searchTerm, - String displayText, String alternateTerm, boolean doPreventPreload) { - fakeResponse(new ResolvedSearchTerm - .Builder(isNetworkUnavailable, responseCode, searchTerm, displayText, - alternateTerm, doPreventPreload) - .build()); - } - - /** - * Fakes a server response with the parameters given. - * {@See ContextualSearchManager#handleSearchTermResolutionResponse}. - */ - private void fakeResponse(ResolvedSearchTerm resolvedSearchTerm) { - if (mFakeServer.getSearchTermRequested() != null) { - InstrumentationRegistry.getInstrumentation().runOnMainSync( - new FakeResponseOnMainThread(resolvedSearchTerm)); - } - } - - //============================================================================================ - // Content Helpers - //============================================================================================ - - /** - * @return The Panel's WebContents. - */ - private WebContents getPanelWebContents() { - return mPanel.getWebContents(); - } - - /** - * @return Whether the Panel's WebContents is visible. - */ - private boolean isWebContentsVisible() { - return mFakeServer.isContentVisible(); - } - - /** - * Asserts that the Panel's WebContents is created. - */ - private void assertWebContentsCreated() { - Assert.assertNotNull(getPanelWebContents()); - } - - /** - * Asserts that the Panel's WebContents is not created. - */ - private void assertNoWebContents() { - Assert.assertNull(getPanelWebContents()); - } - - /** - * Asserts that the Panel's WebContents is visible. - */ - private void assertWebContentsVisible() { - Assert.assertTrue(isWebContentsVisible()); - } - - /** - * Asserts that the Panel's WebContents.onShow() method was never called. - */ - private void assertNeverCalledWebContentsOnShow() { - Assert.assertFalse(mFakeServer.didEverCallWebContentsOnShow()); - } - - /** - * Asserts that the Panel's WebContents is created - */ - private void assertWebContentsCreatedButNeverMadeVisible() { - assertWebContentsCreated(); - Assert.assertFalse(isWebContentsVisible()); - assertNeverCalledWebContentsOnShow(); - } - - /** - * Fakes navigation of the Content View to the URL that was previously requested. - * @param isFailure whether the request resulted in a failure. - */ - private void fakeContentViewDidNavigate(boolean isFailure) { - String url = mFakeServer.getLoadedUrl(); - mManager.getOverlayContentDelegate().onMainFrameNavigation(url, false, isFailure, false); - } - - //============================================================================================ - // Other Helpers - // TODO(donnd): organize into sections. - //============================================================================================ - - /** - * Simulates a click on the given word node. - * Waits for the bar to peek. - * TODO(donnd): rename to include the waitForPanelToPeek semantic, or rename clickNode to - * clickNodeWithoutWaiting. - * @param nodeId A string containing the node ID. - */ - private void clickWordNode(String nodeId) throws TimeoutException { - retryPanelBarInteractions(() -> { - clickNode(nodeId); - waitForPanelToPeek(); - }, true); - } - - /** - * Simulates a simple gesture that could trigger a resolve on the given node in the given tab. - * @param tab The tab that contains the node to trigger (must be frontmost). - * @param nodeId A string containing the node ID. - */ - public void triggerNode(Tab tab, String nodeId) throws TimeoutException { - DOMUtils.clickNode(tab.getWebContents(), nodeId); - } - - /** - * @return The selected text. - */ - private String getSelectedText() { - return mSelectionController.getSelectedText(); - } - - /** - * Asserts that the loaded search term matches the provided value. - * @param searchTerm The provided search term. - */ - private void assertLoadedSearchTermMatches(String searchTerm) { - boolean doesMatch = false; - String loadedUrl = mFakeServer.getLoadedUrl(); - doesMatch = loadedUrl != null && loadedUrl.contains("q=" + searchTerm); - String message = - loadedUrl == null ? "but there was no loaded URL!" : "in URL: " + loadedUrl; - Assert.assertTrue( - "Expected to find searchTerm '" + searchTerm + "', " + message, doesMatch); - } - - /** - * Asserts that the given parameters are present in the most recently loaded URL. - */ - private void assertContainsParameters(String... terms) { - Assert.assertNotNull("Fake server didn't load a SERP URL", mFakeServer.getLoadedUrl()); - for (String term : terms) { - Assert.assertTrue("Expected search term not found:" + term, - mFakeServer.getLoadedUrl().contains(term)); - } - } - - /** - * Asserts that a Search Term has been requested. - */ - private void assertSearchTermRequested() { - Assert.assertNotNull(mFakeServer.getSearchTermRequested()); - } - - /** - * Asserts that there has not been any Search Term requested. - */ - private void assertSearchTermNotRequested() { - Assert.assertNull(mFakeServer.getSearchTermRequested()); - } - - /** - * Asserts that the panel is currently closed or in an undefined state. - */ - private void assertPanelClosedOrUndefined() { - boolean success = false; - if (mPanel == null) { - success = true; - } else { - @PanelState - int panelState = mPanel.getPanelState(); - success = panelState == PanelState.CLOSED || panelState == PanelState.UNDEFINED; - } - Assert.assertTrue(success); - } - - /** - * Asserts that no URL has been loaded in the Overlay Panel. - */ - private void assertLoadedNoUrl() { - Assert.assertTrue("Requested a search or preload when none was expected!", - mFakeServer.getLoadedUrl() == null); - } - - /** - * Asserts that a low-priority URL has been loaded in the Overlay Panel. - */ - private void assertLoadedLowPriorityUrl() { - String message = "Expected a low priority search request URL, but got " - + (mFakeServer.getLoadedUrl() != null ? mFakeServer.getLoadedUrl() : "null"); - Assert.assertTrue(message, - mFakeServer.getLoadedUrl() != null - && mFakeServer.getLoadedUrl().contains(LOW_PRIORITY_SEARCH_ENDPOINT)); - Assert.assertTrue("Low priority request does not have the required prefetch parameter!", - mFakeServer.getLoadedUrl() != null - && mFakeServer.getLoadedUrl().contains(CONTEXTUAL_SEARCH_PREFETCH_PARAM)); - } - - /** - * Asserts that a low-priority URL that is intentionally invalid has been loaded in the Overlay - * Panel (in order to produce an error). - */ - private void assertLoadedLowPriorityInvalidUrl() { - String message = "Expected a low priority invalid search request URL, but got " - + (String.valueOf(mFakeServer.getLoadedUrl())); - Assert.assertTrue(message, - mFakeServer.getLoadedUrl() != null - && mFakeServer.getLoadedUrl().contains( - LOW_PRIORITY_INVALID_SEARCH_ENDPOINT)); - Assert.assertTrue("Low priority request does not have the required prefetch parameter!", - mFakeServer.getLoadedUrl() != null - && mFakeServer.getLoadedUrl().contains(CONTEXTUAL_SEARCH_PREFETCH_PARAM)); - } - - /** - * Asserts that a normal priority URL has been loaded in the Overlay Panel. - */ - private void assertLoadedNormalPriorityUrl() { - String message = "Expected a normal priority search request URL, but got " - + (mFakeServer.getLoadedUrl() != null ? mFakeServer.getLoadedUrl() : "null"); - Assert.assertTrue(message, - mFakeServer.getLoadedUrl() != null - && mFakeServer.getLoadedUrl().contains(NORMAL_PRIORITY_SEARCH_ENDPOINT)); - Assert.assertTrue( - "Normal priority request should not have the prefetch parameter, but did!", - mFakeServer.getLoadedUrl() != null - && !mFakeServer.getLoadedUrl().contains(CONTEXTUAL_SEARCH_PREFETCH_PARAM)); - } - - /** - * Asserts that no URLs have been loaded in the Overlay Panel since the last - * {@link ContextualSearchFakeServer#reset}. - */ - private void assertNoSearchesLoaded() { - Assert.assertEquals(0, mFakeServer.getLoadedUrlCount()); - assertLoadedNoUrl(); - } - - /** - * Asserts that a Search Term has been requested. - * @param isExactResolve Whether the Resolve request must be exact (non-expanding). - */ - private void assertExactResolve(boolean isExactResolve) { - Assert.assertEquals(isExactResolve, mFakeServer.getIsExactResolve()); - } - - /** - * Waits for the Search Panel (the Search Bar) to peek up from the bottom, and asserts that it - * did peek. - */ - private void waitForPanelToPeek() { - waitForPanelToEnterState(PanelState.PEEKED); - } - - /** - * Waits for the Search Panel to expand, and asserts that it did expand. - */ - private void waitForPanelToExpand() { - waitForPanelToEnterState(PanelState.EXPANDED); - } - - /** - * Waits for the Search Panel to maximize, and asserts that it did maximize. - */ - private void waitForPanelToMaximize() { - waitForPanelToEnterState(PanelState.MAXIMIZED); - } - - /** - * Waits for the Search Panel to close, and asserts that it did close. - */ - private void waitForPanelToClose() { - waitForPanelToEnterState(PanelState.CLOSED); - } - - /** - * Waits for the Search Panel to enter the given {@code PanelState} and assert. - * @param state The {@link PanelState} to wait for. - */ - private void waitForPanelToEnterState(final @PanelState int state) { - CriteriaHelper.pollUiThread(() -> { - Criteria.checkThat(mPanel, Matchers.notNullValue()); - Criteria.checkThat(mPanel.getPanelState(), Matchers.is(state)); - Criteria.checkThat(mPanel.isHeightAnimationRunning(), Matchers.is(false)); - }); - } - - /** - * Asserts that the panel is still in the given state and continues to stay that way - * for a while. - * Waits for a reasonable amount of time for the panel to change to a different state, - * and verifies that it did not change state while this method is executing. - * Note that it's quite possible for the panel to transition through some other state and - * back to the initial state before this method is called without that being detected, - * because this method only monitors state during its own execution. - * @param initialState The initial state of the panel at the beginning of an operation that - * should not change the panel state. - * @throws InterruptedException - */ - private void assertPanelStillInState(final @PanelState int initialState) - throws InterruptedException { - boolean didChangeState = false; - long startTime = SystemClock.uptimeMillis(); - while (!didChangeState - && SystemClock.uptimeMillis() - startTime < TEST_EXPECTED_FAILURE_TIMEOUT) { - Thread.sleep(DEFAULT_POLLING_INTERVAL); - didChangeState = mPanel.getPanelState() != initialState; - } - Assert.assertFalse(didChangeState); - } - - /** - * Shorthand for a common sequence: - * 1) Waits for gesture processing, - * 2) Waits for the panel to close, - * 3) Asserts that there is no selection and that the panel closed. - */ - private void waitForGestureToClosePanelAndAssertNoSelection() { - waitForPanelToClose(); - assertPanelClosedOrUndefined(); - Assert.assertTrue(TextUtils.isEmpty(getSelectedText())); - } - - /** - * Waits for the selection to be empty. - * Use this method any time a test repeatedly establishes and dissolves a selection to ensure - * that the selection has been completely dissolved before simulating the next selection event. - * This is needed because the renderer's notification of a selection going away is async, - * and a subsequent tap may think there's a current selection until it has been dissolved. - */ - private void waitForSelectionEmpty() { - CriteriaHelper.pollUiThread( - () -> mSelectionController.isSelectionEmpty(), "Selection never empty."); - } - - /** - * Waits for the panel to close and then waits for the selection to dissolve. - */ - private void waitForPanelToCloseAndSelectionEmpty() { - waitForPanelToClose(); - waitForSelectionEmpty(); - } - - private void waitToPreventDoubleTapRecognition() throws InterruptedException { - // Avoid issues with double-tap detection by ensuring sequential taps - // aren't treated as such. Double-tapping can also select words much as - // longpress, in turn showing the pins and preventing contextual tap - // refinement from nearby taps. The double-tap timeout is sufficiently - // short that this shouldn't conflict with tap refinement by the user. - int doubleTapTimeout = ViewConfiguration.getDoubleTapTimeout(); - Thread.sleep(doubleTapTimeout); - } - - /** - * Generate a fling sequence from the given start/end X,Y percentages, for the given steps. - * Works in either landscape or portrait orientation. - */ - private void fling(float startX, float startY, float endX, float endY, int stepCount) { - Point size = new Point(); - sActivityTestRule.getActivity().getWindowManager().getDefaultDisplay().getSize(size); - float dragStartX = size.x * startX; - float dragEndX = size.x * endX; - float dragStartY = size.y * startY; - float dragEndY = size.y * endY; - long downTime = SystemClock.uptimeMillis(); - TouchCommon.dragStart(sActivityTestRule.getActivity(), dragStartX, dragStartY, downTime); - TouchCommon.dragTo(sActivityTestRule.getActivity(), dragStartX, dragEndX, dragStartY, - dragEndY, stepCount, downTime); - TouchCommon.dragEnd(sActivityTestRule.getActivity(), dragEndX, dragEndY, downTime); - } - - /** - * Generate a swipe sequence from the given start/end X,Y percentages, for the given steps. - * Works in either landscape or portrait orientation. - */ - private void swipe(float startX, float startY, float endX, float endY, int stepCount) { - Point size = new Point(); - sActivityTestRule.getActivity().getWindowManager().getDefaultDisplay().getSize(size); - float dragStartX = size.x * startX; - float dragEndX = size.x * endX; - float dragStartY = size.y * startY; - float dragEndY = size.y * endY; - int halfCount = stepCount / 2; - long downTime = SystemClock.uptimeMillis(); - TouchCommon.dragStart(sActivityTestRule.getActivity(), dragStartX, dragStartY, downTime); - TouchCommon.dragTo(sActivityTestRule.getActivity(), dragStartX, dragEndX, dragStartY, - dragEndY, halfCount, downTime); - // Generate events in the stationary end position in order to simulate a "pause" in - // the movement, therefore preventing this gesture from being interpreted as a fling. - TouchCommon.dragTo(sActivityTestRule.getActivity(), dragEndX, dragEndX, dragEndY, dragEndY, - halfCount, downTime); - TouchCommon.dragEnd(sActivityTestRule.getActivity(), dragEndX, dragEndY, downTime); - } - - /** - * Flings the panel up to its expanded state. - */ - private void flingPanelUp() { - fling(0.5f, 0.95f, 0.5f, 0.55f, 1000); - } - - /** - * Swipes the panel down to its peeked state. - */ - private void swipePanelDown() { - swipe(0.5f, 0.55f, 0.5f, 0.95f, 100); - } - - /** - * Scrolls the base page. - */ - private void scrollBasePage() { - fling(0.f, 0.75f, 0.f, 0.7f, 100); - } - - /** - * Taps the base page near the top. - */ - private void tapBasePageToClosePanel() { - // TODO(donnd): This is not reliable. Find a better approach. - // This taps on the panel in an area that will be selected if the "intelligence" node has - // been tap-selected, and that will cause it to be long-press selected. - // We use the far right side to prevent simulating a tap on top of an - // existing long-press selection (the pins are a tap target). This might not work on RTL. - // We are using y == 0.35f because otherwise it will fail for long press cases. - // It might be better to get the position of the Panel and tap just about outside - // the Panel. I suspect some Flaky tests are caused by this problem (ones involving - // long press and trying to close with the bar peeking, with a long press selection - // established). - tapBasePage(0.95f, 0.35f); - waitForPanelToClose(); - } - - /** - * Taps the base page at the given x, y position. - */ - private void tapBasePage(float x, float y) { - View root = sActivityTestRule.getActivity().getWindow().getDecorView().getRootView(); - x *= root.getWidth(); - y *= root.getHeight(); - TouchCommon.singleClickView(root, (int) x, (int) y); - } - - /** - * Click various places to cause the panel to show, expand, then close. - */ - private void clickToExpandAndClosePanel() throws TimeoutException { - clickWordNode("states"); - tapBarToExpandAndClosePanel(); - waitForSelectionEmpty(); - } - - /** - * Tap on the peeking Bar to expand the panel, then close it. - */ - private void tapBarToExpandAndClosePanel() throws TimeoutException { - tapPeekingBarToExpandAndAssert(); - closePanel(); - } - - /** - * Generate a click in the middle of panel's bar. - * TODO(donnd): Replace this method with panelBarClick since this appears to be unreliable. - */ - private void clickPanelBar() { - View root = sActivityTestRule.getActivity().getWindow().getDecorView().getRootView(); - float tapX = ((mPanel.getOffsetX() + mPanel.getWidth()) / 2f) * mDpToPx; - float tapY = (mPanel.getOffsetY() + (mPanel.getBarContainerHeight() / 2f)) * mDpToPx; - - TouchCommon.singleClickView(root, (int) tapX, (int) tapY); - } - - /** - * Taps the peeking bar to expand the panel - */ - private void tapPeekingBarToExpandAndAssert() throws TimeoutException { - retryPanelBarInteractions(() -> { - clickPanelBar(); - waitForPanelToExpand(); - }, false); - } - - /** - * Simple sequence useful for checking if a Search Request is prefetched. - * Resets the fake server and clicks near to cause a search, then closes the panel, - * which takes us back to the starting state except that the fake server knows - * if a prefetch occurred. - */ - private void clickToTriggerPrefetch() throws Exception { - mFakeServer.reset(); - simulateResolveSearch("search"); - closePanel(); - waitForPanelToCloseAndSelectionEmpty(); - } - - /** - * Simple sequence to trigger, resolve, and prefetch. Verifies a prefetch occurred. - */ - private void triggerToResolveAndAssertPrefetch() throws Exception { - simulateSlowResolveSearch("states"); - assertLoadedNoUrl(); - assertSearchTermRequested(); - simulateSlowResolveFinished(); - } - - /** - * Fakes a response to the Resolve request. - */ - private void fakeAResponse() { - fakeResponse(false, 200, "states", "United States Intelligence", "alternate-term", false); - waitForPanelToPeek(); - assertLoadedLowPriorityUrl(); - assertContainsParameters("states", "alternate-term"); - } - - /** - * Force the Panel to handle a click on open-in-a-new-tab icon. - */ - private void forceOpenTabIconClick() { - InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { - mPanel.handleBarClick(mPanel.getOpenTabIconX() + mPanel.getOpenTabIconDimension() / 2, - mPanel.getBarHeight() / 2); - }); - } - - /** - * Force the Panel to close. - */ - private void closePanel() { - InstrumentationRegistry.getInstrumentation().runOnMainSync( - () -> { mPanel.closePanel(StateChangeReason.UNKNOWN, false); }); - } - - /** - * Force the Panel to maximize. - */ - private void maximizePanel() { - InstrumentationRegistry.getInstrumentation().runOnMainSync( - () -> { mPanel.maximizePanel(StateChangeReason.UNKNOWN); }); - } - - /** - * Force the Panel to peek. - */ - private void peekPanel() { - InstrumentationRegistry.getInstrumentation().runOnMainSync( - () -> { mPanel.peekPanel(StateChangeReason.UNKNOWN); }); - waitForPanelToPeek(); - } - - /** - * Waits for the Action Bar to be visible in response to a selection. - */ - private void waitForSelectActionBarVisible() { - assertWaitForSelectActionBarVisible(true); - } - - /** Gets the Ranker Logger and asserts if we can't. **/ - private ContextualSearchRankerLoggerImpl getRankerLogger() { - ContextualSearchRankerLoggerImpl rankerLogger = - (ContextualSearchRankerLoggerImpl) mManager.getRankerLogger(); - Assert.assertNotNull(rankerLogger); - return rankerLogger; - } - - /** @return The value of the given logged feature, or {@code null} if not logged. */ - private Object loggedToRanker(@ContextualSearchInteractionRecorder.Feature int feature) { - return getRankerLogger().getFeaturesLogged().get(feature); - } - - /** Asserts that all the expected features have been logged to Ranker. **/ - private void assertLoggedAllExpectedFeaturesToRanker() { - for (int feature = 0; feature < ContextualSearchInteractionRecorder.Feature.NUM_ENTRIES; - feature++) { - if (expectedFeatureName(feature) != null) Assert.assertNotNull(loggedToRanker(feature)); - } - } - - /** Asserts that all the expected outcomes have been logged to Ranker. **/ - private void assertLoggedAllExpectedOutcomesToRanker() { - for (int feature = 0; feature < ContextualSearchInteractionRecorder.Feature.NUM_ENTRIES; - feature++) { - if (expectedOutcomeName(feature) != null) { - Assert.assertNotNull("Expected this outcome to be logged: " + feature, - getRankerLogger().getOutcomesLogged().get(feature)); - } - } - } - - /** - * Monitor user action UMA recording operations. - */ - private static class UserActionMonitor extends UserActionTester { - // TODO(donnd): merge into UserActionTester. See https://crbug.com/1103757. - private Set<String> mUserActionPrefixes; - private Map<String, Integer> mUserActionCounts; - - /** @param userActionPrefixes A set of plain prefix strings for user actions to monitor. */ - UserActionMonitor(Set<String> userActionPrefixes) { - mUserActionPrefixes = userActionPrefixes; - mUserActionCounts = new HashMap<String, Integer>(); - for (String action : mUserActionPrefixes) { - mUserActionCounts.put(action, 0); - } - } - - @Override - public void onActionRecorded(String action) { - for (String entry : mUserActionPrefixes) { - if (action.startsWith(entry)) { - mUserActionCounts.put(entry, mUserActionCounts.get(entry) + 1); - } - } - } - - /** - * Gets the count of user actions recorded for the given prefix. - * @param actionPrefix The plain string prefix to lookup (must match a constructed entry) - * @return The count of user actions recorded for that prefix. - */ - int get(String actionPrefix) { - return mUserActionCounts.get(actionPrefix); - } + mTestPage = "/chrome/test/data/android/contextualsearch/tap_test.html"; + super.setUp(); } //============================================================================================ @@ -1318,17 +157,6 @@ Assert.assertTrue(mActionTester.getActions().contains(userActionFullName)); } - /** - * Returns whether all the supported gestures for opted-in users trigger a Resolve request, - * aka intelligent search. - */ - private boolean isConfigurationForResolvingGesturesOnly() { - // The current interpretation of the ability to resolve Longpress (which is forced by the - // Translations Feature as well as the LongpressResolve Feature) preserves a resolving Tap - // so there is no non-resolving gesture for opted-in users. - return mPolicy.canResolveLongpress(); - } - //============================================================================================ // Test Cases //============================================================================================ @@ -1664,21 +492,6 @@ } /** - * Asserts that the action bar does or does not become visible in response to a selection. - * @param visible Whether the Action Bar must become visible or not. - */ - private void assertWaitForSelectActionBarVisible(final boolean visible) { - CriteriaHelper.pollUiThread(() -> { - Criteria.checkThat( - getSelectionPopupController().isSelectActionBarShowing(), Matchers.is(visible)); - }); - } - - private SelectionPopupController getSelectionPopupController() { - return SelectionPopupController.fromWebContents(sActivityTestRule.getWebContents()); - } - - /** * Tests ContextualSearchManager#shouldInterceptNavigation for a case that an external * navigation has a user gesture. */ @@ -2397,7 +1210,7 @@ R.id.move_to_other_window_menu_id); // Wait for the second activity to start up and be ready for interaction. - final ChromeTabbedActivity2 activity2 = waitForSecondChromeTabbedActivity(); + final ChromeTabbedActivity activity2 = waitForSecondChromeTabbedActivity(); waitForTabs("CTA2", activity2, 1, testTabId); // Trigger on a word and wait for the selection to be established. @@ -2474,6 +1287,42 @@ assertContainsParameters("states", "alternate-term"); } + /** + * Monitor user action UMA recording operations. + */ + private static class UserActionMonitor extends UserActionTester { + // TODO(donnd): merge into UserActionTester. See https://crbug.com/1103757. + private Set<String> mUserActionPrefixes; + private Map<String, Integer> mUserActionCounts; + + /** @param userActionPrefixes A set of plain prefix strings for user actions to monitor. */ + UserActionMonitor(Set<String> userActionPrefixes) { + mUserActionPrefixes = userActionPrefixes; + mUserActionCounts = new HashMap<String, Integer>(); + for (String action : mUserActionPrefixes) { + mUserActionCounts.put(action, 0); + } + } + + @Override + public void onActionRecorded(String action) { + for (String entry : mUserActionPrefixes) { + if (action.startsWith(entry)) { + mUserActionCounts.put(entry, mUserActionCounts.get(entry) + 1); + } + } + } + + /** + * Gets the count of user actions recorded for the given prefix. + * @param actionPrefix The plain string prefix to lookup (must match a constructed entry) + * @return The count of user actions recorded for that prefix. + */ + int get(String actionPrefix) { + return mUserActionCounts.get(actionPrefix); + } + } + @Test @SmallTest @Feature({"ContextualSearch"})
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java index 663f31ce..3736ed01 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -64,6 +64,7 @@ import org.chromium.chrome.browser.omnibox.OmniboxStub; import org.chromium.chrome.browser.omnibox.UrlBar; import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler; +import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; import org.chromium.chrome.browser.suggestions.SiteSuggestion; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; @@ -79,6 +80,7 @@ import org.chromium.chrome.test.util.browser.suggestions.mostvisited.FakeMostVisitedSites; import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator; import org.chromium.components.embedder_support.util.UrlConstants; +import org.chromium.components.search_engines.TemplateUrlService; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestTouchUtils; @@ -145,6 +147,8 @@ VoiceRecognitionHandler mVoiceRecognitionHandler; @Mock FeedReliabilityLogger mFeedReliabilityLogger; + @Mock + private TemplateUrlService mTemplateUrlService; private static final String TEST_PAGE = "/chrome/test/data/android/navigate/simple.html"; private static final String TEST_FEED = @@ -497,8 +501,10 @@ @Test @SmallTest @Feature({"NewTabPage", "FeedNewTabPage"}) - @Features.DisableFeatures({ChromeFeatureList.SHOW_SCROLLABLE_MVT_ON_NTP_ANDROID}) public void testPlaceholder() { + TemplateUrlServiceFactory.setInstanceForTesting(mTemplateUrlService); + when(mTemplateUrlService.doesDefaultSearchEngineHaveLogo()).thenReturn(true); + final NewTabPageLayout ntpLayout = mNtp.getNewTabPageLayout(); final View logoView = ntpLayout.findViewById(R.id.search_provider_logo); final View searchBoxView = ntpLayout.findViewById(R.id.search_box); @@ -508,7 +514,7 @@ Assert.assertEquals(View.VISIBLE, logoView.getVisibility()); Assert.assertEquals(View.VISIBLE, searchBoxView.getVisibility()); Assert.assertEquals(8, mMvTilesLayout.getChildCount()); - Assert.assertNull(ntpLayout.getPlaceholder()); + Assert.assertNull(mNtp.getView().findViewById(R.id.tile_grid_placeholder)); // When the search provider has no logo and there are no tile suggestions, the placeholder // is shown. @@ -518,15 +524,17 @@ Assert.assertEquals(View.GONE, searchBoxView.getVisibility()); mMostVisitedSites.setTileSuggestions(new String[] {}); + when(mTemplateUrlService.doesDefaultSearchEngineHaveLogo()).thenReturn(false); - ntpLayout.getTileGroup().onSwitchToForeground(false); // Force tile refresh. + ntpLayout.onSwitchToForeground(); // Force tile refresh. }); CriteriaHelper.pollUiThread(() -> { Criteria.checkThat( "The tile grid was not updated.", mMvTilesLayout.getChildCount(), is(0)); }); - Assert.assertNotNull(ntpLayout.getPlaceholder()); - Assert.assertEquals(View.VISIBLE, ntpLayout.getPlaceholder().getVisibility()); + Assert.assertNotNull(mNtp.getView().findViewById(R.id.tile_grid_placeholder)); + Assert.assertEquals(View.VISIBLE, + mNtp.getView().findViewById(R.id.tile_grid_placeholder).getVisibility()); // Once the search provider has a logo again, the logo and search box are shown again and // the placeholder is hidden. @@ -534,7 +542,14 @@ ntpLayout.setSearchProviderInfo(/* hasLogo = */ true, /* isGoogle */ true); Assert.assertEquals(View.VISIBLE, logoView.getVisibility()); Assert.assertEquals(View.VISIBLE, searchBoxView.getVisibility()); - Assert.assertEquals(View.GONE, ntpLayout.getPlaceholder().getVisibility()); + + when(mTemplateUrlService.doesDefaultSearchEngineHaveLogo()).thenReturn(true); + + // Mock to notify the template URL service observer. + ntpLayout.getMostVisitedTilesCoordinatorForTesting() + .onTemplateURLServiceChangedForTesting(); + Assert.assertEquals(View.GONE, + mNtp.getView().findViewById(R.id.tile_grid_placeholder).getVisibility()); }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsRenderTest.java index 1b7efc5..40afa9c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsRenderTest.java
@@ -13,6 +13,7 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.chromium.base.test.params.ParameterAnnotations; @@ -21,6 +22,7 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.chrome.browser.omnibox.action.OmniboxPedalType; @@ -31,6 +33,8 @@ import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.chrome.test.util.OmniboxTestUtils; import org.chromium.chrome.test.util.OmniboxTestUtils.SuggestionInfo; +import org.chromium.chrome.test.util.browser.Features; +import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.components.omnibox.AutocompleteMatchBuilder; import org.chromium.components.omnibox.AutocompleteResult; @@ -51,6 +55,7 @@ @CommandLineFlags. Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-features=OmniboxPedalsAndroidBatch1"}) @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) +@EnableFeatures(ChromeFeatureList.ENABLE_IPH) public class OmniboxPedalsRenderTest { // TODO(crbug.com/1312078): Enable the tests for incognito mode. @ParameterAnnotations.ClassParameter @@ -59,6 +64,8 @@ new ParameterSet().value(true, false).name("NightMode_RegularTab")); @Rule + public TestRule mFeaturesProcessorRule = new Features.JUnitProcessor(); + @Rule public ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus() .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_OMNIBOX)
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java index 487d782..480fda1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java
@@ -23,6 +23,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.FeatureList; import org.chromium.base.ThreadUtils; import org.chromium.base.test.metrics.HistogramTestRule; import org.chromium.base.test.params.ParameterAnnotations; @@ -35,10 +36,13 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.autofill.settings.AutofillPaymentMethodsFragment; import org.chromium.chrome.browser.browsing_data.ClearBrowsingDataTabsFragment; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.history.HistoryActivity; +import org.chromium.chrome.browser.history_clusters.HistoryClustersBottomSheetContent; import org.chromium.chrome.browser.omnibox.LocationBarLayout; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; +import org.chromium.chrome.browser.omnibox.action.OmniboxActionType; import org.chromium.chrome.browser.omnibox.action.OmniboxPedalType; import org.chromium.chrome.browser.omnibox.suggestions.pedal.PedalSuggestionView; import org.chromium.chrome.browser.password_manager.settings.PasswordSettings; @@ -53,11 +57,13 @@ import org.chromium.chrome.test.util.OmniboxTestUtils; import org.chromium.chrome.test.util.OmniboxTestUtils.SuggestionInfo; import org.chromium.components.browser_ui.accessibility.AccessibilitySettings; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.site_settings.SiteSettings; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.components.omnibox.AutocompleteMatchBuilder; import org.chromium.components.omnibox.AutocompleteResult; +import org.chromium.components.omnibox.action.HistoryClustersAction; import org.chromium.components.omnibox.action.OmniboxPedal; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestTouchUtils; @@ -72,8 +78,7 @@ * Tests of the Omnibox Pedals feature. */ @RunWith(ParameterizedRunner.class) -@CommandLineFlags. -Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-features=OmniboxPedalsAndroidBatch1"}) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @Batch(Batch.PER_CLASS) @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) public class OmniboxPedalsTest { @@ -99,6 +104,11 @@ @BeforeClass public static void beforeClass() { + FeatureList.TestValues featureTestValues = new FeatureList.TestValues(); + featureTestValues.addFeatureFlagOverride(ChromeFeatureList.HISTORY_JOURNEYS, true); + FeatureList.setTestValues(featureTestValues); + FeatureList.setTestCanUseDefaultsForTesting(); + sActivityTestRule.startMainActivityOnBlankPage(); sActivityTestRule.waitForActivityNativeInitializationComplete(); sActivityTestRule.waitForDeferredStartup(); @@ -155,7 +165,7 @@ return null; } - private void clickOnPedal(@OmniboxPedalType int omniboxPedalType) { + private void clickOnPedal() { SuggestionInfo<PedalSuggestionView> info = mOmniboxUtils.getSuggestionByType(OmniboxSuggestionUiType.PEDAL_SUGGESTION); CriteriaHelper.pollUiThread(() -> { @@ -188,7 +198,7 @@ private <T> T clickOnPedalToSettings( final Class<T> activityType, @OmniboxPedalType int pedalType) { return ActivityTestUtils.waitForActivity(InstrumentationRegistry.getInstrumentation(), - activityType, () -> { clickOnPedal(pedalType); }); + activityType, () -> clickOnPedal()); } /** @@ -252,6 +262,15 @@ .build(); } + private AutocompleteMatch createDummyHistoryClustersAction(String name) { + return AutocompleteMatchBuilder.searchWithType(OmniboxSuggestionType.SEARCH_SUGGEST) + .setDisplayText(name) + .setOmniboxPedal(new HistoryClustersAction(OmniboxActionType.HISTORY_CLUSTERS, + "hints", "suggestionContents", "accessibilitySuffix", "accessibilityHint", + GURL.emptyGURL(), name)) + .build(); + } + @Test @MediumTest public void testClearBrowsingDataOmniboxPedalSuggestion() throws InterruptedException { @@ -324,7 +343,7 @@ checkPedalWasShown(OmniboxPedalType.LAUNCH_INCOGNITO, /*expectShown=*/true); - clickOnPedal(OmniboxPedalType.LAUNCH_INCOGNITO); + clickOnPedal(); CriteriaHelper.pollUiThread(() -> { Tab tab = sActivityTestRule.getActivity().getActivityTab(); @@ -411,7 +430,7 @@ // On the phone, the history setting page will be shown as a {@link Fragment}, but on // the tablet, the history setting page will be shown as a native url. So we need to // have a different way to verify if the history setting page is opened. - clickOnPedal(OmniboxPedalType.VIEW_CHROME_HISTORY); + clickOnPedal(); CriteriaHelper.pollUiThread(() -> { Tab tab = sActivityTestRule.getActivity().getActivityTab(); Criteria.checkThat(tab, Matchers.notNullValue()); @@ -488,7 +507,7 @@ checkPedalWasShown(OmniboxPedalType.PLAY_CHROME_DINO_GAME, /*expectShown=*/true); // Click the pedal. - clickOnPedal(OmniboxPedalType.PLAY_CHROME_DINO_GAME); + clickOnPedal(); CriteriaHelper.pollUiThread(() -> { Tab tab = sActivityTestRule.getActivity().getActivityTab(); @@ -534,4 +553,30 @@ mOmniboxUtils.getSuggestionByType(OmniboxSuggestionUiType.PEDAL_SUGGESTION); Assert.assertNotNull("Should show a pedal if the suggestion is in top 3 suggestions", info); } + + @Test + @MediumTest + public void testHistoryClustersAction() { + mOmniboxUtils.requestFocus(); + List<AutocompleteMatch> suggestionsList = buildDummySuggestionsList(2, "Suggestion"); + suggestionsList.add(createDummyHistoryClustersAction("query")); + + mOmniboxUtils.setSuggestions( + AutocompleteResult.fromCache(suggestionsList, null), "Suggestion"); + mOmniboxUtils.checkSuggestionsShown(); + + SuggestionInfo<PedalSuggestionView> info = + mOmniboxUtils.getSuggestionByType(OmniboxSuggestionUiType.PEDAL_SUGGESTION); + Assert.assertNotNull("Should show", info); + + clickOnPedal(); + + CriteriaHelper.pollUiThread(() -> { + BottomSheetController bottomSheetController = sActivityTestRule.getActivity() + .getRootUiCoordinatorForTesting() + .getBottomSheetController(); + Criteria.checkThat(bottomSheetController.getCurrentSheetContent(), + Matchers.instanceOf(HistoryClustersBottomSheetContent.class)); + }); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesLayoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesLayoutTest.java index 93a8d187..4169474 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesLayoutTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesLayoutTest.java
@@ -4,20 +4,22 @@ package org.chromium.chrome.browser.suggestions.tile; +import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; +import static android.content.res.Configuration.ORIENTATION_PORTRAIT; + import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertTrue; +import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; -import static org.chromium.chrome.browser.ntp.NewTabPageLayout.getSiteSectionViewHolder; -import static org.chromium.chrome.browser.ntp.NewTabPageLayout.inflateSiteSection; import static org.chromium.chrome.test.util.browser.suggestions.mostvisited.FakeMostVisitedSites.createSiteSuggestion; import android.app.Activity; import android.content.pm.ActivityInfo; -import android.content.res.Configuration; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; @@ -26,52 +28,57 @@ import androidx.test.filters.MediumTest; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; -import org.chromium.base.ContextUtils; +import org.chromium.base.FeatureList; import org.chromium.base.ThreadUtils; import org.chromium.base.test.params.ParameterAnnotations; +import org.chromium.base.test.params.ParameterSet; import org.chromium.base.test.params.ParameterizedRunner; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.night_mode.ChromeNightModeTestUtils; import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.offlinepages.OfflinePageItem; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.suggestions.SiteSuggestion; -import org.chromium.chrome.browser.suggestions.SuggestionsConfig; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegateImpl; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.ui.native_page.TouchEnabledDelegate; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.chrome.test.util.ActivityTestUtils; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.chrome.test.util.NewTabPageTestUtils; -import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.offlinepages.FakeOfflinePageBridge; import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule; import org.chromium.chrome.test.util.browser.suggestions.mostvisited.FakeMostVisitedSites; -import org.chromium.components.browser_ui.widget.displaystyle.UiConfig; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.test.EmbeddedTestServerRule; -import org.chromium.ui.base.ViewUtils; +import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.test.util.NightModeTestUtils; import org.chromium.url.GURL; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeoutException; @@ -83,8 +90,12 @@ @RunWith(ParameterizedRunner.class) @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) @CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE) -@Features.DisableFeatures({ChromeFeatureList.SHOW_SCROLLABLE_MVT_ON_NTP_ANDROID}) public class MostVisitedTilesLayoutTest { + @ParameterAnnotations.ClassParameter + private static List<ParameterSet> sClassParams = + Arrays.asList(new ParameterSet().value(true).name("EnableScrollableMVTOnNTP"), + new ParameterSet().value(false).name("DisableScrollableMVTOnNTP")); + public final int TILE_GRID_ROWS = 2; public final int TILE_GRID_COLUMNS = 4; @@ -104,6 +115,13 @@ ChromeRenderTestRule.Component.UI_BROWSER_CONTENT_SUGGESTIONS_HISTORY) .build(); + @Mock + ActivityLifecycleDispatcher mActivityLifecycleDispatcher; + @Mock + WindowAndroid mWindowAndroid; + @Mock + TouchEnabledDelegate mTouchEnabledDelegate; + private static final String[] FAKE_MOST_VISITED_URLS = new String[] { "/chrome/test/data/android/navigate/one.html", "/chrome/test/data/android/navigate/two.html", @@ -120,6 +138,11 @@ new String[] {"ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE"}; private final CallbackHelper mLoadCompleteHelper = new CallbackHelper(); + private boolean mEnableScrollableMVT; + + public MostVisitedTilesLayoutTest(boolean enableScrollableMVT) { + mEnableScrollableMVT = enableScrollableMVT; + } @BeforeClass public static void setUpBeforeActivityLaunched() { @@ -137,58 +160,90 @@ ChromeNightModeTestUtils.tearDownNightModeAfterChromeActivityDestroyed(); } + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + FeatureList.TestValues testValuesOverride = new FeatureList.TestValues(); + testValuesOverride.addFeatureFlagOverride( + ChromeFeatureList.SHOW_SCROLLABLE_MVT_ON_NTP_ANDROID, mEnableScrollableMVT); + FeatureList.setTestValues(testValuesOverride); + } + @Test @MediumTest @Feature({"NewTabPage", "RenderTest"}) @ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class) // TODO(https://crbug.com/906151): Add new goldens and enable ExploreSites. @DisableFeatures({ChromeFeatureList.EXPLORE_SITES, ChromeFeatureList.QUERY_TILES}) - public void testTileGridAppearance(boolean nightModeEnabled) throws Exception { + public void testTilesLayoutAppearance(boolean nightModeEnabled) throws Exception { NewTabPage ntp = setUpFakeDataToShowOnNtp(FAKE_MOST_VISITED_URLS.length); - mRenderTestRule.render(getTileGridLayout(ntp), "ntp_tile_grid_layout"); + mRenderTestRule.render(getTilesLayout(ntp), + mEnableScrollableMVT ? "ntp_tile_carousel_layout" : "ntp_tile_grid_layout"); } @Test @MediumTest - @DisabledTest(message = "crbug.com/768779") @Feature({"NewTabPage", "RenderTest"}) - public void testModernTileGridAppearance_Full() throws IOException, InterruptedException { - View tileGridLayout = renderTiles(makeSuggestions(FAKE_MOST_VISITED_URLS.length)); + public void testModernTilesLayoutAppearance_Full() throws IOException, InterruptedException { + View tilesLayout = renderTiles(makeSuggestions(FAKE_MOST_VISITED_URLS.length)); - setOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, mActivityTestRule.getActivity()); - mRenderTestRule.render(tileGridLayout, "modern_full_grid_portrait"); + Activity activity = mActivityTestRule.getActivity(); + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + CriteriaHelper.pollUiThread(() -> { + Criteria.checkThat(activity.getResources().getConfiguration().orientation, + is(ORIENTATION_PORTRAIT)); + }); + mRenderTestRule.render(tilesLayout, + mEnableScrollableMVT ? "modern_full_carousel_portrait" + : "modern_full_grid_portrait"); - setOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, mActivityTestRule.getActivity()); - mRenderTestRule.render(tileGridLayout, "modern_full_grid_landscape"); + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + CriteriaHelper.pollUiThread(() -> { + Criteria.checkThat(activity.getResources().getConfiguration().orientation, + is(ORIENTATION_LANDSCAPE)); + }); + mRenderTestRule.render(tilesLayout, + mEnableScrollableMVT ? "modern_full_carousel_landscape" + : "modern_full_grid_landscape"); // In landscape, modern tiles should use all available space. - int tileGridMaxWidthPx = tileGridLayout.getResources().getDimensionPixelSize( + int tileGridMaxWidthPx = tilesLayout.getResources().getDimensionPixelSize( R.dimen.tile_grid_layout_max_width); - if (((FrameLayout) tileGridLayout.getParent()).getMeasuredWidth() > tileGridMaxWidthPx) { - assertThat(tileGridLayout.getMeasuredWidth(), greaterThan(tileGridMaxWidthPx)); + if (((FrameLayout) tilesLayout.getParent()).getMeasuredWidth() > tileGridMaxWidthPx) { + assertThat(tilesLayout.getMeasuredWidth(), greaterThan(tileGridMaxWidthPx)); } // Reset device orientation. - setOrientation( - ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, mActivityTestRule.getActivity()); + ActivityTestUtils.clearActivityOrientation(activity); } @Test @MediumTest - @DisabledTest(message = "crbug.com/768779") @Feature({"NewTabPage", "RenderTest"}) - public void testModernTileGridAppearance_Two() throws IOException, InterruptedException { - View tileGridLayout = renderTiles(makeSuggestions(2)); + public void testModernTilesLayoutAppearance_Two() throws IOException, InterruptedException { + View tilesLayout = renderTiles(makeSuggestions(2)); - setOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, mActivityTestRule.getActivity()); - mRenderTestRule.render(tileGridLayout, "modern_two_tiles_grid_portrait"); + Activity activity = mActivityTestRule.getActivity(); + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + CriteriaHelper.pollUiThread(() -> { + Criteria.checkThat(activity.getResources().getConfiguration().orientation, + is(ORIENTATION_PORTRAIT)); + }); + mRenderTestRule.render(tilesLayout, + mEnableScrollableMVT ? "modern_two_tiles_carousel_portrait" + : "modern_two_tiles_grid_portrait"); - setOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, mActivityTestRule.getActivity()); - mRenderTestRule.render(tileGridLayout, "modern_two_tiles_grid_landscape"); + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + CriteriaHelper.pollUiThread(() -> { + Criteria.checkThat(activity.getResources().getConfiguration().orientation, + is(ORIENTATION_LANDSCAPE)); + }); + mRenderTestRule.render(tilesLayout, + mEnableScrollableMVT ? "modern_two_tiles_carousel_landscape" + : "modern_two_tiles_grid_landscape"); // Reset device orientation. - setOrientation( - ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, mActivityTestRule.getActivity()); + ActivityTestUtils.clearActivityOrientation(activity); } @Test @@ -244,51 +299,20 @@ return ntp; } - private void setOrientation(final int requestedOrientation, final Activity activity) { - if (orientationMatchesRequest(activity, requestedOrientation)) return; - - TestThreadUtils.runOnUiThreadBlocking( - () -> activity.setRequestedOrientation(requestedOrientation)); - - CriteriaHelper.pollUiThread( - () -> orientationMatchesRequest(activity, requestedOrientation)); - } - - /** - * Checks whether the requested orientation matches the current one. - * @param activity Activity to check the orientation from. We pull its {@link Configuration} and - * content {@link View}. - * @param requestedOrientation The requested orientation, as used in - * {@link ActivityInfo#screenOrientation}. - */ - private boolean orientationMatchesRequest(Activity activity, int requestedOrientation) { - // Note: Requests use a constant from ActivityInfo, not Configuration.ORIENTATION_*! - boolean expectLandscape = requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; - - // We check the orientation by looking at the dimensions of the content view. Looking at - // orientation from the configuration is not reliable as sometimes the activity gets the - // event that its configuration changed, but has not updated its layout yet. - Configuration configuration = activity.getResources().getConfiguration(); - View contentView = activity.findViewById(android.R.id.content); - int smallestWidthPx = ViewUtils.dpToPx(activity, configuration.smallestScreenWidthDp); - boolean viewIsLandscape = contentView.getMeasuredWidth() > smallestWidthPx; - - return expectLandscape == viewIsLandscape; - } - - private MostVisitedTilesGridLayout getTileGridLayout(NewTabPage ntp) { - MostVisitedTilesGridLayout mostVisitedTilesGridLayout = - ntp.getView().findViewById(R.id.mv_tiles_layout); - assertNotNull("Unable to retrieve the TileGridLayout.", mostVisitedTilesGridLayout); - return mostVisitedTilesGridLayout; + private ViewGroup getTilesLayout(NewTabPage ntp) { + ViewGroup mostVisitedTilesLayout = ntp.getView().findViewById(R.id.mv_tiles_layout); + assertNotNull("Unable to retrieve the " + + (mEnableScrollableMVT ? "tile_carousel_layout." : "tile_grid_layout."), + mostVisitedTilesLayout); + return mostVisitedTilesLayout; } /** * Starts and sets up an activity to render the provided site suggestions in the activity. * @return the layout in which the suggestions are rendered. */ - private MostVisitedTilesGridLayout renderTiles(List<SiteSuggestion> siteSuggestions, - List<GURL> offlineUrls) throws InterruptedException { + private ViewGroup renderTiles(List<SiteSuggestion> siteSuggestions, List<GURL> offlineUrls) + throws InterruptedException { // Launching the activity, that should now use the right UI. mActivityTestRule.startMainActivityOnBlankPage(); ChromeActivity activity = mActivityTestRule.getActivity(); @@ -298,28 +322,41 @@ mostVisitedSites.setTileSuggestions(siteSuggestions); mSuggestionsDeps.getFactory().mostVisitedSites = mostVisitedSites; - FrameLayout contentView = new FrameLayout(activity); - UiConfig uiConfig = new UiConfig(contentView); + ViewGroup contentView = new FrameLayout(activity); return TestThreadUtils.runOnUiThreadBlockingNoException(() -> { + setOfflinePageBridge(offlineUrls); activity.setContentView(contentView); - TileGridViewHolder viewHolder = getSiteSectionViewHolder( - inflateSiteSection(contentView), TILE_GRID_ROWS, TILE_GRID_COLUMNS); - uiConfig.updateDisplayStyle(); - createSiteSection(viewHolder, uiConfig, offlineUrls); - contentView.addView(viewHolder.getItemView()); - - return (MostVisitedTilesGridLayout) viewHolder.getItemView(); + ViewGroup containerLayout = + (ViewGroup) LayoutInflater.from(contentView.getContext()) + .inflate(R.layout.mv_tiles_container, contentView, false); + containerLayout.setVisibility(View.VISIBLE); + contentView.addView(containerLayout); + initializeCoordinator(containerLayout); + ViewGroup mostVisitedTilesLayout = containerLayout.findViewById(R.id.mv_tiles_layout); + assertNotNull(mostVisitedTilesLayout); + return mostVisitedTilesLayout; }); } - private MostVisitedTilesGridLayout renderTiles(List<SiteSuggestion> siteSuggestions) + private ViewGroup renderTiles(List<SiteSuggestion> siteSuggestions) throws InterruptedException { return renderTiles(siteSuggestions, Collections.emptyList()); } - private void createSiteSection( - final SiteSectionViewHolder viewHolder, UiConfig uiConfig, List<GURL> offlineUrls) { + private void setOfflinePageBridge(List<GURL> offlineUrls) { + FakeOfflinePageBridge offlinePageBridge = new FakeOfflinePageBridge(); + List<OfflinePageItem> offlinePageItems = new ArrayList<>(); + for (int i = 0; i < offlineUrls.size(); i++) { + offlinePageItems.add(FakeOfflinePageBridge.createOfflinePageItem( + offlineUrls.get(i).getSpec(), i + 1L)); + } + offlinePageBridge.setItems(offlinePageItems); + offlinePageBridge.setIsOfflinePageModelLoaded(true); + mSuggestionsDeps.getFactory().offlinePageBridge = offlinePageBridge; + } + + private void initializeCoordinator(ViewGroup containerLayout) { ThreadUtils.assertOnUiThread(); ChromeActivity activity = mActivityTestRule.getActivity(); @@ -329,15 +366,6 @@ SuggestionsUiDelegate uiDelegate = new SuggestionsUiDelegateImpl(null, profile, null, activity.getSnackbarManager()); - FakeOfflinePageBridge offlinePageBridge = new FakeOfflinePageBridge(); - List<OfflinePageItem> offlinePageItems = new ArrayList<>(); - for (int i = 0; i < offlineUrls.size(); i++) { - offlinePageItems.add(FakeOfflinePageBridge.createOfflinePageItem( - offlineUrls.get(i).getSpec(), i + 1L)); - } - offlinePageBridge.setItems(offlinePageItems); - offlinePageBridge.setIsOfflinePageModelLoaded(true); - TileGroup.Delegate delegate = new TileGroupDelegateImpl(activity, profile, null, null) { @Override public void onLoadingComplete(List<Tile> tiles) { @@ -346,33 +374,9 @@ } }; - TileGroup.Observer observer = new TileGroup.Observer() { - @Override - public void onTileDataChanged() { - viewHolder.refreshData(); - } - - @Override - public void onTileCountChanged() {} - - @Override - public void onTileIconChanged(Tile tile) { - viewHolder.updateIconView(tile); - } - - @Override - public void onTileOfflineBadgeVisibilityChanged(Tile tile) { - viewHolder.updateOfflineBadge(tile); - } - }; - - TileRenderer tileRenderer = new TileRenderer(ContextUtils.getApplicationContext(), - SuggestionsConfig.getTileStyle(uiConfig), 1, uiDelegate.getImageFetcher()); - TileGroup tileGroup = new TileGroup( - tileRenderer, uiDelegate, null, delegate, observer, offlinePageBridge); - tileGroup.onSwitchToForeground(false); - viewHolder.bindDataSource(tileGroup, tileRenderer); - tileGroup.startObserving(TILE_GRID_COLUMNS * TILE_GRID_ROWS); - viewHolder.refreshData(); + MostVisitedTilesCoordinator coordinator = new MostVisitedTilesCoordinator(activity, + mActivityLifecycleDispatcher, containerLayout, mWindowAndroid, false, + mEnableScrollableMVT, TILE_GRID_ROWS, TILE_GRID_COLUMNS, null, null); + coordinator.initWithNative(uiDelegate, delegate, mTouchEnabledDelegate); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupTest.java index 33adae5e..d119aa7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupTest.java
@@ -229,7 +229,8 @@ tileView = ((MostVisitedTilesCarouselLayout) getTileLayout()) .findTileViewForTesting(suggestion); } else { - tileView = ((MostVisitedTilesGridLayout) getTileLayout()).getTileView(suggestion); + tileView = ((MostVisitedTilesGridLayout) getTileLayout()) + .findTileViewForTesting(suggestion); } return tileView; }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupUnitTest.java index 3c091a7..f8abd7f8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupUnitTest.java
@@ -301,14 +301,13 @@ mTileGroupDelegate, mTileGroupObserver, mOfflinePageBridge); tileGroup.startObserving(MAX_TILES_TO_FETCH); - TileGridViewHolder tileGrid = setupView(tileGroup); - MostVisitedTilesGridLayout layout = (MostVisitedTilesGridLayout) tileGrid.getItemView(); + MostVisitedTilesGridLayout layout = setupView(); // Initialise the internal list of tiles mMostVisitedSites.setTileSuggestions(URLS); // Render them to the layout. - tileGrid.refreshData(); + refreshData(tileGroup, layout); assertThat(layout.getChildCount(), is(2)); assertThat(((SuggestionsTileView) layout.getChildAt(0)).getUrl().getSpec(), is(URLS[0])); assertThat(((SuggestionsTileView) layout.getChildAt(1)).getUrl().getSpec(), is(URLS[1])); @@ -324,13 +323,13 @@ TileGroup tileGroup = new TileGroup(mTileRenderer, uiDelegate, mContextMenuManager, mTileGroupDelegate, mTileGroupObserver, mOfflinePageBridge); tileGroup.startObserving(MAX_TILES_TO_FETCH); - TileGridViewHolder tileGrid = setupView(tileGroup); + MostVisitedTilesGridLayout layout = setupView(); // Initialise the internal list of tiles mMostVisitedSites.setTileSuggestions(URLS[0], URLS[1], URLS[0]); // Render them to the layout. The duplicated URL should not trigger an exception. - tileGrid.refreshData(); + refreshData(tileGroup, layout); } @Test @@ -346,8 +345,7 @@ mMostVisitedSites.setTileSuggestions(URLS); // Initialise the layout with views whose URLs don't match the ones of the new tiles. - TileGridViewHolder tileGrid = setupView(tileGroup); - MostVisitedTilesGridLayout layout = (MostVisitedTilesGridLayout) tileGrid.getItemView(); + MostVisitedTilesGridLayout layout = setupView(); SuggestionsTileView view1 = mSuggestionsTileView1; layout.addView(view1); @@ -355,7 +353,7 @@ layout.addView(view2); // The tiles should be updated, the old ones removed. - tileGrid.refreshData(); + refreshData(tileGroup, layout); assertThat(layout.getChildCount(), is(2)); assertThat(layout.indexOfChild(view1), is(-1)); assertThat(layout.indexOfChild(view2), is(-1)); @@ -383,7 +381,7 @@ layout.addView(view2); // The tiles should be updated, the old ones reused. - setupView(tileGroup).refreshData(); + refreshData(tileGroup); assertThat(layout.getChildCount(), is(2)); assertThat(layout.getChildAt(0), CoreMatchers.is(view1)); assertThat(layout.getChildAt(1), CoreMatchers.is(view2)); @@ -425,14 +423,6 @@ verify(mTileGroupObserver, never()).onTileIconChanged(tile); } - private TileGridViewHolder setupView(TileGroup tileGroup) { - MostVisitedTilesGridLayout layout = - new MostVisitedTilesGridLayout(ContextUtils.getApplicationContext(), null); - TileGridViewHolder tileGrid = new TileGridViewHolder(layout, 4, 2); - tileGrid.bindDataSource(tileGroup, mTileRenderer); - return tileGrid; - } - @Test @UiThreadTest @SmallTest @@ -443,7 +433,7 @@ // Notify for a second set. mMostVisitedSites.setTileSuggestions(URLS); - setupView(tileGroup).refreshData(); + refreshData(tileGroup); mImageFetcher.fulfillLargeIconRequests(); // Data changed but no loading complete event is sent @@ -463,7 +453,7 @@ // Notify for a second set. mMostVisitedSites.setTileSuggestions(URLS); tileGroup.onSwitchToForeground(/* trackLoadTask: */ false); - setupView(tileGroup).refreshData(); + refreshData(tileGroup); mImageFetcher.fulfillLargeIconRequests(); // Data changed but no loading complete event is sent (same as sync) @@ -483,7 +473,7 @@ // Notify for a second set. mMostVisitedSites.setTileSuggestions(URLS); tileGroup.onSwitchToForeground(/* trackLoadTask: */ true); - setupView(tileGroup).refreshData(); + refreshData(tileGroup); mImageFetcher.fulfillLargeIconRequests(); // Data changed but no loading complete event is sent @@ -492,6 +482,23 @@ verify(mTileGroupDelegate).onLoadingComplete(any()); } + private MostVisitedTilesGridLayout setupView() { + return new MostVisitedTilesGridLayout(ContextUtils.getApplicationContext(), null); + } + + private void refreshData(TileGroup tileGroup) { + MostVisitedTilesGridLayout layout = setupView(); + refreshData(tileGroup, layout); + } + + private void refreshData(TileGroup tileGroup, ViewGroup tilesLayout) { + assert tileGroup.getTileSections().size() == 1; + List<Tile> tiles = tileGroup.getTileSections().get(TileSectionType.PERSONALIZED); + assert tiles != null; + mTileRenderer.renderTileSection(tiles, tilesLayout, tileGroup.getTileSetupDelegate()); + tileGroup.notifyTilesRendered(); + } + /** {@link #initialiseTileGroup(boolean, String...)} override that does not defer loads. */ private TileGroup initialiseTileGroup(String... urls) { return initialiseTileGroup(false, urls); @@ -512,7 +519,7 @@ TileGroup tileGroup = new TileGroup(mTileRenderer, mSuggestionsUiDelegate, mContextMenuManager, mTileGroupDelegate, mTileGroupObserver, mOfflinePageBridge); tileGroup.startObserving(MAX_TILES_TO_FETCH); - setupView(tileGroup).refreshData(); + refreshData(tileGroup); reset(mTileGroupObserver); reset(mTileGroupDelegate);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java index ae331679..9df8eb8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java
@@ -666,10 +666,11 @@ Assert.assertEquals(15, LaunchTypeAtCreation.FROM_APP_WIDGET); Assert.assertEquals(16, LaunchTypeAtCreation.FROM_LONGPRESS_INCOGNITO); Assert.assertEquals(17, LaunchTypeAtCreation.FROM_RECENT_TABS); + Assert.assertEquals(18, LaunchTypeAtCreation.FROM_READING_LIST); Assert.assertEquals( "Need to increment 1 to expected value each time a LaunchTypeAtCreation " + "is added. Also need to add any new LaunchTypeAtCreation to this test.", - 20, LaunchTypeAtCreation.names.length); + 21, LaunchTypeAtCreation.names.length); } @SmallTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/tab_restore/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/tab_restore/OWNERS new file mode 100644 index 0000000..84a17fb2 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/tab_restore/OWNERS
@@ -0,0 +1 @@ +file://chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/OWNERS
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/OWNERS index 9cf8c9c8..4968127 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/OWNERS +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/OWNERS
@@ -1,2 +1,4 @@ +file://chrome/browser/tabmodel/OWNERS + per-file MultiInstanceMigrationTest.java=twellington@chromium.org per-file TabModelMergingTest.java=twellington@chromium.org
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2ApiTestHelper.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2ApiTestHelper.java index 7891857..1eb994a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2ApiTestHelper.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2ApiTestHelper.java
@@ -41,6 +41,7 @@ import org.chromium.components.webauthn.Fido2Api; import org.chromium.content.browser.ClientDataJsonImpl; import org.chromium.content.browser.ClientDataJsonImplJni; +import org.chromium.content_public.browser.WebAuthnCredentialDetails; import org.chromium.mojo_base.mojom.TimeDelta; import org.chromium.payments.mojom.PaymentCurrencyAmount; import org.chromium.url.internal.mojom.Origin; @@ -503,4 +504,17 @@ }; mocker.mock(ClientDataJsonImplJni.TEST_HOOKS, clientDataJsonJni); } + + /** + * Creates a {@link WebAuthnCredentailDetails} object for testing. + * @return a newly created {@link WebAuthnCredentialDetails}. + */ + public static WebAuthnCredentialDetails getCredentialDetails() { + WebAuthnCredentialDetails credential = new WebAuthnCredentialDetails(); + credential.mUserId = "1098237235409872".getBytes(UTF_8); + credential.mUserName = "avery.a.jones@example.com"; + credential.mUserDisplayName = "Avery A. Jones"; + credential.mCredentialId = new byte[] {8, 7, 6}; + return credential; + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestTest.java index a92fe1e8..cf39210 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestTest.java
@@ -13,6 +13,9 @@ import androidx.test.filters.SmallTest; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; + import org.junit.Assert; import org.junit.Assume; import org.junit.Before; @@ -38,6 +41,7 @@ import org.chromium.blink.mojom.MakeCredentialAuthenticatorResponse; import org.chromium.blink.mojom.PaymentOptions; import org.chromium.blink.mojom.PublicKeyCredentialCreationOptions; +import org.chromium.blink.mojom.PublicKeyCredentialDescriptor; import org.chromium.blink.mojom.PublicKeyCredentialParameters; import org.chromium.blink.mojom.PublicKeyCredentialRequestOptions; import org.chromium.blink.mojom.PublicKeyCredentialType; @@ -47,6 +51,7 @@ import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule; import org.chromium.components.webauthn.AuthenticatorImpl; import org.chromium.components.webauthn.Fido2Api; +import org.chromium.components.webauthn.Fido2ApiCallHelper; import org.chromium.components.webauthn.Fido2ApiHandler; import org.chromium.components.webauthn.Fido2CredentialRequest; import org.chromium.components.webauthn.FidoErrorResponseCallback; @@ -57,6 +62,7 @@ import org.chromium.components.webauthn.MakeCredentialResponseCallback; import org.chromium.content_public.browser.RenderFrameHost; import org.chromium.content_public.browser.WebAuthenticationDelegate; +import org.chromium.content_public.browser.WebAuthnCredentialDetails; import org.chromium.content_public.browser.test.mock.MockRenderFrameHost; import org.chromium.content_public.browser.test.mock.MockWebContents; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -178,6 +184,16 @@ } } + private static class MockFido2ApiCallHelper extends Fido2ApiCallHelper { + @Override + public void invokeFido2GetCredentials(String relyingPartyId, int supportLevel, + OnSuccessListener<List<WebAuthnCredentialDetails>> successCallback, + OnFailureListener failureCallback) { + WebAuthnCredentialDetails credential = Fido2ApiTestHelper.getCredentialDetails(); + successCallback.onSuccess(Arrays.asList(new WebAuthnCredentialDetails[] {credential})); + } + } + private static class AuthenticatorCallback { private Integer mStatus; private MakeCredentialAuthenticatorResponse mMakeCredentialResponse; @@ -337,6 +353,8 @@ private static class MockAuthenticatorRenderFrameHost extends MockRenderFrameHost { private GURL mLastUrl; private boolean mIsPaymentCredentialCreation; + private byte[] mSelectedCredentialId; + private List<WebAuthnCredentialDetails> mExpectedCredentialList; @Override public GURL getLastCommittedURL() { @@ -360,6 +378,49 @@ mIsPaymentCredentialCreation = isPaymentCredentialCreation; return 0; } + + @Override + public void onCredentialsDetailsListReceived( + List<WebAuthnCredentialDetails> credentialList, Callback<byte[]> callback) { + Assert.assertEquals(mExpectedCredentialList.size(), credentialList.size()); + for (int i = 0; i < credentialList.size(); i++) { + Assert.assertEquals( + mExpectedCredentialList.get(0).mUserName, credentialList.get(0).mUserName); + Assert.assertEquals(mExpectedCredentialList.get(0).mUserDisplayName, + credentialList.get(0).mUserDisplayName); + Assert.assertArrayEquals(mExpectedCredentialList.get(0).mCredentialId, + credentialList.get(0).mCredentialId); + Assert.assertArrayEquals( + mExpectedCredentialList.get(0).mUserId, credentialList.get(0).mUserId); + } + + if (mSelectedCredentialId != null) { + callback.onResult(mSelectedCredentialId); + return; + } + + /* An empty credential list can occur if a device has no applicable credentials. + * In production this is passed to native code and the callback will never be + * invoked. For the sake of testing we invoke with an empty credential selection, + * which normally would imply an error response. + */ + if (credentialList.isEmpty()) { + callback.onResult(new byte[0]); + return; + } + + /* Return the first ID in the list if one has not been explicitly set. */ + callback.onResult(credentialList.get(0).mCredentialId); + } + + public void setSelectedCredentialId(byte[] credentialId) { + mSelectedCredentialId = credentialId; + } + + public void setExpectedCredentialDetailsList( + List<WebAuthnCredentialDetails> credentialList) { + mExpectedCredentialList = credentialList; + } } @Before @@ -387,6 +448,8 @@ mIntentSender, WebAuthenticationDelegate.Support.BROWSER); Fido2ApiHandler.overrideInstanceForTesting(new MockFido2ApiHandler(mRequest)); + Fido2ApiCallHelper.overrideInstanceForTesting(new MockFido2ApiCallHelper()); + mRequest.setWebContentsForTesting(mMockWebContents); mStartTimeMs = SystemClock.elapsedRealtime(); } @@ -1226,4 +1289,44 @@ Assert.assertNull(mCallback.getGetAssertionResponse()); Fido2ApiTestHelper.verifyRespondedBeforeTimeout(mStartTimeMs); } + + @Test + @SmallTest + public void testGetAssertion_conditionalUi_success() { + mIntentSender.setNextResultIntent(Fido2ApiTestHelper.createSuccessfulGetAssertionIntent()); + mFrameHost.setExpectedCredentialDetailsList(Arrays.asList( + new WebAuthnCredentialDetails[] {Fido2ApiTestHelper.getCredentialDetails()})); + + mRequestOptions.allowCredentials = new PublicKeyCredentialDescriptor[0]; + mRequestOptions.isConditional = true; + + mRequest.handleGetAssertionRequest(mRequestOptions, mFrameHost, mOrigin, /*payment=*/null, + (responseStatus, response) + -> mCallback.onSignResponse(responseStatus, response), + errorStatus -> mCallback.onError(errorStatus)); + mCallback.blockUntilCalled(); + Assert.assertEquals(Integer.valueOf(AuthenticatorStatus.SUCCESS), mCallback.getStatus()); + Fido2ApiTestHelper.validateGetAssertionResponse(mCallback.getGetAssertionResponse()); + Fido2ApiTestHelper.verifyRespondedBeforeTimeout(mStartTimeMs); + } + + @Test + @SmallTest + public void testGetAssertion_conditionalUi_failureEmptyCredential() { + mFrameHost.setSelectedCredentialId(new byte[0]); + mFrameHost.setExpectedCredentialDetailsList(Arrays.asList( + new WebAuthnCredentialDetails[] {Fido2ApiTestHelper.getCredentialDetails()})); + mRequestOptions.allowCredentials = new PublicKeyCredentialDescriptor[0]; + mRequestOptions.isConditional = true; + + mRequest.handleGetAssertionRequest(mRequestOptions, mFrameHost, mOrigin, /*payment=*/null, + (responseStatus, response) + -> mCallback.onSignResponse(responseStatus, response), + errorStatus -> mCallback.onError(errorStatus)); + mCallback.blockUntilCalled(); + Assert.assertEquals( + Integer.valueOf(AuthenticatorStatus.UNKNOWN_ERROR), mCallback.getStatus()); + Assert.assertNull(mCallback.getGetAssertionResponse()); + Fido2ApiTestHelper.verifyRespondedBeforeTimeout(mStartTimeMs); + } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/ReadingListSectionHeaderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/ReadingListSectionHeaderTest.java index 45ec1f10..2521d51 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/ReadingListSectionHeaderTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/ReadingListSectionHeaderTest.java
@@ -20,9 +20,9 @@ import org.chromium.base.metrics.test.ShadowRecordHistogram; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.R; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkListEntry.ViewType; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.bookmarks.BookmarkType; import java.util.ArrayList; @@ -42,8 +42,8 @@ private BookmarkListEntry createReadingListEntry(long id, boolean read, int dateAdded) { BookmarkId bookmarkId = new BookmarkId(id, BookmarkType.READING_LIST); - BookmarkItem bookmarkItem = new BookmarkItem( - bookmarkId, null, null, false, null, false, false, dateAdded, read); + BookmarkItem bookmarkItem = new BookmarkItem(bookmarkId, null, null, false, null, false, + false, dateAdded, read, /*readingListSwappable=*/false); return BookmarkListEntry.createBookmarkEntry(bookmarkItem, /*powerBookmarkMeta=*/null); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadLaterIPHControllerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadLaterIPHControllerUnitTest.java index 83387dc..a510062 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadLaterIPHControllerUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadLaterIPHControllerUnitTest.java
@@ -40,7 +40,7 @@ /** Unit test for {@link ReadLaterIPHController}. */ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) -@EnableFeatures(ChromeFeatureList.READ_LATER) +@EnableFeatures({ChromeFeatureList.READ_LATER, ChromeFeatureList.ENABLE_IPH}) public class ReadLaterIPHControllerUnitTest { @Rule public TestRule mFeaturesProcessor = new JUnitProcessor();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadingListUtilsUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadingListUtilsUnitTest.java index 7edef7e..71e8b4ed 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadingListUtilsUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadingListUtilsUnitTest.java
@@ -26,12 +26,12 @@ import org.chromium.base.FeatureList.TestValues; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.bookmarks.BookmarkBridge; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkModel; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.bookmarks.BookmarkType; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.url.GURL; @@ -189,7 +189,8 @@ BookmarkId existingBookmarkId = new BookmarkId(0, BookmarkType.NORMAL); BookmarkItem existingBookmark = new BookmarkItem(existingBookmarkId, "Test", JUnitTestGURLs.getGURL(JUnitTestGURLs.NTP_URL), /*isFolder=*/false, /*parent=*/null, - /*isEditable=*/true, /*isManaged=*/false, /*dateAdded*/ 0, /*read=*/false); + /*isEditable=*/true, /*isManaged=*/false, /*dateAdded*/ 0, /*read=*/false, + /*readingListSwappable=*/false); BookmarkBridge bookmarkBridge = Mockito.mock(BookmarkBridge.class); doReturn(existingBookmark).when(bookmarkBridge).getBookmarkById(existingBookmarkId); BookmarkId newBookmarkId = new BookmarkId(0, BookmarkType.READING_LIST); @@ -218,7 +219,8 @@ BookmarkId existingBookmarkId = new BookmarkId(0, BookmarkType.READING_LIST); BookmarkItem existingBookmark = new BookmarkItem(existingBookmarkId, "Test", JUnitTestGURLs.getGURL(JUnitTestGURLs.NTP_URL), /*isFolder=*/false, /*parent=*/null, - /*isEditable=*/true, /*isManaged=*/false, /*dateAdded*/ 0, /*read=*/false); + /*isEditable=*/true, /*isManaged=*/false, /*dateAdded*/ 0, /*read=*/false, + /*readingListSwappable=*/false); BookmarkBridge bookmarkBridge = Mockito.mock(BookmarkBridge.class); doReturn(existingBookmark).when(bookmarkBridge).getBookmarkById(existingBookmarkId); BookmarkId newBookmarkId = new BookmarkId(0, BookmarkType.NORMAL); @@ -247,11 +249,13 @@ BookmarkId existingBookmarkId1 = new BookmarkId(1, BookmarkType.READING_LIST); BookmarkItem existingBookmark1 = new BookmarkItem(existingBookmarkId1, "Test1", JUnitTestGURLs.getGURL(JUnitTestGURLs.NTP_URL), /*isFolder=*/false, /*parent=*/null, - /*isEditable=*/true, /*isManaged=*/false, /*dateAdded*/ 0, /*read=*/false); + /*isEditable=*/true, /*isManaged=*/false, /*dateAdded*/ 0, /*read=*/false, + /*readingListSwappable=*/false); BookmarkId existingBookmarkId2 = new BookmarkId(2, BookmarkType.READING_LIST); BookmarkItem existingBookmark2 = new BookmarkItem(existingBookmarkId2, "Test2", JUnitTestGURLs.getGURL(JUnitTestGURLs.NTP_URL), /*isFolder=*/false, /*parent=*/null, - /*isEditable=*/true, /*isManaged=*/false, /*dateAdded*/ 0, /*read=*/false); + /*isEditable=*/true, /*isManaged=*/false, /*dateAdded*/ 0, /*read=*/false, + /*readingListSwappable=*/false); BookmarkBridge bookmarkBridge = Mockito.mock(BookmarkBridge.class); doReturn(existingBookmark1).when(bookmarkBridge).getBookmarkById(existingBookmarkId1); doReturn(existingBookmark2).when(bookmarkBridge).getBookmarkById(existingBookmarkId2); @@ -291,7 +295,8 @@ BookmarkId existingBookmarkId = new BookmarkId(0, BookmarkType.NORMAL); BookmarkItem existingBookmark = new BookmarkItem(existingBookmarkId, "Test", JUnitTestGURLs.getGURL(JUnitTestGURLs.NTP_URL), /*isFolder=*/false, /*parent=*/null, - /*isEditable=*/true, /*isManaged=*/false, /*dateAdded*/ 0, /*read=*/false); + /*isEditable=*/true, /*isManaged=*/false, /*dateAdded*/ 0, /*read=*/false, + /*readingListSwappable=*/false); BookmarkBridge bookmarkBridge = Mockito.mock(BookmarkBridge.class); ArrayList<BookmarkId> bookmarks = new ArrayList<>();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedMediatorUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedMediatorUnitTest.java index f79eee3e..a0f2deb 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedMediatorUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedMediatorUnitTest.java
@@ -22,6 +22,7 @@ import android.content.res.Resources; import android.util.DisplayMetrics; import android.view.View; +import android.view.ViewGroup; import android.view.ViewStub; import org.junit.Assert; @@ -37,6 +38,7 @@ import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; +import org.chromium.chrome.browser.suggestions.SiteSuggestion; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate; import org.chromium.chrome.browser.suggestions.mostvisited.MostVisitedSites; import org.chromium.chrome.test.util.browser.suggestions.mostvisited.FakeMostVisitedSites; @@ -58,9 +60,7 @@ @Mock DisplayMetrics mDisplayMetrics; @Mock - View mMvTilesContainerLayout; - @Mock - MostVisitedTilesCarouselLayout mMvTilesLayout; + ViewGroup mMvTilesLayout; @Mock ViewStub mNoMvPlaceholderStub; @Mock @@ -70,6 +70,8 @@ @Mock SuggestionsTileView mTileView; @Mock + SiteSuggestion mData; + @Mock TileRenderer mTileRenderer; @Mock SuggestionsUiDelegate mSuggestionsUiDelegate; @@ -81,6 +83,10 @@ OfflinePageBridge mOfflinePageBridge; @Mock private TemplateUrlService mTemplateUrlService; + @Mock + private Runnable mSnapshotTileGridChangedRunnable; + @Mock + private Runnable mTileCountChangedRunnable; private FakeMostVisitedSites mMostVisitedSites; private PropertyModel mModel; @@ -93,20 +99,18 @@ when(mResources.getConfiguration()).thenReturn(mConfiguration); mDisplayMetrics.widthPixels = 1000; when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics); - when(mResources.getDimensionPixelSize(R.dimen.tile_view_padding_edge_portrait)) .thenReturn(12); when(mResources.getDimensionPixelSize(R.dimen.tile_view_padding_landscape)).thenReturn(16); when(mResources.getDimensionPixelOffset(R.dimen.tile_view_width)).thenReturn(80); + when(mTileView.getData()).thenReturn(mData); + when(mTile.getData()).thenReturn(mData); + mMvTilesLayout.addView(mTileView); when(mMvTilesLayout.getChildCount()).thenReturn(1); - when(mMvTilesLayout.findTileView(mTile)).thenReturn(mTileView); - - when(mMvTilesContainerLayout.findViewById(R.id.tile_grid_placeholder_stub)) - .thenReturn(mNoMvPlaceholderStub); + when(mMvTilesLayout.getChildAt(0)).thenReturn(mTileView); when(mNoMvPlaceholderStub.inflate()).thenReturn(mNoMvPlaceholder); - when(mMvTilesContainerLayout.findViewById(R.id.mv_tiles_layout)).thenReturn(mMvTilesLayout); mMostVisitedSites = new FakeMostVisitedSites(); doAnswer(invocation -> { @@ -129,6 +133,7 @@ verify(mTileRenderer, atLeastOnce()) .renderTileSection(anyList(), eq(mMvTilesLayout), any()); verify(mMvTilesLayout).addView(any()); + verify(mSnapshotTileGridChangedRunnable, atLeastOnce()).run(); } @Test @@ -147,6 +152,7 @@ Assert.assertFalse(mModel.get(IS_MVT_LAYOUT_VISIBLE)); Assert.assertNotNull(mModel.get(PLACEHOLDER_VIEW)); + verify(mTileCountChangedRunnable, atLeastOnce()).run(); // When there is mv tile and the default search engine doesn't have logo, the placeholder // should be hidden and the mv tiles layout should be shown. @@ -164,6 +170,7 @@ mMediator.onTileIconChanged(mTile); verify(mTileView).renderIcon(mTile); + verify(mSnapshotTileGridChangedRunnable, atLeastOnce()).run(); } @Test @@ -172,6 +179,7 @@ mMediator.onTileOfflineBadgeVisibilityChanged(mTile); verify(mTileView).renderOfflineBadge(mTile); + verify(mSnapshotTileGridChangedRunnable, atLeastOnce()).run(); } @Test @@ -202,7 +210,7 @@ } @Test - public void testSetPortraitPaddings() { + public void testSetPortraitPaddings_ScrollableMVT() { mConfiguration.orientation = Configuration.ORIENTATION_PORTRAIT; createMediator(); mMediator.onTileDataChanged(); @@ -218,6 +226,15 @@ } @Test + public void testSetPortraitPaddings_NonScrollableMVT() { + mConfiguration.orientation = Configuration.ORIENTATION_PORTRAIT; + createMediator(/*isScrollableMVTEnabled=*/false); + mMediator.onTileDataChanged(); + Assert.assertNull(mModel.get(HORIZONTAL_EDGE_PADDINGS)); + Assert.assertNull(mModel.get(HORIZONTAL_INTERVAL_PADDINGS)); + } + + @Test public void testSetLandscapePaddings() { mConfiguration.orientation = Configuration.ORIENTATION_LANDSCAPE; createMediator(); @@ -229,9 +246,23 @@ (int) (mModel.get(HORIZONTAL_INTERVAL_PADDINGS))); } + @Test + public void testSetLandscapePaddings_NonScrollableMVT() { + mConfiguration.orientation = Configuration.ORIENTATION_LANDSCAPE; + createMediator(/*isScrollableMVTEnabled=*/false); + mMediator.onTileDataChanged(); + Assert.assertNull(mModel.get(HORIZONTAL_EDGE_PADDINGS)); + Assert.assertNull(mModel.get(HORIZONTAL_INTERVAL_PADDINGS)); + } + private void createMediator() { - mMediator = new MostVisitedTilesMediator( - mResources, mMvTilesContainerLayout, mTileRenderer, mModel, false, false); + createMediator(true); + } + + private void createMediator(boolean isScrollableMVTEnabled) { + mMediator = new MostVisitedTilesMediator(mResources, mMvTilesLayout, mNoMvPlaceholderStub, + mTileRenderer, mModel, false, isScrollableMVTEnabled, false, + mSnapshotTileGridChangedRunnable, mTileCountChangedRunnable); mMediator.initWithNative(mSuggestionsUiDelegate, mContextMenuManager, mTileGroupDelegate, mOfflinePageBridge, mTileRenderer); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tab/tab_restore/OWNERS b/chrome/android/junit/src/org/chromium/chrome/browser/tab/tab_restore/OWNERS new file mode 100644 index 0000000..84a17fb2 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tab/tab_restore/OWNERS
@@ -0,0 +1 @@ +file://chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/OWNERS
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/OWNERS b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/OWNERS new file mode 100644 index 0000000..9de2bf41 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/OWNERS
@@ -0,0 +1 @@ +file://chrome/browser/tabmodel/OWNERS
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelImplUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelImplUnitTest.java new file mode 100644 index 0000000..f800fdc --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelImplUnitTest.java
@@ -0,0 +1,261 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.tabmodel; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.when; + +import androidx.test.filters.SmallTest; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.JniMocker; +import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; +import org.chromium.chrome.browser.flags.ActivityType; +import org.chromium.chrome.browser.homepage.HomepageManager; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.tab.MockTab; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabCreationState; +import org.chromium.chrome.browser.tab.TabLaunchType; +import org.chromium.chrome.browser.tab.TabSelectionType; +import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData; + +/** + * Unit tests for {@link TabModelImpl}. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class TabModelImplUnitTest { + private static final long FAKE_NATIVE_ADDRESS = 123L; + + /** + * Disable native calls from {@link TabModelJniBridge}. + */ + @Rule + public JniMocker mJniMocker = new JniMocker(); + @Mock + private TabModelJniBridge.Natives mTabModelJniBridge; + /** + * Required to be non-null for {@link TabModelJniBridge}. + */ + @Mock + private Profile mProfile; + /** + * Required to simulate tab thumbnail deletion. + */ + @Mock + private TabContentManager mTabContentManager; + /** + * Required to handle some tab lookup actions. + */ + @Mock + private TabModelDelegate mTabModelDelegate; + /** + * Required to handle some actions and initialize {@link TabModelOrderControllerImpl}. + */ + @Mock + private TabModelSelector mTabModelSelector; + + private int mNextTabId; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + // Disable HomepageManager#shouldCloseAppWithZeroTabs() for TabModelImpl#closeAllTabs(). + HomepageManager.getInstance().setPrefHomepageEnabled(false); + + mJniMocker.mock(TabModelJniBridgeJni.TEST_HOOKS, mTabModelJniBridge); + when(mTabModelJniBridge.init(any(), any(), anyInt())).thenReturn(FAKE_NATIVE_ADDRESS); + + when(mTabModelDelegate.isReparentingInProgress()).thenReturn(false); + + mNextTabId = 0; + } + + private Tab createTab(final TabModel model) { + return createTab(model, 0, Tab.INVALID_TAB_ID); + } + + private Tab createTab(final TabModel model, long activeTimestampMillis, int parentId) { + final int launchType = TabLaunchType.FROM_CHROME_UI; + MockTab tab = new MockTab(mNextTabId++, model.isIncognito()); + CriticalPersistedTabData data = new CriticalPersistedTabData(tab); + data.setTimestampMillis(activeTimestampMillis); + data.setParentId(parentId); + tab = (MockTab) MockTab.initializeWithCriticalPersistedTabData(tab, data); + tab.setIsInitialized(true); + model.addTab(tab, -1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND); + return tab; + } + + private void selectTab(final TabModel model, final Tab tab) { + model.setIndex(model.indexOf(tab), TabSelectionType.FROM_USER, false); + } + + /** + * Create a {@link TabModel} to use for the test. + */ + private TabModel createTabModel(boolean isActive, boolean isIncognito) { + AsyncTabParamsManager realAsyncTabParamsManager = + AsyncTabParamsManagerFactory.createAsyncTabParamsManager(); + TabModelOrderControllerImpl orderController = + new TabModelOrderControllerImpl(mTabModelSelector); + TabModel tabModel; + when(mProfile.isOffTheRecord()).thenReturn(isIncognito); + tabModel = new TabModelImpl(mProfile, ActivityType.TABBED, + /*regularTabCreator=*/null, /*incognitoTabCreator=*/null, orderController, + mTabContentManager, + () + -> NextTabPolicy.HIERARCHICAL, + realAsyncTabParamsManager, mTabModelDelegate, /*supportsUndo=*/false); + when(mTabModelSelector.getModel(isIncognito)).thenReturn(tabModel); + tabModel.setActive(isActive); + if (isActive) { + when(mTabModelSelector.getCurrentModel()).thenReturn(tabModel); + when(mTabModelDelegate.getCurrentModel()).thenReturn(tabModel); + } + when(mTabModelDelegate.getModel(isIncognito)).thenReturn(tabModel); + return tabModel; + } + + @Test + @SmallTest + public void testGetNextTabIfClosed_InactiveModel() { + TabModel activeIncognito = createTabModel(true, true); + TabModel inactiveNormal = createTabModel(false, false); + + Tab incognitoTab0 = createTab(activeIncognito); + Tab incognitoTab1 = createTab(activeIncognito); + Tab tab0 = createTab(inactiveNormal); + Tab tab1 = createTab(inactiveNormal); + + selectTab(activeIncognito, incognitoTab1); + selectTab(inactiveNormal, tab1); + + Assert.assertEquals(incognitoTab1, inactiveNormal.getNextTabIfClosed(tab1.getId(), false)); + } + + @Test + @SmallTest + public void testGetNextTabIfClosed_NotCurrentTab() { + TabModel activeNormal = createTabModel(true, false); + // Unused but required for correct mocking of mTabModelDelegate to avoid NPE. + TabModel inactiveIncognito = createTabModel(false, true); + + Tab tab0 = createTab(activeNormal); + Tab tab1 = createTab(activeNormal); + Tab tab2 = createTab(activeNormal); + + selectTab(activeNormal, tab0); + Assert.assertEquals(tab0, activeNormal.getNextTabIfClosed(tab1.getId(), false)); + Assert.assertEquals(tab0, activeNormal.getNextTabIfClosed(tab2.getId(), false)); + + selectTab(activeNormal, tab1); + Assert.assertEquals(tab1, activeNormal.getNextTabIfClosed(tab0.getId(), false)); + Assert.assertEquals(tab1, activeNormal.getNextTabIfClosed(tab2.getId(), false)); + + selectTab(activeNormal, tab2); + Assert.assertEquals(tab2, activeNormal.getNextTabIfClosed(tab0.getId(), false)); + Assert.assertEquals(tab2, activeNormal.getNextTabIfClosed(tab1.getId(), false)); + } + + @Test + @SmallTest + public void testGetNextTabIfClosed_ParentTab() { + TabModel activeNormal = createTabModel(true, false); + // Unused but required for correct mocking of mTabModelDelegate to avoid NPE. + TabModel inactiveIncognito = createTabModel(false, true); + + Tab tab0 = createTab(activeNormal); + Tab tab1 = createTab(activeNormal); + Tab tab2 = createTab(activeNormal, 0, tab0.getId()); + + selectTab(activeNormal, tab2); + Assert.assertEquals(tab0, activeNormal.getNextTabIfClosed(tab2.getId(), false)); + } + + @Test + @SmallTest + public void testGetNextTabIfClosed_Adjacent() { + TabModel activeNormal = createTabModel(true, false); + // Unused but required for correct mocking of mTabModelDelegate to avoid NPE. + TabModel inactiveIncognito = createTabModel(false, true); + + Tab tab0 = createTab(activeNormal); + Tab tab1 = createTab(activeNormal); + Tab tab2 = createTab(activeNormal); + + selectTab(activeNormal, tab0); + Assert.assertEquals(tab1, activeNormal.getNextTabIfClosed(tab0.getId(), false)); + + selectTab(activeNormal, tab1); + Assert.assertEquals(tab0, activeNormal.getNextTabIfClosed(tab1.getId(), false)); + + selectTab(activeNormal, tab2); + Assert.assertEquals(tab1, activeNormal.getNextTabIfClosed(tab2.getId(), false)); + } + + @Test + @SmallTest + public void testGetNextTabIfClosed_LastIncognitoTab() { + TabModel activeIncognito = createTabModel(true, true); + TabModel inactiveNormal = createTabModel(false, false); + + Tab incognitoTab0 = createTab(activeIncognito); + Tab tab0 = createTab(inactiveNormal); + Tab tab1 = createTab(inactiveNormal); + + selectTab(inactiveNormal, tab0); + Assert.assertEquals(tab0, activeIncognito.getNextTabIfClosed(incognitoTab0.getId(), false)); + + selectTab(inactiveNormal, tab1); + Assert.assertEquals(tab1, activeIncognito.getNextTabIfClosed(incognitoTab0.getId(), false)); + } + + @Test + @SmallTest + public void testGetNextTabIfClosed_MostRecentTab() { + TabModel activeNormal = createTabModel(true, false); + // Unused but required for correct mocking of mTabModelDelegate to avoid NPE. + TabModel inactiveIncognito = createTabModel(false, true); + + // uponExit overrides parent selection.. + Tab tab0 = createTab(activeNormal, 10, Tab.INVALID_TAB_ID); + Tab tab1 = createTab(activeNormal, 200, tab0.getId()); + Tab tab2 = createTab(activeNormal, 30, tab0.getId()); + + selectTab(activeNormal, tab0); + Assert.assertEquals(tab1, activeNormal.getNextTabIfClosed(tab0.getId(), true)); + + selectTab(activeNormal, tab1); + Assert.assertEquals(tab2, activeNormal.getNextTabIfClosed(tab1.getId(), true)); + + selectTab(activeNormal, tab2); + Assert.assertEquals(tab1, activeNormal.getNextTabIfClosed(tab2.getId(), true)); + } + + @Test + @SmallTest + public void testGetNextTabIfClosed_InvalidSelection() { + TabModel activeNormal = createTabModel(true, false); + // Unused but required for correct mocking of mTabModelDelegate to avoid NPE. + TabModel inactiveIncognito = createTabModel(false, true); + + Tab tab0 = createTab(activeNormal); + selectTab(activeNormal, tab0); + Assert.assertNull(activeNormal.getNextTabIfClosed(tab0.getId(), false)); + } +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediatorUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediatorUnitTest.java index 888b8af..e0d74c5 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediatorUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediatorUnitTest.java
@@ -40,6 +40,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; @@ -53,6 +54,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.identity_disc.IdentityDiscController; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; @@ -68,6 +70,8 @@ import org.chromium.chrome.browser.user_education.UserEducationHelper; import org.chromium.chrome.browser.util.ChromeAccessibilityUtil; import org.chromium.chrome.features.start_surface.StartSurfaceState; +import org.chromium.chrome.test.util.browser.Features; +import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.components.feature_engagement.EventConstants; import org.chromium.components.feature_engagement.Tracker; import org.chromium.components.search_engines.TemplateUrlService; @@ -77,10 +81,13 @@ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) @LooperMode(LooperMode.Mode.LEGACY) +@EnableFeatures(ChromeFeatureList.ENABLE_IPH) public class StartSurfaceToolbarMediatorUnitTest { private PropertyModel mPropertyModel; private StartSurfaceToolbarMediator mMediator; @Rule + public TestRule mFeaturesProcessorRule = new Features.JUnitProcessor(); + @Rule public JniMocker mJniMocker = new JniMocker(); @Mock private TabModelSelector mTabModelSelector;
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 07e8296..e4eb53f 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -5084,10 +5084,10 @@ Help </message> <message name="IDS_ECHE_APP_SCREEN_LOCK_NOTIFICATION_TITLE" desc="Title for notification shown when screen lock is not enabled while using app stream of EcheApp."> - Couldn’t open <ph name="APP_NAME">$1<ex>the app</ex></ph> + Can't open app </message> <message name="IDS_ECHE_APP_SCREEN_LOCK_NOTIFICATION_MESSAGE" desc="Message for the notification shown when screen lock is not enabled while using app stream of EcheApp."> - Set a pin or password on this Chromebook to protect access to your phone’s apps. + To open <ph name="APP_NAME">$1<ex>the app</ex></ph>, enable "Show lock screen when waking from sleep" </message> <message name="IDS_ECHE_APP_NOTIFICATION_OPEN_AGAIN_BUTTON" desc="Label for the inactivity notification button of EcheApp to open open."> Open again
diff --git a/chrome/app/chromeos_strings_grdp/IDS_ECHE_APP_SCREEN_LOCK_NOTIFICATION_MESSAGE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_ECHE_APP_SCREEN_LOCK_NOTIFICATION_MESSAGE.png.sha1 index f7fc0077..33e553e 100644 --- a/chrome/app/chromeos_strings_grdp/IDS_ECHE_APP_SCREEN_LOCK_NOTIFICATION_MESSAGE.png.sha1 +++ b/chrome/app/chromeos_strings_grdp/IDS_ECHE_APP_SCREEN_LOCK_NOTIFICATION_MESSAGE.png.sha1
@@ -1 +1 @@ -bf284f3dc923008482ba763eb9d056f1ab69f8e9 \ No newline at end of file +680ae77ac0feb1ff37f4aa80877bea62a049a96b \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_ECHE_APP_SCREEN_LOCK_NOTIFICATION_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_ECHE_APP_SCREEN_LOCK_NOTIFICATION_TITLE.png.sha1 index e1d752f..33e553e 100644 --- a/chrome/app/chromeos_strings_grdp/IDS_ECHE_APP_SCREEN_LOCK_NOTIFICATION_TITLE.png.sha1 +++ b/chrome/app/chromeos_strings_grdp/IDS_ECHE_APP_SCREEN_LOCK_NOTIFICATION_TITLE.png.sha1
@@ -1 +1 @@ -47e595c88427adfe5662c60dadfa357d01e0e2d4 \ No newline at end of file +680ae77ac0feb1ff37f4aa80877bea62a049a96b \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index eb144d25..6319e88 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2186,6 +2186,7 @@ "//components/policy/content/", "//components/policy/core/browser", "//components/policy/proto", + "//components/pref_registry", "//components/prefs", "//components/privacy_sandbox", "//components/privacy_sandbox:privacy_sandbox_prefs", @@ -2558,10 +2559,10 @@ if (is_chromeos) { sources += [ - "policy/messaging_layer/util/heartbeat_event.cc", - "policy/messaging_layer/util/heartbeat_event.h", - "policy/messaging_layer/util/heartbeat_event_factory.cc", - "policy/messaging_layer/util/heartbeat_event_factory.h", + "policy/messaging_layer/util/manual_test_heartbeat_event.cc", + "policy/messaging_layer/util/manual_test_heartbeat_event.h", + "policy/messaging_layer/util/manual_test_heartbeat_event_factory.cc", + "policy/messaging_layer/util/manual_test_heartbeat_event_factory.h", "policy/system_features_disable_list_policy_handler.cc", "policy/system_features_disable_list_policy_handler.h", ] @@ -4513,7 +4514,6 @@ "//components/keep_alive_registry", "//components/live_caption", "//components/memory_pressure", - "//components/pref_registry", "//components/services/app_service:lib", "//components/services/app_service/public/cpp:app_file_handling", "//components/services/app_service/public/cpp:app_share_target", @@ -7275,7 +7275,6 @@ "//chrome/browser/supervised_user/supervised_user_error_page", "//chrome/browser/supervised_user/supervised_user_features", "//chrome/common:supervised_user_commands_mojom", - "//components/pref_registry", ] } if (enable_supervised_users && enable_extensions) { @@ -7664,6 +7663,7 @@ "//chrome/browser/media:mojo_bindings_js", "//chrome/browser/resources/internals/user_education:components", "//chrome/browser/resources/local_state:build", + "//chrome/browser/resources/media:build_ts", "//chrome/browser/resources/predictors:build_ts", "//chrome/browser/ui/webui/internals/user_education:mojo_bindings_js", "//components/site_engagement/core/mojom:mojo_bindings_webui_js",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 6d0b7f4..0feffb9 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -269,7 +269,7 @@ #endif #if BUILDFLAG(ENABLE_SUPERVISED_USERS) -#include "chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h" +#include "chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h" // nogncheck #endif // ENABLE_SUPERVISED_USERS #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/accessibility/live_caption_controller_browsertest.cc b/chrome/browser/accessibility/live_caption_controller_browsertest.cc index 99a5eb4..53210ab 100644 --- a/chrome/browser/accessibility/live_caption_controller_browsertest.cc +++ b/chrome/browser/accessibility/live_caption_controller_browsertest.cc
@@ -303,8 +303,9 @@ } IN_PROC_BROWSER_TEST_F(LiveCaptionControllerTest, OnError) { - OnError(); EXPECT_FALSE(HasBubbleController()); + OnError(); + EXPECT_TRUE(HasBubbleController()); SetLiveCaptionEnabled(true); OnError(); @@ -312,7 +313,7 @@ SetLiveCaptionEnabled(false); OnError(); - EXPECT_FALSE(HasBubbleController()); + EXPECT_TRUE(HasBubbleController()); } IN_PROC_BROWSER_TEST_F(LiveCaptionControllerTest, OnAudioStreamEnd) {
diff --git a/chrome/browser/accessibility/live_caption_unavailability_notifier.cc b/chrome/browser/accessibility/live_caption_unavailability_notifier.cc index 5bda20b..6ff4f3b 100644 --- a/chrome/browser/accessibility/live_caption_unavailability_notifier.cc +++ b/chrome/browser/accessibility/live_caption_unavailability_notifier.cc
@@ -18,10 +18,12 @@ #include "components/live_caption/pref_names.h" #include "components/live_caption/views/caption_bubble.h" #include "components/live_caption/views/caption_bubble_model.h" +#include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" +#include "media/mojo/mojom/renderer_extensions.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "url/origin.h" @@ -49,29 +51,31 @@ if (!web_contents) return; context_ = CaptionBubbleContextBrowser::Create(web_contents); + + Profile* profile = + Profile::FromBrowserContext(render_frame_host()->GetBrowserContext()); + profile_prefs_ = profile->GetPrefs(); + + pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>(); + pref_change_registrar_->Init(profile_prefs_); + + // Unretained is safe because |this| owns the pref_change_registrar_. + pref_change_registrar_->Add( + prefs::kLiveCaptionEnabled, + base::BindRepeating(&LiveCaptionUnavailabilityNotifier:: + OnSpeechRecognitionAvailabilityChanged, + base::Unretained(this))); } LiveCaptionUnavailabilityNotifier::~LiveCaptionUnavailabilityNotifier() = default; -void LiveCaptionUnavailabilityNotifier::MediaFoundationRendererCreated() { - LiveCaptionController* live_caption_controller = GetLiveCaptionController(); - if (live_caption_controller && ShouldDisplayMediaFoundationRendererError()) { - // This will trigger the caption bubble to display a message informing the - // user that Live Caption is unavailable and link them to the settings page - // where they can disable the media foundation renderer to enable Live - // Caption. The error message may be overwritten if recognition events are - // received from another audio stream. - live_caption_controller->OnError( - context_.get(), - CaptionBubbleErrorType::MEDIA_FOUNDATION_RENDERER_UNSUPPORTED, - base::BindRepeating(&LiveCaptionUnavailabilityNotifier:: - OnMediaFoundationRendererErrorClicked, - weak_factory_.GetWeakPtr()), - base::BindRepeating( - &LiveCaptionUnavailabilityNotifier:: - OnMediaFoundationRendererErrorDoNotShowAgainCheckboxClicked, - weak_factory_.GetWeakPtr())); +void LiveCaptionUnavailabilityNotifier::MediaFoundationRendererCreated( + mojo::PendingReceiver<media::mojom::MediaFoundationRendererObserver> + observer) { + observers_.Add(this, std::move(observer)); + if (ShouldDisplayMediaFoundationRendererError()) { + DisplayMediaFoundationRendererError(); } } @@ -91,15 +95,21 @@ bool LiveCaptionUnavailabilityNotifier:: ShouldDisplayMediaFoundationRendererError() { - PrefService* prefs = - Profile::FromBrowserContext(render_frame_host()->GetBrowserContext()) - ->GetPrefs(); + if (!profile_prefs_->GetBoolean(prefs::kLiveCaptionEnabled)) + return false; - const base::Value* silenced_sites_pref = - prefs->GetList(prefs::kLiveCaptionMediaFoundationRendererErrorSilenced); + if (observers_.empty()) + return false; + + return !ErrorSilencedForOrigin(); +} + +bool LiveCaptionUnavailabilityNotifier::ErrorSilencedForOrigin() { + const base::Value* silenced_sites_pref = profile_prefs_->GetList( + prefs::kLiveCaptionMediaFoundationRendererErrorSilenced); if (!silenced_sites_pref) - return true; + return false; const auto& silenced_sites_list = silenced_sites_pref->GetList(); const auto it = std::find_if( @@ -109,7 +119,29 @@ render_frame_host()->GetLastCommittedOrigin().Serialize(); }); - return it == silenced_sites_list.end(); + return it != silenced_sites_list.end(); +} + +void LiveCaptionUnavailabilityNotifier::DisplayMediaFoundationRendererError() { + LiveCaptionController* live_caption_controller = GetLiveCaptionController(); + if (!live_caption_controller) + return; + + // This will trigger the caption bubble to display a message informing the + // user that Live Caption is unavailable and link them to the settings page + // where they can disable the media foundation renderer to enable Live + // Caption. The error message may be overwritten if recognition events are + // received from another audio stream. + live_caption_controller->OnError( + context_.get(), + CaptionBubbleErrorType::MEDIA_FOUNDATION_RENDERER_UNSUPPORTED, + base::BindRepeating(&LiveCaptionUnavailabilityNotifier:: + OnMediaFoundationRendererErrorClicked, + weak_factory_.GetWeakPtr()), + base::BindRepeating( + &LiveCaptionUnavailabilityNotifier:: + OnMediaFoundationRendererErrorDoNotShowAgainCheckboxClicked, + weak_factory_.GetWeakPtr())); } void LiveCaptionUnavailabilityNotifier:: @@ -141,4 +173,11 @@ Navigate(¶ms); } +void LiveCaptionUnavailabilityNotifier:: + OnSpeechRecognitionAvailabilityChanged() { + if (ShouldDisplayMediaFoundationRendererError()) { + DisplayMediaFoundationRendererError(); + } +} + } // namespace captions
diff --git a/chrome/browser/accessibility/live_caption_unavailability_notifier.h b/chrome/browser/accessibility/live_caption_unavailability_notifier.h index 967a432..66da970e 100644 --- a/chrome/browser/accessibility/live_caption_unavailability_notifier.h +++ b/chrome/browser/accessibility/live_caption_unavailability_notifier.h
@@ -11,8 +11,12 @@ #include "components/live_caption/views/caption_bubble_model.h" #include "content/public/browser/document_service.h" #include "content/public/browser/web_contents_observer.h" -#include "media/mojo/mojom/speech_recognition_service.mojom.h" +#include "media/mojo/mojom/renderer_extensions.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver_set.h" + +class PrefChangeRegistrar; +class PrefService; namespace content { class RenderFrameHost; @@ -26,7 +30,8 @@ // Used to notify the browser that the renderer does not support Live Caption. class LiveCaptionUnavailabilityNotifier : public content::DocumentService< - media::mojom::MediaFoundationRendererNotifier> { + media::mojom::MediaFoundationRendererNotifier>, + public media::mojom::MediaFoundationRendererObserver { public: LiveCaptionUnavailabilityNotifier( content::RenderFrameHost* frame_host, @@ -45,7 +50,9 @@ receiver); // media::mojom::MediaFoundationRendererNotifier: - void MediaFoundationRendererCreated() override; + void MediaFoundationRendererCreated( + mojo::PendingReceiver<media::mojom::MediaFoundationRendererObserver> + observer) override; private: friend class LiveCaptionUnavailabilityNotifierTest; @@ -56,12 +63,18 @@ LiveCaptionController* GetLiveCaptionController(); bool ShouldDisplayMediaFoundationRendererError(); + bool ErrorSilencedForOrigin(); + void DisplayMediaFoundationRendererError(); void OnMediaFoundationRendererErrorDoNotShowAgainCheckboxClicked( CaptionBubbleErrorType error_type, bool checked); void OnMediaFoundationRendererErrorClicked(); + void OnSpeechRecognitionAvailabilityChanged(); + mojo::ReceiverSet<media::mojom::MediaFoundationRendererObserver> observers_; std::unique_ptr<CaptionBubbleContextBrowser> context_; + std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_; + raw_ptr<PrefService> profile_prefs_; base::WeakPtrFactory<LiveCaptionUnavailabilityNotifier> weak_factory_{this}; };
diff --git a/chrome/browser/accessibility/live_caption_unavailability_notifier_unittest.cc b/chrome/browser/accessibility/live_caption_unavailability_notifier_unittest.cc index bbeae721b..c85796c0 100644 --- a/chrome/browser/accessibility/live_caption_unavailability_notifier_unittest.cc +++ b/chrome/browser/accessibility/live_caption_unavailability_notifier_unittest.cc
@@ -27,9 +27,7 @@ LiveCaptionUnavailabilityNotifierTest& operator=( const LiveCaptionUnavailabilityNotifierTest&) = delete; - bool ShouldDisplayMediaFoundationRendererError() { - return notifier_->ShouldDisplayMediaFoundationRendererError(); - } + bool ErrorSilencedForOrigin() { return notifier_->ErrorSilencedForOrigin(); } void OnMediaFoundationRendererErrorDoNotShowAgainCheckboxClicked( bool checked) { @@ -61,19 +59,19 @@ }; TEST_F(LiveCaptionUnavailabilityNotifierTest, MediaFoundationRendererCreated) { - ASSERT_TRUE(ShouldDisplayMediaFoundationRendererError()); + ASSERT_FALSE(ErrorSilencedForOrigin()); OnMediaFoundationRendererErrorDoNotShowAgainCheckboxClicked(true); - ASSERT_FALSE(ShouldDisplayMediaFoundationRendererError()); + ASSERT_TRUE(ErrorSilencedForOrigin()); NavigateAndCommit(GURL(kExampleSiteSameOrigin)); - ASSERT_FALSE(ShouldDisplayMediaFoundationRendererError()); + ASSERT_TRUE(ErrorSilencedForOrigin()); OnMediaFoundationRendererErrorDoNotShowAgainCheckboxClicked(false); - ASSERT_TRUE(ShouldDisplayMediaFoundationRendererError()); + ASSERT_FALSE(ErrorSilencedForOrigin()); NavigateAndCommit(GURL(kExampleSiteDifferentOrigin)); - ASSERT_TRUE(ShouldDisplayMediaFoundationRendererError()); + ASSERT_FALSE(ErrorSilencedForOrigin()); } } // namespace captions
diff --git a/chrome/browser/ash/accessibility/accessibility_manager.cc b/chrome/browser/ash/accessibility/accessibility_manager.cc index d7566317..21f4d79 100644 --- a/chrome/browser/ash/accessibility/accessibility_manager.cc +++ b/chrome/browser/ash/accessibility/accessibility_manager.cc
@@ -228,13 +228,6 @@ ~AccessibilityPanelWidgetObserver() override { CHECK(!IsInObserverList()); } - void OnWidgetClosing(views::Widget* widget) override { - CHECK_EQ(widget_, widget); - widget->RemoveObserver(this); - std::move(on_destroying_).Run(); - // |this| should be deleted. - } - void OnWidgetDestroying(views::Widget* widget) override { CHECK_EQ(widget_, widget); widget->RemoveObserver(this);
diff --git a/chrome/browser/ash/app_restore/full_restore_service.cc b/chrome/browser/ash/app_restore/full_restore_service.cc index 7ca6c2c7..f54461a7 100644 --- a/chrome/browser/ash/app_restore/full_restore_service.cc +++ b/chrome/browser/ash/app_restore/full_restore_service.cc
@@ -10,15 +10,11 @@ #include "base/metrics/histogram_functions.h" #include "base/strings/string_util.h" #include "chrome/app/vector_icons/vector_icons.h" -#include "chrome/browser/apps/app_service/app_service_proxy.h" -#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" -#include "chrome/browser/apps/app_service/browser_app_instance_registry.h" #include "chrome/browser/ash/app_restore/app_restore_arc_task_handler.h" #include "chrome/browser/ash/app_restore/full_restore_app_launch_handler.h" #include "chrome/browser/ash/app_restore/full_restore_data_handler.h" #include "chrome/browser/ash/app_restore/full_restore_prefs.h" #include "chrome/browser/ash/app_restore/full_restore_service_factory.h" -#include "chrome/browser/ash/app_restore/lacros_window_handler.h" #include "chrome/browser/ash/app_restore/new_user_restore_pref_handler.h" #include "chrome/browser/ash/policy/scheduled_task_handler/reboot_notifications_scheduler.h" #include "chrome/browser/ash/profiles/profile_helper.h" @@ -140,14 +136,6 @@ ::full_restore::FullRestoreSaveHandler::GetInstance() ->SetPrimaryProfilePath(profile_->GetPath()); - auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile_); - if (proxy && proxy->BrowserAppInstanceRegistry() && - ::full_restore::features::IsFullRestoreForLacrosEnabled()) { - lacros_window_handler_ = - std::make_unique<app_restore::LacrosWindowHandler>( - *proxy->BrowserAppInstanceRegistry()); - } - // In Multi-Profile mode, only set for the primary user. For other users, // active profile path is set when switch users. ::full_restore::SetActiveProfilePath(profile_->GetPath());
diff --git a/chrome/browser/ash/app_restore/full_restore_service.h b/chrome/browser/ash/app_restore/full_restore_service.h index d0fafab..dc90426b 100644 --- a/chrome/browser/ash/app_restore/full_restore_service.h +++ b/chrome/browser/ash/app_restore/full_restore_service.h
@@ -26,10 +26,6 @@ namespace ash { -namespace app_restore { -class LacrosWindowHandler; -} - namespace full_restore { class FullRestoreAppLaunchHandler; @@ -175,8 +171,6 @@ std::unique_ptr<FullRestoreDataHandler> restore_data_handler_; - std::unique_ptr<app_restore::LacrosWindowHandler> lacros_window_handler_; - std::unique_ptr<message_center::Notification> notification_; content::NotificationRegistrar notification_registrar_;
diff --git a/chrome/browser/ash/app_restore/lacros_window_handler.cc b/chrome/browser/ash/app_restore/lacros_window_handler.cc deleted file mode 100644 index 84f3133..0000000 --- a/chrome/browser/ash/app_restore/lacros_window_handler.cc +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2022 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ash/app_restore/lacros_window_handler.h" - -#include "chrome/browser/apps/app_service/browser_app_instance.h" -#include "components/app_restore/app_restore_utils.h" - -namespace ash { -namespace app_restore { - -LacrosWindowHandler::LacrosWindowHandler( - apps::BrowserAppInstanceRegistry& browser_app_instance_registry) { - browser_app_instance_registry_observation_.Observe( - &browser_app_instance_registry); -} - -LacrosWindowHandler::~LacrosWindowHandler() = default; - -void LacrosWindowHandler::OnBrowserWindowAdded( - const apps::BrowserWindowInstance& instance) { - ::app_restore::OnLacrosWindowAdded( - instance.window, instance.browser_session_id, - instance.restored_browser_session_id, /*is_browser_app=*/false); -} - -void LacrosWindowHandler::OnBrowserAppAdded( - const apps::BrowserAppInstance& instance) { - if (instance.type == apps::BrowserAppInstance::Type::kAppWindow) { - ::app_restore::OnLacrosWindowAdded( - instance.window, instance.browser_session_id, - instance.restored_browser_session_id, /*is_browser_app=*/true); - } -} - -} // namespace app_restore -} // namespace ash
diff --git a/chrome/browser/ash/app_restore/lacros_window_handler.h b/chrome/browser/ash/app_restore/lacros_window_handler.h deleted file mode 100644 index 9c713c3..0000000 --- a/chrome/browser/ash/app_restore/lacros_window_handler.h +++ /dev/null
@@ -1,50 +0,0 @@ -// Copyright 2022 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_ASH_APP_RESTORE_LACROS_WINDOW_HANDLER_H_ -#define CHROME_BROWSER_ASH_APP_RESTORE_LACROS_WINDOW_HANDLER_H_ - -#include "base/scoped_observation.h" -#include "chrome/browser/apps/app_service/browser_app_instance_observer.h" -#include "chrome/browser/apps/app_service/browser_app_instance_registry.h" - -namespace apps { -struct BrowserWindowInstance; -struct BrowserAppInstance; -} // namespace apps - -namespace ash { -namespace app_restore { - -// Created in ash-chrome. Listens to |BrowserAppInstanceRegistry| events and -// calls the app restore interface to save and restore lacros windows. -class LacrosWindowHandler : public apps::BrowserAppInstanceObserver { - public: - LacrosWindowHandler( - apps::BrowserAppInstanceRegistry& browser_app_instance_registry); - LacrosWindowHandler(const LacrosWindowHandler&) = delete; - LacrosWindowHandler& operator=(const LacrosWindowHandler&) = delete; - ~LacrosWindowHandler() override; - - // BrowserAppInstanceObserver overrides: - void OnBrowserWindowAdded( - const apps::BrowserWindowInstance& instance) override; - void OnBrowserWindowUpdated( - const apps::BrowserWindowInstance& instance) override {} - void OnBrowserWindowRemoved( - const apps::BrowserWindowInstance& instance) override {} - void OnBrowserAppAdded(const apps::BrowserAppInstance& instance) override; - void OnBrowserAppUpdated(const apps::BrowserAppInstance& instance) override {} - void OnBrowserAppRemoved(const apps::BrowserAppInstance& instance) override {} - - private: - base::ScopedObservation<apps::BrowserAppInstanceRegistry, - apps::BrowserAppInstanceObserver> - browser_app_instance_registry_observation_{this}; -}; - -} // namespace app_restore -} // namespace ash - -#endif // CHROME_BROWSER_ASH_APP_RESTORE_LACROS_WINDOW_HANDLER_H_
diff --git a/chrome/browser/ash/eche_app/eche_app_manager_factory.cc b/chrome/browser/ash/eche_app/eche_app_manager_factory.cc index 4a19629..11299af5 100644 --- a/chrome/browser/ash/eche_app/eche_app_manager_factory.cc +++ b/chrome/browser/ash/eche_app/eche_app_manager_factory.cc
@@ -180,7 +180,9 @@ if (absl::get<LaunchAppHelper::NotificationInfo::NotificationType>( info->type()) == LaunchAppHelper::NotificationInfo::NotificationType::kScreenLock) { - weak_ptr->notification_controller_->ShowScreenLockNotification(title); + weak_ptr->notification_controller_->ShowScreenLockNotification( + title ? title.value() + : u""); // If null, show a default value to be safe. } } else if (info->category() == LaunchAppHelper::NotificationInfo::Category::kWebUI) {
diff --git a/chrome/browser/ash/eche_app/eche_app_notification_controller.cc b/chrome/browser/ash/eche_app/eche_app_notification_controller.cc index 6de6701..82d042fc 100644 --- a/chrome/browser/ash/eche_app/eche_app_notification_controller.cc +++ b/chrome/browser/ash/eche_app/eche_app_notification_controller.cc
@@ -137,18 +137,17 @@ } void EcheAppNotificationController::ShowScreenLockNotification( - const absl::optional<std::u16string>& title) { + const std::u16string& title) { message_center::RichNotificationData rich_notification_data; rich_notification_data.buttons.push_back(message_center::ButtonInfo( l10n_util::GetStringUTF16(IDS_ECHE_APP_SCREEN_LOCK_SETTINGS_BUTTON))); rich_notification_data.buttons.push_back(message_center::ButtonInfo( l10n_util::GetStringUTF16(IDS_ECHE_APP_SCREEN_LOCK_LEARN_MORE))); - ShowNotification(CreateNotification( kEcheAppScreenLockNotifierId, - l10n_util::GetStringFUTF16(IDS_ECHE_APP_SCREEN_LOCK_NOTIFICATION_TITLE, - title.value()), - l10n_util::GetStringUTF16(IDS_ECHE_APP_SCREEN_LOCK_NOTIFICATION_MESSAGE), + l10n_util::GetStringUTF16(IDS_ECHE_APP_SCREEN_LOCK_NOTIFICATION_TITLE), + l10n_util::GetStringFUTF16(IDS_ECHE_APP_SCREEN_LOCK_NOTIFICATION_MESSAGE, + title), ui::ImageModel(), rich_notification_data, new NotificationDelegate(kEcheAppScreenLockNotifierId, weak_ptr_factory_.GetWeakPtr())));
diff --git a/chrome/browser/ash/eche_app/eche_app_notification_controller.h b/chrome/browser/ash/eche_app/eche_app_notification_controller.h index be0e6d8..8a9b672f 100644 --- a/chrome/browser/ash/eche_app/eche_app_notification_controller.h +++ b/chrome/browser/ash/eche_app/eche_app_notification_controller.h
@@ -38,7 +38,7 @@ // Shows the notification when screen lock is already enabled on the phone, // but the ChromeOS is not enabled. - void ShowScreenLockNotification(const absl::optional<std::u16string>& title); + void ShowScreenLockNotification(const std::u16string& title); // Shows the notification which was generated from WebUI and carry title and // message. void ShowNotificationFromWebUI(
diff --git a/chrome/browser/ash/eche_app/eche_app_notification_controller_unittest.cc b/chrome/browser/ash/eche_app/eche_app_notification_controller_unittest.cc index b754868..3752c1a 100644 --- a/chrome/browser/ash/eche_app/eche_app_notification_controller_unittest.cc +++ b/chrome/browser/ash/eche_app/eche_app_notification_controller_unittest.cc
@@ -162,11 +162,37 @@ } TEST_F(EcheAppNotificationControllerTest, ShowScreenLockNotification) { - absl::optional<std::u16string> title = u"title"; + std::u16string title = u"title"; notification_controller_->ShowScreenLockNotification(title); absl::optional<message_center::Notification> notification = display_service_->GetNotification(kEcheAppScreenLockNotifierId); ASSERT_TRUE(notification.has_value()); + ASSERT_TRUE(notification->title().size() > 0); + ASSERT_TRUE(notification->message().size() > 0); + ASSERT_EQ(2u, notification->buttons().size()); + EXPECT_EQ(message_center::SYSTEM_PRIORITY, notification->priority()); + + // Clicking the first notification button should launch settings. + EXPECT_CALL(*notification_controller_, LaunchSettings()); + notification->delegate()->Click(0, absl::nullopt); + + // Clicking the second notification button should launch learn more. + EXPECT_CALL(*new_window_delegate_, + OpenUrl(GURL(kEcheAppLearnMoreUrl), + NewWindowDelegate::OpenUrlFrom::kUserInteraction)); + notification->delegate()->Click(1, absl::nullopt); +} + +TEST_F(EcheAppNotificationControllerTest, + ShowScreenLockNotificationWithNullValue) { + // Null value for title should still show a degraded message. + std::u16string title; + notification_controller_->ShowScreenLockNotification(title); + absl::optional<message_center::Notification> notification = + display_service_->GetNotification(kEcheAppScreenLockNotifierId); + ASSERT_TRUE(notification.has_value()); + ASSERT_TRUE(notification->title().size() > 0); + ASSERT_TRUE(notification->message().size() > 0); ASSERT_EQ(2u, notification->buttons().size()); EXPECT_EQ(message_center::SYSTEM_PRIORITY, notification->priority()); @@ -182,7 +208,7 @@ } TEST_F(EcheAppNotificationControllerTest, CloseNotification) { - absl::optional<std::u16string> title = u"title"; + std::u16string title = u"title"; notification_controller_->ShowScreenLockNotification(title); notification_controller_->CloseNotification(kEcheAppScreenLockNotifierId); absl::optional<message_center::Notification> notification = @@ -216,7 +242,7 @@ TEST_F(EcheAppNotificationControllerTest, CloseConnectionOrLaunchErrorNotifications) { - absl::optional<std::u16string> title = u"title"; + std::u16string title = u"title"; absl::optional<std::u16string> message = u"message"; notification_controller_->ShowScreenLockNotification(title); notification_controller_->ShowNotificationFromWebUI(
diff --git a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc index 24a3e61..442f5527 100644 --- a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc +++ b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc
@@ -8,7 +8,9 @@ #include <utility> #include "ash/webui/os_feedback_ui/mojom/os_feedback_ui.mojom.h" +#include "base/bind.h" #include "base/strings/utf_string_conversions.h" +#include "base/time/time.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/feedback/feedback_dialog_utils.h" #include "chrome/browser/feedback/feedback_uploader_chrome.h" @@ -24,6 +26,8 @@ #include "components/signin/public/base/consent_level.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "content/public/browser/browser_context.h" +#include "extensions/browser/api/feedback_private/feedback_private_api.h" +#include "extensions/browser/api/feedback_private/feedback_service.h" #include "net/base/network_change_notifier.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" @@ -40,9 +44,19 @@ } // namespace using ::ash::os_feedback_ui::mojom::SendReportStatus; +using extensions::FeedbackParams; +using extensions::FeedbackPrivateAPI; ChromeOsFeedbackDelegate::ChromeOsFeedbackDelegate(Profile* profile) - : profile_(profile) { + : ChromeOsFeedbackDelegate(profile, + FeedbackPrivateAPI::GetFactoryInstance() + ->Get(profile) + ->GetService()) {} + +ChromeOsFeedbackDelegate::ChromeOsFeedbackDelegate( + Profile* profile, + scoped_refptr<extensions::FeedbackService> feedback_service) + : profile_(profile), feedback_service_(feedback_service) { Browser* browser = BrowserList::GetInstance()->GetLastActive(); if (browser) { // Save the last active page url before opening the feedback tool. @@ -74,19 +88,18 @@ void ChromeOsFeedbackDelegate::SendReport( os_feedback_ui::mojom::ReportPtr report, SendReportCallback callback) { - base::WeakPtr<feedback::FeedbackUploader> uploader; - if (feedback_uploader_for_testing_) { - uploader = base::AsWeakPtr(feedback_uploader_for_testing_.get()); - } else { - uploader = base::AsWeakPtr(GetFeedbackUploaderForContext(profile_)); - } - scoped_refptr<feedback::FeedbackData> feedback_data = + // Populate feedback_params + FeedbackParams feedback_params; + feedback_params.form_submit_time = base::TimeTicks::Now(); + feedback_params.load_system_info = report->include_system_logs_and_histograms; + feedback_params.send_histograms = report->include_system_logs_and_histograms; + + base::WeakPtr<feedback::FeedbackUploader> uploader = + base::AsWeakPtr(GetFeedbackUploaderForContext(profile_)); + scoped_refptr<::feedback::FeedbackData> feedback_data = base::MakeRefCounted<feedback::FeedbackData>( std::move(uploader), ContentTracingManager::Get()); - feedback_data->set_locale(GetApplicationLocale()); - // TODO(xiangdongkong): Add UserAgent. - feedback_data->set_description(base::UTF16ToUTF8(report->description)); const auto& feedback_context = report->feedback_context; @@ -96,21 +109,18 @@ if (feedback_context->page_url.has_value()) { feedback_data->set_page_url(feedback_context->page_url.value().spec()); } - // TODO(xiangdongkong): Fetch system logs if needed. - // Signal the feedback object that the data from the feedback page has been - // filled - the object will manage sending of the actual report. - feedback_data->OnFeedbackPageDataComplete(); - - const SendReportStatus status = net::NetworkChangeNotifier::IsOffline() - ? SendReportStatus::kDelayed - : SendReportStatus::kSuccess; - std::move(callback).Run(status); + feedback_service_->SendFeedback( + feedback_params, feedback_data, + base::BindOnce(&ChromeOsFeedbackDelegate::OnSendFeedbackDone, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } -void ChromeOsFeedbackDelegate::SetFeedbackUploaderForTesting( - feedback::FeedbackUploader* uploader) { - feedback_uploader_for_testing_ = uploader; +void ChromeOsFeedbackDelegate::OnSendFeedbackDone(SendReportCallback callback, + bool status) { + const SendReportStatus send_status = + status ? SendReportStatus::kDelayed : SendReportStatus::kSuccess; + std::move(callback).Run(send_status); } } // namespace ash
diff --git a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.h b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.h index de055fa2..86405659 100644 --- a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.h +++ b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.h
@@ -9,20 +9,25 @@ #include "ash/webui/os_feedback_ui/backend/os_feedback_delegate.h" #include "base/memory/raw_ptr.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" class Profile; -namespace feedback { -class FeedbackUploader; -} // namespace feedback +namespace extensions { +class FeedbackService; +} // namespace extensions namespace ash { class ChromeOsFeedbackDelegate : public OsFeedbackDelegate { public: explicit ChromeOsFeedbackDelegate(Profile* profile); + ChromeOsFeedbackDelegate( + Profile* profile, + scoped_refptr<extensions::FeedbackService> feedback_service); ~ChromeOsFeedbackDelegate() override; ChromeOsFeedbackDelegate(const ChromeOsFeedbackDelegate&) = delete; @@ -34,15 +39,17 @@ absl::optional<std::string> GetSignedInUserEmail() const override; void SendReport(os_feedback_ui::mojom::ReportPtr report, SendReportCallback callback) override; - void SetFeedbackUploaderForTesting(::feedback::FeedbackUploader* uploader); private: + void OnSendFeedbackDone(SendReportCallback callback, bool status); + // TODO(xiangdongkong): make sure the profile_ cannot be destroyed while // operations are pending. raw_ptr<Profile> profile_; + scoped_refptr<extensions::FeedbackService> feedback_service_; absl::optional<GURL> page_url_; - raw_ptr<::feedback::FeedbackUploader> feedback_uploader_for_testing_; + base::WeakPtrFactory<ChromeOsFeedbackDelegate> weak_ptr_factory_{this}; }; } // namespace ash
diff --git a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc index 35c6cd6f..514570d 100644 --- a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc +++ b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc
@@ -5,12 +5,15 @@ #include "chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.h" #include <memory> +#include <utility> #include "base/bind.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/ref_counted.h" +#include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" -#include "base/test/task_environment.h" +#include "base/test/test_future.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" @@ -19,13 +22,11 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/feedback/feedback_report.h" -#include "components/feedback/feedback_uploader.h" #include "components/prefs/testing_pref_service.h" #include "components/signin/public/identity_manager/identity_test_utils.h" #include "content/public/test/browser_test.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" -#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" -#include "services/network/test/test_url_loader_factory.h" +#include "extensions/browser/api/feedback_private/feedback_service.h" +#include "extensions/browser/api/feedback_private/mock_feedback_service.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" @@ -39,41 +40,19 @@ using ::ash::os_feedback_ui::mojom::Report; using ::ash::os_feedback_ui::mojom::ReportPtr; using ::ash::os_feedback_ui::mojom::SendReportStatus; +using extensions::FeedbackParams; +using feedback::FeedbackData; +using testing::_; constexpr char kPageUrl[] = "https://www.google.com/?q=123"; constexpr char kSignedInUserEmail[] = "test_user_email@gmail.com"; - -class MockUploader : public feedback::FeedbackUploader { - public: - MockUploader( - bool is_off_the_record, - const base::FilePath& state_path, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) - : FeedbackUploader(is_off_the_record, state_path, url_loader_factory) {} - - MockUploader(const MockUploader&) = delete; - MockUploader& operator=(const MockUploader&) = delete; - - void QueueReport(std::unique_ptr<std::string> data, bool has_email) override { - report_had_email_ = has_email; - called_queue_report_ = true; - } - - bool called_queue_report() const { return called_queue_report_; } - bool report_had_email() const { return report_had_email_; } - - private: - bool called_queue_report_ = false; - bool report_had_email_ = false; -}; +const std::u16string kDescription = u"This is a fake description"; } // namespace class ChromeOsFeedbackDelegateTest : public InProcessBrowserTest { public: - ChromeOsFeedbackDelegateTest() { - EXPECT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); - } + ChromeOsFeedbackDelegateTest() = default; ~ChromeOsFeedbackDelegateTest() override = default; absl::optional<GURL> GetLastActivePageUrl() { @@ -82,30 +61,39 @@ } protected: - void RunSendReport(ReportPtr report) { - network::TestURLLoaderFactory test_url_loader_factory_; - scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_ = - base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( - &test_url_loader_factory_); - mock_uploader_ = std::make_unique<MockUploader>( - /*is_off_the_record=*/false, scoped_temp_dir_.GetPath(), - test_shared_loader_factory_); + void RunSendReport(ReportPtr report, + const FeedbackParams& expected_params, + scoped_refptr<FeedbackData>& actual_feedback_data) { + auto* profile_ = browser()->profile(); + auto mock = base::MakeRefCounted<extensions::MockFeedbackService>(profile_); - ChromeOsFeedbackDelegate feedback_delegate_(browser()->profile()); - feedback_delegate_.SetFeedbackUploaderForTesting(mock_uploader_.get()); + EXPECT_CALL(*mock, SendFeedback(_, _, _)) + .WillOnce([&](const extensions::FeedbackParams& params, + scoped_refptr<FeedbackData> feedback_data, + extensions::SendFeedbackCallback callback) { + // Pass the feedback data out to verify its properties + actual_feedback_data = feedback_data; - bool send_report_callback_called = false; - feedback_delegate_.SendReport( - std::move(report), - base::BindLambdaForTesting([&](SendReportStatus status) { - send_report_callback_called = true; - })); + // Verify that the flags in params are set correctly + EXPECT_EQ(expected_params.is_internal_email, + params.is_internal_email); + EXPECT_EQ(expected_params.load_system_info, params.load_system_info); + EXPECT_EQ(expected_params.send_tab_titles, params.send_tab_titles); + EXPECT_EQ(expected_params.send_histograms, params.send_histograms); + EXPECT_EQ(expected_params.send_bluetooth_logs, + params.send_bluetooth_logs); - EXPECT_TRUE(send_report_callback_called); + std::move(callback).Run(true); + }); + + auto feedback_delegate_ = + std::make_unique<ChromeOsFeedbackDelegate>(profile_, std::move(mock)); + + base::test::TestFuture<SendReportStatus> future; + feedback_delegate_->SendReport(std::move(report), future.GetCallback()); + + EXPECT_NE(SendReportStatus::kUnknown, future.Get()); } - - base::ScopedTempDir scoped_temp_dir_; - std::unique_ptr<MockUploader> mock_uploader_; }; // Test GetApplicationLocale returns a valid locale. @@ -137,25 +125,54 @@ EXPECT_EQ(feedback_delegate_.GetSignedInUserEmail(), kSignedInUserEmail); } -// Test that SendReport method adds the report to queue without an email. -IN_PROC_BROWSER_TEST_F(ChromeOsFeedbackDelegateTest, SendReportNoEmail) { +// Test that feedback params and data are populated with correct data before +// passed to SendFeedback method of the feedback service . +// TODO(xiangdongkong): Add tests for other flags once they are supported. +// Currently, only load_system_info and send_histograms flags are implemented. +IN_PROC_BROWSER_TEST_F(ChromeOsFeedbackDelegateTest, + FeedbackDataPopulatedIncludeSysLogs) { ReportPtr report = Report::New(); report->feedback_context = FeedbackContext::New(); - RunSendReport(std ::move(report)); + report->description = kDescription; - EXPECT_TRUE(mock_uploader_->called_queue_report()); - EXPECT_FALSE(mock_uploader_->report_had_email()); + report->include_system_logs_and_histograms = true; + const FeedbackParams expected_params{/*is_internal_email=*/false, + /*load_system_info=*/true, + /*send_tab_titles=*/false, + /*send_histograms=*/true, + /*send_bluetooth_logs=*/false}; + + scoped_refptr<FeedbackData> feedback_data; + RunSendReport(std::move(report), expected_params, feedback_data); + + EXPECT_EQ("", feedback_data->user_email()); + EXPECT_EQ("", feedback_data->page_url()); + EXPECT_EQ(base::UTF16ToUTF8(kDescription), feedback_data->description()); } -// Test that SendReport method adds the report to queue with an email. -IN_PROC_BROWSER_TEST_F(ChromeOsFeedbackDelegateTest, SendReportWithEmail) { +// Test that feedback params and data are populated with correct data before +// passed to SendFeedback method of the feedback service . +IN_PROC_BROWSER_TEST_F(ChromeOsFeedbackDelegateTest, + FeedbackDataPopulatedNotIncludeSysLogs) { ReportPtr report = Report::New(); report->feedback_context = FeedbackContext::New(); report->feedback_context->email = kSignedInUserEmail; - RunSendReport(std ::move(report)); + report->feedback_context->page_url = GURL(kPageUrl); + report->description = kDescription; - EXPECT_TRUE(mock_uploader_->called_queue_report()); - EXPECT_TRUE(mock_uploader_->report_had_email()); + report->include_system_logs_and_histograms = false; + const FeedbackParams expected_params{/*is_internal_email=*/false, + /*load_system_info=*/false, + /*send_tab_titles=*/false, + /*send_histograms=*/false, + /*send_bluetooth_logs=*/false}; + + scoped_refptr<FeedbackData> feedback_data; + RunSendReport(std::move(report), expected_params, feedback_data); + + EXPECT_EQ(kSignedInUserEmail, feedback_data->user_email()); + EXPECT_EQ(kPageUrl, feedback_data->page_url()); + EXPECT_EQ(base::UTF16ToUTF8(kDescription), feedback_data->description()); } } // namespace ash
diff --git a/chrome/browser/ash/power/ml/user_activity_manager_unittest.cc b/chrome/browser/ash/power/ml/user_activity_manager_unittest.cc index 937b53ef..fce71be 100644 --- a/chrome/browser/ash/power/ml/user_activity_manager_unittest.cc +++ b/chrome/browser/ash/power/ml/user_activity_manager_unittest.cc
@@ -36,7 +36,6 @@ #include "chromeos/services/machine_learning/public/cpp/service_connection.h" #include "components/session_manager/session_manager_types.h" #include "components/site_engagement/content/site_engagement_service.h" -#include "components/ukm/content/source_url_recorder.h" #include "components/ukm/test_ukm_recorder.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index 34208a6..c003238 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -171,6 +171,7 @@ #include "chrome/common/webui_url_constants.h" #include "components/history_clusters/core/history_clusters_service.h" #include "components/search/ntp_features.h" +#include "media/mojo/mojom/renderer_extensions.mojom.h" #include "media/mojo/mojom/speech_recognition_service.mojom.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "ui/webui/resources/cr_components/customize_themes/customize_themes.mojom.h" @@ -587,14 +588,8 @@ content::RenderFrameHost* frame_host, mojo::PendingReceiver<media::mojom::MediaFoundationRendererNotifier> receiver) { - Profile* profile = Profile::FromBrowserContext( - frame_host->GetProcess()->GetBrowserContext()); - PrefService* profile_prefs = profile->GetPrefs(); - if (profile_prefs->GetBoolean(prefs::kLiveCaptionEnabled) && - captions::IsLiveCaptionFeatureSupported()) { - captions::LiveCaptionUnavailabilityNotifier::Create(frame_host, - std::move(receiver)); - } + captions::LiveCaptionUnavailabilityNotifier::Create(frame_host, + std::move(receiver)); } #endif
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 96e0ae54..0b614b2c 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -398,6 +398,7 @@ #include "chrome/browser/download/android/intercept_oma_download_navigation_throttle.h" #include "chrome/browser/flags/android/chrome_feature_list.h" #include "chrome/browser/ui/android/tab_model/tab_model_list.h" +#include "chrome/browser/webauthn/chrome_conditional_ui_delegate_android.h" #include "chrome/common/chrome_descriptors.h" #include "components/browser_ui/accessibility/android/font_size_prefs_android.h" #include "components/cdm/browser/cdm_message_filter_android.h" @@ -6514,3 +6515,12 @@ return web_app::GetOfflinePageInfo(url, browser_context); } + +#if BUILDFLAG(IS_ANDROID) +content::ConditionalUiDelegateAndroid* +ChromeContentBrowserClient::GetConditionalUiDelegate( + content::RenderFrameHost* host) { + return ChromeConditionalUiDelegateAndroid::GetConditionalUiDelegate( + content::WebContents::FromRenderFrameHost(host)); +} +#endif
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 68768d0..7c38e0b 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -791,6 +791,11 @@ content::BrowserContext* browser_context, int32_t error_code) override; +#if BUILDFLAG(IS_ANDROID) + content::ConditionalUiDelegateAndroid* GetConditionalUiDelegate( + content::RenderFrameHost* host) override; +#endif + protected: static bool HandleWebUI(GURL* url, content::BrowserContext* browser_context); static bool HandleWebUIReverse(GURL* url,
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index e668989..7197ebb 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -665,8 +665,6 @@ "../ash/app_restore/full_restore_service.h", "../ash/app_restore/full_restore_service_factory.cc", "../ash/app_restore/full_restore_service_factory.h", - "../ash/app_restore/lacros_window_handler.cc", - "../ash/app_restore/lacros_window_handler.h", "../ash/app_restore/new_user_restore_pref_handler.cc", "../ash/app_restore/new_user_restore_pref_handler.h", "../ash/apps/apk_web_app_installer.cc",
diff --git a/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc b/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc index 318ae15..a2f0051 100644 --- a/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc +++ b/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc
@@ -38,7 +38,9 @@ host == chrome::kChromeUIDeviceLogHost || host == chrome::kChromeUIDomainReliabilityInternalsHost || host == chrome::kChromeUIDownloadInternalsHost || +#if BUILDFLAG(ENABLE_SUPERVISED_USERS) host == chrome::kChromeUIFamilyLinkUserInternalsHost || +#endif host == chrome::kChromeUIGCMInternalsHost || host == chrome::kChromeUIInternalsHost || host == chrome::kChromeUIInterstitialHost ||
diff --git a/chrome/browser/dev_ui_browser_resources.grd b/chrome/browser/dev_ui_browser_resources.grd index 988ef38..2c380bef 100644 --- a/chrome/browser/dev_ui_browser_resources.grd +++ b/chrome/browser/dev_ui_browser_resources.grd
@@ -34,12 +34,12 @@ <include name="IDR_DOMAIN_RELIABILITY_INTERNALS_JS" file="resources\domain_reliability_internals\domain_reliability_internals.js" type="BINDATA" /> <include name="IDR_LOCAL_STATE_HTML" file="resources\local_state\local_state.html" type="BINDATA" /> <include name="IDR_LOCAL_STATE_JS" file="${root_gen_dir}\chrome\browser\resources\local_state\local_state.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_MEDIA_DATA_TABLE_JS" file="resources\media\media_data_table.js" type="BINDATA" /> + <include name="IDR_MEDIA_DATA_TABLE_JS" file="${root_gen_dir}\chrome\browser\resources\media\media_data_table.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_MEDIA_ENGAGEMENT_HTML" file="resources\media\media_engagement.html" type="BINDATA" /> <include name="IDR_MEDIA_ENGAGEMENT_JS" file="resources\media\media_engagement.js" type="BINDATA" /> <include name="IDR_MEDIA_ENGAGEMENT_SCORE_DETAILS_MOJOM_WEBUI_JS" file="${root_gen_dir}\mojom-webui\chrome\browser\media\media_engagement_score_details.mojom-webui.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_MEDIA_HISTORY_HTML" file="resources\media\media_history.html" type="BINDATA" allowexternalscript="true" /> - <include name="IDR_MEDIA_HISTORY_JS" file="resources\media\media_history.js" type="BINDATA" /> + <include name="IDR_MEDIA_HISTORY_JS" file="${root_gen_dir}\chrome\browser\resources\media\media_history.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_MEDIA_HISTORY_STORE_MOJOM_WEBUI_JS" file="${root_gen_dir}\mojom-webui\chrome\browser\media\history\media_history_store.mojom-webui.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_MEMORY_INTERNALS_HTML" file="resources\memory_internals\memory_internals.html" type="BINDATA" /> <include name="IDR_MEMORY_INTERNALS_JS" file="resources\memory_internals\memory_internals.js" type="BINDATA" />
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index 4072e2d..825ec4b0 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -841,6 +841,7 @@ "//components/no_state_prefetch/browser", "//components/onc", "//components/page_load_metrics/browser:browser", + "//components/password_manager/content/browser", "//components/password_manager/core/browser", "//components/password_manager/core/browser:affiliation", "//components/password_manager/core/browser/leak_detection",
diff --git a/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc b/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc index a21f7185..5d6b53a0 100644 --- a/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc +++ b/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
@@ -31,11 +31,13 @@ #include "chrome/common/extensions/api/passwords_private.h" #include "chrome/grit/generated_resources.h" #include "components/keyed_service/core/service_access_type.h" +#include "components/password_manager/content/browser/password_change_success_tracker_factory.h" #include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h" #include "components/password_manager/core/browser/bulk_leak_check_service.h" #include "components/password_manager/core/browser/insecure_credentials_table.h" #include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h" #include "components/password_manager/core/browser/leak_detection/encryption_utils.h" +#include "components/password_manager/core/browser/password_change_success_tracker.h" #include "components/password_manager/core/browser/password_form.h" #include "components/password_manager/core/browser/ui/credential_utils.h" #include "components/password_manager/core/browser/ui/insecure_credentials_manager.h" @@ -59,6 +61,7 @@ using password_manager::CredentialWithPassword; using password_manager::InsecureCredentialTypeFlags; using password_manager::LeakCheckCredential; +using password_manager::PasswordChangeSuccessTracker; using password_manager::PasswordForm; using ui::TimeFormat; @@ -355,6 +358,27 @@ return insecure_credentials_manager_.UnmuteCredential(*insecure_credential); } +// Records that a change password flow was started for |credential| and +// whether |is_manual_flow| applies to the flow. +void PasswordCheckDelegate::RecordChangePasswordFlowStarted( + const api::passwords_private::InsecureCredential& credential, + bool is_manual_flow) { + // If the |credential| does not have a |change_password_url|, skip it. + if (!credential.change_password_url) + return; + + if (is_manual_flow) { + GetPasswordChangeSuccessTracker()->OnManualChangePasswordFlowStarted( + GURL(*credential.change_password_url), credential.username, + PasswordChangeSuccessTracker::EntryPoint::kLeakCheckInSettings); + } else { + GetPasswordChangeSuccessTracker()->OnChangePasswordFlowStarted( + GURL(*credential.change_password_url), credential.username, + PasswordChangeSuccessTracker::StartEvent::kAutomatedFlow, + PasswordChangeSuccessTracker::EntryPoint::kLeakCheckInSettings); + } +} + void PasswordCheckDelegate::StartPasswordCheck( StartPasswordCheckCallback callback) { // If the delegate isn't initialized yet, enqueue the callback and return @@ -613,4 +637,10 @@ return api_credential; } +PasswordChangeSuccessTracker* +PasswordCheckDelegate::GetPasswordChangeSuccessTracker() { + return password_manager::PasswordChangeSuccessTrackerFactory:: + GetForBrowserContext(profile_); +} + } // namespace extensions
diff --git a/chrome/browser/extensions/api/passwords_private/password_check_delegate.h b/chrome/browser/extensions/api/passwords_private/password_check_delegate.h index 8d777e9748..b7db681 100644 --- a/chrome/browser/extensions/api/passwords_private/password_check_delegate.h +++ b/chrome/browser/extensions/api/passwords_private/password_check_delegate.h
@@ -26,6 +26,10 @@ class Profile; +namespace password_manager { +class PasswordChangeSuccessTracker; +} // namespace password_manager + namespace extensions { extern const char kPasswordCheckDataKey[]; @@ -85,6 +89,12 @@ bool UnmuteInsecureCredential( const api::passwords_private::InsecureCredential& credential); + // Records that a change password flow was started for |credential| and + // whether |is_manual_flow| applies to the flow. + void RecordChangePasswordFlowStarted( + const api::passwords_private::InsecureCredential& credential, + bool is_manual_flow); + // Requests to start a check for insecure passwords. Invokes |callback| once a // check is running or the request was stopped via StopPasswordCheck(). void StartPasswordCheck( @@ -151,6 +161,11 @@ api::passwords_private::InsecureCredential ConstructInsecureCredential( const password_manager::CredentialWithPassword& credential); + // Obtain a raw pointer to the |PasswordChangeSuccessTracker| associated + // with |profile_|. + password_manager::PasswordChangeSuccessTracker* + GetPasswordChangeSuccessTracker(); + // Raw pointer to the underlying profile. Needs to outlive this instance. raw_ptr<Profile> profile_ = nullptr;
diff --git a/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc b/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc index 8625926..4d3e3ed7 100644 --- a/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc +++ b/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc
@@ -28,9 +28,12 @@ #include "chrome/common/extensions/api/passwords_private.h" #include "chrome/test/base/testing_profile.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/password_manager/content/browser/password_change_success_tracker_factory.h" #include "components/password_manager/core/browser/bulk_leak_check_service.h" #include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h" #include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h" +#include "components/password_manager/core/browser/mock_password_change_success_tracker.h" +#include "components/password_manager/core/browser/password_change_success_tracker.h" #include "components/password_manager/core/browser/password_form.h" #include "components/password_manager/core/browser/password_manager_test_utils.h" #include "components/password_manager/core/browser/test_password_store.h" @@ -81,6 +84,9 @@ using password_manager::IsLeaked; using password_manager::IsMuted; using password_manager::LeakCheckCredential; +using password_manager::MockPasswordChangeSuccessTracker; +using password_manager::PasswordChangeSuccessTracker; +using password_manager::PasswordChangeSuccessTrackerFactory; using password_manager::PasswordForm; using password_manager::SavedPasswordsPresenter; using password_manager::TestPasswordStore; @@ -123,6 +129,17 @@ }))); } +MockPasswordChangeSuccessTracker* CreateAndUsePasswordChangeSuccessTracker( + Profile* profile) { + return static_cast<MockPasswordChangeSuccessTracker*>( + PasswordChangeSuccessTrackerFactory::GetInstance() + ->SetTestingSubclassFactoryAndUse( + profile, base::BindRepeating([](content::BrowserContext*) { + return std::make_unique< + testing::StrictMock<MockPasswordChangeSuccessTracker>>(); + }))); +} + BulkLeakCheckService* CreateAndUseBulkLeakCheckService( signin::IdentityManager* identity_manager, Profile* profile) { @@ -243,6 +260,9 @@ TestingProfile& profile() { return profile_; } TestPasswordStore& store() { return *store_; } BulkLeakCheckService* service() { return bulk_leak_check_service_; } + MockPasswordChangeSuccessTracker& password_change_success_tracker() { + return *password_change_success_tracker_; + } SavedPasswordsPresenter& presenter() { return presenter_; } PasswordCheckDelegate& delegate() { return delegate_; } @@ -260,6 +280,8 @@ &profile_); scoped_refptr<TestPasswordStore> store_ = CreateAndUseTestPasswordStore(&profile_); + raw_ptr<MockPasswordChangeSuccessTracker> password_change_success_tracker_ = + CreateAndUsePasswordChangeSuccessTracker(&profile_); SavedPasswordsPresenter presenter_{store_}; PasswordCheckDelegate delegate_{&profile_, &presenter_}; }; @@ -858,6 +880,94 @@ EXPECT_FALSE(delegate().UnmuteInsecureCredential(credential)); } +TEST_F(PasswordCheckDelegateTest, RecordChangePasswordFlowStartedManual) { + // Create an insecure credential. + PasswordForm form = MakeSavedPassword(kExampleCom, kUsername1); + AddIssueToForm(&form, InsecureType::kLeaked); + store().AddLogin(form); + RunUntilIdle(); + + InsecureCredential credential = + std::move(delegate().GetCompromisedCredentials().at(0)); + ASSERT_EQ(base::UTF16ToASCII(kUsername1), credential.username); + + EXPECT_CALL( + password_change_success_tracker(), + OnManualChangePasswordFlowStarted( + GURL(*credential.change_password_url), credential.username, + PasswordChangeSuccessTracker::EntryPoint::kLeakCheckInSettings)); + + delegate().RecordChangePasswordFlowStarted(credential, + /*is_manual_flow=*/true); +} + +TEST_F(PasswordCheckDelegateTest, RecordChangePasswordFlowStartedAutomated) { + // Create an insecure credential. + PasswordForm form = MakeSavedPassword(kExampleCom, kUsername1); + AddIssueToForm(&form, InsecureType::kLeaked); + store().AddLogin(form); + RunUntilIdle(); + + InsecureCredential credential = + std::move(delegate().GetCompromisedCredentials().at(0)); + ASSERT_EQ(base::UTF16ToASCII(kUsername1), credential.username); + + EXPECT_CALL( + password_change_success_tracker(), + OnChangePasswordFlowStarted( + GURL(*credential.change_password_url), credential.username, + PasswordChangeSuccessTracker::StartEvent::kAutomatedFlow, + PasswordChangeSuccessTracker::EntryPoint::kLeakCheckInSettings)); + + delegate().RecordChangePasswordFlowStarted(credential, + /*is_manual_flow=*/false); +} + +TEST_F(PasswordCheckDelegateTest, + RecordChangePasswordFlowStartedForAppWithWebRealm) { + // Create an insecure credential. + PasswordForm form = MakeSavedAndroidPassword(kExampleApp, kUsername2, + "Example App", kExampleCom); + AddIssueToForm(&form, InsecureType::kLeaked); + store().AddLogin(form); + RunUntilIdle(); + + InsecureCredential credential = + std::move(delegate().GetCompromisedCredentials().at(0)); + ASSERT_EQ(base::UTF16ToASCII(kUsername2), credential.username); + + EXPECT_CALL( + password_change_success_tracker(), + OnManualChangePasswordFlowStarted( + GURL(*credential.change_password_url), credential.username, + PasswordChangeSuccessTracker::EntryPoint::kLeakCheckInSettings)); + + delegate().RecordChangePasswordFlowStarted(credential, + /*is_manual_flow=*/true); +} + +TEST_F(PasswordCheckDelegateTest, + RecordChangePasswordFlowStartedForAppWithoutWebRealm) { + // Create an insecure credential. + PasswordForm form = + MakeSavedAndroidPassword(kExampleApp, kUsername1, "", kExampleCom); + AddIssueToForm(&form, InsecureType::kLeaked); + store().AddLogin(form); + RunUntilIdle(); + + InsecureCredential credential = + std::move(delegate().GetCompromisedCredentials().at(0)); + ASSERT_EQ(base::UTF16ToASCII(kUsername1), credential.username); + + // Since no password change link exists, we expect no call to the tracker. + EXPECT_CALL(password_change_success_tracker(), + OnManualChangePasswordFlowStarted) + .Times(0); + + delegate().RecordChangePasswordFlowStarted(credential, + /*is_manual_flow=*/true); +} + // Tests that we don't create an entry in the database if there is no matching // saved password. TEST_F(PasswordCheckDelegateTest, OnLeakFoundDoesNotCreateCredential) {
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc index eaa32a0f..11e309631 100644 --- a/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc +++ b/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc
@@ -389,6 +389,22 @@ return RespondNow(NoArguments()); } +// PasswordsPrivateRecordChangePasswordFlowStartedFunction: +PasswordsPrivateRecordChangePasswordFlowStartedFunction:: + ~PasswordsPrivateRecordChangePasswordFlowStartedFunction() = default; + +ResponseAction PasswordsPrivateRecordChangePasswordFlowStartedFunction::Run() { + auto parameters = + api::passwords_private::RecordChangePasswordFlowStarted::Params::Create( + args()); + EXTENSION_FUNCTION_VALIDATE(parameters); + + GetDelegate(browser_context()) + ->RecordChangePasswordFlowStarted(parameters->credential, + parameters->is_manual_flow); + return RespondNow(NoArguments()); +} + // PasswordsPrivateStartPasswordCheckFunction: PasswordsPrivateStartPasswordCheckFunction:: ~PasswordsPrivateStartPasswordCheckFunction() = default;
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_api.h b/chrome/browser/extensions/api/passwords_private/passwords_private_api.h index b19d147..01878f1 100644 --- a/chrome/browser/extensions/api/passwords_private/passwords_private_api.h +++ b/chrome/browser/extensions/api/passwords_private/passwords_private_api.h
@@ -340,6 +340,19 @@ ResponseAction Run() override; }; +class PasswordsPrivateRecordChangePasswordFlowStartedFunction + : public ExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("passwordsPrivate.recordChangePasswordFlowStarted", + PASSWORDSPRIVATE_RECORDCHANGEPASSWORDFLOWSTARTED) + + protected: + ~PasswordsPrivateRecordChangePasswordFlowStartedFunction() override; + + // ExtensionFunction overrides. + ResponseAction Run() override; +}; + class PasswordsPrivateStartPasswordCheckFunction : public ExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("passwordsPrivate.startPasswordCheck",
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc index 94e2703..e7eeb49b 100644 --- a/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc +++ b/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc
@@ -110,6 +110,10 @@ s_test_delegate_->SetIsAccountStoreDefault(is_default); } + const std::string& last_change_flow_url() { + return s_test_delegate_->last_change_flow_url(); + } + const std::vector<int>& last_moved_passwords() const { return s_test_delegate_->last_moved_passwords(); } @@ -340,6 +344,29 @@ EXPECT_TRUE(RunPasswordsSubtest("unmuteInsecureCredentialFails")) << message_; } +IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, + RecordChangePasswordFlowStartedManual) { + EXPECT_TRUE(RunPasswordsSubtest("recordChangePasswordFlowStartedManual")) + << message_; + EXPECT_EQ(last_change_flow_url(), + "https://example.com/.well-known/change-password"); +} + +IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, + RecordChangePasswordFlowStartedAutomated) { + EXPECT_TRUE(RunPasswordsSubtest("recordChangePasswordFlowStartedAutomated")) + << message_; + EXPECT_EQ(last_change_flow_url(), + "https://example.com/.well-known/change-password"); +} + +IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, + RecordChangePasswordFlowStartedAppNoUrl) { + EXPECT_TRUE(RunPasswordsSubtest("recordChangePasswordFlowStartedAppNoUrl")) + << message_; + EXPECT_EQ(last_change_flow_url(), ""); +} + IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, StartPasswordCheck) { set_start_password_check_state( password_manager::BulkLeakCheckService::State::kRunning);
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h index 129688d7..f1dbbc4d 100644 --- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h +++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h
@@ -191,6 +191,12 @@ virtual bool UnmuteInsecureCredential( const api::passwords_private::InsecureCredential& credential) = 0; + // Records that a change password flow was started for |credential| and + // whether |is_manual_flow| applies to the flow. + virtual void RecordChangePasswordFlowStarted( + const api::passwords_private::InsecureCredential& credential, + bool is_manual_flow) = 0; + // Requests to start a check for insecure passwords. Invokes |callback| // once a check is running or the request was stopped via StopPasswordCheck(). virtual void StartPasswordCheck(StartPasswordCheckCallback callback) = 0;
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc index 3c785b90..4925fa6 100644 --- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc +++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
@@ -560,6 +560,13 @@ return password_check_delegate_.UnmuteInsecureCredential(credential); } +void PasswordsPrivateDelegateImpl::RecordChangePasswordFlowStarted( + const api::passwords_private::InsecureCredential& credential, + bool is_manual_flow) { + password_check_delegate_.RecordChangePasswordFlowStarted(credential, + is_manual_flow); +} + void PasswordsPrivateDelegateImpl::StartPasswordCheck( StartPasswordCheckCallback callback) { password_check_delegate_.StartPasswordCheck(std::move(callback));
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h index 9a1f006..a5cba18 100644 --- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h +++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h
@@ -103,6 +103,9 @@ const api::passwords_private::InsecureCredential& credential) override; bool UnmuteInsecureCredential( const api::passwords_private::InsecureCredential& credential) override; + void RecordChangePasswordFlowStarted( + const api::passwords_private::InsecureCredential& credential, + bool is_manual_flow) override; void StartPasswordCheck(StartPasswordCheckCallback callback) override; void StopPasswordCheck() override; api::passwords_private::PasswordCheckStatus GetPasswordCheckStatus() override;
diff --git a/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc b/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc index e93a5aca..263ccb50 100644 --- a/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc +++ b/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc
@@ -11,6 +11,7 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h" #include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router_factory.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/base/l10n/time_format.h" namespace extensions { @@ -288,6 +289,13 @@ return IsCredentialPresentInInsecureCredentialsList(credential); } +void TestPasswordsPrivateDelegate::RecordChangePasswordFlowStarted( + const api::passwords_private::InsecureCredential& credential, + bool is_manual_flow) { + last_change_flow_url_ = + credential.change_password_url ? *credential.change_password_url : ""; +} + void TestPasswordsPrivateDelegate::StartPasswordCheck( StartPasswordCheckCallback callback) { start_password_check_triggered_ = true;
diff --git a/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h b/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h index ebd7d35..f9e8377 100644 --- a/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h +++ b/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h
@@ -88,6 +88,11 @@ // delegate knows of a insecure credential with the same id. bool UnmuteInsecureCredential( const api::passwords_private::InsecureCredential& credential) override; + // Fake implementation of RecordChangePasswordFlowStarted. Sets the url + // returned by |last_change_flow_url()|. + void RecordChangePasswordFlowStarted( + const api::passwords_private::InsecureCredential& credential, + bool is_manual_flow) override; void StartPasswordCheck(StartPasswordCheckCallback callback) override; void StopPasswordCheck() override; api::passwords_private::PasswordCheckStatus GetPasswordCheckStatus() override; @@ -117,6 +122,8 @@ start_password_check_state_ = state; } + const std::string& last_change_flow_url() { return last_change_flow_url_; } + const std::vector<int>& last_moved_passwords() const { return last_moved_passwords_; } @@ -160,6 +167,10 @@ password_manager::BulkLeakCheckService::State start_password_check_state_ = password_manager::BulkLeakCheckService::State::kRunning; + // Url of the last reported change password flow. Defaults to empty if + // none has been registered. + std::string last_change_flow_url_; + // Records the ids of the passwords that were last moved. std::vector<int> last_moved_passwords_; };
diff --git a/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate_unittest.cc b/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate_unittest.cc index c33db707..a46c51f 100644 --- a/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate_unittest.cc +++ b/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate_unittest.cc
@@ -412,8 +412,16 @@ ExtensionId extension_id_; }; +// Test failing on Linux: https://crbug.com/1321186 +#if BUILDFLAG(IS_LINUX) +#define MAYBE_TerminateExtensionWithTooManyReloads \ + DISABLED_TerminateExtensionWithTooManyReloads +#else +#define MAYBE_TerminateExtensionWithTooManyReloads \ + TerminateExtensionWithTooManyReloads +#endif TEST_F(ChromeRuntimeAPIDelegateReloadTest, - TerminateExtensionWithTooManyReloads) { + MAYBE_TerminateExtensionWithTooManyReloads) { base::ScopedAllowBlockingForTesting allow_blocking; // We expect the extension to be reloaded 30 times in quick succession before
diff --git a/chrome/browser/extensions/extension_keybinding_registry.cc b/chrome/browser/extensions/extension_keybinding_registry.cc index 66c2d482..f11d113 100644 --- a/chrome/browser/extensions/extension_keybinding_registry.cc +++ b/chrome/browser/extensions/extension_keybinding_registry.cc
@@ -142,8 +142,8 @@ if (!extension) return; - std::unique_ptr<base::ListValue> args(new base::ListValue()); - args->Append(command); + std::vector<base::Value> args; + args.emplace_back(base::Value(command)); std::unique_ptr<base::Value> tab_value; if (delegate_) { @@ -180,11 +180,11 @@ // No currently-active tab. Push a null value. tab_value = std::make_unique<base::Value>(); } - args->Append(std::move(tab_value)); + args.push_back(base::Value::FromUniquePtrValue(std::move(tab_value))); - auto event = std::make_unique<Event>( - events::COMMANDS_ON_COMMAND, kOnCommandEventName, - std::move(*args).TakeListDeprecated(), browser_context_); + auto event = + std::make_unique<Event>(events::COMMANDS_ON_COMMAND, kOnCommandEventName, + std::move(args), browser_context_); event->user_gesture = EventRouter::USER_GESTURE_ENABLED; EventRouter::Get(browser_context_) ->DispatchEventToExtension(extension_id, std::move(event));
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc index 253ea51..e5ad4ae 100644 --- a/chrome/browser/extensions/extension_tab_util.cc +++ b/chrome/browser/extensions/extension_tab_util.cc
@@ -505,9 +505,10 @@ WebContents* web_contents = tab_strip->GetWebContentsAt(i); ExtensionTabUtil::ScrubTabBehavior scrub_tab_behavior = ExtensionTabUtil::GetScrubTabBehavior(extension, context, web_contents); - tab_list->Append(CreateTabObject(web_contents, scrub_tab_behavior, - extension, tab_strip, i) - ->ToValue()); + tab_list->Append(base::Value::FromUniquePtrValue( + CreateTabObject(web_contents, scrub_tab_behavior, extension, tab_strip, + i) + ->ToValue())); } return tab_list;
diff --git a/chrome/browser/extensions/permissions_updater.cc b/chrome/browser/extensions/permissions_updater.cc index 2bf7ca8..dba23f7b 100644 --- a/chrome/browser/extensions/permissions_updater.cc +++ b/chrome/browser/extensions/permissions_updater.cc
@@ -676,13 +676,13 @@ EventRouter* event_router = event_name ? EventRouter::Get(browser_context) : nullptr; if (event_router) { - std::unique_ptr<base::ListValue> value(new base::ListValue()); + std::vector<base::Value> event_args; std::unique_ptr<api::permissions::Permissions> permissions = PackPermissionSet(*changed); - value->Append(permissions->ToValue()); - auto event = std::make_unique<Event>(histogram_value, event_name, - std::move(*value).TakeListDeprecated(), - browser_context); + event_args.emplace_back( + base::Value::FromUniquePtrValue(permissions->ToValue())); + auto event = std::make_unique<Event>( + histogram_value, event_name, std::move(event_args), browser_context); event_router->DispatchEventToExtension(extension->id(), std::move(event)); }
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedSurfaceProvider.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedSurfaceProvider.java index b07fa6f..727bdf0 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedSurfaceProvider.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedSurfaceProvider.java
@@ -56,4 +56,9 @@ */ @Nullable FeedReliabilityLogger getReliabilityLogger(); + + /** + * Reloads the contents. + */ + void reload(); }
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java index 6563388f..29d041dc 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java
@@ -189,6 +189,7 @@ ChromeFeatureList.WEB_FEED, "intro_style", "IPH"); mBaseTestValues.addFeatureFlagOverride(ChromeFeatureList.SNOOZABLE_IPH, false); mBaseTestValues.addFeatureFlagOverride(ChromeFeatureList.ENABLE_AUTOMATIC_SNOOZE, false); + mBaseTestValues.addFeatureFlagOverride(ChromeFeatureList.ENABLE_IPH, true); FeatureList.setTestValues(mBaseTestValues); resetWebFeedFollowIntroController();
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroViewTest.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroViewTest.java index 1f25ee43..8e9d036b 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroViewTest.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroViewTest.java
@@ -27,6 +27,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.user_education.UserEducationHelper; import org.chromium.components.feature_engagement.Tracker; @@ -85,6 +86,10 @@ @Test @SmallTest public void showIPHTest() { + FeatureList.TestValues baseTestValues = new FeatureList.TestValues(); + baseTestValues.addFeatureFlagOverride(ChromeFeatureList.ENABLE_IPH, true); + FeatureList.setTestValues(baseTestValues); + mWebFeedFollowIntroView.showIPH(mHelper, () -> {}, () -> {}); verify(mHelper, times(1)).requestShowIPH(any()); }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 1d7cf659..454c890 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -5070,7 +5070,7 @@ { "name": "read-later", "owners": [ "chrome-desktop-ui-sea@google.com", "corising", "wylieb", "chrome-collections@google.com" ], - "expiry_milestone": 102 + "expiry_milestone": 105 }, { "name": "read-later-reminder-notification", @@ -5556,6 +5556,11 @@ "expiry_milestone": 102 }, { + "name": "suggestions-scrolling-ipad", + "owners": [ "christianxu", "bling-flags@google.com" ], + "expiry_milestone": 106 + }, + { "name": "suppress-toolbar-captures", "owners": [ "pnoland@google.com" ], "expiry_milestone": 104
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 0ede832..3c616f41 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -130,6 +130,7 @@ &features::kToolbarUseHardwareBitmapDraw, &features::kWebNfc, &features::kIncognitoNtpRevamp, + &feature_engagement::kEnableIPH, &feature_engagement::kEnableAutomaticSnooze, &feature_engagement::kIPHNewTabPageHomeButtonFeature, &feature_engagement::kIPHSnooze, @@ -240,6 +241,7 @@ &kLensCameraAssistedSearch, &kLensOnQuickActionSearchWidget, &kLocationBarModelOptimizations, + &kMostRecentTabOnBackgroundCloseTab, &kNewWindowAppMenu, &kNotificationPermissionVariant, &kPageAnnotationsService, @@ -666,6 +668,9 @@ const base::Feature kSearchEnginePromoNewDeviceV2{ "SearchEnginePromo.NewDeviceVer2", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kMostRecentTabOnBackgroundCloseTab{ + "MostRecentTabOnBackgroundCloseTab", base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kNewWindowAppMenu{"NewWindowAppMenu", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index 0141620..db14f48 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -105,6 +105,7 @@ extern const base::Feature kLensCameraAssistedSearch; extern const base::Feature kLensOnQuickActionSearchWidget; extern const base::Feature kLocationBarModelOptimizations; +extern const base::Feature kMostRecentTabOnBackgroundCloseTab; extern const base::Feature kNewWindowAppMenu; extern const base::Feature kNotificationPermissionVariant; extern const base::Feature kPageAnnotationsService;
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index 0b075f05..8f95ac6 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -311,6 +311,7 @@ public static final String DETAILED_LANGUAGE_SETTINGS = "DetailedLanguageSettings"; public static final String DIRECT_ACTIONS = "DirectActions"; public static final String DISABLE_COMPOSITED_PROGRESS_BAR = "DisableCompositedProgressBar"; + public static final String ENABLE_IPH = "EnableIPH"; public static final String DNS_OVER_HTTPS = "DnsOverHttps"; public static final String DOWNLOAD_FILE_PROVIDER = "DownloadFileProvider"; public static final String DOWNLOAD_NOTIFICATION_BADGE = "DownloadNotificationBadge"; @@ -399,6 +400,8 @@ public static final String MESSAGES_FOR_ANDROID_SYNC_ERROR = "MessagesForAndroidSyncError"; public static final String MODAL_PERMISSION_DIALOG_VIEW = "ModalPermissionDialogView"; public static final String METRICS_SETTINGS_ANDROID = "MetricsSettingsAndroid"; + public static final String MOST_RECENT_TAB_ON_BACKGROUND_CLOSE_TAB = + "MostRecentTabOnBackgroundCloseTab"; public static final String NEW_WINDOW_APP_MENU = "NewWindowAppMenu"; public static final String NOTIFICATION_PERMISSION_VARIANT = "NotificationPermissionVariant"; public static final String OFFLINE_INDICATOR = "OfflineIndicator";
diff --git a/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersBottomSheetContent.java b/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersBottomSheetContent.java index f37bb8b..bb3cc76 100644 --- a/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersBottomSheetContent.java +++ b/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersBottomSheetContent.java
@@ -7,6 +7,7 @@ import android.view.View; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; @@ -14,7 +15,8 @@ * Bottom sheet content implementation for the HistoryClusters UI. This enables the bottom sheet * system to render our bottom sheet content and e.g. announce accessibility events correctly. */ -class HistoryClustersBottomSheetContent implements BottomSheetContent { +@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) +public class HistoryClustersBottomSheetContent implements BottomSheetContent { private View mContentView; private View mToolbarView;
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc index b4e9658..b27e0625 100644 --- a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc +++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
@@ -32,7 +32,6 @@ #include "components/reputation/core/safety_tips_config.h" #include "components/security_interstitials/content/security_interstitial_tab_helper.h" #include "components/site_engagement/content/site_engagement_service.h" -#include "components/ukm/content/source_url_recorder.h" #include "components/url_formatter/spoof_checks/top_domains/top500_domains.h" #include "components/url_formatter/spoof_checks/top_domains/top_domain_util.h" #include "content/public/browser/navigation_handle.h"
diff --git a/chrome/browser/metrics/power/power_metrics.cc b/chrome/browser/metrics/power/power_metrics.cc index 73e67ef..5c9db09 100644 --- a/chrome/browser/metrics/power/power_metrics.cc +++ b/chrome/browser/metrics/power/power_metrics.cc
@@ -9,7 +9,6 @@ #include "base/metrics/histogram_functions.h" #include "base/strings/strcat.h" #include "chrome/browser/performance_monitor/process_metrics_recorder_util.h" -#include "chrome/browser/performance_monitor/process_monitor.h" #if BUILDFLAG(IS_MAC) #include "base/mac/mac_util.h" @@ -63,31 +62,50 @@ } } +BatteryDischarge GetBatteryDischargeDuringInterval( + const BatteryLevelProvider::BatteryState& previous_battery_state, + const BatteryLevelProvider::BatteryState& new_battery_state, + base::TimeDelta interval_duration) { + if (previous_battery_state.battery_count == 0 || + new_battery_state.battery_count == 0) { + return {BatteryDischargeMode::kNoBattery, absl::nullopt}; + } + if (!previous_battery_state.on_battery && !new_battery_state.on_battery) { + return {BatteryDischargeMode::kPluggedIn, absl::nullopt}; + } + if (previous_battery_state.on_battery != new_battery_state.on_battery) { + return {BatteryDischargeMode::kStateChanged, absl::nullopt}; + } + if (!previous_battery_state.charge_level.has_value() || + !new_battery_state.charge_level.has_value()) { + return {BatteryDischargeMode::kChargeLevelUnavailable, absl::nullopt}; + } + + // The battery discharge rate is reported per minute with 1/10000 of full + // charge resolution. + static constexpr int64_t kDischargeRateFactor = + 10000 * base::Minutes(1).InSecondsF(); + +#if BUILDFLAG(IS_MAC) + // On MacOS, empirical evidence has shown that right after a full charge, the + // current capacity stays equal to the maximum capacity for several minutes, + // despite the fact that power was definitely consumed. Reporting a zero + // discharge rate for this duration would be misleading. + if (previous_battery_state.charge_level.value() == 1.0) + return {BatteryDischargeMode::kMacFullyCharged, absl::nullopt}; +#endif + + auto discharge_rate = (previous_battery_state.charge_level.value() - + new_battery_state.charge_level.value()) * + kDischargeRateFactor / interval_duration.InSeconds(); + if (discharge_rate < 0) + return {BatteryDischargeMode::kBatteryLevelIncreased, absl::nullopt}; + return {BatteryDischargeMode::kDischarging, discharge_rate}; +} + void ReportBatteryHistograms(base::TimeDelta interval_duration, BatteryDischarge battery_discharge, const std::vector<const char*>& suffixes) { - // Ratio by which the time elapsed can deviate from - // |ProcessMonitor::kGatherInterval| without invalidating this sample. - constexpr double kTolerableTimeElapsedRatio = 0.10; - constexpr double kTolerablePositiveDrift = (1. + kTolerableTimeElapsedRatio); - constexpr double kTolerableNegativeDrift = (1. - kTolerableTimeElapsedRatio); - - if (battery_discharge.mode == BatteryDischargeMode::kDischarging && - interval_duration > performance_monitor::ProcessMonitor::kGatherInterval * - kTolerablePositiveDrift) { - // Too much time passed since the last record. Either the task took - // too long to get executed or system sleep took place. - battery_discharge.mode = BatteryDischargeMode::kInvalidInterval; - } - - if (battery_discharge.mode == BatteryDischargeMode::kDischarging && - interval_duration < performance_monitor::ProcessMonitor::kGatherInterval * - kTolerableNegativeDrift) { - // The recording task executed too early after the previous one, possibly - // because the previous task took too long to execute. - battery_discharge.mode = BatteryDischargeMode::kInvalidInterval; - } - for (const char* suffix : suffixes) { base::UmaHistogramEnumeration( base::StrCat({kBatteryDischargeModeHistogramName, suffix}),
diff --git a/chrome/browser/metrics/power/power_metrics.h b/chrome/browser/metrics/power/power_metrics.h index 7b5401c..a19124f1 100644 --- a/chrome/browser/metrics/power/power_metrics.h +++ b/chrome/browser/metrics/power/power_metrics.h
@@ -9,6 +9,7 @@ #include "base/time/time.h" #include "build/build_config.h" +#include "chrome/browser/metrics/power/battery_level_provider.h" #include "chrome/browser/performance_monitor/process_monitor.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -43,6 +44,14 @@ absl::optional<int64_t> rate; }; +// Computes and returns the battery discharge mode and rate during the interval. +// If the discharge rate isn't valid, the returned rate is nullopt and the +// reason is indicated per BatteryDischargeMode. +BatteryDischarge GetBatteryDischargeDuringInterval( + const BatteryLevelProvider::BatteryState& previous_battery_state, + const BatteryLevelProvider::BatteryState& new_battery_state, + base::TimeDelta interval_duration); + // Report battery metrics to histograms with |suffixes|. void ReportBatteryHistograms(base::TimeDelta interval_duration, BatteryDischarge battery_discharge,
diff --git a/chrome/browser/metrics/power/power_metrics_reporter.cc b/chrome/browser/metrics/power/power_metrics_reporter.cc index 65a9a39b..e3e1d3f 100644 --- a/chrome/browser/metrics/power/power_metrics_reporter.cc +++ b/chrome/browser/metrics/power/power_metrics_reporter.cc
@@ -45,6 +45,12 @@ kOverflowBucket); } +bool IsWithinTolerance(base::TimeDelta value, + base::TimeDelta expected, + base::TimeDelta tolerance) { + return (value - expected).magnitude() < tolerance; +} + } // namespace PowerMetricsReporter::PowerMetricsReporter( @@ -151,6 +157,16 @@ ReportAggregatedProcessMetricsHistograms(aggregated_process_metrics, suffixes); + // Ratio by which the time elapsed can deviate from + // |ProcessMonitor::kGatherInterval| without invalidating this sample. + constexpr double kTolerableTimeElapsedRatio = 0.10; + if (battery_discharge.mode == BatteryDischargeMode::kDischarging && + !IsWithinTolerance(interval_duration, + performance_monitor::ProcessMonitor::kGatherInterval, + performance_monitor::ProcessMonitor::kGatherInterval * + kTolerableTimeElapsedRatio)) { + battery_discharge.mode = BatteryDischargeMode::kInvalidInterval; + } ReportBatteryHistograms(interval_duration, battery_discharge, suffixes); #if BUILDFLAG(IS_MAC) if (coalition_resource_usage_rate.has_value()) { @@ -194,7 +210,7 @@ void PowerMetricsReporter::OnBatteryAndAggregatedProcessMetricsSampled( const ProcessMonitor::Metrics& aggregated_process_metrics, base::TimeTicks battery_sample_begin_time, - const BatteryLevelProvider::BatteryState& battery_state) { + const BatteryLevelProvider::BatteryState& new_battery_state) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); const base::TimeTicks now = base::TimeTicks::Now(); @@ -208,8 +224,10 @@ interval_begin_ = now; // Evaluate battery discharge mode and rate. - auto battery_discharge = - GetBatteryDischargeDuringInterval(battery_state, interval_duration); + auto previous_battery_state = + std::exchange(battery_state_, new_battery_state); + auto battery_discharge = GetBatteryDischargeDuringInterval( + previous_battery_state, new_battery_state, interval_duration); // Get usage scenario data. auto long_interval_data = @@ -326,49 +344,6 @@ builder.Record(ukm_recorder); } -BatteryDischarge PowerMetricsReporter::GetBatteryDischargeDuringInterval( - const BatteryLevelProvider::BatteryState& new_battery_state, - base::TimeDelta interval_duration) { - auto previous_battery_state = - std::exchange(battery_state_, new_battery_state); - - if (previous_battery_state.battery_count == 0 || - battery_state_.battery_count == 0) { - return {BatteryDischargeMode::kNoBattery, absl::nullopt}; - } - if (!previous_battery_state.on_battery && !battery_state_.on_battery) { - return {BatteryDischargeMode::kPluggedIn, absl::nullopt}; - } - if (previous_battery_state.on_battery != battery_state_.on_battery) { - return {BatteryDischargeMode::kStateChanged, absl::nullopt}; - } - if (!previous_battery_state.charge_level.has_value() || - !battery_state_.charge_level.has_value()) { - return {BatteryDischargeMode::kChargeLevelUnavailable, absl::nullopt}; - } - - // The battery discharge rate is reported per minute with 1/10000 of full - // charge resolution. - static const int64_t kDischargeRateFactor = - 10000 * base::Minutes(1).InSecondsF(); - -#if BUILDFLAG(IS_MAC) - // On MacOS, empirical evidence has shown that right after a full charge, the - // current capacity stays equal to the maximum capacity for several minutes, - // despite the fact that power was definitely consumed. Reporting a zero - // discharge rate for this duration would be misleading. - if (previous_battery_state.charge_level.value() == 1.0) - return {BatteryDischargeMode::kMacFullyCharged, absl::nullopt}; -#endif - - auto discharge_rate = (previous_battery_state.charge_level.value() - - battery_state_.charge_level.value()) * - kDischargeRateFactor / interval_duration.InSeconds(); - if (discharge_rate < 0) - return {BatteryDischargeMode::kBatteryLevelIncreased, absl::nullopt}; - return {BatteryDischargeMode::kDischarging, discharge_rate}; -} - #if BUILDFLAG(IS_MAC) void PowerMetricsReporter::OnShortIntervalBegin() { short_interval_begin_time_ = base::TimeTicks::Now();
diff --git a/chrome/browser/metrics/power/power_metrics_reporter.h b/chrome/browser/metrics/power/power_metrics_reporter.h index 897e479..36a597d7 100644 --- a/chrome/browser/metrics/power/power_metrics_reporter.h +++ b/chrome/browser/metrics/power/power_metrics_reporter.h
@@ -122,7 +122,7 @@ void OnBatteryAndAggregatedProcessMetricsSampled( const ProcessMonitor::Metrics& aggregated_process_metrics, base::TimeTicks battery_sample_begin_time, - const BatteryLevelProvider::BatteryState& battery_state); + const BatteryLevelProvider::BatteryState& new_battery_state); // Report the UKMs for the past interval. static void ReportUKMs( @@ -131,14 +131,6 @@ base::TimeDelta interval_duration, BatteryDischarge battery_discharge); - // Computes and returns the battery discharge mode and rate during the - // interval, and reset |battery_state_| to the current state. If the discharge - // rate isn't valid, the returned value is nullopt and the reason is indicated - // per BatteryDischargeMode. - BatteryDischarge GetBatteryDischargeDuringInterval( - const BatteryLevelProvider::BatteryState& new_battery_state, - base::TimeDelta interval_duration); - #if BUILDFLAG(IS_MAC) // Invoked at the beginning of a "short" interval (~10 seconds before // OnAggregatedMetricsSampled).
diff --git a/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc b/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc index a356187..d981c9e 100644 --- a/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc +++ b/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc
@@ -35,6 +35,9 @@ constexpr base::TimeDelta kExpectedMetricsCollectionInterval = base::Seconds(120); +constexpr double kTolerableTimeElapsedRatio = 0.10; +constexpr double kTolerablePositiveDrift = 1 + kTolerableTimeElapsedRatio; +constexpr double kTolerableNegativeDrift = 1 - kTolerableTimeElapsedRatio; performance_monitor::ProcessMonitor::Metrics GetFakeProcessMetrics() { performance_monitor::ProcessMonitor::Metrics metrics; @@ -236,6 +239,80 @@ } #endif +TEST_F(PowerMetricsReporterUnitTest, BatteryDischargeCaptureIsTooEarly) { + // Pretend that the battery has dropped by 2%. + battery_states_.push(BatteryLevelProvider::BatteryState{ + 1, 1, 0.48, true, base::TimeTicks::Now()}); + + const base::TimeDelta kTooEarly = + kExpectedMetricsCollectionInterval * kTolerableNegativeDrift - + base::Microseconds(1); + task_environment_.FastForwardBy(kTooEarly); + + performance_monitor::ProcessMonitor::Metrics aggregated_process_metrics = {}; + WaitForNextSample(aggregated_process_metrics); + + histogram_tester_.ExpectTotalCount(kBatteryDischargeRateHistogramName, 0); + histogram_tester_.ExpectUniqueSample(kBatteryDischargeModeHistogramName, + BatteryDischargeMode::kInvalidInterval, + 1); +} + +TEST_F(PowerMetricsReporterUnitTest, BatteryDischargeCaptureIsEarly) { + // Pretend that the battery has dropped by 2%. + battery_states_.push(BatteryLevelProvider::BatteryState{ + 1, 1, 0.48, true, base::TimeTicks::Now()}); + + const base::TimeDelta kEarly = + kExpectedMetricsCollectionInterval * kTolerableNegativeDrift + + base::Microseconds(1); + task_environment_.FastForwardBy(kEarly); + + performance_monitor::ProcessMonitor::Metrics aggregated_process_metrics = {}; + WaitForNextSample(aggregated_process_metrics); + + histogram_tester_.ExpectTotalCount(kBatteryDischargeRateHistogramName, 1); + histogram_tester_.ExpectUniqueSample(kBatteryDischargeModeHistogramName, + BatteryDischargeMode::kDischarging, 1); +} + +TEST_F(PowerMetricsReporterUnitTest, BatteryDischargeCaptureIsTooLate) { + // Pretend that the battery has dropped by 2%. + battery_states_.push(BatteryLevelProvider::BatteryState{ + 1, 1, 0.48, true, base::TimeTicks::Now()}); + + const base::TimeDelta kTooLate = + kExpectedMetricsCollectionInterval * kTolerablePositiveDrift + + base::Microseconds(1); + task_environment_.FastForwardBy(kTooLate); + + performance_monitor::ProcessMonitor::Metrics aggregated_process_metrics = {}; + WaitForNextSample(aggregated_process_metrics); + + histogram_tester_.ExpectTotalCount(kBatteryDischargeRateHistogramName, 0); + histogram_tester_.ExpectUniqueSample(kBatteryDischargeModeHistogramName, + BatteryDischargeMode::kInvalidInterval, + 1); +} + +TEST_F(PowerMetricsReporterUnitTest, BatteryDischargeCaptureIsLate) { + // Pretend that the battery has dropped by 2%. + battery_states_.push(BatteryLevelProvider::BatteryState{ + 1, 1, 0.48, true, base::TimeTicks::Now()}); + + const base::TimeDelta kLate = + kExpectedMetricsCollectionInterval * kTolerablePositiveDrift - + base::Microseconds(1); + task_environment_.FastForwardBy(kLate); + + performance_monitor::ProcessMonitor::Metrics aggregated_process_metrics = {}; + WaitForNextSample(aggregated_process_metrics); + + histogram_tester_.ExpectTotalCount(kBatteryDischargeRateHistogramName, 1); + histogram_tester_.ExpectUniqueSample(kBatteryDischargeModeHistogramName, + BatteryDischargeMode::kDischarging, 1); +} + TEST_F(PowerMetricsReporterUnitTest, UKMs) { UsageScenarioDataStore::IntervalData fake_interval_data;
diff --git a/chrome/browser/metrics/power/power_metrics_unittest.cc b/chrome/browser/metrics/power/power_metrics_unittest.cc index 19ba754..9f5e220 100644 --- a/chrome/browser/metrics/power/power_metrics_unittest.cc +++ b/chrome/browser/metrics/power/power_metrics_unittest.cc
@@ -14,17 +14,6 @@ namespace { -constexpr const char* kBatteryDischargeRateHistogramName = - "Power.BatteryDischargeRate2"; -constexpr const char* kBatteryDischargeModeHistogramName = - "Power.BatteryDischargeMode"; - -constexpr base::TimeDelta kExpectedMetricsCollectionInterval = - base::Seconds(120); -constexpr double kTolerableTimeElapsedRatio = 0.10; -constexpr double kTolerablePositiveDrift = 1 + kTolerableTimeElapsedRatio; -constexpr double kTolerableNegativeDrift = 1 - kTolerableTimeElapsedRatio; - #if BUILDFLAG(IS_MAC) power_metrics::CoalitionResourceUsageRate GetFakeResourceUsageRate() { power_metrics::CoalitionResourceUsageRate rate; @@ -115,66 +104,6 @@ }); } -TEST(PowerMetricsTest, BatteryDischargeCaptureIsTooEarly) { - base::HistogramTester histogram_tester; - std::vector<const char*> suffixes = {""}; - - ReportBatteryHistograms( - (kExpectedMetricsCollectionInterval * kTolerableNegativeDrift) - - base::Seconds(1), - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}, suffixes); - - histogram_tester.ExpectTotalCount(kBatteryDischargeRateHistogramName, 0); - histogram_tester.ExpectUniqueSample(kBatteryDischargeModeHistogramName, - BatteryDischargeMode::kInvalidInterval, - 1); -} - -TEST(PowerMetricsTest, BatteryDischargeCaptureIsEarly) { - base::HistogramTester histogram_tester; - std::vector<const char*> suffixes = {""}; - - ReportBatteryHistograms( - (kExpectedMetricsCollectionInterval * kTolerableNegativeDrift) + - base::Seconds(1), - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}, suffixes); - - histogram_tester.ExpectUniqueSample(kBatteryDischargeRateHistogramName, 2500, - 1); - histogram_tester.ExpectUniqueSample(kBatteryDischargeModeHistogramName, - BatteryDischargeMode::kDischarging, 1); -} - -TEST(PowerMetricsTest, BatteryDischargeCaptureIsTooLate) { - base::HistogramTester histogram_tester; - std::vector<const char*> suffixes = {""}; - - ReportBatteryHistograms( - (kExpectedMetricsCollectionInterval * kTolerablePositiveDrift) + - base::Seconds(1), - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}, suffixes); - - histogram_tester.ExpectTotalCount(kBatteryDischargeRateHistogramName, 0); - histogram_tester.ExpectUniqueSample(kBatteryDischargeModeHistogramName, - BatteryDischargeMode::kInvalidInterval, - 1); -} - -TEST(PowerMetricsTest, BatteryDischargeCaptureIsLate) { - base::HistogramTester histogram_tester; - std::vector<const char*> suffixes = {""}; - - ReportBatteryHistograms( - (kExpectedMetricsCollectionInterval * kTolerablePositiveDrift) - - base::Seconds(1), - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}, suffixes); - - histogram_tester.ExpectUniqueSample(kBatteryDischargeRateHistogramName, 2500, - 1); - histogram_tester.ExpectUniqueSample(kBatteryDischargeModeHistogramName, - BatteryDischargeMode::kDischarging, 1); -} - #if BUILDFLAG(IS_MAC) TEST(PowerMetricsTest, ReportShortIntervalHistograms) { base::HistogramTester histogram_tester;
diff --git a/chrome/browser/metrics/ukm_browsertest.cc b/chrome/browser/metrics/ukm_browsertest.cc index 70304e7..f3336c2 100644 --- a/chrome/browser/metrics/ukm_browsertest.cc +++ b/chrome/browser/metrics/ukm_browsertest.cc
@@ -39,7 +39,6 @@ #include "components/sync/driver/sync_service_impl.h" #include "components/sync/driver/sync_token_status.h" #include "components/sync/test/fake_server/fake_server_network_resources.h" -#include "components/ukm/content/source_url_recorder.h" #include "components/ukm/ukm_recorder_observer.h" #include "components/ukm/ukm_service.h" #include "components/ukm/ukm_test_helper.h"
diff --git a/chrome/browser/net/dns_probe_service_factory_unittest.cc b/chrome/browser/net/dns_probe_service_factory_unittest.cc index 739104a..c26653fb 100644 --- a/chrome/browser/net/dns_probe_service_factory_unittest.cc +++ b/chrome/browser/net/dns_probe_service_factory_unittest.cc
@@ -343,9 +343,10 @@ EXPECT_THAT(overrides.secure_dns_mode, testing::Optional(net::SecureDnsMode::kSecure)); - EXPECT_THAT(overrides.dns_over_https_config, - testing::Optional(*net::DnsOverHttpsConfig::FromStrings( - {kDohTemplateGet, kDohTemplatePost}))); + EXPECT_THAT( + overrides.dns_over_https_config, + testing::Optional(*net::DnsOverHttpsConfig::FromTemplatesForTesting( + {kDohTemplateGet, kDohTemplatePost}))); } } // namespace
diff --git a/chrome/browser/ntp_tiles/chrome_most_visited_sites_factory.cc b/chrome/browser/ntp_tiles/chrome_most_visited_sites_factory.cc index 2ce8f04e..a3fd4c0 100644 --- a/chrome/browser/ntp_tiles/chrome_most_visited_sites_factory.cc +++ b/chrome/browser/ntp_tiles/chrome_most_visited_sites_factory.cc
@@ -36,7 +36,7 @@ #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/supervised_user/supervised_user_service_observer.h" -#include "chrome/browser/supervised_user/supervised_user_url_filter.h" +#include "chrome/browser/supervised_user/supervised_user_url_filter.h" // nogncheck #endif #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc index ad5908e1..771bf04 100644 --- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc +++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
@@ -24,6 +24,7 @@ #include "chrome/browser/profiles/profile_key.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/chrome_paths.h" +#include "components/component_updater/pref_names.h" #include "components/leveldb_proto/public/proto_database_provider.h" #include "components/optimization_guide/core/command_line_top_host_provider.h" #include "components/optimization_guide/core/hints_processing_util.h" @@ -40,6 +41,7 @@ #include "components/optimization_guide/core/tab_url_provider.h" #include "components/optimization_guide/core/top_host_provider.h" #include "components/optimization_guide/proto/models.pb.h" +#include "components/prefs/pref_service.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h" @@ -107,8 +109,7 @@ OPTIMIZATION_GUIDE_LOG(optimization_guide_logger, "FEATURE_FLAG Hints component disabled"); } - if (!optimization_guide::features::IsRemoteFetchingEnabled( - profile->GetPrefs())) { + if (!optimization_guide::features::IsRemoteFetchingEnabled()) { OPTIMIZATION_GUIDE_LOG(optimization_guide_logger, "FEATURE_FLAG remote fetching feature disabled"); } @@ -165,6 +166,11 @@ return BackgroundDownloadServiceFactory::GetForKey(profile->GetProfileKey()); } +bool OptimizationGuideKeyedService::ComponentUpdatesEnabledProvider() const { + return g_browser_process->local_state()->GetBoolean( + ::prefs::kComponentUpdatesEnabled); +} + void OptimizationGuideKeyedService::Initialize() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -263,6 +269,11 @@ &OptimizationGuideKeyedService::BackgroundDownloadServiceProvider, // It's safe to use |base::Unretained(this)| here because // |this| owns |prediction_manager_|. + base::Unretained(this)), + base::BindRepeating( + &OptimizationGuideKeyedService::ComponentUpdatesEnabledProvider, + // It's safe to use |base::Unretained(this)| here because + // |this| owns |prediction_manager_|. base::Unretained(this))); // The previous store paths were written in incorrect locations. Delete the
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h index 74a92ad..78de30c 100644 --- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h +++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
@@ -187,6 +187,8 @@ download::BackgroundDownloadService* BackgroundDownloadServiceProvider(); + bool ComponentUpdatesEnabledProvider() const; + raw_ptr<content::BrowserContext> browser_context_; // The store of hints.
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc b/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc index dc060b7..b639677 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc +++ b/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc
@@ -28,6 +28,7 @@ #include "chrome/common/chrome_paths.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/component_updater/pref_names.h" #include "components/metrics/content/subprocess_metrics_provider.h" #include "components/optimization_guide/core/model_util.h" #include "components/optimization_guide/core/optimization_guide_constants.h" @@ -315,11 +316,11 @@ }; IN_PROC_BROWSER_TEST_F(PredictionManagerBrowserTest, - RemoteFetchingPrefDisabled) { + ComponentUpdatesPrefDisabled) { ModelFileObserver model_file_observer; SetResponseType(PredictionModelsFetcherRemoteResponseType::kUnsuccessful); - browser()->profile()->GetPrefs()->SetBoolean( - optimization_guide::prefs::kOptimizationGuideFetchingEnabled, false); + g_browser_process->local_state()->SetBoolean( + ::prefs::kComponentUpdatesEnabled, false); base::HistogramTester histogram_tester; RegisterWithKeyedService(&model_file_observer);
diff --git a/chrome/browser/page_load_metrics/observers/core/INP.md b/chrome/browser/page_load_metrics/observers/core/INP.md new file mode 100644 index 0000000..d65678cf --- /dev/null +++ b/chrome/browser/page_load_metrics/observers/core/INP.md
@@ -0,0 +1,90 @@ +# Interaction to Next Paint + +[Interaction to Next Paint](https://web.dev/inp) is an experimental metric that +reports the 98th percentile interaction duration over the course of a page view. +We are evaluating it in the hopes that it one day replaces +[First Input Delay](https://web.dev/fid) + +This document details: +* [Where it is computed in the renderer](#Computation-in-Renderer) +* [How it is reported in trace events and web performance APIs](#Reporting-in-web-performance-APIs-and-trace-events) +* [How values from different frames are merged](#Merging-multiple-frames) +* [How it is reported to UKM/UMA](#Reporting-in-UKM-and-UMA) + +## Computation in Renderer + +Individual interactions are timed in the renderer. To understand interactions +better, it might be helpful to start with the documentation on how interactions +are defined in our +[blog post about defining the metric](https://web.dev/better-responsiveness-metric/#group-events-into-interactions). + +The code works like this: + +* Interactions are created in the [`EventTiming`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/event_timing) + class. Its [`Create()`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/event_timing.cc;l=95;drc=b41db61995ded8bd8ee37dfba0c09d7c17d78e55;bpv=1;bpt=1) + method is called from event dispatch of various events. +* When the `EventTiming` destructor is called, it calls + [`WindowPerformance::RegisterEventTiming()`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/window_performance.cc;drc=b41db61995ded8bd8ee37dfba0c09d7c17d78e55;bpv=1;bpt=1;l=381) + which in turn registers a callback for the presentation timestamp. +* The presentation timestamp callback is + [`WindowPerformance::ReportEventTimings()`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/window_performance.cc;l=441?q=WindowPerformance::ReportEventTimings&ss=chromium) + It does the following: + * Sets the `duration` and other timestamps of the EventTiming + * Calls + [`WindowPerformance::SetInteractionIdAndRecordLatency`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/window_performance.cc;l=562;drc=1d8b1965b96c021ee069a3ebda38be7aaf8a5786;bpv=1;bpt=1?q=WindowPerformance::ReportEventTimings&ss=chromium) + which sets the interaction id. + * Calls + [`ResponsivenessMetrics::RecordUserInteractionUKM()`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/responsiveness_metrics.cc;l=186;drc=1d8b1965b96c021ee069a3ebda38be7aaf8a5786;bpv=1;bpt=1) + which calculates the maximum interaction duration and calls + [`LocalFrameClientImpl::DidObserveUserInteraction()`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/frame/local_frame_client_impl.cc;l=712;drc=1d8b1965b96c021ee069a3ebda38be7aaf8a5786;bpv=1;bpt=1) + which kicks off [marshalling the interaction data to the browser](../../passing_data_from_renderer_to_browser.md). + * *Note that `ResponsivenessMetrics::RecordUserInteractionUKM()` records a + **separate** `Responsiveness.UserInteraction` UKM for individual interactions; + the INP UKM is logged in the browser as described below.* + +The data for the responsiveness metric is in the +[`ResponsivenessMetrics`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/responsiveness_metrics.cc;l=186;drc=1d8b1965b96c021ee069a3ebda38be7aaf8a5786;bpv=1;bpt=1) +class; tracing back from that class can help answer questions about individual +interactions. + +## Reporting in web performance APIs and trace events + +* The [Event Timing API](https://w3c.github.io/event-timing/) reports timings of + individual events, and reports interactionIds for events tied to interactions. + These timings are reported through + [`WindowPerformance::ReportEventTimings()`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/window_performance.cc;l=441?q=WindowPerformance::ReportEventTimings&ss=chromium). +* Event traces are available in a few places: + * [`ResponsivenessMetrics::RecordUserInteractionUKM()`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/responsiveness_metrics.cc;l=186;drc=1d8b1965b96c021ee069a3ebda38be7aaf8a5786;bpv=1;bpt=1) + emits a trace event `Responsiveness.Renderer.UserInteraction` in the + category `devtools.timeline` for each interaction. + * [`WindowPerformance::NotifyAndAddEventTimingBuffer`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/window_performance.cc;l=562;drc=1d8b1965b96c021ee069a3ebda38be7aaf8a5786;bpv=1;bpt=1?q=WindowPerformance::ReportEventTimings&ss=chromium) + emits a trace event `EventTiming` in the category `devtools.timeline` for + each event reported by the EventTiming API. + +## Merging multiple frames + +Data about each interaction in the main frame and all subframes is sent from +renderer to browser via the page load metrics infrastructure. +[You can read more about the data flow here](../../passing_data_from_renderer_to_browser.md). + +[`PageLoadMetricsUpdateDispatcher::UpdatePageInputTiming`](https://source.chromium.org/chromium/chromium/src/+/main:components/page_load_metrics/browser/page_load_metrics_update_dispatcher.cc;l=726;drc=1d8b1965b96c021ee069a3ebda38be7aaf8a5786;bpv=1;bpt=1) +calls +[`ResponsivenessMetricsNormalization::AddNewUserInteractionLatencies`](https://source.chromium.org/chromium/chromium/src/+/main:components/page_load_metrics/browser/responsiveness_metrics_normalization.cc;l=61;drc=1d8b1965b96c021ee069a3ebda38be7aaf8a5786;bpv=1;bpt=1) +which aggregates the interactions across all subframes and calculates the 98th +percentile latency which is reported as INP. Metrics from all frames are treated +equally in the calculation. + +## Reporting in UKM and UMA + +All Core Web Vitals UKM are reported via +[PageLoadMetricsObserver](/chrome/browser/page_load_metrics/observers/README.md). +This ensures consistent reporting of only main frames, excluding error pages, +etc. + +UKM for INP are: +* Most navigations: `PageLoad.InteractiveTiming.UserInteractionLatency.HighPercentile2.MaxEventDuration` +* BFCache navigations: `HistoryNavigation.UserInteractionLatencyAfterBackForwardCacheRestore.HighPercentile2.MaxEventDuration` + +UMA for INP are: +* Most navigations: `PageLoad.InteractiveTiming.UserInteractionLatency.HighPercentile2.MaxEventDuration` +* BFCache navigations: `PageLoad.InteractiveTiming.UserInteractionLatency.HighPercentile2.MaxEventDuration.AfterBackForwardCacheRestore`
diff --git a/chrome/browser/picture_in_picture/document_picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/document_picture_in_picture_window_controller_browsertest.cc index 21cdffe3..3feeff9 100644 --- a/chrome/browser/picture_in_picture/document_picture_in_picture_window_controller_browsertest.cc +++ b/chrome/browser/picture_in_picture/document_picture_in_picture_window_controller_browsertest.cc
@@ -152,7 +152,7 @@ // Checks the creation of the window controller, as well as basic window // creation, visibility and activation. IN_PROC_BROWSER_TEST_F(DocumentPictureInPictureWindowControllerBrowserTest, - CreationAndVisibilityAndActivation) { + DISABLED_CreationAndVisibilityAndActivation) { LoadTabAndEnterPictureInPicture(browser()); gfx::NativeWindow native_window = GetOverlayWindow()->GetNativeWindow(); @@ -163,7 +163,7 @@ // window twice in a row should work, closing the old window before opening the // new one. IN_PROC_BROWSER_TEST_F(DocumentPictureInPictureWindowControllerBrowserTest, - CreateTwice) { + DISABLED_CreateTwice) { LoadTabAndEnterPictureInPicture(browser()); gfx::NativeWindow native_window_1 = GetOverlayWindow()->GetNativeWindow(); @@ -191,7 +191,7 @@ // Tests closing the document picture-in-picture window. IN_PROC_BROWSER_TEST_F(DocumentPictureInPictureWindowControllerBrowserTest, - CloseWindow) { + DISABLED_CloseWindow) { LoadTabAndEnterPictureInPicture(browser()); window_controller()->Close(/*should_pause_video=*/true); @@ -201,7 +201,7 @@ // Tests navigating the opener closes the picture in picture window. IN_PROC_BROWSER_TEST_F(DocumentPictureInPictureWindowControllerBrowserTest, - ClosePictureInPictureWhenOpenerNavigates) { + DISABLED_ClosePictureInPictureWhenOpenerNavigates) { LoadTabAndEnterPictureInPicture(browser()); GURL test_page_url = ui_test_utils::GetTestUrl( base::FilePath(base::FilePath::kCurrentDirectory), @@ -211,8 +211,9 @@ } // Navigation by the pip window to a new document should close the pip window. -IN_PROC_BROWSER_TEST_F(DocumentPictureInPictureWindowControllerBrowserTest, - CloseOnPictureInPictureNavigationToNewDocument) { +IN_PROC_BROWSER_TEST_F( + DocumentPictureInPictureWindowControllerBrowserTest, + DISABLED_CloseOnPictureInPictureNavigationToNewDocument) { LoadTabAndEnterPictureInPicture(browser()); content::WebContents* active_web_contents = @@ -225,8 +226,9 @@ } // Navigation within the pip window's document should not close the pip window. -IN_PROC_BROWSER_TEST_F(DocumentPictureInPictureWindowControllerBrowserTest, - DoNotCloseOnPictureInPictureNavigationInsideDocument) { +IN_PROC_BROWSER_TEST_F( + DocumentPictureInPictureWindowControllerBrowserTest, + DISABLED_DoNotCloseOnPictureInPictureNavigationInsideDocument) { LoadTabAndEnterPictureInPicture(browser()); content::WebContents* active_web_contents = @@ -238,7 +240,7 @@ } IN_PROC_BROWSER_TEST_F(DocumentPictureInPictureWindowControllerBrowserTest, - RequiresSecureContext) { + DISABLED_RequiresSecureContext) { GURL test_page_url("http://media/picture-in-picture/blank.html"); ASSERT_FALSE(network::IsUrlPotentiallyTrustworthy(test_page_url)); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page_url));
diff --git a/chrome/browser/plugins/plugin_info_host_impl.cc b/chrome/browser/plugins/plugin_info_host_impl.cc index 9c88965..22e8a17b 100644 --- a/chrome/browser/plugins/plugin_info_host_impl.cc +++ b/chrome/browser/plugins/plugin_info_host_impl.cc
@@ -38,7 +38,6 @@ #include "components/nacl/common/buildflags.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" -#include "components/ukm/content/source_url_recorder.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/plugin_service.h" #include "content/public/browser/plugin_service_filter.h"
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index aa6f218..e0308ec 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -78,7 +78,6 @@ #include "components/metrics/metrics_pref_names.h" #include "components/network_time/network_time_pref_names.h" #include "components/omnibox/browser/omnibox_prefs.h" -#include "components/optimization_guide/core/optimization_guide_prefs.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/payments/core/payment_prefs.h" #include "components/policy/core/browser/configuration_policy_handler.h" @@ -212,9 +211,6 @@ { key::kEditBookmarksEnabled, bookmarks::prefs::kEditBookmarksEnabled, base::Value::Type::BOOLEAN }, - { key::kOptimizationGuideFetchingEnabled, - optimization_guide::prefs::kOptimizationGuideFetchingEnabled, - base::Value::Type::BOOLEAN }, { key::kPasswordManagerEnabled, password_manager::prefs::kCredentialsEnableService, base::Value::Type::BOOLEAN },
diff --git a/chrome/browser/policy/messaging_layer/util/get_cloud_policy_client_unittest.cc b/chrome/browser/policy/messaging_layer/util/get_cloud_policy_client_unittest.cc index c8008c7..1430155 100644 --- a/chrome/browser/policy/messaging_layer/util/get_cloud_policy_client_unittest.cc +++ b/chrome/browser/policy/messaging_layer/util/get_cloud_policy_client_unittest.cc
@@ -14,7 +14,6 @@ #include <cstddef> #include "base/bind.h" -#include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "chrome/browser/browser_process.h" #include "components/policy/core/common/cloud/cloud_policy_client.h"
diff --git a/chrome/browser/policy/messaging_layer/util/heartbeat_event.h b/chrome/browser/policy/messaging_layer/util/heartbeat_event.h deleted file mode 100644 index 480955d9..0000000 --- a/chrome/browser/policy/messaging_layer/util/heartbeat_event.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_HEARTBEAT_EVENT_H_ -#define CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_HEARTBEAT_EVENT_H_ - -#include "base/feature_list.h" -#include "components/keyed_service/core/keyed_service.h" - -namespace reporting { - -class HeartbeatEvent : public KeyedService { - public: - HeartbeatEvent(); - ~HeartbeatEvent() override; - - // KeyedService - void Shutdown() override; - - private: - - // Starts a self-managed ReportQueueManualTestContext running on its own - // SequencedTaskRunner. Will upload ten records to the HEARTBEAT_EVENTS - // Destination and delete itself. - void StartHeartbeatEvent() const; -}; - -} // namespace reporting - -#endif // CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_HEARTBEAT_EVENT_H_
diff --git a/chrome/browser/policy/messaging_layer/util/heartbeat_event_factory.cc b/chrome/browser/policy/messaging_layer/util/heartbeat_event_factory.cc deleted file mode 100644 index a07c58e..0000000 --- a/chrome/browser/policy/messaging_layer/util/heartbeat_event_factory.cc +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/policy/messaging_layer/util/heartbeat_event_factory.h" - -#include "chrome/browser/policy/messaging_layer/util/heartbeat_event.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" - -namespace reporting { - -HeartbeatEventFactory* HeartbeatEventFactory::GetInstance() { - return base::Singleton<HeartbeatEventFactory>::get(); -} - -HeartbeatEventFactory::HeartbeatEventFactory() - : BrowserContextKeyedServiceFactory( - "HeartbeatEvent", - BrowserContextDependencyManager::GetInstance()) {} - -HeartbeatEventFactory::~HeartbeatEventFactory() = default; - -KeyedService* HeartbeatEventFactory::BuildServiceInstanceFor( - content::BrowserContext* context) const { - return new HeartbeatEvent(); -} - -bool HeartbeatEventFactory::ServiceIsCreatedWithBrowserContext() const { - return true; -} - -bool HeartbeatEventFactory::ServiceIsNULLWhileTesting() const { - return true; -} - -} // namespace reporting
diff --git a/chrome/browser/policy/messaging_layer/util/heartbeat_event_factory.h b/chrome/browser/policy/messaging_layer/util/heartbeat_event_factory.h deleted file mode 100644 index 636361ee..0000000 --- a/chrome/browser/policy/messaging_layer/util/heartbeat_event_factory.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright (c) 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_HEARTBEAT_EVENT_FACTORY_H_ -#define CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_HEARTBEAT_EVENT_FACTORY_H_ - -#include "base/memory/singleton.h" -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" - -namespace reporting { - -class HeartbeatEventFactory : public BrowserContextKeyedServiceFactory { - public: - static HeartbeatEventFactory* GetInstance(); - - private: - friend struct base::DefaultSingletonTraits<HeartbeatEventFactory>; - - HeartbeatEventFactory(); - ~HeartbeatEventFactory() override; - - // BrowserContextKeyedServiceFactyory - KeyedService* BuildServiceInstanceFor( - content::BrowserContext* context) const override; - bool ServiceIsCreatedWithBrowserContext() const override; - bool ServiceIsNULLWhileTesting() const override; -}; - -} // namespace reporting - -#endif // CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_HEARTBEAT_EVENT_FACTORY_H_
diff --git a/chrome/browser/policy/messaging_layer/util/heartbeat_event.cc b/chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event.cc similarity index 65% rename from chrome/browser/policy/messaging_layer/util/heartbeat_event.cc rename to chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event.cc index 0118585c..63e7e86b 100644 --- a/chrome/browser/policy/messaging_layer/util/heartbeat_event.cc +++ b/chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event.cc
@@ -1,8 +1,8 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. +// Copyright 2022 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/policy/messaging_layer/util/heartbeat_event.h" +#include "chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event.h" #include "base/callback.h" #include "base/feature_list.h" @@ -20,24 +20,25 @@ namespace reporting { namespace { -const base::Feature kEncryptedReportingHeartbeatEvent{ - "EncryptedReportingHeartbeatEvent", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kEncryptedReportingManualTestHeartbeatEvent{ + "EncryptedReportingManualTestHeartbeatEvent", + base::FEATURE_DISABLED_BY_DEFAULT}; } // namespace -HeartbeatEvent::HeartbeatEvent() { +ManualTestHeartbeatEvent::ManualTestHeartbeatEvent() { StartHeartbeatEvent(); } -HeartbeatEvent::~HeartbeatEvent() { +ManualTestHeartbeatEvent::~ManualTestHeartbeatEvent() { Shutdown(); } -void HeartbeatEvent::Shutdown() { -} +void ManualTestHeartbeatEvent::Shutdown() {} -void HeartbeatEvent::StartHeartbeatEvent() const { - if (!base::FeatureList::IsEnabled(kEncryptedReportingHeartbeatEvent)) { +void ManualTestHeartbeatEvent::StartHeartbeatEvent() const { + if (!base::FeatureList::IsEnabled( + kEncryptedReportingManualTestHeartbeatEvent)) { return; }
diff --git a/chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event.h b/chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event.h new file mode 100644 index 0000000..c8b2c79 --- /dev/null +++ b/chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event.h
@@ -0,0 +1,32 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_MANUAL_TEST_HEARTBEAT_EVENT_H_ +#define CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_MANUAL_TEST_HEARTBEAT_EVENT_H_ + +#include "base/feature_list.h" +#include "components/keyed_service/core/keyed_service.h" + +namespace reporting { + +// This class is only used for manual testing purpose. Do not depend on it in +// other parts of the production code. +class ManualTestHeartbeatEvent : public KeyedService { + public: + ManualTestHeartbeatEvent(); + ~ManualTestHeartbeatEvent() override; + + // KeyedService + void Shutdown() override; + + private: + // Starts a self-managed ReportQueueManualTestContext running on its own + // SequencedTaskRunner. Will upload ten records to the HEARTBEAT_EVENTS + // Destination and delete itself. + void StartHeartbeatEvent() const; +}; + +} // namespace reporting + +#endif // CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_MANUAL_TEST_HEARTBEAT_EVENT_H_
diff --git a/chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event_factory.cc b/chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event_factory.cc new file mode 100644 index 0000000..71ea9af --- /dev/null +++ b/chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event_factory.cc
@@ -0,0 +1,38 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event_factory.h" + +#include "chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" + +namespace reporting { + +ManualTestHeartbeatEventFactory* +ManualTestHeartbeatEventFactory::GetInstance() { + return base::Singleton<ManualTestHeartbeatEventFactory>::get(); +} + +ManualTestHeartbeatEventFactory::ManualTestHeartbeatEventFactory() + : BrowserContextKeyedServiceFactory( + "ManualTestHeartbeatEvent", + BrowserContextDependencyManager::GetInstance()) {} + +ManualTestHeartbeatEventFactory::~ManualTestHeartbeatEventFactory() = default; + +KeyedService* ManualTestHeartbeatEventFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + return new ManualTestHeartbeatEvent(); +} + +bool ManualTestHeartbeatEventFactory::ServiceIsCreatedWithBrowserContext() + const { + return true; +} + +bool ManualTestHeartbeatEventFactory::ServiceIsNULLWhileTesting() const { + return true; +} + +} // namespace reporting
diff --git a/chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event_factory.h b/chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event_factory.h new file mode 100644 index 0000000..dc83e65 --- /dev/null +++ b/chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event_factory.h
@@ -0,0 +1,35 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_MANUAL_TEST_HEARTBEAT_EVENT_FACTORY_H_ +#define CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_MANUAL_TEST_HEARTBEAT_EVENT_FACTORY_H_ + +#include "base/memory/singleton.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +namespace reporting { + +// This class is only used for manual testing purpose. Do not depend on it in +// other parts of the production code. +class ManualTestHeartbeatEventFactory + : public BrowserContextKeyedServiceFactory { + public: + static ManualTestHeartbeatEventFactory* GetInstance(); + + private: + friend struct base::DefaultSingletonTraits<ManualTestHeartbeatEventFactory>; + + ManualTestHeartbeatEventFactory(); + ~ManualTestHeartbeatEventFactory() override; + + // BrowserContextKeyedServiceFactyory + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; + bool ServiceIsCreatedWithBrowserContext() const override; + bool ServiceIsNULLWhileTesting() const override; +}; + +} // namespace reporting + +#endif // CHROME_BROWSER_POLICY_MESSAGING_LAYER_UTIL_MANUAL_TEST_HEARTBEAT_EVENT_FACTORY_H_
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc b/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc index ad3611d..6241ef19 100644 --- a/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc +++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
@@ -3148,7 +3148,7 @@ }; IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceNavigationPrefetchBrowserTest, - NavigationPrefetchIsServed) { + DISABLED_NavigationPrefetchIsServed) { SetDSEWithURL( GetSearchServerQueryURL("{searchTerms}&{google:prefetchSource}"), true); auto* search_prefetch_service =
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index a2f2393..6a49e31 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -770,6 +770,10 @@ const char kTimeOnOobe[] = "settings.time_on_oobe"; #endif // BUILDFLAG(IS_CHROMEOS_ASH) +// Deprecated 04/2022. +const char kOptimizationGuideRemoteFetchingEnabled[] = + "optimization_guide.remote_fetching_enabled"; + // Register local state used only for migration (clearing or moving to a new // key). void RegisterLocalStatePrefsForMigration(PrefRegistrySimple* registry) { @@ -1012,6 +1016,8 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) registry->RegisterIntegerPref(kTimeOnOobe, 0); #endif // BUILDFLAG(IS_CHROMEOS_ASH) + + registry->RegisterBooleanPref(kOptimizationGuideRemoteFetchingEnabled, true); } } // namespace @@ -1969,6 +1975,9 @@ profile_prefs->ClearPref(kTimeOnOobe); #endif // BUILDFLAG(IS_CHROMEOS_ASH) + // Added 04/2022 + profile_prefs->ClearPref(kOptimizationGuideRemoteFetchingEnabled); + // Please don't delete the following line. It is used by PRESUBMIT.py. // END_MIGRATE_OBSOLETE_PROFILE_PREFS
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 461e528..62992ec 100644 --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -175,7 +175,7 @@ #if BUILDFLAG(IS_CHROMEOS) #include "chrome/browser/apps/intent_helper/supported_links_infobar_prefs_service_factory.h" #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h" -#include "chrome/browser/policy/messaging_layer/util/heartbeat_event_factory.h" +#include "chrome/browser/policy/messaging_layer/util/manual_test_heartbeat_event_factory.h" #include "chrome/browser/policy/networking/policy_cert_service_factory.h" #include "chrome/browser/policy/networking/user_network_configuration_updater_factory.h" #endif @@ -492,7 +492,7 @@ RendererUpdaterFactory::GetInstance(); #if BUILDFLAG(IS_CHROMEOS) - reporting::HeartbeatEventFactory::GetInstance(); + reporting::ManualTestHeartbeatEventFactory::GetInstance(); #endif #if !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn index 1d3dc8e3..8c37560db 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
@@ -53,7 +53,7 @@ "background/user_action_monitor.js", "common/abstract_earcons.js", "common/background_bridge.js", - "common/braille_interface.js", + "common/braille/braille_interface.js", "common/bridge_constants.js", "common/bridge_helper.js", "common/extension_bridge.js", @@ -86,7 +86,6 @@ "background/braille/braille_display_manager.js", "background/braille/braille_input_handler.js", "background/braille/braille_key_event_rewriter.js", - "background/braille/braille_table.js", "background/braille/braille_translator_manager.js", "background/braille/cursor_dots.js", "background/braille/expanding_braille_translator.js", @@ -95,7 +94,6 @@ "background/classic_background.js", "background/command_handler.js", "background/console_tts.js", - "background/custom_automation_event.js", "background/desktop_automation_handler.js", "background/desktop_automation_interface.js", "background/download_handler.js", @@ -117,15 +115,18 @@ "background/page_load_sound_handler.js", "background/panel/i_search.js", "background/panel/i_search_handler.js", + "background/panel/panel_background.js", "background/pointer_handler.js", "background/prefs.js", "background/range_automation_handler.js", "background/smart_sticky_mode.js", "background/tts_background.js", "common/abstract_tts.js", - "common/braille_command_data.js", + "common/braille/braille_command_data.js", + "common/braille/braille_table.js", "common/command_store.js", "common/composite_tts.js", + "common/custom_automation_event.js", "common/editable_text_base.js", "common/gesture_command_data.js", "common/key_map.js", @@ -393,7 +394,7 @@ "background/braille/liblouis.js", "background/phonetic_data.js", "common/abstract_earcons.js", - "common/braille_interface.js", + "common/braille/braille_interface.js", "common/editable_text_base.js", "common/key_sequence.js", "common/msgs.js", @@ -450,6 +451,7 @@ "background/smart_sticky_mode_test.js", "background/tts_background_test.js", "background/user_action_monitor_test.js", + "common/braille/braille_command_data_test.js", "learn_mode/learn_mode_test.js", "options/bluetooth_braille_display_ui_test.js", "options/options_test.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js index 9a5c2d74..23463ee 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
@@ -17,6 +17,7 @@ import {MathHandler} from '/chromevox/background/math_handler.js'; import {MediaAutomationHandler} from '/chromevox/background/media_automation_handler.js'; import {PageLoadSoundHandler} from '/chromevox/background/page_load_sound_handler.js'; +import {PanelBackground} from '/chromevox/background/panel/panel_background.js'; import {RangeAutomationHandler} from '/chromevox/background/range_automation_handler.js'; import {InstanceChecker} from '/common/instance_checker.js'; @@ -99,6 +100,7 @@ FindHandler.init(); DownloadHandler.init(); JaPhoneticData.init(JaPhoneticMap.MAP); + PanelBackground.init(); chrome.accessibilityPrivate.onAnnounceForAccessibility.addListener( (announceText) => {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js index 5a2023b..3e5c91c8 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
@@ -31,7 +31,7 @@ 'ChromeVoxBackground', '/chromevox/background/classic_background.js'); await importModule( 'CustomAutomationEvent', - '/chromevox/background/custom_automation_event.js'); + '/chromevox/common/custom_automation_event.js'); await importModule( 'DesktopAutomationInterface', '/chromevox/background/desktop_automation_interface.js');
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/base_automation_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/base_automation_handler.js index d058914..b8557611 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/base_automation_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/base_automation_handler.js
@@ -6,7 +6,7 @@ * @fileoverview Basic facillities to handle events from a single automation * node. */ -import {ChromeVoxEvent} from '/chromevox/background/custom_automation_event.js'; +import {ChromeVoxEvent} from '/chromevox/common/custom_automation_event.js'; const ActionType = chrome.automation.ActionType; const AutomationEvent = chrome.automation.AutomationEvent;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_captions_background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_captions_background.js index 2f89991..a0325da3 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_captions_background.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_captions_background.js
@@ -7,6 +7,7 @@ * braille content to the Panel on Chrome OS, or a content script on * other platforms. */ +import {ChromeVoxPrefs} from '../prefs.js'; export const BrailleCaptionsBackground = {}; @@ -145,7 +146,7 @@ BrailleCaptionsBackground.setActive = function(newValue) { const self = BrailleCaptionsBackground; const oldValue = self.isEnabled(); - window['prefs'].setPref(self.PREF_KEY, String(newValue)); + ChromeVoxPrefs.instance.setPref(self.PREF_KEY, String(newValue)); if (oldValue !== newValue) { if (self.stateCallback_) { self.stateCallback_();
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_command_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_command_handler.js index ec009260..c6894ae 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_command_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_command_handler.js
@@ -6,7 +6,7 @@ * @fileoverview ChromeVox braille commands. */ import {DesktopAutomationInterface} from '/chromevox/background/desktop_automation_interface.js'; -import {BrailleCommandData} from '/chromevox/common/braille_command_data.js'; +import {BrailleCommandData} from '/chromevox/common/braille/braille_command_data.js'; import {EventGenerator} from '/common/event_generator.js'; const RoleType = chrome.automation.RoleType;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_table_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_table_test.js index 22fcab2..c8f33a18 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_table_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_table_test.js
@@ -15,7 +15,7 @@ async setUpDeferred() { await super.setUpDeferred(); await importModule( - 'BrailleTable', '/chromevox/background/braille/braille_table.js'); + 'BrailleTable', '/chromevox/common/braille/braille_table.js'); } };
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager.js index 8aeef80..8906018e 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager.js
@@ -5,8 +5,8 @@ /** * @fileoverview Keeps track of the current braille translators. */ -import {BrailleTable} from '/chromevox/background/braille/braille_table.js'; import {ExpandingBrailleTranslator} from '/chromevox/background/braille/expanding_braille_translator.js'; +import {BrailleTable} from '/chromevox/common/braille/braille_table.js'; export class BrailleTranslatorManager { /**
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager_test.js index ddbf1bd..a367461 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_translator_manager_test.js
@@ -15,7 +15,7 @@ async setUpDeferred() { await super.setUpDeferred(); await importModule( - 'BrailleTable', '/chromevox/background/braille/braille_table.js'); + 'BrailleTable', '/chromevox/common/braille/braille_table.js'); await importModule( 'BrailleTranslatorManager', '/chromevox/background/braille/braille_translator_manager.js');
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/liblouis_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/liblouis_test.js index 6f5eab1..e9769b26 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/liblouis_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/liblouis_test.js
@@ -15,7 +15,7 @@ async setUpDeferred() { await super.setUpDeferred(); await importModule( - 'BrailleTable', '/chromevox/background/braille/braille_table.js'); + 'BrailleTable', '/chromevox/common/braille/braille_table.js'); } createLiblouis() {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox.js index fbf33f9b..b640ce7d 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox.js
@@ -8,7 +8,8 @@ // Forward declare. goog.addDependency('../common/abstract_earcons.js', ['AbstractEarcons'], []); -goog.addDependency('../common/braille_interface.js', ['BrailleInterface'], []); +goog.addDependency( + '../common/braille/braille_interface.js', ['BrailleInterface'], []); goog.addDependency('../common/tts_interface.js', ['TtsInterface'], []); goog.provide('ChromeVox');
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/classic_background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/classic_background.js index 7a7f99c..a5d97f6 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/classic_background.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/classic_background.js
@@ -93,17 +93,17 @@ /** * @param {string} pref - * @param {*} value + * @param {Object|boolean|number|string} value * @param {boolean} announce */ static setPref(pref, value, announce) { if (pref === 'earcons') { - AbstractEarcons.enabled = !!value; + AbstractEarcons.enabled = Boolean(value); } else if (pref === 'sticky' && announce) { if (typeof (value) !== 'boolean') { throw new Error('Unexpected sticky mode value ' + value); } - chrome.accessibilityPrivate.setKeyboardListener(true, !!value); + chrome.accessibilityPrivate.setKeyboardListener(true, Boolean(value)); new Output() .withInitialSpeechProperties(AbstractTts.PERSONALITY_ANNOTATION) .withString( @@ -135,13 +135,13 @@ .go(); } } else if (pref === 'brailleCaptions') { - BrailleCaptionsBackground.setActive(!!value); + BrailleCaptionsBackground.setActive(Boolean(value)); } else if (pref === 'position') { ChromeVox.position = /** @type {Object<string, constants.Point>} */ (JSON.parse( /** @type {string} */ (value))); } - window['prefs'].setPref(pref, value); + ChromeVoxPrefs.instance.setPref(pref, value); ChromeVoxBackground.readPrefs(); } @@ -310,11 +310,9 @@ // object for access by the options page. const background = new ChromeVoxBackground(); - // TODO: this needs to be cleaned up (move to init?). - window['speak'] = background.tts.speak.bind(background.tts); ChromeVoxState.backgroundTts = background.backgroundTts_; - // Export the prefs object for access by the options page. - window['prefs'] = ChromeVoxPrefs.instance; - window['getCurrentVoice'] = background.getCurrentVoice.bind(background); + BridgeHelper.registerHandler( + /* target= */ 'ChromeVoxBackground', 'getCurrentVoice', + () => background.getCurrentVoice()); } }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js index e91ca19..5df76e4 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
@@ -10,13 +10,13 @@ import {BrailleCaptionsBackground} from '/chromevox/background/braille/braille_captions_background.js'; import {ChromeVoxBackground} from '/chromevox/background/classic_background.js'; import {Color} from '/chromevox/background/color.js'; -import {CustomAutomationEvent} from '/chromevox/background/custom_automation_event.js'; import {DesktopAutomationInterface} from '/chromevox/background/desktop_automation_interface.js'; import {GestureInterface} from '/chromevox/background/gesture_interface.js'; import {ChromeVoxPrefs} from '/chromevox/background/prefs.js'; import {SmartStickyMode} from '/chromevox/background/smart_sticky_mode.js'; import {AbstractTts} from '/chromevox/common/abstract_tts.js'; import {CommandStore} from '/chromevox/common/command_store.js'; +import {CustomAutomationEvent} from '/chromevox/common/custom_automation_event.js'; import {TypingEcho} from '/chromevox/common/editable_text_base.js'; import {GestureGranularity} from '/chromevox/common/gesture_command_data.js'; import {ChromeVoxKbHandler} from '/chromevox/common/keyboard_handler.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js index 9fdbf864..321b88f 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js
@@ -6,9 +6,9 @@ * @fileoverview Handles automation from a desktop automation node. */ import {AutoScrollHandler} from '/chromevox/background/auto_scroll_handler.js'; -import {ChromeVoxEvent, CustomAutomationEvent} from '/chromevox/background/custom_automation_event.js'; import {DesktopAutomationInterface} from '/chromevox/background/desktop_automation_interface.js'; import {TextEditHandler} from '/chromevox/background/editing/editing.js'; +import {ChromeVoxEvent, CustomAutomationEvent} from '/chromevox/common/custom_automation_event.js'; const ActionType = chrome.automation.ActionType; const AutomationNode = chrome.automation.AutomationNode;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler_test.js index 90c7607f..d2f235a 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler_test.js
@@ -16,7 +16,7 @@ await importModule( 'CustomAutomationEvent', - '/chromevox/background/custom_automation_event.js'); + '/chromevox/common/custom_automation_event.js'); await importModule( 'DesktopAutomationHandler', '/chromevox/background/desktop_automation_handler.js');
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js index 4b713b1f..ebda5dc 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing.js
@@ -8,10 +8,10 @@ */ import {BrailleBackground} from '/chromevox/background/braille/braille_background.js'; import {Color} from '/chromevox/background/color.js'; -import {ChromeVoxEvent} from '/chromevox/background/custom_automation_event.js'; import {EditableLine} from '/chromevox/background/editing/editable_line.js'; import {IntentHandler} from '/chromevox/background/editing/intent_handler.js'; import {AbstractTts} from '/chromevox/common/abstract_tts.js'; +import {ChromeVoxEvent} from '/chromevox/common/custom_automation_event.js'; import {ChromeVoxEditableTextBase, TextChangeEvent} from '/chromevox/common/editable_text_base.js'; const AutomationEvent = chrome.automation.AutomationEvent;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/event_source.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/event_source.js index 68ffe30..aa4a5ca 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/event_source.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/event_source.js
@@ -40,3 +40,7 @@ chrome.accessibilityPrivate.IS_DEFAULT_EVENT_SOURCE_TOUCH ? EventSourceType.TOUCH_GESTURE : EventSourceType.NONE; + +BridgeHelper.registerHandler( + BridgeTarget.EVENT_SOURCE_STATE, BridgeAction.GET, + () => EventSourceState.get());
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/focus_automation_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/focus_automation_handler.js index 02ffabe..184c5d96 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/focus_automation_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/focus_automation_handler.js
@@ -6,7 +6,7 @@ * @fileoverview Handles automation events on the currently focused node. */ import {BaseAutomationHandler} from '/chromevox/background/base_automation_handler.js'; -import {ChromeVoxEvent} from '/chromevox/background/custom_automation_event.js'; +import {ChromeVoxEvent} from '/chromevox/common/custom_automation_event.js'; const AutomationEvent = chrome.automation.AutomationEvent; const AutomationNode = chrome.automation.AutomationNode;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/page_load_sound_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/page_load_sound_handler.js index 7c583eee..ddca216 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/page_load_sound_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/page_load_sound_handler.js
@@ -6,7 +6,7 @@ * @fileoverview Handles page loading sounds based on automation events. */ import {BaseAutomationHandler} from '/chromevox/background/base_automation_handler.js'; -import {ChromeVoxEvent} from '/chromevox/background/custom_automation_event.js'; +import {ChromeVoxEvent} from '/chromevox/common/custom_automation_event.js'; const ActionType = chrome.automation.ActionType; const AutomationNode = chrome.automation.AutomationNode;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel/panel_background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel/panel_background.js new file mode 100644 index 0000000..d6d37547 --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel/panel_background.js
@@ -0,0 +1,82 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Handles logic for the ChromeVox panel that requires state from + * the background context. + */ +import {ISearch} from './i_search.js'; +import {ISearchHandler} from './i_search_handler.js'; + +export class PanelBackground { + constructor() { + /** @private {ISearch} */ + this.iSearch_; + /** @private {ISearchHandler} */ + this.iSearchHandler_; + } + + static init() { + if (window.panelBackground) { + throw 'Trying to create two copies of singleton PanelBackground'; + } + window.panelBackground = new PanelBackground(); + } + + /** + * Creates a new ISearch object, ready to search starting from the current + * ChromeVox focus. + */ + createNewISearch() { + if (this.iSearch_) { + this.iSearch_.clear(); + } + this.iSearch_ = new ISearch(ChromeVoxState.instance.currentRange.start); + } + + /** Destroy the ISearch object so it can be garbage collected. */ + destroyISearch() { + this.iSearch_.handler = null; + this.iSearch_ = null; + } + + /** @param {!ISearchHandler} handler */ + setISearchHandler(handler) { + this.iSearchHandler_ = handler; + this.iSearch_.handler = handler; + } + + /** + * @param {string} searchStr + * @param {constants.Dir} dir + * @param {boolean=} opt_nextObject + */ + incrementalSearch(searchStr, dir, opt_nextObject) { + if (!this.iSearch_) { + console.error( + 'Trying to incrementally search when no ISearch has been created'); + return; + } + + this.iSearch_.search(searchStr, dir, opt_nextObject); + } + + /** Sets the current ChromeVox focus to the current ISearch node. */ + setRangeToISearchNode() { + if (!this.iSearch_) { + console.error( + 'Setting range to ISearch node when no ISearch in progress'); + return; + } + + const node = this.iSearch_.cursor.node; + if (!node) { + return; + } + ChromeVoxState.instance.navigateToRange(cursors.Range.fromNode(node)); + } +} + +/** @type {PanelBackground} */ +window.panelBackground;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/pointer_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/pointer_handler.js index 3771bc3..07c7326 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/pointer_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/pointer_handler.js
@@ -7,8 +7,8 @@ * either user touch or mouse input. */ import {BaseAutomationHandler} from '/chromevox/background/base_automation_handler.js'; -import {CustomAutomationEvent} from '/chromevox/background/custom_automation_event.js'; import {DesktopAutomationInterface} from '/chromevox/background/desktop_automation_interface.js'; +import {CustomAutomationEvent} from '/chromevox/common/custom_automation_event.js'; import {EventGenerator} from '/common/event_generator.js'; const AutomationEvent = chrome.automation.AutomationEvent;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js index 36a6d14..fe8b7eab 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js
@@ -72,7 +72,7 @@ /** * Set the value of a pref. * @param {string} key The pref key. - * @param {Object|string|boolean} value The new value of the pref. + * @param {Object|string|number|boolean} value The new value of the pref. */ setPref(key, value) { if (localStorage[key] !== value) {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/range_automation_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/range_automation_handler.js index 7a11d6b..a2ffe706 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/range_automation_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/range_automation_handler.js
@@ -6,8 +6,8 @@ * @fileoverview Handles automation from ChromeVox's current range. */ import {BaseAutomationHandler} from '/chromevox/background/base_automation_handler.js'; -import {ChromeVoxEvent, CustomAutomationEvent} from '/chromevox/background/custom_automation_event.js'; import {DesktopAutomationHandler} from '/chromevox/background/desktop_automation_handler.js'; +import {ChromeVoxEvent, CustomAutomationEvent} from '/chromevox/common/custom_automation_event.js'; const AutomationEvent = chrome.automation.AutomationEvent; const AutomationNode = chrome.automation.AutomationNode;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/braille/pan_strategy.js b/chrome/browser/resources/chromeos/accessibility/chromevox/braille/pan_strategy.js deleted file mode 100644 index e26fad3..0000000 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/braille/pan_strategy.js +++ /dev/null
@@ -1,412 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Logic for panning a braille display within a line of braille - * content that might not fit on a single display. - */ -import {CURSOR_DOTS} from '/chromevox/braille/cursor_dots.js'; - -export class PanStrategy { - constructor() { - /** - * @type {{rows: number, columns: number}} - * @private - */ - this.displaySize_ = {rows: 1, columns: 40}; - - /** - * Start and end are both inclusive. - * @type {!PanStrategy.Range} - * @private - */ - this.viewPort_ = {firstRow: 0, lastRow: 0}; - - /** - * The ArrayBuffer holding the braille cells after it's been processed to - * wrap words that are cut off by the column boundaries. - * @type {!ArrayBuffer} - * @private - */ - this.wrappedBuffer_ = new ArrayBuffer(0); - - /** - * The original text that corresponds with the braille buffers. There is - * only one textBuffer that correlates with both fixed and wrapped buffers. - * @type {string} - * @private - */ - this.textBuffer_ = ''; - - /** - * The ArrayBuffer holding the original braille cells, without being - * processed to wrap words. - * @type {!ArrayBuffer} - * @private - */ - this.fixedBuffer_ = new ArrayBuffer(0); - - /** - * The updated mapping from braille cells to text characters for the wrapped - * buffer. - * @type {Array<number>} - * @private - */ - this.wrappedBrailleToText_ = []; - - /** - * The original mapping from braille cells to text characters. - * @type {Array<number>} - * @private - */ - this.fixedBrailleToText_ = []; - - /** - * Indicates whether the pan strategy is wrapped or fixed. It is wrapped - * when true. - * @type {boolean} - * @private - */ - this.panStrategyWrapped_ = false; - - /** @type {{start: (number), end: (number)}} */ - this.cursor_ = {start: -1, end: -1}; - - /** @type {{start: (number), end: (number)}} */ - this.wrappedCursor_ = {start: -1, end: -1}; - } - - /** - * Gets the current viewport which is never larger than the current - * display size and whose end points are always within the limits of - * the current content. - * @type {!PanStrategy.Range} - */ - get viewPort() { - return this.viewPort_; - } - - /** - * Gets the current displaySize. - * @type {{rows: number, columns: number}} - */ - get displaySize() { - return this.displaySize_; - } - - /** - * @return {{brailleOffset: number, textOffset: number}} The offset of - * braille and text indices of the current slice. - */ - get offsetsForSlices() { - return { - brailleOffset: this.viewPort_.firstRow * this.displaySize_.columns, - textOffset: this.brailleToText - [this.viewPort_.firstRow * this.displaySize_.columns] - }; - } - - /** - * @return {number} The number of lines in the fixedBuffer. - */ - get fixedLineCount() { - return Math.ceil(this.fixedBuffer_.byteLength / this.displaySize_.columns); - } - - /** - * @return {number} The number of lines in the wrappedBuffer. - */ - get wrappedLineCount() { - return Math.ceil( - this.wrappedBuffer_.byteLength / this.displaySize_.columns); - } - - /** - * @return {Array<number>} The map of Braille cells to the first index of the - * corresponding text character. - */ - get brailleToText() { - if (this.panStrategyWrapped_) { - return this.wrappedBrailleToText_; - } else { - return this.fixedBrailleToText_; - } - } - - /** - * @param {boolean=} opt_showCursor Defaults to true. - * @return {ArrayBuffer} Buffer of the slice of braille cells within the - * bounds of the viewport. - */ - getCurrentBrailleViewportContents(opt_showCursor) { - opt_showCursor = opt_showCursor === undefined ? true : opt_showCursor; - const buf = - this.panStrategyWrapped_ ? this.wrappedBuffer_ : this.fixedBuffer_; - - let startIndex, endIndex; - if (this.panStrategyWrapped_) { - startIndex = this.wrappedCursor_.start; - endIndex = this.wrappedCursor_.end; - } else { - startIndex = this.cursor_.start; - endIndex = this.cursor_.end; - } - - if (startIndex >= 0 && startIndex < buf.byteLength && - endIndex >= startIndex && endIndex <= buf.byteLength) { - const dataView = new DataView(buf); - while (startIndex < endIndex) { - let value = dataView.getUint8(startIndex); - if (opt_showCursor) { - value |= CURSOR_DOTS; - } else { - value &= ~CURSOR_DOTS; - } - dataView.setUint8(startIndex, value); - startIndex++; - } - } - - return buf.slice( - this.viewPort_.firstRow * this.displaySize_.columns, - (this.viewPort_.lastRow + 1) * this.displaySize_.columns); - } - - /** - * @return {string} String of the slice of text letters corresponding with - * the current braille slice. - */ - getCurrentTextViewportContents() { - const brailleToText = this.brailleToText; - // Index of last braille character in slice. - let index = (this.viewPort_.lastRow + 1) * this.displaySize_.columns - 1; - // Index of first text character that the last braille character points - // to. - const end = brailleToText[index]; - // Increment index until brailleToText[index] points to a different char. - // This is the cutoff point, as substring cuts up to, but not including, - // brailleToText[index]. - while (index < brailleToText.length && brailleToText[index] === end) { - index++; - } - return this.textBuffer_.substring( - brailleToText[this.viewPort_.firstRow * this.displaySize_.columns], - brailleToText[index]); - } - - /** - * Sets the current pan strategy and resets the viewport. - */ - setPanStrategy(wordWrap) { - this.panStrategyWrapped_ = wordWrap; - this.panToPosition_(0); - } - - /** - * Sets the display size. This call may update the viewport. - * @param {number} rowCount the new row size, or {@code 0} if no display is - * present. - * @param {number} columnCount the new column size, or {@code 0} - * if no display is present. - */ - setDisplaySize(rowCount, columnCount) { - this.displaySize_ = {rows: rowCount, columns: columnCount}; - this.setContent( - this.textBuffer_, this.fixedBuffer_, this.fixedBrailleToText_, 0); - } - - /** - * Sets the internal data structures that hold the fixed and wrapped buffers - * and maps. - * @param {string} textBuffer Text of the shown braille. - * @param {!ArrayBuffer} translatedContent The new braille content. - * @param {Array<number>} fixedBrailleToText Map of Braille cells to the - * first index of corresponding text letter. - * @param {number} targetPosition Target position. The viewport is changed - * to overlap this position. - */ - setContent( - textBuffer, translatedContent, fixedBrailleToText, targetPosition) { - this.viewPort_.firstRow = 0; - this.viewPort_.lastRow = this.displaySize_.rows - 1; - this.fixedBrailleToText_ = fixedBrailleToText; - this.wrappedBrailleToText_ = []; - this.textBuffer_ = textBuffer; - this.fixedBuffer_ = translatedContent; - - // Convert the cells to Unicode braille pattern characters. - const view = new Uint8Array(translatedContent); - const wrappedBrailleArray = []; - - let lastBreak = 0; - let cellsPadded = 0; - let index; - for (index = 0; index < translatedContent.byteLength + cellsPadded; - index++) { - // Is index at the beginning of a new line? - if (index !== 0 && index % this.displaySize_.columns === 0) { - if (view[index - cellsPadded] === 0) { - // Delete all empty cells at the beginning of this line. - while (index - cellsPadded < view.length && - view[index - cellsPadded] === 0) { - cellsPadded--; - } - index--; - lastBreak = index; - } else if ( - view[index - cellsPadded - 1] !== 0 && - lastBreak % this.displaySize_.columns !== 0) { - // If first cell is not empty, we need to move the whole word down - // to this line and padd to previous line with 0's, from |lastBreak| - // to index. The braille to text map is also updated. If lastBreak - // is at the beginning of a line, that means the current word is - // bigger than |this.displaySize_.columns| so we shouldn't wrap. - for (let j = lastBreak + 1; j < index; j++) { - wrappedBrailleArray[j] = 0; - this.wrappedBrailleToText_[j] = this.wrappedBrailleToText_[j - 1]; - cellsPadded++; - } - lastBreak = index; - index--; - } else { - // |lastBreak| is at the beginning of a line, so current word is - // bigger than |this.displaySize_.columns| so we shouldn't wrap. - this.maybeSetWrappedCursor_( - index - cellsPadded, wrappedBrailleArray.length); - wrappedBrailleArray.push(view[index - cellsPadded]); - this.wrappedBrailleToText_.push( - fixedBrailleToText[index - cellsPadded]); - } - } else { - if (view[index - cellsPadded] === 0) { - lastBreak = index; - } - this.maybeSetWrappedCursor_( - index - cellsPadded, wrappedBrailleArray.length); - wrappedBrailleArray.push(view[index - cellsPadded]); - this.wrappedBrailleToText_.push( - fixedBrailleToText[index - cellsPadded]); - } - } - - // It's possible the end of the wrapped cursor falls at the - // |translatedContent.byteLength| exactly. - this.maybeSetWrappedCursor_( - index - cellsPadded, wrappedBrailleArray.length); - - // Convert the wrapped Braille Uint8 Array back to ArrayBuffer. - const wrappedBrailleUint8Array = new Uint8Array(wrappedBrailleArray); - this.wrappedBuffer_ = new ArrayBuffer(wrappedBrailleUint8Array.length); - new Uint8Array(this.wrappedBuffer_).set(wrappedBrailleUint8Array); - this.panToPosition_(targetPosition); - } - - /** - * Sets a braille cursor. - * @param {number} startIndex - * @param {number} endIndex - */ - setCursor(startIndex, endIndex) { - this.cursor_ = {start: startIndex, end: endIndex}; - } - - /** - * Gets the current cursor. - * @return {{start: (number), end: (number)}} - */ - getCursor() { - return this.cursor_; - } - - /** - * Refreshes the wrapped cursor given a mapping from an unwrapped index to a - * wrapped index. - * @param {number} unwrappedIndex - * @param {number} wrappedIndex - */ - maybeSetWrappedCursor_(unwrappedIndex, wrappedIndex) { - // We only care about the bounds of the index start/end. - if (this.cursor_.start !== unwrappedIndex && - this.cursor_.end !== unwrappedIndex) { - return; - } - if (this.cursor_.start === unwrappedIndex) { - this.wrappedCursor_.start = wrappedIndex; - } else if (this.cursor_.end === unwrappedIndex) { - this.wrappedCursor_.end = wrappedIndex; - } - } - - /** - * If possible, changes the viewport to a part of the line that follows - * the current viewport. - * @return {boolean} {@code true} if the viewport was changed. - */ - next() { - const contentLength = - this.panStrategyWrapped_ ? this.wrappedLineCount : this.fixedLineCount; - const newStart = this.viewPort_.lastRow + 1; - let newEnd; - if (newStart + this.displaySize_.rows - 1 < contentLength) { - newEnd = newStart + this.displaySize_.rows - 1; - } else { - newEnd = contentLength - 1; - } - if (newEnd >= newStart) { - this.viewPort_ = {firstRow: newStart, lastRow: newEnd}; - return true; - } - return false; - } - - /** - * If possible, changes the viewport to a part of the line that precedes - * the current viewport. - * @return {boolean} {@code true} if the viewport was changed. - */ - previous() { - const contentLength = - this.panStrategyWrapped_ ? this.wrappedLineCount : this.fixedLineCount; - if (this.viewPort_.firstRow > 0) { - let newStart, newEnd; - if (this.viewPort_.firstRow < this.displaySize_.rows) { - newStart = 0; - newEnd = Math.min(this.displaySize_.rows, contentLength); - } else { - newEnd = this.viewPort_.firstRow - 1; - newStart = newEnd - this.displaySize_.rows + 1; - } - if (newStart <= newEnd) { - this.viewPort_ = {firstRow: newStart, lastRow: newEnd}; - return true; - } - } - return false; - } - - /** - * Moves the viewport so that it overlaps a target position without taking - * the current viewport position into consideration. - * @param {number} position Target position. - */ - panToPosition_(position) { - if (this.displaySize_.rows * this.displaySize_.columns > 0) { - this.viewPort_ = {firstRow: -1, lastRow: -1}; - while (this.next() && - (this.viewPort_.lastRow + 1) * this.displaySize_.columns <= - position) { - // Nothing to do. - } - } else { - this.viewPort_ = {firstRow: position, lastRow: position}; - } - } -} - -/** - * A range used to represent the viewport with inclusive start and xclusive - * end position. - * @typedef {{firstRow: number, lastRow: number}} - */ -PanStrategy.Range;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js index e3d05bbf..ecf3ed1a 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js
@@ -32,6 +32,16 @@ }, }; +BackgroundBridge.ChromeVoxBackground = { + /** + * Gets the voice currently used by ChromeVox when calling tts. + * @return {!Promise<string>} + */ + async getCurrentVoice() { + return BridgeHelper.sendMessage('ChromeVoxBackground', 'getCurrentVoice'); + }, +}; + BackgroundBridge.ChromeVoxPrefs = { /** * Get the prefs (not including keys). @@ -91,6 +101,17 @@ }, }; +BackgroundBridge.EventSourceState = { + /** + * Gets the current event source. + * @return {!Promise<EventSourceType>} + */ + async get() { + return BridgeHelper.sendMessage( + BridgeTarget.EVENT_SOURCE_STATE, BridgeAction.GET); + } +}; + BackgroundBridge.LogStore = { /** Clear the log buffer. */ async clearLog() {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille_command_data.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_command_data.js similarity index 100% rename from chrome/browser/resources/chromeos/accessibility/chromevox/common/braille_command_data.js rename to chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_command_data.js
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille_command_data_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_command_data_test.js similarity index 80% rename from chrome/browser/resources/chromeos/accessibility/chromevox/common/braille_command_data_test.js rename to chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_command_data_test.js index 84c34b3..3aa3dd8 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille_command_data_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_command_data_test.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. // Include test fixture. -GEN_INCLUDE(['../testing/chromevox_next_e2e_test_base.js']); +GEN_INCLUDE(['../../testing/chromevox_next_e2e_test_base.js']); /** * Test fixture for braille_command_data.js. @@ -13,7 +13,8 @@ async setUpDeferred() { await super.setUpDeferred(); await importModule( - 'BrailleCommandData', '/chromevox/common/braille_command_data.js'); + 'BrailleCommandData', + '/chromevox/common/braille/braille_command_data.js'); } };
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille_interface.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_interface.js similarity index 98% rename from chrome/browser/resources/chromeos/accessibility/chromevox/common/braille_interface.js rename to chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_interface.js index 31badde..fad99a5 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille_interface.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_interface.js
@@ -17,8 +17,6 @@ /** @interface */ BrailleInterface = class { - constructor() {} - /** * Sends the given params to the Braille display for output. * @param {!NavBraille} params Parameters to send to the
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_table.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_table.js similarity index 100% rename from chrome/browser/resources/chromeos/accessibility/chromevox/background/braille/braille_table.js rename to chrome/browser/resources/chromeos/accessibility/chromevox/common/braille/braille_table.js
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/bridge_constants.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/bridge_constants.js index 95cac2bf..609b728 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/bridge_constants.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/bridge_constants.js
@@ -17,6 +17,7 @@ CHROMEVOX_PREFS: 'ChromeVoxPrefs', CHROMEVOX_STATE: 'ChromeVoxState', COMMAND_HANDLER: 'CommandHandler', + EVENT_SOURCE_STATE: 'EventSourceState', LOG_STORE: 'LogStore', }; @@ -27,6 +28,7 @@ BridgeAction = { BACK_TRANSLATE: 'backTranslate', CLEAR_LOG: 'clearLog', + GET: 'get', GET_LOGS: 'getLogs', GET_PREFS: 'getPrefs', ON_COMMAND: 'onCommand',
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/custom_automation_event.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/custom_automation_event.js similarity index 100% rename from chrome/browser/resources/chromeos/accessibility/chromevox/background/custom_automation_event.js rename to chrome/browser/resources/chromeos/accessibility/chromevox/common/custom_automation_event.js
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/editable_text_base.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/editable_text_base.js index 050d342b..bf6efe4 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/editable_text_base.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/editable_text_base.js
@@ -13,8 +13,8 @@ * extended to override methods that extract lines for multiline fields * or to provide other customizations. */ -import {ChromeVoxEvent} from '/chromevox/background/custom_automation_event.js'; import {AbstractTts} from '/chromevox/common/abstract_tts.js'; +import {ChromeVoxEvent} from '/chromevox/common/custom_automation_event.js'; /** * A class containing the information needed to speak
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/learn_mode.js b/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/learn_mode.js index 9e98660..fa45c1b 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/learn_mode.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/learn_mode.js
@@ -6,7 +6,7 @@ * @fileoverview Script for ChromeOS keyboard explorer. * */ -import {BrailleCommandData} from '/chromevox/common/braille_command_data.js'; +import {BrailleCommandData} from '/chromevox/common/braille/braille_command_data.js'; import {CommandStore} from '/chromevox/common/command_store.js'; import {GestureCommandData} from '/chromevox/common/gesture_command_data.js'; import {KeyMap} from '/chromevox/common/key_map.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/options/options.js b/chrome/browser/resources/chromeos/accessibility/chromevox/options/options.js index 591f66a..a5fa44b 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/options/options.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/options/options.js
@@ -5,8 +5,8 @@ /** * @fileoverview ChromeVox options page. */ -import {BrailleTable} from '/chromevox/background/braille/braille_table.js'; import {AbstractTts} from '/chromevox/common/abstract_tts.js'; +import {BrailleTable} from '/chromevox/common/braille/braille_table.js'; import {BluetoothBrailleDisplayUI} from '/chromevox/options/bluetooth_braille_display_ui.js'; /** @const {string} */ @@ -242,12 +242,12 @@ /** * Populates the voices select with options. */ - static populateVoicesSelect() { + static async populateVoicesSelect() { const select = $('voices'); - function setVoiceList() { + async function setVoiceList() { const selectedVoice = - chrome.extension.getBackgroundPage()['getCurrentVoice'](); + await BackgroundBridge.ChromeVoxBackground.getCurrentVoice(); const addVoiceOption = (visibleVoiceName, voiceName) => { const option = document.createElement('option'); option.voiceName = voiceName; @@ -292,7 +292,7 @@ } window.speechSynthesis.onvoiceschanged = setVoiceList; - setVoiceList(); + await setVoiceList(); select.addEventListener('change', function(evt) { const selIndex = select.selectedIndex;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/i_search_ui.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/i_search_ui.js index b95ceaf..88f46a2f 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/i_search_ui.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/i_search_ui.js
@@ -5,8 +5,8 @@ /** * @fileoverview The driver for the UI for incremental search. */ -import {ISearch} from '/chromevox/background/panel/i_search.js'; import {ISearchHandler} from '/chromevox/background/panel/i_search_handler.js'; +import {PanelBackground} from '/chromevox/background/panel/panel_background.js'; import {PanelInterface} from '/chromevox/panel/panel_interface.js'; const AutomationNode = chrome.automation.AutomationNode; @@ -19,10 +19,12 @@ /** @private {ChromeVoxState} */ this.background_ = chrome.extension.getBackgroundPage()['ChromeVoxState']['instance']; - this.iSearch_ = new ISearch(this.background_.currentRange.start); + const panelBackground = + chrome.extension.getBackgroundPage().panelBackground; + panelBackground.createNewISearch(); + panelBackground.setISearchHandler(this); this.input_ = input; this.dir_ = Dir.FORWARD; - this.iSearch_.handler = this; this.onKeyDown = this.onKeyDown.bind(this); this.onTextInput = this.onTextInput.bind(this); @@ -67,21 +69,16 @@ PanelInterface.instance.closeMenusAndRestoreFocus(); return false; case 'Enter': - PanelInterface.instance.setPendingCallback(function() { - const node = this.iSearch_.cursor.node; - if (!node) { - return; - } - chrome.extension.getBackgroundPage() - .ChromeVoxState.instance['navigateToRange']( - cursors.Range.fromNode(node)); - }.bind(this)); + PanelInterface.instance.setPendingCallback( + () => chrome.extension.getBackgroundPage() + .panelBackground.setRangeToISearchNode()); PanelInterface.instance.closeMenusAndRestoreFocus(); return false; default: return false; } - this.iSearch_.search(this.input_.value, this.dir_, true); + chrome.extension.getBackgroundPage().panelBackground.incrementalSearch( + this.input_.value, this.dir_, true); evt.preventDefault(); evt.stopPropagation(); return false; @@ -94,8 +91,8 @@ */ onTextInput(evt) { const searchStr = evt.target.value + evt.data; - this.iSearch_.clear(); - this.iSearch_.search(searchStr, this.dir_); + chrome.extension.getBackgroundPage().panelBackground.incrementalSearch( + searchStr, this.dir_); return true; } @@ -137,8 +134,7 @@ /** Unregisters event handlers. */ destroy() { - this.iSearch_.handler = null; - this.iSearch_ = null; + chrome.extension.getBackgroundPage().panelBackground.destroyISearch(); const input = this.input_; this.input_ = null; input.removeEventListener('keydown', this.onKeyDown, true);
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js index 78bce4c2..0ae20b7 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js
@@ -5,7 +5,7 @@ /** * @fileoverview The ChromeVox panel and menus. */ -import {BrailleCommandData} from '/chromevox/common/braille_command_data.js'; +import {BrailleCommandData} from '/chromevox/common/braille/braille_command_data.js'; import {CommandStore} from '/chromevox/common/command_store.js'; import {GestureCommandData} from '/chromevox/common/gesture_command_data.js'; import {KeyMap} from '/chromevox/common/key_map.js'; @@ -305,9 +305,9 @@ const bkgnd = chrome.extension.getBackgroundPage(); const range = bkgnd.ChromeVoxState.instance.getCurrentRange(); const node = range ? range.start.node : null; + const eventSourceState = await BackgroundBridge.EventSourceState.get(); const touchScreen = - (bkgnd['EventSourceState']['get']() === - EventSourceType.TOUCH_GESTURE || + (eventSourceState === EventSourceType.TOUCH_GESTURE || this.mockTouchGestureSourceForTesting_); // Build the top-level menus.
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_menu_item.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_menu_item.js index 8a33fa33..6dba144 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_menu_item.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_menu_item.js
@@ -18,16 +18,30 @@ constructor( menuItemTitle, menuItemShortcut, menuItemBraille, gesture, callback, opt_id) { - // Save inputs. + /** @type {string} */ this.menuItemTitle = menuItemTitle; + /** @type {string} */ this.menuItemShortcut = menuItemShortcut; + /** @type {string} */ this.menuItemBraille = menuItemBraille; + /** @type {string} */ this.gesture = gesture; + /** @type {Function} */ this.callback = callback; + /** @type {Element} */ + this.element; /** @type {boolean} */ this.enabled_ = true; + this.init_(opt_id); + } + + /** + * @param {string=} opt_id + * @private + */ + async init_(opt_id) { this.element = document.createElement('tr'); this.element.className = 'menu-item'; this.element.tabIndex = -1; @@ -37,42 +51,37 @@ } this.element.addEventListener( - 'mouseover', (function(evt) { - this.element.focus(); - }).bind(this), - false); + 'mouseover', () => this.element.focus(), false); const title = document.createElement('td'); title.className = 'menu-item-title'; - title.textContent = menuItemTitle; + title.textContent = this.menuItemTitle; // Tooltip in case the menu item is cut off. - title.title = menuItemTitle; + title.title = this.menuItemTitle; this.element.appendChild(title); - const backgroundWindow = chrome.extension.getBackgroundPage(); - if (backgroundWindow['EventSourceState']['get']() === - EventSourceType.TOUCH_GESTURE) { + const eventSourceState = await BackgroundBridge.EventSourceState.get(); + if (eventSourceState === EventSourceType.TOUCH_GESTURE) { const gestureNode = document.createElement('td'); gestureNode.className = 'menu-item-shortcut'; - gestureNode.textContent = gesture; + gestureNode.textContent = this.gesture; this.element.appendChild(gestureNode); return; } const shortcut = document.createElement('td'); shortcut.className = 'menu-item-shortcut'; - shortcut.textContent = menuItemShortcut; + shortcut.textContent = this.menuItemShortcut; this.element.appendChild(shortcut); if (localStorage['brailleCaptions'] === String(true) || localStorage['menuBrailleCommands'] === String(true)) { const braille = document.createElement('td'); braille.className = 'menu-item-shortcut'; - braille.textContent = menuItemBraille; + braille.textContent = this.menuItemBraille; this.element.appendChild(braille); } - } /**
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/testing/mock_feedback_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/testing/mock_feedback_test.js index c4d251d..116c69c 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/testing/mock_feedback_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/testing/mock_feedback_test.js
@@ -40,7 +40,7 @@ '../background/braille/nav_braille.js', '../background/chromevox.js', '../common/abstract_earcons.js', - '../common/braille_interface.js', + '../common/braille/braille_interface.js', '../common/spannable.js', '../common/tts_interface.js', 'mock_feedback.js',
diff --git a/chrome/browser/resources/chromeos/login/BUILD.gn b/chrome/browser/resources/chromeos/login/BUILD.gn index 19f58b1d..24296f2 100644 --- a/chrome/browser/resources/chromeos/login/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/BUILD.gn
@@ -145,6 +145,7 @@ in_files = [ "cr_ui.html", "display_manager.html", + "i18n_setup.html", "i18n_setup.js", "keyboard_utils.html", "login_ui_tools.html", @@ -153,7 +154,6 @@ "oobe_popup_overlay.css", "oobe_screen.css", "screens.js", - "components/behaviors/i18n_setup.html", "components/behaviors/login_screen_behavior.html", "components/behaviors/login_screen_behavior.js", "components/behaviors/multi_step_behavior.html", @@ -543,7 +543,6 @@ ":demo_mode_test_helper.m", ":display_manager.m", "//ui/webui/resources/js:cr.m", - "//ui/webui/resources/js:i18n_template_no_process.m", "//ui/webui/resources/js:load_time_data.m", ] extra_deps = [ ":modulize" ]
diff --git a/chrome/browser/resources/chromeos/login/components/BUILD.gn b/chrome/browser/resources/chromeos/login/components/BUILD.gn index 678b19f9..5025b9e 100644 --- a/chrome/browser/resources/chromeos/login/components/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/components/BUILD.gn
@@ -109,6 +109,7 @@ "./buttons:oobe_text_button.m", "./dialogs:oobe_content_dialog.m", "//ui/webui/resources/js:cr.m", + "//ui/webui/resources/js:load_time_data.m", ] extra_deps = [ ":gaia_dialog_module" ] }
diff --git a/chrome/browser/resources/chromeos/login/components/gaia_dialog.html b/chrome/browser/resources/chromeos/login/components/gaia_dialog.html index 3816b89..5bb19a6 100644 --- a/chrome/browser/resources/chromeos/login/components/gaia_dialog.html +++ b/chrome/browser/resources/chromeos/login/components/gaia_dialog.html
@@ -4,6 +4,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/html/cr.html"> +<link rel="import" href="chrome://resources/html/load_time_data.html"> <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
diff --git a/chrome/browser/resources/chromeos/login/cr_ui.js b/chrome/browser/resources/chromeos/login/cr_ui.js index 99d7e58..1a3f310 100644 --- a/chrome/browser/resources/chromeos/login/cr_ui.js +++ b/chrome/browser/resources/chromeos/login/cr_ui.js
@@ -9,7 +9,6 @@ */ // #import {assert} from 'chrome://resources/js/assert.m.js'; -// #import {i18nTemplate} from 'chrome://resources/js/i18n_template_no_process.m.js'; // #import {$} from 'chrome://resources/js/util.m.js'; // #import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js'; @@ -307,13 +306,36 @@ static reloadContent(data) { // Reload global local strings, process DOM tree again. loadTimeData.overrideValues(data); - i18nTemplate.process(document, loadTimeData); + Oobe.updateDocumentLocalizedStrings(); // Update localized content of the screens. Oobe.getInstance().updateLocalizedContent_(); } /** + * Update localized strings in tags that are used at the `document` level. + * These strings are used outside of a Polymer Element and cannot leverage + * I18nBehavior for it. + */ + static updateDocumentLocalizedStrings() { + // Update attributes used in the <html> tag. + const attrToStrMap = { + lang: 'language', + dir: 'textdirection', + highlight: 'highlightStrength', + }; + for (const [attribute, stringName] of Object.entries(attrToStrMap)) { + const localizedString = loadTimeData.getValue(stringName); + document.documentElement.setAttribute(attribute, localizedString); + } + + // Update this standalone div in the main document. + const notice = loadTimeData.getValue('missingAPIKeysNotice'); + const apiKeysNoticeDiv = $('api-keys-notice'); + apiKeysNoticeDiv.textContent = notice; + } + + /** * Updates "device in tablet mode" state when tablet mode is changed. * @param {Boolean} isInTabletMode True when in tablet mode. */
diff --git a/chrome/browser/resources/chromeos/login/components/behaviors/i18n_setup.html b/chrome/browser/resources/chromeos/login/i18n_setup.html similarity index 100% rename from chrome/browser/resources/chromeos/login/components/behaviors/i18n_setup.html rename to chrome/browser/resources/chromeos/login/i18n_setup.html
diff --git a/chrome/browser/resources/chromeos/login/md_login.html b/chrome/browser/resources/chromeos/login/md_login.html index 3ca7d91..bec5cab5 100644 --- a/chrome/browser/resources/chromeos/login/md_login.html +++ b/chrome/browser/resources/chromeos/login/md_login.html
@@ -1,12 +1,9 @@ <!doctype html> -<html i18n-values="dir:textdirection; - build:buildType; - highlight:highlightStrength; - lang:language"> +<html build="$i18n{buildType}"> <head> <meta charset="utf-8"> <meta name="google" value="notranslate"> -<title i18n-content="title"></title> +<title>$i18n{title}</title> <script src="chrome://resources/polymer/v1_0/html-imports/html-imports.min.js"></script> <!-- This must be the first import in all login pages. --> <link rel="import" href="chrome://resources/html/polymer.html"> @@ -54,13 +51,12 @@ <script src="chrome://oobe/keyboard_utils.js"></script> -<link rel="import" href="/components/behaviors/i18n_setup.html"> +<link rel="import" href="./i18n_setup.html"> <link rel="import" href="chrome://oobe/custom_elements.html"> <script src="chrome://oobe/components/test_util.js"></script> <script src="chrome://oobe/login.js"></script> </head> -<body i18n-values=".style.fontFamily:fontfamily;" class="chromeos"> +<body style="font-family:$i18n{fontfamily}" class="chromeos"> <include src="md_screen_container.html"> - <script src="chrome://resources/js/i18n_template_no_process.js"></script> </body> </html>
diff --git a/chrome/browser/resources/chromeos/login/md_screen_container.html b/chrome/browser/resources/chromeos/login/md_screen_container.html index b3d7f96..07c592b0 100644 --- a/chrome/browser/resources/chromeos/login/md_screen_container.html +++ b/chrome/browser/resources/chromeos/login/md_screen_container.html
@@ -1,5 +1,5 @@ <div id="api-keys-notice-container" hidden> - <div id="api-keys-notice" i18n-content="missingAPIKeysNotice"></div> + <div id="api-keys-notice"></div> </div> <div id="scroll-container"> <div id="outer-container" class="layout vertical">
diff --git a/chrome/browser/resources/chromeos/login/oobe.html b/chrome/browser/resources/chromeos/login/oobe.html index 090f67b..3252017 100644 --- a/chrome/browser/resources/chromeos/login/oobe.html +++ b/chrome/browser/resources/chromeos/login/oobe.html
@@ -1,12 +1,9 @@ <!doctype html> -<html i18n-values="dir:textdirection; - build:buildType; - highlight:highlightStrength; - lang:language"> +<html build="$i18n{buildType}"> <head> <meta charset="utf-8"> <meta name="google" value="notranslate"> -<title i18n-content="title"></title> +<title>$i18n{title}</title> <script src="chrome://resources/polymer/v1_0/html-imports/html-imports.min.js"></script> <!-- This must be the first import in all login pages. --> <link rel="import" href="chrome://resources/html/polymer.html"> @@ -58,13 +55,12 @@ <script src="chrome://oobe/keyboard_utils.js"></script> <script src="chrome://oobe/components/keyboard_utils_for_injection.js"></script> -<link rel="import" href="/components/behaviors/i18n_setup.html"> +<link rel="import" href="./i18n_setup.html"> <link rel="import" href="chrome://oobe/custom_elements.html"> <script src="chrome://oobe/components/test_util.js"></script> <script src="chrome://oobe/oobe.js"></script> </head> -<body class="oobe-display chromeos" i18n-values=".style.fontFamily:fontfamily;"> +<body class="oobe-display chromeos" style="font-family:$i18n{fontfamily}"> <include src="md_screen_container.html"> - <script src="chrome://resources/js/i18n_template_no_process.js"></script> </body> </html>
diff --git a/chrome/browser/resources/chromeos/login/oobe.js b/chrome/browser/resources/chromeos/login/oobe.js index 8ef7dea..56cdd46 100644 --- a/chrome/browser/resources/chromeos/login/oobe.js +++ b/chrome/browser/resources/chromeos/login/oobe.js
@@ -37,7 +37,8 @@ // <include src="components/web_view_loader.js"> HTMLImports.whenReady(() => { - i18nTemplate.process(document, loadTimeData); + // Update localized strings at the document level. + Oobe.updateDocumentLocalizedStrings(); // <include src="oobe_initialization.js"> });
diff --git a/chrome/browser/resources/chromeos/login/oobe_polymer3.html b/chrome/browser/resources/chromeos/login/oobe_polymer3.html index 9acd6cd..c6d28d6 100644 --- a/chrome/browser/resources/chromeos/login/oobe_polymer3.html +++ b/chrome/browser/resources/chromeos/login/oobe_polymer3.html
@@ -1,7 +1,5 @@ <!doctype html> -<html highlight="$i18n{highlightStrength}" build="$i18n{buildType}" - i18n-values="dir:textdirection; - lang:language"> +<html build="$i18n{buildType}"> <head> <meta charset="utf-8"> <meta name="google" value="notranslate"> @@ -19,7 +17,7 @@ <body class="oobe-display chromeos" style="font-family:$i18n{fontfamily}"> <div id="api-keys-notice-container" hidden> - <div id="api-keys-notice" i18n-content="missingAPIKeysNotice"></div> + <div id="api-keys-notice"></div> </div> <div id="scroll-container"> <div id="outer-container" class="layout vertical">
diff --git a/chrome/browser/resources/chromeos/login/oobe_polymer3.js b/chrome/browser/resources/chromeos/login/oobe_polymer3.js index 0cd080f..4408b713 100644 --- a/chrome/browser/resources/chromeos/login/oobe_polymer3.js +++ b/chrome/browser/resources/chromeos/login/oobe_polymer3.js
@@ -11,7 +11,6 @@ import {loadTimeData} from './i18n_setup.js'; import 'chrome://oobe/components/test_util.m.js'; import 'chrome://oobe/test_api/test_api.m.js'; -import {i18nTemplate} from 'chrome://resources/js/i18n_template_no_process.m.js'; import {commonScreensList, loginScreensList, oobeScreensList} from 'chrome://oobe/screens.js'; import {MultiTapDetector} from './multi_tap_detector.m.js'; // clang-format on @@ -113,7 +112,9 @@ } (function (root) { - i18nTemplate.process(document, loadTimeData); + // Update localized strings at the document level. + Oobe.updateDocumentLocalizedStrings(); + prepareGlobalValues(window); // Add screens to the document.
diff --git a/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn b/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn index 9a2a062..37bd279 100644 --- a/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn
@@ -296,6 +296,7 @@ "../../components/behaviors:oobe_i18n_behavior.m", "../../components/dialogs:oobe_adaptive_dialog.m", "//ui/webui/resources/js:cr.m", + "//ui/webui/resources/js:load_time_data.m", ] extra_deps = [ ":gaia_signin_module" ] }
diff --git a/chrome/browser/resources/chromeos/login/screens/common/gaia_signin.html b/chrome/browser/resources/chromeos/login/screens/common/gaia_signin.html index b4bbfa43..34ed9d8 100644 --- a/chrome/browser/resources/chromeos/login/screens/common/gaia_signin.html +++ b/chrome/browser/resources/chromeos/login/screens/common/gaia_signin.html
@@ -9,6 +9,7 @@ <link rel="import" href="chrome://resources/html/action_link.html"> <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> +<link rel="import" href="chrome://resources/html/load_time_data.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="../../../../gaia_auth_host/authenticator.html">
diff --git a/chrome/browser/resources/history/history_clusters/cluster.html b/chrome/browser/resources/history/history_clusters/cluster.html index b773a24..15d3261 100644 --- a/chrome/browser/resources/history/history_clusters/cluster.html +++ b/chrome/browser/resources/history/history_clusters/cluster.html
@@ -31,6 +31,7 @@ display: flex; flex-grow: 1; justify-content: space-between; + min-height: 40px; min-width: 0; padding-inline-start: var(--cluster-padding-horizontal); user-select: none; @@ -38,6 +39,7 @@ #label { color: var(--cr-secondary-text-color); + font-size: 1rem; /* 16px */ font-weight: 500; } @@ -99,9 +101,8 @@ <div id="label-row" hidden="[[!cluster.label]]"> <div id="label"></div> <div class="timestamp-and-menu"> - <div class="timestamp">[[cluster.visit.relativeDate]]</div> - <menu-container is-top-menu is-cluster-menu visit="[[cluster.visit]]"> - </menu-container> + <div class="timestamp">[[cluster.visits.0.relativeDate]]</div> + <menu-container is-top-menu is-cluster-menu></menu-container> </div> </div> <template is="dom-repeat" items="[[visibleVisits_]]">
diff --git a/chrome/browser/resources/media/BUILD.gn b/chrome/browser/resources/media/BUILD.gn index 6425819..c1660c2 100644 --- a/chrome/browser/resources/media/BUILD.gn +++ b/chrome/browser/resources/media/BUILD.gn
@@ -5,8 +5,42 @@ import("//chrome/common/features.gni") import("//third_party/closure_compiler/compile_js.gni") import("//tools/grit/grit_rule.gni") +import("//tools/grit/preprocess_if_expr.gni") +import("//tools/typescript/ts_library.gni") import("//ui/webui/resources/tools/generate_grd.gni") +preprocess_folder = "preprocessed" +copy("copy_mojo") { + deps = [ "//chrome/browser/media:mojo_bindings_js" ] + sources = [ "$root_gen_dir/mojom-webui/chrome/browser/media/history/media_history_store.mojom-webui.js" ] + outputs = [ "$target_gen_dir/$preprocess_folder/{{source_file_part}}" ] +} + +preprocess_if_expr("preprocess_src") { + in_folder = "." + in_files = [ + "media_history.ts", + "media_data_table.ts", + ] + out_folder = "$target_gen_dir/$preprocess_folder" +} + +ts_library("build_ts") { + root_dir = "$target_gen_dir/$preprocess_folder" + out_dir = target_gen_dir + tsconfig_base = "tsconfig_base.json" + in_files = [ + "media_history.ts", + "media_data_table.ts", + "media_history_store.mojom-webui.js", + ] + deps = [ "//ui/webui/resources:library" ] + extra_deps = [ + ":copy_mojo", + ":preprocess_src", + ] +} + generate_grd("build_grd") { grd_prefix = "webrtc_logs" out_grd = "$target_gen_dir/webrtc_logs_resources.grd" @@ -46,11 +80,7 @@ "$root_gen_dir/mojom-webui/services/media_session/public/mojom/", root_build_dir), ] - deps = [ - ":media_data_table", - ":media_engagement", - ":media_history", - ] + deps = [ ":media_engagement" ] } js_library("media_engagement") { @@ -61,16 +91,3 @@ "//ui/webui/resources/js:util.m", ] } - -js_library("media_history") { - deps = [ - ":media_data_table", - "//chrome/browser/media:mojo_bindings_webui_js", - "//ui/webui/resources/js:assert.m", - "//ui/webui/resources/js:promise_resolver.m", - "//ui/webui/resources/js:util.m", - ] -} - -js_library("media_data_table") { -}
diff --git a/chrome/browser/resources/media/media_data_table.js b/chrome/browser/resources/media/media_data_table.js deleted file mode 100644 index 62e6e97..0000000 --- a/chrome/browser/resources/media/media_data_table.js +++ /dev/null
@@ -1,117 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - /** - * TODO(beccahughes): Description - */ -export class MediaDataTable { - /** - * @param {HTMLElement} table - * @param {!MediaDataTableDelegate} delegate - */ - constructor(table, delegate) { - /** @private {HTMLElement} */ - this.table_ = table; - - /** @private {Array<Object>} */ - this.data_ = []; - - /** @private {MediaDataTableDelegate} */ - this.delegate_ = delegate; - - // Set table header sort handlers. - const headers = this.table_.querySelectorAll('th[sort-key]'); - headers.forEach(header => { - header.addEventListener('click', this.handleSortClick_.bind(this)); - }); - } - - handleSortClick_(e) { - if (e.target.classList.contains('sort-column')) { - e.target.toggleAttribute('sort-reverse'); - } else { - document.querySelector('.sort-column').classList.remove('sort-column'); - e.target.classList.add('sort-column'); - } - - this.render(); - } - - render() { - // Find the body of the table and clear it. - const body = this.table_.querySelectorAll('tbody')[0]; - body.innerHTML = trustedTypes.emptyHTML; - - // Get the sort key from the columns to determine which data should be in - // which column. - const headerCells = Array.from(this.table_.querySelectorAll('thead th')); - const dataAndSortKeys = headerCells.map((e) => { - return e.getAttribute('sort-key') ? e.getAttribute('sort-key') : - e.getAttribute('data-key'); - }); - - const currentSortCol = this.table_.querySelectorAll('.sort-column')[0]; - const currentSortKey = currentSortCol.getAttribute('sort-key'); - const currentSortReverse = currentSortCol.hasAttribute('sort-reverse'); - - // Sort the data based on the current sort key. - this.data_.sort((a, b) => { - return (currentSortReverse ? -1 : 1) * - this.delegate_.compareTableItem(currentSortKey, a, b); - }); - - // Generate the table rows. - this.data_.forEach((dataRow) => { - const tr = document.createElement('tr'); - body.appendChild(tr); - - dataAndSortKeys.forEach((key) => { - const td = document.createElement('td'); - - // Keys with a period denote nested objects. - let data = dataRow; - const expandedKey = key.split('.'); - expandedKey.forEach((k) => { - data = data[k]; - key = k; - }); - - this.delegate_.insertDataField(td, data, key, dataRow); - tr.appendChild(td); - }); - }); - } - - /** - * @param {Array} data The data to update - */ - setData(data) { - this.data_ = data; - this.render(); - } -} - -/** @interface */ -export class MediaDataTableDelegate { - /** - * Formats a field to be displayed in the data table and inserts it into the - * element. - * @param {Element} td - * @param {?Object} data - * @param {string} key - * @param {Object} dataRow This is the row itself in case we need extra - * data to render the field. - */ - insertDataField(td, data, key, dataRow) {} - - /** - * Compares two objects based on |sortKey|. - * @param {string} sortKey The name of the property to sort by. - * @param {?Object} a The first object to compare. - * @param {?Object} b The second object to compare. - * @return {number} A negative number if |a| should be ordered - * before |b|, a positive number otherwise. - */ - compareTableItem(sortKey, a, b) {} -}
diff --git a/chrome/browser/resources/media/media_data_table.ts b/chrome/browser/resources/media/media_data_table.ts new file mode 100644 index 0000000..8acb8b5 --- /dev/null +++ b/chrome/browser/resources/media/media_data_table.ts
@@ -0,0 +1,115 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {assert} from 'chrome://resources/js/assert_ts.js'; + +/** + * TODO(beccahughes): Description + */ +export class MediaDataTable { + private table_: HTMLElement; + private data_: Array<{[key: string]: any}> = []; + private delegate_: MediaDataTableDelegate; + + constructor(table: HTMLElement, delegate: MediaDataTableDelegate) { + this.table_ = table; + this.delegate_ = delegate; + + // Set table header sort handlers. + const headers = this.table_.querySelectorAll('th[sort-key]'); + headers.forEach(header => { + header.addEventListener('click', this.handleSortClick_.bind(this)); + }); + } + + private handleSortClick_(e: Event) { + const target = e.target as HTMLElement; + assert(target); + if (target.classList.contains('sort-column')) { + target.toggleAttribute('sort-reverse'); + } else { + const sortColumn = document.querySelector<HTMLElement>('.sort-column'); + assert(sortColumn); + sortColumn.classList.remove('sort-column'); + target.classList.add('sort-column'); + } + + this.render(); + } + + render() { + // Find the body of the table and clear it. + const body = this.table_.querySelectorAll('tbody')[0]!; + (body.innerHTML as string | TrustedHTML) = + window.trustedTypes ? window.trustedTypes.emptyHTML : ''; + + // Get the sort key from the columns to determine which data should be in + // which column. + const headerCells = Array.from(this.table_.querySelectorAll('thead th')); + const dataAndSortKeys = headerCells.map((e) => { + return e.getAttribute('sort-key') ? e.getAttribute('sort-key') : + e.getAttribute('data-key'); + }); + + const currentSortCol = this.table_.querySelectorAll('.sort-column')[0]!; + const currentSortKey = currentSortCol.getAttribute('sort-key') || ''; + const currentSortReverse = currentSortCol.hasAttribute('sort-reverse'); + + // Sort the data based on the current sort key. + this.data_.sort((a, b) => { + return (currentSortReverse ? -1 : 1) * + this.delegate_.compareTableItem(currentSortKey, a, b); + }); + + // Generate the table rows. + this.data_.forEach((dataRow) => { + const tr = document.createElement('tr'); + body.appendChild(tr); + + dataAndSortKeys.forEach((key) => { + const td = document.createElement('td'); + + // Keys with a period denote nested objects. + let data = dataRow; + const expandedKey = key!.split('.'); + expandedKey.forEach((k) => { + data = data[k]; + key = k; + }); + + this.delegate_.insertDataField(td, data, key!, dataRow); + tr.appendChild(td); + }); + }); + } + + /** + * @param data The data to update + */ + setData(data: object[]) { + this.data_ = data; + this.render(); + } +} + +export interface MediaDataTableDelegate { + /** + * Formats a field to be displayed in the data table and inserts it into the + * element. + * @param dataRow This is the row itself in case we need extra + * data to render the field. + */ + insertDataField(td: Element, data: object, key: string, dataRow: object): + void; + + /** + * Compares two objects based on |sortKey|. + * @param sortKey The name of the property to sort by. + * @param a The first object to compare. + * @param b The second object to compare. + * @return A negative number if |a| should be ordered + * before |b|, a positive number otherwise. + */ + compareTableItem(sortKey: string, a: object, b: object): number; +}
diff --git a/chrome/browser/resources/media/media_history.html b/chrome/browser/resources/media/media_history.html index 04fc32e..37cb846 100644 --- a/chrome/browser/resources/media/media_history.html +++ b/chrome/browser/resources/media/media_history.html
@@ -16,6 +16,7 @@ } cr-tab-box { + display: none; padding-top: 10px; }
diff --git a/chrome/browser/resources/media/media_history.js b/chrome/browser/resources/media/media_history.js deleted file mode 100644 index 9dfa7b7..0000000 --- a/chrome/browser/resources/media/media_history.js +++ /dev/null
@@ -1,265 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'chrome://resources/cr_elements/cr_tab_box/cr_tab_box.js'; - -import {assertNotReached} from 'chrome://resources/js/assert.m.js'; -import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js'; -import {$} from 'chrome://resources/js/util.m.js'; -import {String16} from 'chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-webui.js'; - -import {MediaDataTable, MediaDataTableDelegate} from './media_data_table.js'; -import {MediaHistoryStats, MediaHistoryStore} from './media_history_store.mojom-webui.js'; - -// Allow a function to be provided by tests, which will be called when -// the page has been populated. -const mediaHistoryPageIsPopulatedResolver = new PromiseResolver(); -window.whenPageIsPopulatedForTest = function() { - return mediaHistoryPageIsPopulatedResolver.promise; -}; - -let store = null; -let statsTableBody = null; -let originsTable = null; -let playbacksTable = null; -let sessionsTable = null; -let delegate = null; - -/** - * Creates a single row in the stats table. - * @param {string} name The name of the table. - * @param {number} count The row count of the table. - * @return {!Node} - */ -function createStatsRow(name, count) { - const template = $('stats-row'); - const td = template.content.querySelectorAll('td'); - td[0].textContent = name; - td[1].textContent = count; - return document.importNode(template.content, true); -} - -/** @implements {MediaDataTableDelegate} */ -class MediaHistoryTableDelegate { - /** - * Formats a field to be displayed in the data table and inserts it into the - * element. - * @param {Element} td - * @param {?Object} data - * @param {string} key - */ - insertDataField(td, data, key) { - if (data === undefined || data === null) { - return; - } - - if (key === 'origin') { - // Format a mojo origin. - const {scheme, host, port} = data; - td.textContent = new URL(`${scheme}://${host}:${port}`).origin; - } else if (key === 'lastUpdatedTime') { - // Format a JS timestamp. - td.textContent = data ? new Date(data).toISOString() : ''; - } else if ( - key === 'cachedAudioVideoWatchtime' || - key === 'actualAudioVideoWatchtime' || key === 'watchtime' || - key === 'duration' || key === 'position') { - // Format a mojo timedelta. - const secs = (data.microseconds / 1000000); - td.textContent = - secs.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,'); - } else if (key === 'url') { - // Format a mojo GURL. - td.textContent = data.url; - } else if (key === 'hasAudio' || key === 'hasVideo') { - // Format a boolean. - td.textContent = data ? 'Yes' : 'No'; - } else if ( - key === 'title' || key === 'artist' || key === 'album' || - key === 'sourceTitle') { - // Format a mojo string16. - td.textContent = decodeString16( - /** @type {String16} */ (data)); - } else if (key === 'artwork') { - // Format an array of mojo media images. - data.forEach((image) => { - const a = document.createElement('a'); - a.href = image.src.url; - a.textContent = image.src.url; - a.target = '_blank'; - td.appendChild(a); - td.appendChild(document.createElement('br')); - }); - } else { - td.textContent = data; - } - } - - /** - * Compares two objects based on |sortKey|. - * @param {string} sortKey The name of the property to sort by. - * @param {?Object} a The first object to compare. - * @param {?Object} b The second object to compare. - * @return {number} A negative number if |a| should be ordered - * before |b|, a positive number otherwise. - */ - compareTableItem(sortKey, a, b) { - const val1 = a[sortKey]; - const val2 = b[sortKey]; - - // Compare the hosts of the origin ignoring schemes. - if (sortKey === 'origin') { - return val1.host > val2.host ? 1 : -1; - } - - // Compare the url property. - if (sortKey === 'url') { - return val1.url > val2.url ? 1 : -1; - } - - // Compare TimeDelta microseconds value. - if (sortKey === 'cachedAudioVideoWatchtime' || - sortKey === 'actualAudioVideoWatchtime' || sortKey === 'watchtime' || - sortKey === 'duration' || sortKey === 'position') { - return val1.microseconds - val2.microseconds; - } - - if (sortKey.startsWith('metadata.')) { - // Keys with a period denote nested objects. - let nestedA = a; - let nestedB = b; - const expandedKey = sortKey.split('.'); - expandedKey.forEach((k) => { - nestedA = nestedA[k]; - nestedB = nestedB[k]; - }); - - return nestedA > nestedB ? 1 : -1; - } - - if (sortKey === 'lastUpdatedTime') { - return val1 - val2; - } - - assertNotReached('Unsupported sort key: ' + sortKey); - return 0; - } -} - -/** - * Parses utf16 coded string. - * @param {String16} arr - * @return {string} - */ -function decodeString16(arr) { - if (!arr) { - return ''; - } - - return arr.data.map(ch => String.fromCodePoint(ch)).join(''); -} - -/** - * Regenerates the stats table. - * @param {!MediaHistoryStats} stats The stats for the Media - * History store. - */ -function renderStatsTable(stats) { - statsTableBody.innerHTML = trustedTypes.emptyHTML; - - Object.keys(stats.tableRowCounts).forEach((key) => { - statsTableBody.appendChild(createStatsRow(key, stats.tableRowCounts[key])); - }); -} - -/** - * @param {!string} name The name of the tab to show. - * @return {Promise} - */ -function showTab(name) { - switch (name) { - case 'stats': - return store.getMediaHistoryStats().then(response => { - renderStatsTable(response.stats); - setSelectedTab(name); - }); - case 'origins': - return store.getMediaHistoryOriginRows().then(response => { - originsTable.setData(response.rows); - setSelectedTab(name); - }); - case 'playbacks': - return store.getMediaHistoryPlaybackRows().then(response => { - playbacksTable.setData(response.rows); - setSelectedTab(name); - }); - case 'sessions': - return store.getMediaHistoryPlaybackSessionRows().then(response => { - sessionsTable.setData(response.rows); - setSelectedTab(name); - }); - } - - // Return an empty promise if there is no tab. - return new Promise(() => {}); -} - -/** @param {string} id The id of the tab to set as selected. */ -function setSelectedTab(id) { - const tabbox = $('tabbox'); - const index = Array.from(tabbox.querySelectorAll('div[slot=\'tabs\']')) - .findIndex(tab => tab.id === id); - tabbox.setAttribute('selected-index', `${index}`); -} - -document.addEventListener('DOMContentLoaded', function() { - store = MediaHistoryStore.getRemote(); - - statsTableBody = $('stats-table-body'); - - delegate = new MediaHistoryTableDelegate(); - - originsTable = new MediaDataTable($('origins-table'), delegate); - playbacksTable = new MediaDataTable($('playbacks-table'), delegate); - sessionsTable = new MediaDataTable($('sessions-table'), delegate); - - // Allow tabs to be navigated to by fragment. The fragment with be of the - // format "#tab-<tab id>". - window.onhashchange = function() { - showTab(window.location.hash.substr(5)); - }; - - // Default to the stats tab. - if (!window.location.hash.substr(5)) { - window.location.hash = 'tab-stats'; - } else { - showTab(window.location.hash.substr(5)) - .then(mediaHistoryPageIsPopulatedResolver.resolve); - } - - // When the tab updates, update the anchor. - $('tabbox').addEventListener('selected-index-change', function(e) { - const tabbox = $('tabbox'); - const tabs = tabbox.querySelectorAll('div[slot=\'tabs\']'); - const selectedTab = tabs[e.detail]; - window.location.hash = 'tab-' + selectedTab.id; - }, true); - - // Add handler to 'copy all to clipboard' button. - const copyAllToClipboardButtons = - document.querySelectorAll('.copy-all-to-clipboard'); - - copyAllToClipboardButtons.forEach((button) => { - button.addEventListener('click', (e) => { - // Make sure nothing is selected. - window.getSelection().removeAllRanges(); - - document.execCommand('selectAll'); - document.execCommand('copy'); - - // And deselect everything at the end. - window.getSelection().removeAllRanges(); - }); - }); -});
diff --git a/chrome/browser/resources/media/media_history.ts b/chrome/browser/resources/media/media_history.ts new file mode 100644 index 0000000..019cc3d --- /dev/null +++ b/chrome/browser/resources/media/media_history.ts
@@ -0,0 +1,275 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/cr_elements/cr_tab_box/cr_tab_box.js'; + +import {assert, assertNotReached} from 'chrome://resources/js/assert_ts.js'; +import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js'; +import {String16} from 'chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-webui.js'; + +import {MediaDataTable, MediaDataTableDelegate} from './media_data_table.js'; +import {MediaHistoryStats, MediaHistoryStore, MediaHistoryStoreRemote} from './media_history_store.mojom-webui.js'; + +// Allow a function to be provided by tests, which will be called when +// the page has been populated. +const mediaHistoryPageIsPopulatedResolver = new PromiseResolver<void>(); +const whenPageIsPopulatedForTest = function() { + return mediaHistoryPageIsPopulatedResolver.promise; +}; +Object.assign(window, {whenPageIsPopulatedForTest}); + +let store: MediaHistoryStoreRemote|null = null; +let statsTableBody: HTMLElement|null = null; +let originsTable: MediaDataTable|null = null; +let playbacksTable: MediaDataTable|null = null; +let sessionsTable: MediaDataTable|null = null; +let delegate: MediaDataTableDelegate|null = null; + +/** + * Creates a single row in the stats table. + * @param name The name of the table. + * @param count The row count of the table. + */ +function createStatsRow(name: string, count: number): Node { + const template = document.querySelector<HTMLTemplateElement>('#stats-row'); + assert(template); + const td = template.content.querySelectorAll('td'); + td[0]!.textContent = name; + td[1]!.textContent = count.toString(); + return document.importNode(template.content, true); +} + +class MediaHistoryTableDelegate implements MediaDataTableDelegate { + /** + * Formats a field to be displayed in the data table and inserts it into the + * element. + */ + insertDataField(td: HTMLElement, data: unknown, key: string) { + if (data === undefined || data === null) { + return; + } + + if (key === 'origin') { + // Format a mojo origin. + const {scheme, host, port} = + data as {scheme: string, host: string, port: number}; + td.textContent = new URL(`${scheme}://${host}:${port}`).origin; + } else if (key === 'lastUpdatedTime') { + // Format a JS timestamp. + td.textContent = data ? new Date(data as number).toISOString() : ''; + } else if ( + key === 'cachedAudioVideoWatchtime' || + key === 'actualAudioVideoWatchtime' || key === 'watchtime' || + key === 'duration' || key === 'position') { + // Format a mojo timedelta. + const secs = ((data as {microseconds: number}).microseconds / 1000000); + td.textContent = + secs.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,'); + } else if (key === 'url') { + // Format a mojo GURL. + td.textContent = (data as {url: string}).url; + } else if (key === 'hasAudio' || key === 'hasVideo') { + // Format a boolean. + td.textContent = data as boolean ? 'Yes' : 'No'; + } else if ( + key === 'title' || key === 'artist' || key === 'album' || + key === 'sourceTitle') { + // Format a mojo string16. + td.textContent = decodeString16(data as String16); + } else if (key === 'artwork') { + // Format an array of mojo media images. + (data as Array<{src: {url: string}}>).forEach((image) => { + const a = document.createElement('a'); + a.href = image.src.url; + a.textContent = image.src.url; + a.target = '_blank'; + td.appendChild(a); + td.appendChild(document.createElement('br')); + }); + } else { + td.textContent = data as string; + } + } + + compareTableItem( + sortKey: string, a: {[key: string]: any}, + b: {[key: string]: any}): number { + const val1 = a[sortKey]; + const val2 = b[sortKey]; + + // Compare the hosts of the origin ignoring schemes. + if (sortKey === 'origin') { + return (val1 as {host: string}).host > (val2 as {host: string}).host ? 1 : + -1; + } + + // Compare the url property. + if (sortKey === 'url') { + return (val1 as {url: string}).url > (val2 as {url: string}).url ? 1 : -1; + } + + // Compare TimeDelta microseconds value. + if (sortKey === 'cachedAudioVideoWatchtime' || + sortKey === 'actualAudioVideoWatchtime' || sortKey === 'watchtime' || + sortKey === 'duration' || sortKey === 'position') { + return (val1 as {microseconds: number}).microseconds - + (val2 as {microseconds: number}).microseconds; + } + + if (sortKey.startsWith('metadata.')) { + // Keys with a period denote nested objects. + let nestedA = a; + let nestedB = b; + const expandedKey = sortKey.split('.'); + expandedKey.forEach((k) => { + nestedA = nestedA[k] as {[key: string]: any}; + nestedB = nestedB[k] as {[key: string]: any}; + }); + + return (nestedA as unknown as number | string) > + (nestedB as unknown as number | string) ? + 1 : + -1; + } + + if (sortKey === 'lastUpdatedTime') { + return (val1 as number) - (val2 as number); + } + + assertNotReached('Unsupported sort key: ' + sortKey); + } +} + +/** + * Parses utf16 coded string. + */ +function decodeString16(arr: String16): string { + if (!arr) { + return ''; + } + + return arr.data.map(ch => String.fromCodePoint(ch)).join(''); +} + +/** + * Regenerates the stats table. + * @param stats The stats for the Media + * History store. + */ +function renderStatsTable(stats: MediaHistoryStats) { + assert(statsTableBody); + (statsTableBody.innerHTML as TrustedHTML | string) = + window.trustedTypes ? window.trustedTypes.emptyHTML : ''; + + Object.keys(stats.tableRowCounts).forEach((key) => { + statsTableBody!.appendChild(createStatsRow(key, stats.tableRowCounts[key])); + }); +} + +/** + * @param name The name of the tab to show. + */ +function showTab(name: string): Promise<void> { + assert(store); + switch (name) { + case 'stats': + return store.getMediaHistoryStats().then(response => { + renderStatsTable(response.stats); + setSelectedTab(name); + }); + case 'origins': + return store.getMediaHistoryOriginRows().then(response => { + assert(originsTable); + originsTable.setData(response.rows); + setSelectedTab(name); + }); + case 'playbacks': + return store.getMediaHistoryPlaybackRows().then(response => { + assert(playbacksTable); + playbacksTable.setData(response.rows); + setSelectedTab(name); + }); + case 'sessions': + return store.getMediaHistoryPlaybackSessionRows().then(response => { + assert(sessionsTable); + sessionsTable.setData(response.rows); + setSelectedTab(name); + }); + } + + // Return an empty promise if there is no tab. + return new Promise(() => {}); +} + +function setSelectedTab(id: string) { + const tabbox = document.querySelector('cr-tab-box'); + assert(tabbox); + const index = + Array.from(tabbox.querySelectorAll<HTMLElement>('div[slot=\'tabs\']')) + .findIndex(tab => tab.id === id); + tabbox.setAttribute('selected-index', `${index}`); +} + +document.addEventListener('DOMContentLoaded', function() { + store = MediaHistoryStore.getRemote(); + + statsTableBody = document.querySelector<HTMLElement>('#stats-table-body'); + + delegate = new MediaHistoryTableDelegate(); + + originsTable = new MediaDataTable( + document.querySelector<HTMLElement>('#origins-table')!, delegate); + playbacksTable = new MediaDataTable( + document.querySelector<HTMLElement>('#playbacks-table')!, delegate); + sessionsTable = new MediaDataTable( + document.querySelector<HTMLElement>('#sessions-table')!, delegate); + + // Allow tabs to be navigated to by fragment. The fragment with be of the + // format "#tab-<tab id>". + window.onhashchange = function() { + showTab(window.location.hash.substr(5)); + }; + + const tabBox = document.querySelector('cr-tab-box'); + assert(tabBox); + + // Default to the stats tab. + if (!window.location.hash.substr(5)) { + window.location.hash = 'tab-stats'; + // Show the tab box. + tabBox.style.display = 'block'; + } else { + showTab(window.location.hash.substr(5)).then(() => { + // Show the tab box. + tabBox.style.display = 'block'; + mediaHistoryPageIsPopulatedResolver.resolve(); + }); + } + + // When the tab updates, update the anchor. + tabBox.addEventListener('selected-index-change', function(e) { + const tabbox = document.querySelector('cr-tab-box'); + assert(tabbox); + const tabs = tabbox.querySelectorAll<HTMLElement>('div[slot=\'tabs\']'); + const selectedTab = tabs[(e as CustomEvent<number>).detail]; + window.location.hash = 'tab-' + selectedTab.id; + }, true); + + // Add handler to 'copy all to clipboard' button. + const copyAllToClipboardButtons = + document.querySelectorAll<HTMLElement>('.copy-all-to-clipboard'); + + copyAllToClipboardButtons.forEach((button) => { + button.addEventListener('click', () => { + // Make sure nothing is selected. + window.getSelection()!.removeAllRanges(); + + document.execCommand('selectAll'); + document.execCommand('copy'); + + // And deselect everything at the end. + window.getSelection()!.removeAllRanges(); + }); + }); +});
diff --git a/chrome/browser/resources/media/tsconfig_base.json b/chrome/browser/resources/media/tsconfig_base.json new file mode 100644 index 0000000..3e71f763 --- /dev/null +++ b/chrome/browser/resources/media/tsconfig_base.json
@@ -0,0 +1,9 @@ +{ + "extends": "../../../../tools/typescript/tsconfig_base.json", + "compilerOptions": { + "allowJs": true, + "noUncheckedIndexedAccess": false, + "noUnusedLocals": false, + "strictPropertyInitialization": false + } +}
diff --git a/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts b/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts index 8b086df..940379a 100644 --- a/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts +++ b/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts
@@ -140,7 +140,8 @@ assert(this.item.changePasswordUrl); OpenWindowProxyImpl.getInstance().openURL(this.item.changePasswordUrl); - + PasswordManagerImpl.getInstance().recordChangePasswordFlowStarted( + this.item, /*is_manual_flow=*/ true); PasswordManagerImpl.getInstance().recordPasswordCheckInteraction( PasswordCheckInteraction.CHANGE_PASSWORD); }
diff --git a/chrome/browser/resources/settings/autofill_page/password_manager_proxy.ts b/chrome/browser/resources/settings/autofill_page/password_manager_proxy.ts index db94013..b5474ed 100644 --- a/chrome/browser/resources/settings/autofill_page/password_manager_proxy.ts +++ b/chrome/browser/resources/settings/autofill_page/password_manager_proxy.ts
@@ -256,6 +256,14 @@ insecureCredential: chrome.passwordsPrivate.InsecureCredential): void; /** + * Records the state of a change password flow for |insecureCredential| + * and notes it is a manual flow via |isManualFlow|. + */ + recordChangePasswordFlowStarted( + insecureCredential: chrome.passwordsPrivate.InsecureCredential, + isManualFlow: boolean): void; + + /** * Add an observer to the compromised passwords change. */ addCompromisedCredentialsListener(listener: CredentialsChangedListener): void; @@ -566,6 +574,13 @@ chrome.passwordsPrivate.unmuteInsecureCredential(insecureCredential); } + recordChangePasswordFlowStarted( + insecureCredential: chrome.passwordsPrivate.InsecureCredential, + isManualFlow: boolean) { + chrome.passwordsPrivate.recordChangePasswordFlowStarted( + insecureCredential, isManualFlow); + } + addCompromisedCredentialsListener(listener: CredentialsChangedListener) { chrome.passwordsPrivate.onCompromisedCredentialsChanged.addListener( listener);
diff --git a/chrome/browser/search/search.cc b/chrome/browser/search/search.cc index 5b7e755..26fc116e 100644 --- a/chrome/browser/search/search.cc +++ b/chrome/browser/search/search.cc
@@ -31,7 +31,7 @@ #if BUILDFLAG(ENABLE_SUPERVISED_USERS) #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" -#include "chrome/browser/supervised_user/supervised_user_url_filter.h" +#include "chrome/browser/supervised_user/supervised_user_url_filter.h" // nogncheck #endif #if !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/sessions/session_service_utils.cc b/chrome/browser/sessions/session_service_utils.cc index 4d45f5e8..68e50ef 100644 --- a/chrome/browser/sessions/session_service_utils.cc +++ b/chrome/browser/sessions/session_service_utils.cc
@@ -13,6 +13,9 @@ return sessions::SessionWindow::TYPE_NORMAL; case Browser::TYPE_POPUP: return sessions::SessionWindow::TYPE_POPUP; + case Browser::TYPE_PICTURE_IN_PICTURE: + // For now, picture in picture windows can be treated like popups. + return sessions::SessionWindow::TYPE_POPUP; case Browser::TYPE_APP: return sessions::SessionWindow::TYPE_APP; case Browser::TYPE_DEVTOOLS:
diff --git a/chrome/browser/startup_data.cc b/chrome/browser/startup_data.cc index 8357ef0..7c78319 100644 --- a/chrome/browser/startup_data.cc +++ b/chrome/browser/startup_data.cc
@@ -32,9 +32,6 @@ #include "chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.h" #include "chrome/browser/profiles/pref_service_builder_utils.h" #include "chrome/browser/profiles/profile_key.h" -#include "chrome/browser/supervised_user/supervised_user_pref_store.h" -#include "chrome/browser/supervised_user/supervised_user_settings_service.h" -#include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "components/keyed_service/content/browser_context_dependency_manager.h"
diff --git a/chrome/browser/subresource_filter/ad_tagging_browsertest.cc b/chrome/browser/subresource_filter/ad_tagging_browsertest.cc index 64ee12b..1adf76c 100644 --- a/chrome/browser/subresource_filter/ad_tagging_browsertest.cc +++ b/chrome/browser/subresource_filter/ad_tagging_browsertest.cc
@@ -24,7 +24,6 @@ #include "components/subresource_filter/content/browser/ad_tagging_browser_test_utils.h" #include "components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h" #include "components/subresource_filter/core/common/test_ruleset_utils.h" -#include "components/ukm/content/source_url_recorder.h" #include "components/ukm/test_ukm_recorder.h" #include "content/public/test/back_forward_cache_util.h" #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java index b5ab7bb4..2513868 100644 --- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java +++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java
@@ -345,6 +345,8 @@ return TabLaunchType.FROM_APP_WIDGET; case LaunchTypeAtCreation.FROM_RECENT_TABS: return TabLaunchType.FROM_RECENT_TABS; + case LaunchTypeAtCreation.FROM_READING_LIST: + return TabLaunchType.FROM_READING_LIST; case LaunchTypeAtCreation.SIZE: return TabLaunchType.SIZE; case LaunchTypeAtCreation.UNKNOWN: @@ -399,6 +401,8 @@ return LaunchTypeAtCreation.FROM_APP_WIDGET; case LaunchTypeAtCreation.FROM_RECENT_TABS: return TabLaunchType.FROM_RECENT_TABS; + case LaunchTypeAtCreation.FROM_READING_LIST: + return TabLaunchType.FROM_READING_LIST; case TabLaunchType.SIZE: return LaunchTypeAtCreation.SIZE; default:
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/flatbuffer/critical_persisted_tab_data.fbs b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/flatbuffer/critical_persisted_tab_data.fbs index 81fde1cf..fcff3ad 100644 --- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/flatbuffer/critical_persisted_tab_data.fbs +++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/flatbuffer/critical_persisted_tab_data.fbs
@@ -34,6 +34,7 @@ FROM_APP_WIDGET = 15, FROM_LONGPRESS_INCOGNITO = 16, FROM_RECENT_TABS = 17, + FROM_READING_LIST = 18, // Add new values here and don't change existing values // as they are persisted across restarts. Changing existing // values will lead to backwards compatibility issues crbug.com/1286984.
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/proto/critical_persisted_tab_data.proto b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/proto/critical_persisted_tab_data.proto index 8c94e77b..fa30dec 100644 --- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/proto/critical_persisted_tab_data.proto +++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/proto/critical_persisted_tab_data.proto
@@ -51,8 +51,9 @@ FROM_APP_WIDGET = 15; FROM_LONGPRESS_INCOGNITO = 16; FROM_RECENT_TABS = 17; - SIZE = 18; - UNKNOWN = 19; + FROM_READING_LIST = 18; + SIZE = 19; + UNKNOWN = 20; } optional LaunchTypeAtCreation launch_type_at_creation = 8;
diff --git a/chrome/browser/tabmodel/OWNERS b/chrome/browser/tabmodel/OWNERS index ed81765..722432c2 100644 --- a/chrome/browser/tabmodel/OWNERS +++ b/chrome/browser/tabmodel/OWNERS
@@ -1,3 +1,4 @@ +ckitagawa@chromium.org dtrainor@chromium.org hnakashima@chromium.org meiliang@chromium.org
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModel.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModel.java index 1b03feb5..419aaaf 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModel.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModel.java
@@ -54,7 +54,7 @@ } @Override - public Tab getNextTabIfClosed(int id) { + public Tab getNextTabIfClosed(int id, boolean uponExit) { return null; }
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java index f5f56cb..5c8f9c6 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java
@@ -137,8 +137,8 @@ } @Override - public Tab getNextTabIfClosed(int id) { - return mDelegateModel.getNextTabIfClosed(id); + public Tab getNextTabIfClosed(int id, boolean uponExit) { + return mDelegateModel.getNextTabIfClosed(id, uponExit); } @Override
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModel.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModel.java index 41032da..9128c96 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModel.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModel.java
@@ -74,9 +74,10 @@ /** * Returns which tab would be selected if the specified tab {@code id} were closed. * @param id The ID of tab which would be closed. + * @param uponExit If the next tab is being selected upon exit or backgrounding of the app. * @return The id of the next tab that would be visible. */ - public Tab getNextTabIfClosed(int id); + public Tab getNextTabIfClosed(int id, boolean uponExit); /** * Close multiple tabs on this model.
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelUtils.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelUtils.java index 380d008..28966523 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelUtils.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelUtils.java
@@ -186,4 +186,27 @@ } return tabIds; } + + /** + * Returns the most recently visited Tab in the specified TabList that is not {@code tabId}. + * @param model The {@link TabModel} to act on. + * @param tabId The ID of the {@link Tab} to skip or {@link Tab.INVALID_TAB_ID}. + * @return the most recently visited Tab or null if none can be found. + */ + public static Tab getMostRecentTab(TabList model, int tabId) { + Tab mostRecentTab = null; + long mostRecentTabTime = 0; + for (int i = 0; i < model.getCount(); i++) { + final Tab currentTab = model.getTabAt(i); + if (currentTab.getId() == tabId || currentTab.isClosing()) continue; + + final long currentTime = CriticalPersistedTabData.from(currentTab).getTimestampMillis(); + if (currentTime != CriticalPersistedTabData.INVALID_TIMESTAMP + && mostRecentTabTime < currentTime) { + mostRecentTabTime = currentTime; + mostRecentTab = currentTab; + } + } + return mostRecentTab; + } }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index eba0cbb9..1775199 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -2056,6 +2056,8 @@ "app_list/search/games/game_result.h", "app_list/search/help_app_provider.cc", "app_list/search/help_app_provider.h", + "app_list/search/help_app_zero_state_provider.cc", + "app_list/search/help_app_zero_state_provider.h", "app_list/search/keyboard_shortcut_data.cc", "app_list/search/keyboard_shortcut_data.h", "app_list/search/keyboard_shortcut_provider.cc",
diff --git a/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java b/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java index 9e6aaa00..a1e1c70 100644 --- a/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java +++ b/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java
@@ -71,6 +71,11 @@ } /** + * Reloads the native page. + */ + default void reload() {} + + /** * @return True if the native page needs the toolbar shadow to be drawn. */ boolean needsToolbarShadow();
diff --git a/chrome/browser/ui/android/tab_model/tab_model.h b/chrome/browser/ui/android/tab_model/tab_model.h index 547bed4..3623bed 100644 --- a/chrome/browser/ui/android/tab_model/tab_model.h +++ b/chrome/browser/ui/android/tab_model/tab_model.h
@@ -102,6 +102,9 @@ // parent/child relationship. The tab is added to the end of the TabModel. // This does not include opening in the current tab. FROM_RECENT_TABS, + // Opened from a Reading list. When going "back" on Android, the Reading + // list should be reopened. + FROM_READING_LIST, // Must be last. SIZE };
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/HomeButtonCoordinatorTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/HomeButtonCoordinatorTest.java index 53c2326..9a5fceb 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/HomeButtonCoordinatorTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/HomeButtonCoordinatorTest.java
@@ -16,7 +16,9 @@ import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; @@ -36,6 +38,8 @@ import org.chromium.chrome.browser.toolbar.ToolbarIntentMetadata; import org.chromium.chrome.browser.user_education.IPHCommand; import org.chromium.chrome.browser.user_education.UserEducationHelper; +import org.chromium.chrome.test.util.browser.Features; +import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.components.feature_engagement.FeatureConstants; import org.chromium.url.GURL; import org.chromium.url.JUnitTestGURLs; @@ -46,6 +50,7 @@ /** Unit tests for HomeButtonCoordinator. */ @RunWith(BaseRobolectricTestRunner.class) @Config(shadows = {HomeButtonCoordinatorTest.ShadowChromeFeatureList.class}) +@EnableFeatures(ChromeFeatureList.ENABLE_IPH) public class HomeButtonCoordinatorTest { private static final GURL NTP_URL = JUnitTestGURLs.getGURL(JUnitTestGURLs.NTP_URL); private static final GURL NOT_NTP_URL = JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL); @@ -70,6 +75,9 @@ } } + @Rule + public TestRule mFeaturesProcessorRule = new Features.JUnitProcessor(); + @Mock private Context mContext; @Mock
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinatorTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinatorTest.java index fa8cc10..d7c0c20 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinatorTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinatorTest.java
@@ -16,7 +16,9 @@ import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; @@ -37,6 +39,8 @@ import org.chromium.chrome.browser.toolbar.ToolbarIntentMetadata; import org.chromium.chrome.browser.user_education.IPHCommand; import org.chromium.chrome.browser.user_education.UserEducationHelper; +import org.chromium.chrome.test.util.browser.Features; +import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.components.feature_engagement.FeatureConstants; import java.util.HashMap; @@ -50,6 +54,7 @@ @RunWith(BaseRobolectricTestRunner.class) @Config(shadows = {ToggleTabStackButtonCoordinatorTest.ShadowChromeFeatureList.class}) @LooperMode(LooperMode.Mode.LEGACY) +@EnableFeatures(ChromeFeatureList.ENABLE_IPH) public class ToggleTabStackButtonCoordinatorTest { private static final ToolbarIntentMetadata DEFAULT_INTENT_METADATA = new ToolbarIntentMetadata(/*isMainIntent*/ true, /*isIntentWithEffect*/ false); @@ -66,6 +71,9 @@ } } + @Rule + public TestRule mFeaturesProcessorRule = new Features.JUnitProcessor(); + @Mock private Context mContext; @Mock
diff --git a/chrome/browser/ui/app_list/search/common/types_util.cc b/chrome/browser/ui/app_list/search/common/types_util.cc index 864c9402..882873a 100644 --- a/chrome/browser/ui/app_list/search/common/types_util.cc +++ b/chrome/browser/ui/app_list/search/common/types_util.cc
@@ -48,6 +48,8 @@ return "Assistant text"; case ash::AppListSearchResultType::kHelpApp: return "Help app"; + case ash::AppListSearchResultType::kZeroStateHelpApp: + return "Help app - zero state"; case ash::AppListSearchResultType::kFileSearch: return "File search"; case ash::AppListSearchResultType::kDriveSearch:
diff --git a/chrome/browser/ui/app_list/search/help_app_provider.cc b/chrome/browser/ui/app_list/search/help_app_provider.cc index 56fcdc83..960d1f0 100644 --- a/chrome/browser/ui/app_list/search/help_app_provider.cc +++ b/chrome/browser/ui/app_list/search/help_app_provider.cc
@@ -10,8 +10,6 @@ #include "ash/public/cpp/app_list/app_list_config.h" #include "ash/public/cpp/app_list/app_list_features.h" #include "ash/public/cpp/app_list/app_list_metrics.h" -#include "ash/public/cpp/app_list/vector_icons/vector_icons.h" -#include "ash/public/cpp/style/color_provider.h" #include "ash/webui/help_app_ui/help_app_manager.h" #include "ash/webui/help_app_ui/help_app_manager_factory.h" #include "ash/webui/help_app_ui/search/search_handler.h" @@ -19,12 +17,10 @@ #include "base/bind.h" #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" -#include "base/metrics/user_metrics.h" #include "base/time/time.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/apps/app_service/launch_utils.h" -#include "chrome/browser/ash/release_notes/release_notes_storage.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/search/common/icon_constants.h" #include "chrome/browser/ui/app_list/search/search_tags_util.h" @@ -32,58 +28,22 @@ #include "chrome/browser/web_applications/system_web_apps/system_web_app_types.h" #include "chrome/browser/web_applications/web_app_id_constants.h" #include "chrome/common/chrome_features.h" -#include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" #include "chromeos/strings/grit/chromeos_strings.h" -#include "components/prefs/pref_service.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" #include "components/services/app_service/public/cpp/app_types.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/image/image_skia.h" -#include "ui/gfx/paint_vector_icon.h" #include "url/gurl.h" namespace app_list { namespace { -constexpr char kHelpAppDiscoverResult[] = "help-app://discover"; -constexpr char kHelpAppUpdatesResult[] = "help-app://updates"; - constexpr size_t kMinQueryLength = 3u; constexpr double kMinScore = 0.4; constexpr size_t kNumRequestedResults = 5u; constexpr size_t kMaxShownResults = 2u; -// Whether we should show the Discover Tab suggestion chip. -bool ShouldShowDiscoverTabSuggestionChip(Profile* profile) { - if (!base::FeatureList::IsEnabled(ash::features::kHelpAppDiscoverTab)) { - return false; - } - - if (ash::features::IsProductivityLauncherEnabled()) - return false; - - const int times_left_to_show = profile->GetPrefs()->GetInteger( - prefs::kDiscoverTabSuggestionChipTimesLeftToShow); - return times_left_to_show > 0; -} - -// Decrements the times left to show the Discover Tab suggestion chip in -// PrefService. -void DecreaseTimesLeftToShowDiscoverTabSuggestionChip(Profile* profile) { - const int times_left_to_show = profile->GetPrefs()->GetInteger( - prefs::kDiscoverTabSuggestionChipTimesLeftToShow); - profile->GetPrefs()->SetInteger( - prefs::kDiscoverTabSuggestionChipTimesLeftToShow, times_left_to_show - 1); -} - -// Sets the times left to show the Discover Tab suggestion chip to 0 in -// PrefService. -void StopShowingDiscoverTabSuggestionChip(Profile* profile) { - profile->GetPrefs()->SetInteger( - prefs::kDiscoverTabSuggestionChipTimesLeftToShow, 0); -} - // The end result of a list search. Logged once per time a list search finishes. // Not logged if the search is canceled by a new search starting. Not logged for // suggestion chips. These values persist to logs. Entries should not be @@ -106,36 +66,6 @@ } // namespace -HelpAppResult::HelpAppResult(Profile* profile, - const std::string& id, - DisplayType display_type, - const std::u16string& title, - const std::u16string& details, - const gfx::ImageSkia& icon) - : profile_(profile) { - DCHECK(profile_); - set_id(id); - SetCategory(Category::kHelp); - SetTitle(title); - if (!details.empty()) - SetDetails(details); - // Show this in the first position, in front of any other chips that may be - // also claiming the first slot. - SetDisplayIndex(DisplayIndex::kFirstIndex); - SetPositionPriority(1.0f); - SetResultType(ResultType::kHelpApp); - SetDisplayType(display_type); - // Some chips have different metrics types. - if (id == kHelpAppDiscoverResult) { - SetMetricsType(ash::HELP_APP_DISCOVER); - } else if (id == kHelpAppUpdatesResult) { - SetMetricsType(ash::HELP_APP_UPDATES); - } else { - SetMetricsType(ash::HELP_APP_DEFAULT); - } - SetChipIcon(icon); -} - HelpAppResult::HelpAppResult( const float& relevance, Profile* profile, @@ -161,34 +91,6 @@ void HelpAppResult::Open(int event_flags) { // Note: event_flags is ignored, LaunchSWA doesn't need it. - if (id() == kHelpAppDiscoverResult) { - // Launch discover tab suggestion chip. - web_app::SystemAppLaunchParams params; - params.url = GURL("chrome://help-app/discover"); - params.launch_source = - apps::mojom::LaunchSource::kFromAppListRecommendation; - web_app::LaunchSystemWebAppAsync( - profile_, web_app::SystemAppType::HELP, params, - apps::MakeWindowInfo(display::kDefaultDisplayId)); - - StopShowingDiscoverTabSuggestionChip(profile_); - return; - } else if (id() == kHelpAppUpdatesResult) { - // Launch release notes suggestion chip. - base::RecordAction( - base::UserMetricsAction("ReleaseNotes.SuggestionChipLaunched")); - - web_app::SystemAppLaunchParams params; - params.url = GURL("chrome://help-app/updates"); - params.launch_source = - apps::mojom::LaunchSource::kFromAppListRecommendation; - web_app::LaunchSystemWebAppAsync( - profile_, web_app::SystemAppType::HELP, params, - apps::MakeWindowInfo(display::kDefaultDisplayId)); - - ash::ReleaseNotesStorage(profile_).StopShowingSuggestionChip(); - return; - } // Launch list result. web_app::SystemAppLaunchParams params; params.url = GURL(ash::kChromeUIHelpAppURL + url_path_); @@ -202,18 +104,14 @@ base::PersistentHash(help_app_content_id_)); } -HelpAppProvider::HelpAppProvider(Profile* profile, - ash::AppListNotifier* notifier) - : profile_(profile), notifier_(notifier), search_handler_(nullptr) { +HelpAppProvider::HelpAppProvider(Profile* profile) + : profile_(profile), search_handler_(nullptr) { DCHECK(profile_); app_service_proxy_ = apps::AppServiceProxyFactory::GetForProfile(profile_); Observe(&app_service_proxy_->AppRegistryCache()); LoadIcon(); - if (notifier_) - notifier_->AddObserver(this); - if (!base::FeatureList::IsEnabled( chromeos::features::kHelpAppLauncherSearch)) { // Only get the help app manager if the launcher search feature is enabled. @@ -229,10 +127,7 @@ search_results_observer_receiver_.BindNewPipeAndPassRemote()); } -HelpAppProvider::~HelpAppProvider() { - if (notifier_) - notifier_->RemoveObserver(this); -} +HelpAppProvider::~HelpAppProvider() = default; void HelpAppProvider::Start(const std::u16string& query) { ClearResultsSilently(); @@ -273,44 +168,8 @@ } void HelpAppProvider::StartZeroState() { - SearchProvider::Results search_results; ClearResultsSilently(); last_query_.clear(); - - if (ShouldShowDiscoverTabSuggestionChip(profile_)) { - search_results.emplace_back(std::make_unique<HelpAppResult>( - profile_, kHelpAppDiscoverResult, DisplayType::kChip, - l10n_util::GetStringUTF16(IDS_HELP_APP_DISCOVER_TAB_SUGGESTION_CHIP), - /*details=*/u"", icon_)); - } else if (ash::ReleaseNotesStorage(profile_).ShouldShowSuggestionChip()) { - // With productivity launcher enabled, release notes are shown in continue - // section. - if (ash::features::IsProductivityLauncherEnabled()) { - auto* color_provider = ash::ColorProvider::Get(); - // NOTE: Color provider may not be set in unit tests. - SkColor icon_color = color_provider - ? color_provider->GetContentLayerColor( - ash::ColorProvider::ContentLayerType:: - kButtonIconColorPrimary) - : gfx::kGoogleGrey900; - gfx::ImageSkia icon = - gfx::CreateVectorIcon(ash::kReleaseNotesChipIcon, - app_list::kSystemIconDimension, icon_color); - search_results.emplace_back(std::make_unique<HelpAppResult>( - profile_, kHelpAppUpdatesResult, DisplayType::kContinue, - l10n_util::GetStringUTF16(IDS_HELP_APP_WHATS_NEW_CONTINUE_TASK_TITLE), - l10n_util::GetStringUTF16( - IDS_HELP_APP_WHATS_NEW_CONTINUE_TASK_DETAILS), - icon)); - } else { - search_results.emplace_back(std::make_unique<HelpAppResult>( - profile_, kHelpAppUpdatesResult, DisplayType::kChip, - l10n_util::GetStringUTF16(IDS_HELP_APP_WHATS_NEW_SUGGESTION_CHIP), - /*details=*/u"", icon_)); - } - } - - SwapResults(&search_results); } void HelpAppProvider::ViewClosing() { @@ -348,10 +207,6 @@ return ash::AppListSearchResultType::kHelpApp; } -bool HelpAppProvider::ShouldBlockZeroState() const { - return true; -} - void HelpAppProvider::OnAppUpdate(const apps::AppUpdate& update) { if (update.AppId() == web_app::kHelpAppId && update.ReadinessChanged() && update.Readiness() == apps::Readiness::kReady) { @@ -364,25 +219,6 @@ Observe(nullptr); } -void HelpAppProvider::OnImpression( - ash::AppListNotifier::Location location, - const std::vector<ash::AppListNotifier::Result>& results, - const std::u16string& query) { - if (location != ash::AppListNotifier::Location::kChip && - location != ash::AppListNotifier::Location::kContinue) { - return; - } - - for (const auto& result : results) { - if (result.id == kHelpAppDiscoverResult) { - DecreaseTimesLeftToShowDiscoverTabSuggestionChip(profile_); - } else if (result.id == kHelpAppUpdatesResult) { - ash::ReleaseNotesStorage(profile_) - .DecreaseTimesLeftToShowSuggestionChip(); - } - } -} - // If the availability of search results changed, start a new search. void HelpAppProvider::OnSearchResultAvailabilityChanged() { if (last_query_.empty())
diff --git a/chrome/browser/ui/app_list/search/help_app_provider.h b/chrome/browser/ui/app_list/search/help_app_provider.h index b26bc0c..3da7a7d 100644 --- a/chrome/browser/ui/app_list/search/help_app_provider.h +++ b/chrome/browser/ui/app_list/search/help_app_provider.h
@@ -8,7 +8,6 @@ #include <string> #include <vector> -#include "ash/public/cpp/app_list/app_list_notifier.h" #include "ash/webui/help_app_ui/search/search.mojom.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" @@ -38,14 +37,6 @@ // Search results for the Help App (aka Explore). class HelpAppResult : public ChromeSearchResult { public: - // Constructor for the What's new chip. - HelpAppResult(Profile* profile, - const std::string& id, - DisplayType display_type, - const std::u16string& title, - const std::u16string& details, - const gfx::ImageSkia& icon); - // Constructor for a list result. HelpAppResult(const float& relevance, Profile* profile, const ash::help_app::mojom::SearchResultPtr& result, @@ -66,14 +57,12 @@ const std::string help_app_content_id_; }; -// Provides results from the Help App based on the search query. Also provides -// zero-state results. +// Provides results from the Help App based on the search query. class HelpAppProvider : public SearchProvider, public apps::AppRegistryCache::Observer, - public ash::AppListNotifier::Observer, public ash::help_app::mojom::SearchResultsObserver { public: - HelpAppProvider(Profile* profile, ash::AppListNotifier* notifier); + explicit HelpAppProvider(Profile* profile); ~HelpAppProvider() override; HelpAppProvider(const HelpAppProvider&) = delete; @@ -84,18 +73,12 @@ void StartZeroState() override; void ViewClosing() override; ash::AppListSearchResultType ResultType() const override; - bool ShouldBlockZeroState() const override; // apps::AppRegistryCache::Observer: void OnAppUpdate(const apps::AppUpdate& update) override; void OnAppRegistryCacheWillBeDestroyed( apps::AppRegistryCache* cache) override; - // ash::AppListNotifier::Observer: - void OnImpression(ash::AppListNotifier::Location location, - const std::vector<ash::AppListNotifier::Result>& results, - const std::u16string& query) override; - // mojom::SearchResultsObserver: void OnSearchResultAvailabilityChanged() override; @@ -108,7 +91,6 @@ void LoadIcon(); Profile* const profile_; - ash::AppListNotifier* const notifier_; ash::help_app::SearchHandler* search_handler_; apps::AppServiceProxy* app_service_proxy_;
diff --git a/chrome/browser/ui/app_list/search/help_app_search_browsertest.cc b/chrome/browser/ui/app_list/search/help_app_search_browsertest.cc index 579ccb7..d1dff9c0 100644 --- a/chrome/browser/ui/app_list/search/help_app_search_browsertest.cc +++ b/chrome/browser/ui/app_list/search/help_app_search_browsertest.cc
@@ -75,7 +75,7 @@ void ShowAppListAndWaitForHelpAppZeroStateResults() { ShowAppListAndWaitForZeroStateResults( - {ash::AppListSearchResultType::kHelpApp}); + {ash::AppListSearchResultType::kZeroStateHelpApp}); } void ShowAppListAndWaitForZeroStateResults( @@ -246,7 +246,7 @@ SearchResultsChangedWaiter results_waiter( GetClient()->search_controller(), - {ash::AppListSearchResultType::kHelpApp}); + {ash::AppListSearchResultType::kZeroStateHelpApp}); ash::ShellTestApi().SetTabletModeEnabledForTest(true); // Minimize the browser window to show home screen. browser()->window()->Minimize(); @@ -391,7 +391,7 @@ prefs::kReleaseNotesSuggestionChipTimesLeftToShow, 3); ShowAppListAndWaitForZeroStateResults( - {ash::AppListSearchResultType::kHelpApp, + {ash::AppListSearchResultType::kZeroStateHelpApp, ash::AppListSearchResultType::kInstalledApp}); auto* result = FindResult(web_app::kHelpAppId); @@ -412,7 +412,7 @@ const web_app::AppId app_id = web_app::kHelpAppId; ShowAppListAndWaitForZeroStateResults( - {ash::AppListSearchResultType::kHelpApp, + {ash::AppListSearchResultType::kZeroStateHelpApp, ash::AppListSearchResultType::kInstalledApp}); auto* result = FindResult(web_app::kHelpAppId);
diff --git a/chrome/browser/ui/app_list/search/help_app_zero_state_provider.cc b/chrome/browser/ui/app_list/search/help_app_zero_state_provider.cc new file mode 100644 index 0000000..8903167 --- /dev/null +++ b/chrome/browser/ui/app_list/search/help_app_zero_state_provider.cc
@@ -0,0 +1,274 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/app_list/search/help_app_zero_state_provider.h" + +#include <memory> + +#include "ash/constants/ash_features.h" +#include "ash/public/cpp/app_list/app_list_config.h" +#include "ash/public/cpp/app_list/vector_icons/vector_icons.h" +#include "ash/public/cpp/style/color_provider.h" +#include "base/bind.h" +#include "base/feature_list.h" +#include "base/metrics/user_metrics.h" +#include "base/time/time.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/launch_utils.h" +#include "chrome/browser/ash/release_notes/release_notes_storage.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/app_list/search/common/icon_constants.h" +#include "chrome/browser/ui/app_list/search/search_tags_util.h" +#include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h" +#include "chrome/browser/web_applications/system_web_apps/system_web_app_types.h" +#include "chrome/browser/web_applications/web_app_id_constants.h" +#include "chrome/common/chrome_features.h" +#include "chrome/common/pref_names.h" +#include "chrome/grit/generated_resources.h" +#include "chromeos/strings/grit/chromeos_strings.h" +#include "components/prefs/pref_service.h" +#include "components/services/app_service/public/cpp/app_registry_cache.h" +#include "components/services/app_service/public/cpp/app_types.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/image/image_skia.h" +#include "ui/gfx/paint_vector_icon.h" +#include "url/gurl.h" + +namespace app_list { +namespace { + +constexpr char kHelpAppDiscoverResult[] = "help-app://discover"; +constexpr char kHelpAppUpdatesResult[] = "help-app://updates"; + +// Whether we should show the Discover Tab suggestion chip. +bool ShouldShowDiscoverTabSuggestionChip(Profile* profile) { + if (!base::FeatureList::IsEnabled(ash::features::kHelpAppDiscoverTab)) { + return false; + } + + if (ash::features::IsProductivityLauncherEnabled()) + return false; + + const int times_left_to_show = profile->GetPrefs()->GetInteger( + prefs::kDiscoverTabSuggestionChipTimesLeftToShow); + return times_left_to_show > 0; +} + +// Decrements the times left to show the Discover Tab suggestion chip in +// PrefService. +void DecreaseTimesLeftToShowDiscoverTabSuggestionChip(Profile* profile) { + const int times_left_to_show = profile->GetPrefs()->GetInteger( + prefs::kDiscoverTabSuggestionChipTimesLeftToShow); + profile->GetPrefs()->SetInteger( + prefs::kDiscoverTabSuggestionChipTimesLeftToShow, times_left_to_show - 1); +} + +// Sets the times left to show the Discover Tab suggestion chip to 0 in +// PrefService. +void StopShowingDiscoverTabSuggestionChip(Profile* profile) { + profile->GetPrefs()->SetInteger( + prefs::kDiscoverTabSuggestionChipTimesLeftToShow, 0); +} + +} // namespace + +HelpAppZeroStateResult::HelpAppZeroStateResult(Profile* profile, + const std::string& id, + DisplayType display_type, + const std::u16string& title, + const std::u16string& details, + const gfx::ImageSkia& icon) + : profile_(profile) { + DCHECK(profile_); + set_id(id); + SetCategory(Category::kHelp); + SetTitle(title); + if (!details.empty()) + SetDetails(details); + // Show this in the first position, in front of any other chips that may be + // also claiming the first slot. + SetDisplayIndex(DisplayIndex::kFirstIndex); + SetPositionPriority(1.0f); + SetResultType(ResultType::kZeroStateHelpApp); + SetDisplayType(display_type); + // Some chips have different metrics types. + if (id == kHelpAppDiscoverResult) { + SetMetricsType(ash::HELP_APP_DISCOVER); + } else if (id == kHelpAppUpdatesResult) { + SetMetricsType(ash::HELP_APP_UPDATES); + } else { + SetMetricsType(ash::HELP_APP_DEFAULT); + } + SetChipIcon(icon); +} + +HelpAppZeroStateResult::~HelpAppZeroStateResult() = default; + +void HelpAppZeroStateResult::Open(int event_flags) { + // Note: event_flags is ignored, LaunchSWA doesn't need it. + if (id() == kHelpAppDiscoverResult) { + // Launch discover tab suggestion chip. + web_app::SystemAppLaunchParams params; + params.url = GURL("chrome://help-app/discover"); + params.launch_source = + apps::mojom::LaunchSource::kFromAppListRecommendation; + web_app::LaunchSystemWebAppAsync( + profile_, web_app::SystemAppType::HELP, params, + apps::MakeWindowInfo(display::kDefaultDisplayId)); + + StopShowingDiscoverTabSuggestionChip(profile_); + } else if (id() == kHelpAppUpdatesResult) { + // Launch release notes suggestion chip. + base::RecordAction( + base::UserMetricsAction("ReleaseNotes.SuggestionChipLaunched")); + + web_app::SystemAppLaunchParams params; + params.url = GURL("chrome://help-app/updates"); + params.launch_source = + apps::mojom::LaunchSource::kFromAppListRecommendation; + web_app::LaunchSystemWebAppAsync( + profile_, web_app::SystemAppType::HELP, params, + apps::MakeWindowInfo(display::kDefaultDisplayId)); + + ash::ReleaseNotesStorage(profile_).StopShowingSuggestionChip(); + } +} + +HelpAppZeroStateProvider::HelpAppZeroStateProvider( + Profile* profile, + ash::AppListNotifier* notifier) + : profile_(profile), notifier_(notifier) { + DCHECK(profile_); + + app_service_proxy_ = apps::AppServiceProxyFactory::GetForProfile(profile_); + Observe(&app_service_proxy_->AppRegistryCache()); + LoadIcon(); + + if (notifier_) + notifier_->AddObserver(this); +} + +HelpAppZeroStateProvider::~HelpAppZeroStateProvider() { + if (notifier_) + notifier_->RemoveObserver(this); +} + +void HelpAppZeroStateProvider::Start(const std::u16string& query) { + // TODO(crbug.com/1258415): Remove this when non-categorical search is + // removed. With categorical search enabled, `ClearResultsSilently()` is + // actually no-op, and the search controller already clears all results + // that need to be cleared when search query is updated. + ClearResultsSilently(); +} + +void HelpAppZeroStateProvider::StartZeroState() { + SearchProvider::Results search_results; + ClearResultsSilently(); + + if (ShouldShowDiscoverTabSuggestionChip(profile_)) { + search_results.emplace_back(std::make_unique<HelpAppZeroStateResult>( + profile_, kHelpAppDiscoverResult, DisplayType::kChip, + l10n_util::GetStringUTF16(IDS_HELP_APP_DISCOVER_TAB_SUGGESTION_CHIP), + /*details=*/u"", icon_)); + } else if (ash::ReleaseNotesStorage(profile_).ShouldShowSuggestionChip()) { + // With productivity launcher enabled, release notes are shown in continue + // section. + if (ash::features::IsProductivityLauncherEnabled()) { + auto* color_provider = ash::ColorProvider::Get(); + // NOTE: Color provider may not be set in unit tests. + SkColor icon_color = color_provider + ? color_provider->GetContentLayerColor( + ash::ColorProvider::ContentLayerType:: + kButtonIconColorPrimary) + : gfx::kGoogleGrey900; + gfx::ImageSkia icon = + gfx::CreateVectorIcon(ash::kReleaseNotesChipIcon, + app_list::kSystemIconDimension, icon_color); + search_results.emplace_back(std::make_unique<HelpAppZeroStateResult>( + profile_, kHelpAppUpdatesResult, DisplayType::kContinue, + l10n_util::GetStringUTF16(IDS_HELP_APP_WHATS_NEW_CONTINUE_TASK_TITLE), + l10n_util::GetStringUTF16( + IDS_HELP_APP_WHATS_NEW_CONTINUE_TASK_DETAILS), + icon)); + } else { + search_results.emplace_back(std::make_unique<HelpAppZeroStateResult>( + profile_, kHelpAppUpdatesResult, DisplayType::kChip, + l10n_util::GetStringUTF16(IDS_HELP_APP_WHATS_NEW_SUGGESTION_CHIP), + /*details=*/u"", icon_)); + } + } + + SwapResults(&search_results); +} + +ash::AppListSearchResultType HelpAppZeroStateProvider::ResultType() const { + return ash::AppListSearchResultType::kZeroStateHelpApp; +} + +bool HelpAppZeroStateProvider::ShouldBlockZeroState() const { + return true; +} + +void HelpAppZeroStateProvider::OnAppUpdate(const apps::AppUpdate& update) { + if (update.AppId() == web_app::kHelpAppId && update.ReadinessChanged() && + update.Readiness() == apps::Readiness::kReady) { + LoadIcon(); + } +} + +void HelpAppZeroStateProvider::OnAppRegistryCacheWillBeDestroyed( + apps::AppRegistryCache* cache) { + Observe(nullptr); +} + +void HelpAppZeroStateProvider::OnImpression( + ash::AppListNotifier::Location location, + const std::vector<ash::AppListNotifier::Result>& results, + const std::u16string& query) { + if (location != ash::AppListNotifier::Location::kChip && + location != ash::AppListNotifier::Location::kContinue) { + return; + } + + for (const auto& result : results) { + if (result.id == kHelpAppDiscoverResult) { + DecreaseTimesLeftToShowDiscoverTabSuggestionChip(profile_); + } else if (result.id == kHelpAppUpdatesResult) { + ash::ReleaseNotesStorage(profile_) + .DecreaseTimesLeftToShowSuggestionChip(); + } + } +} + +void HelpAppZeroStateProvider::OnLoadIcon(apps::IconValuePtr icon_value) { + if (icon_value && icon_value->icon_type == apps::IconType::kStandard) { + icon_ = icon_value->uncompressed; + } +} + +void HelpAppZeroStateProvider::LoadIcon() { + auto app_type = + app_service_proxy_->AppRegistryCache().GetAppType(web_app::kHelpAppId); + + if (base::FeatureList::IsEnabled(features::kAppServiceLoadIconWithoutMojom)) { + app_service_proxy_->LoadIcon( + app_type, web_app::kHelpAppId, apps::IconType::kStandard, + ash::SharedAppListConfig::instance().suggestion_chip_icon_dimension(), + /*allow_placeholder_icon=*/false, + base::BindOnce(&HelpAppZeroStateProvider::OnLoadIcon, + weak_factory_.GetWeakPtr())); + } else { + app_service_proxy_->LoadIcon( + apps::ConvertAppTypeToMojomAppType(app_type), web_app::kHelpAppId, + apps::mojom::IconType::kStandard, + ash::SharedAppListConfig::instance().suggestion_chip_icon_dimension(), + /*allow_placeholder_icon=*/false, + apps::MojomIconValueToIconValueCallback( + base::BindOnce(&HelpAppZeroStateProvider::OnLoadIcon, + weak_factory_.GetWeakPtr()))); + } +} + +} // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/help_app_zero_state_provider.h b/chrome/browser/ui/app_list/search/help_app_zero_state_provider.h new file mode 100644 index 0000000..32271b64 --- /dev/null +++ b/chrome/browser/ui/app_list/search/help_app_zero_state_provider.h
@@ -0,0 +1,92 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_HELP_APP_ZERO_STATE_PROVIDER_H_ +#define CHROME_BROWSER_UI_APP_LIST_SEARCH_HELP_APP_ZERO_STATE_PROVIDER_H_ + +#include <string> +#include <vector> + +#include "ash/public/cpp/app_list/app_list_notifier.h" +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" +#include "chrome/browser/apps/app_service/app_service_proxy_forward.h" +#include "chrome/browser/ui/app_list/search/chrome_search_result.h" +#include "chrome/browser/ui/app_list/search/search_provider.h" +#include "components/services/app_service/public/cpp/app_registry_cache.h" +#include "components/services/app_service/public/cpp/icon_types.h" + +class Profile; + +namespace gfx { +class ImageSkia; +} // namespace gfx + +namespace app_list { + +// Search results for the Help App (aka Explore). +class HelpAppZeroStateResult : public ChromeSearchResult { + public: + HelpAppZeroStateResult(Profile* profile, + const std::string& id, + DisplayType display_type, + const std::u16string& title, + const std::u16string& details, + const gfx::ImageSkia& icon); + + ~HelpAppZeroStateResult() override; + + HelpAppZeroStateResult(const HelpAppZeroStateResult&) = delete; + HelpAppZeroStateResult& operator=(const HelpAppZeroStateResult&) = delete; + + // ChromeSearchResult overrides: + void Open(int event_flags) override; + + private: + Profile* const profile_; +}; + +// Provides zero-state results from the Help App. +class HelpAppZeroStateProvider : public SearchProvider, + public apps::AppRegistryCache::Observer, + public ash::AppListNotifier::Observer { + public: + HelpAppZeroStateProvider(Profile* profile, ash::AppListNotifier* notifier); + ~HelpAppZeroStateProvider() override; + + HelpAppZeroStateProvider(const HelpAppZeroStateProvider&) = delete; + HelpAppZeroStateProvider& operator=(const HelpAppZeroStateProvider&) = delete; + + // SearchProvider: + void Start(const std::u16string& query) override; + void StartZeroState() override; + ash::AppListSearchResultType ResultType() const override; + bool ShouldBlockZeroState() const override; + + // apps::AppRegistryCache::Observer: + void OnAppUpdate(const apps::AppUpdate& update) override; + void OnAppRegistryCacheWillBeDestroyed( + apps::AppRegistryCache* cache) override; + + // ash::AppListNotifier::Observer: + void OnImpression(ash::AppListNotifier::Location location, + const std::vector<ash::AppListNotifier::Result>& results, + const std::u16string& query) override; + + private: + void OnLoadIcon(apps::IconValuePtr icon_value); + void LoadIcon(); + + Profile* const profile_; + ash::AppListNotifier* const notifier_; + + apps::AppServiceProxy* app_service_proxy_; + gfx::ImageSkia icon_; + + base::WeakPtrFactory<HelpAppZeroStateProvider> weak_factory_{this}; +}; + +} // namespace app_list + +#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_HELP_APP_ZERO_STATE_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/help_app_provider_unittest.cc b/chrome/browser/ui/app_list/search/help_app_zero_state_provider_unittest.cc similarity index 86% rename from chrome/browser/ui/app_list/search/help_app_provider_unittest.cc rename to chrome/browser/ui/app_list/search/help_app_zero_state_provider_unittest.cc index 3e2e5e4..93c349a 100644 --- a/chrome/browser/ui/app_list/search/help_app_provider_unittest.cc +++ b/chrome/browser/ui/app_list/search/help_app_zero_state_provider_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/app_list/search/help_app_provider.h" +#include "chrome/browser/ui/app_list/search/help_app_zero_state_provider.h" #include <memory> #include <string> @@ -36,7 +36,8 @@ EXPECT_EQ( l10n_util::GetStringUTF16(IDS_HELP_APP_DISCOVER_TAB_SUGGESTION_CHIP), result->title()); - EXPECT_EQ(ash::AppListSearchResultType::kHelpApp, result->result_type()); + EXPECT_EQ(ash::AppListSearchResultType::kZeroStateHelpApp, + result->result_type()); EXPECT_EQ(ash::SearchResultDisplayType::kChip, result->display_type()); } @@ -45,17 +46,19 @@ ash::SearchResultDisplayType display_type) { EXPECT_EQ(kReleaseNotesResultId, result->id()); EXPECT_EQ(l10n_util::GetStringUTF16(title_id), result->title()); - EXPECT_EQ(ash::AppListSearchResultType::kHelpApp, result->result_type()); + EXPECT_EQ(ash::AppListSearchResultType::kZeroStateHelpApp, + result->result_type()); EXPECT_EQ(display_type, result->display_type()); } } // namespace // Parameterized by whether ProductivityLauncher feature is enabled. -class HelpAppProviderTest : public AppListTestBase, - public ::testing::WithParamInterface<bool> { +class HelpAppZeroStateProviderTest + : public AppListTestBase, + public ::testing::WithParamInterface<bool> { public: - HelpAppProviderTest() { + HelpAppZeroStateProviderTest() { if (GetParam()) { scoped_feature_list_.InitWithFeatures( /*enabled_features=*/{chromeos::features::kHelpAppDiscoverTab, @@ -70,7 +73,7 @@ /*disabled_features=*/{ash::features::kProductivityLauncher}); } } - ~HelpAppProviderTest() override = default; + ~HelpAppZeroStateProviderTest() override = default; void SetUp() override { AppListTestBase::SetUp(); @@ -83,8 +86,8 @@ std::make_unique<AppListNotifierImplOld>(&app_list_controller_); } - provider_ = - std::make_unique<HelpAppProvider>(profile(), app_list_notifier_.get()); + provider_ = std::make_unique<HelpAppZeroStateProvider>( + profile(), app_list_notifier_.get()); provider_->set_controller(&search_controller_); } @@ -113,22 +116,23 @@ ash::AppListNotifier* app_list_notifier() { return app_list_notifier_.get(); } - HelpAppProvider* provider() { return provider_.get(); } + HelpAppZeroStateProvider* provider() { return provider_.get(); } private: ::test::TestAppListController app_list_controller_; std::unique_ptr<ash::AppListNotifier> app_list_notifier_; TestSearchController search_controller_; - std::unique_ptr<HelpAppProvider> provider_; + std::unique_ptr<HelpAppZeroStateProvider> provider_; base::test::ScopedFeatureList scoped_feature_list_; }; INSTANTIATE_TEST_SUITE_P(ProductivityLauncher, - HelpAppProviderTest, + HelpAppZeroStateProviderTest, testing::Bool()); // Test for empty query. -TEST_P(HelpAppProviderTest, HasNoResultsForEmptyQueryIfTimesLeftToShowIsZero) { +TEST_P(HelpAppZeroStateProviderTest, + HasNoResultsForEmptyQueryIfTimesLeftToShowIsZero) { profile()->GetPrefs()->SetInteger( prefs::kDiscoverTabSuggestionChipTimesLeftToShow, 0); profile()->GetPrefs()->SetInteger( @@ -139,7 +143,7 @@ EXPECT_TRUE(GetLatestResults().empty()); } -TEST_P(HelpAppProviderTest, +TEST_P(HelpAppZeroStateProviderTest, ReturnsDiscoverTabChipForEmptyQueryIfTimesLeftIsPositive) { profile()->GetPrefs()->SetInteger( prefs::kDiscoverTabSuggestionChipTimesLeftToShow, 1); @@ -156,7 +160,7 @@ ExpectDiscoverTabChip(result); } -TEST_P(HelpAppProviderTest, +TEST_P(HelpAppZeroStateProviderTest, ReturnsReleaseNotesChipForEmptyQueryIfTimesLeftIsPositive) { profile()->GetPrefs()->SetInteger( prefs::kDiscoverTabSuggestionChipTimesLeftToShow, 0); @@ -171,7 +175,7 @@ GetExpectedReleaseNotesDisplayType()); } -TEST_P(HelpAppProviderTest, PrioritizesDiscoverTabChipForEmptyQuery) { +TEST_P(HelpAppZeroStateProviderTest, PrioritizesDiscoverTabChipForEmptyQuery) { profile()->GetPrefs()->SetInteger( prefs::kDiscoverTabSuggestionChipTimesLeftToShow, 1); profile()->GetPrefs()->SetInteger( @@ -190,7 +194,7 @@ } } -TEST_P(HelpAppProviderTest, +TEST_P(HelpAppZeroStateProviderTest, DecrementsTimesLeftToShowDiscoverTabChipUponShowing) { profile()->GetPrefs()->SetInteger( prefs::kDiscoverTabSuggestionChipTimesLeftToShow, 3); @@ -223,7 +227,7 @@ prefs::kDiscoverTabSuggestionChipTimesLeftToShow)); } -TEST_P(HelpAppProviderTest, +TEST_P(HelpAppZeroStateProviderTest, DecrementsTimesLeftToShowReleaseNotesChipUponShowing) { profile()->GetPrefs()->SetInteger( prefs::kReleaseNotesSuggestionChipTimesLeftToShow, 3); @@ -262,7 +266,8 @@ prefs::kReleaseNotesSuggestionChipTimesLeftToShow)); } -TEST_P(HelpAppProviderTest, ClickingDiscoverTabChipStopsItFromShowing) { +TEST_P(HelpAppZeroStateProviderTest, + ClickingDiscoverTabChipStopsItFromShowing) { profile()->GetPrefs()->SetInteger( prefs::kDiscoverTabSuggestionChipTimesLeftToShow, 3); @@ -281,7 +286,8 @@ prefs::kDiscoverTabSuggestionChipTimesLeftToShow)); } -TEST_P(HelpAppProviderTest, ClickingReleaseNotesChipStopsItFromShowing) { +TEST_P(HelpAppZeroStateProviderTest, + ClickingReleaseNotesChipStopsItFromShowing) { profile()->GetPrefs()->SetInteger( prefs::kReleaseNotesSuggestionChipTimesLeftToShow, 3); @@ -294,24 +300,25 @@ prefs::kReleaseNotesSuggestionChipTimesLeftToShow)); } -class HelpAppProviderWithDiscoverTabDisabledTest : public HelpAppProviderTest { +class HelpAppZeroStateProviderWithDiscoverTabDisabledTest + : public HelpAppZeroStateProviderTest { public: - HelpAppProviderWithDiscoverTabDisabledTest() { + HelpAppZeroStateProviderWithDiscoverTabDisabledTest() { scoped_feature_list_.InitWithFeatures( /*enabled_features=*/{chromeos::features::kReleaseNotesSuggestionChip}, /*disabled_features=*/{chromeos::features::kHelpAppDiscoverTab}); } - ~HelpAppProviderWithDiscoverTabDisabledTest() override = default; + ~HelpAppZeroStateProviderWithDiscoverTabDisabledTest() override = default; private: base::test::ScopedFeatureList scoped_feature_list_; }; INSTANTIATE_TEST_SUITE_P(ProductivityLauncher, - HelpAppProviderWithDiscoverTabDisabledTest, + HelpAppZeroStateProviderWithDiscoverTabDisabledTest, testing::Bool()); -TEST_P(HelpAppProviderWithDiscoverTabDisabledTest, +TEST_P(HelpAppZeroStateProviderWithDiscoverTabDisabledTest, DoesNotReturnDiscoverTabChipForEmptyQuery) { profile()->GetPrefs()->SetInteger( prefs::kDiscoverTabSuggestionChipTimesLeftToShow, 1);
diff --git a/chrome/browser/ui/app_list/search/ranking/continue_ranker.cc b/chrome/browser/ui/app_list/search/ranking/continue_ranker.cc index 4673ec5..e2d11b811 100644 --- a/chrome/browser/ui/app_list/search/ranking/continue_ranker.cc +++ b/chrome/browser/ui/app_list/search/ranking/continue_ranker.cc
@@ -25,7 +25,7 @@ } else if (provider == ProviderType::kZeroStateDrive) { for (auto& result : it->second) result->scoring().continue_rank = 2; - } else if (provider == ProviderType::kHelpApp) { + } else if (provider == ProviderType::kZeroStateHelpApp) { for (auto& result : it->second) result->scoring().continue_rank = 3; }
diff --git a/chrome/browser/ui/app_list/search/ranking/util.cc b/chrome/browser/ui/app_list/search/ranking/util.cc index 32b4b604..e4a24f16 100644 --- a/chrome/browser/ui/app_list/search/ranking/util.cc +++ b/chrome/browser/ui/app_list/search/ranking/util.cc
@@ -53,6 +53,7 @@ case ResultType::kPersonalization: return Category::kSettings; case ResultType::kHelpApp: + case ResultType::kZeroStateHelpApp: case ResultType::kKeyboardShortcut: return Category::kHelp; case ResultType::kPlayStoreReinstallApp:
diff --git a/chrome/browser/ui/app_list/search/search_controller_factory.cc b/chrome/browser/ui/app_list/search/search_controller_factory.cc index c3ee67bd..3ded2a2 100644 --- a/chrome/browser/ui/app_list/search/search_controller_factory.cc +++ b/chrome/browser/ui/app_list/search/search_controller_factory.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/ui/app_list/search/files/zero_state_file_provider.h" #include "chrome/browser/ui/app_list/search/games/game_provider.h" #include "chrome/browser/ui/app_list/search/help_app_provider.h" +#include "chrome/browser/ui/app_list/search/help_app_zero_state_provider.h" #include "chrome/browser/ui/app_list/search/keyboard_shortcut_provider.h" #include "chrome/browser/ui/app_list/search/mixer.h" #include "chrome/browser/ui/app_list/search/omnibox_lacros_provider.h" @@ -188,7 +189,13 @@ size_t help_app_group_id = controller->AddGroup(kGenericMaxResults); controller->AddProvider(help_app_group_id, - std::make_unique<HelpAppProvider>(profile, notifier)); + std::make_unique<HelpAppProvider>(profile)); + + size_t help_app_zero_state_group_id = + controller->AddGroup(kGenericMaxResults); + controller->AddProvider( + help_app_zero_state_group_id, + std::make_unique<HelpAppZeroStateProvider>(profile, notifier)); if (search_features::IsLauncherGameSearchEnabled()) { size_t games_group_id = controller->AddGroup(kGenericMaxResults);
diff --git a/chrome/browser/ui/app_list/search/search_controller_impl_new.cc b/chrome/browser/ui/app_list/search/search_controller_impl_new.cc index f23711d..5021295 100644 --- a/chrome/browser/ui/app_list/search/search_controller_impl_new.cc +++ b/chrome/browser/ui/app_list/search/search_controller_impl_new.cc
@@ -46,6 +46,7 @@ switch (type) { case ash::AppListSearchResultType::kZeroStateFile: case ash::AppListSearchResultType::kZeroStateDrive: + case ash::AppListSearchResultType::kZeroStateHelpApp: return true; case ash::AppListSearchResultType::kUnknown: case ash::AppListSearchResultType::kInstalledApp:
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc b/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc index 75821906..958abe5 100644 --- a/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc +++ b/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc
@@ -39,6 +39,7 @@ case ash::AppListSearchResultType::kPersonalization: // Types that are only shown in the productivity launcher: case ash::AppListSearchResultType::kHelpApp: + case ash::AppListSearchResultType::kZeroStateHelpApp: case ash::AppListSearchResultType::kKeyboardShortcut: case ash::AppListSearchResultType::kOpenTab: // NOTE: We don't rank results of type kAssistantChip, kAssistantText
diff --git a/chrome/browser/ui/ash/capture_mode/recording_service_browsertest.cc b/chrome/browser/ui/ash/capture_mode/recording_service_browsertest.cc index 0491ef5..374d059a 100644 --- a/chrome/browser/ui/ash/capture_mode/recording_service_browsertest.cc +++ b/chrome/browser/ui/ash/capture_mode/recording_service_browsertest.cc
@@ -39,6 +39,11 @@ // Runs a loop for the given |milliseconds| duration. void WaitForMilliseconds(int milliseconds) { +#if defined(MEMORY_SANITIZER) + // MSAN runs much slower than regular tests, so give it more time to complete + milliseconds *= 2; +#endif + base::RunLoop loop; base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, loop.QuitClosure(), base::Milliseconds(milliseconds)); @@ -176,25 +181,13 @@ std::unique_ptr<ui::test::EventGenerator> event_generator_; }; -// Failing on ChromiumOS MSAN. https://crbug.com/1315067 -#if defined(MEMORY_SANITIZER) -#define MAYBE_RecordFullscreen DISABLED_RecordFullscreen -#else -#define MAYBE_RecordFullscreen RecordFullscreen -#endif -IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest, MAYBE_RecordFullscreen) { +IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest, RecordFullscreen) { ash::CaptureModeTestApi test_api; test_api.StartForFullscreen(/*for_video=*/true); FinishVideoRecordingTest(&test_api); } -// Failing on ChromiumOS MSAN. https://crbug.com/1315067 -#if defined(MEMORY_SANITIZER) -#define MAYBE_RecordWindow DISABLED_RecordWindow -#else -#define MAYBE_RecordWindow RecordWindow -#endif -IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest, MAYBE_RecordWindow) { +IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest, RecordWindow) { ash::CaptureModeTestApi test_api; test_api.StartForWindow(/*for_video=*/true); auto* generator = GetEventGenerator(); @@ -255,13 +248,7 @@ VerifyVideoFileAndDelete(video_path); } -// Failing on ChromiumOS MSAN. https://crbug.com/1315067 -#if defined(MEMORY_SANITIZER) -#define MAYBE_RecordRegion DISABLED_RecordRegion -#else -#define MAYBE_RecordRegion RecordRegion -#endif -IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest, MAYBE_RecordRegion) { +IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest, RecordRegion) { ash::CaptureModeTestApi test_api; test_api.StartForRegion(/*for_video=*/true); // Select a random partial region of the screen. @@ -269,15 +256,8 @@ FinishVideoRecordingTest(&test_api); } -// Failing on ChromiumOS MSAN. https://crbug.com/1315067 -#if defined(MEMORY_SANITIZER) -#define MAYBE_RecordingServiceEndpointDropped \ - DISABLED_RecordingServiceEndpointDropped -#else -#define MAYBE_RecordingServiceEndpointDropped RecordingServiceEndpointDropped -#endif IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest, - MAYBE_RecordingServiceEndpointDropped) { + RecordingServiceEndpointDropped) { ash::CaptureModeTestApi test_api; test_api.StartForFullscreen(/*for_video=*/true); test_api.PerformCapture(); @@ -288,17 +268,8 @@ VerifyVideoFileAndDelete(video_path); } -// TODO(crbug.com/1313907): Flaky on ash-chrome w/ SwANGLE and MSAN -#if defined(MEMORY_SANITIZER) -#define MAYBE_RecordingServiceClientEndpointDropped \ - DISABLED_RecordingServiceClientEndpointDropped -#else -#define MAYBE_RecordingServiceClientEndpointDropped \ - RecordingServiceClientEndpointDropped -#endif - IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest, - MAYBE_RecordingServiceClientEndpointDropped) { + RecordingServiceClientEndpointDropped) { ash::CaptureModeTestApi test_api; test_api.StartForFullscreen(/*for_video=*/true); test_api.PerformCapture(); @@ -313,16 +284,7 @@ VerifyVideoFileAndDelete(video_path, /*allow_empty=*/true); } -// Doing multiple recordings one after the other should produce non-corrupt webm -// files (i.e. the recording service should send webm chunks that are not -// affected by buffered chunks from a previous recording). -// Failing on ChromiumOS MSAN. https://crbug.com/1315067 -#if defined(MEMORY_SANITIZER) -#define MAYBE_SuccessiveRecording DISABLED_SuccessiveRecording -#else -#define MAYBE_SuccessiveRecording SuccessiveRecording -#endif -IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest, MAYBE_SuccessiveRecording) { +IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest, SuccessiveRecording) { ash::CaptureModeTestApi test_api; // Do a fullscreen recording, followed by a region recording. test_api.StartForFullscreen(/*for_video=*/true); @@ -332,18 +294,9 @@ FinishVideoRecordingTest(&test_api); } -// TODO(crbug.com/1313907): Flaky on ash-chrome w/ SwANGLE and MSAN -#if defined(MEMORY_SANITIZER) -#define MAYBE_RecordingInterruptedOnCaptureLocked \ - DISABLED_RecordingInterruptedOnCaptureLocked -#else -#define MAYBE_RecordingInterruptedOnCaptureLocked \ - RecordingInterruptedOnCaptureLocked -#endif - // Tests that recording will be interrupted once screen capture becomes locked. IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest, - MAYBE_RecordingInterruptedOnCaptureLocked) { + RecordingInterruptedOnCaptureLocked) { ash::CaptureModeTestApi test_api; test_api.StartForFullscreen(/*for_video=*/true); test_api.PerformCapture(); @@ -354,18 +307,7 @@ VerifyVideoFileAndDelete(video_path); } -// Tests that an invalid downloads path set in the browser settings (such as one -// that points to a location in a non-existing removable device) won't affect -// where the recordings are saved, and the recording file will be successfully -// saved. https://crbug.com/1192406. -// Failing on ChromiumOS MSAN. https://crbug.com/1315067 -#if defined(MEMORY_SANITIZER) -#define MAYBE_InvalidDownloadsPath DISABLED_InvalidDownloadsPath -#else -#define MAYBE_InvalidDownloadsPath InvalidDownloadsPath -#endif -IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest, - MAYBE_InvalidDownloadsPath) { +IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest, InvalidDownloadsPath) { auto* download_prefs = DownloadPrefs::FromBrowserContext(browser()->profile()); const base::FilePath removable_path =
diff --git a/chrome/browser/ui/ash/shelf/app_service/exo_app_type_resolver.cc b/chrome/browser/ui/ash/shelf/app_service/exo_app_type_resolver.cc index 0b175483..7f42cb6e 100644 --- a/chrome/browser/ui/ash/shelf/app_service/exo_app_type_resolver.cc +++ b/chrome/browser/ui/ash/shelf/app_service/exo_app_type_resolver.cc
@@ -50,8 +50,6 @@ params.app_id); const int32_t restore_window_id = app_restore::GetLacrosRestoreWindowId(params.app_id); - out_properties_container.SetProperty(app_restore::kRestoreWindowIdKey, - restore_window_id); out_properties_container.SetProperty( app_restore::kParentToHiddenContainerKey, restore_window_id == app_restore::kParentToHiddenContainer);
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 9b36031..f52b2c3 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -2918,6 +2918,21 @@ } #endif +bool Browser::PictureInPictureBrowserSupportsWindowFeature( + WindowFeature feature, + bool check_can_support) const { + switch (feature) { + case FEATURE_TITLEBAR: + return true; + case FEATURE_LOCATIONBAR: + case FEATURE_TABSTRIP: + case FEATURE_TOOLBAR: + case FEATURE_BOOKMARKBAR: + case FEATURE_NONE: + return false; + } +} + bool Browser::SupportsWindowFeatureImpl(WindowFeature feature, bool check_can_support) const { switch (type_) { @@ -2937,6 +2952,9 @@ case TYPE_CUSTOM_TAB: return CustomTabBrowserSupportsWindowFeature(feature); #endif + case TYPE_PICTURE_IN_PICTURE: + return PictureInPictureBrowserSupportsWindowFeature(feature, + check_can_support); } }
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index 0f29638f..631c30c 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h
@@ -150,6 +150,10 @@ // CustomTabToolbarview. TYPE_CUSTOM_TAB, #endif + // Document picture-in-picture browser. It's mostly the same as a + // TYPE_POPUP, except that it floats above other windows. It also has some + // additional restrictions, like it cannot navigated, to prevent misuse. + TYPE_PICTURE_IN_PICTURE, // If you add a new type, consider updating the test // BrowserTest.StartMaximized. }; @@ -698,6 +702,9 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) bool is_type_custom_tab() const { return type_ == TYPE_CUSTOM_TAB; } #endif + bool is_type_picture_in_picture() const { + return type_ == TYPE_PICTURE_IN_PICTURE; + } // True when the mouse cursor is locked. bool IsMouseLocked() const; @@ -1074,6 +1081,10 @@ bool CustomTabBrowserSupportsWindowFeature(WindowFeature feature) const; #endif + bool PictureInPictureBrowserSupportsWindowFeature( + WindowFeature feature, + bool check_can_support) const; + // Implementation of SupportsWindowFeature and CanSupportWindowFeature. If // |check_fullscreen| is true, the set of features reflect the actual state of // the browser, otherwise the set of features reflect the possible state of
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index 48cbe80..1826bbe 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -1517,13 +1517,20 @@ // set_show_state(ui::SHOW_STATE_MAXIMIZED) has been invoked. IN_PROC_BROWSER_TEST_F(BrowserTest, StartMaximized) { Browser::CreateParams params[] = { - Browser::CreateParams(Browser::TYPE_NORMAL, browser()->profile(), true), - Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(), true), - Browser::CreateParams::CreateForApp("app_name", true, gfx::Rect(), - browser()->profile(), true), - Browser::CreateParams::CreateForDevTools(browser()->profile()), - Browser::CreateParams::CreateForAppPopup("app_name", true, gfx::Rect(), - browser()->profile(), true)}; + Browser::CreateParams(Browser::TYPE_NORMAL, browser()->profile(), true), + Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(), true), + Browser::CreateParams::CreateForApp("app_name", true, gfx::Rect(), + browser()->profile(), true), + Browser::CreateParams::CreateForDevTools(browser()->profile()), + Browser::CreateParams::CreateForAppPopup("app_name", true, gfx::Rect(), + browser()->profile(), true), +#if !BUILDFLAG(IS_CHROMEOS_LACROS) + // Picture in picture v2 is not supported yet. + // See crbug.com/1320453 . + Browser::CreateParams(Browser::TYPE_PICTURE_IN_PICTURE, + browser()->profile(), true), +#endif + }; for (size_t i = 0; i < std::size(params); ++i) { params[i].initial_show_state = ui::SHOW_STATE_MAXIMIZED; AddBlankTabAndShow(Browser::Create(params[i])); @@ -1534,13 +1541,19 @@ // set_show_state(ui::SHOW_STATE_MINIMIZED) has been invoked. IN_PROC_BROWSER_TEST_F(BrowserTest, StartMinimized) { Browser::CreateParams params[] = { - Browser::CreateParams(Browser::TYPE_NORMAL, browser()->profile(), true), - Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(), true), - Browser::CreateParams::CreateForApp("app_name", true, gfx::Rect(), - browser()->profile(), true), - Browser::CreateParams::CreateForDevTools(browser()->profile()), - Browser::CreateParams::CreateForAppPopup("app_name", true, gfx::Rect(), - browser()->profile(), true)}; + Browser::CreateParams(Browser::TYPE_NORMAL, browser()->profile(), true), + Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(), true), + Browser::CreateParams::CreateForApp("app_name", true, gfx::Rect(), + browser()->profile(), true), + Browser::CreateParams::CreateForDevTools(browser()->profile()), + Browser::CreateParams::CreateForAppPopup("app_name", true, gfx::Rect(), + browser()->profile(), true), +#if !BUILDFLAG(IS_CHROMEOS_LACROS) + // Picture in picture v2 is not supported yet. + Browser::CreateParams(Browser::TYPE_PICTURE_IN_PICTURE, + browser()->profile(), true), +#endif // !IS_CHROMEOS_LACROS + }; for (size_t i = 0; i < std::size(params); ++i) { params[i].initial_show_state = ui::SHOW_STATE_MINIMIZED; AddBlankTabAndShow(Browser::Create(params[i])); @@ -2947,3 +2960,11 @@ EXPECT_TRUE(back_observer.has_committed()); EXPECT_FALSE(back_observer.was_same_document()); } + +#if !BUILDFLAG(IS_CHROMEOS_LACROS) +IN_PROC_BROWSER_TEST_F(BrowserTest, CreatePictureInPicture) { + Browser* popup_browser = Browser::Create(Browser::CreateParams( + Browser::TYPE_PICTURE_IN_PICTURE, browser()->profile(), true)); + ASSERT_TRUE(popup_browser->is_type_picture_in_picture()); +} +#endif // !IS_CHROMEOS_LACROS
diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc index a1680f4..fd72594b 100644 --- a/chrome/browser/ui/browser_navigator.cc +++ b/chrome/browser/ui/browser_navigator.cc
@@ -11,6 +11,7 @@ #include "base/command_line.h" #include "base/memory/raw_ptr.h" +#include "base/notreached.h" #include "base/strings/utf_string_conversions.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" @@ -253,13 +254,33 @@ // re-run with NEW_WINDOW. return {GetOrCreateBrowser(profile, params.user_gesture), -1}; case WindowOpenDisposition::NEW_PICTURE_IN_PICTURE: +#if !BUILDFLAG(IS_CHROMEOS_LACROS) // Out of paranoia, check that the PictureInPictureV2 feature is actually // enabled as a browser feature before allowing the browser to create an // always-on-top window. This helps protect against a compromised // renderer. TODO(https://crbug.com/1285144): Remove this check once // the feature is no longer experimental. - CHECK(base::FeatureList::IsEnabled(features::kPictureInPictureV2)); - return {params.browser, -1}; + if (!base::FeatureList::IsEnabled(features::kPictureInPictureV2)) + return {nullptr, -1}; + + // Picture in picture windows may not be opened by other picture in + // picture windows. + if (params.browser->is_type_picture_in_picture()) + return {nullptr, -1}; + + { + Browser::CreateParams browser_params(Browser::TYPE_PICTURE_IN_PICTURE, + profile, params.user_gesture); + browser_params.trusted_source = params.trusted_source; + browser_params.initial_bounds = params.window_bounds; + return {Browser::Create(browser_params), -1}; + } +#else // !IS_CHROMEOS_LACROS + // Picture in picture 2.0 is turned off in lacros. + // See crbug.com/1320453 . + NOTIMPLEMENTED_LOG_ONCE() << "TYPE_PICTURE_IN_PICTURE for lacros"; + return {nullptr, -1}; +#endif // !IS_CHROMEOS_LACROS case WindowOpenDisposition::NEW_POPUP: { // Make a new popup window. // Coerce app-style if |source| represents an app. @@ -338,10 +359,10 @@ break; case WindowOpenDisposition::NEW_PICTURE_IN_PICTURE: - // Do nothing for a document PiP popup, it's handled via - // PictureInPictureController. - params->window_action = NavigateParams::NO_ACTION; + // Always show a new picture in picture window. + params->window_action = NavigateParams::SHOW_WINDOW; break; + case WindowOpenDisposition::NEW_WINDOW: case WindowOpenDisposition::NEW_POPUP: { // Code that wants to open a new window typically expects it to be shown @@ -436,10 +457,7 @@ ~ScopedBrowserShower() { BrowserWindow* window = params_->browser->window(); - if (params_->disposition == WindowOpenDisposition::NEW_PICTURE_IN_PICTURE) { - // Don't activate or focus the window, PictureInPictureManager - // takes care of that for a DocumentPictureInPictureWindowControllerImpl. - } else if (params_->window_action == NavigateParams::SHOW_WINDOW_INACTIVE) { + if (params_->window_action == NavigateParams::SHOW_WINDOW_INACTIVE) { window->ShowInactive(); } else if (params_->window_action == NavigateParams::SHOW_WINDOW) { window->Show(); @@ -741,11 +759,7 @@ (params->tabstrip_add_types & TabStripModel::ADD_INHERIT_OPENER)) params->source_contents->Focus(); - if (params->disposition == WindowOpenDisposition::NEW_PICTURE_IN_PICTURE) { - auto* mgr = PictureInPictureWindowManager::GetInstance(); - mgr->EnterDocumentPictureInPicture(params->source_contents, - std::move(contents_to_insert)); - } else if (params->source_contents == contents_to_navigate_or_insert) { + if (params->source_contents == contents_to_navigate_or_insert) { // The navigation occurred in the source tab. params->browser->UpdateUIForNavigationInTab( contents_to_navigate_or_insert, params->transition,
diff --git a/chrome/browser/ui/browser_navigator_browsertest.cc b/chrome/browser/ui/browser_navigator_browsertest.cc index addf212..a5ad0c56 100644 --- a/chrome/browser/ui/browser_navigator_browsertest.cc +++ b/chrome/browser/ui/browser_navigator_browsertest.cc
@@ -8,6 +8,7 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "chrome/app/chrome_command_ids.h" @@ -45,6 +46,7 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/bindings_policy.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/test_frame_navigation_observer.h" @@ -1871,4 +1873,52 @@ } #endif +#if !BUILDFLAG(IS_CHROMEOS_LACROS) +// Helper class to enable picture in picture V2 for those tests that need it. +// Once the feature is enabled permanently, these can be merged back to +// BrowserNavigatorTest instead. +// See crbug.com/1320453 for why this is off for lacros. +class BrowserNavigatorWithPictureInPictureTest : public BrowserNavigatorTest { + public: + base::test::ScopedFeatureList scoped_feature_list_{ + features::kPictureInPictureV2}; +}; + +IN_PROC_BROWSER_TEST_F(BrowserNavigatorWithPictureInPictureTest, + Disposition_PictureInPicture_Open) { + // Opening a picture in picture window should create a new browser. + NavigateParams params(MakeNavigateParams(browser())); + params.disposition = WindowOpenDisposition::NEW_PICTURE_IN_PICTURE; + Navigate(¶ms); + + // Should not re-use the browser. + EXPECT_NE(browser(), params.browser); + EXPECT_TRUE(params.browser->is_type_picture_in_picture()); +} + +IN_PROC_BROWSER_TEST_F(BrowserNavigatorWithPictureInPictureTest, + Disposition_PictureInPicture_CantFromAnotherPip) { + // Make sure that attempting to open a picture in picture window from a + // picture in picture window fails. + Browser* pip = CreateEmptyBrowserForType(Browser::TYPE_PICTURE_IN_PICTURE, + browser()->profile()); + NavigateParams params(MakeNavigateParams(pip)); + params.disposition = WindowOpenDisposition::NEW_PICTURE_IN_PICTURE; + Navigate(¶ms); + + EXPECT_EQ(params.browser, nullptr); +} + +IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, + Disposition_PictureInPicture_FeatureMustBeEnabled) { + // Creating a picture in picture window should not work if the feature is off. + ASSERT_FALSE(base::FeatureList::IsEnabled(features::kPictureInPictureV2)); + NavigateParams params(MakeNavigateParams(browser())); + params.disposition = WindowOpenDisposition::NEW_PICTURE_IN_PICTURE; + Navigate(¶ms); + + EXPECT_EQ(params.browser, nullptr); +} +#endif // !IS_CHROMEOS_LACROS + } // namespace
diff --git a/chrome/browser/ui/browser_window_state.cc b/chrome/browser/ui/browser_window_state.cc index 29c16d2..de8b5a0 100644 --- a/chrome/browser/ui/browser_window_state.cc +++ b/chrome/browser/ui/browser_window_state.cc
@@ -85,6 +85,7 @@ #endif return prefs::kBrowserWindowPlacement; case Browser::TYPE_POPUP: + case Browser::TYPE_PICTURE_IN_PICTURE: return prefs::kBrowserWindowPlacementPopup; case Browser::TYPE_APP: case Browser::TYPE_DEVTOOLS:
diff --git a/chrome/browser/ui/hid/hid_chooser_controller.cc b/chrome/browser/ui/hid/hid_chooser_controller.cc index f9f982a..8d812cd 100644 --- a/chrome/browser/ui/hid/hid_chooser_controller.cc +++ b/chrome/browser/ui/hid/hid_chooser_controller.cc
@@ -318,9 +318,21 @@ base::StringPrintf( "Chooser dialog is not displaying a device blocked by " "the HID blocklist: vendorId=%d, " - "productId=%d, name='%s', serial='%s'", + "productId=%d, name='%s', serial='%s', numberOfCollections=%zu, " + "numberOfProtectedInputReports=%zu, " + "numberOfProtectedOutputReports=%zu, " + "numberOfProtectedFeatureReports=%zu", device.vendor_id, device.product_id, device.product_name.c_str(), - device.serial_number.c_str())); + device.serial_number.c_str(), device.collections.size(), + device.protected_input_report_ids + ? device.protected_input_report_ids->size() + : 0, + device.protected_output_report_ids + ? device.protected_output_report_ids->size() + : 0, + device.protected_feature_report_ids + ? device.protected_feature_report_ids->size() + : 0)); return false; }
diff --git a/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc b/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc index 6a90a45..28a7229 100644 --- a/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc +++ b/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc
@@ -19,7 +19,6 @@ #include "components/embedder_support/switches.h" #include "components/javascript_dialogs/app_modal_dialog_manager.h" #include "components/javascript_dialogs/tab_modal_dialog_manager.h" -#include "components/ukm/content/source_url_recorder.h" #include "components/ukm/test_ukm_recorder.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ui/javascript_dialogs/javascript_tab_modal_dialog_manager_delegate_desktop.cc b/chrome/browser/ui/javascript_dialogs/javascript_tab_modal_dialog_manager_delegate_desktop.cc index 47e7bfb..6f8c2dfe 100644 --- a/chrome/browser/ui/javascript_dialogs/javascript_tab_modal_dialog_manager_delegate_desktop.cc +++ b/chrome/browser/ui/javascript_dialogs/javascript_tab_modal_dialog_manager_delegate_desktop.cc
@@ -16,7 +16,6 @@ #include "components/javascript_dialogs/tab_modal_dialog_manager.h" #include "components/javascript_dialogs/tab_modal_dialog_view.h" #include "components/navigation_metrics/navigation_metrics.h" -#include "components/ukm/content/source_url_recorder.h" #include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h"
diff --git a/chrome/browser/ui/views/frame/browser_frame.cc b/chrome/browser/ui/views/frame/browser_frame.cc index c445cef..0bfc7b1 100644 --- a/chrome/browser/ui/views/frame/browser_frame.cc +++ b/chrome/browser/ui/views/frame/browser_frame.cc
@@ -95,8 +95,12 @@ params.delegate = browser_view_; params.headless_mode = headless::IsChromeNativeHeadless(); + Browser* browser = browser_view_->browser(); + if (browser->is_type_picture_in_picture()) { + params.z_order = ui::ZOrderLevel::kFloatingWindow; + } + if (native_browser_frame_->ShouldRestorePreviousBrowserWidgetState()) { - Browser* browser = browser_view_->browser(); if (browser->is_type_normal() || browser->is_type_devtools() || browser->is_type_app()) { // Typed panel/popup can only return a size once the widget has been
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index e50b35f..ca22c595 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -812,6 +812,13 @@ // `create_params` to enable/disable specific size controls. if (chrome::IsRunningInForcedAppMode()) { SetHasWindowSizeControls(false); + } else if (GetIsPictureInPictureType()) { + // Picture in picture windows must always have a title, can never minimize, + // and can never maximize regardless of what the params say. + SetShowTitle(true); + SetCanMinimize(false); + SetCanMaximize(false); + SetCanResize(true); } else { SetCanResize(browser_->create_params().can_resize); SetCanMaximize(browser_->create_params().can_maximize); @@ -1165,6 +1172,10 @@ return web_app::AppBrowserController::IsWebApp(browser_.get()); } +bool BrowserView::GetIsPictureInPictureType() const { + return browser_->is_type_picture_in_picture(); +} + bool BrowserView::GetTopControlsSlideBehaviorEnabled() const { return top_controls_slide_controller_ && top_controls_slide_controller_->IsEnabled();
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index 1198262..edb58f65 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -313,6 +313,10 @@ // for an installed web app. bool GetIsWebAppType() const; + // Returns true if the Browser object associated with this BrowserView is for + // a Picture in Picture window. + bool GetIsPictureInPictureType() const; + // Returns true if the top browser controls (a.k.a. top-chrome UIs) are // allowed to slide up and down with the gesture scrolls on the current tab's // page.
diff --git a/chrome/browser/ui/views/frame/desktop_browser_frame_aura_linux.cc b/chrome/browser/ui/views/frame/desktop_browser_frame_aura_linux.cc index 48e3fdd..765ac82d 100644 --- a/chrome/browser/ui/views/frame/desktop_browser_frame_aura_linux.cc +++ b/chrome/browser/ui/views/frame/desktop_browser_frame_aura_linux.cc
@@ -80,8 +80,9 @@ } // Hosted app windows get a custom frame (if the desktop PWA experimental - // feature is enabled). - return browser_view()->GetIsWebAppType(); + // feature is enabled), or if the window is picture in picture. + return browser_view()->GetIsWebAppType() || + browser_view()->GetIsPictureInPictureType(); } void DesktopBrowserFrameAuraLinux::TabDraggingKindChanged(
diff --git a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc index 6a6138b7..ee9f353 100644 --- a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc +++ b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
@@ -265,6 +265,8 @@ auto default_header_background = PaymentRequestSheetController::GetHeaderBackground(header_view); if (web_contents() && header_view->GetWidget()) { + // Make sure the color is actually set before using it. + default_header_background->OnViewThemeChanged(header_view); return views::CreateSolidBackground(color_utils::GetResultingPaintColor( web_contents()->GetThemeColor().value_or(SK_ColorTRANSPARENT), default_header_background->get_color()));
diff --git a/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc b/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc index e0a6a6c..e3da148c 100644 --- a/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc +++ b/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc
@@ -246,6 +246,10 @@ DialogDelegate::SetCloseCallback( base::BindOnce(&PermissionPromptBubbleView::ClosingPermission, base::Unretained(this))); + } else if (prompt_style_ == PermissionPromptStyle::kChip || + prompt_style_ == PermissionPromptStyle::kQuietChip) { + // Override the `CloseCallback` if it was set previously. + DialogDelegate::SetCloseCallback(base::DoNothing()); } }
diff --git a/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc b/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc index 2f00f89..6b9c170c 100644 --- a/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc +++ b/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc
@@ -274,7 +274,7 @@ void PermissionPromptImpl::SelectNormalPrompt() { DCHECK(!delegate_->ShouldCurrentRequestUseQuietUI()); - if (ShouldCurrentRequestUseChip()) { + if (ShouldCurrentRequestUseChip() && IsLocationBarDisplayed()) { ShowChip(); } else { ShowBubble();
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 e0943c0..d8740f18 100644 --- a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc +++ b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
@@ -76,7 +76,7 @@ TabStripModel* tab_strip_model) : views::BubbleDialogDelegateView(anchor_view, views::BubbleBorder::Arrow::TOP_RIGHT), - idp_etld_plus_one_(base::ASCIIToUTF16(idp_etld_plus_one)), + idp_etld_plus_one_(base::UTF8ToUTF16(idp_etld_plus_one)), brand_text_color_(idp_metadata.brand_text_color), brand_background_color_(idp_metadata.brand_background_color), tab_strip_model_(tab_strip_model), @@ -90,7 +90,7 @@ set_close_on_deactivate(false); SetTitle(l10n_util::GetStringFUTF16( IDS_ACCOUNT_SELECTION_SHEET_TITLE_EXPLICIT, - base::ASCIIToUTF16(rp_etld_plus_one), idp_etld_plus_one_)); + base::UTF8ToUTF16(rp_etld_plus_one), idp_etld_plus_one_)); auto imageSkia = gfx::ImageSkia::CreateFrom1xBitmap(idp_metadata.brand_icon); SetIcon(imageSkia); SetShowIcon(true); @@ -128,7 +128,7 @@ base::BindRepeating(&AccountSelectionBubbleView::OnAccountSelected, weak_ptr_factory_.GetWeakPtr(), account), l10n_util::GetStringFUTF16(IDS_ACCOUNT_SELECTION_CONTINUE, - base::ASCIIToUTF16(display_name))); + base::UTF8ToUTF16(display_name))); button->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_CENTER); if (brand_background_color_) { button->SetBackground(views::CreateRoundedRectBackground( @@ -227,8 +227,8 @@ auto row = std::make_unique<HoverButton>( base::BindRepeating(&AccountSelectionBubbleView::OnSingleAccountPicked, weak_ptr_factory_.GetWeakPtr(), account), - std::move(image_view), base::ASCIIToUTF16(account.name), - base::ASCIIToUTF16(account.email)); + std::move(image_view), base::UTF8ToUTF16(account.name), + base::UTF8ToUTF16(account.email)); row->SetImageModel(views::Button::STATE_NORMAL, ui::ImageModel()); return row; } @@ -240,11 +240,11 @@ views::BoxLayout::Orientation::kVertical)); text_column ->AddChildView( - std::make_unique<views::Label>(base::ASCIIToUTF16(account.name))) + std::make_unique<views::Label>(base::UTF8ToUTF16(account.name))) ->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT); text_column ->AddChildView( - std::make_unique<views::Label>(base::ASCIIToUTF16(account.email))) + std::make_unique<views::Label>(base::UTF8ToUTF16(account.email))) ->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT); const views::LayoutProvider* provider = views::LayoutProvider::Get(); text_column->SetBorder(
diff --git a/chrome/browser/ui/webui/image_editor/image_editor_untrusted_ui.cc b/chrome/browser/ui/webui/image_editor/image_editor_untrusted_ui.cc index 055fd5d..8b4e359a 100644 --- a/chrome/browser/ui/webui/image_editor/image_editor_untrusted_ui.cc +++ b/chrome/browser/ui/webui/image_editor/image_editor_untrusted_ui.cc
@@ -16,7 +16,6 @@ #include "base/memory/scoped_refptr.h" #include "base/metrics/histogram_functions.h" #include "base/strings/string_piece.h" -#include "base/task/post_task.h" #include "base/task/sequenced_task_runner.h" #include "base/task/task_runner_util.h" #include "base/task/thread_pool.h"
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc index dd7ef21..88dd1a63 100644 --- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc +++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -65,7 +65,7 @@ #endif #if BUILDFLAG(ENABLE_SUPERVISED_USERS) -#include "chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.h" +#include "chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.h" // nogncheck #include "chrome/browser/supervised_user/supervised_user_interstitial.h" #endif
diff --git a/chrome/browser/user_education/java/src/org/chromium/chrome/browser/user_education/IPHCommandBuilder.java b/chrome/browser/user_education/java/src/org/chromium/chrome/browser/user_education/IPHCommandBuilder.java index 1bc5b0cd..5a3be4c4 100644 --- a/chrome/browser/user_education/java/src/org/chromium/chrome/browser/user_education/IPHCommandBuilder.java +++ b/chrome/browser/user_education/java/src/org/chromium/chrome/browser/user_education/IPHCommandBuilder.java
@@ -12,6 +12,7 @@ import androidx.annotation.StringRes; import org.chromium.base.TraceEvent; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.components.browser_ui.widget.highlight.ViewHighlighter.HighlightParams; import org.chromium.components.browser_ui.widget.textbubble.TextBubble; import org.chromium.ui.widget.AnchoredPopupWindow; @@ -219,19 +220,22 @@ mOnBlockedCallback = NO_OP_RUNNABLE; } + boolean disableIPH = !ChromeFeatureList.isEnabled(ChromeFeatureList.ENABLE_IPH); + if (mContentString == null) { assert mResources != null; - mContentString = mResources.getString(mStringId); + mContentString = disableIPH ? "" : mResources.getString(mStringId); } if (mAccessibilityText == null) { assert mResources != null; - mAccessibilityText = mResources.getString(mAccessibilityStringId); + mAccessibilityText = disableIPH ? "" : mResources.getString(mAccessibilityStringId); } if (mInsetRect == null && mAnchorRect == null) { - int yInsetPx = mResources.getDimensionPixelOffset( - R.dimen.iph_text_bubble_menu_anchor_y_inset); + int yInsetPx = disableIPH ? 14 + : mResources.getDimensionPixelOffset( + R.dimen.iph_text_bubble_menu_anchor_y_inset); mInsetRect = new Rect(0, 0, 0, yInsetPx); }
diff --git a/chrome/browser/user_education/java/src/org/chromium/chrome/browser/user_education/UserEducationHelperTest.java b/chrome/browser/user_education/java/src/org/chromium/chrome/browser/user_education/UserEducationHelperTest.java index d7cfa13..185f0be 100644 --- a/chrome/browser/user_education/java/src/org/chromium/chrome/browser/user_education/UserEducationHelperTest.java +++ b/chrome/browser/user_education/java/src/org/chromium/chrome/browser/user_education/UserEducationHelperTest.java
@@ -112,6 +112,7 @@ public void testShowIPHWithSnooze() throws Throwable { mTestValues.addFeatureFlagOverride(ChromeFeatureList.SNOOZABLE_IPH, true); mTestValues.addFeatureFlagOverride(ChromeFeatureList.ENABLE_AUTOMATIC_SNOOZE, false); + mTestValues.addFeatureFlagOverride(ChromeFeatureList.ENABLE_IPH, true); FeatureList.setTestValues(mTestValues); TestThreadUtils.runOnUiThreadBlocking(() -> { when(mTracker.shouldTriggerHelpUIWithSnooze(FeatureConstants.DOWNLOAD_HOME_FEATURE))
diff --git a/chrome/browser/webauthn/chrome_conditional_ui_delegate_android.h b/chrome/browser/webauthn/chrome_conditional_ui_delegate_android.h index b7480a13..4bb085c0 100644 --- a/chrome/browser/webauthn/chrome_conditional_ui_delegate_android.h +++ b/chrome/browser/webauthn/chrome_conditional_ui_delegate_android.h
@@ -9,14 +9,20 @@ #include "base/callback.h" #include "base/supports_user_data.h" -#include "device/fido/discoverable_credential_metadata.h" +#include "content/public/browser/conditional_ui_delegate_android.h" namespace content { class WebContents; } +namespace device { +class DiscoverableCredentialMetadata; +} + // Chrome implementation of ConditionalUiDelegateAndroid. -class ChromeConditionalUiDelegateAndroid : public base::SupportsUserData::Data { +class ChromeConditionalUiDelegateAndroid + : public base::SupportsUserData::Data, + public content::ConditionalUiDelegateAndroid { public: ChromeConditionalUiDelegateAndroid(); @@ -27,11 +33,11 @@ ~ChromeConditionalUiDelegateAndroid() override; - // TODO(kenrb): This will override a method in a content delegate interface - // in a subsequent change, so that it can be invoked from RenderFrameHost. + // content::ConditionalUiDelegateAndroid: void OnWebAuthnRequestPending( const std::vector<device::DiscoverableCredentialMetadata>& credentials, - base::OnceCallback<void(const std::vector<uint8_t>& user_id)> callback); + base::OnceCallback<void(const std::vector<uint8_t>& id)> callback) + override; // Tells the driver that the user has selected a Web Authentication // credential from a dialog, and provides the credential ID for the selected
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index c6fe86c..792f996 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1651233361-f94e7905e686c6ee3414a53a77d421e79edab0ab.profdata +chrome-linux-main-1651255096-c574ea1a61aa8b78e14d0d08e41da93dc94bcf46.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index ff371042..8c29c73 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1651233361-319a435485d0fc37a02b759d4e1c15a9a1a1a31c.profdata +chrome-mac-arm-main-1651255096-ffcdfc32ad3cf630f621bef102f00ada093c5f2f.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index a6751a4f..2211c81 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1651233361-16f6502d77d95ecb200c2fca308527b0a56a81f2.profdata +chrome-mac-main-1651255096-9b230e6402063fa251adb5034ca6c9bc51f462b2.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 809c9875..bf029d9 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1651244242-fa25134105722ca8621484acfa8a6fc3fa955c3f.profdata +chrome-win32-main-1651255096-f34242b1ab88688b95b959f76c3b656fb4906e44.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 0106bf41..f695975 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1651244242-aba4ad7cfef4e8bb79cfaa6cd9c1efdf81af88d5.profdata +chrome-win64-main-1651255096-ebac82a900983bd01c92359cdf8fe5c43f8ac58e.profdata
diff --git a/chrome/common/extensions/api/passwords_private.idl b/chrome/common/extensions/api/passwords_private.idl index bb82a16a..650eff9 100644 --- a/chrome/common/extensions/api/passwords_private.idl +++ b/chrome/common/extensions/api/passwords_private.idl
@@ -384,6 +384,15 @@ [supportsPromises] static void unmuteInsecureCredential( InsecureCredential credential, optional VoidCallback callback); + // Records that a change password flow was started for |credential|. + // |credential|: The credential for which the flow was triggered. + // |isAutomatedFlow|: Whether the flow is a manual one. + // Invokes |callback| on completion. + [supportsPromises] static void recordChangePasswordFlowStarted( + InsecureCredential credential, + boolean isManualFlow, + optional VoidCallback callback); + // Starts a check for insecure passwords. Invokes |callback| on completion. [supportsPromises] static void startPasswordCheck( optional VoidCallback callback);
diff --git a/chrome/renderer/media/chrome_key_systems.cc b/chrome/renderer/media/chrome_key_systems.cc index ff769b9..5871445 100644 --- a/chrome/renderer/media/chrome_key_systems.cc +++ b/chrome/renderer/media/chrome_key_systems.cc
@@ -351,7 +351,7 @@ } // namespace void GetChromeKeySystems(media::GetSupportedKeySystemsCB cb) { -#if BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) && BUILDFLAG(ENABLE_WIDEVINE) KeySystemPropertiesVector key_systems; cdm::AddAndroidWidevine(&key_systems); std::move(cb).Run(std::move(key_systems));
diff --git a/chrome/services/cups_proxy/ipp_attribute_validator.cc b/chrome/services/cups_proxy/ipp_attribute_validator.cc index 21bb5c2..76ed7c2 100644 --- a/chrome/services/cups_proxy/ipp_attribute_validator.cc +++ b/chrome/services/cups_proxy/ipp_attribute_validator.cc
@@ -10,14 +10,16 @@ #include <set> #include <string> -#include "base/containers/contains.h" +#include "base/containers/fixed_flat_map.h" +#include "base/containers/fixed_flat_set.h" +#include "base/strings/string_piece.h" #include "chrome/services/ipp_parser/public/mojom/ipp_parser.mojom.h" namespace cups_proxy { namespace { -using ValueType = ipp_parser::mojom::ValueType; +using ValueType = ipp_parser::mojom::IppAttributeValue::Tag; // Represents the type of a single attribute. struct AttributeDefinition { @@ -34,109 +36,118 @@ ValueType type, size_t values_count) { // Definitions of attributes used in IPP requests. - static const std::map<std::string, AttributeDefinition> kAttributeDefinitions{ - {"attributes-charset", {false, ValueType::STRING}}, - {"attributes-natural-language", {false, ValueType::STRING}}, - {"auth-info", {true, ValueType::STRING}}, - {"auth-info-required", {true, ValueType::STRING}}, - {"charset-configured", {false, ValueType::STRING}}, - {"compression", {false, ValueType::STRING}}, - {"copies", {false, ValueType::INTEGER}}, - {"document-format", {false, ValueType::STRING}}, - {"document-name", {false, ValueType::STRING}}, - {"finishings", {true, ValueType::INTEGER}}, - {"ipp-attribute-fidelity", {false, ValueType::BOOLEAN}}, - {"job-cancel-after", {false, ValueType::INTEGER}}, - {"job-hold-until", {false, ValueType::STRING}}, - {"job-id", {false, ValueType::INTEGER}}, - {"job-k-limit", {false, ValueType::INTEGER}}, - {"job-media-progress", {false, ValueType::INTEGER}}, - {"job-name", {false, ValueType::STRING}}, - {"job-originating-host-name", {false, ValueType::STRING}}, - {"job-originating-user-name", {false, ValueType::STRING}}, - {"job-page-limit", {false, ValueType::INTEGER}}, - {"job-password", {false, ValueType::OCTET}}, - {"job-printer-state-message", {false, ValueType::STRING}}, - {"job-printer-state-reasons", {true, ValueType::STRING}}, - {"job-printer-up-time", {false, ValueType::INTEGER}}, - {"job-printer-uri", {false, ValueType::STRING}}, - {"job-priority", {false, ValueType::INTEGER}}, - {"job-quota-period", {false, ValueType::INTEGER}}, - {"job-state", {false, ValueType::INTEGER}}, - {"job-state-reasons", {true, ValueType::STRING}}, - {"job-uri", {false, ValueType::STRING}}, - {"last-document", {false, ValueType::BOOLEAN}}, - {"limit", {false, ValueType::INTEGER}}, - {"marker-change-time", {false, ValueType::INTEGER}}, - {"marker-colors", {true, ValueType::STRING}}, - {"marker-high-levels", {true, ValueType::INTEGER}}, - {"marker-levels", {true, ValueType::INTEGER}}, - {"marker-low-levels", {true, ValueType::INTEGER}}, - {"marker-message", {false, ValueType::STRING}}, - {"marker-names", {true, ValueType::STRING}}, - {"marker-types", {true, ValueType::STRING}}, - {"media", {false, ValueType::STRING}}, - {"media-ready", {true, ValueType::STRING}}, - // This is not a PWG attribute but CUPS supports it for InputSlot - // selection. - {"media-source", {true, ValueType::STRING}}, - {"member-names", {true, ValueType::STRING}}, - {"member-uris", {true, ValueType::STRING}}, - {"multiple-document-handling", {false, ValueType::STRING}}, - {"my-jobs", {false, ValueType::BOOLEAN}}, - {"natural-language-configured", {false, ValueType::STRING}}, - {"number-up", {false, ValueType::INTEGER}}, - {"orientation-requested", {false, ValueType::INTEGER}}, - {"output-bin", {false, ValueType::STRING}}, - {"page-border", {false, ValueType::STRING}}, - {"page-ranges", {true, ValueType::INTEGER}}, - {"pages-per-minute", {false, ValueType::INTEGER}}, - {"pages-per-minute-color", {false, ValueType::INTEGER}}, - {"print-color-mode", {false, ValueType::STRING}}, - {"print-quality", {false, ValueType::INTEGER}}, - {"printer-alert", {true, ValueType::STRING}}, - {"printer-alert-description", {true, ValueType::STRING}}, - {"printer-device-id", {false, ValueType::STRING}}, - {"printer-dns-sd-name", {false, ValueType::STRING}}, - {"printer-id", {false, ValueType::INTEGER}}, - {"printer-info", {false, ValueType::STRING}}, - {"printer-is-accepting-jobs", {false, ValueType::BOOLEAN}}, - {"printer-location", {false, ValueType::STRING}}, - {"printer-make-and-model", {false, ValueType::STRING}}, - {"printer-more-info", {false, ValueType::STRING}}, - {"printer-name", {false, ValueType::STRING}}, - {"printer-resolution", {false, ValueType::RESOLUTION}}, - {"printer-state", {false, ValueType::INTEGER}}, - {"printer-state-reasons", {true, ValueType::STRING}}, - {"printer-type", {false, ValueType::INTEGER}}, - {"printer-type-mask", {false, ValueType::INTEGER}}, - {"printer-up-time", {false, ValueType::INTEGER}}, - {"printer-uri", {false, ValueType::STRING}}, - {"queued-job-count", {false, ValueType::INTEGER}}, - {"requested-attributes", {true, ValueType::STRING}}, - {"requesting-user-name", {false, ValueType::STRING}}, - {"sides", {false, ValueType::STRING}}, - {"status-message", {false, ValueType::STRING}}, - {"time-at-completed", {false, ValueType::INTEGER}}, - {"time-at-creation", {false, ValueType::INTEGER}}, - {"time-at-processing", {false, ValueType::INTEGER}}, - {"which-jobs", {false, ValueType::STRING}}}; + static constexpr auto kAttributeDefinitions = + base::MakeFixedFlatMap<base::StringPiece, AttributeDefinition>( + {{"attributes-charset", {false, ValueType::kStrings}}, + {"attributes-natural-language", {false, ValueType::kStrings}}, + {"auth-info", {true, ValueType::kStrings}}, + {"auth-info-required", {true, ValueType::kStrings}}, + {"charset-configured", {false, ValueType::kStrings}}, + {"compression", {false, ValueType::kStrings}}, + {"copies", {false, ValueType::kInts}}, + {"document-format", {false, ValueType::kStrings}}, + {"document-name", {false, ValueType::kStrings}}, + {"finishings", {true, ValueType::kInts}}, + {"ipp-attribute-fidelity", {false, ValueType::kBools}}, + {"job-cancel-after", {false, ValueType::kInts}}, + {"job-hold-until", {false, ValueType::kStrings}}, + {"job-id", {false, ValueType::kInts}}, + {"job-k-limit", {false, ValueType::kInts}}, + {"job-media-progress", {false, ValueType::kInts}}, + {"job-name", {false, ValueType::kStrings}}, + {"job-originating-host-name", {false, ValueType::kStrings}}, + {"job-originating-user-name", {false, ValueType::kStrings}}, + {"job-page-limit", {false, ValueType::kInts}}, + {"job-password", {false, ValueType::kOctets}}, + {"job-printer-state-message", {false, ValueType::kStrings}}, + {"job-printer-state-reasons", {true, ValueType::kStrings}}, + {"job-printer-up-time", {false, ValueType::kInts}}, + {"job-printer-uri", {false, ValueType::kStrings}}, + {"job-priority", {false, ValueType::kInts}}, + {"job-quota-period", {false, ValueType::kInts}}, + {"job-state", {false, ValueType::kInts}}, + {"job-state-reasons", {true, ValueType::kStrings}}, + {"job-uri", {false, ValueType::kStrings}}, + {"last-document", {false, ValueType::kBools}}, + {"limit", {false, ValueType::kInts}}, + {"marker-change-time", {false, ValueType::kInts}}, + {"marker-colors", {true, ValueType::kStrings}}, + {"marker-high-levels", {true, ValueType::kInts}}, + {"marker-levels", {true, ValueType::kInts}}, + {"marker-low-levels", {true, ValueType::kInts}}, + {"marker-message", {false, ValueType::kStrings}}, + {"marker-names", {true, ValueType::kStrings}}, + {"marker-types", {true, ValueType::kStrings}}, + {"media", {false, ValueType::kStrings}}, + {"media-ready", {true, ValueType::kStrings}}, + // This is not a PWG attribute but CUPS supports it for InputSlot + // selection. + {"media-source", {true, ValueType::kStrings}}, + {"member-names", {true, ValueType::kStrings}}, + {"member-uris", {true, ValueType::kStrings}}, + {"multiple-document-handling", {false, ValueType::kStrings}}, + {"my-jobs", {false, ValueType::kBools}}, + {"natural-language-configured", {false, ValueType::kStrings}}, + {"number-up", {false, ValueType::kInts}}, + {"orientation-requested", {false, ValueType::kInts}}, + {"output-bin", {false, ValueType::kStrings}}, + {"page-border", {false, ValueType::kStrings}}, + {"page-ranges", {true, ValueType::kInts}}, + {"pages-per-minute", {false, ValueType::kInts}}, + {"pages-per-minute-color", {false, ValueType::kInts}}, + {"print-color-mode", {false, ValueType::kStrings}}, + {"print-quality", {false, ValueType::kInts}}, + {"printer-alert", {true, ValueType::kStrings}}, + {"printer-alert-description", {true, ValueType::kStrings}}, + {"printer-device-id", {false, ValueType::kStrings}}, + {"printer-dns-sd-name", {false, ValueType::kStrings}}, + {"printer-id", {false, ValueType::kInts}}, + {"printer-info", {false, ValueType::kStrings}}, + {"printer-is-accepting-jobs", {false, ValueType::kBools}}, + {"printer-location", {false, ValueType::kStrings}}, + {"printer-make-and-model", {false, ValueType::kStrings}}, + {"printer-more-info", {false, ValueType::kStrings}}, + {"printer-name", {false, ValueType::kStrings}}, + {"printer-resolution", {false, ValueType::kResolutions}}, + {"printer-state", {false, ValueType::kInts}}, + {"printer-state-reasons", {true, ValueType::kStrings}}, + {"printer-type", {false, ValueType::kInts}}, + {"printer-type-mask", {false, ValueType::kInts}}, + {"printer-up-time", {false, ValueType::kInts}}, + {"printer-uri", {false, ValueType::kStrings}}, + {"queued-job-count", {false, ValueType::kInts}}, + {"requested-attributes", {true, ValueType::kStrings}}, + {"requesting-user-name", {false, ValueType::kStrings}}, + {"sides", {false, ValueType::kStrings}}, + {"status-message", {false, ValueType::kStrings}}, + {"time-at-completed", {false, ValueType::kInts}}, + {"time-at-creation", {false, ValueType::kInts}}, + {"time-at-processing", {false, ValueType::kInts}}, + {"which-jobs", {false, ValueType::kStrings}}}); // Allowed IPP Operations. - static const std::set<ipp_op_t> kOperationIds{ - IPP_OP_CANCEL_JOB, IPP_OP_CREATE_JOB, - IPP_OP_CUPS_GET_DEFAULT, IPP_OP_CUPS_GET_PPD, - IPP_OP_CUPS_GET_PRINTERS, IPP_OP_GET_JOBS, - IPP_OP_GET_JOB_ATTRIBUTES, IPP_OP_GET_PRINTER_ATTRIBUTES, - IPP_OP_HOLD_JOB, IPP_OP_PAUSE_PRINTER, - IPP_OP_PRINT_JOB, IPP_OP_PRINT_URI, - IPP_OP_RELEASE_JOB, IPP_OP_RESUME_PRINTER, - IPP_OP_SEND_DOCUMENT, IPP_OP_SEND_URI, + static constexpr auto kOperationIds = base::MakeFixedFlatSet<ipp_op_t>({ + IPP_OP_CANCEL_JOB, + IPP_OP_CREATE_JOB, + IPP_OP_CUPS_GET_DEFAULT, + IPP_OP_CUPS_GET_PPD, + IPP_OP_CUPS_GET_PRINTERS, + IPP_OP_GET_JOBS, + IPP_OP_GET_JOB_ATTRIBUTES, + IPP_OP_GET_PRINTER_ATTRIBUTES, + IPP_OP_HOLD_JOB, + IPP_OP_PAUSE_PRINTER, + IPP_OP_PRINT_JOB, + IPP_OP_PRINT_URI, + IPP_OP_RELEASE_JOB, + IPP_OP_RESUME_PRINTER, + IPP_OP_SEND_DOCUMENT, + IPP_OP_SEND_URI, IPP_OP_VALIDATE_JOB, - }; + }); // Ensure |ipp_oper_id| is an allowed operation. - if (!base::Contains(kOperationIds, ipp_oper_id)) { + if (!kOperationIds.contains(ipp_oper_id)) { return ValidateAttributeResult::kFatalError; }
diff --git a/chrome/services/cups_proxy/ipp_attribute_validator.h b/chrome/services/cups_proxy/ipp_attribute_validator.h index 213d2e1..9553dff 100644 --- a/chrome/services/cups_proxy/ipp_attribute_validator.h +++ b/chrome/services/cups_proxy/ipp_attribute_validator.h
@@ -31,10 +31,11 @@ // - a single-value attribute cannot have more than one value // - a set-of-values attribute cannot be empty // Returns kFatalError <=> at least one of the constraints has been violated. -ValidateAttributeResult ValidateAttribute(ipp_op_t ipp_oper_id, - const std::string& name, - ipp_parser::mojom::ValueType type, - size_t values_count); +ValidateAttributeResult ValidateAttribute( + ipp_op_t ipp_oper_id, + const std::string& name, + ipp_parser::mojom::IppAttributeValue::Tag type, + size_t values_count); } // namespace cups_proxy
diff --git a/chrome/services/cups_proxy/ipp_validator.cc b/chrome/services/cups_proxy/ipp_validator.cc index 84c9722e..5e82f88e 100644 --- a/chrome/services/cups_proxy/ipp_validator.cc +++ b/chrome/services/cups_proxy/ipp_validator.cc
@@ -27,7 +27,7 @@ namespace cups_proxy { namespace { -using ValueType = ipp_parser::mojom::ValueType; +using ValueType = ipp_parser::mojom::IppAttributeValue::Tag; // Initial version only supports english lcoales. // TODO(crbug.com/945409): Extending to supporting arbitrary locales. @@ -71,31 +71,23 @@ // Depending on |type|, returns the number of values associated with |attr|. size_t GetAttributeValuesSize(const ipp_parser::mojom::IppAttributePtr& attr) { const auto& attr_value = attr->value; - switch (attr->type) { - case ValueType::DATE: + switch (attr->value->which()) { + case ValueType::kDate: return 1; - case ValueType::BOOLEAN: - DCHECK(attr_value->is_bools()); + case ValueType::kBools: return attr_value->get_bools().size(); - case ValueType::INTEGER: - DCHECK(attr_value->is_ints()); + case ValueType::kInts: return attr_value->get_ints().size(); - case ValueType::STRING: - DCHECK(attr_value->is_strings()); + case ValueType::kStrings: return attr_value->get_strings().size(); - case ValueType::OCTET: - DCHECK(attr_value->is_octets()); + case ValueType::kOctets: return attr_value->get_octets().size(); - case ValueType::RESOLUTION: - DCHECK(attr_value->is_resolutions()); + case ValueType::kResolutions: return attr_value->get_resolutions().size(); - - default: - break; } - DVLOG(1) << "Unknown CupsIppParser ValueType " << attr->type; + NOTREACHED(); return 0; } @@ -198,8 +190,8 @@ return nullptr; } - auto ret = ValidateAttribute(ipp_oper_id, attribute->name, attribute->type, - num_values); + auto ret = ValidateAttribute(ipp_oper_id, attribute->name, + attribute->value->which(), num_values); if (ret == ValidateAttributeResult::kFatalError) { return nullptr; } @@ -210,9 +202,8 @@ continue; } - switch (attribute->type) { - case ValueType::BOOLEAN: { - DCHECK(attribute->value->is_bools()); + switch (attribute->value->which()) { + case ValueType::kBools: { std::vector<char> values = ConvertBooleans(attribute->value->get_bools()); @@ -224,8 +215,7 @@ } break; } - case ValueType::DATE: { - DCHECK(attribute->value->is_date()); + case ValueType::kDate: { std::vector<uint8_t> date = attribute->value->get_date(); // Per RFC2910, ipp_uchar_t is defined as an OCTET, so below @@ -239,8 +229,7 @@ } break; } - case ValueType::INTEGER: { - DCHECK(attribute->value->is_ints()); + case ValueType::kInts: { std::vector<int> values = attribute->value->get_ints(); auto* attr = ippAddIntegers( @@ -252,9 +241,7 @@ } break; } - case ValueType::STRING: { - DCHECK(attribute->value->is_strings()); - + case ValueType::kStrings: { // Note: cstrings_values references attribute->value's strings, i.e. // attribute->value MUST outlive cstrings_values. std::vector<const char*> cstrings_values = @@ -270,8 +257,7 @@ } break; } - case ValueType::OCTET: { - DCHECK(attribute->value->is_octets()); + case ValueType::kOctets: { size_t num = attribute->value->get_octets().size(); if (num != 1) { LOG(ERROR) << "CUPS API only supports adding a single octet string " @@ -293,8 +279,7 @@ } break; } - case ValueType::RESOLUTION: { - DCHECK(attribute->value->is_resolutions()); + case ValueType::kResolutions: { std::array<std::vector<int>, 2> res = ConvertResolutions(attribute->value->get_resolutions()); auto* attr = ippAddResolutions(
diff --git a/chrome/services/cups_proxy/ipp_validator_unittest.cc b/chrome/services/cups_proxy/ipp_validator_unittest.cc index ddf4c07..f28e15d 100644 --- a/chrome/services/cups_proxy/ipp_validator_unittest.cc +++ b/chrome/services/cups_proxy/ipp_validator_unittest.cc
@@ -24,7 +24,6 @@ using ipp_parser::mojom::IppAttributePtr; using ipp_parser::mojom::IppMessagePtr; using ipp_parser::mojom::IppRequestPtr; -using ipp_parser::mojom::ValueType; using Printer = chromeos::Printer; @@ -84,7 +83,6 @@ ret->name = name; ret->group_tag = group_tag; ret->value_tag = value_tag; - ret->value = ipp_parser::mojom::IppAttributeValue::New(); return ret; } @@ -117,13 +115,13 @@ // Setup each attribute. IppAttributePtr attr_charset = BuildAttributePtr( "attributes-charset", IPP_TAG_OPERATION, IPP_TAG_CHARSET); - attr_charset->type = ValueType::STRING; - attr_charset->value->set_strings({"utf-8"}); + attr_charset->value = + ipp_parser::mojom::IppAttributeValue::NewStrings({"utf-8"}); IppAttributePtr attr_natlang = BuildAttributePtr( "attributes-natural-language", IPP_TAG_OPERATION, IPP_TAG_LANGUAGE); - attr_natlang->type = ValueType::STRING; - attr_natlang->value->set_strings({"en"}); + attr_natlang->value = + ipp_parser::mojom::IppAttributeValue::NewStrings({"en"}); ipp_message->attributes.push_back(std::move(attr_charset)); ipp_message->attributes.push_back(std::move(attr_natlang)); @@ -187,8 +185,8 @@ std::string fake_attr_name = "fake-attribute-name"; IppAttributePtr fake_attr = BuildAttributePtr(fake_attr_name, IPP_TAG_OPERATION, IPP_TAG_TEXT); - fake_attr->type = ValueType::STRING; - fake_attr->value->set_strings({"fake_attribute_value"}); + fake_attr->value = ipp_parser::mojom::IppAttributeValue::NewStrings( + {"fake_attribute_value"}); request->ipp->attributes.push_back(std::move(fake_attr)); auto result = RunValidateIppRequest(request);
diff --git a/chrome/services/ipp_parser/public/cpp/ipp_converter.cc b/chrome/services/ipp_parser/public/cpp/ipp_converter.cc index 83227c6..0dbe719 100644 --- a/chrome/services/ipp_parser/public/cpp/ipp_converter.cc +++ b/chrome/services/ipp_parser/public/cpp/ipp_converter.cc
@@ -19,7 +19,7 @@ namespace ipp_converter { namespace { -using ValueType = ipp_parser::mojom::ValueType; +using IppAttributeValue = ipp_parser::mojom::IppAttributeValue; const char kStatusDelimiter[] = " "; const char kHeaderDelimiter[] = ": "; @@ -85,15 +85,15 @@ } // Converts |value_tag| to corresponding mojom type for marshalling. -absl::optional<ValueType> ValueTagToType(const int value_tag) { +absl::optional<IppAttributeValue::Tag> ValueTagToType(const int value_tag) { switch (value_tag) { case IPP_TAG_BOOLEAN: - return ValueType::BOOLEAN; + return IppAttributeValue::Tag::kBools; case IPP_TAG_DATE: - return ValueType::DATE; + return IppAttributeValue::Tag::kDate; case IPP_TAG_INTEGER: case IPP_TAG_ENUM: - return ValueType::INTEGER; + return IppAttributeValue::Tag::kInts; // Below string cases take from libCUPS ippAttributeString API case IPP_TAG_TEXT: @@ -106,14 +106,14 @@ case IPP_TAG_LANGUAGE: case IPP_TAG_TEXTLANG: case IPP_TAG_NAMELANG: - return ValueType::STRING; + return IppAttributeValue::Tag::kStrings; // Octet (binary) string case IPP_TAG_STRING: - return ValueType::OCTET; + return IppAttributeValue::Tag::kOctets; case IPP_TAG_RESOLUTION: - return ValueType::RESOLUTION; + return IppAttributeValue::Tag::kResolutions; default: break; @@ -410,60 +410,63 @@ if (!type) { return nullptr; } - attrptr->type = type.value(); - attrptr->value = ipp_parser::mojom::IppAttributeValue::New(); - switch (attrptr->type) { - case ValueType::BOOLEAN: { - attrptr->value->set_bools(IppGetBools(attr)); + switch (*type) { + case IppAttributeValue::Tag::kBools: { + attrptr->value = + ipp_parser::mojom::IppAttributeValue::NewBools(IppGetBools(attr)); break; } - case ValueType::DATE: { + case IppAttributeValue::Tag::kDate: { // Note: We expect date-attributes to be single-valued. const uint8_t* v = reinterpret_cast<const uint8_t*>(ippGetDate(attr, 0)); if (!v) { return nullptr; } - attrptr->value->set_date(std::vector<uint8_t>(v, v + kIppDateSize)); + attrptr->value = ipp_parser::mojom::IppAttributeValue::NewDate( + std::vector<uint8_t>(v, v + kIppDateSize)); break; } - case ValueType::INTEGER: { + case IppAttributeValue::Tag::kInts: { auto vals = IppGetInts(attr); if (!vals.has_value()) { return nullptr; } - attrptr->value->set_ints(*vals); + attrptr->value = ipp_parser::mojom::IppAttributeValue::NewInts(*vals); break; } - case ValueType::STRING: { + case IppAttributeValue::Tag::kStrings: { auto vals = IppGetStrings(attr); if (!vals.has_value()) { return nullptr; } - attrptr->value->set_strings(*vals); + attrptr->value = + ipp_parser::mojom::IppAttributeValue::NewStrings(*vals); break; } - case ValueType::OCTET: { + case IppAttributeValue::Tag::kOctets: { auto vals = IppGetOctets(attr); if (!vals.has_value()) { return nullptr; } - attrptr->value->set_octets(*vals); + attrptr->value = ipp_parser::mojom::IppAttributeValue::NewOctets(*vals); break; } - case ValueType::RESOLUTION: { + case IppAttributeValue::Tag::kResolutions: { auto vals = IppGetResolutions(attr); if (!vals.has_value()) { return nullptr; } - attrptr->value->set_resolutions(std::move(*vals)); + attrptr->value = ipp_parser::mojom::IppAttributeValue::NewResolutions( + std::move(*vals)); break; } - default: - NOTREACHED(); } + if (!attrptr->value) + NOTREACHED(); + attributes.push_back(std::move(attrptr)); }
diff --git a/chrome/services/ipp_parser/public/mojom/ipp_parser.mojom b/chrome/services/ipp_parser/public/mojom/ipp_parser.mojom index 3763c932d..6c336238 100644 --- a/chrome/services/ipp_parser/public/mojom/ipp_parser.mojom +++ b/chrome/services/ipp_parser/public/mojom/ipp_parser.mojom
@@ -10,15 +10,6 @@ import "sandbox/policy/mojom/sandbox.mojom"; -[Extensible] enum ValueType { - BOOLEAN, - DATE, - INTEGER, - STRING, - OCTET, - RESOLUTION, -}; - struct Resolution { int32 xres; int32 yres; @@ -41,7 +32,6 @@ string name; int64 group_tag; int64 value_tag; - ValueType type; IppAttributeValue value; };
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index df6eb4f..2dad347b 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -6974,7 +6974,7 @@ "../browser/ui/app_list/search/files/zero_state_file_provider_unittest.cc", "../browser/ui/app_list/search/games/game_provider_unittest.cc", "../browser/ui/app_list/search/games/game_result_unittest.cc", - "../browser/ui/app_list/search/help_app_provider_unittest.cc", + "../browser/ui/app_list/search/help_app_zero_state_provider_unittest.cc", "../browser/ui/app_list/search/keyboard_shortcut_provider_unittest.cc", "../browser/ui/app_list/search/keyboard_shortcut_result_unittest.cc", "../browser/ui/app_list/search/mixer_unittest.cc",
diff --git a/chrome/test/data/extensions/api_test/passwords_private/test.js b/chrome/test/data/extensions/api_test/passwords_private/test.js index 218cb8b..d27cdf2 100644 --- a/chrome/test/data/extensions/api_test/passwords_private/test.js +++ b/chrome/test/data/extensions/api_test/passwords_private/test.js
@@ -688,6 +688,74 @@ }); }, + function recordChangePasswordFlowStartedManual() { + chrome.passwordsPrivate.recordChangePasswordFlowStarted( + { + id: 0, + formattedOrigin: 'example.com', + detailedOrigin: 'https://example.com', + isAndroidCredential: false, + signonRealm: 'https://example.com', + username: 'alice', + changePasswordUrl: 'https://example.com/.well-known/change-password', + compromisedInfo: { + compromiseTime: COMPROMISE_TIME, + elapsedTimeSinceCompromise: '3 days ago', + compromiseType: 'LEAKED', + isMuted: false, + }, + }, + true, () => { + chrome.test.assertNoLastError(); + chrome.test.succeed(); + }); + }, + + function recordChangePasswordFlowStartedAutomated() { + chrome.passwordsPrivate.recordChangePasswordFlowStarted( + { + id: 0, + formattedOrigin: 'example.com', + detailedOrigin: 'https://example.com', + isAndroidCredential: false, + signonRealm: 'https://example.com', + username: 'alice', + changePasswordUrl: 'https://example.com/.well-known/change-password', + compromisedInfo: { + compromiseTime: COMPROMISE_TIME, + elapsedTimeSinceCompromise: '3 days ago', + compromiseType: 'LEAKED', + isMuted: false, + }, + }, + false, () => { + chrome.test.assertNoLastError(); + chrome.test.succeed(); + }); + }, + + function recordChangePasswordFlowStartedAppNoUrl() { + chrome.passwordsPrivate.recordChangePasswordFlowStarted( + { + id: 0, + formattedOrigin: 'App (com.example.app)', + detailedOrigin: 'com.example.app', + isAndroidCredential: true, + signonRealm: '', + username: 'alice', + compromisedInfo: { + compromiseTime: COMPROMISE_TIME, + elapsedTimeSinceCompromise: '3 days ago', + compromiseType: 'LEAKED', + isMuted: false, + }, + }, + true, () => { + chrome.test.assertNoLastError(); + chrome.test.succeed(); + }); + }, + function startPasswordCheck() { chrome.passwordsPrivate.startPasswordCheck(() => { chrome.test.assertNoLastError();
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index 75d954e..52bc485 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -569,38 +569,7 @@ ] }, "OptimizationGuideFetchingEnabled": { - "os": [ - "win", - "linux", - "mac", - "chromeos_ash", - "chromeos_lacros", - "android" - ], - "policy_pref_mapping_tests": [ - { - "policies": { - "OptimizationGuideFetchingEnabled": true - }, - "prefs": { - "optimization_guide.fetching_enabled": { - "location": "user_profile", - "value": true - } - } - }, - { - "policies": { - "OptimizationGuideFetchingEnabled": false - }, - "prefs": { - "optimization_guide.fetching_enabled": { - "location": "user_profile", - "value": false - } - } - } - ] + "reason_for_missing_test": "Policy was removed" }, "RemoteAccessClientFirewallTraversal": { "reason_for_missing_test": "Policy was removed"
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.ts index 94c1396..b9efcf0 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.ts
@@ -7,7 +7,7 @@ import 'chrome://personalization/strings.m.js'; import 'chrome://webui-test/mojo_webui_test_support.js'; -import {CurrentWallpaper, DisplayableImage, WallpaperFullscreen, WallpaperLayout, WallpaperType} from 'chrome://personalization/trusted/personalization_app.js'; +import {CurrentWallpaper, DailyRefreshType, DisplayableImage, WallpaperFullscreen, WallpaperLayout, WallpaperType} from 'chrome://personalization/trusted/personalization_app.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/test_util.js'; @@ -316,8 +316,10 @@ ...personalizationStore.data.wallpaper.currentSelected, type: WallpaperType.kDaily, }; - personalizationStore.data.wallpaper.dailyRefresh.collectionId = - wallpaperProvider.collections![0]!.id; + personalizationStore.data.wallpaper.dailyRefresh = { + id: wallpaperProvider.collections![0]!.id, + type: DailyRefreshType.BACKDROP, + }; personalizationStore.data.wallpaper.pendingSelected = wallpaperProvider.images![1]; personalizationStore.notifyObservers();
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.ts index 117f856..757ab19 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.ts
@@ -7,7 +7,7 @@ import 'chrome://personalization/strings.m.js'; import 'chrome://webui-test/mojo_webui_test_support.js'; -import {CurrentWallpaper, Paths, WallpaperLayout, WallpaperSelected, WallpaperType} from 'chrome://personalization/trusted/personalization_app.js'; +import {CurrentWallpaper, DailyRefreshType, Paths, WallpaperLayout, WallpaperSelected, WallpaperType} from 'chrome://personalization/trusted/personalization_app.js'; import {assertDeepEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/test_util.js'; @@ -246,7 +246,8 @@ personalizationStore.data.wallpaper.loading.selected = false; const collection_id = wallpaperProvider.collections![0]!.id; personalizationStore.data.wallpaper.dailyRefresh = { - collectionId: collection_id, + id: collection_id, + type: DailyRefreshType.BACKDROP, }; wallpaperSelectedElement = initElement(
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_failed_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_failed_page_test.js index 15dd7a8..153e2895 100644 --- a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_failed_page_test.js +++ b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_failed_page_test.js
@@ -77,15 +77,6 @@ return flushTasks(); } - /** @return {!Promise} */ - function clickRetryCalibrationButton() { - const retryButton = - component.shadowRoot.querySelector('#retryCalibrationButton'); - assertFalse(retryButton.disabled); - retryButton.click(); - return flushTasks(); - } - /** * Get getComponentsList_ private member for testing. * @suppress {visibility} // access private member @@ -176,7 +167,7 @@ assertDeepEquals(savedResult, expectedResult); }); - test('RetryButtonTriggersCalibration', async () => { + test('NextButtonTriggersCalibration', async () => { const resolver = new PromiseResolver(); await initializeCalibrationPage(fakeCalibrationComponentsWithFails); @@ -198,8 +189,15 @@ return resolver.promise; }; - await clickRetryCalibrationButton(); + const expectedResult = {foo: 'bar'}; + let savedResult; + component.onNextButtonClick().then((result) => savedResult = result); + // Resolve to a distinct result to confirm it was not modified. + resolver.resolve(expectedResult); + await flushTasks(); + assertEquals(1, startCalibrationCalls); + assertDeepEquals(savedResult, expectedResult); }); test('ComponentChipAllButtonsDisabled', async () => { @@ -213,16 +211,6 @@ assertTrue(lidAccelerometerComponent.disabled); }); - test('RetryCalibrationAllButtonsDisabled', async () => { - await initializeCalibrationPage(fakeCalibrationComponentsWithFails); - - const retryButton = - component.shadowRoot.querySelector('#retryCalibrationButton'); - assertFalse(retryButton.disabled); - component.allButtonsDisabled = true; - assertTrue(retryButton.disabled); - }); - test('SkipCalibrationWithFailedComponents', async () => { await initializeCalibrationPage(fakeCalibrationComponentsWithFails);
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_finalize_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_finalize_page_test.js index 7a3327f4..22c1e7b4 100644 --- a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_finalize_page_test.js +++ b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_finalize_page_test.js
@@ -69,38 +69,19 @@ assertFalse(manualEnableComponent.hidden); }); - test('FinalizationIncompleteDisablesNext', async () => { - await initializeFinalizePage(); - - let savedResult; - let savedError; - component.onNextButtonClick() - .then((result) => savedResult = result) - .catch((error) => savedError = error); - await flushTasks(); - - assertTrue(savedError instanceof Error); - assertEquals(savedError.message, 'Finalization is not complete.'); - assertEquals(savedResult, undefined); - }); - - test('FinalizationCompleteEnablesNext', async () => { + test('FinalizationCompleteAutoTransitions', async () => { const resolver = new PromiseResolver(); await initializeFinalizePage(); - service.triggerFinalizationObserver(FinalizationStatus.kComplete, 1.0, 0); - await flushTasks(); + + let callCount = 0; service.finalizationComplete = () => { + callCount++; return resolver.promise; }; - - const expectedResult = {foo: 'bar'}; - let savedResult; - component.onNextButtonClick().then((result) => savedResult = result); - // Resolve to a distinct result to confirm it was not modified. - resolver.resolve(expectedResult); + service.triggerFinalizationObserver(FinalizationStatus.kComplete, 1.0, 0); await flushTasks(); - assertDeepEquals(savedResult, expectedResult); + assertEquals(1, callCount); }); test('FinalizationFailedBlockingRetry', async () => {
diff --git a/chrome/test/data/webui/settings/test_password_manager_proxy.ts b/chrome/test/data/webui/settings/test_password_manager_proxy.ts index ec336af3..d2ddcad 100644 --- a/chrome/test/data/webui/settings/test_password_manager_proxy.ts +++ b/chrome/test/data/webui/settings/test_password_manager_proxy.ts
@@ -111,6 +111,7 @@ 'addPassword', 'muteInsecureCredential', 'unmuteInsecureCredential', + 'recordChangePasswordFlowStarted', ]); /** @private {!PasswordManagerExpectations} */ @@ -394,6 +395,13 @@ this.methodCalled('unmuteInsecureCredential', insecureCredential); } + recordChangePasswordFlowStarted( + insecureCredential: chrome.passwordsPrivate.InsecureCredential, + isManualFlow: boolean) { + this.methodCalled( + 'recordChangePasswordFlowStarted', insecureCredential, isManualFlow); + } + cancelExportPasswords() {} exportPasswords(_callback: () => void) {}
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index 23c0b36..b1fd55c 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -3274,6 +3274,18 @@ <message name="IDS_ASH_QUICK_ANSWERS_VIEW_REPORT_QUERY_REPORT_LABEL" desc="Description text of the report query button for the Quick Answers view."> Report this query </message> + + <!-- Feedback Tool--> + <message name="IDS_FEEDBACK_TOOL_CONTINUE_BUTTON_LABEL" translateable="false" desc="Label of the continue button."> + Continue + </message> + <message name="IDS_FEEDBACK_TOOL_DESCRIPTION_LABEL" translateable="false" desc="Label of the text box where users can describe a problem they are having"> + Description + </message> + <message name="IDS_FEEDBACK_TOOL_PAGE_TITLE" translateable="false" desc="Label showing the title of the feedback tool before a report has been sent"> + Send feedback + </message> + <!-- End of Feedback Tool --> </messages> </release> </grit>
diff --git a/chromeos/dbus/hermes/hermes_euicc_client.cc b/chromeos/dbus/hermes/hermes_euicc_client.cc index bc986977..2b74ca9f 100644 --- a/chromeos/dbus/hermes/hermes_euicc_client.cc +++ b/chromeos/dbus/hermes/hermes_euicc_client.cc
@@ -23,9 +23,6 @@ namespace { HermesEuiccClient* g_instance = nullptr; - -// TODO(b/198205364): Remove when method name is added in dbus-constants. -const char kRefreshInstalledProfiles[] = "RefreshInstalledProfiles"; } // namespace HermesEuiccClient::Properties::Properties( @@ -106,7 +103,7 @@ bool restore_slot, HermesResponseCallback callback) override { dbus::MethodCall method_call(hermes::kHermesEuiccInterface, - kRefreshInstalledProfiles); + hermes::euicc::kRefreshInstalledProfiles); dbus::MessageWriter writer(&method_call); writer.AppendBool(restore_slot); dbus::ObjectProxy* object_proxy = GetOrCreateProperties(euicc_path).first;
diff --git a/chromeos/dbus/hermes/hermes_euicc_client_unittest.cc b/chromeos/dbus/hermes/hermes_euicc_client_unittest.cc index 4c65f36..55c496a 100644 --- a/chromeos/dbus/hermes/hermes_euicc_client_unittest.cc +++ b/chromeos/dbus/hermes/hermes_euicc_client_unittest.cc
@@ -30,9 +30,6 @@ const char kTestEuiccPath[] = "/org/chromium/hermes/Euicc/1"; const char kTestCarrierProfilePath[] = "/org/chromium/hermes/Profile/1"; -// TODO(b/198205364): Remove when method name is added in dbus-constants. -const char kRefreshInstalledProfiles[] = "RefreshInstalledProfiles"; - // Matches dbus::MethodCall for UninstallProfile call with given path. MATCHER_P(MatchUninstallProfileCall, expected_profile_path, "") { dbus::MessageReader reader(arg); @@ -63,7 +60,7 @@ MATCHER_P(MatchRefreshPendingProfilesCall, expected_restore_slot, "") { dbus::MessageReader reader(arg); bool restore_slot; - if (arg->GetMember() != kRefreshInstalledProfiles || + if (arg->GetMember() != hermes::euicc::kRefreshInstalledProfiles || !reader.PopBool(&restore_slot) || restore_slot != expected_restore_slot) { *result_listener << "has method_name=" << arg->GetMember() << " restore_slot=" << restore_slot; @@ -285,7 +282,7 @@ TEST_F(HermesEuiccClientTest, TestRefreshInstalledProfiles) { dbus::ObjectPath test_euicc_path(kTestEuiccPath); dbus::MethodCall method_call(hermes::kHermesEuiccInterface, - kRefreshInstalledProfiles); + hermes::euicc::kRefreshInstalledProfiles); method_call.SetSerial(123); EXPECT_CALL(*proxy_.get(), DoCallMethodWithErrorResponse( MatchRefreshPendingProfilesCall(
diff --git a/components/app_restore/app_restore_utils.cc b/components/app_restore/app_restore_utils.cc index 15e6e4ca..070be6a 100644 --- a/components/app_restore/app_restore_utils.cc +++ b/components/app_restore/app_restore_utils.cc
@@ -223,19 +223,4 @@ ->GetLacrosRestoreWindowId(lacros_window_id); } -void OnLacrosWindowAdded(aura::Window* const window, - uint32_t browser_session_id, - uint32_t restored_browser_session_id, - bool is_browser_app) { - if (!IsLacrosWindow(window)) - return; - - full_restore::FullRestoreReadHandler::GetInstance() - ->OnLacrosBrowserWindowAdded(window, restored_browser_session_id); - - full_restore::FullRestoreSaveHandler::GetInstance() - ->OnLacrosBrowserWindowAdded(window, browser_session_id, - restored_browser_session_id, is_browser_app); -} - } // namespace app_restore
diff --git a/components/app_restore/app_restore_utils.h b/components/app_restore/app_restore_utils.h index a61fbcd..a3e9d8c9 100644 --- a/components/app_restore/app_restore_utils.h +++ b/components/app_restore/app_restore_utils.h
@@ -89,16 +89,6 @@ COMPONENT_EXPORT(APP_RESTORE) int32_t GetLacrosRestoreWindowId(const std::string& lacros_window_id); -// Invoked when Lacros window is created. `browser_session_id` is the -// current browser session id. `restored_browser_session_id` is the restored -// browser session id. `is_browser_app` is true if it's an app type Lacros -// browser window. -COMPONENT_EXPORT(APP_RESTORE) -void OnLacrosWindowAdded(aura::Window* const window, - uint32_t browser_session_id, - uint32_t restored_browser_session_id, - bool is_browser_app); - } // namespace app_restore #endif // COMPONENTS_APP_RESTORE_APP_RESTORE_UTILS_H_
diff --git a/components/app_restore/full_restore_read_and_save_unittest.cc b/components/app_restore/full_restore_read_and_save_unittest.cc index 5853f5a..92f6165 100644 --- a/components/app_restore/full_restore_read_and_save_unittest.cc +++ b/components/app_restore/full_restore_read_and_save_unittest.cc
@@ -281,7 +281,9 @@ } std::unique_ptr<views::Widget> CreateLacrosWidget( - const std::string& lacros_window_id) { + const std::string& lacros_window_id, + int32_t restore_session_id, + int32_t restore_window_id) { views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); params.bounds = gfx::Rect(5, 5, 20, 20); @@ -292,6 +294,12 @@ aura::client::kAppType, static_cast<int>(ash::AppType::LACROS)); params.init_properties_container.SetProperty(app_restore::kLacrosWindowId, lacros_window_id); + + params.init_properties_container.SetProperty(app_restore::kWindowIdKey, + restore_session_id); + params.init_properties_container.SetProperty( + app_restore::kRestoreWindowIdKey, restore_window_id); + auto widget = std::make_unique<views::Widget>(); widget->Init(std::move(params)); @@ -300,13 +308,17 @@ } std::unique_ptr<aura::Window> CreateLacrosWindow( - const std::string& lacros_window_id) { + const std::string& lacros_window_id, + int32_t restore_session_id, + int32_t restore_window_id) { auto window = std::make_unique<aura::Window>( nullptr, aura::client::WINDOW_TYPE_NORMAL); window->SetProperty(aura::client::kAppType, static_cast<int>(ash::AppType::LACROS)); window->SetProperty(app_restore::kLacrosWindowId, std::string(kLacrosWindowId)); + window->SetProperty(app_restore::kWindowIdKey, restore_session_id); + window->SetProperty(app_restore::kRestoreWindowIdKey, restore_window_id); return window; } @@ -948,12 +960,10 @@ ASSERT_TRUE(lacros_save_handler); // Create a browser window first, then OnLacrosWindowAdded is called later. - auto widget = CreateLacrosWidget(kLacrosWindowId); + auto widget = CreateLacrosWidget(kLacrosWindowId, kBrowserSessionId, + /*restored_browser_session_id=*/0); auto* window = widget->GetNativeWindow(); SaveWindowInfo(window, kActivationIndex1); - app_restore::OnLacrosWindowAdded(window, kBrowserSessionId, - /*restored_browser_session_id=*/0, - /*is_browser_app=*/false); // Verify the browser window is saved. EXPECT_EQ(app_constants::kLacrosAppId, @@ -984,7 +994,7 @@ EXPECT_TRUE(restore_data->app_id_to_launch_list().empty()); } -// Verify the Lacros Chrome app window is saved correctly when +// Verify the Lacros browser window is saved correctly when // OnLacrosWindowAdded is called first, then the window is init later. TEST_F(FullRestoreReadAndSaveTest, LacrosBrowserWindowSavingOnLacrosWindowAddedCalledFirst) { @@ -997,10 +1007,8 @@ ASSERT_TRUE(lacros_save_handler); // OnLacrosWindowAdded is called first, then init the browser window later. - auto window = CreateLacrosWindow(kLacrosWindowId); - app_restore::OnLacrosWindowAdded(window.get(), kBrowserSessionId, - /*restored_browser_session_id=*/0, - /*is_browser_app=*/false); + auto window = CreateLacrosWindow(kLacrosWindowId, kBrowserSessionId, + /*restored_browser_session_id=*/0); window->Init(ui::LAYER_NOT_DRAWN); SaveWindowInfo(window.get(), kActivationIndex1); @@ -1052,7 +1060,8 @@ // Create a Chrome app window first, then the crosapi OnAppWindowAdded is // called later. - auto widget = CreateLacrosWidget(kLacrosWindowId); + auto widget = CreateLacrosWidget(kLacrosWindowId, kBrowserSessionId, + /*restored_browser_session_id=*/0); auto* window = widget->GetNativeWindow(); EXPECT_FALSE(test_api.GetLacrosWindowCandidates().empty()); SaveWindowInfo(window, kActivationIndex1); @@ -1117,7 +1126,8 @@ // window later. OnLacrosChromeAppWindowAdded(kAppId, kLacrosWindowId); EXPECT_FALSE(test_api.GetLacrosWindowIdToAppIdMap().empty()); - auto widget = CreateLacrosWidget(kLacrosWindowId); + auto widget = CreateLacrosWidget(kLacrosWindowId, kBrowserSessionId, + /*restored_browser_session_id=*/0); auto* window = widget->GetNativeWindow(); EXPECT_FALSE(test_api.GetLacrosWindowCandidates().empty()); SaveWindowInfo(window, kActivationIndex1);
diff --git a/components/app_restore/full_restore_read_handler.cc b/components/app_restore/full_restore_read_handler.cc index 6e445410..c694cef 100644 --- a/components/app_restore/full_restore_read_handler.cc +++ b/components/app_restore/full_restore_read_handler.cc
@@ -78,6 +78,10 @@ window_id == app_restore::kParentToHiddenContainer) { observed_windows_.AddObservation(window); } + + if (lacros_read_handler_) + lacros_read_handler_->OnWindowInitialized(window); + return; } @@ -164,15 +168,6 @@ arc_read_handler_->OnTaskDestroyed(task_id); } -void FullRestoreReadHandler::OnLacrosBrowserWindowAdded( - aura::Window* const window, - uint32_t restored_browser_session_id) { - if (lacros_read_handler_) { - lacros_read_handler_->OnLacrosBrowserWindowAdded( - window, restored_browser_session_id); - } -} - void FullRestoreReadHandler::OnLacrosChromeAppWindowAdded( const std::string& app_id, const std::string& window_id) {
diff --git a/components/app_restore/full_restore_read_handler.h b/components/app_restore/full_restore_read_handler.h index d84075e..5d6c04e 100644 --- a/components/app_restore/full_restore_read_handler.h +++ b/components/app_restore/full_restore_read_handler.h
@@ -95,11 +95,6 @@ int32_t session_id) override; void OnTaskDestroyed(int32_t task_id) override; - // Invoked when Lacros window is created. `restored_browser_session_id` is the - // restored browser session id. - void OnLacrosBrowserWindowAdded(aura::Window* const window, - uint32_t restored_browser_session_id); - // Invoked when an Chrome app Lacros window is created. `app_id` is the // AppService id, and `window_id` is the wayland app_id property for the // window.
diff --git a/components/app_restore/full_restore_save_handler.cc b/components/app_restore/full_restore_save_handler.cc index 78eb803..daef016b 100644 --- a/components/app_restore/full_restore_save_handler.cc +++ b/components/app_restore/full_restore_save_handler.cc
@@ -326,18 +326,6 @@ ModifyWindowInfo(window_id, window_info); } -void FullRestoreSaveHandler::OnLacrosBrowserWindowAdded( - aura::Window* const window, - uint32_t browser_session_id, - uint32_t restored_browser_session_id, - bool is_browser_app) { - if (lacros_save_handler_) { - lacros_save_handler_->OnBrowserWindowAdded(window, browser_session_id, - restored_browser_session_id, - is_browser_app); - } -} - void FullRestoreSaveHandler::OnLacrosChromeAppWindowAdded( const std::string& app_id, const std::string& window_id) {
diff --git a/components/app_restore/full_restore_save_handler.h b/components/app_restore/full_restore_save_handler.h index b131ecea..6df1ab2 100644 --- a/components/app_restore/full_restore_save_handler.h +++ b/components/app_restore/full_restore_save_handler.h
@@ -110,15 +110,6 @@ // Saves |window_info| to |profile_path_to_restore_data_|. void SaveWindowInfo(const app_restore::WindowInfo& window_info); - // Invoked when Lacros window is created. `browser_session_id` is the - // current browser session id for `window`.`restored_browser_session_id` is - // the restored browser session id. `is_browser_app` is true if it's an app - // type Lacros browser window. - void OnLacrosBrowserWindowAdded(aura::Window* const window, - uint32_t browser_session_id, - uint32_t restored_browser_session_id, - bool is_browser_app); - // Invoked when an Chrome app Lacros window is created. `app_id` is the // AppService id, and `window_id` is the wayland app_id property for the // window.
diff --git a/components/app_restore/lacros_read_handler.cc b/components/app_restore/lacros_read_handler.cc index 4b82de87..4dcbad9 100644 --- a/components/app_restore/lacros_read_handler.cc +++ b/components/app_restore/lacros_read_handler.cc
@@ -21,17 +21,14 @@ LacrosReadHandler::~LacrosReadHandler() = default; -void LacrosReadHandler::AddRestoreData(const std::string& app_id, - int32_t window_id) { - restore_window_id_to_app_id_[window_id] = app_id; -} - -void LacrosReadHandler::OnLacrosBrowserWindowAdded( - aura::Window* const window, - int32_t restored_browser_session_id) { +void LacrosReadHandler::OnWindowInitialized(aura::Window* window) { + // TODO(sophiewen): Test this in full_restore_read_and_save_unittest. if (!IsLacrosWindow(window)) return; + int32_t restored_browser_session_id = + window->GetProperty(app_restore::kRestoreWindowIdKey); + auto it = window_to_window_data_.find(window); if (it != window_to_window_data_.end() && it->second.restore_window_id == restored_browser_session_id) { @@ -54,6 +51,11 @@ UpdateWindow(window); } +void LacrosReadHandler::AddRestoreData(const std::string& app_id, + int32_t window_id) { + restore_window_id_to_app_id_[window_id] = app_id; +} + void LacrosReadHandler::OnAppWindowAdded(const std::string& app_id, const std::string& lacros_window_id) { lacros_window_id_to_app_id_[lacros_window_id] = app_id;
diff --git a/components/app_restore/lacros_read_handler.h b/components/app_restore/lacros_read_handler.h index c354c97f..932ee0a 100644 --- a/components/app_restore/lacros_read_handler.h +++ b/components/app_restore/lacros_read_handler.h
@@ -48,15 +48,13 @@ LacrosReadHandler& operator=(const LacrosReadHandler&) = delete; ~LacrosReadHandler(); + // Invoked when `window` is initialized. + void OnWindowInitialized(aura::Window* window); + // Sets `app_id` and `window_id` to `restore_window_id_to_app_id_` to record // that there is a restore data for `app_id` and `window_id`. void AddRestoreData(const std::string& app_id, int32_t window_id); - // Invoked when Lacros window is created. `restored_browser_session_id` is the - // restored browser session id. - void OnLacrosBrowserWindowAdded(aura::Window* const window, - int32_t restored_browser_session_id); - // Invoked when an Chrome app Lacros window is created. `app_id` is the // AppService id, and `window_id` is the wayland app_id property for the // window.
diff --git a/components/app_restore/lacros_save_handler.cc b/components/app_restore/lacros_save_handler.cc index 8a4bbd8..c5832e4 100644 --- a/components/app_restore/lacros_save_handler.cc +++ b/components/app_restore/lacros_save_handler.cc
@@ -24,19 +24,12 @@ void LacrosSaveHandler::OnWindowInitialized(aura::Window* window) { const std::string lacros_window_id = app_restore::GetLacrosWindowId(window); - // If `window` has been saved by OnBrowserWindowAdded, we don't need to save - // again. - if (base::Contains(window_candidates_, lacros_window_id)) - return; - std::string app_id; int32_t window_id = ++window_id_; std::unique_ptr<app_restore::AppLaunchInfo> app_launch_info; auto it = lacros_window_id_to_app_id_.find(lacros_window_id); if (it != lacros_window_id_to_app_id_.end()) { - // For Chrome app windows, get the app launch info and set the Chrome app - // id. app_id = it->second; app_launch_info = FullRestoreSaveHandler::GetInstance()->FetchAppLaunchInfo( profile_path_, app_id); @@ -52,6 +45,15 @@ window_candidates_[lacros_window_id].app_id = app_id; window_candidates_[lacros_window_id].window_id = window_id; + // Don't overwrite window info if `window_id` was already saved by + // OnAppWindowAdded. + if (it == lacros_window_id_to_app_id_.end()) { + // TODO(sophiewen): Move logic to OnWindowInitialized instead of calling + // OnBrowserWindowAdded. + OnBrowserWindowAdded(window, false); + return; + } + FullRestoreSaveHandler::GetInstance()->AddAppLaunchInfo( profile_path_, std::move(app_launch_info)); } @@ -70,16 +72,16 @@ window_candidates_.erase(it); } -void LacrosSaveHandler::OnBrowserWindowAdded( - aura::Window* const window, - uint32_t browser_session_id, - uint32_t restored_browser_session_id, - bool is_browser_app) { +void LacrosSaveHandler::OnBrowserWindowAdded(aura::Window* const window, + bool is_browser_app) { const std::string lacros_window_id = app_restore::GetLacrosWindowId(window); std::unique_ptr<app_restore::WindowInfo> window_info; auto* save_handler = FullRestoreSaveHandler::GetInstance(); DCHECK(save_handler); + uint32_t browser_session_id = + static_cast<uint32_t>(window->GetProperty(app_restore::kWindowIdKey)); + auto it = window_candidates_.find(lacros_window_id); if (it != window_candidates_.end() && it->second.window_id != browser_session_id) { @@ -96,13 +98,6 @@ window_candidates_[lacros_window_id].app_id = app_constants::kLacrosAppId; window_candidates_[lacros_window_id].window_id = browser_session_id; - // TODO(xdai): Remove this once crbug.com/1291799 is fixed. These two window - // properties are supposed to be set correctly before the widnow is created. - window->SetProperty(app_restore::kWindowIdKey, - static_cast<int32_t>(browser_session_id)); - window->SetProperty(app_restore::kRestoreWindowIdKey, - static_cast<int32_t>(restored_browser_session_id)); - std::unique_ptr<app_restore::AppLaunchInfo> app_launch_info = std::make_unique<app_restore::AppLaunchInfo>(app_constants::kLacrosAppId, browser_session_id);
diff --git a/components/app_restore/lacros_save_handler.h b/components/app_restore/lacros_save_handler.h index 242d0d8..fcc5ec6 100644 --- a/components/app_restore/lacros_save_handler.h +++ b/components/app_restore/lacros_save_handler.h
@@ -35,12 +35,8 @@ // Invoked when `window` is destroyed. void OnWindowDestroyed(aura::Window* window); - // Invoked when Lacros browser window is created. `browser_session_id` is the - // current browser session id. - void OnBrowserWindowAdded(aura::Window* const window, - uint32_t browser_session_id, - uint32_t restored_browser_session_id, - bool is_browser_app); + // Invoked when Lacros browser window is created. + void OnBrowserWindowAdded(aura::Window* const window, bool is_browser_app); // Invoked when an Chrome app Lacros window is created. `app_id` is the // AppService id, and `window_id` is the wayland app_id property for the
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc index ab9e1f1..11ef56c3 100644 --- a/components/autofill_assistant/browser/controller.cc +++ b/components/autofill_assistant/browser/controller.cc
@@ -29,7 +29,6 @@ #include "components/google/core/common/google_util.h" #include "components/password_manager/core/browser/password_change_success_tracker_impl.h" #include "components/strings/grit/components_strings.h" -#include "components/ukm/content/source_url_recorder.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h"
diff --git a/components/autofill_assistant/browser/metrics.cc b/components/autofill_assistant/browser/metrics.cc index 414d2ddb..e1a6cbe 100644 --- a/components/autofill_assistant/browser/metrics.cc +++ b/components/autofill_assistant/browser/metrics.cc
@@ -11,7 +11,6 @@ #include "components/autofill_assistant/browser/features.h" #include "components/autofill_assistant/browser/intent_strings.h" #include "components/autofill_assistant/browser/startup_util.h" -#include "components/ukm/content/source_url_recorder.h" #include "services/metrics/public/cpp/ukm_builders.h" namespace autofill_assistant {
diff --git a/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc b/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc index ec1bd62..932503a 100644 --- a/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc +++ b/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc
@@ -12,7 +12,6 @@ #include "components/autofill_assistant/browser/protocol_utils.h" #include "components/autofill_assistant/browser/starter_platform_delegate.h" #include "components/autofill_assistant/browser/url_utils.h" -#include "components/ukm/content/source_url_recorder.h" #include "components/version_info/version_info.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h"
diff --git a/components/bookmarks/common/android/BUILD.gn b/components/bookmarks/common/android/BUILD.gn index 8b1a38c..76467e0 100644 --- a/components/bookmarks/common/android/BUILD.gn +++ b/components/bookmarks/common/android/BUILD.gn
@@ -19,10 +19,15 @@ android_library("bookmarks_java") { deps = [ "//base:base_java", + "//components/url_formatter/android:url_formatter_java", "//third_party/androidx:androidx_annotation_annotation_java", + "//url:gurl_java", ] srcjar_deps = [ ":bookmark_type_javagen" ] - sources = [ "java/src/org/chromium/components/bookmarks/BookmarkId.java" ] + sources = [ + "java/src/org/chromium/components/bookmarks/BookmarkId.java", + "java/src/org/chromium/components/bookmarks/BookmarkItem.java", + ] } generate_jni("bookmarks_jni_headers") {
diff --git a/components/bookmarks/common/android/java/src/org/chromium/components/bookmarks/BookmarkItem.java b/components/bookmarks/common/android/java/src/org/chromium/components/bookmarks/BookmarkItem.java new file mode 100644 index 0000000..5192b1c --- /dev/null +++ b/components/bookmarks/common/android/java/src/org/chromium/components/bookmarks/BookmarkItem.java
@@ -0,0 +1,129 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.bookmarks; + +import org.chromium.components.url_formatter.SchemeDisplay; +import org.chromium.components.url_formatter.UrlFormatter; +import org.chromium.url.GURL; + +/** + * Contains data about a bookmark or bookmark folder. + */ +public class BookmarkItem { + private final String mTitle; + private final GURL mUrl; + private final BookmarkId mId; + private final BookmarkId mParentId; + private final long mDateAdded; + private final boolean mIsFolder; + private final boolean mIsEditable; + private final boolean mIsManaged; + private final boolean mRead; + private final boolean mReadingListSwappable; + + private boolean mForceEditableForTesting; + + /** + * Constructs a bookmark item. + * @param id The id. + * @param title The title of the bookmark/folder. + * @param url The url of the bookmark. + * @param isFolder Whether this item is a folder. + * @param parentId The id of the parent. + * @param isEditable Whether this item is editable. + * @param isManaged Whether this item is managed. + * @param dateAdded The date this item was added. + * @param read Whether this item has been read (reading list only). + * @param readingListSwappable Whether this item is swappable to/from reading list. + */ + public BookmarkItem(BookmarkId id, String title, GURL url, boolean isFolder, + BookmarkId parentId, boolean isEditable, boolean isManaged, long dateAdded, + boolean read, boolean readingListSwappable) { + mId = id; + mTitle = title; + mUrl = url; + mIsFolder = isFolder; + mParentId = parentId; + mIsEditable = isEditable; + mIsManaged = isManaged; + mDateAdded = dateAdded; + mRead = read; + mReadingListSwappable = readingListSwappable; + } + + /** Returns the title of the bookmark item. */ + public String getTitle() { + return mTitle; + } + + /** Returns the url of the bookmark item. */ + public GURL getUrl() { + return mUrl; + } + + /** Returns the string to display for the item's url. */ + public String getUrlForDisplay() { + return UrlFormatter.formatUrlForSecurityDisplay( + getUrl(), SchemeDisplay.OMIT_HTTP_AND_HTTPS); + } + + /** Returns whether item is a folder or a bookmark. */ + public boolean isFolder() { + return mIsFolder; + } + + /** Returns the parent id of the bookmark item. */ + public BookmarkId getParentId() { + return mParentId; + } + + /** Returns whether this bookmark can be edited. */ + public boolean isEditable() { + return mForceEditableForTesting || mIsEditable; + } + + /** Returns whether this bookmark's URL can be edited */ + public boolean isUrlEditable() { + return isEditable() && mId.getType() == BookmarkType.NORMAL; + } + + /** Returns whether this bookmark can be moved */ + public boolean isMovable() { + return mReadingListSwappable || isReorderable(); + } + + /** Returns whether this bookmark can be moved */ + public boolean isReorderable() { + return isEditable() && mId.getType() == BookmarkType.NORMAL; + } + + /** Returns whether this is a managed bookmark. */ + public boolean isManaged() { + return mIsManaged; + } + + /** Returns the {@link BookmarkId}. */ + public BookmarkId getId() { + return mId; + } + + /** Returns the timestamp in milliseconds since epoch that the bookmark is added. */ + public long getDateAdded() { + return mDateAdded; + } + + /** + * Returns whether the bookmark is read. Only valid for {@link BookmarkType#READING_LIST}. + * Defaults to "false" for other types. + */ + public boolean isRead() { + return mRead; + } + + // TODO(https://crbug.com/1019217): Remove when BookmarkModel is stubbed in tests instead. + public void forceEditableForTesting() { + mForceEditableForTesting = true; + } +} \ No newline at end of file
diff --git a/components/client_hints/OWNERS b/components/client_hints/OWNERS index 3f91ab5..789eadcc 100644 --- a/components/client_hints/OWNERS +++ b/components/client_hints/OWNERS
@@ -1,4 +1,5 @@ abeyad@chromium.org arichiv@chromium.org ryansturm@chromium.org +victortan@chromium.org yoavweiss@chromium.org
diff --git a/components/desks_storage/core/desk_sync_bridge_unittest.cc b/components/desks_storage/core/desk_sync_bridge_unittest.cc index def61c48..96244fa1 100644 --- a/components/desks_storage/core/desk_sync_bridge_unittest.cc +++ b/components/desks_storage/core/desk_sync_bridge_unittest.cc
@@ -24,9 +24,8 @@ #include "components/app_restore/app_launch_info.h" #include "components/desks_storage/core/desk_model_observer.h" #include "components/desks_storage/core/desk_template_conversion.h" +#include "components/desks_storage/core/desk_template_util.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" -#include "components/services/app_service/public/cpp/app_registry_cache_wrapper.h" -#include "components/services/app_service/public/cpp/app_types.h" #include "components/services/app_service/public/cpp/features.h" #include "components/sync/model/entity_change.h" #include "components/sync/model/in_memory_metadata_change_list.h" @@ -333,15 +332,6 @@ return state; } -apps::AppPtr MakeApp(const char* app_id, - const char* name, - apps::AppType app_type) { - apps::AppPtr app = std::make_unique<apps::App>(app_type, app_id); - app->readiness = apps::Readiness::kReady; - app->name = name; - return app; -} - class MockDeskModelObserver : public DeskModelObserver { public: MOCK_METHOD0(DeskModelLoaded, void()); @@ -408,39 +398,6 @@ InitializeBridge(); } - void PopulateAppRegistryCache() { - std::vector<apps::AppPtr> deltas; - - deltas.push_back( - MakeApp(kTestPwaAppId, "Test PWA App", apps::AppType::kWeb)); - // chromeAppId returns kExtension in the real Apps cache. - deltas.push_back(MakeApp(app_constants::kChromeAppId, "Chrome Browser", - apps::AppType::kChromeApp)); - deltas.push_back(MakeApp(kTestChromeAppId, "Test Chrome App", - apps::AppType::kChromeApp)); - deltas.push_back(MakeApp(kTestArcAppId, "Arc app", apps::AppType::kArc)); - - if (base::FeatureList::IsEnabled( - apps::kAppServiceOnAppUpdateWithoutMojom)) { - cache_->OnApps(std::move(deltas), apps::AppType::kUnknown, - /*should_notify_initialized=*/false); - } else { - std::vector<apps::mojom::AppPtr> mojom_deltas; - for (const auto& delta : deltas) { - mojom_deltas.push_back(apps::ConvertAppToMojomApp(delta)); - } - cache_->OnApps(std::move(mojom_deltas), apps::mojom::AppType::kUnknown, - /*should_notify_initialized=*/false); - } - - cache_->SetAccountId(account_id_); - - apps::AppRegistryCacheWrapper::Get().AddAppRegistryCache(account_id_, - cache_.get()); - } - - void SetUp() override { PopulateAppRegistryCache(); } - void WriteToStoreWithMetadata( const std::vector<WorkspaceDeskSpecifics>& specifics_list, ModelTypeState state) { @@ -576,6 +533,11 @@ bridge()->SetPolicyDeskTemplates(policy_json); } + // testing::test. + void SetUp() override { + desk_template_util::PopulateAppRegistryCache(account_id_, cache_.get()); + } + MockModelTypeChangeProcessor* processor() { return &mock_processor_; } DeskSyncBridge* bridge() { return bridge_.get(); }
diff --git a/components/desks_storage/core/desk_template_conversion_unittests.cc b/components/desks_storage/core/desk_template_conversion_unittests.cc index 56939ee..9e51969a 100644 --- a/components/desks_storage/core/desk_template_conversion_unittests.cc +++ b/components/desks_storage/core/desk_template_conversion_unittests.cc
@@ -18,6 +18,7 @@ #include "components/app_restore/app_launch_info.h" #include "components/app_restore/app_restore_data.h" #include "components/app_restore/window_info.h" +#include "components/desks_storage/core/desk_template_util.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" #include "components/services/app_service/public/cpp/app_registry_cache_wrapper.h" #include "components/services/app_service/public/cpp/app_types.h" @@ -34,8 +35,8 @@ "7f4b7ff0-970a-41bb-aa91-f6c3e2724207"; const std::string kBrowserTemplateName = "BrowserTest"; const std::string kChromePwaTemplateName = "ChromeAppTest"; -const std::string kChromeAppId = "chrome_app_1"; -const std::string kProgressiveAppid = "progressive_app_1"; +const std::string kChromeAppId = "test_chrome_app_1"; +const std::string kProgressiveAppid = "test_pwa_app_1"; const std::string kValidTemplateBrowser = "{\"version\":1,\"uuid\":\"" + kTestUuidBrowser + "\",\"name\":\"" + kBrowserTemplateName + @@ -79,15 +80,6 @@ "\"display_id\":\"100\",\"event_flag\":0,\"pre_minimized_window_state\":" "\"NORMAL\"}]}}"; -apps::AppPtr MakeApp(const char* app_id, - const char* name, - apps::AppType app_type) { - apps::AppPtr app = std::make_unique<apps::App>(app_type, app_id); - app->readiness = apps::Readiness::kReady; - app->name = name; - return app; -} - } // namespace class DeskTemplateConversionTest : public testing::Test { @@ -101,38 +93,10 @@ : account_id_(AccountId::FromUserEmail("test@gmail.com")), cache_(std::make_unique<apps::AppRegistryCache>()) {} - void PopulateAppRegistryCache() { - std::vector<apps::AppPtr> deltas; - - deltas.push_back(MakeApp(kProgressiveAppid.c_str(), "Test PWA App", - apps::AppType::kWeb)); - // chromeAppId returns kExtension in the real Apps cache. - deltas.push_back(MakeApp(app_constants::kChromeAppId, "Chrome Browser", - apps::AppType::kChromeApp)); - deltas.push_back(MakeApp(kChromeAppId.c_str(), "Test Chrome App", - apps::AppType::kChromeApp)); - - if (base::FeatureList::IsEnabled( - apps::kAppServiceOnAppUpdateWithoutMojom)) { - cache_->OnApps(std::move(deltas), apps::AppType::kUnknown, - /*should_notify_initialized=*/false); - } else { - std::vector<apps::mojom::AppPtr> mojom_deltas; - for (const auto& delta : deltas) { - mojom_deltas.push_back(apps::ConvertAppToMojomApp(delta)); - } - cache_->OnApps(std::move(mojom_deltas), apps::mojom::AppType::kUnknown, - /*should_notify_initialized=*/false); - } - - cache_->SetAccountId(account_id_); - - apps::AppRegistryCacheWrapper::Get().AddAppRegistryCache(account_id_, - cache_.get()); + void SetUp() override { + desk_template_util::PopulateAppRegistryCache(account_id_, cache_.get()); } - void SetUp() override { PopulateAppRegistryCache(); } - AccountId account_id_; private:
diff --git a/components/desks_storage/core/desk_template_util.cc b/components/desks_storage/core/desk_template_util.cc index ec2a105..14e9123 100644 --- a/components/desks_storage/core/desk_template_util.cc +++ b/components/desks_storage/core/desk_template_util.cc
@@ -6,6 +6,9 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "components/app_constants/constants.h" +#include "components/services/app_service/public/cpp/app_registry_cache_wrapper.h" +#include "components/services/app_service/public/cpp/app_types.h" #include "third_party/re2/src/re2/re2.h" namespace { @@ -16,6 +19,11 @@ constexpr char kInitialDuplicateNumberValue[] = " (1)"; // Regex used in determining if duplicate name should be incremented. constexpr char kDuplicateNumberRegex[] = "\\(([0-9]+)\\)$"; +constexpr char kTestPwaAppId[] = "test_pwa_app_id"; +constexpr char kTestChromeAppId[] = "test_chrome_app_id"; +constexpr char kTestArcAppId[] = "test_arc_app_id"; +constexpr char kTestChromeAppId1[] = "test_chrome_app_1"; +constexpr char kTestPwaAppId1[] = "test_pwa_app_1"; } // namespace @@ -23,6 +31,15 @@ namespace desk_template_util { +apps::AppPtr MakeApp(const char* app_id, + const char* name, + apps::AppType app_type) { + apps::AppPtr app = std::make_unique<apps::App>(app_type, app_id); + app->readiness = apps::Readiness::kReady; + app->name = name; + return app; +} + std::u16string AppendDuplicateNumberToDuplicateName( const std::u16string& duplicate_name_u16) { std::string duplicate_name = base::UTF16ToUTF8(duplicate_name_u16); @@ -40,6 +57,39 @@ return base::UTF8ToUTF16(duplicate_name); } +void PopulateAppRegistryCache(AccountId account_id, + apps::AppRegistryCache* cache) { + std::vector<apps::AppPtr> deltas; + + deltas.push_back(MakeApp(kTestPwaAppId, "Test PWA App", apps::AppType::kWeb)); + // chromeAppId returns kExtension in the real Apps cache. + deltas.push_back(MakeApp(app_constants::kChromeAppId, "Chrome Browser", + apps::AppType::kChromeApp)); + deltas.push_back( + MakeApp(kTestChromeAppId, "Test Chrome App", apps::AppType::kChromeApp)); + deltas.push_back(MakeApp(kTestArcAppId, "Arc app", apps::AppType::kArc)); + deltas.push_back( + MakeApp(kTestPwaAppId1, "Test PWA App", apps::AppType::kWeb)); + deltas.push_back( + MakeApp(kTestChromeAppId1, "Test Chrome App", apps::AppType::kChromeApp)); + + if (base::FeatureList::IsEnabled(apps::kAppServiceOnAppUpdateWithoutMojom)) { + cache->OnApps(std::move(deltas), apps::AppType::kUnknown, + /*should_notify_initialized=*/false); + } else { + std::vector<apps::mojom::AppPtr> mojom_deltas; + for (const auto& delta : deltas) { + mojom_deltas.push_back(apps::ConvertAppToMojomApp(delta)); + } + cache->OnApps(std::move(mojom_deltas), apps::mojom::AppType::kUnknown, + /*should_notify_initialized=*/false); + } + + cache->SetAccountId(account_id); + + apps::AppRegistryCacheWrapper::Get().AddAppRegistryCache(account_id, cache); +} + } // namespace desk_template_util } // namespace desks_storage
diff --git a/components/desks_storage/core/desk_template_util.h b/components/desks_storage/core/desk_template_util.h index 77caedb..48fae9a3 100644 --- a/components/desks_storage/core/desk_template_util.h +++ b/components/desks_storage/core/desk_template_util.h
@@ -7,6 +7,9 @@ #include <string> +#include "components/account_id/account_id.h" +#include "components/services/app_service/public/cpp/app_registry_cache.h" + namespace desks_storage { namespace desk_template_util { @@ -18,6 +21,10 @@ std::u16string AppendDuplicateNumberToDuplicateName( const std::u16string& duplicate_name_u16); +// Populates the given cache with test app information. +void PopulateAppRegistryCache(AccountId account_id, + apps::AppRegistryCache* cache); + } // namespace desk_template_util } // namespace desks_storage
diff --git a/components/desks_storage/core/desk_template_util_unittests.cc b/components/desks_storage/core/desk_template_util_unittests.cc index 0cedf515..97f4044f5 100644 --- a/components/desks_storage/core/desk_template_util_unittests.cc +++ b/components/desks_storage/core/desk_template_util_unittests.cc
@@ -41,4 +41,11 @@ u"test (1) (9)")); } +TEST_F(DeskTemplateUtilTest, PopulateRegistryCacheHasAppInfo) { + AccountId account_id = AccountId::FromUserEmail("test@gmail.com"); + auto cache = std::make_unique<apps::AppRegistryCache>(); + desk_template_util::PopulateAppRegistryCache(account_id, cache.get()); + EXPECT_EQ(6ul, cache->GetAllApps().size()); +} + } // namespace desks_storage
diff --git a/components/embedder_support/OWNERS b/components/embedder_support/OWNERS index 7d5dea9a..eb0dee8 100644 --- a/components/embedder_support/OWNERS +++ b/components/embedder_support/OWNERS
@@ -1,2 +1,3 @@ abeyad@chromium.org miketaylr@chromium.org +victortan@chromium.org
diff --git a/components/feature_engagement/internal/tracker_impl.cc b/components/feature_engagement/internal/tracker_impl.cc index 66842b9c..4ee2fec7 100644 --- a/components/feature_engagement/internal/tracker_impl.cc +++ b/components/feature_engagement/internal/tracker_impl.cc
@@ -177,11 +177,19 @@ } bool TrackerImpl::ShouldTriggerHelpUI(const base::Feature& feature) { + if (!base::FeatureList::IsEnabled(feature_engagement::kEnableIPH)) { + return false; + } + return ShouldTriggerHelpUIWithSnooze(feature).ShouldShowIph(); } TrackerImpl::TriggerDetails TrackerImpl::ShouldTriggerHelpUIWithSnooze( const base::Feature& feature) { + if (!base::FeatureList::IsEnabled(feature_engagement::kEnableIPH)) { + return TriggerDetails(false, false); + } + FeatureConfig feature_config = configuration_->GetFeatureConfig(feature); ConditionValidator::Result result = condition_validator_->MeetsConditions( feature, feature_config, *event_model_, *availability_model_,
diff --git a/components/feature_engagement/public/feature_constants.cc b/components/feature_engagement/public/feature_constants.cc index 650daa6..6e1a6060 100644 --- a/components/feature_engagement/public/feature_constants.cc +++ b/components/feature_engagement/public/feature_constants.cc
@@ -14,6 +14,7 @@ const base::Feature kIPHDemoMode{"IPH_DemoMode", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kIPHSnooze{"IPH_Snooze", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kEnableIPH{"EnableIPH", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kUseClientConfigIPH{"UseClientConfigIPH", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/feature_engagement/public/feature_constants.h b/components/feature_engagement/public/feature_constants.h index 5964388f..176fc64 100644 --- a/components/feature_engagement/public/feature_constants.h +++ b/components/feature_engagement/public/feature_constants.h
@@ -29,6 +29,8 @@ // A feature to ensure all arrays can contain at least one feature. extern const base::Feature kIPHDummyFeature; +extern const base::Feature kEnableIPH; + #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \ BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA) extern const base::Feature kIPHDesktopSharedHighlightingFeature;
diff --git a/components/live_caption/live_caption_controller.cc b/components/live_caption/live_caption_controller.cc index 8272b54..c2f1f27 100644 --- a/components/live_caption/live_caption_controller.cc +++ b/components/live_caption/live_caption_controller.cc
@@ -229,7 +229,7 @@ OnErrorClickedCallback error_clicked_callback, OnDoNotShowAgainClickedCallback error_silenced_callback) { if (!caption_bubble_controller_) - return; + CreateUI(); caption_bubble_controller_->OnError(caption_bubble_context, error_type, std::move(error_clicked_callback), std::move(error_silenced_callback));
diff --git a/components/optimization_guide/core/hints_fetcher.cc b/components/optimization_guide/core/hints_fetcher.cc index 257e28b..7d58512 100644 --- a/components/optimization_guide/core/hints_fetcher.cc +++ b/components/optimization_guide/core/hints_fetcher.cc
@@ -94,7 +94,7 @@ CHECK(optimization_guide_service_url_.SchemeIs(url::kHttpsScheme) || base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kOptimizationGuideServiceGetHintsURL)); - DCHECK(features::IsRemoteFetchingEnabled(pref_service)); + DCHECK(features::IsRemoteFetchingEnabled()); } HintsFetcher::~HintsFetcher() {
diff --git a/components/optimization_guide/core/optimization_guide_features.cc b/components/optimization_guide/core/optimization_guide_features.cc index 50802f2..7b5ae32 100644 --- a/components/optimization_guide/core/optimization_guide_features.cc +++ b/components/optimization_guide/core/optimization_guide_features.cc
@@ -16,10 +16,8 @@ #include "build/build_config.h" #include "components/optimization_guide/core/insertion_ordered_set.h" #include "components/optimization_guide/core/optimization_guide_constants.h" -#include "components/optimization_guide/core/optimization_guide_prefs.h" #include "components/optimization_guide/core/optimization_guide_switches.h" #include "components/optimization_guide/machine_learning_tflite_buildflags.h" -#include "components/prefs/pref_service.h" #include "components/variations/hashing.h" #include "google_apis/google_api_keys.h" #include "net/base/url_util.h" @@ -266,10 +264,8 @@ return base::FeatureList::IsEnabled(kOptimizationHints); } -bool IsRemoteFetchingEnabled(PrefService* pref_service) { - return base::FeatureList::IsEnabled(kRemoteOptimizationGuideFetching) && - pref_service->GetBoolean( - optimization_guide::prefs::kOptimizationGuideFetchingEnabled); +bool IsRemoteFetchingEnabled() { + return base::FeatureList::IsEnabled(kRemoteOptimizationGuideFetching); } bool IsPushNotificationsEnabled() {
diff --git a/components/optimization_guide/core/optimization_guide_features.h b/components/optimization_guide/core/optimization_guide_features.h index cb015a1..b76c7ee 100644 --- a/components/optimization_guide/core/optimization_guide_features.h +++ b/components/optimization_guide/core/optimization_guide_features.h
@@ -18,8 +18,6 @@ #include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" -class PrefService; - namespace optimization_guide { namespace features { @@ -91,8 +89,8 @@ bool IsOptimizationHintsEnabled(); // Returns true if the feature to fetch from the remote Optimization Guide -// Service is enabled. -bool IsRemoteFetchingEnabled(PrefService* pref_service); +// Service is enabled. This controls the fetching of both hints and models. +bool IsRemoteFetchingEnabled(); // Returns true if the feature to fetch data for users that have consented to // anonymous data collection is enabled but are not Data Saver users.
diff --git a/components/optimization_guide/core/optimization_guide_permissions_util.cc b/components/optimization_guide/core/optimization_guide_permissions_util.cc index ab81b717..fec0880 100644 --- a/components/optimization_guide/core/optimization_guide_permissions_util.cc +++ b/components/optimization_guide/core/optimization_guide_permissions_util.cc
@@ -40,7 +40,7 @@ return true; } - if (!features::IsRemoteFetchingEnabled(pref_service)) + if (!features::IsRemoteFetchingEnabled()) return false; if (features::IsRemoteFetchingExplicitlyAllowedForPerformanceInfo())
diff --git a/components/optimization_guide/core/optimization_guide_permissions_util.h b/components/optimization_guide/core/optimization_guide_permissions_util.h index 9b80ab9..da88197 100644 --- a/components/optimization_guide/core/optimization_guide_permissions_util.h +++ b/components/optimization_guide/core/optimization_guide_permissions_util.h
@@ -11,6 +11,9 @@ // Returns true if the user, as represented by |profile| is permitted to make // calls to the remote Optimization Guide Service. +// +// Note that this does not include the additional enterprise policy check that +// gates model downloads. bool IsUserPermittedToFetchFromRemoteOptimizationGuide( bool is_off_the_record, PrefService* pref_service);
diff --git a/components/optimization_guide/core/optimization_guide_permissions_util_unittest.cc b/components/optimization_guide/core/optimization_guide_permissions_util_unittest.cc index 7e78be6..015955c 100644 --- a/components/optimization_guide/core/optimization_guide_permissions_util_unittest.cc +++ b/components/optimization_guide/core/optimization_guide_permissions_util_unittest.cc
@@ -8,7 +8,6 @@ #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "components/optimization_guide/core/optimization_guide_features.h" -#include "components/optimization_guide/core/optimization_guide_prefs.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "components/unified_consent/pref_names.h" #include "components/unified_consent/unified_consent_service.h" @@ -21,7 +20,6 @@ void SetUp() override { unified_consent::UnifiedConsentService::RegisterPrefs( pref_service_.registry()); - prefs::RegisterProfilePrefs(pref_service_.registry()); } void SetUrlKeyedAnonymizedDataCollectionEnabled(bool enabled) { @@ -30,10 +28,6 @@ enabled); } - void SetOptimizationGuideFetchingPrefEnabled(bool enabled) { - pref_service_.SetBoolean(prefs::kOptimizationGuideFetchingEnabled, enabled); - } - PrefService* pref_service() { return &pref_service_; } private: @@ -106,15 +100,6 @@ } TEST_F(OptimizationGuidePermissionsUtilTest, - IsUserPermittedToFetchHintsAllFeaturesEnabledButPrefDisabled) { - SetUrlKeyedAnonymizedDataCollectionEnabled(true); - SetOptimizationGuideFetchingPrefEnabled(false); - - EXPECT_FALSE(IsUserPermittedToFetchFromRemoteOptimizationGuide( - /*is_off_the_record=*/false, pref_service())); -} - -TEST_F(OptimizationGuidePermissionsUtilTest, IsUserPermittedToFetchHintsPerformanceInfoFlagExplicitlyAllows) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitWithFeatures(
diff --git a/components/optimization_guide/core/optimization_guide_prefs.cc b/components/optimization_guide/core/optimization_guide_prefs.cc index 388fefd..87ccde8 100644 --- a/components/optimization_guide/core/optimization_guide_prefs.cc +++ b/components/optimization_guide/core/optimization_guide_prefs.cc
@@ -49,10 +49,6 @@ const char kPreviouslyRegisteredOptimizationTypes[] = "optimization_guide.previously_registered_optimization_types"; -// A boolean pref that stores whether fetching is enabled. True by default. -const char kOptimizationGuideFetchingEnabled[] = - "optimization_guide.fetching_enabled"; - // A dictionary pref that stores the file paths that need to be deleted as keys. // The value will not be used. const char kStoreFilePathsToDelete[] = @@ -76,7 +72,6 @@ PrefRegistry::LOSSY_PREF); registry->RegisterDictionaryPref(kPreviouslyRegisteredOptimizationTypes, PrefRegistry::LOSSY_PREF); - registry->RegisterBooleanPref(kOptimizationGuideFetchingEnabled, true); registry->RegisterDictionaryPref(kStoreFilePathsToDelete, PrefRegistry::LOSSY_PREF); }
diff --git a/components/optimization_guide/core/optimization_guide_prefs.h b/components/optimization_guide/core/optimization_guide_prefs.h index 9a503d5e..220147b6 100644 --- a/components/optimization_guide/core/optimization_guide_prefs.h +++ b/components/optimization_guide/core/optimization_guide_prefs.h
@@ -16,7 +16,6 @@ extern const char kHintsFetcherHostsSuccessfullyFetched[]; extern const char kPendingHintsProcessingVersion[]; extern const char kPreviouslyRegisteredOptimizationTypes[]; -extern const char kOptimizationGuideFetchingEnabled[]; extern const char kStoreFilePathsToDelete[]; // Registers the optimization guide's prefs.
diff --git a/components/optimization_guide/core/prediction_manager.cc b/components/optimization_guide/core/prediction_manager.cc index 4725fcaf..817933c4 100644 --- a/components/optimization_guide/core/prediction_manager.cc +++ b/components/optimization_guide/core/prediction_manager.cc
@@ -7,6 +7,7 @@ #include <memory> #include <utility> +#include "base/callback.h" #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" #include "base/containers/flat_tree.h" @@ -139,9 +140,9 @@ // Returns whether models should be fetched from the // remote Optimization Guide Service. -bool ShouldFetchModels(bool off_the_record, PrefService* pref_service) { - return features::IsRemoteFetchingEnabled(pref_service) && !off_the_record && - features::IsModelDownloadingEnabled(); +bool ShouldFetchModels(bool off_the_record, bool component_updates_enabled) { + return features::IsRemoteFetchingEnabled() && !off_the_record && + features::IsModelDownloadingEnabled() && component_updates_enabled; } // Returns whether the model metadata proto is on the server allowlist. @@ -183,12 +184,14 @@ const std::string& application_locale, const base::FilePath& models_dir_path, OptimizationGuideLogger* optimization_guide_logger, - BackgroundDownloadServiceProvider background_download_service_provider) + BackgroundDownloadServiceProvider background_download_service_provider, + ComponentUpdatesEnabledProvider component_updates_enabled_provider) : prediction_model_download_manager_(nullptr), model_and_features_store_(model_and_features_store), url_loader_factory_(url_loader_factory), optimization_guide_logger_(optimization_guide_logger), pref_service_(pref_service), + component_updates_enabled_provider_(component_updates_enabled_provider), clock_(base::DefaultClock::GetInstance()), off_the_record_(off_the_record), application_locale_(application_locale), @@ -816,7 +819,8 @@ } void PredictionManager::MaybeScheduleFirstModelFetch() { - if (!ShouldFetchModels(off_the_record_, pref_service_)) + if (!ShouldFetchModels(off_the_record_, + component_updates_enabled_provider_.Run())) return; // Add a slight delay to allow the rest of the browser startup process to
diff --git a/components/optimization_guide/core/prediction_manager.h b/components/optimization_guide/core/prediction_manager.h index 5e3022b..ea909f36 100644 --- a/components/optimization_guide/core/prediction_manager.h +++ b/components/optimization_guide/core/prediction_manager.h
@@ -9,6 +9,7 @@ #include <string> #include <vector> +#include "base/callback.h" #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" #include "base/containers/lru_cache.h" @@ -53,8 +54,11 @@ // BackgroundDownloadService is only available once the profile is fully // initialized and that cannot be done as part of |Initialize|. Get a provider // to retrieve the service when it is needed. - typedef base::OnceCallback<download::BackgroundDownloadService*(void)> - BackgroundDownloadServiceProvider; + using BackgroundDownloadServiceProvider = + base::OnceCallback<download::BackgroundDownloadService*(void)>; + + // Callback to whether component updates are enabled for the browser. + using ComponentUpdatesEnabledProvider = base::RepeatingCallback<bool(void)>; PredictionManager( base::WeakPtr<OptimizationGuideStore> model_and_features_store, @@ -64,7 +68,8 @@ const std::string& application_locale, const base::FilePath& models_dir_path, OptimizationGuideLogger* optimization_guide_logger, - BackgroundDownloadServiceProvider background_dowload_service_provider); + BackgroundDownloadServiceProvider background_download_service_provider, + ComponentUpdatesEnabledProvider component_updates_enabled_provider); PredictionManager(const PredictionManager&) = delete; PredictionManager& operator=(const PredictionManager&) = delete; @@ -286,6 +291,10 @@ // A reference to the PrefService for this profile. Not owned. raw_ptr<PrefService> pref_service_ = nullptr; + // The repeating callback that will be used to determine if component updates + // are enabled. + ComponentUpdatesEnabledProvider component_updates_enabled_provider_; + // Time the prediction manager got initialized. base::TimeTicks init_time_;
diff --git a/components/optimization_guide/core/prediction_manager_unittest.cc b/components/optimization_guide/core/prediction_manager_unittest.cc index ee849c7..a422329 100644 --- a/components/optimization_guide/core/prediction_manager_unittest.cc +++ b/components/optimization_guide/core/prediction_manager_unittest.cc
@@ -349,6 +349,7 @@ base::WeakPtr<OptimizationGuideStore> model_and_features_store, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, PrefService* pref_service, + ComponentUpdatesEnabledProvider component_updates_enabled_provider, bool off_the_record, const std::string& application_locale, const base::FilePath& models_dir_path) @@ -361,7 +362,8 @@ models_dir_path, &optimization_guide_logger_, /*background_download_service_provider=*/ - base::OnceCallback<download::BackgroundDownloadService*()>()) {} + base::OnceCallback<download::BackgroundDownloadService*()>(), + component_updates_enabled_provider) {} ~TestPredictionManager() override = default; @@ -403,7 +405,11 @@ model_and_features_store_ = CreateModelAndHostModelFeaturesStore(); prediction_manager_ = std::make_unique<TestPredictionManager>( model_and_features_store_->AsWeakPtr(), url_loader_factory_, - pref_service_.get(), false, "en-US", temp_dir()); + pref_service_.get(), + base::BindRepeating( + &PredictionManagerTestBase::AreComponentUpdatesEnabled, + base::Unretained(this)), + false, "en-US", temp_dir()); prediction_manager_->SetClockForTesting(task_environment_.GetMockClock()); } @@ -473,11 +479,12 @@ base::test::TaskEnvironment* task_environment() { return &task_environment_; } - void SetOptimizationGuideFetchingPrefEnabled(bool enabled) { - pref_service_->SetBoolean(prefs::kOptimizationGuideFetchingEnabled, - enabled); + void SetComponentUpdatesPrefEnabled(bool enabled) { + component_updates_enabled_ = enabled; } + bool AreComponentUpdatesEnabled() const { return component_updates_enabled_; } + protected: // |feature_list_| needs to be destroyed after |task_environment_|, to avoid // tsan flakes caused by other tasks running while |feature_list_| is @@ -494,6 +501,8 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; network::TestURLLoaderFactory test_url_loader_factory_; std::unique_ptr<TestingPrefServiceSimple> pref_service_; + std::unique_ptr<TestingPrefServiceSimple> local_state_prefs_; + bool component_updates_enabled_ = true; }; class PredictionManagerRemoteFetchingDisabledTest @@ -567,7 +576,7 @@ }; TEST_F(PredictionManagerTest, RemoteFetchingPrefDisabled) { - SetOptimizationGuideFetchingPrefEnabled(false); + SetComponentUpdatesPrefEnabled(false); CreatePredictionManager(); prediction_manager()->SetPredictionModelFetcherForTesting(
diff --git a/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc b/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc index f7f1876..bb710b7 100644 --- a/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc +++ b/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc
@@ -35,7 +35,6 @@ #include "components/subresource_filter/core/common/common_features.h" #include "components/subresource_filter/core/common/load_policy.h" #include "components/subresource_filter/core/mojom/subresource_filter.mojom.h" -#include "components/ukm/content/source_url_recorder.h" #include "content/public/browser/global_request_id.h" #include "content/public/browser/global_routing_id.h" #include "content/public/browser/navigation_handle.h"
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/InvalidPaymentRequest.java b/components/payments/content/android/java/src/org/chromium/components/payments/InvalidPaymentRequest.java index d84679a..8d0d27d 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/InvalidPaymentRequest.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/InvalidPaymentRequest.java
@@ -30,11 +30,6 @@ @Override public void show(boolean unusedWaitForUpdatedDetails) { - showNew(unusedWaitForUpdatedDetails); - } - - @Override - public void showNew(boolean unusedWaitForUpdatedDetails) { if (mClient != null) { mClient.onError(PaymentErrorReason.USER_CANCEL, ErrorStrings.WEB_PAYMENT_API_DISABLED); mClient.close();
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/MojoPaymentRequestGateKeeper.java b/components/payments/content/android/java/src/org/chromium/components/payments/MojoPaymentRequestGateKeeper.java index 6b58ae0..1c1ca64 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/MojoPaymentRequestGateKeeper.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/MojoPaymentRequestGateKeeper.java
@@ -65,12 +65,6 @@ // Implement PaymentRequest: @Override public void show(boolean waitForUpdatedDetails) { - showNew(waitForUpdatedDetails); - } - - // Implement PaymentRequest: - @Override - public void showNew(boolean waitForUpdatedDetails) { if (mPaymentRequestService == null) return; mPaymentRequestService.show(waitForUpdatedDetails); }
diff --git a/components/payments/content/payment_request.cc b/components/payments/content/payment_request.cc index 63098bf..1a606ac2 100644 --- a/components/payments/content/payment_request.cc +++ b/components/payments/content/payment_request.cc
@@ -276,10 +276,6 @@ } void PaymentRequest::Show(bool wait_for_updated_details) { - ShowNew(wait_for_updated_details); -} - -void PaymentRequest::ShowNew(bool wait_for_updated_details) { if (!IsInitialized()) { log_.Error(errors::kCannotShowWithoutInit); ResetAndDeleteThis();
diff --git a/components/payments/content/payment_request.h b/components/payments/content/payment_request.h index b3b9de34..877b14c3 100644 --- a/components/payments/content/payment_request.h +++ b/components/payments/content/payment_request.h
@@ -95,7 +95,6 @@ mojom::PaymentDetailsPtr details, mojom::PaymentOptionsPtr options) override; void Show(bool wait_for_updated_details) override; - void ShowNew(bool wait_for_updated_details) override; void Retry(mojom::PaymentValidationErrorsPtr errors) override; void UpdateWith(mojom::PaymentDetailsPtr details) override; void OnPaymentDetailsNotUpdated() override;
diff --git a/components/permissions/permission_uma_util.cc b/components/permissions/permission_uma_util.cc index d4118d85..1b503d02 100644 --- a/components/permissions/permission_uma_util.cc +++ b/components/permissions/permission_uma_util.cc
@@ -20,7 +20,6 @@ #include "components/permissions/prediction_service/prediction_common.h" #include "components/permissions/prediction_service/prediction_request_features.h" #include "components/permissions/request_type.h" -#include "components/ukm/content/source_url_recorder.h" #include "content/public/browser/web_contents.h" #include "services/metrics/public/cpp/metrics_utils.h" #include "services/metrics/public/cpp/ukm_builders.h"
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index e801bc1c..21f7ae3 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -2163,7 +2163,7 @@ If the policy is left unset, Journeys will be visible at chrome://history/journeys by default and users can change the visibility of Journeys. - Please note, if <ph name="OPTIMIZATION_GUIDE_FETCHING_ENABLED_POLICY_NAME">OptimizationGuideFetchingEnabled</ph> policy is set to Disabled, but <ph name="HISTORY_CLUSTERS_VISIBLE_POLICY_NAME">HistoryClustersVisible</ph> is set to Enabled or unset, Journeys will still be available at chrome://history/journeys, but may be absent from the omnibox, and less relevant to the user. + Please note, if <ph name="COMPONENT_UPDATES_ENABLED_POLICY_NAME">ComponentUpdatesEnabled</ph> policy is set to Disabled, but <ph name="HISTORY_CLUSTERS_VISIBLE_POLICY_NAME">HistoryClustersVisible</ph> is set to Enabled or unset, Journeys will still be available at chrome://history/journeys, but may be absent from the omnibox, and less relevant to the user. ''', }, { @@ -30636,7 +30636,7 @@ 'owners': ['file://components/optimization_guide/OWNERS', 'sophiechang@chromium.org'], 'type': 'main', 'schema': { 'type': 'boolean' }, - 'supported_on': ['android:101-', 'chrome.*:101-', 'chrome_os:101-', 'ios:101-'], + 'supported_on': ['android:101-103', 'chrome.*:101-103', 'chrome_os:101-103', 'ios:101-103'], 'features': { 'dynamic_refresh': False, 'per_profile': True, @@ -30652,6 +30652,7 @@ }, ], 'default': True, + 'deprecated': True, 'example_value': True, 'id': 963, 'caption': '''Enable Optimization Guide Fetching''',
diff --git a/components/reporting/client/report_queue.h b/components/reporting/client/report_queue.h index 065890a4..50e5186d 100644 --- a/components/reporting/client/report_queue.h +++ b/components/reporting/client/report_queue.h
@@ -147,7 +147,8 @@ // Prepares a callback to attach actual queue to the speculative. // Implemented only in SpeculativeReportQueue, CHECKs in a regular one. - virtual base::OnceCallback<void(StatusOr<std::unique_ptr<ReportQueue>>)> + [[nodiscard]] virtual base::OnceCallback< + void(StatusOr<std::unique_ptr<ReportQueue>>)> PrepareToAttachActualQueue() const = 0; protected:
diff --git a/components/reporting/client/report_queue_impl.h b/components/reporting/client/report_queue_impl.h index 2b603c99..344b1ec 100644 --- a/components/reporting/client/report_queue_impl.h +++ b/components/reporting/client/report_queue_impl.h
@@ -54,7 +54,7 @@ void Flush(Priority priority, FlushCallback callback) override; // Dummy implementation for a regular queue. - base::OnceCallback<void(StatusOr<std::unique_ptr<ReportQueue>>)> + [[nodiscard]] base::OnceCallback<void(StatusOr<std::unique_ptr<ReportQueue>>)> PrepareToAttachActualQueue() const override; protected: @@ -70,7 +70,8 @@ Priority priority, EnqueueCallback callback) const; - reporting::Record AugmentRecord(base::StringPiece record_data) const; + [[nodiscard]] reporting::Record AugmentRecord( + base::StringPiece record_data) const; std::unique_ptr<ReportQueueConfiguration> config_; scoped_refptr<StorageModuleInterface> storage_; @@ -93,7 +94,7 @@ // Provides a callback to attach initialized actual queue to the speculative // queue. - base::OnceCallback<void(StatusOr<std::unique_ptr<ReportQueue>>)> + [[nodiscard]] base::OnceCallback<void(StatusOr<std::unique_ptr<ReportQueue>>)> PrepareToAttachActualQueue() const override; // Substitutes actual queue to the speculative, when ready.
diff --git a/components/reporting/compression/decompression.h b/components/reporting/compression/decompression.h index b87e5ed5..140b0a5 100644 --- a/components/reporting/compression/decompression.h +++ b/components/reporting/compression/decompression.h
@@ -29,7 +29,7 @@ // string then can be further updated by the caller. std::string is used // instead of base::StringPiece because ownership is taken of |record| through // std::move(record). - static std::string DecompressRecord( + [[nodiscard]] static std::string DecompressRecord( std::string record, CompressionInformation compression_information); @@ -46,4 +46,4 @@ } // namespace reporting -#endif // COMPONENTS_REPORTING_COMPRESSION_DECOMPRESSION_H_ \ No newline at end of file +#endif // COMPONENTS_REPORTING_COMPRESSION_DECOMPRESSION_H_
diff --git a/components/reporting/encryption/decryption.cc b/components/reporting/encryption/decryption.cc index d8b9a7d..70e94fc 100644 --- a/components/reporting/encryption/decryption.cc +++ b/components/reporting/encryption/decryption.cc
@@ -16,7 +16,6 @@ #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" -#include "base/task/post_task.h" #include "base/task/task_runner.h" #include "base/task/thread_pool.h" #include "components/reporting/encryption/encryption.h"
diff --git a/components/reporting/encryption/encryption.cc b/components/reporting/encryption/encryption.cc index e3b5b82..d2e9eb8 100644 --- a/components/reporting/encryption/encryption.cc +++ b/components/reporting/encryption/encryption.cc
@@ -15,7 +15,6 @@ #include "base/memory/ptr_util.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" -#include "base/task/post_task.h" #include "base/task/task_runner.h" #include "base/task/thread_pool.h" #include "components/reporting/encryption/primitives.h"
diff --git a/components/reporting/storage/storage_queue.cc b/components/reporting/storage/storage_queue.cc index 85068a6b..0d350d4 100644 --- a/components/reporting/storage/storage_queue.cc +++ b/components/reporting/storage/storage_queue.cc
@@ -34,7 +34,6 @@ #include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" -#include "base/task/post_task.h" #include "base/task/task_runner.h" #include "base/task/thread_pool.h" #include "components/reporting/compression/compression_module.h"
diff --git a/components/reporting/util/status.h b/components/reporting/util/status.h index 30b182f..1f6a2cc 100644 --- a/components/reporting/util/status.h +++ b/components/reporting/util/status.h
@@ -43,7 +43,7 @@ }; } // namespace error -class Status { +class [[nodiscard]] Status { public: // Creates a "successful" status. Status();
diff --git a/components/reporting/util/statusor.h b/components/reporting/util/statusor.h index bfa5acd..66ab50b 100644 --- a/components/reporting/util/statusor.h +++ b/components/reporting/util/statusor.h
@@ -81,7 +81,7 @@ } // namespace internal template <typename T> -class StatusOr { +class [[nodiscard]] StatusOr { template <typename U> friend class StatusOr;
diff --git a/components/segmentation_platform/internal/database/metadata_utils.cc b/components/segmentation_platform/internal/database/metadata_utils.cc index b850b51..a3ceff8 100644 --- a/components/segmentation_platform/internal/database/metadata_utils.cc +++ b/components/segmentation_platform/internal/database/metadata_utils.cc
@@ -106,7 +106,8 @@ } ValidationResult ValidateMetadataUmaFeature(const proto::UMAFeature& feature) { - if (feature.type() == proto::SignalType::UNKNOWN_SIGNAL_TYPE) + if (feature.type() == proto::SignalType::UNKNOWN_SIGNAL_TYPE || + feature.type() == proto::SignalType::UKM_EVENT) return ValidationResult::kSignalTypeInvalid; if ((feature.type() == proto::SignalType::HISTOGRAM_ENUM || @@ -295,6 +296,7 @@ return SignalKey::Kind::HISTOGRAM_ENUM; case proto::SignalType::HISTOGRAM_VALUE: return SignalKey::Kind::HISTOGRAM_VALUE; + case proto::SignalType::UKM_EVENT: case proto::SignalType::UNKNOWN_SIGNAL_TYPE: return SignalKey::Kind::UNKNOWN; }
diff --git a/components/segmentation_platform/internal/database/metadata_utils_unittest.cc b/components/segmentation_platform/internal/database/metadata_utils_unittest.cc index a272e4b..5fcbce1 100644 --- a/components/segmentation_platform/internal/database/metadata_utils_unittest.cc +++ b/components/segmentation_platform/internal/database/metadata_utils_unittest.cc
@@ -90,6 +90,10 @@ EXPECT_EQ(metadata_utils::ValidationResult::kSignalTypeInvalid, metadata_utils::ValidateMetadataUmaFeature(feature)); + feature.set_type(proto::SignalType::UKM_EVENT); + EXPECT_EQ(metadata_utils::ValidationResult::kSignalTypeInvalid, + metadata_utils::ValidateMetadataUmaFeature(feature)); + // name not required for USER_ACTION. feature.set_type(proto::SignalType::USER_ACTION); EXPECT_EQ(metadata_utils::ValidationResult::kFeatureNameHashNotFound,
diff --git a/components/segmentation_platform/internal/database/signal_storage_config.cc b/components/segmentation_platform/internal/database/signal_storage_config.cc index c674127..033fd653 100644 --- a/components/segmentation_platform/internal/database/signal_storage_config.cc +++ b/components/segmentation_platform/internal/database/signal_storage_config.cc
@@ -63,11 +63,13 @@ proto::SignalStorageConfig* SignalStorageConfig::FindSignal( uint64_t signal_hash, + uint64_t event_hash, proto::SignalType signal_type) { // TODO(shaktisahu): May be have an internal map of signals. for (int i = 0; i < config_.signals().size(); ++i) { auto* signal_config = config_.mutable_signals(i); if (signal_config->name_hash() == signal_hash && + signal_config->event_hash() == event_hash && signal_config->signal_type() == signal_type) { return signal_config; } @@ -75,6 +77,35 @@ return nullptr; } +bool SignalStorageConfig::UpdateConfigForSignal(int signal_storage_length, + uint64_t signal_hash, + uint64_t event_hash, + proto::SignalType signal_type) { + proto::SignalStorageConfig* config = + FindSignal(signal_hash, event_hash, signal_type); + if (config) { + if (config->storage_length_s() < signal_storage_length) { + // We found a model that has a longer storage length requirement. Update + // it to DB. + config->set_storage_length_s(signal_storage_length); + return true; + } + } else { + // This is the first time we have encountered this signal. Just create an + // entry in the DB, and set collection start time. + proto::SignalStorageConfig* signal_config = config_.add_signals(); + signal_config->set_name_hash(signal_hash); + if (signal_type == proto::SignalType::UKM_EVENT) + signal_config->set_event_hash(event_hash); + signal_config->set_signal_type(signal_type); + signal_config->set_storage_length_s(signal_storage_length); + signal_config->set_collection_start_time_s( + clock_->Now().ToDeltaSinceWindowsEpoch().InSeconds()); + return true; + } + return false; +} + bool SignalStorageConfig::MeetsSignalCollectionRequirement( const proto::SegmentationModelMetadata& model_metadata, bool include_outputs) { @@ -98,7 +129,7 @@ } proto::SignalStorageConfig* config = - FindSignal(feature.name_hash(), feature.type()); + FindSignal(feature.name_hash(), 0, feature.type()); if (!config || config->collection_start_time_s() == 0) return false; @@ -108,6 +139,8 @@ return false; } + // TODO(haileywang): Handle UKM features. + return true; } @@ -126,29 +159,36 @@ metadata_utils::ValidationResult::kValidationSuccess) { continue; } - - proto::SignalStorageConfig* config = - FindSignal(feature.name_hash(), feature.type()); - if (config) { - if (config->storage_length_s() < signal_storage_length) { - // We found a model that has a longer storage length requirement. Update - // it to DB. - config->set_storage_length_s(signal_storage_length); - is_dirty = true; - } - } else { - // This is the first time we have encountered this signal. Just create an - // entry in the DB, and set collection start time. - proto::SignalStorageConfig* signal_config = config_.add_signals(); - signal_config->set_name_hash(feature.name_hash()); - signal_config->set_signal_type(feature.type()); - signal_config->set_storage_length_s(signal_storage_length); - signal_config->set_collection_start_time_s( - clock_->Now().ToDeltaSinceWindowsEpoch().InSeconds()); + if (UpdateConfigForSignal(signal_storage_length, feature.name_hash(), 0, + feature.type())) { is_dirty = true; } } + // Add signals for sql features. + for (auto const& feature : model_metadata.input_features()) { + if (!feature.has_sql_feature()) + continue; + + if (metadata_utils::ValidateMetadataSqlFeature(feature.sql_feature()) != + metadata_utils::ValidationResult::kValidationSuccess) { + continue; + } + + const proto::SignalFilterConfig& sql_config = + feature.sql_feature().signal_filter(); + + for (auto const& event : sql_config.ukm_events()) { + for (auto const& metric_hash : event.metric_hash_filter()) { + if (UpdateConfigForSignal(signal_storage_length, metric_hash, + event.event_hash(), + proto::SignalType::UKM_EVENT)) { + is_dirty = true; + } + } + } + } + if (is_dirty) WriteToDB(); } @@ -158,6 +198,7 @@ std::vector<std::tuple<uint64_t, proto::SignalType, base::Time>>& result) const { // Collect the signals that have longer than required data. + // TODO(haileywang): Handle UKM signals. for (int i = 0; i < config_.signals_size(); ++i) { const auto& signal_config = config_.signals(i); base::Time collection_start_time = base::Time::FromDeltaSinceWindowsEpoch( @@ -202,7 +243,7 @@ base::Time timestamp = std::get<2>(tuple); proto::SignalStorageConfig* signal_config = - FindSignal(name_hash, signal_type); + FindSignal(name_hash, 0, signal_type); if (!signal_config) continue;
diff --git a/components/segmentation_platform/internal/database/signal_storage_config.h b/components/segmentation_platform/internal/database/signal_storage_config.h index f8dbfcd..16d80d7 100644 --- a/components/segmentation_platform/internal/database/signal_storage_config.h +++ b/components/segmentation_platform/internal/database/signal_storage_config.h
@@ -85,8 +85,14 @@ std::unique_ptr<std::vector<proto::SignalStorageConfigs>> entries); proto::SignalStorageConfig* FindSignal(uint64_t signal_hash, + uint64_t event_hash, proto::SignalType signal_type); + bool UpdateConfigForSignal(int signal_storage_length, + uint64_t signal_hash, + uint64_t event_hash, + proto::SignalType signal_type); + // Helper method to flush the cached data to the DB. Called whenever the cache // is dirty. void WriteToDB();
diff --git a/components/segmentation_platform/internal/database/signal_storage_config_unittest.cc b/components/segmentation_platform/internal/database/signal_storage_config_unittest.cc index 8c2015e..2e3137f 100644 --- a/components/segmentation_platform/internal/database/signal_storage_config_unittest.cc +++ b/components/segmentation_platform/internal/database/signal_storage_config_unittest.cc
@@ -13,6 +13,8 @@ #include "components/leveldb_proto/public/proto_database.h" #include "components/leveldb_proto/testing/fake_db.h" #include "components/segmentation_platform/internal/proto/aggregation.pb.h" +#include "components/segmentation_platform/internal/proto/model_metadata.pb.h" +#include "components/segmentation_platform/internal/proto/signal_storage_config.pb.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -174,6 +176,87 @@ EXPECT_NE(0, signal_config.collection_start_time_s()); } +TEST_F(SignalStorageConfigTest, + CheckMeetsSignalCollectionRequirementWithSqlFeature) { + // Start with empty DB. + SetUpDB(); + base::MockCallback<SignalStorageConfig::SuccessCallback> init_callback; + EXPECT_CALL(init_callback, Run(true)).Times(1); + signal_storage_config_->InitAndLoad(init_callback.Get()); + db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK); + db_->LoadCallback(true); + EXPECT_EQ(0u, db_entries_.size()); + + // Create a model metadata. + proto::SegmentationModelMetadata metadata; + metadata.set_time_unit(proto::TimeUnit::DAY); + metadata.set_signal_storage_length(2); + metadata.set_min_signal_collection_length(2); + + // Create a second model metadata with longer requirement. + proto::SegmentationModelMetadata metadata2; + metadata2.set_time_unit(proto::TimeUnit::DAY); + metadata2.set_signal_storage_length(6); + metadata2.set_min_signal_collection_length(4); + + // Add a sql feature to both models. + proto::InputFeature* input_feature = metadata.add_input_features(); + proto::SqlFeature* feature = input_feature->mutable_sql_feature(); + proto::SignalFilterConfig::UkmEvent* ukm_event = + feature->mutable_signal_filter()->add_ukm_events(); + uint64_t event_hash = base::HashMetricName("some event"); + uint64_t metric_hash = base::HashMetricName("some metric"); + feature->set_sql("sql"); + ukm_event->set_event_hash(event_hash); + ukm_event->add_metric_hash_filter(metric_hash); + + proto::InputFeature* input_feature2 = metadata2.add_input_features(); + proto::SqlFeature* feature2 = input_feature2->mutable_sql_feature(); + proto::SignalFilterConfig::UkmEvent* ukm_event2 = + feature2->mutable_signal_filter()->add_ukm_events(); + feature2->set_sql("sql"); + ukm_event2->set_event_hash(event_hash); + ukm_event2->add_metric_hash_filter(metric_hash); + + // The DB should be empty before the model is added. + EXPECT_EQ(0u, db_entries_.size()); + + // Add the model. + signal_storage_config_->OnSignalCollectionStarted(metadata); + db_->UpdateCallback(true); + + // Verify that the DB has now a top level entry. + EXPECT_EQ(1u, db_entries_.size()); + const auto& config = db_entries_[kDatabaseKey]; + EXPECT_EQ(1, config.signals_size()); + + // Verify that DB has a signal entry with correct storage and collection start + // time. + proto::SignalStorageConfig signal_config = config.signals(0); + EXPECT_EQ(metric_hash, signal_config.name_hash()); + EXPECT_EQ(event_hash, signal_config.event_hash()); + EXPECT_EQ(proto::SignalType::UKM_EVENT, signal_config.signal_type()); + EXPECT_EQ(base::Days(2).InSeconds(), signal_config.storage_length_s()); + EXPECT_NE(0, signal_config.collection_start_time_s()); + + // Add the second model. It should do a overwrite of previous value. + signal_storage_config_->OnSignalCollectionStarted(metadata2); + db_->UpdateCallback(true); + + // Verify DB size. + EXPECT_EQ(1u, db_entries_.size()); + EXPECT_EQ(1, config.signals_size()); + + // Verify that DB has a signal entry with correct storage and collection start + // time. + signal_config = config.signals(0); + EXPECT_EQ(metric_hash, signal_config.name_hash()); + EXPECT_EQ(event_hash, signal_config.event_hash()); + EXPECT_EQ(proto::SignalType::UKM_EVENT, signal_config.signal_type()); + EXPECT_EQ(base::Days(6).InSeconds(), signal_config.storage_length_s()); + EXPECT_NE(0, signal_config.collection_start_time_s()); +} + TEST_F(SignalStorageConfigTest, CleanupSignals) { SetUpDB();
diff --git a/components/segmentation_platform/internal/database/storage_service.cc b/components/segmentation_platform/internal/database/storage_service.cc index 63d68b2..944e6562 100644 --- a/components/segmentation_platform/internal/database/storage_service.cc +++ b/components/segmentation_platform/internal/database/storage_service.cc
@@ -85,6 +85,18 @@ ukm_data_manager_->AddRef(); } +StorageService::StorageService( + std::unique_ptr<SegmentInfoDatabase> segment_info_database, + std::unique_ptr<SignalDatabase> signal_database, + std::unique_ptr<SignalStorageConfig> signal_storage_config, + std::unique_ptr<DefaultModelManager> default_model_manager, + UkmDataManager* ukm_data_manager) + : default_model_manager_(std::move(default_model_manager)), + segment_info_database_(std::move(segment_info_database)), + signal_database_(std::move(signal_database)), + signal_storage_config_(std::move(signal_storage_config)), + ukm_data_manager_(ukm_data_manager) {} + StorageService::~StorageService() { ukm_data_manager_->RemoveRef(); }
diff --git a/components/segmentation_platform/internal/database/storage_service.h b/components/segmentation_platform/internal/database/storage_service.h index ac76151..a5c33bb 100644 --- a/components/segmentation_platform/internal/database/storage_service.h +++ b/components/segmentation_platform/internal/database/storage_service.h
@@ -69,6 +69,7 @@ all_segment_ids, ModelProviderFactory* model_provider_factory); + // For tests: StorageService( std::unique_ptr<leveldb_proto::ProtoDatabase<proto::SegmentInfo>> segment_db, @@ -82,6 +83,13 @@ all_segment_ids, ModelProviderFactory* model_provider_factory); + // For tests: + StorageService(std::unique_ptr<SegmentInfoDatabase> segment_info_database, + std::unique_ptr<SignalDatabase> signal_database, + std::unique_ptr<SignalStorageConfig> signal_storage_config, + std::unique_ptr<DefaultModelManager> default_model_manager, + UkmDataManager* ukm_data_manager); + ~StorageService(); StorageService(StorageService&) = delete;
diff --git a/components/segmentation_platform/internal/proto/model_metadata.proto b/components/segmentation_platform/internal/proto/model_metadata.proto index df8d9aa2..3766b9b 100644 --- a/components/segmentation_platform/internal/proto/model_metadata.proto +++ b/components/segmentation_platform/internal/proto/model_metadata.proto
@@ -47,6 +47,8 @@ message UMAFeature { // The type of signal this feature refers to. + // Note: SignalType::UKM_EVENT type is only used for SignalStorageConfig and + // should not be used as uma feature's signal type. optional SignalType type = 1; // The human readable name of the histogram or user action. @@ -118,11 +120,10 @@ message UkmEvent { // Event hash of the UKM event. optional uint64 event_hash = 1; - // List of metric hashes for the event, to store in the database. If - // empty, the database will store all the metrics for the UKM event. It is - // is recommended to provide list of necessary metrics, unless it is clear - // that the list of metrics of the event is easily trackable and doesn't - // grow over time. + // List of metric hashes for the event, to store in the database. It is + // is required to provide list of necessary metrics. + // TODO: Support empty metric hash list, the database will store all the + // metrics for the UKM event. repeated uint64 metric_hash_filter = 2; } // List of UKM events to store in the database.
diff --git a/components/segmentation_platform/internal/proto/signal_storage_config.proto b/components/segmentation_platform/internal/proto/signal_storage_config.proto index f3b1fa6..c9b3525b 100644 --- a/components/segmentation_platform/internal/proto/signal_storage_config.proto +++ b/components/segmentation_platform/internal/proto/signal_storage_config.proto
@@ -12,9 +12,13 @@ // Contains storage related information about a particular signal useful for // determining eligibility for model evaluation and DB cleanups. message SignalStorageConfig { - // The name (hash) of the user action or histogram. + // The name hash of the user action/histogram or the metric hash of the ukm + // event. optional uint64 name_hash = 1; + // The event hash of the ukm event. Only filled if signal type is UKM_EVENT. + optional uint64 event_hash = 5; + // The type of the signal. optional SignalType signal_type = 2;
diff --git a/components/segmentation_platform/internal/proto/types.proto b/components/segmentation_platform/internal/proto/types.proto index 9452ca3a..7d32b6c1 100644 --- a/components/segmentation_platform/internal/proto/types.proto +++ b/components/segmentation_platform/internal/proto/types.proto
@@ -13,4 +13,5 @@ USER_ACTION = 1; HISTOGRAM_ENUM = 2; HISTOGRAM_VALUE = 3; + UKM_EVENT = 4; }
diff --git a/components/segmentation_platform/internal/segmentation_platform_service_impl.cc b/components/segmentation_platform/internal/segmentation_platform_service_impl.cc index 1e703dd..675be866 100644 --- a/components/segmentation_platform/internal/segmentation_platform_service_impl.cc +++ b/components/segmentation_platform/internal/segmentation_platform_service_impl.cc
@@ -87,11 +87,8 @@ all_segment_ids_.end()); // Construct signal processors. - signal_handler_.Initialize( - storage_service_->signal_database(), - storage_service_->segment_info_database(), - storage_service_->ukm_data_manager(), init_params->history_service, - storage_service_->default_model_manager(), segment_id_vec); + signal_handler_.Initialize(storage_service_.get(), + init_params->history_service, segment_id_vec); for (const auto& config : configs_) { segment_selectors_[config->segmentation_key] =
diff --git a/components/segmentation_platform/internal/signals/history_service_observer.cc b/components/segmentation_platform/internal/signals/history_service_observer.cc index b5a764f..f09327d 100644 --- a/components/segmentation_platform/internal/signals/history_service_observer.cc +++ b/components/segmentation_platform/internal/signals/history_service_observer.cc
@@ -4,22 +4,30 @@ #include "components/segmentation_platform/internal/signals/history_service_observer.h" +#include "base/metrics/user_metrics.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_service_observer.h" +#include "components/segmentation_platform/internal/database/segment_info_database.h" +#include "components/segmentation_platform/internal/database/storage_service.h" #include "components/segmentation_platform/internal/signals/history_delegate_impl.h" #include "components/segmentation_platform/internal/signals/url_signal_handler.h" +#include "components/segmentation_platform/internal/ukm_data_manager.h" namespace segmentation_platform { HistoryServiceObserver::HistoryServiceObserver( history::HistoryService* history_service, - UrlSignalHandler* url_signal_handler) - : url_signal_handler_(url_signal_handler), + StorageService* storage_service) + : storage_service_(storage_service), + url_signal_handler_( + storage_service->ukm_data_manager()->GetOrCreateUrlHandler()), history_delegate_( std::make_unique<HistoryDelegateImpl>(history_service, - url_signal_handler)) { + url_signal_handler_)) { history_observation_.Observe(history_service); } +HistoryServiceObserver::HistoryServiceObserver() + : storage_service_(nullptr), url_signal_handler_(nullptr) {} HistoryServiceObserver::~HistoryServiceObserver() = default; @@ -36,6 +44,15 @@ void HistoryServiceObserver::OnURLsDeleted( history::HistoryService* history_service, const history::DeletionInfo& deletion_info) { + // If the history deletion was not from expiration or if the whole history + // database was removed, delete the segment results computed based on URL + // data. + if (deletion_info.IsAllHistory() || !deletion_info.is_from_expiration()) { + base::RecordAction( + base::UserMetricsAction("SegmentationPurgeTriggeredByHistoryDelete")); + DeleteResultsForHistoryBasedSegments(); + } + if (deletion_info.IsAllHistory()) { url_signal_handler_->OnUrlsRemovedFromHistory({}, /*all_urls=*/true); return; @@ -47,4 +64,31 @@ history_delegate_->OnUrlRemoved(urls); } +void HistoryServiceObserver::SetHistoryBasedSegments( + base::flat_set<optimization_guide::proto::OptimizationTarget>&& + history_based_segments) { + history_based_segments_ = std::move(history_based_segments); + // If a delete is pending, clear the results now. + if (pending_deletion_based_on_history_based_segments_) { + DeleteResultsForHistoryBasedSegments(); + + // Only clear results once on first init. This method can be called multiple + // times during the session when model updates. + pending_deletion_based_on_history_based_segments_ = false; + } +} + +void HistoryServiceObserver::DeleteResultsForHistoryBasedSegments() { + if (!history_based_segments_) { + // Set the delete flag to clear the history based results when + // SetHistoryBasedSegments() is called. + pending_deletion_based_on_history_based_segments_ = true; + return; + } + for (const auto segment_id : *history_based_segments_) { + storage_service_->segment_info_database()->SaveSegmentResult( + segment_id, absl::nullopt, base::DoNothing()); + } +} + } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/signals/history_service_observer.h b/components/segmentation_platform/internal/signals/history_service_observer.h index 0c66f28..3aca0ef49 100644 --- a/components/segmentation_platform/internal/signals/history_service_observer.h +++ b/components/segmentation_platform/internal/signals/history_service_observer.h
@@ -5,22 +5,28 @@ #ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SIGNALS_HISTORY_SERVICE_OBSERVER_H_ #define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SIGNALS_HISTORY_SERVICE_OBSERVER_H_ +#include "base/containers/flat_set.h" #include "base/memory/raw_ptr.h" #include "base/scoped_observation.h" #include "base/time/time.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_service_observer.h" +#include "components/optimization_guide/proto/models.pb.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace segmentation_platform { class HistoryDelegateImpl; +class StorageService; class UrlSignalHandler; // Observes history service for visits. class HistoryServiceObserver : public history::HistoryServiceObserver { public: HistoryServiceObserver(history::HistoryService* history_service, - UrlSignalHandler* url_signal_handler); + StorageService* storage_service); + // For tests. + HistoryServiceObserver(); ~HistoryServiceObserver() override; HistoryServiceObserver(HistoryServiceObserver&) = delete; @@ -35,8 +41,23 @@ void OnURLsDeleted(history::HistoryService* history_service, const history::DeletionInfo& deletion_info) override; + // Sets the list of segment IDs that are based on history data. + virtual void SetHistoryBasedSegments( + base::flat_set<optimization_guide::proto::OptimizationTarget>&& + history_based_segments); + private: - raw_ptr<UrlSignalHandler> url_signal_handler_; + void DeleteResultsForHistoryBasedSegments(); + + const raw_ptr<StorageService> storage_service_; + const raw_ptr<UrlSignalHandler> url_signal_handler_; + + // List of segment IDs that depend on history data, that will be cleared when + // history is deleted. + absl::optional<base::flat_set<optimization_guide::proto::OptimizationTarget>> + history_based_segments_; + bool pending_deletion_based_on_history_based_segments_ = false; + std::unique_ptr<HistoryDelegateImpl> history_delegate_; base::ScopedObservation<history::HistoryService, history::HistoryServiceObserver>
diff --git a/components/segmentation_platform/internal/signals/signal_filter_processor.cc b/components/segmentation_platform/internal/signals/signal_filter_processor.cc index 808f09e..185f240a 100644 --- a/components/segmentation_platform/internal/signals/signal_filter_processor.cc +++ b/components/segmentation_platform/internal/signals/signal_filter_processor.cc
@@ -9,10 +9,13 @@ #include "base/logging.h" #include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/segment_info_database.h" +#include "components/segmentation_platform/internal/database/storage_service.h" #include "components/segmentation_platform/internal/execution/default_model_manager.h" #include "components/segmentation_platform/internal/proto/model_prediction.pb.h" #include "components/segmentation_platform/internal/proto/types.pb.h" #include "components/segmentation_platform/internal/signals/histogram_signal_handler.h" +#include "components/segmentation_platform/internal/signals/history_service_observer.h" +#include "components/segmentation_platform/internal/signals/signal_handler.h" #include "components/segmentation_platform/internal/signals/ukm_config.h" #include "components/segmentation_platform/internal/signals/user_action_signal_handler.h" #include "components/segmentation_platform/internal/stats.h" @@ -29,13 +32,16 @@ const proto::SegmentInfo& segment_info = info->segment_info; const auto& metadata = segment_info.model_metadata(); AddUmaFeatures(metadata); - AddUkmFeatures(metadata); + if (AddUkmFeatures(metadata)) { + history_based_segments.insert(segment_info.segment_id()); + } } } std::set<uint64_t> user_actions; std::set<std::pair<std::string, proto::SignalType>> histograms; UkmConfig ukm_config; + base::flat_set<OptimizationTarget> history_based_segments; private: void AddUmaFeatures(const proto::SegmentationModelMetadata& metadata) { @@ -64,7 +70,8 @@ } } - void AddUkmFeatures(const proto::SegmentationModelMetadata& metadata) { + bool AddUkmFeatures(const proto::SegmentationModelMetadata& metadata) { + bool has_ukm_features = false; for (const auto& feature : metadata.input_features()) { for (const auto& ukm_event : feature.sql_feature().signal_filter().ukm_events()) { @@ -73,32 +80,32 @@ metrics.insert(UkmMetricHash::FromUnsafeValue(metric)); ukm_config.AddEvent( UkmEventHash::FromUnsafeValue(ukm_event.event_hash()), metrics); + has_ukm_features = true; } } + return has_ukm_features; } }; } // namespace SignalFilterProcessor::SignalFilterProcessor( - SegmentInfoDatabase* segment_database, + StorageService* storage_service, UserActionSignalHandler* user_action_signal_handler, HistogramSignalHandler* histogram_signal_handler, - UkmDataManager* ukm_data_manager, - DefaultModelManager* default_model_manager, + HistoryServiceObserver* history_observer, const std::vector<OptimizationTarget>& segment_ids) - : segment_database_(segment_database), + : storage_service_(storage_service), user_action_signal_handler_(user_action_signal_handler), histogram_signal_handler_(histogram_signal_handler), - ukm_data_manager_(ukm_data_manager), - default_model_manager_(default_model_manager), + history_observer_(history_observer), segment_ids_(segment_ids) {} SignalFilterProcessor::~SignalFilterProcessor() = default; void SignalFilterProcessor::OnSignalListUpdated() { - default_model_manager_->GetAllSegmentInfoFromBothModels( - segment_ids_, segment_database_, + storage_service_->default_model_manager()->GetAllSegmentInfoFromBothModels( + segment_ids_, storage_service_->segment_info_database(), base::BindOnce(&SignalFilterProcessor::FilterSignals, weak_ptr_factory_.GetWeakPtr())); } @@ -113,13 +120,19 @@ user_action_signal_handler_->SetRelevantUserActions( std::move(extractor.user_actions)); histogram_signal_handler_->SetRelevantHistograms(extractor.histograms); - ukm_data_manager_->StartObservingUkm(extractor.ukm_config); + storage_service_->ukm_data_manager()->StartObservingUkm(extractor.ukm_config); + + if (history_observer_) { + history_observer_->SetHistoryBasedSegments( + std::move(extractor.history_based_segments)); + } } void SignalFilterProcessor::EnableMetrics(bool enable_metrics) { user_action_signal_handler_->EnableMetrics(enable_metrics); histogram_signal_handler_->EnableMetrics(enable_metrics); - ukm_data_manager_->PauseOrResumeObservation(/*pause=*/!enable_metrics); + storage_service_->ukm_data_manager()->PauseOrResumeObservation( + /*pause=*/!enable_metrics); } } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/signals/signal_filter_processor.h b/components/segmentation_platform/internal/signals/signal_filter_processor.h index 1465966..26b4232 100644 --- a/components/segmentation_platform/internal/signals/signal_filter_processor.h +++ b/components/segmentation_platform/internal/signals/signal_filter_processor.h
@@ -15,20 +15,19 @@ namespace segmentation_platform { class HistogramSignalHandler; -class SegmentInfoDatabase; +class HistoryServiceObserver; +class StorageService; class UserActionSignalHandler; -class UkmDataManager; // Responsible for listening to the metadata updates for the models and // registers various signal handlers for the relevant UMA signals specified in // the metadata. class SignalFilterProcessor { public: - SignalFilterProcessor(SegmentInfoDatabase* segment_database, + SignalFilterProcessor(StorageService* storage_service, UserActionSignalHandler* user_action_signal_handler, HistogramSignalHandler* histogram_signal_handler, - UkmDataManager* ukm_data_manager, - DefaultModelManager* default_model_manager, + HistoryServiceObserver* history_observer, const std::vector<OptimizationTarget>& segment_ids); ~SignalFilterProcessor(); @@ -50,11 +49,10 @@ private: void FilterSignals(DefaultModelManager::SegmentInfoList segment_infos); - raw_ptr<SegmentInfoDatabase> segment_database_; - raw_ptr<UserActionSignalHandler> user_action_signal_handler_; - raw_ptr<HistogramSignalHandler> histogram_signal_handler_; - raw_ptr<UkmDataManager> ukm_data_manager_; - raw_ptr<DefaultModelManager> default_model_manager_; + const raw_ptr<StorageService> storage_service_; + const raw_ptr<UserActionSignalHandler> user_action_signal_handler_; + const raw_ptr<HistogramSignalHandler> histogram_signal_handler_; + const raw_ptr<HistoryServiceObserver> history_observer_; std::vector<OptimizationTarget> segment_ids_; base::WeakPtrFactory<SignalFilterProcessor> weak_ptr_factory_{this};
diff --git a/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc b/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc index dfc35a90..ff0ff53 100644 --- a/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc +++ b/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc
@@ -9,6 +9,9 @@ #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "components/segmentation_platform/internal/database/segment_info_database.h" +#include "components/segmentation_platform/internal/database/signal_database.h" +#include "components/segmentation_platform/internal/database/signal_storage_config.h" +#include "components/segmentation_platform/internal/database/storage_service.h" #include "components/segmentation_platform/internal/database/test_segment_info_database.h" #include "components/segmentation_platform/internal/execution/default_model_manager.h" #include "components/segmentation_platform/internal/execution/mock_model_provider.h" @@ -16,6 +19,7 @@ #include "components/segmentation_platform/internal/proto/aggregation.pb.h" #include "components/segmentation_platform/internal/proto/types.pb.h" #include "components/segmentation_platform/internal/signals/histogram_signal_handler.h" +#include "components/segmentation_platform/internal/signals/history_service_observer.h" #include "components/segmentation_platform/internal/signals/mock_histogram_signal_handler.h" #include "components/segmentation_platform/internal/signals/user_action_signal_handler.h" #include "testing/gmock/include/gmock/gmock.h" @@ -24,6 +28,7 @@ using testing::_; using testing::Contains; using testing::Invoke; +using testing::IsEmpty; using testing::SaveArg; namespace segmentation_platform { @@ -45,6 +50,14 @@ MOCK_METHOD(void, EnableMetrics, (bool)); }; +class MockHistoryObserver : public HistoryServiceObserver { + public: + MOCK_METHOD1( + SetHistoryBasedSegments, + void(base::flat_set<optimization_guide::proto::OptimizationTarget>&& + history_based_segments)); +}; + // Noop version. For database calls, just passes the calls to the DB. class TestDefaultModelManager : public DefaultModelManager { public: @@ -95,25 +108,32 @@ std::vector<OptimizationTarget> segment_ids( {OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB, OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE}); - segment_database_ = std::make_unique<test::TestSegmentInfoDatabase>(); user_action_signal_handler_ = std::make_unique<MockUserActionSignalHandler>(); histogram_signal_handler_ = std::make_unique<MockHistogramSignalHandler>(); + history_observer_ = std::make_unique<MockHistoryObserver>(); + + auto moved_segment_database = + std::make_unique<test::TestSegmentInfoDatabase>(); + segment_database_ = moved_segment_database.get(); ukm_data_manager_ = std::make_unique<MockUkmDataManager>(); - default_model_manager_ = std::make_unique<TestDefaultModelManager>(); + storage_service_ = std::make_unique<StorageService>( + std::move(moved_segment_database), nullptr, nullptr, + std::make_unique<TestDefaultModelManager>(), ukm_data_manager_.get()); + signal_filter_processor_ = std::make_unique<SignalFilterProcessor>( - segment_database_.get(), user_action_signal_handler_.get(), - histogram_signal_handler_.get(), ukm_data_manager_.get(), - default_model_manager_.get(), segment_ids); + storage_service_.get(), user_action_signal_handler_.get(), + histogram_signal_handler_.get(), history_observer_.get(), segment_ids); } base::test::TaskEnvironment task_environment_; - std::unique_ptr<test::TestSegmentInfoDatabase> segment_database_; std::unique_ptr<MockUserActionSignalHandler> user_action_signal_handler_; std::unique_ptr<MockHistogramSignalHandler> histogram_signal_handler_; - std::unique_ptr<TestDefaultModelManager> default_model_manager_; std::unique_ptr<SignalFilterProcessor> signal_filter_processor_; + std::unique_ptr<MockHistoryObserver> history_observer_; std::unique_ptr<MockUkmDataManager> ukm_data_manager_; + std::unique_ptr<StorageService> storage_service_; + raw_ptr<test::TestSegmentInfoDatabase> segment_database_; }; TEST_F(SignalFilterProcessorTest, UserActionRegistrationFlow) { @@ -168,6 +188,8 @@ } TEST_F(SignalFilterProcessorTest, UkmMetricsConfig) { + const OptimizationTarget kSegmentId = + OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB; EXPECT_CALL(*histogram_signal_handler_, SetRelevantHistograms( std::set<std::pair<std::string, proto::SignalType>>())) @@ -181,6 +203,7 @@ .WillOnce(Invoke([](const UkmConfig& actual_config) { EXPECT_EQ(actual_config, UkmConfig()); })); + EXPECT_CALL(*history_observer_, SetHistoryBasedSegments(IsEmpty())); signal_filter_processor_->OnSignalListUpdated(); UkmConfig config1; @@ -188,15 +211,11 @@ {TestMetric(100), TestMetric(101), TestMetric(102)}); config1.AddEvent(TestEvent(11), {TestMetric(103), TestMetric(104), TestMetric(105)}); - segment_database_->AddSqlFeature( - OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB, "", - config1); + segment_database_->AddSqlFeature(kSegmentId, "", config1); UkmConfig config2; config2.AddEvent(TestEvent(10), {TestMetric(100), TestMetric(104), TestMetric(105)}); - segment_database_->AddSqlFeature( - OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB, "", - config2); + segment_database_->AddSqlFeature(kSegmentId, "", config2); config2.Merge(config1); UkmConfig actual_config; @@ -206,6 +225,9 @@ .WillOnce(Invoke([&config2](const UkmConfig& actual_config) { EXPECT_EQ(actual_config, config2); })); + EXPECT_CALL(*history_observer_, + SetHistoryBasedSegments( + base::flat_set<OptimizationTarget>({kSegmentId}))); signal_filter_processor_->OnSignalListUpdated(); }
diff --git a/components/segmentation_platform/internal/signals/signal_handler.cc b/components/segmentation_platform/internal/signals/signal_handler.cc index 8190b48..c180993 100644 --- a/components/segmentation_platform/internal/signals/signal_handler.cc +++ b/components/segmentation_platform/internal/signals/signal_handler.cc
@@ -4,6 +4,7 @@ #include "components/segmentation_platform/internal/signals/signal_handler.h" +#include "components/segmentation_platform/internal/database/storage_service.h" #include "components/segmentation_platform/internal/signals/histogram_signal_handler.h" #include "components/segmentation_platform/internal/signals/history_service_observer.h" #include "components/segmentation_platform/internal/signals/signal_filter_processor.h" @@ -16,28 +17,27 @@ SignalHandler::~SignalHandler() = default; void SignalHandler::Initialize( - SignalDatabase* signal_database, - SegmentInfoDatabase* segment_info_database, - UkmDataManager* ukm_data_manager, + StorageService* storage_service, history::HistoryService* history_service, - DefaultModelManager* default_model_manager, const std::vector<optimization_guide::proto::OptimizationTarget>& segment_ids) { - user_action_signal_handler_ = - std::make_unique<UserActionSignalHandler>(signal_database); - histogram_signal_handler_ = - std::make_unique<HistogramSignalHandler>(signal_database); - signal_filter_processor_ = std::make_unique<SignalFilterProcessor>( - segment_info_database, user_action_signal_handler_.get(), - histogram_signal_handler_.get(), ukm_data_manager, default_model_manager, - segment_ids); + user_action_signal_handler_ = std::make_unique<UserActionSignalHandler>( + storage_service->signal_database()); + histogram_signal_handler_ = std::make_unique<HistogramSignalHandler>( + storage_service->signal_database()); - if (ukm_data_manager->IsUkmEngineEnabled() && history_service) { + if (storage_service->ukm_data_manager()->IsUkmEngineEnabled() && + history_service) { // If UKM engine is enabled and history service is not available, then we // would write metrics without URLs to the database, which is OK. history_service_observer_ = std::make_unique<HistoryServiceObserver>( - history_service, ukm_data_manager->GetOrCreateUrlHandler()); + history_service, storage_service); } + + signal_filter_processor_ = std::make_unique<SignalFilterProcessor>( + storage_service, user_action_signal_handler_.get(), + histogram_signal_handler_.get(), history_service_observer_.get(), + segment_ids); } void SignalHandler::TearDown() {
diff --git a/components/segmentation_platform/internal/signals/signal_handler.h b/components/segmentation_platform/internal/signals/signal_handler.h index cf34f619..6b3d7ad6 100644 --- a/components/segmentation_platform/internal/signals/signal_handler.h +++ b/components/segmentation_platform/internal/signals/signal_handler.h
@@ -15,13 +15,10 @@ namespace segmentation_platform { -class DefaultModelManager; class HistogramSignalHandler; class HistoryServiceObserver; -class SegmentInfoDatabase; -class SignalDatabase; class SignalFilterProcessor; -class UkmDataManager; +class StorageService; class UserActionSignalHandler; // Finds and observes the right signals needed for the models, and stores to the @@ -36,11 +33,8 @@ SignalHandler& operator=(SignalHandler&) = delete; void Initialize( - SignalDatabase* signal_database, - SegmentInfoDatabase* segment_info_database, - UkmDataManager* ukm_data_manager, + StorageService* storage_service, history::HistoryService* history_service, - DefaultModelManager* default_model_manager, const std::vector<optimization_guide::proto::OptimizationTarget>& segment_ids); @@ -68,6 +62,7 @@ std::unique_ptr<UserActionSignalHandler> user_action_signal_handler_; std::unique_ptr<HistogramSignalHandler> histogram_signal_handler_; std::unique_ptr<SignalFilterProcessor> signal_filter_processor_; + // Can be null when UKM engine is disabled. std::unique_ptr<HistoryServiceObserver> history_service_observer_; };
diff --git a/components/segmentation_platform/internal/ukm_data_manager_impl_unittest.cc b/components/segmentation_platform/internal/ukm_data_manager_impl_unittest.cc index 848ce824..e944d56 100644 --- a/components/segmentation_platform/internal/ukm_data_manager_impl_unittest.cc +++ b/components/segmentation_platform/internal/ukm_data_manager_impl_unittest.cc
@@ -13,6 +13,7 @@ #include "components/segmentation_platform/internal/database/mock_ukm_database.h" #include "components/segmentation_platform/internal/database/ukm_types.h" #include "components/segmentation_platform/internal/execution/model_execution_manager_impl.h" +#include "components/segmentation_platform/internal/proto/model_prediction.pb.h" #include "components/segmentation_platform/internal/segmentation_platform_service_impl.h" #include "components/segmentation_platform/internal/segmentation_platform_service_test_base.h" #include "components/segmentation_platform/internal/signals/ukm_observer.h" @@ -127,6 +128,28 @@ return *segmentation_platform_service_impl_; } + void SaveSegmentResult(OptimizationTarget segment_id, + absl::optional<proto::PredictionResult> result) { + const std::string key = base::NumberToString(static_cast<int>(segment_id)); + auto& segment_info = segment_db_entries_[key]; + // Assume that test already created the segment info, this method only + // writes result. + ASSERT_EQ(segment_info.segment_id(), segment_id); + if (result) { + *segment_info.mutable_prediction_result() = std::move(*result); + } else { + segment_info.clear_prediction_result(); + } + } + + bool HasSegmentResult(OptimizationTarget segment_id) { + const std::string key = base::NumberToString(static_cast<int>(segment_id)); + const auto it = segment_db_entries_.find(key); + if (it == segment_db_entries_.end()) + return false; + return it->second.has_prediction_result(); + } + base::ScopedTempDir profile_dir; std::unique_ptr<history::HistoryService> history_service; }; @@ -195,8 +218,16 @@ TEST_F(UkmDataManagerImplTest, HistoryNotification) { const GURL kUrl1 = GURL("https://www.url1.com/"); + const OptimizationTarget kSegmentId = + OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE; TestServicesForPlatform& platform1 = CreatePlatform(); + platform1.AddModel(PageLoadModelMetadata()); + proto::PredictionResult prediction_result; + prediction_result.set_result(10); + prediction_result.set_timestamp_us(1000); + platform1.SaveSegmentResult(kSegmentId, prediction_result); + EXPECT_TRUE(platform1.HasSegmentResult(kSegmentId)); // Add a page to history and check that the notification is sent to // UkmDatabase. All notifications should be sent. @@ -216,6 +247,14 @@ [&wait_for_remove1]() { wait_for_remove1.QuitClosure().Run(); }); wait_for_remove1.Run(); + // Run segment info callbacks that were posted to remove results. + platform1.segment_db().GetCallback(true); + platform1.segment_db().UpdateCallback(true); + + // History based segment results should be removed. + EXPECT_FALSE(platform1.HasSegmentResult( + OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE)); + RemovePlatform(&platform1); }
diff --git a/components/translate/content/browser/per_frame_content_translate_driver.cc b/components/translate/content/browser/per_frame_content_translate_driver.cc index 357438f7..463c54f0 100644 --- a/components/translate/content/browser/per_frame_content_translate_driver.cc +++ b/components/translate/content/browser/per_frame_content_translate_driver.cc
@@ -29,7 +29,6 @@ #include "components/translate/core/common/translate_metrics.h" #include "components/translate/core/common/translate_util.h" #include "components/translate/core/language_detection/language_detection_util.h" -#include "components/ukm/content/source_url_recorder.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/navigation_details.h" #include "content/public/browser/navigation_entry.h"
diff --git a/components/ukm/content/source_url_recorder.cc b/components/ukm/content/source_url_recorder.cc index 284b34ff..e047c86 100644 --- a/components/ukm/content/source_url_recorder.cc +++ b/components/ukm/content/source_url_recorder.cc
@@ -343,12 +343,4 @@ web_contents); } -SourceId GetSourceIdForWebContentsDocument( - const content::WebContents* web_contents) { - const internal::SourceUrlRecorderWebContentsObserver* obs = - internal::SourceUrlRecorderWebContentsObserver::FromWebContents( - web_contents); - return obs ? obs->GetLastCommittedSourceId() : kInvalidSourceId; -} - } // namespace ukm
diff --git a/components/ukm/content/source_url_recorder.h b/components/ukm/content/source_url_recorder.h index 64f704d..372abeb 100644 --- a/components/ukm/content/source_url_recorder.h +++ b/components/ukm/content/source_url_recorder.h
@@ -17,11 +17,6 @@ void InitializeSourceUrlRecorderForWebContents( content::WebContents* web_contents); -// Get a UKM SourceId for the currently committed document of web contents. -// Returns kInvalidSourceId if no commit has been observed. -SourceId GetSourceIdForWebContentsDocument( - const content::WebContents* web_contents); - } // namespace ukm #endif // COMPONENTS_UKM_CONTENT_SOURCE_URL_RECORDER_H_
diff --git a/components/ukm/content/source_url_recorder_browsertest.cc b/components/ukm/content/source_url_recorder_browsertest.cc index 2e29645..ea94d91b 100644 --- a/components/ukm/content/source_url_recorder_browsertest.cc +++ b/components/ukm/content/source_url_recorder_browsertest.cc
@@ -59,7 +59,7 @@ GURL GetAssociatedURLForWebContentsDocument() { const ukm::UkmSource* src = test_ukm_recorder_->GetSourceForSourceId( - ukm::GetSourceIdForWebContentsDocument(shell()->web_contents())); + shell()->web_contents()->GetMainFrame()->GetPageUkmSourceId()); return src ? src->url() : GURL(); } @@ -326,6 +326,10 @@ GetSourceForNavigationId(prerender_observer.navigation_id()); EXPECT_EQ(1u, source2->urls().size()); EXPECT_EQ(prerender_url, source2->url()); - EXPECT_EQ(prerender_url, GetAssociatedURLForWebContentsDocument()); + GURL expected_ukm_url; + // TODO(crbug.com/1245014): The URL is not assigned yet for prerendering + // UKM source ids, so expect it to not be set. + // expected_ukm_url = prerender_url; + EXPECT_EQ(expected_ukm_url, GetAssociatedURLForWebContentsDocument()); EXPECT_NE(source1, source2); }
diff --git a/components/ukm/content/source_url_recorder_test.cc b/components/ukm/content/source_url_recorder_test.cc index 97ffd71..fd1cbe7 100644 --- a/components/ukm/content/source_url_recorder_test.cc +++ b/components/ukm/content/source_url_recorder_test.cc
@@ -27,7 +27,7 @@ GURL GetAssociatedURLForWebContentsDocument() { const ukm::UkmSource* src = test_ukm_recorder_.GetSourceForSourceId( - ukm::GetSourceIdForWebContentsDocument(web_contents())); + web_contents()->GetMainFrame()->GetPageUkmSourceId()); return src ? src->url() : GURL(); }
diff --git a/components/webauthn/android/BUILD.gn b/components/webauthn/android/BUILD.gn index 6fdacf8..2625bce 100644 --- a/components/webauthn/android/BUILD.gn +++ b/components/webauthn/android/BUILD.gn
@@ -17,6 +17,7 @@ "java/src/org/chromium/components/webauthn/AuthenticatorImpl.java", "java/src/org/chromium/components/webauthn/Fido2Api.java", "java/src/org/chromium/components/webauthn/Fido2ApiCall.java", + "java/src/org/chromium/components/webauthn/Fido2ApiCallHelper.java", "java/src/org/chromium/components/webauthn/Fido2ApiHandler.java", "java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java", "java/src/org/chromium/components/webauthn/FidoErrorResponseCallback.java", @@ -25,7 +26,6 @@ "java/src/org/chromium/components/webauthn/IsUvpaaResponseCallback.java", "java/src/org/chromium/components/webauthn/ListCredentials.java", "java/src/org/chromium/components/webauthn/MakeCredentialResponseCallback.java", - "java/src/org/chromium/components/webauthn/WebAuthnCredentialDetails.java", ] annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] deps = [
diff --git a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2Api.java b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2Api.java index 41a8a91..c0b76ae 100644 --- a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2Api.java +++ b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2Api.java
@@ -31,6 +31,7 @@ import org.chromium.blink.mojom.ResidentKeyRequirement; import org.chromium.blink.mojom.UserVerificationRequirement; import org.chromium.blink.mojom.UvmEntry; +import org.chromium.content_public.browser.WebAuthnCredentialDetails; import org.chromium.mojo_base.mojom.TimeDelta; import java.security.NoSuchAlgorithmException;
diff --git a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2ApiCall.java b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2ApiCall.java index 686412e..9390222 100644 --- a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2ApiCall.java +++ b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2ApiCall.java
@@ -28,6 +28,7 @@ import com.google.android.gms.tasks.TaskCompletionSource; import org.chromium.content_public.browser.WebAuthenticationDelegate; +import org.chromium.content_public.browser.WebAuthnCredentialDetails; import java.util.List;
diff --git a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2ApiCallHelper.java b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2ApiCallHelper.java new file mode 100644 index 0000000..2a3a74f6 --- /dev/null +++ b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2ApiCallHelper.java
@@ -0,0 +1,58 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.webauthn; + +import android.os.Parcel; + +import androidx.annotation.VisibleForTesting; + +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; +import com.google.android.gms.tasks.Task; + +import org.chromium.base.ContextUtils; +import org.chromium.content_public.browser.WebAuthnCredentialDetails; + +import java.util.List; + +/** + * Provides helper methods to wrap Fido2ApiCall invocations. + * This class is useful to override GMS Core API interactions from Fido2CredentialRequest in tests. + */ +public class Fido2ApiCallHelper { + private static Fido2ApiCallHelper sInstance; + + @VisibleForTesting + public static void overrideInstanceForTesting(Fido2ApiCallHelper instance) { + sInstance = instance; + } + + /** + * @return The Fido2ApiCallHelper for use during the lifetime of the browser process. + */ + public static Fido2ApiCallHelper getInstance() { + if (sInstance == null) { + sInstance = new Fido2ApiCallHelper(); + } + return sInstance; + } + + public void invokeFido2GetCredentials(String relyingPartyId, int supportLevel, + OnSuccessListener<List<WebAuthnCredentialDetails>> successCallback, + OnFailureListener failureCallback) { + Fido2ApiCall call = new Fido2ApiCall(ContextUtils.getApplicationContext(), supportLevel); + Parcel args = call.start(); + Fido2ApiCall.WebAuthnCredentialDetailsListResult result = + new Fido2ApiCall.WebAuthnCredentialDetailsListResult(); + args.writeStrongBinder(result); + args.writeString(relyingPartyId); + + Task<List<WebAuthnCredentialDetails>> task = + call.run(Fido2ApiCall.METHOD_BROWSER_GETCREDENTIALS, + Fido2ApiCall.TRANSACTION_GETCREDENTIALS, args, result); + task.addOnSuccessListener(successCallback); + task.addOnFailureListener(failureCallback); + } +} \ No newline at end of file
diff --git a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java index ec64b6b8..8c8d4f5c 100644 --- a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java +++ b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java
@@ -21,8 +21,11 @@ import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.blink.mojom.AuthenticatorStatus; +import org.chromium.blink.mojom.AuthenticatorTransport; import org.chromium.blink.mojom.PaymentOptions; +import org.chromium.blink.mojom.PublicKeyCredentialDescriptor; import org.chromium.blink.mojom.PublicKeyCredentialRequestOptions; +import org.chromium.blink.mojom.PublicKeyCredentialType; import org.chromium.components.externalauth.ExternalAuthUtils; import org.chromium.components.externalauth.UserRecoverableErrorHandler; import org.chromium.components.payments.PaymentFeatureList; @@ -31,6 +34,7 @@ import org.chromium.content_public.browser.RenderFrameHost; import org.chromium.content_public.browser.RenderFrameHost.WebAuthSecurityChecksResults; import org.chromium.content_public.browser.WebAuthenticationDelegate; +import org.chromium.content_public.browser.WebAuthnCredentialDetails; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsStatics; import org.chromium.net.GURLUtils; @@ -208,25 +212,14 @@ } if (options.isConditional) { - Fido2ApiCall call = - new Fido2ApiCall(ContextUtils.getApplicationContext(), mSupportLevel); - Parcel args = call.start(); - Fido2ApiCall.WebAuthnCredentialDetailsListResult result = - new Fido2ApiCall.WebAuthnCredentialDetailsListResult(); - args.writeStrongBinder(result); - args.writeString(options.relyingPartyId); - // For use in the lambda expression. final byte[] finalClientDataHash = clientDataHash; - - Task<List<WebAuthnCredentialDetails>> task = - call.run(Fido2ApiCall.METHOD_BROWSER_GETCREDENTIALS, - Fido2ApiCall.TRANSACTION_GETCREDENTIALS, args, result); - task.addOnSuccessListener( + Fido2ApiCallHelper.getInstance().invokeFido2GetCredentials(options.relyingPartyId, + mSupportLevel, (credentials) -> onWebAuthnCredentialDetailsListReceived(frameHost, options, - callerOriginString, finalClientDataHash, credentials)); - task.addOnFailureListener(this::onBinderCallException); + callerOriginString, finalClientDataHash, credentials), + this::onBinderCallException); return; } @@ -268,18 +261,28 @@ private void onWebAuthnCredentialDetailsListReceived(RenderFrameHost frameHost, PublicKeyCredentialRequestOptions options, String callerOriginString, byte[] clientDataHash, List<WebAuthnCredentialDetails> credentials) { - // TODO(kenrb): Call frameHost.onCredentialsDetailsListReceived with - // dispatchGetAssertionRequest as a callback. - // i.e.: - // frameHost.onCredentialsDetailsListReceived(credentials, - // (selectedCredential) -> dispatchGetAssertionRequest(options, - // callerOriginString, - // clientDataHash, - // selectedCredentialId)); + frameHost.onCredentialsDetailsListReceived(credentials, + (selectedCredentialId) + -> dispatchGetAssertionRequest( + options, callerOriginString, clientDataHash, selectedCredentialId)); } private void dispatchGetAssertionRequest(PublicKeyCredentialRequestOptions options, String callerOriginString, byte[] clientDataHash, byte[] credentialId) { + if (credentialId != null) { + if (credentialId.length == 0) { + // An empty credential ID means an error from native code, which can happen if the + // embedder does not support Conditional UI. + Log.e(TAG, "Empty credential ID from account selection."); + returnErrorAndResetCallback(AuthenticatorStatus.UNKNOWN_ERROR); + return; + } + PublicKeyCredentialDescriptor selected_credential = new PublicKeyCredentialDescriptor(); + selected_credential.type = PublicKeyCredentialType.PUBLIC_KEY; + selected_credential.id = credentialId; + selected_credential.transports = new int[] {AuthenticatorTransport.INTERNAL}; + options.allowCredentials = new PublicKeyCredentialDescriptor[] {selected_credential}; + } Fido2ApiCall call = new Fido2ApiCall(ContextUtils.getApplicationContext(), mSupportLevel); Parcel args = call.start(); Fido2ApiCall.PendingIntentResult result = new Fido2ApiCall.PendingIntentResult(call);
diff --git a/components/webauthn/android/java/src/org/chromium/components/webauthn/WebAuthnCredentialDetails.java b/components/webauthn/android/java/src/org/chromium/components/webauthn/WebAuthnCredentialDetails.java deleted file mode 100644 index 173fc05d..0000000 --- a/components/webauthn/android/java/src/org/chromium/components/webauthn/WebAuthnCredentialDetails.java +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2022 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.components.webauthn; - -import org.chromium.base.annotations.CalledByNative; - -/** - * Describes a WebAuthn credential available on the authenticator. - */ -public class WebAuthnCredentialDetails { - public String mUserName; - public String mUserDisplayName; - public byte[] mUserId; - public byte[] mCredentialId; - - public WebAuthnCredentialDetails() {} - - @CalledByNative - public String getUserName() { - return mUserName; - } - - @CalledByNative - public String getUserDisplayName() { - return mUserDisplayName; - } - - @CalledByNative - public byte[] getUserId() { - return mUserId; - } - - @CalledByNative - public byte[] getCredentialId() { - return mCredentialId; - } -}
diff --git a/content/browser/aggregation_service/aggregation_service_test_utils.cc b/content/browser/aggregation_service/aggregation_service_test_utils.cc index 761ef74a..b714106 100644 --- a/content/browser/aggregation_service/aggregation_service_test_utils.cc +++ b/content/browser/aggregation_service/aggregation_service_test_utils.cc
@@ -14,14 +14,21 @@ #include "base/base64.h" #include "base/containers/contains.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/guid.h" +#include "base/json/json_reader.h" +#include "base/strings/strcat.h" #include "base/task/thread_pool.h" #include "base/threading/sequence_bound.h" #include "base/time/time.h" +#include "base/values.h" #include "content/browser/aggregation_service/aggregatable_report.h" #include "content/browser/aggregation_service/aggregation_service_storage_sql.h" #include "content/browser/aggregation_service/public_key.h" +#include "content/browser/aggregation_service/public_key_parsing_utils.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/include/openssl/hpke.h" #include "url/gurl.h" #include "url/origin.h" @@ -233,6 +240,49 @@ return hpke_key; } +absl::optional<PublicKeyset> ReadAndParsePublicKeys(const base::FilePath& file, + base::Time now, + std::string* error_msg) { + if (!base::PathExists(file)) { + if (error_msg) + *error_msg = base::StrCat({"Failed to open file: ", file.MaybeAsASCII()}); + + return absl::nullopt; + } + + std::string contents; + if (!base::ReadFileToString(file, &contents)) { + if (error_msg) + *error_msg = base::StrCat({"Failed to read file: ", file.MaybeAsASCII()}); + + return absl::nullopt; + } + + base::JSONReader::ValueWithError value_with_error = + base::JSONReader::ReadAndReturnValueWithError(contents); + if (!value_with_error.value) { + if (error_msg) { + *error_msg = + base::StrCat({"Failed to parse \"", contents, + "\" as JSON: ", value_with_error.error_message}); + } + return absl::nullopt; + } + + std::vector<PublicKey> keys = GetPublicKeys(*value_with_error.value); + if (keys.empty()) { + if (error_msg) { + *error_msg = + base::StrCat({"Failed to parse public keys from \"", contents, "\""}); + } + + return absl::nullopt; + } + + return PublicKeyset(std::move(keys), /*fetch_time=*/now, + /*expiry_time=*/base::Time::Max()); +} + } // namespace aggregation_service TestAggregationServiceStorageContext::TestAggregationServiceStorageContext(
diff --git a/content/browser/aggregation_service/aggregation_service_test_utils.h b/content/browser/aggregation_service/aggregation_service_test_utils.h index 0a7039f..2204034e 100644 --- a/content/browser/aggregation_service/aggregation_service_test_utils.h +++ b/content/browser/aggregation_service/aggregation_service_test_utils.h
@@ -22,6 +22,8 @@ namespace base { class Clock; +class FilePath; +class Time; } // namespace base namespace content { @@ -67,6 +69,11 @@ // object for use in assembler methods. TestHpkeKey GenerateKey(std::string key_id = "example_id"); +absl::optional<PublicKeyset> ReadAndParsePublicKeys( + const base::FilePath& file, + base::Time now, + std::string* error_msg = nullptr); + } // namespace aggregation_service // The strings "ABCD1234" and "EFGH5678", Base64-decoded to bytes. Note that
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index 5f771ec..7ba9abdb 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc
@@ -167,6 +167,7 @@ #include "third_party/blink/public/mojom/unhandled_tap_notifier/unhandled_tap_notifier.mojom.h" #else // BUILDFLAG(IS_ANDROID) #include "content/browser/direct_sockets/direct_sockets_service_impl.h" +#include "media/mojo/mojom/renderer_extensions.mojom.h" #include "media/mojo/mojom/speech_recognition_service.mojom.h" #include "third_party/blink/public/mojom/hid/hid.mojom.h" #include "third_party/blink/public/mojom/installedapp/installed_app_provider.mojom.h"
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc index 912be1d..f1d97dd 100644 --- a/content/browser/indexed_db/indexed_db_database.cc +++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -330,9 +330,6 @@ } void IndexedDBDatabase::TransactionCreated() { - UMA_HISTOGRAM_COUNTS_1000( - "WebCore.IndexedDB.Database.OutstandingTransactionCount", - transaction_count_); ++transaction_count_; }
diff --git a/content/browser/interest_group/auction_runner.cc b/content/browser/interest_group/auction_runner.cc index 8de85ae..1782a32 100644 --- a/content/browser/interest_group/auction_runner.cc +++ b/content/browser/interest_group/auction_runner.cc
@@ -1261,9 +1261,18 @@ // an error if it crashes at this point, failing the auction unnecessarily. seller_worklet_handle_.reset(); - if (!seller_ad_beacon_map.empty()) + if (!seller_ad_beacon_map.empty()) { + for (const auto& element : seller_ad_beacon_map) { + if (!IsUrlValid(element.second)) { + mojo::ReportBadMessage(base::StrCat( + {"Invalid seller beacon URL for '", element.first, "'"})); + OnReportingPhaseComplete(AuctionResult::kBadMojoMessage); + return; + } + } ad_beacon_map_.metadata[ReportingDestination::kSeller] = seller_ad_beacon_map; + } if (seller_report_url) { if (!IsUrlValid(*seller_report_url)) { @@ -1344,9 +1353,18 @@ // fatal error notification. top_bid_->bid->bid_state->worklet_handle.reset(); - if (!bidder_ad_beacon_map.empty()) + if (!bidder_ad_beacon_map.empty()) { + for (const auto& element : bidder_ad_beacon_map) { + if (!IsUrlValid(element.second)) { + mojo::ReportBadMessage(base::StrCat( + {"Invalid bidder beacon URL for '", element.first, "'"})); + OnReportingPhaseComplete(AuctionResult::kBadMojoMessage); + return; + } + } ad_beacon_map_.metadata[ReportingDestination::kBuyer] = bidder_ad_beacon_map; + } if (bidder_report_url) { if (!IsUrlValid(*bidder_report_url)) {
diff --git a/content/browser/interest_group/auction_runner_unittest.cc b/content/browser/interest_group/auction_runner_unittest.cc index 4b5480d..95a4e9d 100644 --- a/content/browser/interest_group/auction_runner_unittest.cc +++ b/content/browser/interest_group/auction_runner_unittest.cc
@@ -924,10 +924,11 @@ } void InvokeReportWinCallback( - absl::optional<GURL> report_url = absl::nullopt) { + absl::optional<GURL> report_url = absl::nullopt, + base::flat_map<std::string, GURL> ad_beacon_map = {}) { DCHECK(report_win_callback_); std::move(report_win_callback_) - .Run(report_url, /*ad_beacon_map=*/{}, + .Run(report_url, ad_beacon_map, /*errors=*/std::vector<std::string>()); } @@ -1085,11 +1086,12 @@ // the provided score. WaitForReportResult() must have been invoked first. void InvokeReportResultCallback( absl::optional<GURL> report_url = absl::nullopt, + base::flat_map<std::string, GURL> ad_beacon_map = {}, std::vector<std::string> errors = {}) { DCHECK(report_result_callback_); std::move(report_result_callback_) .Run(/*signals_for_winner=*/absl::nullopt, std::move(report_url), - /*ad_beacon_map=*/{}, errors); + ad_beacon_map, errors); } void Flush() { receiver_.FlushForTesting(); } @@ -5555,7 +5557,7 @@ const char kScriptError[] = "Script error"; component_seller_worklet->InvokeReportResultCallback( - /*report_url=*/absl::nullopt, {kScriptError}); + /*report_url=*/absl::nullopt, /*ad_beacon_map=*/{}, {kScriptError}); // Winning bidder worklet should be reloaded and ReportWin() invoked. mock_auction_process_manager_->WaitForWinningBidderReload(); @@ -6107,7 +6109,7 @@ } } -// Test cases where bad a report URL is received over Mojo from the seller +// Test cases where a bad report URL is received over Mojo from the seller // worklet. Bad report URLs should be rejected in the Mojo process, so these are // treated as security errors. TEST_F(AuctionRunnerTest, BadSellerReportUrl) { @@ -6161,7 +6163,63 @@ /*expected_sellers=*/1); } -// Test cases where bad a report URL is received over Mojo from the winning +// Test cases where a bad report URL is received over Mojo from the seller +// worklet. Bad report URLs should be rejected in the Mojo process, so these are +// treated as security errors. +TEST_F(AuctionRunnerTest, BadSellerBeaconUrl) { + StartStandardAuctionWithMockService(); + + auto seller_worklet = mock_auction_process_manager_->TakeSellerWorklet(); + ASSERT_TRUE(seller_worklet); + auto bidder1_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder1Url); + ASSERT_TRUE(bidder1_worklet); + auto bidder2_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder2Url); + ASSERT_TRUE(bidder2_worklet); + + // Only Bidder1 bids, to keep things simple. + bidder1_worklet->InvokeGenerateBidCallback(/*bid=*/5, + GURL("https://ad1.com/")); + bidder2_worklet->InvokeGenerateBidCallback(/*bid=*/absl::nullopt); + + auto score_ad_params = seller_worklet->WaitForScoreAd(); + EXPECT_EQ(kBidder1, score_ad_params.interest_group_owner); + EXPECT_EQ(5, score_ad_params.bid); + std::move(score_ad_params.callback) + .Run(/*score=*/10, + auction_worklet::mojom::ComponentAuctionModifiedBidParamsPtr(), + /*data_version=*/0, /*has_data_version=*/false, + /*debug_loss_report_url=*/absl::nullopt, + /*debug_win_report_url=*/absl::nullopt, /*errors=*/{}); + + // Bidder1 never gets to report anything, since the seller providing a bad + // report URL aborts the auction. + seller_worklet->WaitForReportResult(); + seller_worklet->InvokeReportResultCallback( + /*report_url=*/absl::nullopt, + {{"click", GURL("http://not.https.test/")}}); + auction_run_loop_->Run(); + + EXPECT_EQ("Invalid seller beacon URL for 'click'", TakeBadMessage()); + + // No bidder won. + EXPECT_FALSE(result_.winning_group_id); + EXPECT_FALSE(result_.ad_url); + EXPECT_TRUE(result_.ad_component_urls.empty()); + EXPECT_THAT(result_.report_urls, testing::UnorderedElementsAre()); + EXPECT_TRUE(result_.ad_beacon_map.metadata.empty()); + EXPECT_EQ(6, result_.bidder1_bid_count); + EXPECT_EQ(3u, result_.bidder1_prev_wins.size()); + EXPECT_EQ(5, result_.bidder2_bid_count); + EXPECT_EQ(3u, result_.bidder2_prev_wins.size()); + EXPECT_THAT(result_.errors, testing::ElementsAre()); + CheckHistograms(AuctionRunner::AuctionResult::kBadMojoMessage, + /*expected_interest_groups=*/2, /*expected_owners=*/2, + /*expected_sellers=*/1); +} + +// Test cases where a bad report URL is received over Mojo from the winning // component seller worklet. Bad report URLs should be rejected in the Mojo // process, so these are treated as security errors. TEST_F(AuctionRunnerTest, BadComponentSellerReportUrl) { @@ -6247,7 +6305,7 @@ /*expected_sellers=*/2); } -// Test cases where bad a report URL is received over Mojo from the bidder +// Test cases where a bad report URL is received over Mojo from the bidder // worklet. Bad report URLs should be rejected in the Mojo process, so these are // treated as security errors. TEST_F(AuctionRunnerTest, BadBidderReportUrl) { @@ -6305,6 +6363,66 @@ /*expected_sellers=*/1); } +// Test cases where a bad URL is present in the beacon mapping received over +// Mojo from the bidder worklet. Bad report URLs should be rejected in the Mojo +// process, so these are treated as security errors. +TEST_F(AuctionRunnerTest, BadBidderBeaconUrl) { + StartStandardAuctionWithMockService(); + + auto seller_worklet = mock_auction_process_manager_->TakeSellerWorklet(); + ASSERT_TRUE(seller_worklet); + auto bidder1_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder1Url); + ASSERT_TRUE(bidder1_worklet); + auto bidder2_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder2Url); + ASSERT_TRUE(bidder2_worklet); + + // Only Bidder1 bids, to keep things simple. + bidder1_worklet->InvokeGenerateBidCallback(/*bid=*/5, + GURL("https://ad1.com/")); + bidder2_worklet->InvokeGenerateBidCallback(/*bid=*/absl::nullopt); + + auto score_ad_params = seller_worklet->WaitForScoreAd(); + EXPECT_EQ(kBidder1, score_ad_params.interest_group_owner); + EXPECT_EQ(5, score_ad_params.bid); + std::move(score_ad_params.callback) + .Run(/*score=*/10, + auction_worklet::mojom::ComponentAuctionModifiedBidParamsPtr(), + /*data_version=*/0, /*has_data_version=*/false, + /*debug_loss_report_url=*/absl::nullopt, + /*debug_win_report_url=*/absl::nullopt, /*errors=*/{}); + + seller_worklet->WaitForReportResult(); + seller_worklet->InvokeReportResultCallback( + GURL("https://valid.url.that.is.thrown.out.test/")); + mock_auction_process_manager_->WaitForWinningBidderReload(); + bidder1_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder1Url); + bidder1_worklet->WaitForReportWin(); + bidder1_worklet->InvokeReportWinCallback( + /*report_url=*/absl::nullopt, + {{"click", GURL("http://not.https.test/")}}); + auction_run_loop_->Run(); + + EXPECT_EQ("Invalid bidder beacon URL for 'click'", TakeBadMessage()); + + // No bidder won. + EXPECT_FALSE(result_.winning_group_id); + EXPECT_FALSE(result_.ad_url); + EXPECT_TRUE(result_.ad_component_urls.empty()); + EXPECT_THAT(result_.report_urls, testing::UnorderedElementsAre()); + EXPECT_TRUE(result_.ad_beacon_map.metadata.empty()); + EXPECT_EQ(6, result_.bidder1_bid_count); + EXPECT_EQ(3u, result_.bidder1_prev_wins.size()); + EXPECT_EQ(5, result_.bidder2_bid_count); + EXPECT_EQ(3u, result_.bidder2_prev_wins.size()); + EXPECT_THAT(result_.errors, testing::ElementsAre()); + CheckHistograms(AuctionRunner::AuctionResult::kBadMojoMessage, + /*expected_interest_groups=*/2, /*expected_owners=*/2, + /*expected_sellers=*/1); +} + // Check that BidderWorklets that don't make a bid are destroyed immediately. TEST_F(AuctionRunnerTest, DestroyBidderWorkletWithoutBid) { StartStandardAuctionWithMockService();
diff --git a/content/browser/media/encrypted_media_browsertest.cc b/content/browser/media/encrypted_media_browsertest.cc index ab20334..d042d3a 100644 --- a/content/browser/media/encrypted_media_browsertest.cc +++ b/content/browser/media/encrypted_media_browsertest.cc
@@ -305,8 +305,8 @@ #if !BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_FUCHSIA) && defined(ARCH_CPU_ARM_FAMILY)) -// https://crbug.com/1222685 -// https://crbug.com/1280308 +// TODO(https://crbug.com/1222685): Failing on Mac. +// TODO(https://crbug.com/1280308): Failing on Fuchsia arm. #define MAYBE_Playback_VideoOnly_WebM_VP9Profile2 \ DISABLED_Playback_VideoOnly_WebM_VP9Profile2 #else @@ -318,8 +318,9 @@ TestSimplePlayback("bear-320x240-v-vp9_profile2_subsample_cenc-v.webm"); } -#if BUILDFLAG(IS_MAC) -// https://crbug.com/1270792 +#if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_FUCHSIA) && defined(ARCH_CPU_ARM_FAMILY)) +// TODO(https://crbug.com/1270792): Failing on Mac. +// TODO(https://crbug.com/1280308): Failing on Fuchsia arm. #define MAYBE_Playback_VideoOnly_MP4_VP9Profile2 \ DISABLED_Playback_VideoOnly_MP4_VP9Profile2 #else
diff --git a/content/browser/net/dns_https_protocol_upgrade_browsertest.cc b/content/browser/net/dns_https_protocol_upgrade_browsertest.cc index 24a1bea..1df62e1 100644 --- a/content/browser/net/dns_https_protocol_upgrade_browsertest.cc +++ b/content/browser/net/dns_https_protocol_upgrade_browsertest.cc
@@ -53,8 +53,7 @@ // Build a DoH config that points to our one DoH server and pass the config // into the network service. absl::optional<net::DnsOverHttpsConfig> doh_config = - net::DnsOverHttpsConfig::FromStrings( - /*servers=*/{doh_server_->GetTemplate()}); + net::DnsOverHttpsConfig::FromString(doh_server_->GetTemplate()); ASSERT_TRUE(doh_config.has_value()); // When the network service runs out-of-process, use `BrowserTestBase`
diff --git a/content/browser/renderer_host/DEPS b/content/browser/renderer_host/DEPS index 3219bc4..34644bc3f 100644 --- a/content/browser/renderer_host/DEPS +++ b/content/browser/renderer_host/DEPS
@@ -2,6 +2,7 @@ "+cc/switches.h", # For cc command line switches. "+components/viz/common", "+components/viz/host", + "+device/fido", "+jni", "+net/dns/public", "+third_party/blink/public/platform/web_gesture_curve.h",
diff --git a/content/browser/renderer_host/render_frame_host_android.cc b/content/browser/renderer_host/render_frame_host_android.cc index 6405ea76..f0edf0b 100644 --- a/content/browser/renderer_host/render_frame_host_android.cc +++ b/content/browser/renderer_host/render_frame_host_android.cc
@@ -21,6 +21,8 @@ #include "content/public/browser/browser_context.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/site_instance.h" +#include "device/fido/discoverable_credential_metadata.h" +#include "device/fido/public_key_credential_user_entity.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom.h" #include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-shared.h" @@ -50,6 +52,55 @@ base::android::RunObjectCallbackAndroid( jcallback, url::GURLAndroid::FromNativeGURL(env, url.value())); } + +device::DiscoverableCredentialMetadata ConvertJavaCredentialDetailsToMetadata( + JNIEnv* env, + ScopedJavaLocalRef<jobject> j_credential) { + device::DiscoverableCredentialMetadata credential; + base::android::JavaByteArrayToByteVector( + env, + Java_RenderFrameHostImpl_getWebAuthnCredentialDetailsCredentialId( + env, j_credential), + &credential.cred_id); + base::android::JavaByteArrayToByteVector( + env, + Java_RenderFrameHostImpl_getWebAuthnCredentialDetailsUserId(env, + j_credential), + &credential.user.id); + credential.user.name = ConvertJavaStringToUTF8( + env, Java_RenderFrameHostImpl_getWebAuthnCredentialDetailsUserName( + env, j_credential)); + credential.user.display_name = ConvertJavaStringToUTF8( + env, Java_RenderFrameHostImpl_getWebAuthnCredentialDetailsUserDisplayName( + env, j_credential)); + return credential; +} + +void ConvertJavaCredentialArrayToMetadataVector( + JNIEnv* env, + const base::android::JavaRef<jobjectArray>& array, + std::vector<device::DiscoverableCredentialMetadata>* out) { + jsize jlength = env->GetArrayLength(array.obj()); + // GetArrayLength() returns -1 if |array| is not a valid Java array. + DCHECK_GE(jlength, 0) << "Invalid array length: " << jlength; + size_t length = static_cast<size_t>(std::max(0, jlength)); + for (size_t i = 0; i < length; ++i) { + ScopedJavaLocalRef<jobject> j_credential( + env, static_cast<jobject>(env->GetObjectArrayElement(array.obj(), i))); + out->emplace_back( + ConvertJavaCredentialDetailsToMetadata(env, j_credential)); + } +} + +void OnWebAuthnCredentialSelected( + const base::android::JavaRef<jobject>& jcallback, + const std::vector<uint8_t>& credential_id) { + base::android::RunObjectCallbackAndroid( + jcallback, base::android::ToJavaByteArray( + base::android::AttachCurrentThread(), credential_id.data(), + credential_id.size())); +} + } // namespace // static @@ -236,6 +287,21 @@ is_payment_credential_creation, nullptr)); } +void RenderFrameHostAndroid::OnCredentialsDetailsListReceived( + JNIEnv* env, + const base::android::JavaParamRef<jobject>&, + const base::android::JavaParamRef<jobjectArray>& credentials, + const base::android::JavaParamRef<jobject>& jcallback) const { + std::vector<device::DiscoverableCredentialMetadata> credentials_metadata; + ConvertJavaCredentialArrayToMetadataVector(env, credentials, + &credentials_metadata); + render_frame_host_->WebAuthnConditionalUiRequestPending( + credentials_metadata, + base::BindOnce( + &OnWebAuthnCredentialSelected, + base::android::ScopedJavaGlobalRef<jobject>(env, jcallback))); +} + jint RenderFrameHostAndroid::GetLifecycleState( JNIEnv* env, const base::android::JavaParamRef<jobject>&) const {
diff --git a/content/browser/renderer_host/render_frame_host_android.h b/content/browser/renderer_host/render_frame_host_android.h index 55412020..809f00c 100644 --- a/content/browser/renderer_host/render_frame_host_android.h +++ b/content/browser/renderer_host/render_frame_host_android.h
@@ -98,6 +98,12 @@ const base::android::JavaParamRef<jobject>&, jboolean is_payment_credential_creation) const; + void OnCredentialsDetailsListReceived( + JNIEnv* env, + const base::android::JavaParamRef<jobject>&, + const base::android::JavaParamRef<jobjectArray>& credentials, + const base::android::JavaParamRef<jobject>& jcallback) const; + jint GetLifecycleState(JNIEnv* env, const base::android::JavaParamRef<jobject>&) const;
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 5dfbdef..08afe0bb 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -260,6 +260,7 @@ #include "content/browser/android/java_interfaces_impl.h" #include "content/browser/renderer_host/render_frame_host_android.h" #include "content/public/browser/android/java_interfaces.h" +#include "device/fido/discoverable_credential_metadata.h" #else #include "content/browser/hid/hid_service.h" #include "content/browser/host_zoom_map_impl.h" @@ -12864,6 +12865,20 @@ return blink::mojom::AuthenticatorStatus::SUCCESS; } +#if BUILDFLAG(IS_ANDROID) +void RenderFrameHostImpl::WebAuthnConditionalUiRequestPending( + const std::vector<device::DiscoverableCredentialMetadata>& credentials, + base::OnceCallback<void(const std::vector<uint8_t>& id)> callback) { + auto* delegate = + GetContentClient()->browser()->GetConditionalUiDelegate(this); + if (!delegate) { + std::move(callback).Run(std::vector<uint8_t>()); + return; + } + delegate->OnWebAuthnRequestPending(credentials, std::move(callback)); +} +#endif + void RenderFrameHostImpl::IsClipboardPasteContentAllowed( const ui::ClipboardFormatType& data_type, const std::string& data,
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h index 12d8979..f6e183bf 100644 --- a/content/browser/renderer_host/render_frame_host_impl.h +++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -172,6 +172,10 @@ } // namespace mojom } // namespace blink +namespace device { +class DiscoverableCredentialMetadata; +} + namespace gfx { class Range; } @@ -2447,6 +2451,17 @@ float GetPageScaleFactor() const; +#if BUILDFLAG(IS_ANDROID) + // Provide a list of Web Authentication credentials that can be used to + // fulfill a WebAuthn sign-in request. These can be passed to the embedder to + // be displayed to the user, and the user's selection is returned through the + // callback. This is Android only because on desktop platforms the embedder + // interacts directly with the device layer. + void WebAuthnConditionalUiRequestPending( + const std::vector<device::DiscoverableCredentialMetadata>& credentials, + base::OnceCallback<void(const std::vector<uint8_t>& id)> callback); +#endif + enum class FencedFrameStatus { kNotNestedInFencedFrame, kFencedFrameRoot,
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc index 97a520f..286fd8c 100644 --- a/content/browser/webid/federated_auth_request_impl.cc +++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -527,7 +527,7 @@ void FederatedAuthRequestImpl::OnManifestListFetched( IdpNetworkRequestManager::FetchStatus status, - const std::set<std::string>& urls) { + const std::set<GURL>& urls) { switch (status) { case IdpNetworkRequestManager::FetchStatus::kHttpNotFoundError: { RecordRequestIdTokenStatus(IdTokenStatus::kManifestListHttpNotFound, @@ -592,18 +592,10 @@ // Besides, for GURL without path, |provider_.spec()| will append a trailing // slash automatically. Therefore we relax the requirement by allowing // mismatch on trailing slash. - std::string provider_url = provider_.spec(); - if (provider_.path().empty() || provider_.path().back() != '/') { - std::string new_path = provider_.path() + '/'; - GURL::Replacements replacements; - replacements.SetPathStr(new_path); - provider_url = provider_.ReplaceComponents(replacements).spec(); - } - DCHECK_EQ(provider_url.back(), '/'); + GURL provider_url = IdpNetworkRequestManager::FixupProviderUrl(provider_); + DCHECK_EQ(provider_url.path().back(), '/'); bool provider_url_is_valid = (urls.count(provider_url) != 0); - provider_url.pop_back(); - provider_url_is_valid |= (urls.count(provider_url) != 0); if (!provider_url_is_valid) { RecordRequestIdTokenStatus(IdTokenStatus::kManifestNotInManifestList, @@ -621,7 +613,7 @@ void FederatedAuthRequestImpl::OnManifestListFetchedForRevoke( IdpNetworkRequestManager::FetchStatus status, - const std::set<std::string>& urls) { + const std::set<GURL>& urls) { switch (status) { case IdpNetworkRequestManager::FetchStatus::kHttpNotFoundError: { RecordRevokeStatus(RevokeStatusForMetrics::kManifestListHttpNotFound, @@ -661,7 +653,8 @@ return; } - if (urls.count(provider_.spec()) == 0) { + GURL provider_url = IdpNetworkRequestManager::FixupProviderUrl(provider_); + if (urls.count(provider_url) == 0) { RecordRevokeStatus(RevokeStatusForMetrics::kManifestNotInManifestList, render_frame_host_->GetPageUkmSourceId()); CompleteRevokeRequest(RevokeStatus::kError,
diff --git a/content/browser/webid/federated_auth_request_impl.h b/content/browser/webid/federated_auth_request_impl.h index 9c5e054..618131a 100644 --- a/content/browser/webid/federated_auth_request_impl.h +++ b/content/browser/webid/federated_auth_request_impl.h
@@ -86,10 +86,10 @@ enum FetchManifestType { kForToken, kForRevoke }; void FetchManifest(FetchManifestType type); void OnManifestListFetched(IdpNetworkRequestManager::FetchStatus status, - const std::set<std::string>& urls); + const std::set<GURL>& urls); void OnManifestListFetchedForRevoke( IdpNetworkRequestManager::FetchStatus status, - const std::set<std::string>& urls); + const std::set<GURL>& urls); void OnManifestFetched(IdpNetworkRequestManager::FetchStatus status, IdpNetworkRequestManager::Endpoints, IdentityProviderMetadata idp_metadata);
diff --git a/content/browser/webid/federated_auth_request_impl_unittest.cc b/content/browser/webid/federated_auth_request_impl_unittest.cc index 80dd9e07..b2db25fb 100644 --- a/content/browser/webid/federated_auth_request_impl_unittest.cc +++ b/content/browser/webid/federated_auth_request_impl_unittest.cc
@@ -388,8 +388,9 @@ void FetchManifestList(FetchManifestListCallback callback) override { fetched_endpoints_ |= FetchedEndpoint::MANIFEST_LIST; - std::move(callback).Run(FetchStatus::kSuccess, - config_.manifest_list.provider_urls); + std::set<GURL> url_set(config_.manifest_list.provider_urls.begin(), + config_.manifest_list.provider_urls.end()); + std::move(callback).Run(FetchStatus::kSuccess, url_set); } void FetchManifest(absl::optional<int> idp_brand_icon_ideal_size, @@ -968,21 +969,6 @@ // Test mismatching trailing slash is allowed. TEST_F(BasicFederatedAuthRequestImplTest, - ManifestListHasTrailingSlashAfterPath) { - base::test::ScopedFeatureList list; - list.InitAndEnableFeature(features::kFedCmManifestValidation); - - RequestParameters parameters{"https://idp.example/foo/", kClientId, kNonce, - /*prefer_auto_sign_in=*/false}; - MockConfiguration config{kConfigurationValid}; - config.manifest_list.provider_urls = - std::set<std::string>{"https://idp.example/foo"}; - - RunAuthTest(parameters, kExpectationSuccess, config); -} - -// Test mismatching trailing slash is allowed. -TEST_F(BasicFederatedAuthRequestImplTest, ManifestListHasNoTrailingSlashAfterPath) { base::test::ScopedFeatureList list; list.InitAndEnableFeature(features::kFedCmManifestValidation);
diff --git a/content/browser/webid/idp_network_request_manager.cc b/content/browser/webid/idp_network_request_manager.cc index a5969b6..5a8d80c 100644 --- a/content/browser/webid/idp_network_request_manager.cc +++ b/content/browser/webid/idp_network_request_manager.cc
@@ -381,6 +381,22 @@ IdpNetworkRequestManager::~IdpNetworkRequestManager() = default; +GURL IdpNetworkRequestManager::FixupProviderUrl(const GURL& url) { + // We accept both "https://idp.example/foo/" and "https://idp.example/foo" as + // valid provider url to locate the manifest. Historically, URLs with a + // trailing slash indicate a directory while those without a trailing slash + // denote a file. However, to give developers more flexibility, we append a + // trailing slash if one is not present. + GURL target_url = url; + if (target_url.path().empty() || target_url.path().back() != '/') { + std::string new_path = target_url.path() + '/'; + GURL::Replacements replacements; + replacements.SetPathStr(new_path); + target_url = target_url.ReplaceComponents(replacements); + } + return target_url; +} + void IdpNetworkRequestManager::FetchManifestList( FetchManifestListCallback callback) { DCHECK(!manifest_list_url_loader_); @@ -409,18 +425,7 @@ idp_manifest_callback_ = std::move(callback); - // Accepts both "https://idp.example/foo/" and "https://idp.example/foo" as - // valid provider url to locate the manifest. Historically, URLs with a - // trailing slash indicate a directory while those without a trailing slash - // denote a file. However, to give developers more flexibility, we append a - // trailing slash if one is not present. - GURL target_url = provider_; - if (target_url.path().empty() || target_url.path().back() != '/') { - std::string new_path = target_url.path() + '/'; - GURL::Replacements replacements; - replacements.SetPathStr(new_path); - target_url = target_url.ReplaceComponents(replacements); - } + GURL target_url = FixupProviderUrl(provider_); target_url = target_url.Resolve(IdpNetworkRequestManager::kManifestFilePath); @@ -588,8 +593,7 @@ manifest_list_url_loader_.reset(); if (response_error != FetchStatus::kSuccess) { - std::move(manifest_list_callback_) - .Run(response_error, std::set<std::string>()); + std::move(manifest_list_callback_).Run(response_error, std::set<GURL>()); return; } @@ -622,7 +626,7 @@ void IdpNetworkRequestManager::OnManifestListParsed( data_decoder::DataDecoder::ValueOrError result) { - std::set<std::string> urls; + std::set<GURL> urls; if (GetParsingError(result) == FetchStatus::kInvalidResponseError) { std::move(manifest_list_callback_) @@ -648,10 +652,10 @@ const std::string* url = value.GetIfString(); if (!url) { std::move(manifest_list_callback_) - .Run(FetchStatus::kInvalidResponseError, std::set<std::string>()); + .Run(FetchStatus::kInvalidResponseError, std::set<GURL>()); return; } - urls.insert(*url); + urls.insert(FixupProviderUrl(GURL(*url))); } std::move(manifest_list_callback_).Run(FetchStatus::kSuccess, urls);
diff --git a/content/browser/webid/idp_network_request_manager.h b/content/browser/webid/idp_network_request_manager.h index 71462257..566d0a9 100644 --- a/content/browser/webid/idp_network_request_manager.h +++ b/content/browser/webid/idp_network_request_manager.h
@@ -100,7 +100,7 @@ using AccountList = std::vector<content::IdentityRequestAccount>; using FetchManifestListCallback = - base::OnceCallback<void(FetchStatus, const std::set<std::string>&)>; + base::OnceCallback<void(FetchStatus, const std::set<GURL>&)>; using FetchManifestCallback = base::OnceCallback< void(FetchStatus, Endpoints, IdentityProviderMetadata)>; using FetchClientMetadataCallback = @@ -127,7 +127,8 @@ IdpNetworkRequestManager(const IdpNetworkRequestManager&) = delete; IdpNetworkRequestManager& operator=(const IdpNetworkRequestManager&) = delete; - GURL ManifestUrl() const; + // Does provider URL fixups (add a slash to the path if missing). + static GURL FixupProviderUrl(const GURL& url); // Fetch the manifest list. This is the /.well-known/fedcm.json file on // the eTLD+1 calculated from the provider URL, used to check that the
diff --git a/content/browser/webid/idp_network_request_manager_unittest.cc b/content/browser/webid/idp_network_request_manager_unittest.cc index ccf0f229..5b646a5 100644 --- a/content/browser/webid/idp_network_request_manager_unittest.cc +++ b/content/browser/webid/idp_network_request_manager_unittest.cc
@@ -63,16 +63,16 @@ void TearDown() override { manager_.reset(); } - std::tuple<FetchStatus, std::set<std::string>> + std::tuple<FetchStatus, std::set<GURL>> SendManifestListRequestAndWaitForResponse(const char* test_data) { GURL manifest_list_url(kTestManifestListUrl); test_url_loader_factory().AddResponse(manifest_list_url.spec(), test_data); base::RunLoop run_loop; FetchStatus parsed_fetch_status; - std::set<std::string> parsed_urls; + std::set<GURL> parsed_urls; auto callback = base::BindLambdaForTesting( - [&](FetchStatus fetch_status, const std::set<std::string>& urls) { + [&](FetchStatus fetch_status, const std::set<GURL>& urls) { parsed_fetch_status = fetch_status; parsed_urls = urls; run_loop.Quit(); @@ -422,29 +422,35 @@ TEST_F(IdpNetworkRequestManagerTest, ParseManifestList) { FetchStatus fetch_status; - std::set<std::string> urls; + std::set<GURL> urls; std::tie(fetch_status, urls) = SendManifestListRequestAndWaitForResponse(R"({ - "provider_urls": ["https://idp.test/fedcm.json"] + "provider_urls": ["https://idp.test/"] })"); EXPECT_EQ(FetchStatus::kSuccess, fetch_status); - EXPECT_EQ(std::set<std::string>{kTestManifestUrl}, urls); + EXPECT_EQ(std::set<GURL>{GURL("https://idp.test/")}, urls); + + std::tie(fetch_status, urls) = SendManifestListRequestAndWaitForResponse(R"({ + "provider_urls": ["https://idp.test/path"] + })"); + EXPECT_EQ(FetchStatus::kSuccess, fetch_status); + EXPECT_EQ(std::set<GURL>{GURL("https://idp.test/path/")}, urls); // Value not a list std::tie(fetch_status, urls) = SendManifestListRequestAndWaitForResponse(R"({ - "provider_urls": "https://idp.test/fedcm.json" + "provider_urls": "https://idp.test/" })"); EXPECT_EQ(FetchStatus::kInvalidResponseError, fetch_status); // Toplevel not a dictionary std::tie(fetch_status, urls) = SendManifestListRequestAndWaitForResponse(R"( - ["https://idp.test/fedcm.json"] + ["https://idp.test/"] )"); EXPECT_EQ(FetchStatus::kInvalidResponseError, fetch_status); // Incorrect key std::tie(fetch_status, urls) = SendManifestListRequestAndWaitForResponse(R"({ - "providers": ["https://idp.test/fedcm.json"] + "providers": ["https://idp.test/"] })"); EXPECT_EQ(FetchStatus::kInvalidResponseError, fetch_status);
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 9d328f8..92c9845 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -366,6 +366,7 @@ "java/src/org/chromium/content_public/browser/SpeechRecognition.java", "java/src/org/chromium/content_public/browser/ViewEventSink.java", "java/src/org/chromium/content_public/browser/WebAuthenticationDelegate.java", + "java/src/org/chromium/content_public/browser/WebAuthnCredentialDetails.java", "java/src/org/chromium/content_public/browser/WebContents.java", "java/src/org/chromium/content_public/browser/WebContentsAccessibility.java", "java/src/org/chromium/content_public/browser/WebContentsInternals.java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java b/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java index 869a576..e965e2c 100644 --- a/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java
@@ -16,6 +16,7 @@ import org.chromium.content_public.browser.LifecycleState; import org.chromium.content_public.browser.PermissionsPolicyFeature; import org.chromium.content_public.browser.RenderFrameHost; +import org.chromium.content_public.browser.WebAuthnCredentialDetails; import org.chromium.mojo.bindings.Interface; import org.chromium.mojo.bindings.InterfaceRequest; import org.chromium.mojo.system.Pair; @@ -216,6 +217,42 @@ } @Override + public void onCredentialsDetailsListReceived( + List<WebAuthnCredentialDetails> credentialList, Callback<byte[]> callback) { + assert credentialList != null; + assert callback != null; + if (mNativeRenderFrameHostAndroid == 0) { + callback.onResult(new byte[0]); + return; + } + WebAuthnCredentialDetails[] credentialArray = + credentialList.toArray(new WebAuthnCredentialDetails[credentialList.size()]); + RenderFrameHostImplJni.get().onCredentialsDetailsListReceived( + mNativeRenderFrameHostAndroid, RenderFrameHostImpl.this, credentialArray, callback); + } + + @CalledByNative + private static String getWebAuthnCredentialDetailsUserName(WebAuthnCredentialDetails cred) { + return cred.mUserName; + } + + @CalledByNative + private static String getWebAuthnCredentialDetailsUserDisplayName( + WebAuthnCredentialDetails cred) { + return cred.mUserDisplayName; + } + + @CalledByNative + private static byte[] getWebAuthnCredentialDetailsUserId(WebAuthnCredentialDetails cred) { + return cred.mUserId; + } + + @CalledByNative + private static byte[] getWebAuthnCredentialDetailsCredentialId(WebAuthnCredentialDetails cred) { + return cred.mCredentialId; + } + + @Override public GlobalRenderFrameHostId getGlobalRenderFrameHostId() { return mRenderFrameHostId; } @@ -257,6 +294,9 @@ int performMakeCredentialWebAuthSecurityChecks(long nativeRenderFrameHostAndroid, RenderFrameHostImpl caller, String relyingPartyId, Origin effectiveOrigin, boolean isPaymentCredentialCreation); + void onCredentialsDetailsListReceived(long nativeRenderFrameHostAndroid, + RenderFrameHostImpl caller, WebAuthnCredentialDetails[] credentialList, + Callback<byte[]> callback); int getLifecycleState(long nativeRenderFrameHostAndroid, RenderFrameHostImpl caller); } }
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/RenderFrameHost.java b/content/public/android/java/src/org/chromium/content_public/browser/RenderFrameHost.java index 59c2a1d..c3191ce 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/RenderFrameHost.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/RenderFrameHost.java
@@ -4,6 +4,7 @@ package org.chromium.content_public.browser; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import org.chromium.base.Callback; @@ -163,6 +164,17 @@ String relyingPartyId, Origin effectiveOrigin, boolean isPaymentCredentialCreation); /** + * Provides a list of credentials for WebAuthn Conditional UI. These credentials become + * available as options for autofill UI on sign-in input fields. The callback is invoked when + * a user selects one of the credentials from the list. + * + * @param credentialList The list of credentials that can be used as autofill suggestions. + * @param callback The callback to be invoked with the credential ID of a selected credential. + */ + void onCredentialsDetailsListReceived(@NonNull List<WebAuthnCredentialDetails> credentialList, + @NonNull Callback<byte[]> callback); + + /** * @return An identifier for this RenderFrameHost. */ GlobalRenderFrameHostId getGlobalRenderFrameHostId();
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebAuthnCredentialDetails.java b/content/public/android/java/src/org/chromium/content_public/browser/WebAuthnCredentialDetails.java new file mode 100644 index 0000000..1e212a3 --- /dev/null +++ b/content/public/android/java/src/org/chromium/content_public/browser/WebAuthnCredentialDetails.java
@@ -0,0 +1,33 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.content_public.browser; + +/** + * Describes a WebAuthn credential available on the authenticator. + */ +public final class WebAuthnCredentialDetails { + /** + * Username associated with the credential. + */ + public String mUserName; + + /** + * Display name associated with the credential. + */ + public String mUserDisplayName; + + /** + * Unique identifier associated with the user account that the credential + * signs in to. + */ + public byte[] mUserId; + + /** + * Identifier for the credential itself. + */ + public byte[] mCredentialId; + + public WebAuthnCredentialDetails() {} +}
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index bd6baf28..cf71d5d 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -547,6 +547,7 @@ "android/synchronous_compositor.h", "android/synchronous_compositor_client.h", "ax_inspect_factory_android.cc", + "conditional_ui_delegate_android.h", "tts_environment_android.h", ] }
diff --git a/content/public/browser/conditional_ui_delegate_android.h b/content/public/browser/conditional_ui_delegate_android.h new file mode 100644 index 0000000..74992bc19 --- /dev/null +++ b/content/public/browser/conditional_ui_delegate_android.h
@@ -0,0 +1,34 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_PUBLIC_BROWSER_CONDITIONAL_UI_DELEGATE_ANDROID_H_ +#define CONTENT_PUBLIC_BROWSER_CONDITIONAL_UI_DELEGATE_ANDROID_H_ + +#include <vector> + +#include "base/callback_forward.h" + +namespace device { +class DiscoverableCredentialMetadata; +} + +namespace content { + +// Interface for providing the embedder with a list of Web Authentication +// credentials for use in Conditional UI. +class ConditionalUiDelegateAndroid { + public: + virtual ~ConditionalUiDelegateAndroid() = default; + + // Called when a Web Authentication Conditional UI request is received. This + // provides the callback that will complete the request if and when a user + // selects a credential from a form autofill dialog. + virtual void OnWebAuthnRequestPending( + const std::vector<device::DiscoverableCredentialMetadata>& credentials, + base::OnceCallback<void(const std::vector<uint8_t>& id)> callback) = 0; +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_CONDITIONAL_UI_DELEGATE_ANDROID_H_
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index 1ffe039..b9e9efeb 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -76,6 +76,7 @@ #include "url/origin.h" #if BUILDFLAG(IS_ANDROID) +#include "content/public/browser/conditional_ui_delegate_android.h" #include "content/public/browser/tts_environment_android.h" #endif @@ -1337,4 +1338,11 @@ return nullptr; } +#if BUILDFLAG(IS_ANDROID) +ConditionalUiDelegateAndroid* ContentBrowserClient::GetConditionalUiDelegate( + RenderFrameHost* host) { + return nullptr; +} +#endif + } // namespace content
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index c78f2f41..3c3c92e 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -64,6 +64,10 @@ #include "ui/base/page_transition_types.h" #include "ui/base/window_open_disposition.h" +#if BUILDFLAG(IS_ANDROID) +#include "content/public/browser/conditional_ui_delegate_android.h" +#endif + #if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)) || BUILDFLAG(IS_FUCHSIA) #include "base/posix/global_descriptors.h" #endif @@ -2232,6 +2236,13 @@ GetAlternativeErrorPageOverrideInfo(const GURL& url, BrowserContext* browser_context, int32_t error_code); + +#if BUILDFLAG(IS_ANDROID) + // Gets the delegate interface that is used to interact with the Web + // Authentication Conditional UI implementation in the embedder. + virtual ConditionalUiDelegateAndroid* GetConditionalUiDelegate( + RenderFrameHost* host); +#endif // BUILDFLAG(IS_ANDROID) }; } // namespace content
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockRenderFrameHost.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockRenderFrameHost.java index 1c74295..eb71a6a 100644 --- a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockRenderFrameHost.java +++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockRenderFrameHost.java
@@ -10,6 +10,7 @@ import org.chromium.content_public.browser.LifecycleState; import org.chromium.content_public.browser.PermissionsPolicyFeature; import org.chromium.content_public.browser.RenderFrameHost; +import org.chromium.content_public.browser.WebAuthnCredentialDetails; import org.chromium.mojo.bindings.Interface; import org.chromium.url.GURL; import org.chromium.url.Origin; @@ -90,6 +91,10 @@ } @Override + public void onCredentialsDetailsListReceived( + List<WebAuthnCredentialDetails> credentialList, Callback<byte[]> callback) {} + + @Override public GlobalRenderFrameHostId getGlobalRenderFrameHostId() { return new GlobalRenderFrameHostId(-1, -1); }
diff --git a/content/public/test/test_aggregation_service.h b/content/public/test/test_aggregation_service.h index 91b8f5c..94ae456 100644 --- a/content/public/test/test_aggregation_service.h +++ b/content/public/test/test_aggregation_service.h
@@ -21,6 +21,7 @@ namespace base { class Clock; +class FilePath; } // namespace base namespace network { @@ -92,11 +93,11 @@ // after serialization. virtual void SetDisablePayloadEncryption(bool should_disable) = 0; - // Parses the keys for `url` from `json_string`, and saves the set of keys + // Parses the keys for `url` from `json_file`, and saves the set of keys // to storage. `callback` will be run once completed which takes a boolean // value indicating whether the keys were parsed successfully. virtual void SetPublicKeys(const GURL& url, - const std::string& json_string, + const base::FilePath& json_file, base::OnceCallback<void(bool)> callback) = 0; // Construct an aggregatable report from the information in `request`.
diff --git a/content/services/auction_worklet/register_ad_beacon_bindings.cc b/content/services/auction_worklet/register_ad_beacon_bindings.cc index bcf9fce..3bdd068 100644 --- a/content/services/auction_worklet/register_ad_beacon_bindings.cc +++ b/content/services/auction_worklet/register_ad_beacon_bindings.cc
@@ -14,7 +14,6 @@ #include "base/strings/strcat.h" #include "content/services/auction_worklet/auction_v8_helper.h" #include "gin/converter.h" -#include "services/network/public/cpp/is_potentially_trustworthy.h" #include "url/gurl.h" #include "url/url_constants.h" #include "v8-context.h" @@ -89,7 +88,7 @@ std::string url_string = gin::V8ToString(isolate, obj->Get(context, key).ToLocalChecked()); GURL url(url_string); - if (!url.is_valid() || !network::IsUrlPotentiallyTrustworthy(url)) { + if (!url.is_valid() || !url.SchemeIs(url::kHttpsScheme)) { isolate->ThrowException( v8::Exception::TypeError(v8_helper->CreateStringFromLiteral( base::StrCat({"registerAdBeacon invalid reporting url for key '",
diff --git a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt index 3782de4..7ea691b 100644 --- a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
@@ -128,6 +128,8 @@ # Flakey on Lacros FYI bot crbug.com/1311719 [ linux display-server-wayland ] GpuProcess_disabling_workarounds_works [ RetryOnFailure ] +crbug.com/1321145 [ fuchsia fuchsia-board-qemu-x64 ] * [ Failure ] + ####################################################################### # Automated Entries After This Point - Do Not Manually Add Below Here # #######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index b249652..98125e3d 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -205,6 +205,8 @@ crbug.com/1213170 [ mac nvidia-0xfe9 ] Pixel_WebGPUCopyExternalImage* [ Skip ] crbug.com/1213170 [ mac nvidia-0xfe9 ] Pixel_WebGPUWebGLTexImage2D [ Skip ] +crbug.com/1203317 [ mac ] Pixel_OffscreenCanvasWebGLPaintAfterResize [ Skip ] + # WebGPU pixel tests fail on Linux+SkiaRenderer+Vulkan crbug.com/1213657 [ linux skia-renderer-vulkan ] Pixel_WebGPU* [ Skip ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index bc2fc6c..3e17b4e 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -284,8 +284,6 @@ crbug.com/1297265 [ win7 passthrough amd-0x6613 angle-d3d11 ] conformance2/renderbuffers/multisampled-stencil-renderbuffer-initialization.html [ RetryOnFailure ] crbug.com/1298096 [ win7 passthrough amd-0x6613 angle-d3d11 ] conformance2/textures/canvas_sub_rectangle/tex-3d-r16f-red-half_float.html [ RetryOnFailure ] -# Test regression and potential driver bug on AMD RX 5500 XT with recent BlendState refactoring -crbug.com/angleproject/7200 [ win amd-0x7340 angle-d3d11 ] conformance2/textures/misc/angle-stuck-depth-textures.html [ Failure ] # Recent AMD drivers seem to have a regression with 3D textures. # (Some of these tests seem to occasionally pass unexpectedly.)
diff --git a/content/test/test_aggregation_service_impl.cc b/content/test/test_aggregation_service_impl.cc index 73490c0..6462c49 100644 --- a/content/test/test_aggregation_service_impl.cc +++ b/content/test/test_aggregation_service_impl.cc
@@ -4,15 +4,14 @@ #include "content/test/test_aggregation_service_impl.h" -#include <memory> #include <string> #include <utility> #include "base/bind.h" #include "base/callback.h" #include "base/check.h" +#include "base/files/file_path.h" #include "base/guid.h" -#include "base/json/json_string_value_serializer.h" #include "base/logging.h" #include "base/memory/scoped_refptr.h" #include "base/task/thread_pool.h" @@ -23,9 +22,10 @@ #include "content/browser/aggregation_service/aggregatable_report_assembler.h" #include "content/browser/aggregation_service/aggregatable_report_sender.h" #include "content/browser/aggregation_service/aggregation_service_storage_sql.h" +#include "content/browser/aggregation_service/aggregation_service_test_utils.h" #include "content/browser/aggregation_service/public_key.h" -#include "content/browser/aggregation_service/public_key_parsing_utils.h" #include "services/network/public/cpp/shared_url_loader_factory.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" @@ -102,30 +102,20 @@ void TestAggregationServiceImpl::SetPublicKeys( const GURL& url, - const std::string& json_string, + const base::FilePath& json_file, base::OnceCallback<void(bool)> callback) { - JSONStringValueDeserializer deserializer(json_string); - std::string error_message; - std::unique_ptr<base::Value> value_ptr = - deserializer.Deserialize(nullptr, &error_message); - if (!value_ptr) { - LOG(ERROR) << "Unable to deserialze json string: " << json_string - << ", error: " << error_message; + std::string error_msg; + absl::optional<PublicKeyset> keyset = + aggregation_service::ReadAndParsePublicKeys(json_file, clock_.Now(), + &error_msg); + if (!keyset) { + LOG(ERROR) << error_msg; std::move(callback).Run(false); return; } - std::vector<PublicKey> keys = aggregation_service::GetPublicKeys(*value_ptr); - if (keys.empty()) { - std::move(callback).Run(false); - return; - } - - PublicKeyset keyset(std::move(keys), - /*fetch_time=*/clock_.Now(), - /*expiry_time=*/base::Time::Max()); storage_.AsyncCall(&AggregationServiceKeyStorage::SetPublicKeys) - .WithArgs(url, std::move(keyset)) + .WithArgs(url, std::move(*keyset)) .Then(base::BindOnce(std::move(callback), true)); }
diff --git a/content/test/test_aggregation_service_impl.h b/content/test/test_aggregation_service_impl.h index 91439c5..a4250afa 100644 --- a/content/test/test_aggregation_service_impl.h +++ b/content/test/test_aggregation_service_impl.h
@@ -45,7 +45,7 @@ // TestAggregationService: void SetDisablePayloadEncryption(bool should_disable) override; void SetPublicKeys(const GURL& url, - const std::string& json_string, + const base::FilePath& json_file, base::OnceCallback<void(bool)> callback) override; void AssembleReport( AssembleRequest request,
diff --git a/content/test/test_aggregation_service_impl_unittest.cc b/content/test/test_aggregation_service_impl_unittest.cc index 67db588..7757bd3 100644 --- a/content/test/test_aggregation_service_impl_unittest.cc +++ b/content/test/test_aggregation_service_impl_unittest.cc
@@ -8,6 +8,9 @@ #include <string> #include <vector> +#include "base/files/file_path.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/test/bind.h" @@ -54,9 +57,16 @@ })", {generated_key.base64_encoded_public_key}, /*offsets=*/nullptr); + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + base::FilePath json_file = + temp_dir.GetPath().Append(FILE_PATH_LITERAL("public_keys.json")); + + ASSERT_TRUE(base::WriteFile(json_file, json_string)); + GURL url("https://a.com/keys"); - service_impl_->SetPublicKeys(url, json_string, + service_impl_->SetPublicKeys(url, json_file, base::BindLambdaForTesting([&](bool succeeded) { EXPECT_TRUE(succeeded); }));
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index 35e4d46..c849b17f 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1710,6 +1710,7 @@ OS_DIAGNOSTICS_RUNLANCONNECTIVITYROUTINE = 1647, LOGIN_REQUESTEXTERNALLOGOUT = 1648, LOGIN_NOTIFYEXTERNALLOGOUTDONE = 1649, + PASSWORDSPRIVATE_RECORDCHANGEPASSWORDFLOWSTARTED = 1650, // Last entry: Add new entries above, then run: // tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/extensions/common/api/declarative/declarative_manifest_data.cc b/extensions/common/api/declarative/declarative_manifest_data.cc index 30405bf..4258c91 100644 --- a/extensions/common/api/declarative/declarative_manifest_data.cc +++ b/extensions/common/api/declarative/declarative_manifest_data.cc
@@ -131,7 +131,7 @@ return nullptr; } - for (const auto& element : value.GetListDeprecated()) { + for (const auto& element : value.GetList()) { const base::DictionaryValue* dict = nullptr; if (!element.GetAsDictionary(&dict)) { error_builder.Append("expected dictionary, got %s",
diff --git a/extensions/common/event_matcher.cc b/extensions/common/event_matcher.cc index 659c24f..b20c601 100644 --- a/extensions/common/event_matcher.cc +++ b/extensions/common/event_matcher.cc
@@ -60,14 +60,14 @@ int EventMatcher::GetURLFilterCount() const { base::ListValue* url_filters = nullptr; if (filter_->GetList(kUrlFiltersKey, &url_filters)) - return url_filters->GetListDeprecated().size(); + return url_filters->GetList().size(); return 0; } const base::Value::Dict* EventMatcher::GetURLFilter(int i) { base::ListValue* url_filters = nullptr; if (filter_->GetList(kUrlFiltersKey, &url_filters)) { - base::Value& dict = url_filters->GetListDeprecated()[i]; + base::Value& dict = url_filters->GetList()[i]; return dict.GetIfDict(); } return nullptr; @@ -94,14 +94,14 @@ int EventMatcher::GetWindowTypeCount() const { base::ListValue* window_type_filters = nullptr; if (filter_->GetList(kWindowTypesKey, &window_type_filters)) - return window_type_filters->GetListDeprecated().size(); + return window_type_filters->GetList().size(); return 0; } bool EventMatcher::GetWindowType(int i, std::string* window_type_out) const { base::ListValue* window_types = nullptr; if (filter_->GetList(kWindowTypesKey, &window_types)) { - base::Value::ConstListView types_list = window_types->GetListDeprecated(); + const base::Value::List& types_list = window_types->GetList(); if (i >= 0 && static_cast<size_t>(i) < types_list.size() && types_list[i].is_string()) { *window_type_out = types_list[i].GetString();
diff --git a/extensions/common/extension.cc b/extensions/common/extension.cc index 6922ff3..f6c71db 100644 --- a/extensions/common/extension.cc +++ b/extensions/common/extension.cc
@@ -725,8 +725,7 @@ *error = base::ASCIIToUTF16(list_error); return false; } - base::Value::ConstListView pattern_list = - temp_pattern_value->GetListDeprecated(); + const base::Value::List& pattern_list = temp_pattern_value->GetList(); for (size_t i = 0; i < pattern_list.size(); ++i) { std::string pattern_string; if (pattern_list[i].is_string()) {
diff --git a/extensions/common/extension_api.cc b/extensions/common/extension_api.cc index c6acb25..ad67441 100644 --- a/extensions/common/extension_api.cc +++ b/extensions/common/extension_api.cc
@@ -55,7 +55,7 @@ const base::DictionaryValue* FindListItem(const base::ListValue* list, const std::string& property_name, const std::string& property_value) { - for (const base::Value& item_value : list->GetListDeprecated()) { + for (const base::Value& item_value : list->GetList()) { CHECK(item_value.is_dict()) << property_value << "/" << property_name; const base::DictionaryValue* item = static_cast<const base::DictionaryValue*>(&item_value);
diff --git a/extensions/common/extension_l10n_util.cc b/extensions/common/extension_l10n_util.cc index 102f4956..720693c 100644 --- a/extensions/common/extension_l10n_util.cc +++ b/extensions/common/extension_l10n_util.cc
@@ -124,22 +124,20 @@ const extensions::MessageBundle& messages, base::DictionaryValue* manifest, std::string* error) { - base::ListValue* list = NULL; - if (!manifest->GetList(key, &list)) + base::ListValue* list_value = nullptr; + if (!manifest->GetList(key, &list_value)) return true; - bool ret = true; - base::Value::ListView list_view = list->GetListDeprecated(); - for (size_t i = 0; i < list_view.size(); ++i) { - if (list_view[i].is_string()) { - std::string result = list_view[i].GetString(); - if (messages.ReplaceMessages(&result, error)) - list_view[i] = base::Value(result); - else - ret = false; + for (base::Value& item : list_value->GetList()) { + if (item.is_string()) { + std::string result = item.GetString(); + if (!messages.ReplaceMessages(&result, error)) { + return false; + } + item = base::Value(result); } } - return ret; + return true; } std::string& GetProcessLocale() { @@ -270,7 +268,7 @@ base::ListValue* file_handlers = NULL; if (manifest->GetList(keys::kFileBrowserHandlers, &file_handlers)) { - for (base::Value& handler : file_handlers->GetListDeprecated()) { + for (base::Value& handler : file_handlers->GetList()) { if (!handler.is_dict()) { *error = errors::kInvalidFileBrowserHandler; return false; @@ -284,7 +282,7 @@ // Initialize all input_components base::ListValue* input_components = NULL; if (manifest->GetList(keys::kInputComponents, &input_components)) { - for (base::Value& module : input_components->GetListDeprecated()) { + for (base::Value& module : input_components->GetList()) { if (!module.is_dict()) { *error = errors::kInvalidInputComponents; return false;
diff --git a/extensions/common/extension_l10n_util_unittest.cc b/extensions/common/extension_l10n_util_unittest.cc index 3773e79..7ea8c7bf 100644 --- a/extensions/common/extension_l10n_util_unittest.cc +++ b/extensions/common/extension_l10n_util_unittest.cc
@@ -530,7 +530,7 @@ base::ListValue* handlers_raw = nullptr; manifest.GetList(keys::kFileBrowserHandlers, &handlers_raw); base::DictionaryValue* handler_raw = nullptr; - handlers_raw->GetListDeprecated()[0].GetAsDictionary(&handler_raw); + handlers_raw->GetList()[0].GetAsDictionary(&handler_raw); ASSERT_TRUE(handler_raw->GetString(keys::kActionDefaultTitle, &result)); EXPECT_EQ("file handler title", result); @@ -668,9 +668,8 @@ base::ListValue* startup_pages_raw = nullptr; ASSERT_TRUE(manifest.GetList(keys::kOverrideStartupPage, &startup_pages_raw)); - base::Value::ConstListView startup_pages_raw_list = - startup_pages_raw->GetListDeprecated(); - ASSERT_GT(startup_pages_raw_list.size(), 0u); + base::Value::List& startup_pages_raw_list = startup_pages_raw->GetList(); + ASSERT_FALSE(startup_pages_raw_list.empty()); ASSERT_TRUE(startup_pages_raw_list[0].is_string()); EXPECT_EQ("http://www.foo.de", startup_pages_raw_list[0].GetString());
diff --git a/extensions/common/manifest_handlers/action_handlers_handler.cc b/extensions/common/manifest_handlers/action_handlers_handler.cc index 17378724..7db5ab56 100644 --- a/extensions/common/manifest_handlers/action_handlers_handler.cc +++ b/extensions/common/manifest_handlers/action_handlers_handler.cc
@@ -50,7 +50,7 @@ } auto info = std::make_unique<ActionHandlersInfo>(); - for (const base::Value& wrapped_value : entries->GetListDeprecated()) { + for (const base::Value& wrapped_value : entries->GetList()) { std::string value; bool enabled_on_lock_screen = false; if (wrapped_value.is_dict()) {
diff --git a/extensions/common/manifest_handlers/app_isolation_info.cc b/extensions/common/manifest_handlers/app_isolation_info.cc index f29bdef..011646b 100644 --- a/extensions/common/manifest_handlers/app_isolation_info.cc +++ b/extensions/common/manifest_handlers/app_isolation_info.cc
@@ -69,15 +69,15 @@ } bool has_isolated_storage = false; - base::Value::ConstListView list_view = isolation_list->GetListDeprecated(); - for (size_t i = 0; i < list_view.size(); ++i) { - if (!list_view[i].is_string()) { + const base::Value::List& list = isolation_list->GetList(); + for (size_t i = 0; i < list.size(); ++i) { + if (!list[i].is_string()) { *error = ErrorUtils::FormatErrorMessageUTF16( manifest_errors::kInvalidIsolationValue, base::NumberToString(i)); return false; } - const std::string& isolation_string = list_view[i].GetString(); + const std::string& isolation_string = list[i].GetString(); // Check for isolated storage. if (isolation_string == manifest_values::kIsolatedStorage) { has_isolated_storage = true;
diff --git a/extensions/common/manifest_handlers/background_info.cc b/extensions/common/manifest_handlers/background_info.cc index eae899d..9ae2128 100644 --- a/extensions/common/manifest_handlers/background_info.cc +++ b/extensions/common/manifest_handlers/background_info.cc
@@ -186,8 +186,8 @@ return false; } - base::Value::ConstListView background_scripts = - background_scripts_value->GetListDeprecated(); + const base::Value::List& background_scripts = + background_scripts_value->GetList(); for (size_t i = 0; i < background_scripts.size(); ++i) { if (!background_scripts[i].is_string()) { *error = ErrorUtils::FormatErrorMessageUTF16(
diff --git a/extensions/common/manifest_handlers/file_handler_info.cc b/extensions/common/manifest_handlers/file_handler_info.cc index c023aad5..2344447 100644 --- a/extensions/common/manifest_handlers/file_handler_info.cc +++ b/extensions/common/manifest_handlers/file_handler_info.cc
@@ -106,8 +106,8 @@ } } - if ((!mime_types || mime_types->GetListDeprecated().empty()) && - (!file_extensions || file_extensions->GetListDeprecated().empty()) && + if ((!mime_types || mime_types->GetList().empty()) && + (!file_extensions || file_extensions->GetList().empty()) && !handler.include_directories) { *error = ErrorUtils::FormatErrorMessageUTF16( errors::kInvalidFileHandlerNoTypeOrExtension, @@ -116,29 +116,28 @@ } if (mime_types) { - base::Value::ConstListView list_storage = mime_types->GetListDeprecated(); - for (size_t i = 0; i < list_storage.size(); ++i) { - if (!list_storage[i].is_string()) { + const base::Value::List& list = mime_types->GetList(); + for (size_t i = 0; i < list.size(); ++i) { + if (!list[i].is_string()) { *error = ErrorUtils::FormatErrorMessageUTF16( errors::kInvalidFileHandlerTypeElement, handler_id, base::NumberToString(i)); return false; } - handler.types.insert(list_storage[i].GetString()); + handler.types.insert(list[i].GetString()); } } if (file_extensions) { - base::Value::ConstListView list_storage = - file_extensions->GetListDeprecated(); - for (size_t i = 0; i < list_storage.size(); ++i) { - if (!list_storage[i].is_string()) { + const base::Value::List& list = file_extensions->GetList(); + for (size_t i = 0; i < list.size(); ++i) { + if (!list[i].is_string()) { *error = ErrorUtils::FormatErrorMessageUTF16( errors::kInvalidFileHandlerExtensionElement, handler_id, base::NumberToString(i)); return false; } - handler.extensions.insert(list_storage[i].GetString()); + handler.extensions.insert(list[i].GetString()); } }
diff --git a/extensions/common/manifest_handlers/kiosk_mode_info.cc b/extensions/common/manifest_handlers/kiosk_mode_info.cc index 79f6adab..e84e306 100644 --- a/extensions/common/manifest_handlers/kiosk_mode_info.cc +++ b/extensions/common/manifest_handlers/kiosk_mode_info.cc
@@ -149,7 +149,7 @@ const bool allow_enabled_on_launch = AllowSecondaryAppEnabledOnLaunch(extension); - for (const auto& value : secondary_apps_value->GetListDeprecated()) { + for (const auto& value : secondary_apps_value->GetList()) { std::unique_ptr<KioskSecondaryAppsType> app = KioskSecondaryAppsType::FromValue(value, error); if (!app) {
diff --git a/extensions/common/manifest_handlers/mime_types_handler.cc b/extensions/common/manifest_handlers/mime_types_handler.cc index bdeff4a..26ebb6f7 100644 --- a/extensions/common/manifest_handlers/mime_types_handler.cc +++ b/extensions/common/manifest_handlers/mime_types_handler.cc
@@ -146,7 +146,7 @@ auto info = std::make_unique<MimeTypesHandlerInfo>(); info->handler_.set_extension_id(extension->id()); - for (const auto& entry : mime_types_value->GetListDeprecated()) { + for (const auto& entry : mime_types_value->GetList()) { if (!entry.is_string()) { *error = errors::kInvalidMIMETypes; return false;
diff --git a/extensions/common/manifest_handlers/nacl_modules_handler.cc b/extensions/common/manifest_handlers/nacl_modules_handler.cc index 0df0768a1..1c96822 100644 --- a/extensions/common/manifest_handlers/nacl_modules_handler.cc +++ b/extensions/common/manifest_handlers/nacl_modules_handler.cc
@@ -52,15 +52,15 @@ std::unique_ptr<NaClModuleData> nacl_module_data(new NaClModuleData); - base::Value::ConstListView list_view = list_value->GetListDeprecated(); - for (size_t i = 0; i < list_view.size(); ++i) { - if (!list_view[i].is_dict()) { + const base::Value::List& list = list_value->GetList(); + for (size_t i = 0; i < list.size(); ++i) { + if (!list[i].is_dict()) { *error = errors::kInvalidNaClModules; return false; } // Get nacl_modules[i].path. - const base::Value* path_str = list_view[i].FindKeyOfType( + const base::Value* path_str = list[i].FindKeyOfType( keys::kNaClModulesPath, base::Value::Type::STRING); if (path_str == nullptr) { *error = ErrorUtils::FormatErrorMessageUTF16( @@ -69,7 +69,7 @@ } // Get nacl_modules[i].mime_type. - const base::Value* mime_type = list_view[i].FindKeyOfType( + const base::Value* mime_type = list[i].FindKeyOfType( keys::kNaClModulesMIMEType, base::Value::Type::STRING); if (mime_type == nullptr) { *error = ErrorUtils::FormatErrorMessageUTF16(
diff --git a/extensions/common/manifest_handlers/permissions_parser.cc b/extensions/common/manifest_handlers/permissions_parser.cc index d1052e3..fc9ee49 100644 --- a/extensions/common/manifest_handlers/permissions_parser.cc +++ b/extensions/common/manifest_handlers/permissions_parser.cc
@@ -103,10 +103,10 @@ } // Add all permissions parsed from the manifest to |hosts|. - base::Value::ConstListView list_view = permissions->GetListDeprecated(); - for (size_t i = 0; i < list_view.size(); ++i) { - if (list_view[i].is_string()) { - hosts->push_back(list_view[i].GetString()); + const base::Value::List& list = permissions->GetList(); + for (size_t i = 0; i < list.size(); ++i) { + if (list[i].is_string()) { + hosts->push_back(list[i].GetString()); } else { *error = ErrorUtils::FormatErrorMessageUTF16( errors::kInvalidHostPermission, key, base::NumberToString(i));
diff --git a/extensions/common/manifest_handlers/sandboxed_page_info.cc b/extensions/common/manifest_handlers/sandboxed_page_info.cc index 9064fa4..432e3714 100644 --- a/extensions/common/manifest_handlers/sandboxed_page_info.cc +++ b/extensions/common/manifest_handlers/sandboxed_page_info.cc
@@ -64,14 +64,14 @@ return false; } - base::Value::ConstListView list_view = list_value->GetListDeprecated(); - for (size_t i = 0; i < list_view.size(); ++i) { - if (!list_view[i].is_string()) { + const base::Value::List& list = list_value->GetList(); + for (size_t i = 0; i < list.size(); ++i) { + if (!list[i].is_string()) { *error = ErrorUtils::FormatErrorMessageUTF16( errors::kInvalidSandboxedPage, base::NumberToString(i)); return false; } - std::string relative_path = list_view[i].GetString(); + std::string relative_path = list[i].GetString(); URLPattern pattern(URLPattern::SCHEME_EXTENSION); if (pattern.Parse(extension->url().spec()) != URLPattern::ParseResult::kSuccess) {
diff --git a/extensions/common/manifest_handlers/webview_info.cc b/extensions/common/manifest_handlers/webview_info.cc index 6c97bea..8a77fc4 100644 --- a/extensions/common/manifest_handlers/webview_info.cc +++ b/extensions/common/manifest_handlers/webview_info.cc
@@ -122,29 +122,28 @@ return false; } - const base::Value* partition_list = dict_value->FindKeyOfType( + const base::Value* partition_list_value = dict_value->FindKeyOfType( keys::kWebviewPartitions, base::Value::Type::LIST); - if (partition_list == nullptr) { + if (partition_list_value == nullptr) { *error = errors::kInvalidWebviewPartitionsList; return false; } // The partition list must have at least one entry. - base::Value::ConstListView partition_list_view = - partition_list->GetListDeprecated(); - if (partition_list_view.empty()) { + const base::Value::List& partition_list = partition_list_value->GetList(); + if (partition_list.empty()) { *error = errors::kInvalidWebviewPartitionsList; return false; } - for (size_t i = 0; i < partition_list_view.size(); ++i) { - if (!partition_list_view[i].is_dict()) { + for (size_t i = 0; i < partition_list.size(); ++i) { + if (!partition_list[i].is_dict()) { *error = ErrorUtils::FormatErrorMessageUTF16( errors::kInvalidWebviewPartition, base::NumberToString(i)); return false; } - const base::Value* webview_name = partition_list_view[i].FindKeyOfType( + const base::Value* webview_name = partition_list[i].FindKeyOfType( keys::kWebviewName, base::Value::Type::STRING); if (webview_name == nullptr) { *error = ErrorUtils::FormatErrorMessageUTF16( @@ -153,31 +152,31 @@ } const std::string& partition_pattern = webview_name->GetString(); - const base::Value* url_list = partition_list_view[i].FindKeyOfType( + const base::Value* url_list_value = partition_list[i].FindKeyOfType( keys::kWebviewAccessibleResources, base::Value::Type::LIST); - if (url_list == nullptr) { + if (url_list_value == nullptr) { *error = errors::kInvalidWebviewAccessibleResourcesList; return false; } // The URL list should have at least one entry. - base::Value::ConstListView url_list_view = url_list->GetListDeprecated(); - if (url_list_view.empty()) { + const base::Value::List& url_list = url_list_value->GetList(); + if (url_list.empty()) { *error = errors::kInvalidWebviewAccessibleResourcesList; return false; } auto partition_item = std::make_unique<PartitionItem>(partition_pattern); - for (size_t url = 0; url < url_list_view.size(); ++url) { - if (!url_list_view[url].is_string()) { + for (const base::Value& item : url_list) { + if (!item.is_string()) { *error = ErrorUtils::FormatErrorMessageUTF16( errors::kInvalidWebviewAccessibleResource, base::NumberToString(i)); return false; } - GURL pattern_url = Extension::GetResourceURL( - extension->url(), url_list_view[url].GetString()); + GURL pattern_url = + Extension::GetResourceURL(extension->url(), item.GetString()); // If passed a non-relative URL (like http://example.com), // Extension::GetResourceURL() will return that URL directly. (See // https://crbug.com/1135236). Check if this happened by comparing the
diff --git a/extensions/common/permissions/api_permission_set.cc b/extensions/common/permissions/api_permission_set.cc index 1f4f71c..8b1155f 100644 --- a/extensions/common/permissions/api_permission_set.cc +++ b/extensions/common/permissions/api_permission_set.cc
@@ -102,11 +102,10 @@ return true; } - base::Value::ConstListView list_view = - permission_value->GetListDeprecated(); - for (size_t i = 0; i < list_view.size(); ++i) { + const base::Value::List& list = permission_value->GetList(); + for (size_t i = 0; i < list.size(); ++i) { std::string permission_str; - if (!list_view[i].is_string()) { + if (!list[i].is_string()) { // permission should be a string if (error) { *error = ErrorUtils::FormatErrorMessageUTF16( @@ -118,8 +117,8 @@ continue; } - if (!CreateAPIPermission(base_name + '.' + list_view[i].GetString(), - nullptr, source, api_permissions, error, + if (!CreateAPIPermission(base_name + '.' + list[i].GetString(), nullptr, + source, api_permissions, error, unhandled_permissions)) return false; } @@ -160,15 +159,15 @@ // return true here anyway. return true; } - base::Value::ConstListView list_view = permissions->GetListDeprecated(); - for (size_t i = 0; i < list_view.size(); ++i) { + const base::Value::List& list = permissions->GetList(); + for (size_t i = 0; i < list.size(); ++i) { std::string permission_str; const base::Value* permission_value = nullptr; // permission should be a string or a single key dict. - if (list_view[i].is_string()) { - permission_str = list_view[i].GetString(); - } else if (list_view[i].is_dict() && list_view[i].DictSize() == 1) { - auto dict_iter = list_view[i].DictItems().begin(); + if (list[i].is_string()) { + permission_str = list[i].GetString(); + } else if (list[i].is_dict() && list[i].DictSize() == 1) { + auto dict_iter = list[i].DictItems().begin(); permission_str = dict_iter->first; permission_value = &dict_iter->second; } else {
diff --git a/extensions/common/permissions/manifest_permission_set.cc b/extensions/common/permissions/manifest_permission_set.cc index 3483230..8467cf0 100644 --- a/extensions/common/permissions/manifest_permission_set.cc +++ b/extensions/common/permissions/manifest_permission_set.cc
@@ -62,8 +62,7 @@ ManifestPermissionSet* manifest_permissions, std::u16string* error, std::vector<std::string>* unhandled_permissions) { - base::Value::ConstListView permissions_list = - permissions->GetListDeprecated(); + const base::Value::List& permissions_list = permissions->GetList(); for (size_t i = 0; i < permissions_list.size(); ++i) { const base::Value& value = permissions_list[i]; std::string permission_name;
diff --git a/extensions/common/url_pattern_set.cc b/extensions/common/url_pattern_set.cc index 9d5b3a9..01a5212 100644 --- a/extensions/common/url_pattern_set.cc +++ b/extensions/common/url_pattern_set.cc
@@ -238,7 +238,7 @@ std::unique_ptr<base::ListValue> value(new base::ListValue); for (auto i = patterns_.cbegin(); i != patterns_.cend(); ++i) { base::Value pattern_str_value(i->GetAsString()); - if (!base::Contains(value->GetListDeprecated(), pattern_str_value)) + if (!base::Contains(value->GetList(), pattern_str_value)) value->Append(std::move(pattern_str_value)); } return value; @@ -283,7 +283,7 @@ bool allow_file_access, std::string* error) { std::vector<std::string> patterns; - for (const base::Value& pattern : value.GetListDeprecated()) { + for (const base::Value& pattern : value.GetList()) { const std::string* item = pattern.GetIfString(); if (!item) return false;
diff --git a/extensions/common/value_builder_unittest.cc b/extensions/common/value_builder_unittest.cc index a44ba5b..68d8dc4 100644 --- a/extensions/common/value_builder_unittest.cc +++ b/extensions/common/value_builder_unittest.cc
@@ -30,11 +30,11 @@ base::ListValue* list_value; ASSERT_TRUE(settings->GetList("permissions", &list_value)); - ASSERT_EQ(2U, list_value->GetListDeprecated().size()); - ASSERT_TRUE(list_value->GetListDeprecated()[0].is_string()); - ASSERT_EQ(list_value->GetListDeprecated()[0].GetString(), "tabs"); - ASSERT_TRUE(list_value->GetListDeprecated()[1].is_string()); - ASSERT_EQ(list_value->GetListDeprecated()[1].GetString(), "history"); + ASSERT_EQ(list_value->GetList().size(), 2u); + ASSERT_TRUE(list_value->GetList()[0].is_string()); + ASSERT_EQ(list_value->GetList()[0].GetString(), "tabs"); + ASSERT_TRUE(list_value->GetList()[1].is_string()); + ASSERT_EQ(list_value->GetList()[1].GetString(), "history"); } TEST(ValueBuilderTest, AppendList) {
diff --git a/gpu/command_buffer/client/raster_implementation.cc b/gpu/command_buffer/client/raster_implementation.cc index 94d238f..c918aba 100644 --- a/gpu/command_buffer/client/raster_implementation.cc +++ b/gpu/command_buffer/client/raster_implementation.cc
@@ -1419,7 +1419,7 @@ raster_properties_->color_space, &skottie_serialization_history_, raster_properties_->can_use_lcd_text, capabilities().context_supports_distance_field_text, - capabilities().max_texture_size, /*raw_draw=*/true)); + capabilities().max_texture_size)); if (preserve_recording) { serializer.Serialize(&list->paint_op_buffer_, &temp_raster_offsets_, preamble);
diff --git a/gpu/command_buffer/service/shared_image_backing_ozone.cc b/gpu/command_buffer/service/shared_image_backing_ozone.cc index db8f6a11..3b1b9bf 100644 --- a/gpu/command_buffer/service/shared_image_backing_ozone.cc +++ b/gpu/command_buffer/service/shared_image_backing_ozone.cc
@@ -410,6 +410,7 @@ // Wait on fence only if reading from stream different than current // stream. if (fence.first != access_stream) { + DCHECK(!fence.second.is_null()); fences->emplace_back(std::move(fence.second)); } } @@ -461,7 +462,9 @@ } if (readonly) { - read_fences_[access_stream] = std::move(fence); + if (!fence.is_null()) { + read_fences_[access_stream] = std::move(fence); + } } else { DCHECK(read_fences_.find(access_stream) == read_fences_.end()); write_fence_ = std::move(fence);
diff --git a/gpu/command_buffer/service/shared_image_factory.cc b/gpu/command_buffer/service/shared_image_factory.cc index e8aec03c..c7788a2 100644 --- a/gpu/command_buffer/service/shared_image_factory.cc +++ b/gpu/command_buffer/service/shared_image_factory.cc
@@ -710,16 +710,22 @@ if (usage & SHARED_IMAGE_USAGE_RAW_DRAW) return true; - // If |shared_image_manager_| is thread safe, it means the display is - // running on a separate thread (which uses a separate GL context or - // VkDeviceQueue). + // DISPLAY is for gpu composition and SCANOUT for overlays. + constexpr int kDisplayCompositorUsage = + SHARED_IMAGE_USAGE_DISPLAY | SHARED_IMAGE_USAGE_SCANOUT; + + // Image is used on display compositor gpu thread if it's used by display + // compositor and if display compositor runs on a separate thread. Image is + // used by display compositor if it has kDisplayCompositorUsage or is being + // created by display compositor. const bool used_by_display_compositor_gpu_thread = - (usage & SHARED_IMAGE_USAGE_DISPLAY || is_for_display_compositor_) && + ((usage & kDisplayCompositorUsage) || is_for_display_compositor_) && shared_image_manager_->display_context_on_another_thread(); - // If it has usage other than DISPLAY OR if it is not used just for display - // compositor, it means that it is used by the gpu main thread. + + // If it has usage other than kDisplayCompositorUsage OR if it is not created + // by display compositor, it means that it is used by the gpu main thread. const bool used_by_main_gpu_thread = - usage & ~SHARED_IMAGE_USAGE_DISPLAY || !is_for_display_compositor_; + usage & ~kDisplayCompositorUsage || !is_for_display_compositor_; return used_by_display_compositor_gpu_thread && used_by_main_gpu_thread; }
diff --git a/infra/OWNERS b/infra/OWNERS index 5c27c867..da9a070 100644 --- a/infra/OWNERS +++ b/infra/OWNERS
@@ -8,9 +8,12 @@ estaab@chromium.org gatong@chromium.org gbeaty@chromium.org +guterman@google.com hypan@google.com kimstephanie@google.com martiniss@chromium.org +morawand@google.com +sshrimp@google.com svenzheng@chromium.org # Other folks who understand the infrastructure well.
diff --git "a/infra/config/generated/builders/ci/Android WebView M \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/Android WebView M \050dbg\051/properties.json" index 404674b..ba8f215 100644 --- "a/infra/config/generated/builders/ci/Android WebView M \050dbg\051/properties.json" +++ "b/infra/config/generated/builders/ci/Android WebView M \050dbg\051/properties.json"
@@ -1,4 +1,98 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView M (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Android WebView M (dbg)", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "android-webview-marshmallow-arm64-dbg", + "group": "tryserver.chromium.android" + }, + { + "builder": "android_arm64_dbg_recipe", + "group": "tryserver.chromium.android" + } + ] + } + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git "a/infra/config/generated/builders/ci/Android WebView N \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/Android WebView N \050dbg\051/properties.json" index 404674b..928f367 100644 --- "a/infra/config/generated/builders/ci/Android WebView N \050dbg\051/properties.json" +++ "b/infra/config/generated/builders/ci/Android WebView N \050dbg\051/properties.json"
@@ -1,4 +1,102 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView N (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Android WebView N (dbg)", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "android-webview-nougat-arm64-dbg", + "group": "tryserver.chromium.android" + }, + { + "builder": "android_arm64_dbg_recipe", + "group": "tryserver.chromium.android" + }, + { + "builder": "android_unswarmed_pixel_aosp", + "group": "tryserver.chromium.android" + } + ] + } + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git "a/infra/config/generated/builders/ci/Android WebView O \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/Android WebView O \050dbg\051/properties.json" index 404674b..cd7658e 100644 --- "a/infra/config/generated/builders/ci/Android WebView O \050dbg\051/properties.json" +++ "b/infra/config/generated/builders/ci/Android WebView O \050dbg\051/properties.json"
@@ -1,4 +1,98 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView O (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Android WebView O (dbg)", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "android-webview-oreo-arm64-dbg", + "group": "tryserver.chromium.android" + }, + { + "builder": "android_arm64_dbg_recipe", + "group": "tryserver.chromium.android" + } + ] + } + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git "a/infra/config/generated/builders/ci/Android WebView P \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/Android WebView P \050dbg\051/properties.json" index 404674b..f5c555e 100644 --- "a/infra/config/generated/builders/ci/Android WebView P \050dbg\051/properties.json" +++ "b/infra/config/generated/builders/ci/Android WebView P \050dbg\051/properties.json"
@@ -1,4 +1,98 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView P (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Android WebView P (dbg)", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "android-webview-pie-arm64-dbg", + "group": "tryserver.chromium.android" + }, + { + "builder": "android_arm64_dbg_recipe", + "group": "tryserver.chromium.android" + } + ] + } + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git "a/infra/config/generated/builders/ci/Android arm64 Builder \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/Android arm64 Builder \050dbg\051/properties.json" index 8252801..6cd8590b 100644 --- "a/infra/config/generated/builders/ci/Android arm64 Builder \050dbg\051/properties.json" +++ "b/infra/config/generated/builders/ci/Android arm64 Builder \050dbg\051/properties.json"
@@ -1,4 +1,427 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView M (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView N (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView O (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView P (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Marshmallow 64 bit Tester", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_wpr_tests" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Nougat Phone Tester", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Oreo Phone Tester", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "android-pie-arm64-dbg", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + ], + "builder_ids_in_scope_for_testing": [ + { + "bucket": "ci", + "builder": "Android WebView M (dbg)", + "project": "chromium" + }, + { + "bucket": "ci", + "builder": "Android WebView N (dbg)", + "project": "chromium" + }, + { + "bucket": "ci", + "builder": "Android WebView O (dbg)", + "project": "chromium" + }, + { + "bucket": "ci", + "builder": "Android WebView P (dbg)", + "project": "chromium" + }, + { + "bucket": "ci", + "builder": "Marshmallow 64 bit Tester", + "project": "chromium" + }, + { + "bucket": "ci", + "builder": "Nougat Phone Tester", + "project": "chromium" + }, + { + "bucket": "ci", + "builder": "Oreo Phone Tester", + "project": "chromium" + }, + { + "bucket": "ci", + "builder": "android-pie-arm64-dbg", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "android-oreo-arm64-dbg", + "group": "tryserver.chromium.android" + }, + { + "builder": "android-pie-arm64-dbg", + "group": "tryserver.chromium.android" + }, + { + "builder": "android-webview-marshmallow-arm64-dbg", + "group": "tryserver.chromium.android" + }, + { + "builder": "android-webview-nougat-arm64-dbg", + "group": "tryserver.chromium.android" + }, + { + "builder": "android-webview-oreo-arm64-dbg", + "group": "tryserver.chromium.android" + }, + { + "builder": "android-webview-pie-arm64-dbg", + "group": "tryserver.chromium.android" + }, + { + "builder": "android_arm64_dbg_recipe", + "group": "tryserver.chromium.android" + }, + { + "builder": "android_n5x_swarming_dbg", + "group": "tryserver.chromium.android" + }, + { + "builder": "android_unswarmed_pixel_aosp", + "group": "tryserver.chromium.android" + }, + { + "builder": "try-nougat-phone-tester", + "group": "tryserver.chromium.android" + } + ] + } + }, "$build/reclient": { "instance": "rbe-chromium-trusted", "jobs": 500,
diff --git a/infra/config/generated/builders/ci/Marshmallow 64 bit Tester/properties.json b/infra/config/generated/builders/ci/Marshmallow 64 bit Tester/properties.json index 404674b..c769cf1d 100644 --- a/infra/config/generated/builders/ci/Marshmallow 64 bit Tester/properties.json +++ b/infra/config/generated/builders/ci/Marshmallow 64 bit Tester/properties.json
@@ -1,4 +1,96 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Marshmallow 64 bit Tester", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_wpr_tests" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Marshmallow 64 bit Tester", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "android_arm64_dbg_recipe", + "group": "tryserver.chromium.android" + }, + { + "builder": "android_n5x_swarming_dbg", + "group": "tryserver.chromium.android" + } + ] + } + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/ci/Nougat Phone Tester/properties.json b/infra/config/generated/builders/ci/Nougat Phone Tester/properties.json index 404674b..0a749ff4 100644 --- a/infra/config/generated/builders/ci/Nougat Phone Tester/properties.json +++ b/infra/config/generated/builders/ci/Nougat Phone Tester/properties.json
@@ -1,4 +1,95 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Nougat Phone Tester", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Nougat Phone Tester", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "android_arm64_dbg_recipe", + "group": "tryserver.chromium.android" + }, + { + "builder": "try-nougat-phone-tester", + "group": "tryserver.chromium.android" + } + ] + } + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/ci/Oreo Phone Tester/properties.json b/infra/config/generated/builders/ci/Oreo Phone Tester/properties.json index 1bc707e..e6630fe8 100644 --- a/infra/config/generated/builders/ci/Oreo Phone Tester/properties.json +++ b/infra/config/generated/builders/ci/Oreo Phone Tester/properties.json
@@ -1,4 +1,95 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Oreo Phone Tester", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Oreo Phone Tester", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "android-oreo-arm64-dbg", + "group": "tryserver.chromium.android" + }, + { + "builder": "android_arm64_dbg_recipe", + "group": "tryserver.chromium.android" + } + ] + } + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/ci/android-pie-arm64-dbg/properties.json b/infra/config/generated/builders/ci/android-pie-arm64-dbg/properties.json index 404674b..0a9d66a 100644 --- a/infra/config/generated/builders/ci/android-pie-arm64-dbg/properties.json +++ b/infra/config/generated/builders/ci/android-pie-arm64-dbg/properties.json
@@ -1,4 +1,95 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "android-pie-arm64-dbg", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "android-pie-arm64-dbg", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "android-pie-arm64-dbg", + "group": "tryserver.chromium.android" + }, + { + "builder": "android_arm64_dbg_recipe", + "group": "tryserver.chromium.android" + } + ] + } + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/ci/chromeos-amd64-generic-cfi-thin-lto-rel/properties.json b/infra/config/generated/builders/ci/chromeos-amd64-generic-cfi-thin-lto-rel/properties.json index a2dcb4f..b47a8e3 100644 --- a/infra/config/generated/builders/ci/chromeos-amd64-generic-cfi-thin-lto-rel/properties.json +++ b/infra/config/generated/builders/ci/chromeos-amd64-generic-cfi-thin-lto-rel/properties.json
@@ -1,4 +1,56 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "chromeos-amd64-generic-cfi-thin-lto-rel", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-chromiumos-archive", + "builder_group": "chromium.chromiumos", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Release", + "config": "chromium", + "target_arch": "intel", + "target_bits": 64, + "target_cros_boards": [ + "amd64-generic" + ], + "target_platform": "chromeos" + }, + "legacy_gclient_config": { + "apply_configs": [ + "chromeos" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "chromeos-amd64-generic-cfi-thin-lto-rel", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "chromeos-amd64-generic-cfi-thin-lto-rel", + "group": "tryserver.chromium.chromiumos" + } + ] + } + }, "$build/goma": { "enable_ats": true, "rpc_extra_params": "?prod",
diff --git a/infra/config/generated/builders/ci/fuchsia-fyi-arm64-emu-arg/properties.json b/infra/config/generated/builders/ci/fuchsia-fyi-arm64-emu-arg/properties.json index fc3bce3..274d3448 100644 --- a/infra/config/generated/builders/ci/fuchsia-fyi-arm64-emu-arg/properties.json +++ b/infra/config/generated/builders/ci/fuchsia-fyi-arm64-emu-arg/properties.json
@@ -1,4 +1,52 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "fuchsia-fyi-arm64-emu-arg", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-fuchsia-archive", + "builder_group": "chromium.fyi", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Release", + "config": "chromium", + "target_arch": "arm", + "target_bits": 64, + "target_platform": "fuchsia" + }, + "legacy_gclient_config": { + "apply_configs": [ + "fuchsia_arm64", + "fuchsia_arm64_host" + ], + "config": "chromium" + }, + "legacy_test_results_config": { + "config": "staging_server" + }, + "run_tests_serially": true + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "fuchsia-fyi-arm64-emu-arg", + "project": "chromium" + } + ] + } + }, "$build/goma": { "enable_ats": true, "rpc_extra_params": "?prod",
diff --git a/infra/config/generated/builders/ci/ios-simulator/properties.json b/infra/config/generated/builders/ci/ios-simulator/properties.json index b65703ff..4878542 100644 --- a/infra/config/generated/builders/ci/ios-simulator/properties.json +++ b/infra/config/generated/builders/ci/ios-simulator/properties.json
@@ -1,4 +1,61 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "ios-simulator", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-mac-archive", + "builder_group": "chromium.mac", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb", + "mac_toolchain" + ], + "build_config": "Debug", + "config": "chromium", + "target_bits": 64, + "target_platform": "ios" + }, + "legacy_gclient_config": { + "apply_configs": [ + "use_clang_coverage" + ], + "config": "ios" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "ios-simulator", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "ios-simulator", + "group": "tryserver.chromium.mac" + }, + { + "builder": "ios-simulator-inverse-fieldtrials-fyi", + "group": "tryserver.chromium.mac" + }, + { + "builder": "ios-simulator-rts", + "group": "tryserver.chromium.mac" + } + ] + } + }, "$build/goma": { "rpc_extra_params": "?prod", "server_host": "goma.chromium.org",
diff --git a/infra/config/generated/builders/try/android-oreo-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-oreo-arm64-dbg/properties.json index d90599c..36c1927 100644 --- a/infra/config/generated/builders/try/android-oreo-arm64-dbg/properties.json +++ b/infra/config/generated/builders/try/android-oreo-arm64-dbg/properties.json
@@ -1,4 +1,92 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Oreo Phone Tester", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + ], + "builder_ids_in_scope_for_testing": [ + { + "bucket": "ci", + "builder": "Oreo Phone Tester", + "project": "chromium" + } + ] + } + }, "$build/goma": { "enable_ats": true, "rpc_extra_params": "?prod",
diff --git a/infra/config/generated/builders/try/android-pie-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-pie-arm64-dbg/properties.json index c21b71f..f0e0dd0 100644 --- a/infra/config/generated/builders/try/android-pie-arm64-dbg/properties.json +++ b/infra/config/generated/builders/try/android-pie-arm64-dbg/properties.json
@@ -1,4 +1,92 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "android-pie-arm64-dbg", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + ], + "builder_ids_in_scope_for_testing": [ + { + "bucket": "ci", + "builder": "android-pie-arm64-dbg", + "project": "chromium" + } + ] + } + }, "$build/flakiness": { "check_for_flakiness": true },
diff --git a/infra/config/generated/builders/try/android-webview-marshmallow-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-webview-marshmallow-arm64-dbg/properties.json index d90599c..5a38c067 100644 --- a/infra/config/generated/builders/try/android-webview-marshmallow-arm64-dbg/properties.json +++ b/infra/config/generated/builders/try/android-webview-marshmallow-arm64-dbg/properties.json
@@ -1,4 +1,95 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView M (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + ], + "builder_ids_in_scope_for_testing": [ + { + "bucket": "ci", + "builder": "Android WebView M (dbg)", + "project": "chromium" + } + ] + } + }, "$build/goma": { "enable_ats": true, "rpc_extra_params": "?prod",
diff --git a/infra/config/generated/builders/try/android-webview-nougat-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-webview-nougat-arm64-dbg/properties.json index d90599c..5bbe912 100644 --- a/infra/config/generated/builders/try/android-webview-nougat-arm64-dbg/properties.json +++ b/infra/config/generated/builders/try/android-webview-nougat-arm64-dbg/properties.json
@@ -1,4 +1,95 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView N (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + ], + "builder_ids_in_scope_for_testing": [ + { + "bucket": "ci", + "builder": "Android WebView N (dbg)", + "project": "chromium" + } + ] + } + }, "$build/goma": { "enable_ats": true, "rpc_extra_params": "?prod",
diff --git a/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/properties.json index d90599c..33f04efa 100644 --- a/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/properties.json +++ b/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/properties.json
@@ -1,4 +1,95 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView O (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + ], + "builder_ids_in_scope_for_testing": [ + { + "bucket": "ci", + "builder": "Android WebView O (dbg)", + "project": "chromium" + } + ] + } + }, "$build/goma": { "enable_ats": true, "rpc_extra_params": "?prod",
diff --git a/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/properties.json index d90599c..faaf911 100644 --- a/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/properties.json +++ b/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/properties.json
@@ -1,4 +1,95 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView P (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + ], + "builder_ids_in_scope_for_testing": [ + { + "bucket": "ci", + "builder": "Android WebView P (dbg)", + "project": "chromium" + } + ] + } + }, "$build/goma": { "enable_ats": true, "rpc_extra_params": "?prod",
diff --git a/infra/config/generated/builders/try/android_arm64_dbg_recipe/properties.json b/infra/config/generated/builders/try/android_arm64_dbg_recipe/properties.json index 1128113..d8a4df5 100644 --- a/infra/config/generated/builders/try/android_arm64_dbg_recipe/properties.json +++ b/infra/config/generated/builders/try/android_arm64_dbg_recipe/properties.json
@@ -1,4 +1,386 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView M (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView N (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView O (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView P (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Marshmallow 64 bit Tester", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_wpr_tests" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Nougat Phone Tester", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Oreo Phone Tester", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "android-pie-arm64-dbg", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + ], + "builder_ids_in_scope_for_testing": [ + { + "bucket": "ci", + "builder": "Android WebView M (dbg)", + "project": "chromium" + }, + { + "bucket": "ci", + "builder": "Android WebView N (dbg)", + "project": "chromium" + }, + { + "bucket": "ci", + "builder": "Android WebView O (dbg)", + "project": "chromium" + }, + { + "bucket": "ci", + "builder": "Android WebView P (dbg)", + "project": "chromium" + }, + { + "bucket": "ci", + "builder": "Marshmallow 64 bit Tester", + "project": "chromium" + }, + { + "bucket": "ci", + "builder": "Nougat Phone Tester", + "project": "chromium" + }, + { + "bucket": "ci", + "builder": "Oreo Phone Tester", + "project": "chromium" + }, + { + "bucket": "ci", + "builder": "android-pie-arm64-dbg", + "project": "chromium" + } + ], + "is_compile_only": true + } + }, "$build/goma": { "enable_ats": true, "jobs": 300,
diff --git a/infra/config/generated/builders/try/android_n5x_swarming_dbg/properties.json b/infra/config/generated/builders/try/android_n5x_swarming_dbg/properties.json index d90599c..e07a4152 100644 --- a/infra/config/generated/builders/try/android_n5x_swarming_dbg/properties.json +++ b/infra/config/generated/builders/try/android_n5x_swarming_dbg/properties.json
@@ -1,4 +1,93 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Marshmallow 64 bit Tester", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_wpr_tests" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + ], + "builder_ids_in_scope_for_testing": [ + { + "bucket": "ci", + "builder": "Marshmallow 64 bit Tester", + "project": "chromium" + } + ] + } + }, "$build/goma": { "enable_ats": true, "rpc_extra_params": "?prod",
diff --git a/infra/config/generated/builders/try/android_unswarmed_pixel_aosp/properties.json b/infra/config/generated/builders/try/android_unswarmed_pixel_aosp/properties.json index d90599c..5bbe912 100644 --- a/infra/config/generated/builders/try/android_unswarmed_pixel_aosp/properties.json +++ b/infra/config/generated/builders/try/android_unswarmed_pixel_aosp/properties.json
@@ -1,4 +1,95 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android WebView N (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "apply_configs": [ + "remove_all_system_webviews" + ], + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + ], + "builder_ids_in_scope_for_testing": [ + { + "bucket": "ci", + "builder": "Android WebView N (dbg)", + "project": "chromium" + } + ] + } + }, "$build/goma": { "enable_ats": true, "rpc_extra_params": "?prod",
diff --git a/infra/config/generated/builders/try/chromeos-amd64-generic-cfi-thin-lto-rel/properties.json b/infra/config/generated/builders/try/chromeos-amd64-generic-cfi-thin-lto-rel/properties.json index 4aada5e..3705294 100644 --- a/infra/config/generated/builders/try/chromeos-amd64-generic-cfi-thin-lto-rel/properties.json +++ b/infra/config/generated/builders/try/chromeos-amd64-generic-cfi-thin-lto-rel/properties.json
@@ -1,4 +1,50 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "chromeos-amd64-generic-cfi-thin-lto-rel", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-chromiumos-archive", + "builder_group": "chromium.chromiumos", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Release", + "config": "chromium", + "target_arch": "intel", + "target_bits": 64, + "target_cros_boards": [ + "amd64-generic" + ], + "target_platform": "chromeos" + }, + "legacy_gclient_config": { + "apply_configs": [ + "chromeos" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "chromeos-amd64-generic-cfi-thin-lto-rel", + "project": "chromium" + } + ] + } + }, "$build/goma": { "enable_ats": true, "rpc_extra_params": "?prod",
diff --git a/infra/config/generated/builders/try/ios-simulator-inverse-fieldtrials-fyi/properties.json b/infra/config/generated/builders/try/ios-simulator-inverse-fieldtrials-fyi/properties.json index b9041d6..1ee7f91 100644 --- a/infra/config/generated/builders/try/ios-simulator-inverse-fieldtrials-fyi/properties.json +++ b/infra/config/generated/builders/try/ios-simulator-inverse-fieldtrials-fyi/properties.json
@@ -1,4 +1,47 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "ios-simulator", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-mac-archive", + "builder_group": "chromium.mac", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb", + "mac_toolchain" + ], + "build_config": "Debug", + "config": "chromium", + "target_bits": 64, + "target_platform": "ios" + }, + "legacy_gclient_config": { + "apply_configs": [ + "use_clang_coverage" + ], + "config": "ios" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "ios-simulator", + "project": "chromium" + } + ] + } + }, "$build/goma": { "rpc_extra_params": "?prod", "server_host": "goma.chromium.org",
diff --git a/infra/config/generated/builders/try/ios-simulator-rts/properties.json b/infra/config/generated/builders/try/ios-simulator-rts/properties.json index 8ddd327..dba3968 100644 --- a/infra/config/generated/builders/try/ios-simulator-rts/properties.json +++ b/infra/config/generated/builders/try/ios-simulator-rts/properties.json
@@ -1,4 +1,50 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "ios-simulator", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-mac-archive", + "builder_group": "chromium.mac", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb", + "mac_toolchain" + ], + "build_config": "Debug", + "config": "chromium", + "target_bits": 64, + "target_platform": "ios" + }, + "legacy_gclient_config": { + "apply_configs": [ + "use_clang_coverage" + ], + "config": "ios" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "ios-simulator", + "project": "chromium" + } + ], + "rts_config": { + "condition": "ALWAYS" + } + } + }, "$build/code_coverage": { "coverage_exclude_sources": "ios_test_files_and_test_utils", "coverage_test_types": [
diff --git a/infra/config/generated/builders/try/ios-simulator/properties.json b/infra/config/generated/builders/try/ios-simulator/properties.json index 8ddd327..5137f096 100644 --- a/infra/config/generated/builders/try/ios-simulator/properties.json +++ b/infra/config/generated/builders/try/ios-simulator/properties.json
@@ -1,4 +1,47 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "ios-simulator", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-mac-archive", + "builder_group": "chromium.mac", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb", + "mac_toolchain" + ], + "build_config": "Debug", + "config": "chromium", + "target_bits": 64, + "target_platform": "ios" + }, + "legacy_gclient_config": { + "apply_configs": [ + "use_clang_coverage" + ], + "config": "ios" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "ios-simulator", + "project": "chromium" + } + ] + } + }, "$build/code_coverage": { "coverage_exclude_sources": "ios_test_files_and_test_utils", "coverage_test_types": [
diff --git a/infra/config/generated/builders/try/linux-blink-web-tests-force-accessibility-rel/properties.json b/infra/config/generated/builders/try/linux-blink-web-tests-force-accessibility-rel/properties.json index 19e0479..4acc0f2 100644 --- a/infra/config/generated/builders/try/linux-blink-web-tests-force-accessibility-rel/properties.json +++ b/infra/config/generated/builders/try/linux-blink-web-tests-force-accessibility-rel/properties.json
@@ -1,4 +1,44 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "try", + "builder": "linux-blink-web-tests-force-accessibility-rel", + "project": "chromium" + }, + "builder_spec": { + "builder_group": "tryserver.chromium.linux", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Release", + "config": "chromium", + "target_bits": 64 + }, + "legacy_gclient_config": { + "config": "chromium" + }, + "legacy_test_results_config": { + "config": "staging_server" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "try", + "builder": "linux-blink-web-tests-force-accessibility-rel", + "project": "chromium" + } + ] + } + }, "$build/goma": { "enable_ats": true, "rpc_extra_params": "?prod",
diff --git a/infra/config/generated/builders/try/try-nougat-phone-tester/properties.json b/infra/config/generated/builders/try/try-nougat-phone-tester/properties.json index d90599c..c3f0a1fd 100644 --- a/infra/config/generated/builders/try/try-nougat-phone-tester/properties.json +++ b/infra/config/generated/builders/try/try-nougat-phone-tester/properties.json
@@ -1,4 +1,92 @@ { + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "Nougat Phone Tester", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.android", + "execution_mode": "TEST", + "legacy_android_config": { + "config": "main_builder_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "download_vr_test_apks" + ], + "build_config": "Debug", + "config": "android", + "target_bits": 64, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Android arm64 Builder (dbg)", + "project": "chromium" + } + ], + "builder_ids_in_scope_for_testing": [ + { + "bucket": "ci", + "builder": "Nougat Phone Tester", + "project": "chromium" + } + ] + } + }, "$build/goma": { "enable_ats": true, "rpc_extra_params": "?prod",
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 85afcb95..4b5abb7 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -67974,6 +67974,10 @@ key: "luci.recipes.use_python3" value: 100 } + experiments { + key: "remove_src_checkout_experiment" + value: 10 + } resultdb { enable: true bq_exports {
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.star b/infra/config/subprojects/chromium/ci/chromium.android.star index f748974..21b326d 100644 --- a/infra/config/subprojects/chromium/ci/chromium.android.star +++ b/infra/config/subprojects/chromium/ci/chromium.android.star
@@ -52,6 +52,31 @@ ci.thin_tester( name = "Android WebView M (dbg)", branch_selector = branches.STANDARD_MILESTONE, + builder_spec = builder_config.builder_spec( + execution_mode = builder_config.execution_mode.TEST, + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "android", + ], + ), + chromium_config = builder_config.chromium_config( + config = "android", + apply_configs = [ + "download_vr_test_apks", + ], + build_config = builder_config.build_config.DEBUG, + target_bits = 64, + target_platform = builder_config.target_platform.ANDROID, + ), + android_config = builder_config.android_config( + config = "main_builder_mb", + apply_configs = [ + "remove_all_system_webviews", + ], + ), + build_gs_bucket = "chromium-android-archive", + ), console_view_entry = consoles.console_view_entry( category = "tester|webview", short_name = "M", @@ -63,6 +88,31 @@ ci.thin_tester( name = "Android WebView N (dbg)", branch_selector = branches.STANDARD_MILESTONE, + builder_spec = builder_config.builder_spec( + execution_mode = builder_config.execution_mode.TEST, + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "android", + ], + ), + chromium_config = builder_config.chromium_config( + config = "android", + apply_configs = [ + "download_vr_test_apks", + ], + build_config = builder_config.build_config.DEBUG, + target_bits = 64, + target_platform = builder_config.target_platform.ANDROID, + ), + android_config = builder_config.android_config( + config = "main_builder_mb", + apply_configs = [ + "remove_all_system_webviews", + ], + ), + build_gs_bucket = "chromium-android-archive", + ), console_view_entry = consoles.console_view_entry( category = "tester|webview", short_name = "N", @@ -74,6 +124,31 @@ ci.thin_tester( name = "Android WebView O (dbg)", branch_selector = branches.STANDARD_MILESTONE, + builder_spec = builder_config.builder_spec( + execution_mode = builder_config.execution_mode.TEST, + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "android", + ], + ), + chromium_config = builder_config.chromium_config( + config = "android", + apply_configs = [ + "download_vr_test_apks", + ], + build_config = builder_config.build_config.DEBUG, + target_bits = 64, + target_platform = builder_config.target_platform.ANDROID, + ), + android_config = builder_config.android_config( + config = "main_builder_mb", + apply_configs = [ + "remove_all_system_webviews", + ], + ), + build_gs_bucket = "chromium-android-archive", + ), console_view_entry = consoles.console_view_entry( category = "tester|webview", short_name = "O", @@ -85,6 +160,31 @@ ci.thin_tester( name = "Android WebView P (dbg)", branch_selector = branches.STANDARD_MILESTONE, + builder_spec = builder_config.builder_spec( + execution_mode = builder_config.execution_mode.TEST, + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "android", + ], + ), + chromium_config = builder_config.chromium_config( + config = "android", + apply_configs = [ + "download_vr_test_apks", + ], + build_config = builder_config.build_config.DEBUG, + target_bits = 64, + target_platform = builder_config.target_platform.ANDROID, + ), + android_config = builder_config.android_config( + config = "main_builder_mb", + apply_configs = [ + "remove_all_system_webviews", + ], + ), + build_gs_bucket = "chromium-android-archive", + ), console_view_entry = consoles.console_view_entry( category = "tester|webview", short_name = "P", @@ -131,6 +231,28 @@ ci.builder( name = "Android arm64 Builder (dbg)", branch_selector = branches.STANDARD_MILESTONE, + builder_spec = builder_config.builder_spec( + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "android", + "enable_reclient", + ], + ), + chromium_config = builder_config.chromium_config( + config = "android", + apply_configs = [ + "download_vr_test_apks", + ], + build_config = builder_config.build_config.DEBUG, + target_bits = 64, + target_platform = builder_config.target_platform.ANDROID, + ), + android_config = builder_config.android_config( + config = "main_builder_mb", + ), + build_gs_bucket = "chromium-android-archive", + ), console_view_entry = consoles.console_view_entry( category = "builder|arm", short_name = "64", @@ -223,6 +345,29 @@ ci.thin_tester( name = "Marshmallow 64 bit Tester", branch_selector = branches.STANDARD_MILESTONE, + builder_spec = builder_config.builder_spec( + execution_mode = builder_config.execution_mode.TEST, + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "android", + "enable_wpr_tests", + ], + ), + chromium_config = builder_config.chromium_config( + config = "android", + apply_configs = [ + "download_vr_test_apks", + ], + build_config = builder_config.build_config.DEBUG, + target_bits = 64, + target_platform = builder_config.target_platform.ANDROID, + ), + android_config = builder_config.android_config( + config = "main_builder_mb", + ), + build_gs_bucket = "chromium-android-archive", + ), console_view_entry = consoles.console_view_entry( category = "tester|phone", short_name = "M", @@ -269,6 +414,28 @@ ci.thin_tester( name = "Nougat Phone Tester", branch_selector = branches.STANDARD_MILESTONE, + builder_spec = builder_config.builder_spec( + execution_mode = builder_config.execution_mode.TEST, + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "android", + ], + ), + chromium_config = builder_config.chromium_config( + config = "android", + apply_configs = [ + "download_vr_test_apks", + ], + build_config = builder_config.build_config.DEBUG, + target_bits = 64, + target_platform = builder_config.target_platform.ANDROID, + ), + android_config = builder_config.android_config( + config = "main_builder_mb", + ), + build_gs_bucket = "chromium-android-archive", + ), console_view_entry = consoles.console_view_entry( category = "tester|phone", short_name = "N", @@ -280,6 +447,28 @@ ci.thin_tester( name = "Oreo Phone Tester", branch_selector = branches.STANDARD_MILESTONE, + builder_spec = builder_config.builder_spec( + execution_mode = builder_config.execution_mode.TEST, + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "android", + ], + ), + chromium_config = builder_config.chromium_config( + config = "android", + apply_configs = [ + "download_vr_test_apks", + ], + build_config = builder_config.build_config.DEBUG, + target_bits = 64, + target_platform = builder_config.target_platform.ANDROID, + ), + android_config = builder_config.android_config( + config = "main_builder_mb", + ), + build_gs_bucket = "chromium-android-archive", + ), console_view_entry = consoles.console_view_entry( category = "tester|phone", short_name = "O", @@ -527,6 +716,28 @@ ci.thin_tester( name = "android-pie-arm64-dbg", branch_selector = branches.STANDARD_MILESTONE, + builder_spec = builder_config.builder_spec( + execution_mode = builder_config.execution_mode.TEST, + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "android", + ], + ), + chromium_config = builder_config.chromium_config( + config = "android", + apply_configs = [ + "download_vr_test_apks", + ], + build_config = builder_config.build_config.DEBUG, + target_bits = 64, + target_platform = builder_config.target_platform.ANDROID, + ), + android_config = builder_config.android_config( + config = "main_builder_mb", + ), + build_gs_bucket = "chromium-android-archive", + ), console_view_entry = consoles.console_view_entry( category = "tester|phone", short_name = "P",
diff --git a/infra/config/subprojects/chromium/ci/chromium.chromiumos.star b/infra/config/subprojects/chromium/ci/chromium.chromiumos.star index 25ec2944..5fbf6173 100644 --- a/infra/config/subprojects/chromium/ci/chromium.chromiumos.star +++ b/infra/config/subprojects/chromium/ci/chromium.chromiumos.star
@@ -183,6 +183,28 @@ ci.builder( name = "chromeos-amd64-generic-cfi-thin-lto-rel", + builder_spec = builder_config.builder_spec( + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "chromeos", + ], + ), + chromium_config = builder_config.chromium_config( + config = "chromium", + apply_configs = [ + "mb", + ], + build_config = builder_config.build_config.RELEASE, + target_arch = builder_config.target_arch.INTEL, + target_bits = 64, + target_cros_boards = [ + "amd64-generic", + ], + target_platform = builder_config.target_platform.CHROMEOS, + ), + build_gs_bucket = "chromium-chromiumos-archive", + ), console_view_entry = consoles.console_view_entry( category = "simple|release|x64", short_name = "cfi",
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star index 59c8879..cd0c02a2 100644 --- a/infra/config/subprojects/chromium/ci/chromium.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -190,6 +190,30 @@ ci.builder( name = "fuchsia-fyi-arm64-emu-arg", + builder_spec = builder_config.builder_spec( + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "fuchsia_arm64", + "fuchsia_arm64_host", + ], + ), + chromium_config = builder_config.chromium_config( + config = "chromium", + apply_configs = [ + "mb", + ], + build_config = builder_config.build_config.RELEASE, + target_arch = builder_config.target_arch.ARM, + target_bits = 64, + target_platform = builder_config.target_platform.FUCHSIA, + ), + test_results_config = builder_config.test_results_config( + config = "staging_server", + ), + build_gs_bucket = "chromium-fuchsia-archive", + run_tests_serially = True, + ), console_view_entry = [ consoles.console_view_entry( category = "fuchsia|a64",
diff --git a/infra/config/subprojects/chromium/ci/chromium.mac.star b/infra/config/subprojects/chromium/ci/chromium.mac.star index cc45506..10e38d3 100644 --- a/infra/config/subprojects/chromium/ci/chromium.mac.star +++ b/infra/config/subprojects/chromium/ci/chromium.mac.star
@@ -346,6 +346,25 @@ ios_builder( name = "ios-simulator", branch_selector = branches.STANDARD_MILESTONE, + builder_spec = builder_config.builder_spec( + gclient_config = builder_config.gclient_config( + config = "ios", + apply_configs = [ + "use_clang_coverage", + ], + ), + chromium_config = builder_config.chromium_config( + config = "chromium", + apply_configs = [ + "mb", + "mac_toolchain", + ], + build_config = builder_config.build_config.DEBUG, + target_bits = 64, + target_platform = builder_config.target_platform.IOS, + ), + build_gs_bucket = "chromium-mac-archive", + ), console_view_entry = [ consoles.console_view_entry( category = "ios|default",
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star index 880f3fd4..6cf4077 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
@@ -263,6 +263,10 @@ try_.builder( name = "android-oreo-arm64-dbg", branch_selector = branches.STANDARD_MILESTONE, + mirrors = [ + "ci/Android arm64 Builder (dbg)", + "ci/Oreo Phone Tester", + ], ) try_.builder( @@ -287,6 +291,10 @@ ".+/[+]/third_party/arcore-android-sdk-client/.+", ], ), + mirrors = [ + "ci/Android arm64 Builder (dbg)", + "ci/android-pie-arm64-dbg", + ], ) # TODO(crbug/1182468) Remove when experiment is done. @@ -383,18 +391,34 @@ try_.builder( name = "android-webview-marshmallow-arm64-dbg", + mirrors = [ + "ci/Android arm64 Builder (dbg)", + "ci/Android WebView M (dbg)", + ], ) try_.builder( name = "android-webview-nougat-arm64-dbg", + mirrors = [ + "ci/Android arm64 Builder (dbg)", + "ci/Android WebView N (dbg)", + ], ) try_.builder( name = "android-webview-oreo-arm64-dbg", + mirrors = [ + "ci/Android arm64 Builder (dbg)", + "ci/Android WebView O (dbg)", + ], ) try_.builder( name = "android-webview-pie-arm64-dbg", + mirrors = [ + "ci/Android arm64 Builder (dbg)", + "ci/Android WebView P (dbg)", + ], ) try_.builder( @@ -408,6 +432,13 @@ try_.builder( name = "android_arm64_dbg_recipe", goma_jobs = goma.jobs.J300, + mirrors = [ + "ci/Android arm64 Builder (dbg)", + ], + try_settings = builder_config.try_settings( + include_all_triggered_testers = True, + is_compile_only = True, + ), ) try_.builder( @@ -487,10 +518,18 @@ try_.builder( name = "android_n5x_swarming_dbg", + mirrors = [ + "ci/Android arm64 Builder (dbg)", + "ci/Marshmallow 64 bit Tester", + ], ) try_.builder( name = "android_unswarmed_pixel_aosp", + mirrors = [ + "ci/Android arm64 Builder (dbg)", + "ci/Android WebView N (dbg)", + ], ) try_.builder( @@ -508,6 +547,10 @@ try_.builder( name = "try-nougat-phone-tester", branch_selector = branches.STANDARD_MILESTONE, + mirrors = [ + "ci/Android arm64 Builder (dbg)", + "ci/Nougat Phone Tester", + ], ) try_.gpu.optional_tests_builder(
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.chromiumos.star b/infra/config/subprojects/chromium/try/tryserver.chromium.chromiumos.star index 3f3938d5..106bfd8 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.chromiumos.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.chromiumos.star
@@ -30,6 +30,9 @@ try_.builder( name = "chromeos-amd64-generic-cfi-thin-lto-rel", + mirrors = [ + "ci/chromeos-amd64-generic-cfi-thin-lto-rel", + ], ) try_.builder(
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star index be7291a..d155e808 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
@@ -209,6 +209,22 @@ try_.builder( name = "linux-blink-web-tests-force-accessibility-rel", + builder_spec = builder_config.builder_spec( + gclient_config = builder_config.gclient_config( + config = "chromium", + ), + chromium_config = builder_config.chromium_config( + config = "chromium", + apply_configs = [ + "mb", + ], + build_config = builder_config.build_config.RELEASE, + target_bits = 64, + ), + test_results_config = builder_config.test_results_config( + config = "staging_server", + ), + ), ) try_.builder( @@ -318,6 +334,9 @@ use_clang_coverage = True, coverage_test_types = ["unit", "overall"], tryjob = try_.job(), + experiments = { + "remove_src_checkout_experiment": 10, + }, ) try_.compilator_builder(
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star index fe03d74..cc2dfa3 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star
@@ -268,6 +268,9 @@ ios_builder( name = "ios-simulator", branch_selector = branches.STANDARD_MILESTONE, + mirrors = [ + "ci/ios-simulator", + ], check_for_flakiness = True, main_list_view = "try", use_clang_coverage = True, @@ -310,6 +313,7 @@ ios_builder( name = "ios-simulator-inverse-fieldtrials-fyi", + mirrors = builder_config.copy_from("try/ios-simulator"), ) ios_builder( @@ -382,6 +386,12 @@ ios_builder( name = "ios-simulator-rts", + mirrors = builder_config.copy_from("try/ios-simulator"), + try_settings = builder_config.try_settings( + rts_config = builder_config.rts_config( + condition = builder_config.rts_condition.ALWAYS, + ), + ), builderless = False, check_for_flakiness = True, use_clang_coverage = True,
diff --git a/ios/chrome/browser/flags/BUILD.gn b/ios/chrome/browser/flags/BUILD.gn index d04b659..dc0a3b5 100644 --- a/ios/chrome/browser/flags/BUILD.gn +++ b/ios/chrome/browser/flags/BUILD.gn
@@ -66,6 +66,7 @@ "//ios/chrome/browser/ui/first_run:field_trial", "//ios/chrome/browser/ui/fullscreen:feature_flags", "//ios/chrome/browser/ui/ntp:feature_flags", + "//ios/chrome/browser/ui/omnibox:features", "//ios/chrome/browser/ui/overlays/infobar_banner:feature_flags", "//ios/chrome/browser/ui/popup_menu/overflow_menu:feature_flags", "//ios/chrome/browser/ui/start_surface:feature_flags",
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index 51f5e95..5b8cfcb 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -76,6 +76,7 @@ #include "ios/chrome/browser/ui/first_run/fre_field_trial.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_feature.h" +#import "ios/chrome/browser/ui/omnibox/omnibox_ui_features.h" #import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_features.h" #import "ios/chrome/browser/ui/popup_menu/overflow_menu/feature_flags.h" #import "ios/chrome/browser/ui/start_surface/start_surface_features.h" @@ -881,6 +882,10 @@ flag_descriptions::kSyncInvalidationsWalletAndOfferDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(::syncer::kUseSyncInvalidationsForWalletAndOffer)}, + {"suggestions-scrolling-ipad", + flag_descriptions::kEnableSuggestionsScrollingOnIPadName, + flag_descriptions::kEnableSuggestionsScrollingOnIPadDescription, + flags_ui::kOsIos, FEATURE_VALUE_TYPE(kEnableSuggestionsScrollingOnIPad)}, }; bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index 8ea6b50..6060922 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -242,6 +242,12 @@ "When enabled, the instructions to turn on Password AutoFill will have " "shorter steps and come with a button that links the user to iOS Settings."; +const char kEnableSuggestionsScrollingOnIPadName[] = + "Enable omnibox suggestions scrolling on iPad"; +const char kEnableSuggestionsScrollingOnIPadDescription[] = + "Enable omnibox suggestions scrolling on iPad and disable suggestions " + "hiding on keyboard dismissal."; + const char kEnableWebChannelsName[] = "Enable WebFeed"; const char kEnableWebChannelsDescription[] = "Enable folowing content from web and display Following feed on NTP based "
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index 37607bd2..f2017ab7 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -214,6 +214,11 @@ extern const char kEnableShortenedPasswordAutoFillInstructionName[]; extern const char kEnableShortenedPasswordAutoFillInstructionDescription[]; +// Title and description for the flag to enable omnibox suggestions scrolling on +// iPad. +extern const char kEnableSuggestionsScrollingOnIPadName[]; +extern const char kEnableSuggestionsScrollingOnIPadDescription[]; + // Title and description for the flag to introduce following web channels on // Chrome iOS. extern const char kEnableWebChannelsName[];
diff --git a/ios/chrome/browser/optimization_guide/BUILD.gn b/ios/chrome/browser/optimization_guide/BUILD.gn index 7155359..1d6d5eb 100644 --- a/ios/chrome/browser/optimization_guide/BUILD.gn +++ b/ios/chrome/browser/optimization_guide/BUILD.gn
@@ -20,6 +20,7 @@ ] deps = [ "//base", + "//components/component_updater", "//components/download/public/background_service:public", "//components/keyed_service/core", "//components/keyed_service/ios", @@ -27,6 +28,7 @@ "//components/optimization_guide/core", "//components/optimization_guide/core:prediction", "//components/optimization_guide/proto:optimization_guide_proto", + "//components/prefs", "//ios/chrome/browser:application_context", "//ios/chrome/browser:chrome_paths", "//ios/chrome/browser/browser_state", @@ -67,6 +69,7 @@ ":optimization_guide", ":resources_unit_tests", "//base/test:test_support", + "//components/component_updater", "//components/download/internal/background_service/ios:background_service", "//components/optimization_guide/core", "//components/optimization_guide/core:test_support", @@ -77,11 +80,13 @@ "//components/unified_consent", "//components/variations", "//components/variations:test_support", + "//ios/chrome/browser:application_context", "//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/main:public", "//ios/chrome/browser/main:test_support", "//ios/chrome/browser/prefs:browser_prefs", "//ios/chrome/browser/web_state_list", + "//ios/chrome/test:test_support", "//ios/web/public/test", "//ios/web/public/test/fakes", "//net:test_support",
diff --git a/ios/chrome/browser/optimization_guide/optimization_guide_service.mm b/ios/chrome/browser/optimization_guide/optimization_guide_service.mm index ec0c329..8309bb5 100644 --- a/ios/chrome/browser/optimization_guide/optimization_guide_service.mm +++ b/ios/chrome/browser/optimization_guide/optimization_guide_service.mm
@@ -9,6 +9,7 @@ #include "base/path_service.h" #import "base/task/thread_pool.h" #import "base/time/default_clock.h" +#import "components/component_updater/pref_names.h" #import "components/optimization_guide/core/command_line_top_host_provider.h" #import "components/optimization_guide/core/hints_processing_util.h" #import "components/optimization_guide/core/optimization_guide_constants.h" @@ -21,6 +22,7 @@ #import "components/optimization_guide/core/optimization_guide_util.h" #include "components/optimization_guide/core/prediction_manager.h" #import "components/optimization_guide/core/top_host_provider.h" +#import "components/prefs/pref_service.h" #import "ios/chrome/browser/application_context.h" #import "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/chrome_paths.h" @@ -50,8 +52,12 @@ : pref_service_(pref_service), off_the_record_(off_the_record) { DCHECK(optimization_guide::features::IsOptimizationHintsEnabled()); - DCHECK(!off_the_record_ || - (hint_store && prediction_model_and_features_store)); + // In off the record profile, the stores of normal profile should be + // passed to the constructor. In normal profile, they will be created. + DCHECK(!off_the_record_ || hint_store); + DCHECK( + !off_the_record_ || prediction_model_and_features_store || + !optimization_guide::features::IsOptimizationTargetPredictionEnabled()); if (!off_the_record_) { // Only create a top host provider from the command line if provided. top_host_provider_ = @@ -98,7 +104,11 @@ prediction_model_and_features_store, url_loader_factory, pref_service, off_the_record_, application_locale, models_dir, optimization_guide_logger_.get(), - std::move(background_download_service_provider)); + std::move(background_download_service_provider), + base::BindRepeating([]() { + return GetApplicationContext()->GetLocalState()->GetBoolean( + ::prefs::kComponentUpdatesEnabled); + })); } }
diff --git a/ios/chrome/browser/optimization_guide/prediction_manager_browsertest.mm b/ios/chrome/browser/optimization_guide/prediction_manager_browsertest.mm index e78f4c4..6045029 100644 --- a/ios/chrome/browser/optimization_guide/prediction_manager_browsertest.mm +++ b/ios/chrome/browser/optimization_guide/prediction_manager_browsertest.mm
@@ -5,6 +5,7 @@ #import "base/test/metrics/histogram_tester.h" #include "base/test/scoped_command_line.h" #import "base/test/scoped_feature_list.h" +#include "components/component_updater/pref_names.h" #include "components/download/internal/background_service/ios/background_download_task_helper.h" #include "components/optimization_guide/core/optimization_guide_constants.h" #include "components/optimization_guide/core/optimization_guide_enums.h" @@ -16,11 +17,13 @@ #import "components/sync_preferences/testing_pref_service_syncable.h" #include "components/variations/hashing.h" #include "components/variations/scoped_variations_ids_provider.h" +#include "ios/chrome/browser/application_context.h" #import "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/optimization_guide/optimization_guide_service.h" #include "ios/chrome/browser/optimization_guide/optimization_guide_service_factory.h" #include "ios/chrome/browser/optimization_guide/optimization_guide_test_utils.h" #import "ios/chrome/browser/prefs/browser_prefs.h" +#import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h" #include "ios/web/public/test/web_task_environment.h" #include "net/base/mock_network_change_notifier.h" #include "net/test/embedded_test_server/default_handlers.h" @@ -174,6 +177,11 @@ expected_field_trial_name_hashes_ = expected_field_trial_name_hashes; } + void SetComponentUpdatesEnabled(bool enabled) { + GetApplicationContext()->GetLocalState()->SetBoolean( + ::prefs::kComponentUpdatesEnabled, enabled); + } + protected: virtual void InitializeFeatureList() = 0; @@ -270,6 +278,7 @@ base::test::ScopedFeatureList scoped_feature_list_; web::WebTaskEnvironment task_environment_{ web::WebTaskEnvironment::IO_MAINLOOP}; + IOSChromeScopedTestingLocalState local_state_; base::HistogramTester histogram_tester_; std::unique_ptr<TestChromeBrowserState> browser_state_; std::unique_ptr<net::test::MockNetworkChangeNotifier> @@ -297,11 +306,10 @@ } }; -TEST_F(PredictionManagerTest, RemoteFetchingPrefDisabled) { +TEST_F(PredictionManagerTest, ComponentUpdatesEnabledPrefDisabled) { ModelFileObserver model_file_observer; SetResponseType(PredictionModelsFetcherRemoteResponseType::kUnsuccessful); - browser_state_->GetPrefs()->SetBoolean( - optimization_guide::prefs::kOptimizationGuideFetchingEnabled, false); + SetComponentUpdatesEnabled(false); base::HistogramTester histogram_tester; RegisterWithKeyedService(&model_file_observer); task_environment_.RunUntilIdle();
diff --git a/ios/chrome/browser/policy/BUILD.gn b/ios/chrome/browser/policy/BUILD.gn index 2affdb3d..b2594aa 100644 --- a/ios/chrome/browser/policy/BUILD.gn +++ b/ios/chrome/browser/policy/BUILD.gn
@@ -67,7 +67,6 @@ "//components/history/core/common", "//components/keyed_service/ios", "//components/metrics", - "//components/optimization_guide/core", "//components/password_manager/core/common", "//components/policy:generated", "//components/policy/core/common",
diff --git a/ios/chrome/browser/policy/configuration_policy_handler_list_factory.mm b/ios/chrome/browser/policy/configuration_policy_handler_list_factory.mm index f269543ce..5d05ce9 100644 --- a/ios/chrome/browser/policy/configuration_policy_handler_list_factory.mm +++ b/ios/chrome/browser/policy/configuration_policy_handler_list_factory.mm
@@ -17,7 +17,6 @@ #include "components/enterprise/browser/reporting/common_pref_names.h" #include "components/history/core/common/pref_names.h" #include "components/metrics/metrics_pref_names.h" -#include "components/optimization_guide/core/optimization_guide_prefs.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/policy/core/browser/configuration_policy_handler.h" #include "components/policy/core/browser/configuration_policy_handler_list.h" @@ -83,9 +82,6 @@ { policy::key::kMetricsReportingEnabled, metrics::prefs::kMetricsReportingEnabled, base::Value::Type::BOOLEAN }, - { policy::key::kOptimizationGuideFetchingEnabled, - optimization_guide::prefs::kOptimizationGuideFetchingEnabled, - base::Value::Type::BOOLEAN }, { policy::key::kPolicyRefreshRate, policy::policy_prefs::kUserPolicyRefreshRate, base::Value::Type::INTEGER },
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm index 47b7a1f..c6f2301 100644 --- a/ios/chrome/browser/prefs/browser_prefs.mm +++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -136,14 +136,16 @@ // Deprecated 03/2022 const char kShowReadingListInBookmarkBar[] = "bookmark_bar.show_reading_list"; -// Depreated 04/2022 -const char kFRETrialGroupPrefName[] = "fre_refactoring.trial_group"; -} - // Deprecated 03/2022 const char kPrefReadingListMessagesNeverShow[] = "reading_list_message_never_show"; +// Deprecated 04/2022 +const char kFRETrialGroupPrefName[] = "fre_refactoring.trial_group"; +const char kOptimizationGuideRemoteFetchingEnabled[] = + "optimization_guide.fetching_enabled"; +} // namespace + void RegisterLocalStatePrefs(PrefRegistrySimple* registry) { BrowserStateInfoCache::RegisterPrefs(registry); flags_ui::PrefServiceFlagsStorage::RegisterPrefs(registry); @@ -325,6 +327,8 @@ registry->RegisterBooleanPref(kSigninAllowedByPolicy, true); registry->RegisterBooleanPref(kShowReadingListInBookmarkBar, true); + + registry->RegisterBooleanPref(kOptimizationGuideRemoteFetchingEnabled, true); } // This method should be periodically pruned of year+ old migrations. @@ -401,4 +405,7 @@ if (prefs->FindPreference(kPrefReadingListMessagesNeverShow)) { prefs->ClearPref(kPrefReadingListMessagesNeverShow); } + + // Added 4/2022. + prefs->ClearPref(kOptimizationGuideRemoteFetchingEnabled); }
diff --git a/ios/chrome/browser/ui/omnibox/BUILD.gn b/ios/chrome/browser/ui/omnibox/BUILD.gn index fde9db6..a7ea59c 100644 --- a/ios/chrome/browser/ui/omnibox/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/BUILD.gn
@@ -295,3 +295,12 @@ outputs = [ "{{bundle_resources_dir}}/" + "ios/chrome/test/data/omnibox/{{source_file_part}}" ] } + +source_set("features") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "omnibox_ui_features.cc", + "omnibox_ui_features.h", + ] + public_deps = [ "//base" ] +}
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_ui_features.cc b/ios/chrome/browser/ui/omnibox/omnibox_ui_features.cc new file mode 100644 index 0000000..a469ab5 --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/omnibox_ui_features.cc
@@ -0,0 +1,8 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/ui/omnibox/omnibox_ui_features.h" + +const base::Feature kEnableSuggestionsScrollingOnIPad{ + "EnableSuggestionsScrollingOnIPad", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_ui_features.h b/ios/chrome/browser/ui/omnibox/omnibox_ui_features.h new file mode 100644 index 0000000..143cdc7e --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/omnibox_ui_features.h
@@ -0,0 +1,14 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_UI_FEATURES_H_ +#define IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_UI_FEATURES_H_ + +#include "base/feature_list.h" + +// Feature flag to enable omnibox suggestions scrolling on iPad. This will also +// disable suggestions hiding on keyboard dismissal. +extern const base::Feature kEnableSuggestionsScrollingOnIPad; + +#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_UI_FEATURES_H_
diff --git a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn index 6591cb79..83244ff 100644 --- a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
@@ -135,13 +135,13 @@ deps = [ ":popup_accessibility_identifier_constants", ":popup_ui_protocols", + "resources:background_color_swiftui_ios14", "resources:grouped_primary_background_color_swiftui_ios14", "resources:omnibox_popup_tab_match", "resources:omnibox_suggestion_answer_icon_color", "resources:omnibox_suggestion_answer_icon_dark_color", "resources:omnibox_suggestion_icon_color", "resources:omnibox_suggestion_icon_dark_color", - "resources:primary_background_color_swiftui_ios14", "//base", "//components/omnibox/common", "//ios/chrome/app/strings:ios_strings_grit",
diff --git a/ios/chrome/browser/ui/omnibox/popup/popup_swift_bridge.h b/ios/chrome/browser/ui/omnibox/popup/popup_swift_bridge.h index 2a20577..78e4c8f9 100644 --- a/ios/chrome/browser/ui/omnibox/popup/popup_swift_bridge.h +++ b/ios/chrome/browser/ui/omnibox/popup/popup_swift_bridge.h
@@ -13,6 +13,7 @@ #import "ios/chrome/browser/ui/omnibox/popup/omnibox_icon.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_pedal.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_accessibility_identifier_constants.h" +#import "ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h" #import "ios/chrome/browser/ui/util/named_guide.h" #import "ios/chrome/common/ui/colors/swift_bridge.h" #include "ios/chrome/grit/ios_strings.h"
diff --git a/ios/chrome/browser/ui/omnibox/popup/resources/BUILD.gn b/ios/chrome/browser/ui/omnibox/popup/resources/BUILD.gn index f704e4d..08f18d87 100644 --- a/ios/chrome/browser/ui/omnibox/popup/resources/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/popup/resources/BUILD.gn
@@ -4,16 +4,16 @@ import("//build/config/ios/asset_catalog.gni") +colorset("background_color_swiftui_ios14") { + sources = [ "background_color_swiftui_ios14.colorset/Contents.json" ] +} + colorset("grouped_primary_background_color_swiftui_ios14") { sources = [ "grouped_primary_background_color_swiftui_ios14.colorset/Contents.json", ] } -colorset("primary_background_color_swiftui_ios14") { - sources = [ "primary_background_color_swiftui_ios14.colorset/Contents.json" ] -} - colorset("omnibox_suggestion_answer_icon_color") { sources = [ "omnibox_suggestion_answer_icon_color.colorset/Contents.json" ] }
diff --git a/ios/chrome/browser/ui/omnibox/popup/resources/primary_background_color_swiftui_ios14.colorset/Contents.json b/ios/chrome/browser/ui/omnibox/popup/resources/background_color_swiftui_ios14.colorset/Contents.json similarity index 86% rename from ios/chrome/browser/ui/omnibox/popup/resources/primary_background_color_swiftui_ios14.colorset/Contents.json rename to ios/chrome/browser/ui/omnibox/popup/resources/background_color_swiftui_ios14.colorset/Contents.json index 01ae198f..73eff6e7 100644 --- a/ios/chrome/browser/ui/omnibox/popup/resources/primary_background_color_swiftui_ios14.colorset/Contents.json +++ b/ios/chrome/browser/ui/omnibox/popup/resources/background_color_swiftui_ios14.colorset/Contents.json
@@ -28,9 +28,9 @@ "color-space": "display-p3", "components": { "alpha": "1.000", - "red": "0x20", - "green": "0x21", - "blue": "0x24" + "red": "0x35", + "green": "0x37", + "blue": "0x39" } } }, @@ -50,9 +50,9 @@ "color-space": "display-p3", "components": { "alpha": "1.000", - "red": "0x20", - "green": "0x21", - "blue": "0x24" + "red": "0x35", + "green": "0x37", + "blue": "0x39" } } }
diff --git a/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_row_view.swift b/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_row_view.swift index f0c37d0..9cd029997 100644 --- a/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_row_view.swift +++ b/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_row_view.swift
@@ -19,15 +19,15 @@ static let actionButtonOuterPadding = EdgeInsets(top: 2, leading: 0, bottom: 2, trailing: 0) static let leadingSpacing: CGFloat = 60 static let minHeight: CGFloat = 58 - static let maxHeight: CGFloat = 98 + static let maxHeight: CGFloat = 320 static let padding = EdgeInsets(top: 9, leading: 0, bottom: 9, trailing: 16) } - @Environment(\.colorScheme) var colorScheme: ColorScheme @Environment(\.popupUIVariation) var uiVariation: PopupUIVariation let match: PopupMatch let isHighlighted: Bool + let toolbarConfiguration: ToolbarConfiguration let selectionHandler: () -> Void let trailingButtonHandler: () -> Void @@ -68,7 +68,7 @@ /// Enable this to tell the row it should display its own custom separator at the bottom. let shouldDisplayCustomSeparator: Bool var customSeparatorColor: Color { - (colorScheme == .dark) ? .cr_grey700 : .cr_grey200 + uiVariation == .one ? .cr_separator : .cr_grey700 } @ViewBuilder var customSeparator: some View { @@ -147,11 +147,16 @@ } .padding(Dimensions.padding) } - .frame(maxWidth: .infinity, minHeight: Dimensions.minHeight) + .frame(maxWidth: .infinity, minHeight: Dimensions.minHeight, maxHeight: Dimensions.maxHeight) } var backgroundColor: Color { - (uiVariation == .one) ? .cr_primaryBackground : .cr_groupedSecondaryBackground + switch uiVariation { + case .one: + return Color(toolbarConfiguration.backgroundColor) + case .two: + return .cr_groupedSecondaryBackground + } } var foregroundColorPrimary: Color {
diff --git a/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift b/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift index b2f1e45..c02e4fca 100644 --- a/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift +++ b/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift
@@ -154,10 +154,15 @@ matchIndex, match in let indexPath = IndexPath(row: matchIndex, section: sectionIndex) let highlighted = indexPath == model.highlightedMatchIndexPath + // UI Variation 1 always has separators. Variation 2 doesn't have + // one on the last row in a section. + let shouldDisplayCustomSeparator = + !highlighted && (matchIndex < section.matches.count - 1 || popupUIVariation == .one) PopupMatchRowView( match: match, isHighlighted: highlighted, + toolbarConfiguration: toolbarConfiguration, selectionHandler: { model.delegate?.autocompleteResultConsumer( model, didSelectRow: UInt(matchIndex), inSection: UInt(sectionIndex)) @@ -167,7 +172,7 @@ model, didTapTrailingButtonForRow: UInt(matchIndex), inSection: UInt(sectionIndex)) }, - shouldDisplayCustomSeparator: (!highlighted && matchIndex < section.matches.count - 1) + shouldDisplayCustomSeparator: shouldDisplayCustomSeparator ) .id(indexPath) .deleteDisabled(!match.supportsDeletion) @@ -255,9 +260,8 @@ if popupUIVariation == .one { if index == 0 { // Additional space between omnibox and top section. - let firstSectionHeader = - Color.cr_primaryBackground.frame( - width: geometry.size.width, height: -Dimensions.VariationOne.hiddenTopContentInset) + let firstSectionHeader = Color(toolbarConfiguration.backgroundColor).frame( + width: geometry.size.width, height: -Dimensions.VariationOne.hiddenTopContentInset) if #available(iOS 15.0, *) { // Additional padding is added on iOS 15, which needs to be cancelled here. firstSectionHeader.padding([.top, .bottom], -6) @@ -272,7 +276,7 @@ separatorColor .frame(width: geometry.size.width, height: 0.5) .padding(Dimensions.VariationOne.pedalSectionSeparatorPadding) - .background(Color.cr_primaryBackground) + .background(Color(toolbarConfiguration.backgroundColor)) if #available(iOS 15.0, *) { pedalSectionSeparator.padding([.top, .bottom], -6) @@ -319,17 +323,30 @@ // mode color. This bug is fixed in iOS 15, but until then, a workaround // color with the dark mode + high contrast color specified is used. if #available(iOS 15, *) { - backgroundColor = - (popupUIVariation == .one) ? Color.cr_primaryBackground : Color.cr_groupedPrimaryBackground + switch popupUIVariation { + case .one: + backgroundColor = Color(toolbarConfiguration.backgroundColor) + case .two: + backgroundColor = .cr_groupedPrimaryBackground + } } else { - backgroundColor = - (popupUIVariation == .one) - ? Color("primary_background_color_swiftui_ios14") - : Color("grouped_primary_background_color_swiftui_ios14") + switch popupUIVariation { + case .one: + backgroundColor = Color("background_color_swiftui_ios14") + case .two: + backgroundColor = Color("grouped_primary_background_color_swiftui_ios14") + } } return backgroundColor.edgesIgnoringSafeArea(.all) } + /// The toolbar configuration for the current popup view. + /// ToolbarConfiguration's background color doesn't actually depend on + /// the style any more, as normal vs. incognito is handled via colorsets. + var toolbarConfiguration: ToolbarConfiguration { + ToolbarConfiguration(style: .NORMAL) + } + func onAppear() { if let appearanceContainerType = self.appearanceContainerType { let listAppearance = UITableView.appearance(whenContainedInInstancesOf: [
diff --git a/ios/chrome/browser/ui/popup_menu/BUILD.gn b/ios/chrome/browser/ui/popup_menu/BUILD.gn index e83db72..e106ae3 100644 --- a/ios/chrome/browser/ui/popup_menu/BUILD.gn +++ b/ios/chrome/browser/ui/popup_menu/BUILD.gn
@@ -22,6 +22,7 @@ "resources:popup_menu_edit_bookmark", "resources:popup_menu_enterprise_icon", "resources:popup_menu_find_in_page", + "resources:popup_menu_follow", "resources:popup_menu_help", "resources:popup_menu_history", "resources:popup_menu_new_incognito_tab",
diff --git a/ios/chrome/browser/ui/popup_menu/cells/BUILD.gn b/ios/chrome/browser/ui/popup_menu/cells/BUILD.gn index 7996667..37d3aa9 100644 --- a/ios/chrome/browser/ui/popup_menu/cells/BUILD.gn +++ b/ios/chrome/browser/ui/popup_menu/cells/BUILD.gn
@@ -14,6 +14,7 @@ ] deps = [ "//base", + "//ios/chrome/browser/ntp:features", "//ios/chrome/browser/ui/favicon/resources:default_favicon", "//ios/chrome/browser/ui/popup_menu/public:ui_constants", "//ios/chrome/browser/ui/popup_menu/public/cells",
diff --git a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.mm b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.mm index b0230803..4b0c1d4b 100644 --- a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.mm +++ b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.mm
@@ -6,6 +6,7 @@ #include <stdlib.h> +#import "ios/chrome/browser/ntp/features.h" #import "ios/chrome/browser/ui/popup_menu/public/popup_menu_ui_constants.h" #import "ios/chrome/browser/ui/reading_list/number_badge_view.h" #import "ios/chrome/browser/ui/reading_list/text_badge_view.h" @@ -109,7 +110,11 @@ self.selectedBackgroundView = selectedBackgroundView; _titleLabel = [[UILabel alloc] init]; - _titleLabel.numberOfLines = 0; + if (IsWebChannelsEnabled()) { + _titleLabel.numberOfLines = 2; + } else { + _titleLabel.numberOfLines = 0; + } _titleLabel.font = [self titleFont]; [_titleLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm index 1342453..21d7239 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm
@@ -131,6 +131,9 @@ WindowActivityToolsOrigin, GURL(kChromeUINewTabURL))]; break; + case PopupMenuActionFollow: + // TODO(crbug.com/1264872): add action. + break; case PopupMenuActionBookmarks: RecordAction(UserMetricsAction("MobileMenuAllBookmarks")); LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeAllTabs);
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_constants.h b/ios/chrome/browser/ui/popup_menu/popup_menu_constants.h index 9ef56799..7470d3d 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_constants.h +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_constants.h
@@ -32,6 +32,8 @@ extern NSString* const kToolsMenuCloseAllIncognitoTabsId; // Close the current tab item accessibility Identifier. extern NSString* const kToolsMenuCloseTabId; +// Follow item accessibility Identifier. +extern NSString* const kToolsMenuFollowId; // Bookmarks item accessibility Identifier. extern NSString* const kToolsMenuBookmarksId; // Reading List item accessibility Identifier.
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_constants.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_constants.mm index d1bcae7..0fb1c8b 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_constants.mm +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_constants.mm
@@ -27,6 +27,7 @@ NSString* const kToolsMenuCloseAllIncognitoTabsId = @"kToolsMenuCloseAllIncognitoTabsId"; NSString* const kToolsMenuCloseTabId = @"kToolsMenuCloseTabId"; +NSString* const kToolsMenuFollowId = @"kToolsMenuFollowId"; NSString* const kToolsMenuBookmarksId = @"kToolsMenuBookmarksId"; NSString* const kToolsMenuReadingListId = @"kToolsMenuReadingListId"; NSString* const kToolsMenuOtherDevicesId = @"kToolsMenuOtherDevicesId";
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm index 54738a3..a512ef30 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
@@ -27,6 +27,7 @@ #import "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/chrome_url_constants.h" #import "ios/chrome/browser/find_in_page/find_tab_helper.h" +#import "ios/chrome/browser/ntp/features.h" #import "ios/chrome/browser/overlays/public/overlay_presenter.h" #import "ios/chrome/browser/overlays/public/overlay_presenter_observer_bridge.h" #import "ios/chrome/browser/overlays/public/overlay_request.h" @@ -99,6 +100,24 @@ return item; } +PopupMenuToolsItem* CreateFollowItem(int titleID, + PopupMenuAction action, + NSString* imageName, + NSString* accessibilityID) { + DCHECK(IsWebChannelsEnabled()); + PopupMenuToolsItem* item = + [[PopupMenuToolsItem alloc] initWithType:kItemTypeEnumZero]; + item.title = l10n_util::GetNSStringF(titleID, base::SysNSStringToUTF16(@"")); + item.enabled = NO; + item.actionIdentifier = action; + item.accessibilityIdentifier = accessibilityID; + if (imageName) { + item.image = [[UIImage imageNamed:imageName] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + } + return item; +} + PopupMenuTextItem* CreateEnterpriseInfoItem(NSString* imageName, NSString* message, PopupMenuAction action, @@ -169,6 +188,7 @@ @property(nonatomic, strong) PopupMenuToolsItem* openNewIncognitoTabItem; @property(nonatomic, strong) PopupMenuToolsItem* reloadStopItem; +@property(nonatomic, strong) PopupMenuToolsItem* followItem; @property(nonatomic, strong) PopupMenuToolsItem* readLaterItem; @property(nonatomic, strong) PopupMenuToolsItem* bookmarkItem; @property(nonatomic, strong) PopupMenuToolsItem* translateItem; @@ -1006,6 +1026,14 @@ - (NSArray<TableViewItem*>*)actionItems { NSMutableArray* actionsArray = [NSMutableArray array]; + + if (!self.isIncognito && IsWebChannelsEnabled()) { + // Follow. + self.followItem = + CreateFollowItem(IDS_IOS_TOOLS_MENU_FOLLOW, PopupMenuActionFollow, + @"popup_menu_follow", kToolsMenuFollowId); + [actionsArray addObject:self.followItem]; + } // Read Later. self.readLaterItem = CreateTableViewItem( IDS_IOS_CONTENT_CONTEXT_ADDTOREADINGLIST, PopupMenuActionReadLater,
diff --git a/ios/chrome/browser/ui/popup_menu/public/cells/popup_menu_item.h b/ios/chrome/browser/ui/popup_menu/public/cells/popup_menu_item.h index e9f744d5..015ace90 100644 --- a/ios/chrome/browser/ui/popup_menu/public/cells/popup_menu_item.h +++ b/ios/chrome/browser/ui/popup_menu/public/cells/popup_menu_item.h
@@ -28,6 +28,7 @@ PopupMenuActionViewSource, #endif // !defined(NDEBUG) PopupMenuActionOpenNewWindow, + PopupMenuActionFollow, PopupMenuActionBookmarks, PopupMenuActionReadingList, PopupMenuActionRecentTabs,
diff --git a/ios/chrome/browser/ui/popup_menu/resources/BUILD.gn b/ios/chrome/browser/ui/popup_menu/resources/BUILD.gn index cdd05e9..1a1d998 100644 --- a/ios/chrome/browser/ui/popup_menu/resources/BUILD.gn +++ b/ios/chrome/browser/ui/popup_menu/resources/BUILD.gn
@@ -248,3 +248,12 @@ "popup_menu_enterprise_icon.imageset/popup_menu_enterprise_icon@3x.png", ] } + +imageset("popup_menu_follow") { + sources = [ + "popup_menu_follow.imageset/Contents.json", + "popup_menu_follow.imageset/popup_menu_follow.png", + "popup_menu_follow.imageset/popup_menu_follow@2x.png", + "popup_menu_follow.imageset/popup_menu_follow@3x.png", + ] +}
diff --git a/ios/chrome/browser/ui/popup_menu/resources/popup_menu_follow.imageset/Contents.json b/ios/chrome/browser/ui/popup_menu/resources/popup_menu_follow.imageset/Contents.json new file mode 100644 index 0000000..73c9696 --- /dev/null +++ b/ios/chrome/browser/ui/popup_menu/resources/popup_menu_follow.imageset/Contents.json
@@ -0,0 +1,23 @@ +{ + "images": [ + { + "idiom": "universal", + "scale": "1x", + "filename": "popup_menu_follow.png" + }, + { + "idiom": "universal", + "scale": "2x", + "filename": "popup_menu_follow@2x.png" + }, + { + "idiom": "universal", + "scale": "3x", + "filename": "popup_menu_follow@3x.png" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +}
diff --git a/ios/chrome/browser/ui/popup_menu/resources/popup_menu_follow.imageset/popup_menu_follow.png b/ios/chrome/browser/ui/popup_menu/resources/popup_menu_follow.imageset/popup_menu_follow.png new file mode 100644 index 0000000..d5404fe0 --- /dev/null +++ b/ios/chrome/browser/ui/popup_menu/resources/popup_menu_follow.imageset/popup_menu_follow.png Binary files differ
diff --git a/ios/chrome/browser/ui/popup_menu/resources/popup_menu_follow.imageset/popup_menu_follow@2x.png b/ios/chrome/browser/ui/popup_menu/resources/popup_menu_follow.imageset/popup_menu_follow@2x.png new file mode 100644 index 0000000..f39d20ac --- /dev/null +++ b/ios/chrome/browser/ui/popup_menu/resources/popup_menu_follow.imageset/popup_menu_follow@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/popup_menu/resources/popup_menu_follow.imageset/popup_menu_follow@3x.png b/ios/chrome/browser/ui/popup_menu/resources/popup_menu_follow.imageset/popup_menu_follow@3x.png new file mode 100644 index 0000000..44812f7 --- /dev/null +++ b/ios/chrome/browser/ui/popup_menu/resources/popup_menu_follow.imageset/popup_menu_follow@3x.png Binary files differ
diff --git a/ios/chrome/browser/web/https_only_mode_egtest.mm b/ios/chrome/browser/web/https_only_mode_egtest.mm index 079c398d..a631aaa 100644 --- a/ios/chrome/browser/web/https_only_mode_egtest.mm +++ b/ios/chrome/browser/web/https_only_mode_egtest.mm
@@ -6,6 +6,8 @@ #include <string> #include "base/bind.h" +#include "base/strings/escape.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/sys_string_conversions.h" #include "base/test/metrics/histogram_tester.h" @@ -52,6 +54,24 @@ const net::test_server::HttpRequest& request) { std::unique_ptr<net::test_server::BasicHttpResponse> response( new net::test_server::BasicHttpResponse); + + const GURL request_url = request.GetURL(); + const std::string destValue = + base::UnescapeBinaryURLComponent(request_url.query_piece()); + // If the URL is in the form http://example.com/?redirect=url, + // redirect the response to `url`. + if (base::StartsWith(destValue, "redirect=")) { + const std::string dest = destValue.substr(strlen("redirect=")); + response->set_code(net::HttpStatusCode::HTTP_MOVED_PERMANENTLY); + response->AddCustomHeader("Location", dest); + response->AddCustomHeader("Access-Control-Allow-Origin", "*"); + response->set_content_type("text/html"); + response->set_content(base::StringPrintf( + "<html><head></head><body>Redirecting to %s</body></html>", + dest.c_str())); + return response; + } + response->set_content_type("text/html"); response->set_content("HTTPS_RESPONSE"); return std::move(response); @@ -226,7 +246,7 @@ expectTotalCount:(repeatCount * 2) forHistogram:@(security_interstitials::https_only_mode:: kEventHistogram)], - @"Failed to record event histogram"); + @"Incorrect numbber of records in event histogram"); GREYAssertNil([MetricsAppInterface expectCount:repeatCount @@ -284,6 +304,41 @@ [self assertSuccessfulUpgrade]; } +// Navigate to an HTTP URL directly. The upgraded HTTPS version serves good SSL +// which redirects to the original HTTP URL. This should show the interstitial. +- (void)testUpgrade_HTTPSRedirectsToHTTP { + [HttpsOnlyModeAppInterface setHTTPPortForTesting:self.testServer->port()]; + [HttpsOnlyModeAppInterface + setHTTPSPortForTesting:self.goodHTTPSServer->port()]; + [HttpsOnlyModeAppInterface useFakeHTTPSForTesting:true]; + + [ChromeEarlGrey loadURL:GURL("chrome://version")]; + [ChromeEarlGrey waitForWebStateContainingText:"Revision"]; + + GURL targetURL = self.testServer->GetURL("/"); + GURL upgradedURL = + self.goodHTTPSServer->GetURL("/?redirect=" + targetURL.spec()); + const std::string port_str = base::NumberToString(self.testServer->port()); + GURL::Replacements replacements; + replacements.SetPortStr(port_str); + GURL testURL = upgradedURL.ReplaceComponents(replacements); + + [ChromeEarlGrey loadURL:testURL]; + [ChromeEarlGrey + waitForWebStateContainingText:"You are seeing this warning because this " + "site does not support HTTPS"]; + [self assertFailedUpgrade:1]; + + // Click through the interstitial. This should load the HTTP page. + [ChromeEarlGrey tapWebStateElementWithID:@"proceed-button"]; + [ChromeEarlGrey waitForWebStateContainingText:"HTTP_RESPONSE"]; + + // Going back should go to chrome://version. + [ChromeEarlGrey goBack]; + [ChromeEarlGrey waitForWebStateContainingText:"Revision"]; + [self assertFailedUpgrade:1]; +} + // Navigate to an HTTP URL directly. The upgraded HTTPS version serves bad SSL. // The upgrade will fail and the HTTPS-Only mode interstitial will be shown. // Click through the interstitial, then reload the page. The HTTP page should
diff --git a/ios/chrome/common/ui/colors/Color+Chrome.swift b/ios/chrome/common/ui/colors/Color+Chrome.swift index 4a4e3d4..d80485d 100644 --- a/ios/chrome/common/ui/colors/Color+Chrome.swift +++ b/ios/chrome/common/ui/colors/Color+Chrome.swift
@@ -6,6 +6,11 @@ // Adds easy SwiftUI access to the Chrome color palette. extension Color { + /// The background color. + public static var cr_background: Color { + return Color(kBackgroundColor) + } + /// The primary text color. public static var cr_textPrimaryColor: Color { return Color(kTextPrimaryColor) @@ -70,4 +75,9 @@ public static var cr_tableRowViewHighlight: Color { return Color(kTableViewRowHighlightColor) } + + /// The table view sseparator color. + public static var cr_separator: Color { + return Color(kSeparatorColor) + } }
diff --git a/ios/chrome/common/ui/colors/resources/background_color.colorset/Contents.json b/ios/chrome/common/ui/colors/resources/background_color.colorset/Contents.json index 241c3635..8e398992 100644 --- a/ios/chrome/common/ui/colors/resources/background_color.colorset/Contents.json +++ b/ios/chrome/common/ui/colors/resources/background_color.colorset/Contents.json
@@ -9,10 +9,10 @@ "color" : { "color-space" : "display-p3", "components" : { - "alpha" : "1.000", - "red" : "1.000", - "green" : "1.000", - "blue" : "1.000" + "alpha": "1.000", + "red": "0xFF", + "green": "0xFF", + "blue": "0xFF" } } }, @@ -27,10 +27,10 @@ "color" : { "color-space" : "display-p3", "components" : { - "alpha" : "1.000", - "red" : "0.208", - "green" : "0.216", - "blue" : "0.227" + "alpha": "1.000", + "red": "0x35", + "green": "0x37", + "blue": "0x39" } } }
diff --git a/ios/chrome/test/data/policy/policy_test_cases.json b/ios/chrome/test/data/policy/policy_test_cases.json index d5dd6f7..b0b6f8e 100644 --- a/ios/chrome/test/data/policy/policy_test_cases.json +++ b/ios/chrome/test/data/policy/policy_test_cases.json
@@ -413,6 +413,9 @@ } ] }, + "OptimizationGuideFetchingEnabled": { + "reason_for_missing_test": "Policy was removed" + }, "PasswordManagerEnabled": { "os": [ "ios" @@ -835,36 +838,6 @@ } ] }, - - "OptimizationGuideFetchingEnabled": { - "os": [ - "ios" - ], - "policy_pref_mapping_tests": [ - { - "policies": { - "OptimizationGuideFetchingEnabled": true - }, - "prefs": { - "optimization_guide.fetching_enabled": { - "location": "user_profile", - "value": true - } - } - }, - { - "policies": { - "OptimizationGuideFetchingEnabled": false - }, - "prefs": { - "optimization_guide.fetching_enabled": { - "location": "user_profile", - "value": false - } - } - } - ] - }, "EnableExperimentalPolicies": { "reason_for_missing_test": "This policy has no pref as it is only directly read by the policy system." }
diff --git a/ios/components/security_interstitials/https_only_mode/https_only_mode_upgrade_tab_helper.mm b/ios/components/security_interstitials/https_only_mode/https_only_mode_upgrade_tab_helper.mm index 6a847a7..0f99588 100644 --- a/ios/components/security_interstitials/https_only_mode/https_only_mode_upgrade_tab_helper.mm +++ b/ios/components/security_interstitials/https_only_mode/https_only_mode_upgrade_tab_helper.mm
@@ -277,14 +277,19 @@ web::WebStatePolicyDecider::PolicyDecision::Allow()); return; } + // If already HTTPS (real or faux), simply allow the response. + if (url.SchemeIs(url::kHttpsScheme) || IsFakeHTTPSForTesting(url)) { + std::move(callback).Run( + web::WebStatePolicyDecider::PolicyDecision::Allow()); + return; + } - // Upgrade to HTTPS. - if (url.SchemeIs(url::kHttpScheme) && !IsFakeHTTPSForTesting(url) && - !is_http_fallback_navigation_) { - web::NavigationItem* item_pending = - web_state()->GetNavigationManager()->GetPendingItem(); + web::NavigationItem* item_pending = + web_state()->GetNavigationManager()->GetPendingItem(); + DCHECK(item_pending); + // Upgrade to HTTPS if the navigation wasn't upgraded before. + if (!item_pending->IsUpgradedToHttps()) { DCHECK(!stopped_loading_to_upgrade_); - DCHECK(!item_pending->IsUpgradedToHttps()); // Copy navigation parameters, then cancel the current navigation. http_url_ = url; referrer_ = item_pending->GetReferrer(); @@ -296,7 +301,24 @@ web::WebStatePolicyDecider::PolicyDecision::Cancel()); return; } - std::move(callback).Run(web::WebStatePolicyDecider::PolicyDecision::Allow()); + + // The navigation was already upgraded but landed on an HTTP URL, possibly + // through redirects (e.g. upgraded HTTPS -> HTTP). In this case, show the + // interstitial. + // Note that this doesn't handle HTTP URLs in the middle of redirects such as + // HTTPS -> HTTP -> HTTPS. The alternative is to do this check in + // ShouldAllowRequest(), but we don't have enough information there to ensure + // whether the HTTP URL is part of the redirect chain or a completely new + // navigation. + // This is divergence from the desktop implementation of this feature which + // relies on a redirect loop triggering a net error. + RecordUMA(Event::kUpgradeFailed); + DCHECK(was_upgraded_); + was_upgraded_ = false; + HttpsOnlyModeContainer* container = + HttpsOnlyModeContainer::FromWebState(web_state()); + container->SetHttpUrl(url); + std::move(callback).Run(CreateHttpsOnlyModeErrorDecision()); } WEB_STATE_USER_DATA_KEY_IMPL(HttpsOnlyModeUpgradeTabHelper)
diff --git a/media/mojo/clients/win/media_foundation_renderer_client.cc b/media/mojo/clients/win/media_foundation_renderer_client.cc index 702228de..4c41e59 100644 --- a/media/mojo/clients/win/media_foundation_renderer_client.cc +++ b/media/mojo/clients/win/media_foundation_renderer_client.cc
@@ -11,8 +11,11 @@ #include "media/base/media_log.h" #include "media/base/win/mf_feature_checks.h" #include "media/base/win/mf_helpers.h" +#include "media/mojo/mojom/speech_recognition_service.mojom.h" #include "media/renderers/win/media_foundation_renderer.h" #include "mojo/public/cpp/bindings/callback_helpers.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/remote.h" namespace media { @@ -24,7 +27,9 @@ mojo::PendingReceiver<ClientExtension> client_extension_receiver, std::unique_ptr<DCOMPTextureWrapper> dcomp_texture_wrapper, ObserveOverlayStateCB observe_overlay_state_cb, - VideoRendererSink* sink) + VideoRendererSink* sink, + mojo::PendingRemote<media::mojom::MediaFoundationRendererObserver> + media_foundation_renderer_observer) : media_task_runner_(std::move(media_task_runner)), media_log_(std::move(media_log)), mojo_renderer_(std::move(mojo_renderer)), @@ -33,7 +38,9 @@ observe_overlay_state_cb_(std::move(observe_overlay_state_cb)), sink_(sink), pending_client_extension_receiver_(std::move(client_extension_receiver)), - client_extension_receiver_(this) { + client_extension_receiver_(this), + pending_media_foundation_renderer_observer_( + std::move(media_foundation_renderer_observer)) { DVLOG_FUNC(1); } @@ -56,6 +63,9 @@ renderer_extension_.Bind(std::move(pending_renderer_extension_), media_task_runner_); + media_foundation_renderer_observer_.Bind( + std::move(pending_media_foundation_renderer_observer_), + media_task_runner_); client_extension_receiver_.Bind(std::move(pending_client_extension_receiver_), media_task_runner_);
diff --git a/media/mojo/clients/win/media_foundation_renderer_client.h b/media/mojo/clients/win/media_foundation_renderer_client.h index d73f501..55b1fa25 100644 --- a/media/mojo/clients/win/media_foundation_renderer_client.h +++ b/media/mojo/clients/win/media_foundation_renderer_client.h
@@ -21,7 +21,9 @@ #include "media/mojo/mojom/dcomp_surface_registry.mojom.h" #include "media/mojo/mojom/renderer_extensions.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" namespace media { @@ -61,7 +63,9 @@ mojo::PendingReceiver<ClientExtension> client_extension_receiver, std::unique_ptr<DCOMPTextureWrapper> dcomp_texture_wrapper, media::ObserveOverlayStateCB observe_overlay_state_cb, - VideoRendererSink* sink); + VideoRendererSink* sink, + mojo::PendingRemote<media::mojom::MediaFoundationRendererObserver> + media_foundation_renderer_observer); MediaFoundationRendererClient(const MediaFoundationRendererClient&) = delete; MediaFoundationRendererClient& operator=( @@ -179,6 +183,12 @@ // Used to receive calls from the MF_CMD LPAC Utility Process. mojo::PendingReceiver<ClientExtension> pending_client_extension_receiver_; mojo::Receiver<ClientExtension> client_extension_receiver_; + + mojo::PendingRemote<media::mojom::MediaFoundationRendererObserver> + pending_media_foundation_renderer_observer_; + mojo::Remote<media::mojom::MediaFoundationRendererObserver> + media_foundation_renderer_observer_; + // NOTE: Weak pointers must be invalidated before all other member variables. base::WeakPtrFactory<MediaFoundationRendererClient> weak_factory_{this}; };
diff --git a/media/mojo/clients/win/media_foundation_renderer_client_factory.cc b/media/mojo/clients/win/media_foundation_renderer_client_factory.cc index 21fa5f4..5c15a834 100644 --- a/media/mojo/clients/win/media_foundation_renderer_client_factory.cc +++ b/media/mojo/clients/win/media_foundation_renderer_client_factory.cc
@@ -12,7 +12,6 @@ #include "media/mojo/clients/mojo_renderer_factory.h" #include "media/mojo/clients/win/media_foundation_renderer_client.h" #include "media/mojo/mojom/renderer_extensions.mojom.h" -#include "media/mojo/mojom/speech_recognition_service.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" @@ -90,14 +89,19 @@ // Notify the browser that a Media Foundation Renderer has been created. Live // Caption supports muted media so this is run regardless of whether the media // is audible. - media_foundation_renderer_notifier_->MediaFoundationRendererCreated(); + mojo::PendingRemote<media::mojom::MediaFoundationRendererObserver> + media_foundation_renderer_observer_remote; + media_foundation_renderer_notifier_->MediaFoundationRendererCreated( + media_foundation_renderer_observer_remote + .InitWithNewPipeAndPassReceiver()); // mojo_renderer's ownership is passed to MediaFoundationRendererClient. return std::make_unique<MediaFoundationRendererClient>( media_task_runner, media_log_->Clone(), std::move(mojo_renderer), std::move(renderer_extension_remote), std::move(client_extension_receiver), std::move(dcomp_texture_wrapper), - std::move(observe_overlay_state_cb_), video_renderer_sink); + std::move(observe_overlay_state_cb_), video_renderer_sink, + std::move(media_foundation_renderer_observer_remote)); } media::MediaResource::Type
diff --git a/media/mojo/clients/win/media_foundation_renderer_client_factory.h b/media/mojo/clients/win/media_foundation_renderer_client_factory.h index edbf604..f37be85c 100644 --- a/media/mojo/clients/win/media_foundation_renderer_client_factory.h +++ b/media/mojo/clients/win/media_foundation_renderer_client_factory.h
@@ -12,7 +12,7 @@ #include "media/base/win/dcomp_texture_wrapper.h" #include "media/base/win/overlay_state_observer_subscription.h" #include "media/mojo/clients/mojo_renderer_factory.h" -#include "media/mojo/mojom/speech_recognition_service.mojom.h" +#include "media/mojo/mojom/renderer_extensions.mojom.h" #include "mojo/public/cpp/bindings/remote.h" namespace media {
diff --git a/media/mojo/mojom/renderer_extensions.mojom b/media/mojo/mojom/renderer_extensions.mojom index 34990cd2..01a0343 100644 --- a/media/mojo/mojom/renderer_extensions.mojom +++ b/media/mojo/mojom/renderer_extensions.mojom
@@ -135,3 +135,24 @@ // Notify which rendering mode to be using for future video frames. SetRenderingMode(RenderingMode mode); }; + +// This interface is used by the browser to determine if there are any renderers +// actively using the Media Foundation Renderer. The number of Media Foundation +// Renderers in use is determined by the number of active connections. The +// remote lives in the renderer process and the receiver lives in the browser +// process. +interface MediaFoundationRendererObserver { +}; + +// This interface is used to notify the browser that the renderer is using the +// Media Foundation Renderer which uses MediaFoundation to render audio +// directly. Live Caption will not work in this case because Chrome is unable +// to tap into the audio rendering pipeline. The remote lives in the renderer +// process and the receiver lives in the browser process. +interface MediaFoundationRendererNotifier { + // Notify the browser than a Media Foundation Renderer has been created. The + // browser will use this event to notify the user that some features + // incompatible with the Media Foundation Renderer may not work. + MediaFoundationRendererCreated( + pending_receiver<MediaFoundationRendererObserver> observer); +};
diff --git a/media/mojo/mojom/speech_recognition_service.mojom b/media/mojo/mojom/speech_recognition_service.mojom index b359fab0..c7046d30 100644 --- a/media/mojo/mojom/speech_recognition_service.mojom +++ b/media/mojo/mojom/speech_recognition_service.mojom
@@ -223,15 +223,3 @@ // and Dictation via OnDeviceSpeechRecognizer in Chrome OS. string? language; }; - -// This interface is used to notify the browser that the renderer is using the -// Media Foundation Renderer which uses MediaFoundation to render audio -// directly. Live Caption will not work in this case because Chrome is unable -// to tap into the audio rendering pipeline. The remote lives in the renderer -// process and the receiver lives in the browser process. -interface MediaFoundationRendererNotifier { - // Notify the browser than a Media Foundation Renderer has been created. The - // browser will use this event to notify the user that some features - // incompatible with the Media Foundation Renderer may not work. - MediaFoundationRendererCreated(); -};
diff --git a/mojo/OWNERS b/mojo/OWNERS index 14b8412..1caa9511 100644 --- a/mojo/OWNERS +++ b/mojo/OWNERS
@@ -1,6 +1,7 @@ set noparent # NOTE: keep this in sync with lsc-owners-override@chromium.org owners # by emailing lsc-policy@chromium.org when this list changes. +ajgo@chromium.org dcheng@chromium.org oksamyt@chromium.org rockot@google.com
diff --git a/net/dns/dns_client.cc b/net/dns/dns_client.cc index a3855b1..179f857 100644 --- a/net/dns/dns_client.cc +++ b/net/dns/dns_client.cc
@@ -15,6 +15,8 @@ #include "base/ranges/algorithm.h" #include "base/values.h" #include "net/base/address_list.h" +#include "net/base/ip_address.h" +#include "net/base/ip_endpoint.h" #include "net/dns/address_sorter.h" #include "net/dns/dns_session.h" #include "net/dns/dns_transaction.h" @@ -191,8 +193,13 @@ }); if (it == servers.end()) return absl::nullopt; - // TODO(crbug.com/1200908): Read preset IPs from the server config. - return absl::nullopt; + std::vector<IPEndPoint> combined; + for (const IPAddressList& ips : it->endpoints()) { + for (const IPAddress& ip : ips) { + combined.emplace_back(ip, endpoint.port()); + } + } + return AddressList(std::move(combined)); } DnsTransactionFactory* GetTransactionFactory() override {
diff --git a/net/dns/dns_client_unittest.cc b/net/dns/dns_client_unittest.cc index 30c87286..17bce032 100644 --- a/net/dns/dns_client_unittest.cc +++ b/net/dns/dns_client_unittest.cc
@@ -23,6 +23,7 @@ #include "net/url_request/url_request_test_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "url/scheme_host_port.h" namespace net { @@ -282,6 +283,35 @@ EXPECT_FALSE(client_->FallbackFromInsecureTransactionPreferred()); } +TEST_F(DnsClientTest, GetPresetAddrs) { + DnsConfig config; + config.doh_config = *net::DnsOverHttpsConfig::FromString(R"( + { + "servers": [{ + "template": "https://www.doh.com/", + "endpoints": [{ + "ips": ["4.3.2.1"] + }, { + "ips": ["4.3.2.2"] + }] + }] + } + )"); + client_->SetSystemConfig(config); + + EXPECT_FALSE(client_->GetPresetAddrs( + url::SchemeHostPort("https", "otherdomain.com", 443))); + EXPECT_FALSE( + client_->GetPresetAddrs(url::SchemeHostPort("http", "www.doh.com", 443))); + EXPECT_FALSE(client_->GetPresetAddrs( + url::SchemeHostPort("https", "www.doh.com", 9999))); + + AddressList expected({{{4, 3, 2, 1}, 443}, {{4, 3, 2, 2}, 443}}); + EXPECT_THAT( + client_->GetPresetAddrs(url::SchemeHostPort("https", "www.doh.com", 443)), + testing::Optional(expected)); +} + TEST_F(DnsClientTest, Override) { client_->SetSystemConfig(BasicValidConfig()); EXPECT_THAT(client_->GetEffectiveConfig(),
diff --git a/net/dns/dns_config.cc b/net/dns/dns_config.cc index 3f05133a..671574b 100644 --- a/net/dns/dns_config.cc +++ b/net/dns/dns_config.cc
@@ -107,7 +107,7 @@ dict.SetBoolKey("rotate", rotate); dict.SetBoolKey("use_local_ipv6", use_local_ipv6); dict.SetIntKey("num_hosts", hosts.size()); - dict.SetKey("doh_config", doh_config.ToValue()); + dict.SetKey("doh_config", base::Value(doh_config.ToValue())); dict.SetIntKey("secure_dns_mode", static_cast<int>(secure_dns_mode)); dict.SetBoolKey("allow_dns_over_https_upgrade", allow_dns_over_https_upgrade);
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc index 3d49a78..67d9ff6b 100644 --- a/net/dns/dns_transaction_unittest.cc +++ b/net/dns/dns_transaction_unittest.cc
@@ -636,7 +636,8 @@ base::StringPrintf("doh_test_%zu", i)) + (use_post ? "" : "{?dns}")); } - config_.doh_config = *DnsOverHttpsConfig::FromStrings(std::move(templates)); + config_.doh_config = + *DnsOverHttpsConfig::FromTemplatesForTesting(std::move(templates)); ConfigureFactory(); if (make_available) {
diff --git a/net/dns/dns_util_unittest.cc b/net/dns/dns_util_unittest.cc index 9febaead..c31e29a56 100644 --- a/net/dns/dns_util_unittest.cc +++ b/net/dns/dns_util_unittest.cc
@@ -501,7 +501,7 @@ EXPECT_EQ(0u, doh_servers.size()); doh_servers = GetDohUpgradeServersFromNameservers(nameservers); - auto expected_config = *DnsOverHttpsConfig::FromStrings( + auto expected_config = *DnsOverHttpsConfig::FromTemplatesForTesting( {"https://chrome.cloudflare-dns.com/dns-query", "https://doh.cleanbrowsing.org/doh/family-filter{?dns}", "https://doh.cleanbrowsing.org/doh/security-filter{?dns}"});
diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc index e420894..2e15f94 100644 --- a/net/dns/host_resolver_manager.cc +++ b/net/dns/host_resolver_manager.cc
@@ -1275,10 +1275,9 @@ DCHECK(client_); DCHECK(delegate_); - if (secure_) - DCHECK(client_->CanUseSecureDnsTransactions()); - else + if (!secure_) { DCHECK(client_->CanUseInsecureDnsTransactions()); + } PushTransactionsNeeded(MaybeDisableAdditionalQueries(query_types)); }
diff --git a/net/dns/host_resolver_manager_unittest.cc b/net/dns/host_resolver_manager_unittest.cc index 95ec797..71a14fc 100644 --- a/net/dns/host_resolver_manager_unittest.cc +++ b/net/dns/host_resolver_manager_unittest.cc
@@ -8303,7 +8303,7 @@ const DnsConfig* fetched_config = client_ptr->GetEffectiveConfig(); EXPECT_EQ(original_config.nameservers, fetched_config->nameservers); - auto expected_doh_config = *DnsOverHttpsConfig::FromStrings( + auto expected_doh_config = *DnsOverHttpsConfig::FromTemplatesForTesting( {"https://chrome.cloudflare-dns.com/dns-query", "https://doh.cleanbrowsing.org/doh/family-filter{?dns}", "https://doh.cleanbrowsing.org/doh/security-filter{?dns}"}); @@ -8462,7 +8462,7 @@ const DnsConfig* fetched_config = client_ptr->GetEffectiveConfig(); EXPECT_EQ(original_config.nameservers, fetched_config->nameservers); - auto expected_doh_config = *DnsOverHttpsConfig::FromStrings( + auto expected_doh_config = *DnsOverHttpsConfig::FromTemplatesForTesting( {"https://chrome.cloudflare-dns.com/dns-query", "https://doh.cleanbrowsing.org/doh/family-filter{?dns}", "https://doh.cleanbrowsing.org/doh/security-filter{?dns}"});
diff --git a/net/dns/public/dns_over_https_config.cc b/net/dns/public/dns_over_https_config.cc index 08a2a7f..9eee96c 100644 --- a/net/dns/public/dns_over_https_config.cc +++ b/net/dns/public/dns_over_https_config.cc
@@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" #include "base/ranges/algorithm.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" @@ -26,16 +28,43 @@ base::SPLIT_WANT_NONEMPTY); } -std::vector<absl::optional<DnsOverHttpsServerConfig>> ParseServers( - std::vector<std::string> servers) { +std::vector<absl::optional<DnsOverHttpsServerConfig>> ParseTemplates( + std::vector<std::string> templates) { std::vector<absl::optional<DnsOverHttpsServerConfig>> parsed; - parsed.reserve(servers.size()); - base::ranges::transform(servers, std::back_inserter(parsed), [](auto& s) { + parsed.reserve(templates.size()); + base::ranges::transform(templates, std::back_inserter(parsed), [](auto& s) { return DnsOverHttpsServerConfig::FromString(std::move(s)); }); return parsed; } +constexpr base::StringPiece kJsonKeyServers("servers"); + +absl::optional<DnsOverHttpsConfig> FromValue(base::Value::Dict value) { + base::Value::List* servers_value = value.FindList(kJsonKeyServers); + if (!servers_value) + return absl::nullopt; + std::vector<DnsOverHttpsServerConfig> servers; + servers.reserve(servers_value->size()); + for (base::Value& elt : *servers_value) { + base::Value::Dict* dict = elt.GetIfDict(); + if (!dict) + return absl::nullopt; + auto parsed = DnsOverHttpsServerConfig::FromValue(std::move(*dict)); + if (!parsed.has_value()) + return absl::nullopt; + servers.push_back(std::move(*parsed)); + } + return DnsOverHttpsConfig(servers); +} + +absl::optional<DnsOverHttpsConfig> FromJson(base::StringPiece json) { + absl::optional<base::Value> value = base::JSONReader::Read(json); + if (!value || !value->is_dict()) + return absl::nullopt; + return FromValue(std::move(value->GetDict())); +} + } // namespace DnsOverHttpsConfig::DnsOverHttpsConfig() = default; @@ -53,11 +82,11 @@ : servers_(std::move(servers)) {} // static -absl::optional<DnsOverHttpsConfig> DnsOverHttpsConfig::FromStrings( - std::vector<std::string> server_strings) { +absl::optional<DnsOverHttpsConfig> DnsOverHttpsConfig::FromTemplates( + std::vector<std::string> server_templates) { // All templates must be valid for the group to be considered valid. std::vector<DnsOverHttpsServerConfig> servers; - for (auto& server_config : ParseServers(server_strings)) { + for (auto& server_config : ParseTemplates(server_templates)) { if (!server_config) return absl::nullopt; servers.push_back(std::move(*server_config)); @@ -66,19 +95,29 @@ } // static +absl::optional<DnsOverHttpsConfig> DnsOverHttpsConfig::FromTemplatesForTesting( + std::vector<std::string> server_templates) { + return FromTemplates(std::move(server_templates)); +} + +// static absl::optional<DnsOverHttpsConfig> DnsOverHttpsConfig::FromString( base::StringPiece doh_config) { - // TODO(crbug.com/1200908): Also accept JSON-formatted input. - std::vector<std::string> server_strings = SplitGroup(doh_config); - if (server_strings.empty()) + absl::optional<DnsOverHttpsConfig> parsed = FromJson(doh_config); + if (parsed && !parsed->servers().empty()) + return parsed; + std::vector<std::string> server_templates = SplitGroup(doh_config); + if (server_templates.empty()) return absl::nullopt; // `doh_config` must contain at least one server. - return FromStrings(std::move(server_strings)); + return FromTemplates(std::move(server_templates)); } // static DnsOverHttpsConfig DnsOverHttpsConfig::FromStringLax( base::StringPiece doh_config) { - auto parsed = ParseServers(SplitGroup(doh_config)); + if (absl::optional<DnsOverHttpsConfig> parsed = FromJson(doh_config)) + return *parsed; + auto parsed = ParseTemplates(SplitGroup(doh_config)); std::vector<DnsOverHttpsServerConfig> servers; for (auto& server_config : parsed) { if (server_config) @@ -91,25 +130,32 @@ return servers() == other.servers(); } -std::vector<base::StringPiece> DnsOverHttpsConfig::ToStrings() const { - std::vector<base::StringPiece> strings; - strings.reserve(servers().size()); - base::ranges::transform(servers(), std::back_inserter(strings), - &DnsOverHttpsServerConfig::server_template_piece); - return strings; -} - std::string DnsOverHttpsConfig::ToString() const { - // TODO(crbug.com/1200908): Return JSON for complex configurations. - return base::JoinString(ToStrings(), "\n"); + if (base::ranges::all_of(servers(), &DnsOverHttpsServerConfig::IsSimple)) { + // Return the templates on separate lines. + std::vector<base::StringPiece> strings; + strings.reserve(servers().size()); + base::ranges::transform(servers(), std::back_inserter(strings), + &DnsOverHttpsServerConfig::server_template_piece); + return base::JoinString(std::move(strings), "\n"); + } + std::string json; + CHECK(base::JSONWriter::WriteWithOptions( + ToValue(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &json)); + // Remove the trailing newline from pretty-print output. + base::TrimWhitespaceASCII(json, base::TRIM_TRAILING, &json); + return json; } -base::Value DnsOverHttpsConfig::ToValue() const { - base::Value::ListStorage list; +base::Value::Dict DnsOverHttpsConfig::ToValue() const { + base::Value::List list; list.reserve(servers().size()); - base::ranges::transform(servers(), std::back_inserter(list), - &DnsOverHttpsServerConfig::ToValue); - return base::Value(std::move(list)); + for (const auto& server : servers()) { + list.Append(server.ToValue()); + } + base::Value::Dict dict; + dict.Set(kJsonKeyServers, std::move(list)); + return dict; } } // namespace net
diff --git a/net/dns/public/dns_over_https_config.h b/net/dns/public/dns_over_https_config.h index fb030d6c..dbc13f5 100644 --- a/net/dns/public/dns_over_https_config.h +++ b/net/dns/public/dns_over_https_config.h
@@ -17,7 +17,8 @@ namespace net { // Represents a collection of DnsOverHttpsServerConfig. The string -// representation is a whitespace-separated list of DoH URI templates. +// representation is either a JSON object or a whitespace-separated +// list of DoH URI templates. // The Value representation is a list of dictionaries. class NET_EXPORT DnsOverHttpsConfig { public: @@ -30,9 +31,9 @@ explicit DnsOverHttpsConfig(std::vector<DnsOverHttpsServerConfig> servers); - // Constructs a Config from textual representations of zero or more servers. + // Constructs a Config from URI templates of zero or more servers. // Returns `nullopt` if any string is invalid. - static absl::optional<DnsOverHttpsConfig> FromStrings( + static absl::optional<DnsOverHttpsConfig> FromTemplatesForTesting( std::vector<std::string> servers); // Constructs a Config from its text form if valid. Returns `nullopt` if the @@ -41,7 +42,7 @@ base::StringPiece doh_config); // Constructs a DnsOverHttpsConfig from its text form, skipping any invalid - // templates. The result may be empty. + // templates in the whitespace-separated form. The result may be empty. static DnsOverHttpsConfig FromStringLax(base::StringPiece doh_config); bool operator==(const DnsOverHttpsConfig& other) const; @@ -51,17 +52,18 @@ return servers_; } - // Returns string representations of the individual DnsOverHttpsServerConfigs. - // The return value will be invalidated if this object is destroyed or moved. - std::vector<base::StringPiece> ToStrings() const; - - // Inverse of FromString(). + // Inverse of FromString(). Uses the JSON representation if necessary. std::string ToString() const; - // Encodes the config as a Value. Currently only used for NetLog. - base::Value ToValue() const; + // Encodes the config as a Value. Used to produce the JSON representation. + base::Value::Dict ToValue() const; private: + // Constructs a Config from URI templates of zero or more servers. + // Returns `nullopt` if any string is invalid. + static absl::optional<DnsOverHttpsConfig> FromTemplates( + std::vector<std::string> servers); + std::vector<DnsOverHttpsServerConfig> servers_; };
diff --git a/net/dns/public/dns_over_https_config_unittest.cc b/net/dns/public/dns_over_https_config_unittest.cc index e4baa66..6830cf5 100644 --- a/net/dns/public/dns_over_https_config_unittest.cc +++ b/net/dns/public/dns_over_https_config_unittest.cc
@@ -6,7 +6,7 @@ #include "base/values.h" #include "net/dns/public/dns_over_https_server_config.h" -#include "testing/gmock/include/gmock/gmock-matchers.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -21,8 +21,10 @@ DnsOverHttpsConfig config({kServerConfig1}); EXPECT_THAT(config.servers(), testing::ElementsAre(kServerConfig1)); - base::Value expected_value(base::Value::Type::LIST); - expected_value.Append(kServerConfig1.ToValue()); + base::Value::List expected_servers; + expected_servers.Append(kServerConfig1.ToValue()); + base::Value::Dict expected_value; + expected_value.Set("servers", std::move(expected_servers)); EXPECT_EQ(expected_value, config.ToValue()); EXPECT_EQ(config, config); @@ -33,16 +35,15 @@ DnsOverHttpsConfig config(servers); EXPECT_EQ(servers, config.servers()); - EXPECT_THAT(config.ToStrings(), - testing::ElementsAre(kServerConfig1.server_template(), - kServerConfig2.server_template())); EXPECT_EQ(kServerConfig1.server_template() + "\n" + kServerConfig2.server_template(), config.ToString()); - base::Value expected_value(base::Value::Type::LIST); - expected_value.Append(kServerConfig1.ToValue()); - expected_value.Append(kServerConfig2.ToValue()); + base::Value::List expected_servers; + expected_servers.Append(kServerConfig1.ToValue()); + expected_servers.Append(kServerConfig2.ToValue()); + base::Value::Dict expected_value; + expected_value.Set("servers", std::move(expected_servers)); EXPECT_EQ(expected_value, config.ToValue()); EXPECT_EQ(config, config); @@ -85,18 +86,6 @@ testing::Optional(DnsOverHttpsConfig({kServerConfig1, kServerConfig2}))); } -TEST(DnsOverHttpsConfigTest, FromStrings) { - EXPECT_THAT(DnsOverHttpsConfig::FromStrings({}), - testing::Optional(DnsOverHttpsConfig())); - EXPECT_THAT( - DnsOverHttpsConfig::FromStrings({kServerConfig1.server_template()}), - testing::Optional(DnsOverHttpsConfig({kServerConfig1}))); - EXPECT_THAT( - DnsOverHttpsConfig::FromStrings( - {kServerConfig1.server_template(), kServerConfig2.server_template()}), - testing::Optional(DnsOverHttpsConfig({kServerConfig1, kServerConfig2}))); -} - TEST(DnsOverHttpsConfigTest, FromStringExtraWhitespace) { auto config = DnsOverHttpsConfig::FromString( " \t" + kServerConfig1.server_template() + " " + @@ -118,18 +107,13 @@ TEST(DnsOverHttpsConfigTest, FromStringAllInvalid) { EXPECT_FALSE(DnsOverHttpsConfig::FromString("foo")); - EXPECT_FALSE(DnsOverHttpsConfig::FromStrings({"foo"})); EXPECT_EQ(DnsOverHttpsConfig(), DnsOverHttpsConfig::FromStringLax("foo")); EXPECT_FALSE(DnsOverHttpsConfig::FromString("foo bar")); - EXPECT_FALSE(DnsOverHttpsConfig::FromStrings({"foo", "bar"})); EXPECT_EQ(DnsOverHttpsConfig(), DnsOverHttpsConfig::FromStringLax("foo bar")); } TEST(DnsOverHttpsConfigTest, FromStringSomeInvalid) { - EXPECT_FALSE(DnsOverHttpsConfig::FromStrings( - {"foo", kServerConfig1.server_template(), "bar"})); - std::string some_invalid = "foo " + kServerConfig1.server_template() + " bar " + kServerConfig2.server_template() + " baz"; @@ -138,5 +122,99 @@ DnsOverHttpsConfig::FromStringLax(some_invalid)); } +TEST(DnsOverHttpsConfigTest, Json) { + auto parsed = DnsOverHttpsConfig::FromString(R"( + { + "servers": [{ + "template": "https://dnsserver.example.net/dns-query{?dns}", + "endpoints": [{ + "ips": ["192.0.2.1", "2001:db8::1"] + }, { + "ips": ["192.0.2.2", "2001:db8::2"] + }] + }] + } + )"); + + ASSERT_TRUE(parsed); + EXPECT_EQ(1u, parsed->servers().size()); + + auto parsed2 = DnsOverHttpsConfig::FromString(parsed->ToString()); + EXPECT_EQ(parsed, parsed2); +} + +TEST(DnsOverHttpsConfigTest, JsonWithUnknownKey) { + auto parsed = DnsOverHttpsConfig::FromString(R"( + { + "servers": [{ + "template": "https://dnsserver.example.net/dns-query{?dns}" + }], + "unknown key": "value is ignored" + } + )"); + + ASSERT_TRUE(parsed); + EXPECT_EQ(1u, parsed->servers().size()); + + auto parsed2 = DnsOverHttpsConfig::FromString(parsed->ToString()); + EXPECT_EQ(parsed, parsed2); +} + +TEST(DnsOverHttpsConfigTest, BadJson) { + // Not JSON + EXPECT_FALSE(DnsOverHttpsConfig::FromString("{")); + + // No servers + EXPECT_FALSE(DnsOverHttpsConfig::FromString("{}")); + + // Not a Dict + EXPECT_FALSE(DnsOverHttpsConfig::FromString("[]")); + + // Wrong type for "servers" + EXPECT_FALSE(DnsOverHttpsConfig::FromString("{\"servers\": 12345}")); + + // One bad server + EXPECT_FALSE(DnsOverHttpsConfig::FromString(R"( + { + "servers": [{ + "template": "https://dnsserver.example.net/dns-query{?dns}", + }, { + "template": "not a valid template" + }] + } + )")); +} + +TEST(DnsOverHttpsConfigTest, JsonLax) { + // Valid JSON is allowed + auto parsed = *DnsOverHttpsConfig::FromString(R"( + { + "servers": [{ + "template": "https://dnsserver.example.net/dns-query{?dns}", + "endpoints": [{ + "ips": ["192.0.2.1", "2001:db8::1"] + }, { + "ips": ["192.0.2.2", "2001:db8::2"] + }] + }] + } + )"); + DnsOverHttpsConfig reparsed = + DnsOverHttpsConfig::FromStringLax(parsed.ToString()); + EXPECT_EQ(parsed, reparsed); + + // Lax parsing does not accept bad servers in JSON. + DnsOverHttpsConfig from_bad = DnsOverHttpsConfig::FromStringLax(R"( + { + "servers": [{ + "template": "https://dnsserver.example.net/dns-query{?dns}", + }, { + "template": "not a valid template" + }] + } + )"); + EXPECT_THAT(from_bad.servers(), testing::IsEmpty()); +} + } // namespace } // namespace net
diff --git a/net/dns/public/dns_over_https_server_config.cc b/net/dns/public/dns_over_https_server_config.cc index 51aa35e..0554b1d5 100644 --- a/net/dns/public/dns_over_https_server_config.cc +++ b/net/dns/public/dns_over_https_server_config.cc
@@ -8,6 +8,8 @@ #include <string> #include <unordered_map> +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" #include "base/strings/string_piece.h" #include "base/values.h" #include "net/third_party/uri_template/uri_template.h" @@ -68,27 +70,54 @@ return true; } +constexpr base::StringPiece kJsonKeyTemplate("template"); +constexpr base::StringPiece kJsonKeyEndpoints("endpoints"); +constexpr base::StringPiece kJsonKeyIps("ips"); + } // namespace namespace net { +DnsOverHttpsServerConfig::DnsOverHttpsServerConfig(std::string server_template, + bool use_post, + Endpoints endpoints) + : server_template_(std::move(server_template)), + use_post_(use_post), + endpoints_(std::move(endpoints)) {} + +DnsOverHttpsServerConfig::DnsOverHttpsServerConfig() = default; +DnsOverHttpsServerConfig::DnsOverHttpsServerConfig( + const DnsOverHttpsServerConfig& other) = default; +DnsOverHttpsServerConfig& DnsOverHttpsServerConfig::operator=( + const DnsOverHttpsServerConfig& other) = default; +DnsOverHttpsServerConfig::DnsOverHttpsServerConfig( + DnsOverHttpsServerConfig&& other) = default; +DnsOverHttpsServerConfig& DnsOverHttpsServerConfig::operator=( + DnsOverHttpsServerConfig&& other) = default; + +DnsOverHttpsServerConfig::~DnsOverHttpsServerConfig() = default; + absl::optional<DnsOverHttpsServerConfig> DnsOverHttpsServerConfig::FromString( - std::string doh_template) { + std::string doh_template, + Endpoints bindings) { bool use_post; if (!IsValidDohTemplate(doh_template, &use_post)) return absl::nullopt; - return DnsOverHttpsServerConfig(std::move(doh_template), use_post); + return DnsOverHttpsServerConfig(std::move(doh_template), use_post, + std::move(bindings)); } bool DnsOverHttpsServerConfig::operator==( const DnsOverHttpsServerConfig& other) const { // use_post_ is derived from server_template_, so we don't need to compare it. - return server_template_ == other.server_template_; + return server_template_ == other.server_template_ && + endpoints_ == other.endpoints_; } bool DnsOverHttpsServerConfig::operator<( const DnsOverHttpsServerConfig& other) const { - return server_template_ < other.server_template_; + return std::tie(server_template_, endpoints_) < + std::tie(other.server_template_, other.endpoints_); } const std::string& DnsOverHttpsServerConfig::server_template() const { @@ -103,10 +132,78 @@ return use_post_; } -base::Value DnsOverHttpsServerConfig::ToValue() const { - base::Value value(base::Value::Type::DICTIONARY); - value.SetStringKey("server_template", server_template()); +const DnsOverHttpsServerConfig::Endpoints& DnsOverHttpsServerConfig::endpoints() + const { + return endpoints_; +} + +bool DnsOverHttpsServerConfig::IsSimple() const { + return endpoints_.empty(); +} + +base::Value::Dict DnsOverHttpsServerConfig::ToValue() const { + base::Value::Dict value; + value.Set(kJsonKeyTemplate, server_template()); + if (!endpoints_.empty()) { + base::Value::List bindings; + bindings.reserve(endpoints_.size()); + for (const IPAddressList& ip_list : endpoints_) { + base::Value::Dict binding; + base::Value::List ips; + ips.reserve(ip_list.size()); + for (const IPAddress& ip : ip_list) { + ips.Append(ip.ToString()); + } + binding.Set(kJsonKeyIps, std::move(ips)); + bindings.Append(std::move(binding)); + } + value.Set(kJsonKeyEndpoints, std::move(bindings)); + } return value; } +// static +absl::optional<DnsOverHttpsServerConfig> DnsOverHttpsServerConfig::FromValue( + base::Value::Dict value) { + std::string* server_template = value.FindString(kJsonKeyTemplate); + if (!server_template) + return absl::nullopt; + bool use_post; + if (!IsValidDohTemplate(*server_template, &use_post)) + return absl::nullopt; + Endpoints endpoints; + const base::Value* endpoints_json = value.Find(kJsonKeyEndpoints); + if (endpoints_json) { + if (!endpoints_json->is_list()) + return absl::nullopt; + const base::Value::List& json_list = endpoints_json->GetList(); + endpoints.reserve(json_list.size()); + for (const base::Value& endpoint : json_list) { + const base::Value::Dict* dict = endpoint.GetIfDict(); + if (!dict) + return absl::nullopt; + IPAddressList parsed_ips; + const base::Value* ips = endpoint.FindKey(kJsonKeyIps); + if (ips) { + const base::Value::List* ip_list = ips->GetIfList(); + if (!ip_list) + return absl::nullopt; + parsed_ips.reserve(ip_list->size()); + for (const base::Value& ip : *ip_list) { + const std::string* ip_str = ip.GetIfString(); + if (!ip_str) + return absl::nullopt; + IPAddress parsed; + if (!parsed.AssignFromIPLiteral(*ip_str)) + return absl::nullopt; + parsed_ips.push_back(std::move(parsed)); + } + } + endpoints.push_back(std::move(parsed_ips)); + } + } + return DnsOverHttpsServerConfig(std::move(*server_template), use_post, + std::move(endpoints)); +} + } // namespace net
diff --git a/net/dns/public/dns_over_https_server_config.h b/net/dns/public/dns_over_https_server_config.h index 4ca53f9..312ce74 100644 --- a/net/dns/public/dns_over_https_server_config.h +++ b/net/dns/public/dns_over_https_server_config.h
@@ -9,6 +9,7 @@ #include "base/strings/string_piece.h" #include "base/values.h" +#include "net/base/ip_address.h" #include "net/base/net_export.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -17,9 +18,25 @@ // Simple representation of a DoH server for use in configurations. class NET_EXPORT DnsOverHttpsServerConfig { public: + // TODO(crbug.com/1200908): Generalize endpoints to enable other capabilities + // of HTTPS records, such as extended metadata and aliases. + using Endpoints = std::vector<IPAddressList>; + + // A default constructor is required by Mojo. + DnsOverHttpsServerConfig(); + DnsOverHttpsServerConfig(const DnsOverHttpsServerConfig& other); + DnsOverHttpsServerConfig& operator=(const DnsOverHttpsServerConfig& other); + DnsOverHttpsServerConfig(DnsOverHttpsServerConfig&& other); + DnsOverHttpsServerConfig& operator=(DnsOverHttpsServerConfig&& other); + ~DnsOverHttpsServerConfig(); + // Returns nullopt if |doh_template| is invalid. static absl::optional<DnsOverHttpsServerConfig> FromString( - std::string doh_template); + std::string doh_template, + Endpoints endpoints = {}); + + static absl::optional<DnsOverHttpsServerConfig> FromValue( + base::Value::Dict value); bool operator==(const DnsOverHttpsServerConfig& other) const; bool operator<(const DnsOverHttpsServerConfig& other) const; @@ -27,15 +44,21 @@ const std::string& server_template() const; base::StringPiece server_template_piece() const; bool use_post() const; + const Endpoints& endpoints() const; - base::Value ToValue() const; + // Returns true if this server config can be represented as just a template. + bool IsSimple() const; + + base::Value::Dict ToValue() const; private: - DnsOverHttpsServerConfig(std::string server_template, bool use_post) - : server_template_(std::move(server_template)), use_post_(use_post) {} + DnsOverHttpsServerConfig(std::string server_template, + bool use_post, + Endpoints endpoints); std::string server_template_; bool use_post_; + Endpoints endpoints_; }; } // namespace net
diff --git a/net/dns/public/dns_over_https_server_config_unittest.cc b/net/dns/public/dns_over_https_server_config_unittest.cc index 39f8e47..8c262e6 100644 --- a/net/dns/public/dns_over_https_server_config_unittest.cc +++ b/net/dns/public/dns_over_https_server_config_unittest.cc
@@ -6,6 +6,8 @@ #include <string> +#include "base/json/json_reader.h" +#include "net/base/ip_address.h" #include "net/dns/public/dns_over_https_config.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -13,6 +15,12 @@ namespace net { namespace { +const IPAddress ip1(192, 0, 2, 1); +const IPAddress ip2(0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); +const IPAddress ip3(192, 0, 2, 2); +const IPAddress ip4(0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2); +const DnsOverHttpsServerConfig::Endpoints endpoints{{ip1, ip2}, {ip3, ip4}}; + TEST(DnsOverHttpsServerConfigTest, ValidWithGet) { auto parsed = DnsOverHttpsServerConfig::FromString( "https://dnsserver.example.net/dns-query{?dns}"); @@ -67,5 +75,162 @@ EXPECT_FALSE(net::DnsOverHttpsServerConfig::FromString("")); } +TEST(DnsOverHttpsServerConfigTest, Simple) { + auto parsed = DnsOverHttpsServerConfig::FromString( + "https://dnsserver.example.net/dns-query{?dns}"); + EXPECT_THAT(parsed, testing::Optional(testing::Property( + &DnsOverHttpsServerConfig::IsSimple, true))); +} + +TEST(DnsOverHttpsServerConfigTest, ToValueSimple) { + auto parsed = DnsOverHttpsServerConfig::FromString( + "https://dnsserver.example.net/dns-query{?dns}"); + ASSERT_TRUE(parsed); + + base::Value expected = *base::JSONReader::Read(R"( + { + "template": "https://dnsserver.example.net/dns-query{?dns}" + } + )"); + EXPECT_EQ(expected.GetDict(), parsed->ToValue()); +} + +TEST(DnsOverHttpsServerConfigTest, ToValueWithEndpoints) { + auto parsed = DnsOverHttpsServerConfig::FromString( + "https://dnsserver.example.net/dns-query{?dns}", endpoints); + ASSERT_TRUE(parsed); + + EXPECT_THAT(parsed, testing::Optional(testing::Property( + &DnsOverHttpsServerConfig::IsSimple, false))); + EXPECT_THAT(parsed, testing::Optional(testing::Property( + &DnsOverHttpsServerConfig::endpoints, endpoints))); + + base::Value expected = *base::JSONReader::Read( + R"({ + "template": "https://dnsserver.example.net/dns-query{?dns}", + "endpoints": [{ + "ips": ["192.0.2.1", "2001:db8::1"] + }, { + "ips": ["192.0.2.2", "2001:db8::2"] + }] + })"); + EXPECT_EQ(expected.GetDict(), parsed->ToValue()); +} + +TEST(DnsOverHttpsServerConfigTest, FromValueSimple) { + base::Value input = *base::JSONReader::Read(R"( + { + "template": "https://dnsserver.example.net/dns-query{?dns}" + } + )"); + + auto parsed = DnsOverHttpsServerConfig::FromValue(std::move(input.GetDict())); + + auto expected = DnsOverHttpsServerConfig::FromString( + "https://dnsserver.example.net/dns-query{?dns}"); + EXPECT_EQ(expected, parsed); +} + +TEST(DnsOverHttpsServerConfigTest, FromValueWithEndpoints) { + base::Value input = *base::JSONReader::Read(R"( + { + "template": "https://dnsserver.example.net/dns-query{?dns}", + "endpoints": [{ + "ips": ["192.0.2.1", "2001:db8::1"] + }, { + "ips": ["192.0.2.2", "2001:db8::2"] + }] + } + )"); + + auto parsed = DnsOverHttpsServerConfig::FromValue(std::move(input.GetDict())); + + auto expected = DnsOverHttpsServerConfig::FromString( + "https://dnsserver.example.net/dns-query{?dns}", endpoints); + EXPECT_EQ(expected, parsed); +} + +TEST(DnsOverHttpsServerConfigTest, FromValueWithUnknownKey) { + base::Value input = *base::JSONReader::Read(R"( + { + "template": "https://dnsserver.example.net/dns-query{?dns}", + "unknown key": "value is ignored" + } + )"); + + auto parsed = DnsOverHttpsServerConfig::FromValue(std::move(input.GetDict())); + + auto expected = DnsOverHttpsServerConfig::FromString( + "https://dnsserver.example.net/dns-query{?dns}"); + EXPECT_EQ(expected, parsed); +} + +TEST(DnsOverHttpsServerConfigTest, FromValueInvalid) { + // Empty dict + EXPECT_FALSE(DnsOverHttpsServerConfig::FromValue(base::Value::Dict())); + + // Wrong scheme + base::StringPiece input = R"( + { + "template": "http://dnsserver.example.net/dns-query{?dns}" + } + )"; + EXPECT_FALSE(DnsOverHttpsServerConfig::FromValue( + std::move(base::JSONReader::Read(input)->GetDict()))); + + // Wrong template type + input = R"({"template": 12345})"; + EXPECT_FALSE(DnsOverHttpsServerConfig::FromValue( + std::move(base::JSONReader::Read(input)->GetDict()))); + + // Wrong endpoints type + input = R"( + { + "template": "https://dnsserver.example.net/dns-query{?dns}", + "endpoints": { + "ips": ["192.0.2.1", "2001:db8::1"] + } + } + )"; + EXPECT_FALSE(DnsOverHttpsServerConfig::FromValue( + std::move(base::JSONReader::Read(input)->GetDict()))); + + // Wrong "ips" type + input = R"( + { + "template": "https://dnsserver.example.net/dns-query{?dns}", + "endpoints": [{ + "ips": "192.0.2.1" + }] + } + )"; + EXPECT_FALSE(DnsOverHttpsServerConfig::FromValue( + std::move(base::JSONReader::Read(input)->GetDict()))); + + // Wrong IP type + input = R"( + { + "template": "https://dnsserver.example.net/dns-query{?dns}", + "endpoints": [{ + "ips": ["2001:db8::1", 192.021] + }] + } + )"; + EXPECT_FALSE(DnsOverHttpsServerConfig::FromValue( + std::move(base::JSONReader::Read(input)->GetDict()))); + + // Bad IP address + input = R"( + { + "template": "https://dnsserver.example.net/dns-query{?dns}", + "endpoints": [{ + "ips": ["2001:db8::1", "256.257.258.259"] + }] + } + )"; + EXPECT_FALSE(DnsOverHttpsServerConfig::FromValue( + std::move(base::JSONReader::Read(input)->GetDict()))); +} + } // namespace } // namespace net
diff --git a/net/dns/resolve_context_unittest.cc b/net/dns/resolve_context_unittest.cc index 4ca342d..4543399 100644 --- a/net/dns/resolve_context_unittest.cc +++ b/net/dns/resolve_context_unittest.cc
@@ -74,7 +74,8 @@ templates.push_back( base::StringPrintf("https://mock.http/doh_test_%d{?dns}", i)); } - config.doh_config = *DnsOverHttpsConfig::FromStrings(std::move(templates)); + config.doh_config = + *DnsOverHttpsConfig::FromTemplatesForTesting(std::move(templates)); return config; }
diff --git a/pdf/BUILD.gn b/pdf/BUILD.gn index 7ecac8f..b173a424 100644 --- a/pdf/BUILD.gn +++ b/pdf/BUILD.gn
@@ -242,8 +242,6 @@ sources = [ "ppapi_migration/bitmap.cc", "ppapi_migration/bitmap.h", - "ppapi_migration/graphics.cc", - "ppapi_migration/graphics.h", "ppapi_migration/result_codes.h", "ppapi_migration/url_loader.cc", "ppapi_migration/url_loader.h", @@ -380,7 +378,6 @@ "pdfium/pdfium_print_unittest.cc", "pdfium/pdfium_test_base.cc", "pdfium/pdfium_test_base.h", - "ppapi_migration/graphics_unittest.cc", "ppapi_migration/url_loader_unittest.cc", "range_set_unittest.cc", "test/run_all_unittests.cc",
diff --git a/pdf/paint_manager.cc b/pdf/paint_manager.cc index 2e94a3f..b5930c9e 100644 --- a/pdf/paint_manager.cc +++ b/pdf/paint_manager.cc
@@ -8,7 +8,7 @@ #include <stdint.h> #include <algorithm> -#include <memory> +#include <cmath> #include <utility> #include "base/auto_reset.h" @@ -20,15 +20,18 @@ #include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h" #include "pdf/paint_ready_rect.h" -#include "pdf/ppapi_migration/graphics.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkSamplingOptions.h" #include "third_party/skia/include/core/SkSurface.h" +#include "ui/gfx/blit.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" +#include "ui/gfx/geometry/skia_conversions.h" #include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/geometry/vector2d_f.h" @@ -94,7 +97,7 @@ const gfx::Point& origin, const gfx::Vector2d& translate, bool schedule_flush) { - if (!graphics_) + if (!surface_) return; if (scale <= 0.0f) { @@ -124,7 +127,7 @@ } void PaintManager::Invalidate() { - if (!graphics_ && !has_pending_resize_) + if (!surface_ && !has_pending_resize_) return; EnsureCallbackPending(); @@ -134,7 +137,7 @@ void PaintManager::InvalidateRect(const gfx::Rect& rect) { DCHECK(!in_paint_); - if (!graphics_ && !has_pending_resize_) + if (!surface_ && !has_pending_resize_) return; // Clip the rect to the device area. @@ -151,7 +154,7 @@ const gfx::Vector2d& amount) { DCHECK(!in_paint_); - if (!graphics_ && !has_pending_resize_) + if (!surface_ && !has_pending_resize_) return; EnsureCallbackPending(); @@ -200,7 +203,7 @@ // do this later. // // Note that `has_pending_resize_` will always be set on the first DoPaint(). - DCHECK(graphics_ || has_pending_resize_); + DCHECK(surface_ || has_pending_resize_); if (has_pending_resize_) { plugin_size_ = pending_size_; // Only create a new graphics context if the current context isn't big @@ -214,7 +217,6 @@ surface_ = SkSurface::MakeRasterN32Premul(new_size.width(), new_size.height()); DCHECK(surface_); - graphics_ = std::make_unique<SkiaGraphics>(surface_.get()); // TODO(crbug.com/1317832): Can we guarantee repainting some other way? client_->InvalidatePluginContainer(); @@ -249,9 +251,14 @@ ready_now = aggregator_.GetReadyRects(); aggregator_.ClearPendingUpdate(); - // Apply any scroll first. - if (update.has_scroll) - graphics_->Scroll(update.scroll_rect, update.scroll_delta); + // First, apply any scroll amount less than the surface's size. + if (update.has_scroll && + std::abs(update.scroll_delta.x()) < surface_->width() && + std::abs(update.scroll_delta.y()) < surface_->height()) { + // TODO(crbug.com/1263614): Use `SkSurface::notifyContentWillChange()`. + gfx::ScrollCanvas(surface_->getCanvas(), update.scroll_rect, + update.scroll_delta); + } view_size_changed_waiting_for_paint_ = false; } else { @@ -280,7 +287,11 @@ } for (const auto& ready_rect : ready_now) { - graphics_->PaintImage(ready_rect.image(), ready_rect.rect()); + // TODO(crbug.com/1284255): Avoid inefficient `SkBitmap::asImage()`. + SkRect skia_rect = gfx::RectToSkRect(ready_rect.rect()); + surface_->getCanvas()->drawImageRect( + ready_rect.image().asImage(), skia_rect, skia_rect, SkSamplingOptions(), + nullptr, SkCanvas::kStrict_SrcRectConstraint); } Flush();
diff --git a/pdf/paint_manager.h b/pdf/paint_manager.h index 3981e3c..be5739a 100644 --- a/pdf/paint_manager.h +++ b/pdf/paint_manager.h
@@ -5,16 +5,11 @@ #ifndef PDF_PAINT_MANAGER_H_ #define PDF_PAINT_MANAGER_H_ -#include <stdint.h> - -#include <memory> #include <vector> #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" -#include "base/time/time.h" #include "pdf/paint_aggregator.h" -#include "pdf/ppapi_migration/graphics.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "ui/gfx/geometry/size.h" @@ -164,9 +159,6 @@ // Backing Skia surface. sk_sp<SkSurface> surface_; - // This graphics device will be null if no graphics has been set yet. - std::unique_ptr<Graphics> graphics_; - PaintAggregator aggregator_; // See comment for EnsureCallbackPending for more on how these work.
diff --git a/pdf/paint_manager_unittest.cc b/pdf/paint_manager_unittest.cc index ae80e86..fcfe2b2 100644 --- a/pdf/paint_manager_unittest.cc +++ b/pdf/paint_manager_unittest.cc
@@ -9,16 +9,20 @@ #include "base/files/file_path.h" #include "base/run_loop.h" #include "base/strings/string_piece.h" +#include "cc/test/pixel_comparator.h" +#include "cc/test/pixel_test_utils.h" #include "pdf/paint_ready_rect.h" -#include "pdf/ppapi_migration/graphics.h" #include "pdf/test/test_helpers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" +#include "ui/gfx/geometry/skia_conversions.h" namespace chrome_pdf { @@ -82,6 +86,78 @@ return saved_snapshot; } + void TestPaintImage(const gfx::Size& plugin_size, + const gfx::Size& source_size, + const gfx::Rect& paint_rect, + const gfx::Rect& overlapped_rect) { + // Paint `paint_rect` from `source_size` image over a magenta background. + paint_manager_.SetSize(plugin_size, 1.0f); + sk_sp<SkImage> snapshot = WaitForFlush( + /*expected_paint_rects=*/{{gfx::Rect(plugin_size)}}, + /*fake_ready=*/ + { + {gfx::Rect(plugin_size), + CreateSkiaImageForTesting(plugin_size, SK_ColorMAGENTA)}, + {paint_rect, CreateSkiaImageForTesting(source_size, SK_ColorRED)}, + }, + /*fake_pending=*/{}); + ASSERT_TRUE(snapshot); + + // Check if snapshot has `overlapped_rect` painted red. + snapshot = snapshot->makeSubset( + SkIRect::MakeWH(plugin_size.width(), plugin_size.height())); + ASSERT_TRUE(snapshot); + + SkBitmap snapshot_bitmap; + ASSERT_TRUE(snapshot->asLegacyBitmap(&snapshot_bitmap)); + + SkBitmap expected_bitmap = + CreateSkiaImageForTesting(plugin_size, SK_ColorMAGENTA); + expected_bitmap.erase(SK_ColorRED, gfx::RectToSkIRect(overlapped_rect)); + + EXPECT_TRUE( + cc::MatchesBitmap(snapshot_bitmap, expected_bitmap, + cc::ExactPixelComparator(/*discard_alpha=*/false))); + } + + void TestScroll(const gfx::Vector2d& scroll_amount, + const gfx::Rect& expected_paint_rect, + base::StringPiece expected_png) { + // Paint non-uniform initial image. + gfx::Size plugin_size = paint_manager_.GetEffectiveSize(); + ASSERT_GE(plugin_size.width(), 4); + ASSERT_GE(plugin_size.height(), 4); + + SkBitmap initial_bitmap = + CreateSkiaImageForTesting(plugin_size, SK_ColorRED); + initial_bitmap.erase(SK_ColorGREEN, {1, 1, plugin_size.width() - 1, + plugin_size.height() - 2}); + + paint_manager_.Invalidate(); + ASSERT_TRUE( + WaitForFlush(/*expected_paint_rects=*/{gfx::Rect(plugin_size)}, + /*fake_ready=*/{{gfx::Rect(plugin_size), initial_bitmap}}, + /*fake_pending=*/{})); + + // Scroll by `scroll_amount`, painting `expected_paint_rect` magenta. + paint_manager_.ScrollRect(gfx::Rect(plugin_size), scroll_amount); + sk_sp<SkImage> snapshot = WaitForFlush( + /*expected_paint_rects=*/{expected_paint_rect}, + /*fake_ready=*/ + {{expected_paint_rect, + CreateSkiaImageForTesting(plugin_size, SK_ColorMAGENTA)}}, + /*fake_pending=*/{}); + ASSERT_TRUE(snapshot); + + // Compare snapshot to `expected_png`. + snapshot = snapshot->makeSubset( + SkIRect::MakeWH(plugin_size.width(), plugin_size.height())); + ASSERT_TRUE(snapshot); + + EXPECT_TRUE( + MatchesPngFile(snapshot.get(), GetTestDataFilePath(expected_png))); + } + NiceMock<FakeClient> client_; PaintManager paint_manager_{&client_}; }; @@ -174,6 +250,65 @@ GetTestDataFilePath("do_paint_first.png"))); } +TEST_F(PaintManagerTest, PaintImage) { + // Painted area is within the plugin area and the source image. + TestPaintImage(/*plugin_size=*/{20, 20}, /*source_size=*/{15, 15}, + /*paint_rect=*/{0, 0, 10, 10}, + /*overlapped_rect=*/{0, 0, 10, 10}); + + // Painted area straddles the plugin area and the source image. + TestPaintImage(/*plugin_size=*/{50, 30}, /*source_size=*/{30, 50}, + /*paint_rect=*/{10, 10, 30, 30}, + /*overlapped_rect=*/{10, 10, 20, 20}); + + // Painted area is outside the plugin area. + TestPaintImage(/*plugin_size=*/{10, 10}, /*source_size=*/{30, 30}, + /*paint_rect=*/{10, 10, 10, 10}, + /*overlapped_rect=*/{0, 0, 0, 0}); + + // Painted area is outside the source image. + TestPaintImage(/*plugin_size=*/{15, 15}, /*source_size=*/{5, 5}, + /*paint_rect=*/{10, 10, 5, 5}, + /*overlapped_rect=*/{0, 0, 0, 0}); +} + +TEST_F(PaintManagerTest, Scroll) { + paint_manager_.SetSize({4, 5}, 1.0f); + + TestScroll(/*scroll_amount=*/{1, 0}, /*expected_paint_rect=*/{0, 0, 1, 5}, + "scroll_right.png"); + TestScroll(/*scroll_amount=*/{-2, 0}, /*expected_paint_rect=*/{2, 0, 2, 5}, + "scroll_left.png"); + TestScroll(/*scroll_amount=*/{0, 3}, /*expected_paint_rect=*/{0, 0, 4, 3}, + "scroll_down.png"); + TestScroll(/*scroll_amount=*/{0, -3}, /*expected_paint_rect=*/{0, 2, 4, 3}, + "scroll_up.png"); +} + +TEST_F(PaintManagerTest, ScrollIgnored) { + paint_manager_.SetSize({4, 5}, 1.0f); + + // Scroll to the edge of the plugin area. + TestScroll(/*scroll_amount=*/{4, 0}, /*expected_paint_rect=*/{0, 0, 4, 5}, + "scroll_ignored.png"); + TestScroll(/*scroll_amount=*/{-4, 0}, /*expected_paint_rect=*/{0, 0, 4, 5}, + "scroll_ignored.png"); + TestScroll(/*scroll_amount=*/{0, 5}, /*expected_paint_rect=*/{0, 0, 4, 5}, + "scroll_ignored.png"); + TestScroll(/*scroll_amount=*/{0, -5}, /*expected_paint_rect=*/{0, 0, 4, 5}, + "scroll_ignored.png"); + + // Scroll outside of the plugin area. + TestScroll(/*scroll_amount=*/{5, 0}, /*expected_paint_rect=*/{0, 0, 4, 5}, + "scroll_ignored.png"); + TestScroll(/*scroll_amount=*/{-7, 0}, /*expected_paint_rect=*/{0, 0, 4, 5}, + "scroll_ignored.png"); + TestScroll(/*scroll_amount=*/{0, 8}, /*expected_paint_rect=*/{0, 0, 4, 5}, + "scroll_ignored.png"); + TestScroll(/*scroll_amount=*/{0, -9}, /*expected_paint_rect=*/{0, 0, 4, 5}, + "scroll_ignored.png"); +} + } // namespace } // namespace chrome_pdf
diff --git a/pdf/pdf_view_plugin_base_unittest.cc b/pdf/pdf_view_plugin_base_unittest.cc index 22728b0..30872b3 100644 --- a/pdf/pdf_view_plugin_base_unittest.cc +++ b/pdf/pdf_view_plugin_base_unittest.cc
@@ -23,7 +23,6 @@ #include "pdf/document_metadata.h" #include "pdf/pdf_engine.h" #include "pdf/pdfium/pdfium_form_filler.h" -#include "pdf/ppapi_migration/graphics.h" #include "pdf/ppapi_migration/url_loader.h" #include "pdf/test/test_pdfium_engine.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/pdf/ppapi_migration/graphics.cc b/pdf/ppapi_migration/graphics.cc deleted file mode 100644 index c2ddab0..0000000 --- a/pdf/ppapi_migration/graphics.cc +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "pdf/ppapi_migration/graphics.h" - -#include <cmath> - -#include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkSurface.h" -#include "ui/gfx/blit.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/skia_conversions.h" -#include "ui/gfx/geometry/vector2d.h" - -namespace chrome_pdf { - -SkiaGraphics::SkiaGraphics(SkSurface* surface) : surface_(surface) {} - -SkiaGraphics::~SkiaGraphics() = default; - -void SkiaGraphics::PaintImage(const SkBitmap& image, - const gfx::Rect& src_rect) { - SkRect skia_rect = RectToSkRect(src_rect); - - // TODO(crbug.com/1284255): Avoid inefficient `SkBitmap::asImage()`. - surface_->getCanvas()->drawImageRect(image.asImage(), skia_rect, skia_rect, - SkSamplingOptions(), nullptr, - SkCanvas::kStrict_SrcRectConstraint); -} - -void SkiaGraphics::Scroll(const gfx::Rect& clip, const gfx::Vector2d& amount) { - // If we are being asked to scroll by more than the graphics' rect size, just - // ignore the scroll command. - if (std::abs(amount.x()) >= surface_->width() || - std::abs(amount.y()) >= surface_->height()) { - return; - } - - // TODO(crbug.com/1263614): Use `SkSurface::notifyContentWillChange()`. - gfx::ScrollCanvas(surface_->getCanvas(), clip, amount); -} - -} // namespace chrome_pdf
diff --git a/pdf/ppapi_migration/graphics.h b/pdf/ppapi_migration/graphics.h deleted file mode 100644 index 1e739f10..0000000 --- a/pdf/ppapi_migration/graphics.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PDF_PPAPI_MIGRATION_GRAPHICS_H_ -#define PDF_PPAPI_MIGRATION_GRAPHICS_H_ - -#include "base/memory/raw_ptr.h" - -class SkBitmap; -class SkSurface; - -namespace gfx { -class Rect; -class Vector2d; -} // namespace gfx - -namespace chrome_pdf { - -// Abstraction for a Pepper or Skia graphics device. -class Graphics { - public: - virtual ~Graphics() = default; - - // Paints the `src_rect` region of `image` to the graphics device. The image - // must be compatible with the concrete `Graphics` implementation. - virtual void PaintImage(const SkBitmap& image, const gfx::Rect& src_rect) = 0; - - // Shifts the `clip` region of the graphics device by `amount`. - virtual void Scroll(const gfx::Rect& clip, const gfx::Vector2d& amount) = 0; - - protected: - Graphics() = default; -}; - -// A Skia graphics device. -class SkiaGraphics final : public Graphics { - public: - // `surface` must outlive this object. - explicit SkiaGraphics(SkSurface* surface); - ~SkiaGraphics() override; - - void PaintImage(const SkBitmap& image, const gfx::Rect& src_rect) override; - - void Scroll(const gfx::Rect& clip, const gfx::Vector2d& amount) override; - - private: - // Unowned pointer. The surface is required to outlive this object. - raw_ptr<SkSurface> surface_; -}; - -} // namespace chrome_pdf - -#endif // PDF_PPAPI_MIGRATION_GRAPHICS_H_
diff --git a/pdf/ppapi_migration/graphics_unittest.cc b/pdf/ppapi_migration/graphics_unittest.cc deleted file mode 100644 index e2ed039..0000000 --- a/pdf/ppapi_migration/graphics_unittest.cc +++ /dev/null
@@ -1,202 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "pdf/ppapi_migration/graphics.h" - -#include <memory> - -#include "cc/test/pixel_comparator.h" -#include "cc/test/pixel_test_utils.h" -#include "pdf/ppapi_migration/bitmap.h" -#include "pdf/test/test_helpers.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkRefCnt.h" -#include "third_party/skia/include/core/SkSize.h" -#include "third_party/skia/include/core/SkSurface.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/size.h" -#include "ui/gfx/geometry/vector2d.h" - -namespace chrome_pdf { - -namespace { - -SkBitmap GenerateExpectedBitmap(const SkISize& graphics_size, - const SkIRect& rect) { - SkBitmap bitmap = CreateN32PremulSkBitmap(graphics_size); - bitmap.erase(SK_ColorRED, rect); - return bitmap; -} - -// Creates a nonuniform SkBitmap with given `width` and `height`, such -// that scrolling will cause a noticeable change to the bitmap. Returns an -// empty SkBitmap if either `width` or `height` is less than 4. -SkBitmap CreateNonuniformBitmap(int width, int height) { - if (width < 4 || height < 4) - return SkBitmap(); - - SkBitmap bitmap = CreateN32PremulSkBitmap(SkISize::Make(width, height)); - bitmap.eraseColor(SK_ColorRED); - bitmap.erase(SK_ColorGREEN, {1, 1, width - 1, height - 2}); - bitmap.erase(SK_ColorBLACK, {2, 3, 1, 2}); - return bitmap; -} - -} // namespace - -class SkiaGraphicsTest : public testing::Test { - protected: - void TestPaintImageResult(const SkISize& graphics_size, - const gfx::Size& src_size, - const gfx::Rect& paint_rect, - const SkIRect& overlapped_rect) { - surface_ = SkSurface::MakeRasterN32Premul(graphics_size.width(), - graphics_size.height()); - ASSERT_TRUE(surface_); - graphics_ = std::make_unique<SkiaGraphics>(surface_.get()); - - // Paint and snapshot. - graphics_->PaintImage(CreateSkiaImageForTesting(src_size, SK_ColorRED), - paint_rect); - SkBitmap snapshot_bitmap = MakeSnapshot(); - - // Verify snapshot dimensions. - EXPECT_EQ(snapshot_bitmap.dimensions(), graphics_size) - << snapshot_bitmap.width() << " x " << snapshot_bitmap.height() - << " != " << graphics_size.width() << " x " << graphics_size.height(); - - // Verify the snapshot matches the expected result. - const SkBitmap expected_bitmap = - GenerateExpectedBitmap(graphics_size, overlapped_rect); - EXPECT_TRUE( - cc::MatchesBitmap(snapshot_bitmap, expected_bitmap, - cc::ExactPixelComparator(/*discard_alpha=*/false))) - << "SkBitmap comparison failed for graphics size of " - << graphics_size.width() << " x " << graphics_size.height(); - } - - SkBitmap MakeSnapshot() { - SkBitmap bitmap; - surface_->makeImageSnapshot()->asLegacyBitmap(&bitmap); - return bitmap; - } - - sk_sp<SkSurface> surface_; - - std::unique_ptr<Graphics> graphics_; -}; - -class SkiaGraphicsScrollTest : public SkiaGraphicsTest { - protected: - static constexpr gfx::Rect kGraphicsRect = gfx::Rect(4, 5); - - // Initializes `initial_bitmap_` and `graphics_` before scrolling tests. - void SetUp() override { - surface_ = SkSurface::MakeRasterN32Premul(kGraphicsRect.width(), - kGraphicsRect.height()); - ASSERT_TRUE(surface_); - graphics_ = std::make_unique<SkiaGraphics>(surface_.get()); - - // Paint a nonuniform SkBitmap to graphics. - initial_bitmap_ = - CreateNonuniformBitmap(kGraphicsRect.width(), kGraphicsRect.height()); - graphics_->PaintImage(initial_bitmap_, kGraphicsRect); - SkBitmap initial_snapshot = MakeSnapshot(); - - ASSERT_TRUE(cc::MatchesBitmap(initial_snapshot, initial_bitmap_, - cc::ExactPixelComparator(false))); - } - - // Resets the canvas with `initial_bitmap_`, then scrolls it by - // `scroll_amount`. - void ResetAndScroll(const gfx::Vector2d& scroll_amount) { - if (!graphics_) - return; - - graphics_->PaintImage(initial_bitmap_, kGraphicsRect); - graphics_->Scroll(kGraphicsRect, scroll_amount); - } - - SkBitmap initial_bitmap_; -}; - -// static -constexpr gfx::Rect SkiaGraphicsScrollTest::kGraphicsRect; - -TEST_F(SkiaGraphicsTest, PaintImage) { - struct PaintImageParams { - // Size of the graphics to be painted on. - SkISize graphics_size; - - // Size of the source image. - gfx::Size src_size; - - // Painting area. - gfx::Rect paint_rect; - - // Common area of the graphics, the source image and the painting area. - SkIRect overlapped_rect; - }; - - static constexpr PaintImageParams kPaintImageTestParams[] = { - // Paint area is within the graphics and the source image. - {{20, 20}, {15, 15}, gfx::Rect(0, 0, 10, 10), {0, 0, 10, 10}}, - // Paint area is not completely within the graphics, or the source - // image. - {{50, 30}, {30, 50}, gfx::Rect(10, 10, 30, 30), {10, 10, 30, 30}}, - // Paint area is outside the graphics. - {{10, 10}, {30, 30}, gfx::Rect(10, 10, 10, 10), {0, 0, 0, 0}}, - // Paint area is outside the source image. - {{15, 15}, {5, 5}, gfx::Rect(10, 10, 5, 5), {0, 0, 0, 0}}, - }; - - for (const auto& params : kPaintImageTestParams) - TestPaintImageResult(params.graphics_size, params.src_size, - params.paint_rect, params.overlapped_rect); -} - -TEST_F(SkiaGraphicsScrollTest, InvalidScroll) { - static constexpr gfx::Vector2d kNoOpScrollAmounts[] = { - // Scroll to the edge of the graphics rect. - {kGraphicsRect.width(), 0}, - {-kGraphicsRect.width(), 0}, - {0, kGraphicsRect.height()}, - {0, -kGraphicsRect.height()}, - // Scroll outside the graphics rect. - {kGraphicsRect.width() + 1, 0}, - {-(kGraphicsRect.width() + 2), 0}, - {0, kGraphicsRect.height() + 3}, - {0, -(kGraphicsRect.height() + 4)}, - }; - - for (const auto& no_op_amount : kNoOpScrollAmounts) { - ResetAndScroll(no_op_amount); - SkBitmap snapshot = MakeSnapshot(); - EXPECT_TRUE(cc::MatchesBitmap(snapshot, initial_bitmap_, - cc::ExactPixelComparator(false))) - << "SkBitmap comparison failed for scroll amount of " - << no_op_amount.ToString(); - } -} - -TEST_F(SkiaGraphicsScrollTest, Scroll) { - static constexpr gfx::Vector2d kValidScrollAmounts[] = { - {1, 0}, - {-2, 0}, - {0, 3}, - {0, -3}, - }; - - for (const auto& valid_amount : kValidScrollAmounts) { - ResetAndScroll(valid_amount); - SkBitmap snapshot = MakeSnapshot(); - EXPECT_FALSE(cc::MatchesBitmap(snapshot, initial_bitmap_, - cc::ExactPixelComparator(false))) - << "The scroll amount of " << valid_amount.ToString() - << " failed to change the snapshot of `graphics_`"; - } -} - -} // namespace chrome_pdf
diff --git a/pdf/test/data/paint_manager/scroll_down.png b/pdf/test/data/paint_manager/scroll_down.png new file mode 100644 index 0000000..1b4bfaf --- /dev/null +++ b/pdf/test/data/paint_manager/scroll_down.png Binary files differ
diff --git a/pdf/test/data/paint_manager/scroll_ignored.png b/pdf/test/data/paint_manager/scroll_ignored.png new file mode 100644 index 0000000..7b8b8d0f --- /dev/null +++ b/pdf/test/data/paint_manager/scroll_ignored.png Binary files differ
diff --git a/pdf/test/data/paint_manager/scroll_left.png b/pdf/test/data/paint_manager/scroll_left.png new file mode 100644 index 0000000..6b5ebd3 --- /dev/null +++ b/pdf/test/data/paint_manager/scroll_left.png Binary files differ
diff --git a/pdf/test/data/paint_manager/scroll_right.png b/pdf/test/data/paint_manager/scroll_right.png new file mode 100644 index 0000000..a0ea26f --- /dev/null +++ b/pdf/test/data/paint_manager/scroll_right.png Binary files differ
diff --git a/pdf/test/data/paint_manager/scroll_up.png b/pdf/test/data/paint_manager/scroll_up.png new file mode 100644 index 0000000..f0c264d1 --- /dev/null +++ b/pdf/test/data/paint_manager/scroll_up.png Binary files differ
diff --git a/remoting/host/chromeos/BUILD.gn b/remoting/host/chromeos/BUILD.gn index 1f2f094..5a9b20a 100644 --- a/remoting/host/chromeos/BUILD.gn +++ b/remoting/host/chromeos/BUILD.gn
@@ -45,6 +45,7 @@ "//ui/aura/cursor", "//ui/base/cursor/mojom:cursor_type", "//ui/display/manager", + "//ui/wm", ] }
diff --git a/remoting/host/chromeos/DEPS b/remoting/host/chromeos/DEPS index 5c5a7323..82e3e97 100644 --- a/remoting/host/chromeos/DEPS +++ b/remoting/host/chromeos/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+ui/display", + "+ui/wm", ] specific_include_rules = {
diff --git a/remoting/host/chromeos/point_transformer.cc b/remoting/host/chromeos/point_transformer.cc index 1ed6427c3..ba2e2ce 100644 --- a/remoting/host/chromeos/point_transformer.cc +++ b/remoting/host/chromeos/point_transformer.cc
@@ -5,70 +5,83 @@ #include "remoting/host/chromeos/point_transformer.h" #include "ash/shell.h" +#include "ash/wm/window_util.h" #include "ui/aura/window_tree_host.h" #include "ui/compositor/layer.h" +#include "ui/wm/core/coordinate_conversion.h" namespace remoting { -PointTransformer::PointTransformer() { - root_window_ = ash::Shell::GetPrimaryRootWindow(); - root_window_->AddObserver(this); - // Set the initial display rotation. - OnWindowTargetTransformChanging(root_window_, - root_window_->layer()->GetTargetTransform()); +namespace { + +gfx::PointF ConvertScreenDIPToWindowDIP(const aura::Window* window, + gfx::PointF location_in_screen_in_dip) { + gfx::PointF result(location_in_screen_in_dip); + wm::ConvertPointFromScreen(window, &result); + return result; } -PointTransformer::~PointTransformer() { - root_window_->RemoveObserver(this); +gfx::PointF ConvertWindowDIPToScreenDIP(const aura::Window* window, + gfx::PointF location_in_window_in_dip) { + gfx::PointF result(location_in_window_in_dip); + wm::ConvertPointToScreen(window, &result); + return result; } -void PointTransformer::OnWindowTargetTransformChanging( - aura::Window* window, - const gfx::Transform& new_transform) { - CHECK_EQ(window, root_window_); - - ui::Layer* layer = root_window_->layer(); - float scale = layer->device_scale_factor(); - - gfx::Transform to_device_pixels; - gfx::Transform to_dip; - - to_device_pixels.Scale(scale, scale); - to_dip.Scale(1 / scale, 1 / scale); - - // Use WindowTreeHost::GetRootTransform instead of |new_transform| because - // |new_transform| no longer contains rotation. The root transform contains - // a transform comprising a rotation and a translation, but it expects DIPs as - // input in DIPs and convert to device pixels. So we need to switch device - // pixels to DIPs then apply it. - gfx::Transform rotation = root_window_->GetHost()->GetRootTransform(); - - // Use GetInverseRootTransform instead of using root transform inverse. The - // two normally should be the same but GetInverseRootTransform() is - // constructed at the same time of root transform and has less rounding - // errors. It expect device pixels as input and convert to DIPs. So we need to - // switch to device pixels after applying it. - gfx::Transform inverse_rotation = - root_window_->GetHost()->GetInverseRootTransform(); - - // Matrix transformations are applied from right to left. See annotations. - // (2) (1) - root_to_screen_ = rotation * to_dip; - screen_to_root_ = to_device_pixels * inverse_rotation; +gfx::PointF ConvertWindowDIPtoWindowPixels( + const aura::Window* window, + gfx::PointF location_in_window_in_dip) { + gfx::PointF result(location_in_window_in_dip); + window->GetHost()->ConvertDIPToPixels(&result); + return result; } -gfx::PointF PointTransformer::ToScreenCoordinates( - const gfx::PointF& root_location) { - gfx::Point3F screen_location(root_location); - root_to_screen_.TransformPoint(&screen_location); - return screen_location.AsPointF(); +gfx::PointF ConvertWindowPixelsToWindowDIP( + const aura::Window* window, + gfx::PointF location_in_window_in_pixels) { + gfx::PointF result(location_in_window_in_pixels); + window->GetHost()->ConvertPixelsToDIP(&result); + return result; } -gfx::PointF PointTransformer::FromScreenCoordinates( - const gfx::PointF& screen_location) { - gfx::Point3F root_location(screen_location); - screen_to_root_.TransformPoint(&root_location); - return root_location.AsPointF(); +gfx::PointF ConvertWindowPixelsToScreenPixels( + const aura::Window* window, + gfx::PointF location_in_window_in_pixels) { + return location_in_window_in_pixels + + window->GetHost()->GetBoundsInPixels().OffsetFromOrigin(); +} + +} // namespace + +// static +gfx::PointF PointTransformer::ConvertScreenInDipToScreenInPixel( + gfx::PointF location_in_screen_in_dip) { + const aura::Window* window = ash::window_util::GetRootWindowAt( + gfx::ToRoundedPoint(location_in_screen_in_dip)); + + gfx::PointF location_in_window_in_dip = + ConvertScreenDIPToWindowDIP(window, location_in_screen_in_dip); + + gfx::PointF location_in_window_in_pixels = + ConvertWindowDIPtoWindowPixels(window, location_in_window_in_dip); + + gfx::PointF location_in_screen_in_pixel = + ConvertWindowPixelsToScreenPixels(window, location_in_window_in_pixels); + + return location_in_screen_in_pixel; +} + +// static +gfx::PointF PointTransformer::ConvertWindowInPixelToScreenInDip( + const aura::Window* window, + gfx::PointF location_in_window_in_pixels) { + gfx::PointF location_in_window_in_dip = + ConvertWindowPixelsToWindowDIP(window, location_in_window_in_pixels); + + gfx::PointF location_in_screen_in_dip = + ConvertWindowDIPToScreenDIP(window, location_in_window_in_dip); + + return location_in_screen_in_dip; } } // namespace remoting
diff --git a/remoting/host/chromeos/point_transformer.h b/remoting/host/chromeos/point_transformer.h index da1e3c1..636924f 100644 --- a/remoting/host/chromeos/point_transformer.h +++ b/remoting/host/chromeos/point_transformer.h
@@ -5,9 +5,7 @@ #ifndef REMOTING_HOST_CHROMEOS_POINT_TRANSFORMER_H_ #define REMOTING_HOST_CHROMEOS_POINT_TRANSFORMER_H_ -#include "ui/aura/window_observer.h" #include "ui/gfx/geometry/point_f.h" -#include "ui/gfx/geometry/transform.h" namespace aura { class Window; @@ -15,42 +13,61 @@ namespace remoting { -// A class that performs coordinate transformations between the root window -// coordinates and the native screen coordinates, according to the current -// display rotation settings. +// This class performs coordinate transformations between the different +// coordinate systems used in ChromeOS. // -// Root window coordinates are expressed relative to the top left corner of the -// root window whereas native screen coordinates are expressed relative to the -// top left corner of the frame buffer, which may not match the root window -// either in origin nor orientation. Both coordinate systems are always in -// device pixels. +// To understand the different coordinate systems, you must understand the +// following concepts: // -// For example, when the display is rotated by 90 deg, the pixel at root window -// coordinates (x, y) will have native screen coordinates (height - y, x). -class PointTransformer : public aura::WindowObserver { +// Screen vs window coordinates: +// * Window coordinates are relative to a given window. So 2 different +// windows both have a 0x0 coordinate. +// Because each physical display has its own root window, window +// coordinates can also be used to express coordinates relative to a +// display. +// * Screen coordinates are absolute. Each root window is placed at a +// different, non-overlapping place in the screen. This way screen +// coordinates are 'globally unique', meaning that they can uniquely +// identify any location in any root window. +// +// DIP vs pixels: +// * Pixel coordinates use the physical pixel location of windows/displays. +// This means a screen with physical resolution 3000x2000 will always have +// a size of 3000x2000 in pixel coordinates, even if the screen is rotated +// or uses a different scale factor (to make things look bigger). +// * DIP coordinates use Device-Independent-Pixels, which is something that +// can be changed in the software to make items on the screen look bigger +// or smaller. So a screen with physical resolution 3000x2000 and a scale +// factor of 2 will have a DIP resolution of 1500x1000. +// DIP coordinates also take rotation into account, so if the above screen +// is rotated 90 degrees in the software, it will have a DIP resolution of +// 1000x1500. +// +// +// These 2 concepts are orthogonal and can be combined, resulting in 4 different +// coordinate systems: +// * Screen DIP: Globally unique coordinates that take rotation and scale +// factor into account. This is the system the user intuitively expects, +// and what the user sees in the display settings. +// * Screen Pixel: Globally unique coordinates that represent the physical +// pixels of each display. This is what is used by the SystemInputInjector +// class. +// * Window DIP: Coordinates relative to a given window (display) that take +// rotation and scale factor into account. +// * Window Pixel: Coordinates relative to a given window (display) that +// match the physical pixels of the display. This is used by the event +// processing pipeline (i.e. the ui::PlatformEvent). +// +// All methods use floating points to minimize the rounding errors when +// transforming between the different coordinate systems. +class PointTransformer { public: - PointTransformer(); + static gfx::PointF ConvertScreenInDipToScreenInPixel( + gfx::PointF location_in_screen_in_dip); - PointTransformer(const PointTransformer&) = delete; - PointTransformer& operator=(const PointTransformer&) = delete; - - ~PointTransformer() override; - - // Converts from root window coordinates to native screen coordinates. - gfx::PointF ToScreenCoordinates(const gfx::PointF& window_location); - - // Converts from native screen coordinates to root window coordinates. - gfx::PointF FromScreenCoordinates(const gfx::PointF& screen_location); - - private: - // aura::WindowObserver interface. - void OnWindowTargetTransformChanging( - aura::Window* window, - const gfx::Transform& new_transform) override; - - aura::Window* root_window_; - gfx::Transform root_to_screen_; - gfx::Transform screen_to_root_; + static gfx::PointF ConvertWindowInPixelToScreenInDip( + const aura::Window* window, + gfx::PointF location_in_window_in_pixels); }; } // namespace remoting
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc index 8015c86f..b8d315a 100644 --- a/remoting/host/client_session.cc +++ b/remoting/host/client_session.cc
@@ -840,8 +840,14 @@ void ClientSession::SetMouseClampingFilter(const DisplaySize& size) { UpdateMouseClampingFilterOffset(); +#if BUILDFLAG(IS_CHROMEOS) + // ChromeOS uses Screen DIP coordinates to uniquely position all displays. + mouse_clamping_filter_.set_output_size(size.WidthAsDips(), + size.HeightAsDips()); +#else mouse_clamping_filter_.set_output_size(size.WidthAsPixels(), size.HeightAsPixels()); +#endif // BUILDFLAG(IS_CHROMEOS) switch (connection_->session()->config().protocol()) { case protocol::SessionConfig::Protocol::ICE:
diff --git a/remoting/host/input_injector_chromeos.cc b/remoting/host/input_injector_chromeos.cc index e30fff3..a7f0224 100644 --- a/remoting/host/input_injector_chromeos.cc +++ b/remoting/host/input_injector_chromeos.cc
@@ -9,6 +9,7 @@ #include <string> #include <utility> +#include "ash/display/window_tree_host_manager.h" #include "ash/shell.h" #include "base/bind.h" #include "base/callback_helpers.h" @@ -124,13 +125,11 @@ private: void SetLockStates(uint32_t states); + void InjectMouseMove(const MouseEvent& event); + bool hide_cursor_on_disconnect_ = false; std::unique_ptr<ui::SystemInputInjector> delegate_; std::unique_ptr<Clipboard> clipboard_; - - // Used to rotate the input coordinates appropriately based on the current - // display rotation settings. - std::unique_ptr<PointTransformer> point_transformer_; }; InputInjectorChromeos::Core::Core() = default; @@ -214,12 +213,20 @@ } else if (event.has_wheel_delta_y() || event.has_wheel_delta_x()) { delegate_->InjectMouseWheel(event.wheel_delta_x(), event.wheel_delta_y()); } else { - DCHECK(event.has_x() && event.has_y()); - delegate_->MoveCursorTo(point_transformer_->ToScreenCoordinates( - gfx::PointF(event.x(), event.y()))); + InjectMouseMove(event); } } +void InputInjectorChromeos::Core::InjectMouseMove(const MouseEvent& event) { + DCHECK(event.has_x() && event.has_y()); + gfx::PointF location_in_screen_in_dip = gfx::PointF(event.x(), event.y()); + gfx::PointF location_in_screen_in_pixels = + PointTransformer::ConvertScreenInDipToScreenInPixel( + location_in_screen_in_dip); + + delegate_->MoveCursorTo(location_in_screen_in_pixels); +} + void InputInjectorChromeos::Core::Start( std::unique_ptr<protocol::ClipboardStub> client_clipboard) { delegate_ = ui::OzonePlatform::GetInstance()->CreateSystemInputInjector(); @@ -238,7 +245,6 @@ // Implemented by remoting::ClipboardAura. clipboard_ = Clipboard::Create(); clipboard_->Start(std::move(client_clipboard)); - point_transformer_ = std::make_unique<PointTransformer>(); // If the cursor was hidden before we start injecting input then we should try // to restore its state when the remote user disconnects. The main scenario
diff --git a/remoting/host/input_monitor/local_pointer_input_monitor_chromeos.cc b/remoting/host/input_monitor/local_pointer_input_monitor_chromeos.cc index 6f97f52..b9c3a28 100644 --- a/remoting/host/input_monitor/local_pointer_input_monitor_chromeos.cc +++ b/remoting/host/input_monitor/local_pointer_input_monitor_chromeos.cc
@@ -7,6 +7,7 @@ #include <memory> #include <utility> +#include "ash/shell.h" #include "base/bind.h" #include "base/callback.h" #include "base/location.h" @@ -15,6 +16,7 @@ #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" #include "ui/events/event.h" #include "ui/events/event_constants.h" +#include "ui/events/event_target.h" #include "ui/events/event_utils.h" #include "ui/events/platform/platform_event_observer.h" #include "ui/events/platform/platform_event_source.h" @@ -66,10 +68,6 @@ // Used to send pointer event notifications. // Must be called on the |caller_task_runner_|. LocalInputMonitor::PointerMoveCallback on_pointer_move_; - - // Used to rotate the local pointer positions appropriately based on the - // current display rotation settings. - std::unique_ptr<PointTransformer> point_transformer_; }; // Task runner on which ui::events are received. @@ -103,7 +101,6 @@ // EventMatchers. (And if that doesn't work, maybe a PointerObserver.) if (ui::PlatformEventSource::GetInstance()) ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this); - point_transformer_ = std::make_unique<PointTransformer>(); } LocalPointerInputMonitorChromeos::Core::~Core() { @@ -132,13 +129,30 @@ void LocalPointerInputMonitorChromeos::Core::HandlePointerMove( const ui::PlatformEvent& event, ui::EventType type) { - auto position = gfx::PointF(ui::EventLocationFromNative(event)); - position = point_transformer_->FromScreenCoordinates(position); + ui::LocatedEvent* located_event = event->AsLocatedEvent(); + // The event we received has the location of the mouse in pixels + // *within the current display*. The event itself does not tell us what + // display the mouse is on (so the top-left of every display has coordinates + // 0x0 in the event). + // Luckily the cursor manager remembers the display the mouse is on. + const display::Display& current_display = + ash::Shell::Get()->cursor_manager()->GetDisplay(); + const aura::Window* window = + ash::Shell::Get()->GetRootWindowForDisplayId(current_display.id()); + + gfx::PointF location_in_window_in_pixels = located_event->location_f(); + + gfx::PointF location_in_screen_in_dip = + PointTransformer::ConvertWindowInPixelToScreenInDip( + window, location_in_window_in_pixels); + + gfx::Point pointer_position = gfx::ToRoundedPoint(location_in_screen_in_dip); caller_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(on_pointer_move_, - webrtc::DesktopVector(position.x(), position.y()), type)); + FROM_HERE, base::BindOnce(on_pointer_move_, + webrtc::DesktopVector(pointer_position.x(), + pointer_position.y()), + type)); } } // namespace
diff --git a/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc b/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc index a4511d3..b58b66f 100644 --- a/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc +++ b/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc
@@ -80,7 +80,7 @@ // DebugData service is needed only for profiling. #if BUILDFLAG(CLANG_PROFILING) - "fuchsia.debugdata.DebugData", + "fuchsia.debugdata.Publisher", #endif fuchsia::intl::PropertyProvider::Name_,
diff --git a/services/network/public/cpp/host_resolver_mojom_traits.cc b/services/network/public/cpp/host_resolver_mojom_traits.cc index 25f7e4e..6080518 100644 --- a/services/network/public/cpp/host_resolver_mojom_traits.cc +++ b/services/network/public/cpp/host_resolver_mojom_traits.cc
@@ -4,8 +4,10 @@ #include "services/network/public/cpp/host_resolver_mojom_traits.h" +#include "base/values.h" #include "mojo/public/cpp/base/time_mojom_traits.h" #include "net/dns/public/dns_over_https_config.h" +#include "net/dns/public/dns_over_https_server_config.h" #include "net/dns/public/host_resolver_source.h" #include "net/dns/public/mdns_listener_update_type.h" #include "net/dns/public/resolve_error_info.h" @@ -77,18 +79,33 @@ } // static +bool StructTraits<network::mojom::DnsOverHttpsServerConfigDataView, + net::DnsOverHttpsServerConfig>:: + Read(network::mojom::DnsOverHttpsServerConfigDataView data, + net::DnsOverHttpsServerConfig* out_server) { + std::string server_template; + if (!data.ReadServerTemplate(&server_template)) + return false; + net::DnsOverHttpsServerConfig::Endpoints endpoints; + if (!data.ReadEndpoints(&endpoints)) + return false; + auto server = net::DnsOverHttpsServerConfig::FromString( + std::move(server_template), std::move(endpoints)); + if (!server.has_value()) + return false; + *out_server = std::move(server.value()); + return true; +} + +// static bool StructTraits<network::mojom::DnsOverHttpsConfigDataView, net::DnsOverHttpsConfig>:: Read(network::mojom::DnsOverHttpsConfigDataView data, net::DnsOverHttpsConfig* out_config) { - std::vector<std::string> representation; - if (!data.ReadServers(&representation)) + std::vector<net::DnsOverHttpsServerConfig> servers; + if (!data.ReadServers(&servers)) return false; - absl::optional<net::DnsOverHttpsConfig> config = - net::DnsOverHttpsConfig::FromStrings(std::move(representation)); - if (!config.has_value()) - return false; - *out_config = std::move(config.value()); + *out_config = net::DnsOverHttpsConfig(std::move(servers)); return true; }
diff --git a/services/network/public/cpp/host_resolver_mojom_traits.h b/services/network/public/cpp/host_resolver_mojom_traits.h index dadfb39..849a0864 100644 --- a/services/network/public/cpp/host_resolver_mojom_traits.h +++ b/services/network/public/cpp/host_resolver_mojom_traits.h
@@ -19,6 +19,7 @@ #include "net/base/ip_endpoint.h" #include "net/dns/public/dns_config_overrides.h" #include "net/dns/public/dns_over_https_config.h" +#include "net/dns/public/dns_over_https_server_config.h" #include "net/dns/public/dns_query_type.h" #include "net/dns/public/host_resolver_source.h" #include "net/dns/public/mdns_listener_update_type.h" @@ -36,12 +37,28 @@ network::mojom::OptionalSecureDnsMode mode); template <> +class StructTraits<network::mojom::DnsOverHttpsServerConfigDataView, + net::DnsOverHttpsServerConfig> { + public: + static base::StringPiece server_template( + const net::DnsOverHttpsServerConfig& server) { + return server.server_template(); + } + static const net::DnsOverHttpsServerConfig::Endpoints& endpoints( + const net::DnsOverHttpsServerConfig& server) { + return server.endpoints(); + } + static bool Read(network::mojom::DnsOverHttpsServerConfigDataView data, + net::DnsOverHttpsServerConfig* out_config); +}; + +template <> class StructTraits<network::mojom::DnsOverHttpsConfigDataView, net::DnsOverHttpsConfig> { public: - static std::vector<base::StringPiece> servers( + static const std::vector<net::DnsOverHttpsServerConfig>& servers( const net::DnsOverHttpsConfig& doh_config) { - return doh_config.ToStrings(); + return doh_config.servers(); } static bool Read(network::mojom::DnsOverHttpsConfigDataView data, net::DnsOverHttpsConfig* out_config);
diff --git a/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc b/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc index 18cb2748..bfd63e7c 100644 --- a/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc +++ b/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc
@@ -6,8 +6,10 @@ #include "mojo/public/cpp/base/time_mojom_traits.h" #include "mojo/public/cpp/test_support/test_utils.h" +#include "net/base/ip_address.h" #include "net/base/net_errors.h" #include "net/dns/public/dns_over_https_config.h" +#include "net/dns/public/dns_over_https_server_config.h" #include "services/network/public/cpp/ip_address_mojom_traits.h" #include "services/network/public/cpp/ip_endpoint_mojom_traits.h" #include "services/network/public/mojom/host_resolver.mojom.h" @@ -74,6 +76,23 @@ EXPECT_EQ(original, deserialized); } +TEST(HostResolverMojomTraitsTest, DnsOverHttpsServerConfig_Roundtrip) { + net::DnsOverHttpsServerConfig::Endpoints endpoints{ + {{192, 0, 2, 1}, + {0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}, + {{192, 0, 2, 2}, + {0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}}}; + auto original = *net::DnsOverHttpsServerConfig::FromString( + "https://example.com/", endpoints); + + net::DnsOverHttpsServerConfig deserialized; + EXPECT_TRUE( + mojo::test::SerializeAndDeserialize<mojom::DnsOverHttpsServerConfig>( + original, deserialized)); + + EXPECT_EQ(original, deserialized); +} + TEST(HostResolverMojomTraitsTest, ResolveErrorInfo) { net::ResolveErrorInfo original; original.error = net::ERR_NAME_NOT_RESOLVED;
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn index a84df993..ec490ec 100644 --- a/services/network/public/mojom/BUILD.gn +++ b/services/network/public/mojom/BUILD.gn
@@ -979,6 +979,10 @@ cpp = "::net::DnsConfigOverrides" }, { + mojom = "network.mojom.DnsOverHttpsServerConfig" + cpp = "::net::DnsOverHttpsServerConfig" + }, + { mojom = "network.mojom.DnsOverHttpsConfig" cpp = "::net::DnsOverHttpsConfig" },
diff --git a/services/network/public/mojom/host_resolver.mojom b/services/network/public/mojom/host_resolver.mojom index 8e03598..7ca8f82 100644 --- a/services/network/public/mojom/host_resolver.mojom +++ b/services/network/public/mojom/host_resolver.mojom
@@ -6,15 +6,20 @@ import "mojo/public/mojom/base/time.mojom"; import "services/network/public/mojom/address_list.mojom"; +import "services/network/public/mojom/ip_address.mojom"; import "services/network/public/mojom/ip_endpoint.mojom"; import "services/network/public/mojom/network_isolation_key.mojom"; import "services/network/public/mojom/network_param.mojom"; import "services/network/public/mojom/request_priority.mojom"; +struct DnsOverHttpsServerConfig { + string server_template; + array<array<network.mojom.IPAddress>> endpoints; +}; + // The DNS over HTTPS configuration, containing zero or more servers. struct DnsOverHttpsConfig { - // String representation of each server. - array<string> servers; + array<DnsOverHttpsServerConfig> servers; }; // The secure DNS mode specifies what types of lookups (secure/insecure) should
diff --git a/storage/browser/blob/blob_storage_context.cc b/storage/browser/blob/blob_storage_context.cc index 147e2adc..bdab234 100644 --- a/storage/browser/blob/blob_storage_context.cc +++ b/storage/browser/blob/blob_storage_context.cc
@@ -223,14 +223,6 @@ ? TransportQuotaType::MEMORY : TransportQuotaType::FILE; - uint64_t total_memory_needed = - content->copy_quota_needed() + - (transport_quota_type == TransportQuotaType::MEMORY - ? content->transport_quota_needed() - : 0); - UMA_HISTOGRAM_COUNTS_1M("Storage.Blob.TotalUnsharedSize", - total_memory_needed / 1024); - std::vector<scoped_refptr<BlobDataItem>> items_needing_timestamp; std::vector<base::FilePath> file_paths_needing_timestamp; for (auto& item : entry->items_) {
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json index 2faa96a..e7bd799e 100644 --- a/testing/buildbot/chrome.json +++ b/testing/buildbot/chrome.json
@@ -4448,6 +4448,7 @@ "args": [ "--git-revision=${got_revision}" ], + "experiment_percentage": 100, "isolate_name": "variations_smoke_tests", "merge": { "args": [],
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index dbe932a..32f47373 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -5881,21 +5881,21 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5032.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5033.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5032.0", + "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5033.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v103.0.5032.0", - "revision": "version:103.0.5032.0" + "location": "lacros_version_skew_tests_v103.0.5033.0", + "revision": "version:103.0.5033.0" } ], "dimension_sets": [ @@ -6023,21 +6023,21 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5032.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5033.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5032.0", + "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5033.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v103.0.5032.0", - "revision": "version:103.0.5032.0" + "location": "lacros_version_skew_tests_v103.0.5033.0", + "revision": "version:103.0.5033.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index f0da763..1b602dd5 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -33511,7 +33511,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -33565,7 +33565,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -35549,7 +35549,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -35602,7 +35602,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -35655,7 +35655,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -41072,7 +41072,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -41125,7 +41125,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -41178,7 +41178,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -41231,7 +41231,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -41284,7 +41284,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -41337,7 +41337,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -49475,7 +49475,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -49531,7 +49531,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -49587,7 +49587,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -49643,7 +49643,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -49699,7 +49699,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -49755,7 +49755,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -55979,7 +55979,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -58241,7 +58241,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -58296,7 +58296,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -61887,7 +61887,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -61940,7 +61940,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -61993,7 +61993,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -62046,7 +62046,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -67419,7 +67419,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -67472,7 +67472,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -67525,7 +67525,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -67578,7 +67578,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -67631,7 +67631,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -67684,7 +67684,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -75877,7 +75877,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -75930,7 +75930,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -75983,7 +75983,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -76036,7 +76036,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -76089,7 +76089,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -76142,7 +76142,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -90695,21 +90695,21 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5032.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5033.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5032.0", + "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5033.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v103.0.5032.0", - "revision": "version:103.0.5032.0" + "location": "lacros_version_skew_tests_v103.0.5033.0", + "revision": "version:103.0.5033.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -90812,21 +90812,21 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5032.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5033.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5032.0", + "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5033.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v103.0.5032.0", - "revision": "version:103.0.5032.0" + "location": "lacros_version_skew_tests_v103.0.5033.0", + "revision": "version:103.0.5033.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -92204,20 +92204,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5032.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5033.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5032.0", + "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5033.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v103.0.5032.0", - "revision": "version:103.0.5032.0" + "location": "lacros_version_skew_tests_v103.0.5033.0", + "revision": "version:103.0.5033.0" } ], "dimension_sets": [ @@ -92346,20 +92346,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5032.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5033.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5032.0", + "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5033.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v103.0.5032.0", - "revision": "version:103.0.5032.0" + "location": "lacros_version_skew_tests_v103.0.5033.0", + "revision": "version:103.0.5033.0" } ], "dimension_sets": [ @@ -93901,20 +93901,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5032.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5033.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5032.0", + "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5033.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v103.0.5032.0", - "revision": "version:103.0.5032.0" + "location": "lacros_version_skew_tests_v103.0.5033.0", + "revision": "version:103.0.5033.0" } ], "dimension_sets": [ @@ -94043,20 +94043,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5032.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5033.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5032.0", + "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5033.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v103.0.5032.0", - "revision": "version:103.0.5032.0" + "location": "lacros_version_skew_tests_v103.0.5033.0", + "revision": "version:103.0.5033.0" } ], "dimension_sets": [ @@ -94800,20 +94800,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5032.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5033.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "interactive_ui_tests Lacros version skew testing ash 103.0.5032.0", + "name": "interactive_ui_tests Lacros version skew testing ash 103.0.5033.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v103.0.5032.0", - "revision": "version:103.0.5032.0" + "location": "lacros_version_skew_tests_v103.0.5033.0", + "revision": "version:103.0.5033.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index d22d0a6..2eaf6e9 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -14105,7 +14105,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -14159,7 +14159,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -19038,7 +19038,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -19092,7 +19092,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -19146,7 +19146,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -19200,7 +19200,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -21214,7 +21214,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -21267,7 +21267,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -21320,7 +21320,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" }, @@ -21373,7 +21373,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 + "shards": 5 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/" },
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index 1f4be2c..a20da35 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -1022,7 +1022,9 @@ ], "isolated_scripts": [ { - "args": [], + "args": [ + "--arch=amd64" + ], "isolate_name": "resource_sizes_lacros_chrome", "merge": { "script": "//tools/perf/process_perf_results.py"
diff --git a/testing/buildbot/filters/fuchsia.browser_tests.filter b/testing/buildbot/filters/fuchsia.browser_tests.filter index e5df093..a9dcdd4d 100644 --- a/testing/buildbot/filters/fuchsia.browser_tests.filter +++ b/testing/buildbot/filters/fuchsia.browser_tests.filter
@@ -1,27 +1,9 @@ --AccessContextAuditBrowserTest.CheckSessionOnly --AccessContextAuditBrowserTest.MultipleAccesses --AccessContextAuditBrowserTest.RemoveHistory --AccessContextAuditBrowserTest.RemoveRecords --AccessContextAuditBrowserTest.TabClosed --AccessContextAuditBrowserTest.TreeModelDeletion --AccessContextAuditSessionRestoreBrowserTest.RestoreSession -AccuracyTipBubbleViewBrowserTest.SurveyShownAfterShowingTip --AccuracyTipBubbleViewDialogBrowserTest.InvokeUi_default --AccuracyTipBubbleViewDialogBrowserTest.InvokeUi_ignore_button -ActivityLogApiTest.TriggerEvent -All/BrowsingDataRemoverBrowserTestP.WebSqlDeletion/0 -All/BrowsingDataRemoverBrowserTestP.WebSqlDeletion/1 -All/BrowsingDataRemoverBrowserTestP.WebSqlIncognitoDeletion/0 -All/BrowsingDataRemoverBrowserTestP.WebSqlIncognitoDeletion/1 --All/CastV2PerformanceTest.Performance/1 --All/CastV2PerformanceTest.Performance/2 --All/CastV2PerformanceTest.Performance/3 --All/CastV2PerformanceTest.Performance/4 --All/CastV2PerformanceTest.Performance/5 --All/ChromeBrowsingDataLifetimeManagerScheduledRemovalTest.KeepsOtherTabData/0 --All/ChromeBrowsingDataLifetimeManagerScheduledRemovalTest.KeepsOtherWindowData/0 --All/ChromeBrowsingDataLifetimeManagerScheduledRemovalTest.SiteData/0 --All/ChromeBrowsingDataLifetimeManagerScheduledRemovalTest.SiteData/1 -All/ChromeMultiProfileStartupBrowserTestBase.PostProfileInitInvocation/1 -All/ChromeMultiProfileStartupBrowserTestBase.PostProfileInitInvocation/3 -All/CryptotokenBrowserTest.SignWithEnterprisePolicyDoesNotShowPrompt/0 @@ -32,6 +14,338 @@ -All/CryptotokenBrowserTest.SignWithOriginTrialInCrossOriginIframeDoesNotShowPrompt/1 -All/DeclarativeNetRequestBrowserTest.PacRequestsBypassRules/0 -All/DeclarativeNetRequestBrowserTest.PacRequestsBypassRules/1 +-All/MediaEngagementAutoplayBrowserTest.PreloadedDataAndHighVisits/0 +-All/MediaEngagementAutoplayBrowserTest.PreloadedDataAndHighVisits/1 +-All/MediaEngagementAutoplayBrowserTest.UsePreloadedData_Allowed/0 +-All/MediaEngagementAutoplayBrowserTest.UsePreloadedData_Allowed/1 +-All/MediaEngagementAutoplayBrowserTest.UsePreloadedData_Denied/0 +-All/MediaEngagementAutoplayBrowserTest.UsePreloadedData_Denied/1 +-All/MediaHistoryBrowserTest.RecordWatchtime_VideoOnly/0 +-All/MediaHistoryBrowserTest.DoNotRecordWatchtime_Muted/2 +-All/PermissionPromptBubbleViewBrowserTest.ActiveTabClosedAfterRendererCrashesWithPendingPermissionRequest/0 +-All/PermissionPromptBubbleViewBrowserTest.ActiveTabClosedAfterRendererCrashesWithPendingPermissionRequest/1 +-All/PrintBackendPrintBrowserTest.UpdatePrintSettings/2 +-All/PrintBackendPrintBrowserTestService.StartPrinting/0 +-All/PrintBackendPrintBrowserTestService.StartPrinting/1 +-All/PrintBackendPrintBrowserTestService.StartPrintingSpoolingSharedMemoryError/0 +-All/PrintBackendPrintBrowserTestService.StartPrintingSpoolingSharedMemoryError/1 +-All/ReportingBrowserTest.CrashReportUnresponsive/1 +-AllForms/FormStructureBrowserTest.DataDrivenHeuristics/153 +-AppSessionRestoreTest.RestoreAppMinimized +-AppSessionRestoreTest.RestoreMaximizedApp +-AppSettingsAppTest.All +-AppWindowApiTest.OnMaximizedEvent +-AppWindowApiTest.OnMinimizedEvent +-AppWindowApiTest.OnRestoredEvent +-BackForwardCacheSiteDetailsBrowserTest.MemoryDetailsForBackForwardCache +-BrowserTest.FaviconChange +-BrowserViewTest.GetAccessibleTabModalDialogTitle +-BrowsingDataRemoverBrowserTest.Database +-BrowsingDataRemoverBrowserTest.SessionOnlyStorageRemoved +-BrowsingDataRemoverBrowserTest.StorageRemovedFromDisk +-ChromeAcceptHeaderTest.Check +-ChromeBackForwardCacheBrowserTest.DoNotShowSameSiteSubframeInTaskManager +-ChromeBackForwardCacheBrowserTest.ShowCrossSiteOOPIFInTaskManager +-ChromeBackForwardCacheBrowserTest.ShowMainFrameInTaskManager +-ChromeBrowserCloudManagementEnrollmentTest/ChromeBrowserCloudManagementEnrollmentTest.Test/1 +-ChromeBrowserCloudManagementEnrollmentTest/ChromeBrowserCloudManagementEnrollmentTest.Test/3 +-ChromeMimeHandlerViewTest.ActivatePostMessageSupportOnce +-ChromeMimeHandlerViewTest.BackgroundPage +-ChromeMimeHandlerViewTest.Basic +-ChromeMimeHandlerViewTest.BeforeUnloadEnabled_WithUserActivation +-ChromeMimeHandlerViewTest.BeforeUnloadEnabled_WithoutUserActivation +-ChromeMimeHandlerViewTest.BeforeUnload_NoDialog +-ChromeMimeHandlerViewTest.BeforeUnload_ShowDialog +-ChromeMimeHandlerViewTest.DataUrl +-ChromeMimeHandlerViewTest.DoNotLoadInSandboxedFrame +-ChromeMimeHandlerViewTest.EmbedWithInitialCrossOriginFrame +-ChromeMimeHandlerViewTest.EmbedWithInitialFrameAcceptBeforeUnloadDialog +-ChromeMimeHandlerViewTest.Embedded +-ChromeMimeHandlerViewTest.EmbeddedDataUrlEmbed +-ChromeMimeHandlerViewTest.EmbeddedDataUrlLong +-ChromeMimeHandlerViewTest.EmbeddedDataUrlObject +-ChromeMimeHandlerViewTest.EmbeddedThenPrint +-ChromeMimeHandlerViewTest.EmbedderFrameRemovedNoCrash +-ChromeMimeHandlerViewTest.Iframe +-ChromeMimeHandlerViewTest.MimeHandlerViewInDisplayNoneFrameForGoogleApps +-ChromeMimeHandlerViewTest.NonAsciiHeaders +-ChromeMimeHandlerViewTest.PostMessage +-ChromeMimeHandlerViewTest.RejectPointLock +-ChromeMimeHandlerViewTest.SingleRequest +-ChromeMimeHandlerViewTest.TargetBlankAnchor +-ChromeMojoProxyResolverFactoryBrowserTest.DestroyAndCreateService +-ChromeMojoProxyResolverFactoryBrowserTest.ServiceLifecycle +-ChromeNavigationBrowserTest.CrossSiteRedirectionToPDF +-ChromeNavigationBrowserTestWithMobileEmulation.CrossSiteRedirectionToPDFWithMobileEmulation +-ChromeNavigationBrowserTestWithMobileEmulation.NavigateToPDFWithMobileEmulation +-ChromePasswordProtectionServiceSyncBrowserTest.GSuitePasswordAlertMode +-ChromeSitePerProcessPDFTest.EmbeddedPDFInsideCrossOriginFrame +-ChromeSitePerProcessTest.PopupWindowFocus +-ChromeURLDataManagerWebUITrustedTypesTest.NoTrustedTypesViolation/chrome___browser_switch +-ChromeURLDataManagerWebUITrustedTypesTest.NoTrustedTypesViolation/chrome___nacl +-ChromeURLDataManagerWebUITrustedTypesTest.NoTrustedTypesViolation/chrome___sandbox +-ClientHintsBrowserTest.SwitchAcceptCHInvalid +-ClientHintsBrowserTest.SwitchAppliesStorage +-ClientHintsBrowserTest.SwitchAppliesStorageOneOrigin +-ClientHintsBrowserTest.SwitchNotJson +-ClientHintsBrowserTest.SwitchOriginNotSecure +-ContentAnalysisDelegateBlockingSettingBrowserTest.BlockLargeFiles/0 +-ContentAnalysisDelegateBlockingSettingBrowserTest.BlockLargeFiles/1 +-ContentAnalysisDelegateBlockingSettingBrowserTest.BlockLargeFiles/2 +-ContentAnalysisDelegateBlockingSettingBrowserTest.BlockLargeFiles/3 +-ContextMenuBrowserTest.OpenProfileNoneReferrer +-CookiePolicyBrowserTest.NestedFirstPartyIFrameStorageForFrame +-CorbAndCorsExtensionBrowserTest.ContentScriptVsHostBlockedByPolicy_AllowedTextResource +-CorbAndCorsExtensionBrowserTest.ContentScriptVsHostBlockedByPolicy_NoSniffXml +-CorbAndCorsExtensionBrowserTest.ContentScript_CorsAllowedByServer_NoPermissionToTarget +-CorbAndCorsExtensionBrowserTest.ContentScript_CorsIgnoredByServer_NoPermissionToTarget +-CorbAndCorsExtensionBrowserTest.ExtensionWithNoHttpPermissions +-CorbAndCorsExtensionBrowserTest.FromProgrammaticContentScript_AllowedAfterSniffing +-CorbAndCorsExtensionBrowserTest.FromProgrammaticContentScript_AllowedTextResource +-CorbAndCorsExtensionBrowserTest.FromProgrammaticContentScript_AllowedTextResource_SubdomainPermissions +-CorbAndCorsExtensionBrowserTest.FromProgrammaticContentScript_SameOrigin +-CorbAndCorsExtensionBrowserTest.FromProgrammaticContentScript_UnloadedExtension +-CrExtensionsA11yTestWithMultipleExensions.WithExtensions_scope_attr_valid +-CrExtensionsA11yTestWithMultipleExensions.WithExtensions_table_fake_caption +-CrSettingsPeoplePageTest.All +-CrSettingsSecurityPageTest.All +-CrossProfileDebuggerApiTest.Attach +-CrossProfileDebuggerApiTest.GetTargets +-DebuggerExtensionApiTest.AttachToPdf +-DestroyProfileOnBrowserClose/ProfileHelperTestWithDestroyProfile.DeleteInactiveProfile/0 +-DestroyProfileOnBrowserClose/ProfileHelperTestWithDestroyProfile.DeleteInactiveProfile/1 +-DestroyProfileOnBrowserClose/ProfileManagerBrowserTest.DeleteAllProfiles/0 +-DestroyProfileOnBrowserClose/ProfileManagerBrowserTest.DeleteAllProfiles/1 +-DestroyProfileOnBrowserClose/ProfileManagerBrowserTest.DeleteInactiveProfile/0 +-DestroyProfileOnBrowserClose/ProfileManagerBrowserTest.DeleteInactiveProfile/1 +-DestroyProfileOnBrowserClose/ProfileManagerBrowserTest.EphemeralProfile/0 +-DestroyProfileOnBrowserClose/ProfileManagerBrowserTest.EphemeralProfile/1 +-DevToolsTest.TestDispatchKeyEventShowsAutoFill +-DiceManageAccountBrowserTest.ClearManagedProfileOnStartup +-DiceWebSigninInterceptionBubbleBrowserTest.ProfileKeepAlive +-DownloadTest.DownloadErrorReadonlyFolder +-DownloadTestSplitCacheEnabled.SaveMainFramePdfFromContextMenu_IsolationInfo +-DownloadTestSplitCacheEnabled.SaveSubframePdfFromContextMenu_IsolationInfo +-DownloadTestSplitCacheEnabled.SaveSubframePdfFromPdfUI_IsolationInfo +-EncryptedMediaSupportedTypesClearKeyTest.Video_MP4 +-EncryptedMediaSupportedTypesClearKeyTest.Video_WebM +-EncryptedMediaSupportedTypesExternalClearKeyTest.EncryptionScheme +-EncryptedMediaSupportedTypesExternalClearKeyTest.Robustness +-EncryptedMediaSupportedTypesExternalClearKeyTest.SessionType +-ExtensionApiTabTest.UpdateWindowResize +-ExtensionApiTest.FontSettings +-ExtensionApiTest.FontSettingsIncognito +-ExtensionApiTest.Storage +-ExtensionApiTest.TemporaryAddressSpoof +-ExtensionBackForwardCacheBrowserTest.StorageCallbackEvicts +-ExtensionDialogTest.TextInputViaKeyEvent +-ExtensionWebRequestApiTest.WebRequestPacRequestProtection +-ExtensionWebRequestApiTest.WebSocketRequestOnWorker +-ExtensionWebstoreGetWebGLStatusTest.Allowed +-ExtensionWindowCreateTest.AcceptState +-ExternalProtocolDialogBrowserTest.TestFocus +-ExtractorBrowserTest.ExtractBigFile +-FedCmAccountSelectionViewBrowserTest.ShowAndVerifyUi +-FencedFrameSiteDetailsBrowserTest.MemoryDetailsForFencedFrame +-FetchBehaviorTests/ContentVerifierHashTest.FetchFailureWithDefaultResourceExtension/1 +-FileSystemApiTest.FileSystemApiRetainDirectoryEntry +-FolderUploadConfirmationViewTest.InitiallyFocusesCancel +-HistoryManipulationInterventionBrowserTest.PDFDoNotSkipOnBackForwardDueToUserGesture +-HistoryManipulationInterventionBrowserTest.PDFSkipOnBackForwardNoUserGesture +-HttpProxyScriptBrowserTest.Verify +-I18nProcessTest.All +-IconLoaderBrowserTest.LoadGroup +-IconModuleTest.All +-InProcess/ChromeNetworkServiceBrowserTest.EncryptedCookies/0 +-InProcessBrowserTest.RunsScheduledLayoutOnAnchoredBubbles +-IncognitoBrowsingDataBrowserTest.Database +-IncognitoBrowsingDataBrowserTest.StorageDoesntWriteToDisk +-IncognitoBrowsingDataBrowserTest.WebSqlDeletion +-InlineLoginHelperBrowserTest.SigninCreatesSyncStarter1 +-InlineLoginHelperBrowserTest.SigninCreatesSyncStarter2 +-InlineLoginHelperBrowserTest.SigninCreatesSyncStarter4 +-InlineLoginHelperBrowserTest.UntrustedSigninDialogCancel +-InlineLoginHelperBrowserTest.WithAuthCode +-IntentChipButtonAppIconBrowserTest.ShowsAppIconInChip +-IntentChipButtonBrowserTest.IconVisibilityAfterTabSwitching +-IntentChipButtonBrowserTest.NavigationToInScopeLinkShowsIntentChip +-IntentChipButtonBrowserTest.NavigationToOutOfScopeLinkDoesNotShowsIntentChip +-IntentChipButtonBrowserTest.ShowsIntentChipCollapsed +-IntentChipButtonBrowserTest.ShowsIntentPickerWhenMultipleApps +-IntentChipButtonIPHBubbleBrowserTest.ShowAndCloseIPH +-IsolatedAppTest.SessionStorage +-LoadingPredictorBrowserTestWithProxy.PrepareForPageLoadWithPrediction +-LoadingPredictorBrowserTestWithProxy.PrepareForPageLoadWithoutPrediction +-MediaEngagementBrowserTest.RecordSingleVisitOnSameOrigin +-MediaEngagementBrowserTest.SessionNewTabNavigateSameURLWithOpener_Typed +-MediaEngagementPreloadBrowserTest.EnsureSingletonListIsLoaded +-MessagingApiTest.Messaging +-MyIpAddressProxyScriptBrowserTest.Verify +-NetworkingPrivateServiceClientApiTest.OnNetworkListChangedEvent +-NetworkingPrivateServiceClientApiTest.OnNetworksChangedEventConnect +-NetworkingPrivateServiceClientApiTest.OnNetworksChangedEventDisconnect +-NetworkingPrivateServiceClientApiTest.RequestNetworkScan +-NetworkConnectionTrackerBrowserTest.SimulateNetworkServiceCrash +-OmniboxPopupContentsViewTest.ClickOmnibox +-OmniboxPopupContentsViewTest.PopupMatchesLocationBarBackground +-OutOfMemoryReporterPrerenderBrowserTest.NotReportedOnPrerenderPage +-OutOfMemoryReporterPrerenderBrowserTest.ReportedOnActivatedPrerenderPage +-OutOfProcess/ChromeNetworkServiceBrowserTest.EncryptedCookies/0 +-PaintPreviewCompositorBrowserTest.CompositorCreate +-PaintPreviewCompositorBrowserTest.KillWithActiveCompositors +-PaintPreviewCompositorBrowserTest.MultipleCompositorCreate +-PaintPreviewCompositorBrowserTest.TestInitializationSuccess +-PolicyPrefsTestCoverageTest.AllPoliciesHaveATestCase +-PortalOutOfMemoryReporterBrowserTest.ReportForActivatedPortal +-PrerenderSiteDetailsBrowserTest.MemoryDetailsForPrerender +-PrintBackendPrintBrowserTestSandboxedService.StartPrintingAccessDenied +-PrintBackendPrintBrowserTestSandboxedService.StartPrintingDocumentDoneAccessDenied +-PrintBackendPrintBrowserTestSandboxedService.StartPrintingRenderDocumentAccessDenied +-PrintBackendPrintBrowserTestSandboxedService.StartPrintingRepeatedAccessDenied +-PrivacyBudgetFieldtrialConfigTest.LoadsSettingsFromFieldTrialConfig +-PrivateNetworkAccessWithFeatureEnabledBrowserTest.DoesNotRecordAddressSpaceFeatureForBlockedRequests +-ProcessManagementTest.ProcessOverflow +-ProcessMemoryMetricsEmitterTest.FetchAndEmitMetricsWithExtensions +-ProcessMemoryMetricsEmitterTest.FetchDuringTrace +-ProcessMemoryMetricsEmitterTest.ForegroundAndBackgroundPages +-ProfileCustomizationBubbleBrowserTest.IPH +-ProfileHelperTest.OpenNewWindowForProfile +-ProfileMenuViewExtensionsTest.CloseIPH +-ProfileWindowBrowserTest.OpenBrowserWindowForProfileWithSigninRequired +-ProxyBrowserTest.BasicAuthWSConnect +-ProxyBrowserTest.ProxyAuthHTTPS +-ProxySettingsApiTest.ProxyEventsParseError +-RecordLanguagesMetricsBrowserTest.ContentLanguageEmpty +-RecordLanguagesMetricsBrowserTest.ContentLanguageMatchTopMostAcceptLanguage +-RecordLanguagesMetricsBrowserTest.ContentLanguageMatchesAnyAcceptLanguage +-RecordLanguagesMetricsBrowserTest.IframeBothParentAndChildContentLanguageIsEmpty +-RecordLanguagesMetricsBrowserTest.IframeContentLanguageChildDifferFromParent +-RecordLanguagesMetricsBrowserTest.IframeParentAndChildContentLanguageAreStar +-RecordLanguagesMetricsBrowserTest.IframeParentAndChildContentLanguageHasSameValue +-RecordLanguagesMetricsBrowserTest.IframeParentContentLanguageIsEmptyAndChildContentLanguageHasValue +-RecordLanguagesMetricsBrowserTest.IframeParentContentLanuageIsStarAndChildContentLanguageHasValue +-RecordLanguagesMetricsBrowserTest.IframeParentHasConentLanguageAndChildContentLanguageIsEmpty +-RecordLanguagesMetricsBrowserTest.LargeAcceptLanguageList +-RemoteCopyBrowserTest.ImageUrl +-RemoteCopyBrowserTest.Text +-RemoteCopyBrowserTest.TextThenImageUrl +-RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.RunTest/0 +-RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.RunTest/1 +-RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.RunTest/2 +-RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.RunTest/3 +-RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.RunTest/4 +-RssLinksFetcherTest.FetchSuccessfulFromBody +-RssLinksFetcherTest.FetchSuccessfulFromHead +-SafetyTipPageInfoBubbleViewDigitalAssetLinksBrowserTest.NoShowOnDigitalAssetLinkMatch +-SaveCardBubbleViewsSyncTransportFullFormBrowserTest.Local_TransportMode_InfoTextIconDoesNotExist +-SaveCardBubbleViewsSyncTransportFullFormBrowserTest.Upload_TransportMode_ClickingSaveClosesBubble +-SaveCardBubbleViewsSyncTransportFullFormBrowserTest.Upload_TransportMode_InfoTextIconExists +-SaveCardBubbleViewsSyncTransportFullFormBrowserTest.Upload_TransportMode_RequestedCardholderNameTextfieldIsPrefilledWithFocusName +-SavePackageDeepScanningBrowserTest.Allowed +-SavePackageDeepScanningBrowserTest.Blocked +-SavePackageDeepScanningBrowserTest.DiscardAfterWarning +-SavePackageDeepScanningBrowserTest.KeepAfterWarning +-SavePackageDeepScanningBrowserTest.OpenNow +-SaveUpdateAddressProfileBubbleControllerImplTest.CloseTabWhileBubbleIsOpen +-ScriptingAPITest.NestedWebContents +-ServiceWorkerTest.MimeHandlerView +-SessionRestorePageLoadMetricsBrowserTest.RestoreForeignSession +-SessionRestoreTest.RestoreAfterClosingTabbedBrowserWithAppAndLaunching +-SigninInterceptFirstRunExperienceDialogBrowserTest.AcceptSync +-SigninInterceptFirstRunExperienceDialogBrowserTest.AcceptSync_ExtensionTheme +-SigninInterceptFirstRunExperienceDialogBrowserTest.AcceptSync_SyncPassphrase +-SigninInterceptFirstRunExperienceDialogBrowserTest.DeclineSync +-SigninInterceptFirstRunExperienceDialogBrowserTest.ForcedIntercept +-SigninInterceptFirstRunExperienceDialogBrowserTest.ForcedIntercept_ProfileColorPolicy +-SigninInterceptFirstRunExperienceDialogBrowserTest.ProfileColorPolicy +-SigninInterceptFirstRunExperienceDialogBrowserTest.SyncDisabled +-SigninInterceptFirstRunExperienceDialogBrowserTest.SyncSettings +-SingleProcessBrowserTest.Test +-SpellcheckServiceBrowserTest.DeleteCorruptedBDICT +-StartupMetricsTest.ReportsValues +-SyncAwareCounterTest.AutofillCounter +-SyncAwareCounterTest.HistoryCounter +-SyncAwareCounterTest.PasswordCounter +-TabHoverCardBubbleViewBrowserTest.WidgetNotVisibleOnMousePressAfterTabFocus +-TabHoverCardBubbleViewBrowserTest.WidgetVisibleOnKeyPressAfterTabFocus +-TabHoverCardBubbleViewBrowserTest.WidgetVisibleOnTabCloseButtonFocusAfterTabFocus +-TabHoverCardBubbleViewBrowserTest.WidgetVisibleOnTabFocus +-TabHoverCardBubbleViewBrowserTest.WidgetVisibleOnTabFocusFromKeyboardAccelerator +-TaskManagerBrowserTest.IdleWakeups +-TrustSafetySentimentServiceBrowserTest.PageInfoTriggersSurvey_Interaction +-TrustSafetySentimentServiceBrowserTest.PageInfoTriggersSurvey_NoInteraction +-UkmBrowserTest.ConsentAddedButNoSyncCheck +-UkmBrowserTest.HistoryDeleteCheck +-UkmBrowserTest.IncognitoPlusRegularCheck +-UkmBrowserTest.LogProtoData +-UkmBrowserTest.MetricsConsentCheck +-UkmBrowserTest.MetricsReportingCheck +-UkmBrowserTest.MultiDisableExtensionsSyncCheck +-UkmBrowserTest.MultiSyncSignoutCheck +-UkmBrowserTest.NetworkProviderPopulatesSystemProfile +-UkmBrowserTest.OpenNonSyncCheck +-UkmBrowserTest.RegularPlusGuestCheck +-UkmBrowserTest.RegularPlusIncognitoCheck +-UkmBrowserTest.ServiceListenerInitFailedCheck +-UkmBrowserTest.SingleDisableExtensionsSyncCheck +-UkmBrowserTestWithSyncTransport.NotEnabledForSecondaryAccountSync +-UkmConsentParamBrowserTests/UkmConsentParamBrowserTest.GroupPolicyConsentCheck/0 +-UkmConsentParamBrowserTests/UkmConsentParamBrowserTest.GroupPolicyConsentCheck/1 +-UsbInternalsTest.WebUIValueRenderTest +-VariationsSafeModeEndToEndBrowserTest.ExtendedSafeModeEndToEnd +-WebAudioBrowserTest.VerifyDynamicsCompressorFingerprint +-WebNavigationApiBackForwardCacheTest.ForwardBack +-WebViewTests/WebViewTest.DownloadCookieIsolation_CrossSession/SiteIsolationForGuestsDisabled +-WebViewTests/WebViewTest.DownloadCookieIsolation_CrossSession/SiteIsolationForGuestsEnabled +-WebViewTests/WebViewTest.NoPrerenderer/SiteIsolationForGuestsDisabled +-WebViewTests/WebViewTest.NoPrerenderer/SiteIsolationForGuestsEnabled +-WorkerDevToolsTest.PauseInSharedWorkerInitialization + +# TODO(crbug.com/1306610): crbug.com/1306610: Enable once PDF rendering can be +# enabled without PPAPI. +-All/PrintBackendPrintBrowserTest.UpdatePrintSettings/0 +-All/PrintBackendPrintBrowserTest.UpdatePrintSettings/1 +-BackForwardCachePrintBrowserTest.DisableCaching +-PdfPluginContextMenuBrowserTest.FullPagePdfFullscreenItems +-PdfPluginContextMenuBrowserTest.FullPagePdfHasPageItems +-PdfPluginContextMenuBrowserTest.IframedPdfHasNoPageItems +-PdfPluginContextMenuBrowserTest.Rotate +-PdfToPwgRasterBrowserTest.TestSuccessColor +-PdfToPwgRasterBrowserTest.TestSuccessLongDuplex +-PdfToPwgRasterBrowserTest.TestSuccessMono +-PortalBrowserTest.PdfViewerLoadsInPortal +-PrintBackendPrintBrowserTestService.StartPrintingAccessDenied +-PrintBackendPrintBrowserTestService.StartPrintingRepeatedAccessDenied +-PrintBrowserTest.LazyLoadedIframeFetched +-PrintBrowserTest.LazyLoadedImagesFetched +-PrintBrowserTest.LegacyLayoutEngineFallback +-PrintBrowserTest.MultipagePrint +-PrintBrowserTest.NoScrolling +-PrintBrowserTest.NoScrollingVerticalRl +-PrintBrowserTest.PDFPluginNotKeyboardFocusable +-PrintBrowserTest.PrintNup +-PrintBrowserTest.ResetPageScaleAfterPrintPreview +-PrintBrowserTest.SelectionContainsIframe +-PrintBrowserTest.WindowDotPrint +-PrintExtensionBrowserTest.PrintOptionPage +-PrintPreviewDestinationDialogTest.PrinterList +-PrintPreviewDestinationDialogTest.UserAccounts +-SitePerProcessPrintBrowserTest.BasicPrint +-SitePerProcessPrintBrowserTest.MultipagePrint +-SitePerProcessPrintBrowserTest.PrintNup +-SitePerProcessPrintBrowserTest.SubframeUnavailableBeforePrint +-SitePerProcessPrintBrowserTest.SubframeUnavailableDuringPrint +-SitePerProcessPrintExtensionBrowserTest.PrintOptionPage +-WebViewTests/WebViewPdfTest.ContextMenuNavigationInMimeHandlerView/SiteIsolationForGuestsDisabled +-WebViewTests/WebViewPdfTest.ContextMenuNavigationInMimeHandlerView/SiteIsolationForGuestsEnabled +-WebViewTests/WebViewPdfTest.NestedGuestContainerBounds/SiteIsolationForGuestsDisabled +-WebViewTests/WebViewPdfTest.NestedGuestContainerBounds/SiteIsolationForGuestsEnabled +-WebViewTests/WebViewPdfTest.Shim_TestDialogInPdf/SiteIsolationForGuestsDisabled +-WebViewTests/WebViewPdfTest.Shim_TestDialogInPdf/SiteIsolationForGuestsEnabled + +# TODO(crbug.com/1315388): Widgets not being extracted because listing all open aura::Windows isn't implemented +-AccuracyTipBubbleViewDialogBrowserTest.InvokeUi_default +-AccuracyTipBubbleViewDialogBrowserTest.InvokeUi_ignore_button -All/DiceWebSigninInterceptionBubblePixelTest.InvokeUi_default/ConsumerDark -All/DiceWebSigninInterceptionBubblePixelTest.InvokeUi_default/ConsumerManagedDevice -All/DiceWebSigninInterceptionBubblePixelTest.InvokeUi_default/ConsumerSimple @@ -48,54 +362,8 @@ -All/DiceWebSigninInterceptionBubbleSyncPromoPixelTest.InvokeUi_default/EnterpriseManagedInterceptedDark -All/DiceWebSigninInterceptionBubbleSyncPromoPixelTest.InvokeUi_default/EnterpriseSimple -All/DiceWebSigninInterceptionBubbleSyncPromoPixelTest.InvokeUi_default/ProfileSwitch --All/MediaEngagementAutoplayBrowserTest.PreloadedDataAndHighVisits/0 --All/MediaEngagementAutoplayBrowserTest.PreloadedDataAndHighVisits/1 --All/MediaEngagementAutoplayBrowserTest.UsePreloadedData_Allowed/0 --All/MediaEngagementAutoplayBrowserTest.UsePreloadedData_Allowed/1 --All/MediaEngagementAutoplayBrowserTest.UsePreloadedData_Denied/0 --All/MediaEngagementAutoplayBrowserTest.UsePreloadedData_Denied/1 --All/MediaHistoryBrowserTest.RecordWatchtime_VideoOnly/0 --All/MediaHistoryBrowserTest.DoNotRecordWatchtime_Muted/2 --All/NetworkRequestMetricsBrowserTest.CancelBeforeHeaders/1 --All/NetworkRequestMetricsBrowserTest.CancelBeforeHeaders/2 --All/NetworkRequestMetricsBrowserTest.CancelBeforeHeaders/3 --All/NetworkRequestMetricsBrowserTest.CancelDuringBody/0 --All/NetworkRequestMetricsBrowserTest.CancelDuringBody/1 --All/NetworkRequestMetricsBrowserTest.CancelDuringBody/2 --All/NetworkRequestMetricsBrowserTest.CancelDuringBody/3 --All/NetworkRequestMetricsBrowserTest.Download/1 --All/NetworkRequestMetricsBrowserTest.FileURLError/1 --All/NetworkRequestMetricsBrowserTest.FileURLError/2 --All/NetworkRequestMetricsBrowserTest.FileURLError/3 --All/NetworkRequestMetricsBrowserTest.FileURLSuccess/0 --All/NetworkRequestMetricsBrowserTest.FileURLSuccess/1 --All/NetworkRequestMetricsBrowserTest.FileURLSuccess/3 --All/NetworkRequestMetricsBrowserTest.InterruptedBeforeHeaders/1 --All/NetworkRequestMetricsBrowserTest.InterruptedBeforeHeaders/2 --All/NetworkRequestMetricsBrowserTest.InterruptedBeforeHeaders/3 --All/NetworkRequestMetricsBrowserTest.InterruptedCancelDuringBody/0 --All/NetworkRequestMetricsBrowserTest.InterruptedCancelDuringBody/1 --All/NetworkRequestMetricsBrowserTest.InterruptedCancelDuringBody/2 --All/NetworkRequestMetricsBrowserTest.InterruptedCancelDuringBody/3 --All/NetworkRequestMetricsBrowserTest.NetErrorBeforeHeaders/1 --All/NetworkRequestMetricsBrowserTest.NetErrorBeforeHeaders/2 --All/NetworkRequestMetricsBrowserTest.NetErrorBeforeHeaders/3 --All/NetworkRequestMetricsBrowserTest.NetErrorDuringBody/0 --All/NetworkRequestMetricsBrowserTest.NetErrorDuringBody/1 --All/NetworkRequestMetricsBrowserTest.NetErrorDuringBody/2 --All/NetworkRequestMetricsBrowserTest.NetErrorDuringBody/3 --All/NetworkRequestMetricsBrowserTest.SuccessWithBody/0 --All/NetworkRequestMetricsBrowserTest.SuccessWithBody/1 --All/NetworkRequestMetricsBrowserTest.SuccessWithBody/2 --All/NetworkRequestMetricsBrowserTest.SuccessWithBody/3 --All/NetworkRequestMetricsBrowserTest.SuccessWithEmptyBody/0 --All/NetworkRequestMetricsBrowserTest.SuccessWithEmptyBody/1 --All/NetworkRequestMetricsBrowserTest.SuccessWithEmptyBody/2 --All/NetworkRequestMetricsBrowserTest.SuccessWithEmptyBody/3 -All/OneTimePermissionPromptBubbleViewBrowserTest.InvokeUi_geolocation/0 -All/OneTimePermissionPromptBubbleViewBrowserTest.InvokeUi_geolocation/1 --All/PermissionPromptBubbleViewBrowserTest.ActiveTabClosedAfterRendererCrashesWithPendingPermissionRequest/0 --All/PermissionPromptBubbleViewBrowserTest.ActiveTabClosedAfterRendererCrashesWithPendingPermissionRequest/1 -All/PermissionPromptBubbleViewBrowserTest.InvokeUi_camera/0 -All/PermissionPromptBubbleViewBrowserTest.InvokeUi_camera/1 -All/PermissionPromptBubbleViewBrowserTest.InvokeUi_downloads/0 @@ -114,24 +382,7 @@ -All/PermissionPromptBubbleViewBrowserTest.InvokeUi_protocol_handlers/1 -All/PermissionPromptBubbleViewBrowserTest.InvokeUi_security_key/0 -All/PermissionPromptBubbleViewBrowserTest.InvokeUi_security_key/1 --All/PrintBackendPrintBrowserTest.UpdatePrintSettings/2 --All/PrintBackendPrintBrowserTestService.StartPrinting/0 --All/PrintBackendPrintBrowserTestService.StartPrinting/1 --All/PrintBackendPrintBrowserTestService.StartPrintingSpoolingSharedMemoryError/0 --All/PrintBackendPrintBrowserTestService.StartPrintingSpoolingSharedMemoryError/1 --All/ReportingBrowserTest.CrashReportUnresponsive/1 --All/TabCapturePerformanceTest.Performance/0 --All/TabCapturePerformanceTest.Performance/1 --All/TabCapturePerformanceTest.Performance/2 --All/TabCapturePerformanceTest.Performance/3 --AllForms/FormStructureBrowserTest.DataDrivenHeuristics/153 -AppInfoDialogBrowserTest.InvokeUi_default --AppSessionRestoreTest.RestoreAppMinimized --AppSessionRestoreTest.RestoreMaximizedApp --AppSettingsAppTest.All --AppWindowApiTest.OnMaximizedEvent --AppWindowApiTest.OnMinimizedEvent --AppWindowApiTest.OnRestoredEvent -AskGoogleForSuggestionsDialogTest.InvokeUi_default -AuthenticatorDialogTest.InvokeUi_account_select -AuthenticatorDialogTest.InvokeUi_activate_usb @@ -173,15 +424,6 @@ -AutofillErrorDialogViewNativeViewsBrowserTest.InvokeUi_permanent -AutofillErrorDialogViewNativeViewsBrowserTest.InvokeUi_temporary -AutofillProgressDialogViewsBrowserTest.InvokeUi --BackForwardCacheSiteDetailsBrowserTest.MemoryDetailsForBackForwardCache --BluetoothApiTest.DeviceEvents --BluetoothApiTest.DeviceInfo --BluetoothApiTest.DiscoveryCallback --BluetoothApiTest.DiscoveryInProgress --BluetoothApiTest.GetAdapterState --BluetoothApiTest.GetDevice --BluetoothApiTest.GetDevices --BluetoothApiTest.OnAdapterStateChanged -BluetoothChooserBrowserTest.InvokeUi_ConnectedBubble -BluetoothChooserBrowserTest.InvokeUi_ConnectedModal -BluetoothChooserBrowserTest.InvokeUi_NoDevicesBubble @@ -194,24 +436,9 @@ -BluetoothChooserBrowserTest.InvokeUi_ScanningWithDevicesModal -BluetoothChooserBrowserTest.InvokeUi_UnavailableBubble -BluetoothChooserBrowserTest.InvokeUi_UnavailableModal --BluetoothPrivateApiTest.CancelPairing --BluetoothPrivateApiTest.Connect --BluetoothPrivateApiTest.DisconnectAll --BluetoothPrivateApiTest.DiscoveryFilter --BluetoothPrivateApiTest.ForgetDevice --BluetoothPrivateApiTest.NoBluetoothAdapter --BluetoothPrivateApiTest.Pair --BluetoothPrivateApiTest.PasskeyPairing --BluetoothPrivateApiTest.PincodePairing --BluetoothPrivateApiTest.SetAdapterState -BookmarkBubbleViewBrowserTest.InvokeUi_bookmark_details -BookmarkBubbleViewBrowserTest.InvokeUi_bookmark_details_signed_in -BookmarkEditorViewBrowserTest.InvokeUi_all_tabs --BrowserTest.FaviconChange --BrowserViewTest.GetAccessibleTabModalDialogTitle --BrowsingDataRemoverBrowserTest.Database --BrowsingDataRemoverBrowserTest.SessionOnlyStorageRemoved --BrowsingDataRemoverBrowserTest.StorageRemovedFromDisk -CardUnmaskAuthenticationSelectionDialogBrowserTest.InvokeUi_CardUnmaskAuthSelectionDialogDisplays -CardUnmaskOtpInputDialogBrowserTest.InvokeUi_CardUnmaskOtpInputDialogDisplays -CardUnmaskPromptViewBrowserTest.InvokeUi_expired @@ -223,86 +450,10 @@ -CastDialogViewBrowserTest.InvokeUi_Mixed -CastDialogViewBrowserTest.InvokeUi_NoSinks -CastDialogViewBrowserTest.InvokeUi_Unavailable --CastMirroringServiceHostBrowserTest.CaptureTabVideo -CertificateSelectorDialogTest.InvokeUi_default --ChromeAcceptHeaderTest.Check --ChromeBackForwardCacheBrowserTest.DoNotShowSameSiteSubframeInTaskManager --ChromeBackForwardCacheBrowserTest.ShowCrossSiteOOPIFInTaskManager --ChromeBackForwardCacheBrowserTest.ShowMainFrameInTaskManager --ChromeBrowserCloudManagementEnrollmentTest/ChromeBrowserCloudManagementEnrollmentTest.Test/1 --ChromeBrowserCloudManagementEnrollmentTest/ChromeBrowserCloudManagementEnrollmentTest.Test/3 -ChromeLabsUiTest.InvokeUi_default --ChromeMimeHandlerViewTest.ActivatePostMessageSupportOnce --ChromeMimeHandlerViewTest.BackgroundPage --ChromeMimeHandlerViewTest.Basic --ChromeMimeHandlerViewTest.BeforeUnloadEnabled_WithUserActivation --ChromeMimeHandlerViewTest.BeforeUnloadEnabled_WithoutUserActivation --ChromeMimeHandlerViewTest.BeforeUnload_NoDialog --ChromeMimeHandlerViewTest.BeforeUnload_ShowDialog --ChromeMimeHandlerViewTest.DataUrl --ChromeMimeHandlerViewTest.DoNotLoadInSandboxedFrame --ChromeMimeHandlerViewTest.EmbedWithInitialCrossOriginFrame --ChromeMimeHandlerViewTest.EmbedWithInitialFrameAcceptBeforeUnloadDialog --ChromeMimeHandlerViewTest.Embedded --ChromeMimeHandlerViewTest.EmbeddedDataUrlEmbed --ChromeMimeHandlerViewTest.EmbeddedDataUrlLong --ChromeMimeHandlerViewTest.EmbeddedDataUrlObject --ChromeMimeHandlerViewTest.EmbeddedThenPrint --ChromeMimeHandlerViewTest.EmbedderFrameRemovedNoCrash --ChromeMimeHandlerViewTest.Iframe --ChromeMimeHandlerViewTest.MimeHandlerViewInDisplayNoneFrameForGoogleApps --ChromeMimeHandlerViewTest.NonAsciiHeaders --ChromeMimeHandlerViewTest.PostMessage --ChromeMimeHandlerViewTest.RejectPointLock --ChromeMimeHandlerViewTest.SingleRequest --ChromeMimeHandlerViewTest.TargetBlankAnchor --ChromeMojoProxyResolverFactoryBrowserTest.DestroyAndCreateService --ChromeMojoProxyResolverFactoryBrowserTest.ServiceLifecycle --ChromeNavigationBrowserTest.CrossSiteRedirectionToPDF --ChromeNavigationBrowserTestWithMobileEmulation.CrossSiteRedirectionToPDFWithMobileEmulation --ChromeNavigationBrowserTestWithMobileEmulation.NavigateToPDFWithMobileEmulation --ChromePasswordProtectionServiceSyncBrowserTest.GSuitePasswordAlertMode --ChromeSitePerProcessPDFTest.EmbeddedPDFInsideCrossOriginFrame --ChromeSitePerProcessTest.PopupWindowFocus --ChromeURLDataManagerWebUITrustedTypesTest.NoTrustedTypesViolation/chrome___browser_switch --ChromeURLDataManagerWebUITrustedTypesTest.NoTrustedTypesViolation/chrome___nacl --ChromeURLDataManagerWebUITrustedTypesTest.NoTrustedTypesViolation/chrome___sandbox --ClientHintsBrowserTest.SwitchAcceptCHInvalid --ClientHintsBrowserTest.SwitchAppliesStorage --ClientHintsBrowserTest.SwitchAppliesStorageOneOrigin --ClientHintsBrowserTest.SwitchNotJson --ClientHintsBrowserTest.SwitchOriginNotSecure -CollectedCookiesTest.InvokeUi_default --CommerceHintAddToCartPatternTest.AddToCartByForm --CommerceHintAddToCartPatternTest.AddToCartByURL --CommerceHintAgentFencedFrameTest.VisitCartInFencedFrame --CommerceHintAgentPortalBrowserTest.VisitCartInPortal --CommerceHintAgentTest.AddToCartByForm --CommerceHintAgentTest.AddToCartByForm_WithLink --CommerceHintAgentTest.AddToCartByForm_WithWrongLink --CommerceHintAgentTest.AddToCartByURL --CommerceHintAgentTest.AddToCartByURL_XHR --CommerceHintAgentTest.ExtractCart_ProductIDFromComponent --CommerceHintAgentTest.ExtractCart_ScriptFromComponent --CommerceHintAgentTest.ExtractCart_ScriptFromResource --CommerceHintAgentTest.PurchaseByForm --CommerceHintAgentTest.VisitCart --CommerceHintAgentTest.VisitCart_GeneralPattern_FromComponent --CommerceHintAgentTest.VisitCart_PerDomain_FromComponent --CommerceHintAgentTest.VisitCheckout --CommerceHintCheckoutPatternTest.VisitCheckout --CommerceHintMaxCountTest.ExtractCart --CommerceHintOptimizeRendererDisabledTest.Rejected --CommerceHintOptimizeRendererTest.CartExtractionSkipped --CommerceHintPurchaseButtonPatternTest.PurchaseByForm --CommerceHintPurchaseURLPatternTest.PurchaseByURL --CommerceHintSkippAddToCartTest.AddToCartByForm --CommerceHintTimeoutTest.ExtractCart -ConfirmBubbleTest.InvokeUi_default --ContentAnalysisDelegateBlockingSettingBrowserTest.BlockLargeFiles/0 --ContentAnalysisDelegateBlockingSettingBrowserTest.BlockLargeFiles/1 --ContentAnalysisDelegateBlockingSettingBrowserTest.BlockLargeFiles/2 --ContentAnalysisDelegateBlockingSettingBrowserTest.BlockLargeFiles/3 -ContentAnalysysDialogUiTest.InvokeUi_default -ContentSettingBubbleDialogTest.InvokeUi_ads -ContentSettingBubbleDialogTest.InvokeUi_automatic_downloads @@ -322,44 +473,12 @@ -ContentSettingBubbleDialogTest.InvokeUi_notifications_quiet_predicted_very_unlikely -ContentSettingBubbleDialogTest.InvokeUi_popups -ContentSettingBubbleDialogTest.InvokeUi_protocol_handlers --ContextMenuBrowserTest.OpenProfileNoneReferrer -CookieControlsBubbleViewTest.InvokeUi_BlockingDisabled -CookieControlsBubbleViewTest.InvokeUi_NotWorkingClicked --CookiePolicyBrowserTest.NestedFirstPartyIFrameStorageForFrame --CorbAndCorsExtensionBrowserTest.ContentScriptVsHostBlockedByPolicy_AllowedTextResource --CorbAndCorsExtensionBrowserTest.ContentScriptVsHostBlockedByPolicy_NoSniffXml --CorbAndCorsExtensionBrowserTest.ContentScript_CorsAllowedByServer_NoPermissionToTarget --CorbAndCorsExtensionBrowserTest.ContentScript_CorsIgnoredByServer_NoPermissionToTarget --CorbAndCorsExtensionBrowserTest.ExtensionWithNoHttpPermissions --CorbAndCorsExtensionBrowserTest.FromProgrammaticContentScript_AllowedAfterSniffing --CorbAndCorsExtensionBrowserTest.FromProgrammaticContentScript_AllowedTextResource --CorbAndCorsExtensionBrowserTest.FromProgrammaticContentScript_AllowedTextResource_SubdomainPermissions --CorbAndCorsExtensionBrowserTest.FromProgrammaticContentScript_SameOrigin --CorbAndCorsExtensionBrowserTest.FromProgrammaticContentScript_UnloadedExtension --CrExtensionsA11yTestWithMultipleExensions.WithExtensions_scope_attr_valid --CrExtensionsA11yTestWithMultipleExensions.WithExtensions_table_fake_caption --CrSettingsPeoplePageTest.All --CrSettingsSecurityPageTest.All -CreateAppShortcutDialogTest.InvokeUi_default --CrossProfileDebuggerApiTest.Attach --CrossProfileDebuggerApiTest.GetTargets --DebuggerExtensionApiTest.AttachToPdf -DeepScanningFailureModalDialogTest.InvokeUi_default --DesktopCaptureApiTest.ChooseDesktopMedia --DesktopCaptureApiTest.Delegation -DesktopMediaPickerViewsBrowserTest.InvokeUi_default -DesktopMediaPickerViewsBrowserTest.InvokeUi_tabs --DestroyProfileOnBrowserClose/ProfileHelperTestWithDestroyProfile.DeleteInactiveProfile/0 --DestroyProfileOnBrowserClose/ProfileHelperTestWithDestroyProfile.DeleteInactiveProfile/1 --DestroyProfileOnBrowserClose/ProfileManagerBrowserTest.DeleteAllProfiles/0 --DestroyProfileOnBrowserClose/ProfileManagerBrowserTest.DeleteAllProfiles/1 --DestroyProfileOnBrowserClose/ProfileManagerBrowserTest.DeleteInactiveProfile/0 --DestroyProfileOnBrowserClose/ProfileManagerBrowserTest.DeleteInactiveProfile/1 --DestroyProfileOnBrowserClose/ProfileManagerBrowserTest.EphemeralProfile/0 --DestroyProfileOnBrowserClose/ProfileManagerBrowserTest.EphemeralProfile/1 --DevToolsTest.TestDispatchKeyEventShowsAutoFill --DiceManageAccountBrowserTest.ClearManagedProfileOnStartup --DiceWebSigninInterceptionBubbleBrowserTest.ProfileKeepAlive -DownloadDangerPromptBrowserTest.InvokeUi_AccountCompromise -DownloadDangerPromptBrowserTest.InvokeUi_AccountCompromiseFromApi -DownloadDangerPromptBrowserTest.InvokeUi_DangerousFile @@ -370,26 +489,10 @@ -DownloadDangerPromptBrowserTest.InvokeUi_PotentiallyUnwantedFromApi -DownloadDangerPromptBrowserTest.InvokeUi_UncommonContent -DownloadDangerPromptBrowserTest.InvokeUi_UncommonContentFromApi --DownloadTest.DownloadErrorReadonlyFolder --DownloadTestSplitCacheEnabled.SaveMainFramePdfFromContextMenu_IsolationInfo --DownloadTestSplitCacheEnabled.SaveSubframePdfFromContextMenu_IsolationInfo --DownloadTestSplitCacheEnabled.SaveSubframePdfFromPdfUI_IsolationInfo -EditAddressProfileDialogControllerImplTest.InvokeUi_Edit --EncryptedMediaSupportedTypesClearKeyTest.Video_MP4 --EncryptedMediaSupportedTypesClearKeyTest.Video_WebM --EncryptedMediaSupportedTypesExternalClearKeyTest.EncryptionScheme --EncryptedMediaSupportedTypesExternalClearKeyTest.Robustness --EncryptedMediaSupportedTypesExternalClearKeyTest.SessionType -EnterpriseStartupDialogViewBrowserTest.InvokeUi_Error -EnterpriseStartupDialogViewBrowserTest.InvokeUi_Information -EnterpriseStartupDialogViewBrowserTest.InvokeUi_Switch --ExtensionApiTabTest.UpdateWindowResize --ExtensionApiTest.FontSettings --ExtensionApiTest.FontSettingsIncognito --ExtensionApiTest.Storage --ExtensionApiTest.TemporaryAddressSpoof --ExtensionBackForwardCacheBrowserTest.StorageCallbackEvicts --ExtensionDialogTest.TextInputViaKeyEvent -ExtensionInstallBlockedDialogViewTest.InvokeUi_WithCustomMessage -ExtensionInstallBlockedDialogViewTest.InvokeUi_WithLongCustomMessage -ExtensionInstallBlockedDialogViewTest.InvokeUi_WithoutCustomMessage @@ -416,16 +519,7 @@ -ExtensionUninstallDialogViewInteractiveBrowserTest.InvokeUi_ManualUninstallShowReportAbuse -ExtensionUninstallDialogViewInteractiveBrowserTest.InvokeUi_UninstallByExtension -ExtensionUninstallDialogViewInteractiveBrowserTest.InvokeUi_UninstallByExtensionShowReportAbuse --ExtensionWebRequestApiTest.WebRequestPacRequestProtection --ExtensionWebRequestApiTest.WebSocketRequestOnWorker --ExtensionWebstoreGetWebGLStatusTest.Allowed --ExtensionWindowCreateTest.AcceptState -ExternalProtocolDialogBrowserTest.InvokeUi_default --ExternalProtocolDialogBrowserTest.TestFocus --ExtractorBrowserTest.ExtractBigFile --FedCmAccountSelectionViewBrowserTest.ShowAndVerifyUi --FencedFrameSiteDetailsBrowserTest.MemoryDetailsForFencedFrame --FetchBehaviorTests/ContentVerifierHashTest.FetchFailureWithDefaultResourceExtension/1 -FileSystemAccessPermissionViewTest.InvokeUi_ExtensionOrigin -FileSystemAccessPermissionViewTest.InvokeUi_FileOrigin -FileSystemAccessPermissionViewTest.InvokeUi_FileRead @@ -449,8 +543,6 @@ -FileSystemAccessUsageBubbleViewTest.InvokeUi_TwoWritableFiles -FileSystemAccessUsageBubbleViewTest.InvokeUi_WritableFilesAndFolders -FileSystemAccessUsageBubbleViewTest.InvokeUi_default --FileSystemApiTest.FileSystemApiRetainDirectoryEntry --FolderUploadConfirmationViewTest.InitiallyFocusesCancel -FolderUploadConfirmationViewTest.InvokeUi_default -FullscreenTabSearchBubbleDialogTest.InvokeUi_default -GlobalErrorBubbleTest.InvokeUi_ExtensionDisabledGlobalError @@ -458,118 +550,14 @@ -GlobalErrorBubbleTest.InvokeUi_ExternalInstallBubbleAlert -GlobalErrorBubbleTest.InvokeUi_SigninGlobalError -HelpBubbleFactoryViewsBrowsertest.InvokeUi_default --HistoryManipulationInterventionBrowserTest.PDFDoNotSkipOnBackForwardDueToUserGesture --HistoryManipulationInterventionBrowserTest.PDFSkipOnBackForwardNoUserGesture --HttpProxyScriptBrowserTest.Verify --I18nProcessTest.All --IconLoaderBrowserTest.LoadGroup --IconModuleTest.All -ImportLockDialogViewBrowserTest.InvokeUi_default --InMemoryApp/NetworkContextConfigurationDataPacBrowserTest.DataPac/0 --InMemoryApp/NetworkContextConfigurationDataPacBrowserTest.DataPac/1 --InMemoryApp/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/0 --InMemoryApp/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/1 --InMemoryApp/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/0 --InMemoryApp/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/1 --InMemoryApp/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/0 --InMemoryApp/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/1 --InProcess/ChromeNetworkServiceBrowserTest.EncryptedCookies/0 --InProcessBrowserTest.RunsScheduledLayoutOnAnchoredBubbles --IncognitoBrowsingDataBrowserTest.Database --IncognitoBrowsingDataBrowserTest.StorageDoesntWriteToDisk --IncognitoBrowsingDataBrowserTest.WebSqlDeletion -IncognitoClearBrowsingDataDialogBrowserTest.InvokeUi_default --IncognitoProfileMainNetworkContext/NetworkContextConfigurationDataPacBrowserTest.DataPac/0 --IncognitoProfileMainNetworkContext/NetworkContextConfigurationDataPacBrowserTest.DataPac/1 --IncognitoProfileMainNetworkContext/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/0 --IncognitoProfileMainNetworkContext/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/1 --IncognitoProfileMainNetworkContext/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/0 --IncognitoProfileMainNetworkContext/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/1 --IncognitoProfileMainNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/0 --IncognitoProfileMainNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/1 -InfoBarUiTest.InvokeUi_multiple_infobars -InlineLoginHelperBrowserTest.InvokeUi_default --InlineLoginHelperBrowserTest.SigninCreatesSyncStarter1 --InlineLoginHelperBrowserTest.SigninCreatesSyncStarter2 --InlineLoginHelperBrowserTest.SigninCreatesSyncStarter4 --InlineLoginHelperBrowserTest.UntrustedSigninDialogCancel --InlineLoginHelperBrowserTest.WithAuthCode --IntentChipButtonAppIconBrowserTest.ShowsAppIconInChip --IntentChipButtonBrowserTest.IconVisibilityAfterTabSwitching --IntentChipButtonBrowserTest.NavigationToInScopeLinkShowsIntentChip --IntentChipButtonBrowserTest.NavigationToOutOfScopeLinkDoesNotShowsIntentChip --IntentChipButtonBrowserTest.ShowsIntentChipCollapsed --IntentChipButtonBrowserTest.ShowsIntentPickerWhenMultipleApps --IntentChipButtonIPHBubbleBrowserTest.ShowAndCloseIPH -IntentPickerDialogTest.InvokeUi_default --IsolatedAppTest.SessionStorage --LoadingPredictorBrowserTestWithProxy.PrepareForPageLoadWithPrediction --LoadingPredictorBrowserTestWithProxy.PrepareForPageLoadWithoutPrediction --LocalCardMigrationBrowserTest.AcceptingDialogAddsLocalCardMigrationStrikes --LocalCardMigrationBrowserTest.CardIdentifierString --LocalCardMigrationBrowserTest.ClickingCancelClosesDialog --LocalCardMigrationBrowserTest.ClickingCloseClosesBubble --LocalCardMigrationBrowserTest.ClickingContinueOpensDialog --LocalCardMigrationBrowserTest.ClickingOmniboxIconReshowsBubble --LocalCardMigrationBrowserTest.ClickingSaveClosesDialog --LocalCardMigrationBrowserTest.ClosedReason_BubbleAccepted --LocalCardMigrationBrowserTest.ClosedReason_BubbleClosed --LocalCardMigrationBrowserTest.ClosedReason_BubbleLostFocus --LocalCardMigrationBrowserTest.ClosedReason_BubbleNotInteracted --LocalCardMigrationBrowserTest.ClosingBubbleAddsLocalCardMigrationStrikes --LocalCardMigrationBrowserTest.ClosingBubbleAgainAddsLocalCardMigrationStrikes --LocalCardMigrationBrowserTest.CreditCardIconShownInLocationBar --LocalCardMigrationBrowserTest.DialogContainsAllValidMigratableCard --LocalCardMigrationBrowserTest.IntermediateMigrationOfferDoesNotShowWhenPaymentsDeclines --LocalCardMigrationBrowserTest.RejectingDialogAddsLocalCardMigrationStrikes --LocalCardMigrationBrowserTest.ReshowingBubbleDoesNotAddStrikes --LocalCardMigrationBrowserTest.ReusingLocalCardDoesNotShowIntermediateMigrationOffer --LocalCardMigrationBrowserTest.ReusingLocalCardShowsIntermediateMigrationOffer --LocalCardMigrationBrowserTest.ReusingServerCardDoesNotShowIntermediateMigrationOffer --LocalCardMigrationBrowserTest.ReusingServerCardWithMigratableLocalCardShowIntermediateMigrationOffer --LocalCardMigrationBrowserTest.UsingNewCardDoesNotShowIntermediateMigrationOffer --LocalCardMigrationBrowserTestForStatusChip.ActivateFirstInactiveBubbleForAccessibility --LocalCardMigrationBrowserTestForStatusChip.ClickingOmniboxIconReshowsBubble --LocalCardMigrationBrowserTestForStatusChip.CreditCardIconShownInStatusChip --LocalCardMigrationBrowserTestForStatusChip.IconAndBubbleVisibilityAfterTabSwitching -LocalCardMigrationBrowserUiTest.InvokeUi_default --MediaEngagementBrowserTest.RecordSingleVisitOnSameOrigin --MediaEngagementBrowserTest.SessionNewTabNavigateSameURLWithOpener_Typed --MediaEngagementPreloadBrowserTest.EnsureSingletonListIsLoaded -MediaGalleriesInteractiveDialogTest.InvokeUi_DisplayDialog --MessagingApiTest.Messaging --MyIpAddressProxyScriptBrowserTest.Verify --NetworkingPrivateServiceClientApiTest.OnNetworkListChangedEvent --NetworkingPrivateServiceClientApiTest.OnNetworksChangedEventConnect --NetworkingPrivateServiceClientApiTest.OnNetworksChangedEventDisconnect --NetworkingPrivateServiceClientApiTest.RequestNetworkScan --NetworkConnectionTrackerBrowserTest.SimulateNetworkServiceCrash --OmniboxPopupContentsViewTest.ClickOmnibox --OmniboxPopupContentsViewTest.PopupMatchesLocationBarBackground -OmniboxSuggestionButtonRowBrowserTest.InvokeUi --OnDiskApp/NetworkContextConfigurationBrowserTest.CacheIsolation/1 --OnDiskApp/NetworkContextConfigurationBrowserTest.CookiesEnabled/0 --OnDiskApp/NetworkContextConfigurationBrowserTest.DiskCache/0 --OnDiskApp/NetworkContextConfigurationDataPacBrowserTest.DataPac/0 --OnDiskApp/NetworkContextConfigurationDataPacBrowserTest.DataPac/1 --OnDiskApp/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/0 --OnDiskApp/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/1 --OnDiskApp/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/0 --OnDiskApp/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/1 --OnDiskApp/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/0 --OnDiskApp/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/1 --OnDiskApp/NetworkContextConfigurationReportingAndNelBrowserTest.PersistReportingAndNel/0 --OnDiskAppWithIncognitoProfile/NetworkContextConfigurationDataPacBrowserTest.DataPac/0 --OnDiskAppWithIncognitoProfile/NetworkContextConfigurationDataPacBrowserTest.DataPac/1 --OnDiskAppWithIncognitoProfile/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/0 --OnDiskAppWithIncognitoProfile/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/1 --OnDiskAppWithIncognitoProfile/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/0 --OnDiskAppWithIncognitoProfile/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/1 --OnDiskAppWithIncognitoProfile/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/0 --OnDiskAppWithIncognitoProfile/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/1 --OutOfMemoryReporterPrerenderBrowserTest.NotReportedOnPrerenderPage --OutOfMemoryReporterPrerenderBrowserTest.ReportedOnActivatedPrerenderPage --OutOfProcess/ChromeNetworkServiceBrowserTest.EncryptedCookies/0 -OutdatedUpgradeBubbleTest.InvokeUi_NoAutoUpdate -OutdatedUpgradeBubbleTest.InvokeUi_Outdated -PageInfoBubbleViewAboutThisSiteDialogBrowserTest.InvokeUi_AboutThisSite @@ -598,10 +586,6 @@ -PageInfoBubbleViewHistoryDialogBrowserTest.InvokeUi_History -PageInfoBubbleViewPrivacySandboxDialogBrowserTest.InvokeUi_PrivacySandboxMain -PageInfoBubbleViewPrivacySandboxDialogBrowserTest.InvokeUi_PrivacySandboxSubpage --PaintPreviewCompositorBrowserTest.CompositorCreate --PaintPreviewCompositorBrowserTest.KillWithActiveCompositors --PaintPreviewCompositorBrowserTest.MultipleCompositorCreate --PaintPreviewCompositorBrowserTest.TestInitializationSuccess -PasswordBubbleBrowserTest.InvokeUi_AutoSignin -PasswordBubbleBrowserTest.InvokeUi_AutomaticPasswordBubble -PasswordBubbleBrowserTest.InvokeUi_ManagePasswordBubble @@ -619,23 +603,92 @@ -PaymentRequestCvcUnmaskViewControllerVisualTest.InvokeUi_default -PaymentsRequestVisualTest.InvokeUi_NoShipping -PaymentsRequestVisualWithBasicCardDisabledTest.InvokeUi_NoShipping --PolicyPrefsTestCoverageTest.AllPoliciesHaveATestCase --PortalOutOfMemoryReporterBrowserTest.ReportForActivatedPortal --PrerenderSiteDetailsBrowserTest.MemoryDetailsForPrerender --PrintBackendPrintBrowserTestSandboxedService.StartPrintingAccessDenied --PrintBackendPrintBrowserTestSandboxedService.StartPrintingDocumentDoneAccessDenied --PrintBackendPrintBrowserTestSandboxedService.StartPrintingRenderDocumentAccessDenied --PrintBackendPrintBrowserTestSandboxedService.StartPrintingRepeatedAccessDenied --PrivacyBudgetFieldtrialConfigTest.LoadsSettingsFromFieldTrialConfig -PrivacySandboxDialogViewBrowserTest.InvokeUi_Notice --PrivateNetworkAccessWithFeatureEnabledBrowserTest.DoesNotRecordAddressSpaceFeatureForBlockedRequests --ProcessManagementTest.ProcessOverflow --ProcessMemoryMetricsEmitterTest.FetchAndEmitMetricsWithExtensions --ProcessMemoryMetricsEmitterTest.FetchDuringTrace --ProcessMemoryMetricsEmitterTest.ForegroundAndBackgroundPages --ProfileCustomizationBubbleBrowserTest.IPH -ProfileCustomizationBubbleBrowserTest.InvokeUi_default --ProfileHelperTest.OpenNewWindowForProfile +-PromptForScanningModalDialogTest.InvokeUi_default +-QRCodeGeneratorBubbleBrowserTest.InvokeUi_bottom_error +-QRCodeGeneratorBubbleBrowserTest.InvokeUi_default +-QRCodeGeneratorBubbleBrowserTest.InvokeUi_top_error +-RelaunchRecommendedBubbleViewDialogTest.InvokeUi_default +-RelaunchRequiredDialogViewDialogTest.InvokeUi_default +-RepostFormWarningTest.InvokeUi_TestRepostWarning +-SafetyTipPageInfoBubbleViewDialogTest.InvokeUi_BadReputation +-SafetyTipPageInfoBubbleViewDialogTest.InvokeUi_Lookalike +-SaveCardBubbleControllerImplTest.InvokeUi_Failure +-SaveCardBubbleControllerImplTest.InvokeUi_Local +-SaveCardBubbleControllerImplTest.InvokeUi_Manage +-SaveCardBubbleControllerImplTest.InvokeUi_Server +-SaveCardBubbleControllerImplTest.InvokeUi_Server_WithCardExpirationDateDropDownBox +-SaveCardBubbleControllerImplTest.InvokeUi_Server_WithCardholderNameTextfield +-SaveUPIBubbleControllerImplTest.InvokeUi +-SaveUpdateAddressProfileBubbleControllerImplTest.InvokeUi_Save +-SaveUpdateAddressProfileBubbleControllerImplTest.InvokeUi_SaveCloseThenReopen +-SaveUpdateAddressProfileBubbleControllerImplTest.InvokeUi_Update +-ScreenCaptureNotificationUiBrowserTest.InvokeUi +-SecurePaymentConfirmationDialogViewTest.InvokeUi_default +-SendTabToSelfBubbleTest.InvokeUi_default +-SessionCrashedBubbleViewTest.InvokeUi_SessionCrashedBubble +-SessionCrashedBubbleViewTest.InvokeUi_SessionCrashedBubbleOfferUma +-SettingsOverriddenDialogViewBrowserTest.InvokeUi_NtpOverriddenDialog_BackToDefault +-SettingsOverriddenDialogViewBrowserTest.InvokeUi_NtpOverriddenDialog_Generic +-SettingsOverriddenDialogViewBrowserTest.InvokeUi_SimpleDialog +-SettingsOverriddenDialogViewBrowserTest.InvokeUi_SimpleDialogWithIcon +-SigninViewControllerDelegateViewsBrowserTest.InvokeUi_SyncConfirmation +-TabGroupEditorBubbleViewDialogBrowserTest.InvokeUi_default +-TabHoverCardBubbleViewBrowserTest.InvokeUi_tab_hover_card +-TabSearchButtonBrowserUITest.InvokeUi_default +-TranslateBubbleVisualTest.InvokeUi_advanced +-TranslateBubbleVisualTest.InvokeUi_before_translate +-TranslateBubbleVisualTest.InvokeUi_error +-TranslateBubbleVisualTest.InvokeUi_select_source +-UpdateRecommendedDialogTest.InvokeUi_default +-UsbChooserBrowserTest.InvokeUi_NoDevicesBubble +-UsbChooserBrowserTest.InvokeUi_NoDevicesModal +-UsbChooserBrowserTest.InvokeUi_WithDevicesBubble +-UsbChooserBrowserTest.InvokeUi_WithDevicesModal +-VirtualCardSelectionDialogBrowserTest.InvokeUi_OneCard +-WebAppUninstallDialogViewInteractiveBrowserTest.InvokeUi_ManualUninstall +-WebauthnDialogBrowserTest.InvokeUi_Offer +-WebauthnDialogBrowserTest.InvokeUi_Verify +-ZoomBubbleDialogTest.InvokeUi_default + +# TODO(crbug.com/1309290): Fail with ERR_INTERNET_DISCONNECTED +-InMemoryApp/NetworkContextConfigurationDataPacBrowserTest.DataPac/0 +-InMemoryApp/NetworkContextConfigurationDataPacBrowserTest.DataPac/1 +-InMemoryApp/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/0 +-InMemoryApp/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/1 +-InMemoryApp/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/0 +-InMemoryApp/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/1 +-InMemoryApp/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/0 +-InMemoryApp/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/1 +-IncognitoProfileMainNetworkContext/NetworkContextConfigurationDataPacBrowserTest.DataPac/0 +-IncognitoProfileMainNetworkContext/NetworkContextConfigurationDataPacBrowserTest.DataPac/1 +-IncognitoProfileMainNetworkContext/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/0 +-IncognitoProfileMainNetworkContext/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/1 +-IncognitoProfileMainNetworkContext/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/0 +-IncognitoProfileMainNetworkContext/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/1 +-IncognitoProfileMainNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/0 +-IncognitoProfileMainNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/1 +-OnDiskApp/NetworkContextConfigurationBrowserTest.CacheIsolation/1 +-OnDiskApp/NetworkContextConfigurationBrowserTest.CookiesEnabled/0 +-OnDiskApp/NetworkContextConfigurationBrowserTest.DiskCache/0 +-OnDiskApp/NetworkContextConfigurationDataPacBrowserTest.DataPac/0 +-OnDiskApp/NetworkContextConfigurationDataPacBrowserTest.DataPac/1 +-OnDiskApp/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/0 +-OnDiskApp/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/1 +-OnDiskApp/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/0 +-OnDiskApp/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/1 +-OnDiskApp/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/0 +-OnDiskApp/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/1 +-OnDiskApp/NetworkContextConfigurationReportingAndNelBrowserTest.PersistReportingAndNel/0 +-OnDiskAppWithIncognitoProfile/NetworkContextConfigurationDataPacBrowserTest.DataPac/0 +-OnDiskAppWithIncognitoProfile/NetworkContextConfigurationDataPacBrowserTest.DataPac/1 +-OnDiskAppWithIncognitoProfile/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/0 +-OnDiskAppWithIncognitoProfile/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/1 +-OnDiskAppWithIncognitoProfile/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/0 +-OnDiskAppWithIncognitoProfile/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/1 +-OnDiskAppWithIncognitoProfile/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/0 +-OnDiskAppWithIncognitoProfile/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/1 -ProfileMainNetworkContext/NetworkContextConfigurationBrowserTest.CacheIsolation/0 -ProfileMainNetworkContext/NetworkContextConfigurationBrowserTest.CacheIsolation/1 -ProfileMainNetworkContext/NetworkContextConfigurationBrowserTest.DiskCache/0 @@ -647,40 +700,7 @@ -ProfileMainNetworkContext/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/1 -ProfileMainNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/0 -ProfileMainNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/1 --ProfileMenuViewExtensionsTest.CloseIPH -ProfileNetworkContextServiceDiskCacheBrowsertest.DiskCacheLocation --ProfileWindowBrowserTest.OpenBrowserWindowForProfileWithSigninRequired --PromptForScanningModalDialogTest.InvokeUi_default --ProxyBrowserTest.BasicAuthWSConnect --ProxyBrowserTest.ProxyAuthHTTPS --ProxySettingsApiTest.ProxyEventsParseError --QRCodeGeneratorBubbleBrowserTest.InvokeUi_bottom_error --QRCodeGeneratorBubbleBrowserTest.InvokeUi_default --QRCodeGeneratorBubbleBrowserTest.InvokeUi_top_error --RecordLanguagesMetricsBrowserTest.ContentLanguageEmpty --RecordLanguagesMetricsBrowserTest.ContentLanguageMatchTopMostAcceptLanguage --RecordLanguagesMetricsBrowserTest.ContentLanguageMatchesAnyAcceptLanguage --RecordLanguagesMetricsBrowserTest.IframeBothParentAndChildContentLanguageIsEmpty --RecordLanguagesMetricsBrowserTest.IframeContentLanguageChildDifferFromParent --RecordLanguagesMetricsBrowserTest.IframeParentAndChildContentLanguageAreStar --RecordLanguagesMetricsBrowserTest.IframeParentAndChildContentLanguageHasSameValue --RecordLanguagesMetricsBrowserTest.IframeParentContentLanguageIsEmptyAndChildContentLanguageHasValue --RecordLanguagesMetricsBrowserTest.IframeParentContentLanuageIsStarAndChildContentLanguageHasValue --RecordLanguagesMetricsBrowserTest.IframeParentHasConentLanguageAndChildContentLanguageIsEmpty --RecordLanguagesMetricsBrowserTest.LargeAcceptLanguageList --RelaunchRecommendedBubbleViewDialogTest.InvokeUi_default --RelaunchRequiredDialogViewDialogTest.InvokeUi_default --RemoteCopyBrowserTest.ImageUrl --RemoteCopyBrowserTest.Text --RemoteCopyBrowserTest.TextThenImageUrl --RepostFormWarningTest.InvokeUi_TestRepostWarning --RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.RunTest/0 --RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.RunTest/1 --RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.RunTest/2 --RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.RunTest/3 --RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.RunTest/4 --RssLinksFetcherTest.FetchSuccessfulFromBody --RssLinksFetcherTest.FetchSuccessfulFromHead -SafeBrowsingNetworkContext/NetworkContextConfigurationDataPacBrowserTest.DataPac/0 -SafeBrowsingNetworkContext/NetworkContextConfigurationDataPacBrowserTest.DataPac/1 -SafeBrowsingNetworkContext/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/0 @@ -689,15 +709,44 @@ -SafeBrowsingNetworkContext/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/1 -SafeBrowsingNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/0 -SafeBrowsingNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/1 --SafetyTipPageInfoBubbleViewDigitalAssetLinksBrowserTest.NoShowOnDigitalAssetLinkMatch --SafetyTipPageInfoBubbleViewDialogTest.InvokeUi_BadReputation --SafetyTipPageInfoBubbleViewDialogTest.InvokeUi_Lookalike --SaveCardBubbleControllerImplTest.InvokeUi_Failure --SaveCardBubbleControllerImplTest.InvokeUi_Local --SaveCardBubbleControllerImplTest.InvokeUi_Manage --SaveCardBubbleControllerImplTest.InvokeUi_Server --SaveCardBubbleControllerImplTest.InvokeUi_Server_WithCardExpirationDateDropDownBox --SaveCardBubbleControllerImplTest.InvokeUi_Server_WithCardholderNameTextfield +-SystemNetworkContext/NetworkContextConfigurationDataPacBrowserTest.DataPac/0 +-SystemNetworkContext/NetworkContextConfigurationDataPacBrowserTest.DataPac/1 +-SystemNetworkContext/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/0 +-SystemNetworkContext/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/1 +-SystemNetworkContext/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/0 +-SystemNetworkContext/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/1 +-SystemNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/0 +-SystemNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/1 + +# TODO(crbug.com/1321162) OpenTab gets stuck waiting for the page to render. Possibly isn't +# rendering because it isn't visible +-LocalCardMigrationBrowserTest.AcceptingDialogAddsLocalCardMigrationStrikes +-LocalCardMigrationBrowserTest.CardIdentifierString +-LocalCardMigrationBrowserTest.ClickingCancelClosesDialog +-LocalCardMigrationBrowserTest.ClickingCloseClosesBubble +-LocalCardMigrationBrowserTest.ClickingContinueOpensDialog +-LocalCardMigrationBrowserTest.ClickingOmniboxIconReshowsBubble +-LocalCardMigrationBrowserTest.ClickingSaveClosesDialog +-LocalCardMigrationBrowserTest.ClosedReason_BubbleAccepted +-LocalCardMigrationBrowserTest.ClosedReason_BubbleClosed +-LocalCardMigrationBrowserTest.ClosedReason_BubbleLostFocus +-LocalCardMigrationBrowserTest.ClosedReason_BubbleNotInteracted +-LocalCardMigrationBrowserTest.ClosingBubbleAddsLocalCardMigrationStrikes +-LocalCardMigrationBrowserTest.ClosingBubbleAgainAddsLocalCardMigrationStrikes +-LocalCardMigrationBrowserTest.CreditCardIconShownInLocationBar +-LocalCardMigrationBrowserTest.DialogContainsAllValidMigratableCard +-LocalCardMigrationBrowserTest.IntermediateMigrationOfferDoesNotShowWhenPaymentsDeclines +-LocalCardMigrationBrowserTest.RejectingDialogAddsLocalCardMigrationStrikes +-LocalCardMigrationBrowserTest.ReshowingBubbleDoesNotAddStrikes +-LocalCardMigrationBrowserTest.ReusingLocalCardDoesNotShowIntermediateMigrationOffer +-LocalCardMigrationBrowserTest.ReusingLocalCardShowsIntermediateMigrationOffer +-LocalCardMigrationBrowserTest.ReusingServerCardDoesNotShowIntermediateMigrationOffer +-LocalCardMigrationBrowserTest.ReusingServerCardWithMigratableLocalCardShowIntermediateMigrationOffer +-LocalCardMigrationBrowserTest.UsingNewCardDoesNotShowIntermediateMigrationOffer +-LocalCardMigrationBrowserTestForStatusChip.ActivateFirstInactiveBubbleForAccessibility +-LocalCardMigrationBrowserTestForStatusChip.ClickingOmniboxIconReshowsBubble +-LocalCardMigrationBrowserTestForStatusChip.CreditCardIconShownInStatusChip +-LocalCardMigrationBrowserTestForStatusChip.IconAndBubbleVisibilityAfterTabSwitching -SaveCardBubbleViewsFullFormBrowserTest.AlertAccessibleEvent -SaveCardBubbleViewsFullFormBrowserTest.Local_ClickingNoThanksClosesBubble -SaveCardBubbleViewsFullFormBrowserTest.Local_SynchronousCloseAfterAsynchronousClose @@ -750,61 +799,87 @@ -SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream.Upload_SubmittingFormWithMissingExpirationDateRequestsExpirationDate -SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream.Upload_SubmittingFormWithMissingExpirationDateYearAndWithMonth -SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream.Upload_SubmittingFormWithMissingNamesRequestsCardholderNameIfExpOn --SaveCardBubbleViewsSyncTransportFullFormBrowserTest.Local_TransportMode_InfoTextIconDoesNotExist --SaveCardBubbleViewsSyncTransportFullFormBrowserTest.Upload_TransportMode_ClickingSaveClosesBubble --SaveCardBubbleViewsSyncTransportFullFormBrowserTest.Upload_TransportMode_InfoTextIconExists --SaveCardBubbleViewsSyncTransportFullFormBrowserTest.Upload_TransportMode_RequestedCardholderNameTextfieldIsPrefilledWithFocusName --SavePackageDeepScanningBrowserTest.Allowed --SavePackageDeepScanningBrowserTest.Blocked --SavePackageDeepScanningBrowserTest.DiscardAfterWarning --SavePackageDeepScanningBrowserTest.KeepAfterWarning --SavePackageDeepScanningBrowserTest.OpenNow --SaveUPIBubbleControllerImplTest.InvokeUi --SaveUpdateAddressProfileBubbleControllerImplTest.CloseTabWhileBubbleIsOpen --SaveUpdateAddressProfileBubbleControllerImplTest.InvokeUi_Save --SaveUpdateAddressProfileBubbleControllerImplTest.InvokeUi_SaveCloseThenReopen --SaveUpdateAddressProfileBubbleControllerImplTest.InvokeUi_Update --ScreenCaptureNotificationUiBrowserTest.InvokeUi --ScriptingAPITest.NestedWebContents --SecurePaymentConfirmationDialogViewTest.InvokeUi_default --SendTabToSelfBubbleTest.InvokeUi_default --ServiceWorkerTest.MimeHandlerView --SessionCrashedBubbleViewTest.InvokeUi_SessionCrashedBubble --SessionCrashedBubbleViewTest.InvokeUi_SessionCrashedBubbleOfferUma --SessionRestorePageLoadMetricsBrowserTest.RestoreForeignSession --SessionRestoreTest.RestoreAfterClosingTabbedBrowserWithAppAndLaunching --SettingsOverriddenDialogViewBrowserTest.InvokeUi_NtpOverriddenDialog_BackToDefault --SettingsOverriddenDialogViewBrowserTest.InvokeUi_NtpOverriddenDialog_Generic --SettingsOverriddenDialogViewBrowserTest.InvokeUi_SimpleDialog --SettingsOverriddenDialogViewBrowserTest.InvokeUi_SimpleDialogWithIcon -SharedClipboardBrowserTest.ContextMenu_MultipleDevices -SharedClipboardBrowserTest.ContextMenu_NoDevices -SharedClipboardBrowserTest.ContextMenu_SingleDevice -SharedClipboardUIFeatureDisabledBrowserTest.ContextMenu_UIFeatureDisabled --SigninInterceptFirstRunExperienceDialogBrowserTest.AcceptSync --SigninInterceptFirstRunExperienceDialogBrowserTest.AcceptSync_ExtensionTheme --SigninInterceptFirstRunExperienceDialogBrowserTest.AcceptSync_SyncPassphrase --SigninInterceptFirstRunExperienceDialogBrowserTest.DeclineSync --SigninInterceptFirstRunExperienceDialogBrowserTest.ForcedIntercept --SigninInterceptFirstRunExperienceDialogBrowserTest.ForcedIntercept_ProfileColorPolicy --SigninInterceptFirstRunExperienceDialogBrowserTest.ProfileColorPolicy --SigninInterceptFirstRunExperienceDialogBrowserTest.SyncDisabled --SigninInterceptFirstRunExperienceDialogBrowserTest.SyncSettings --SigninViewControllerDelegateViewsBrowserTest.InvokeUi_SyncConfirmation --SingleProcessBrowserTest.Test --SpellcheckServiceBrowserTest.DeleteCorruptedBDICT --StartupMetricsTest.ReportsValues --SyncAwareCounterTest.AutofillCounter --SyncAwareCounterTest.HistoryCounter --SyncAwareCounterTest.PasswordCounter --SystemNetworkContext/NetworkContextConfigurationDataPacBrowserTest.DataPac/0 --SystemNetworkContext/NetworkContextConfigurationDataPacBrowserTest.DataPac/1 --SystemNetworkContext/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/0 --SystemNetworkContext/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/1 --SystemNetworkContext/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/0 --SystemNetworkContext/NetworkContextConfigurationManagedProxySettingsBrowserTest.MaxConnectionsPerProxy/1 --SystemNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/0 --SystemNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/1 + +# TODO(crbug.com/1298019): Metrics histogram not yet supported +-All/NetworkRequestMetricsBrowserTest.CancelBeforeHeaders/1 +-All/NetworkRequestMetricsBrowserTest.CancelBeforeHeaders/2 +-All/NetworkRequestMetricsBrowserTest.CancelBeforeHeaders/3 +-All/NetworkRequestMetricsBrowserTest.CancelDuringBody/0 +-All/NetworkRequestMetricsBrowserTest.CancelDuringBody/1 +-All/NetworkRequestMetricsBrowserTest.CancelDuringBody/2 +-All/NetworkRequestMetricsBrowserTest.CancelDuringBody/3 +-All/NetworkRequestMetricsBrowserTest.Download/1 +-All/NetworkRequestMetricsBrowserTest.FileURLError/1 +-All/NetworkRequestMetricsBrowserTest.FileURLError/2 +-All/NetworkRequestMetricsBrowserTest.FileURLError/3 +-All/NetworkRequestMetricsBrowserTest.FileURLSuccess/0 +-All/NetworkRequestMetricsBrowserTest.FileURLSuccess/1 +-All/NetworkRequestMetricsBrowserTest.FileURLSuccess/3 +-All/NetworkRequestMetricsBrowserTest.InterruptedBeforeHeaders/1 +-All/NetworkRequestMetricsBrowserTest.InterruptedBeforeHeaders/2 +-All/NetworkRequestMetricsBrowserTest.InterruptedBeforeHeaders/3 +-All/NetworkRequestMetricsBrowserTest.InterruptedCancelDuringBody/0 +-All/NetworkRequestMetricsBrowserTest.InterruptedCancelDuringBody/1 +-All/NetworkRequestMetricsBrowserTest.InterruptedCancelDuringBody/2 +-All/NetworkRequestMetricsBrowserTest.InterruptedCancelDuringBody/3 +-All/NetworkRequestMetricsBrowserTest.NetErrorBeforeHeaders/1 +-All/NetworkRequestMetricsBrowserTest.NetErrorBeforeHeaders/2 +-All/NetworkRequestMetricsBrowserTest.NetErrorBeforeHeaders/3 +-All/NetworkRequestMetricsBrowserTest.NetErrorDuringBody/0 +-All/NetworkRequestMetricsBrowserTest.NetErrorDuringBody/1 +-All/NetworkRequestMetricsBrowserTest.NetErrorDuringBody/2 +-All/NetworkRequestMetricsBrowserTest.NetErrorDuringBody/3 +-All/NetworkRequestMetricsBrowserTest.SuccessWithBody/0 +-All/NetworkRequestMetricsBrowserTest.SuccessWithBody/1 +-All/NetworkRequestMetricsBrowserTest.SuccessWithBody/2 +-All/NetworkRequestMetricsBrowserTest.SuccessWithBody/3 +-All/NetworkRequestMetricsBrowserTest.SuccessWithEmptyBody/0 +-All/NetworkRequestMetricsBrowserTest.SuccessWithEmptyBody/1 +-All/NetworkRequestMetricsBrowserTest.SuccessWithEmptyBody/2 +-All/NetworkRequestMetricsBrowserTest.SuccessWithEmptyBody/3 +-CommerceHintAddToCartPatternTest.AddToCartByForm +-CommerceHintAddToCartPatternTest.AddToCartByURL +-CommerceHintAgentFencedFrameTest.VisitCartInFencedFrame +-CommerceHintAgentPortalBrowserTest.VisitCartInPortal +-CommerceHintAgentTest.AddToCartByForm +-CommerceHintAgentTest.AddToCartByForm_WithLink +-CommerceHintAgentTest.AddToCartByForm_WithWrongLink +-CommerceHintAgentTest.AddToCartByURL +-CommerceHintAgentTest.AddToCartByURL_XHR +-CommerceHintAgentTest.ExtractCart_ProductIDFromComponent +-CommerceHintAgentTest.ExtractCart_ScriptFromComponent +-CommerceHintAgentTest.ExtractCart_ScriptFromResource +-CommerceHintAgentTest.PurchaseByForm +-CommerceHintAgentTest.VisitCart +-CommerceHintAgentTest.VisitCart_GeneralPattern_FromComponent +-CommerceHintAgentTest.VisitCart_PerDomain_FromComponent +-CommerceHintAgentTest.VisitCheckout +-CommerceHintCheckoutPatternTest.VisitCheckout +-CommerceHintMaxCountTest.ExtractCart +-CommerceHintOptimizeRendererDisabledTest.Rejected +-CommerceHintOptimizeRendererTest.CartExtractionSkipped +-CommerceHintPurchaseButtonPatternTest.PurchaseByForm +-CommerceHintPurchaseURLPatternTest.PurchaseByURL +-CommerceHintSkippAddToCartTest.AddToCartByForm +-CommerceHintTimeoutTest.ExtractCart + +# TODO(crbug.com/1316456): Capture not yet supported +-All/CastV2PerformanceTest.Performance/1 +-All/CastV2PerformanceTest.Performance/2 +-All/CastV2PerformanceTest.Performance/3 +-All/CastV2PerformanceTest.Performance/4 +-All/CastV2PerformanceTest.Performance/5 +-All/TabCapturePerformanceTest.Performance/0 +-All/TabCapturePerformanceTest.Performance/1 +-All/TabCapturePerformanceTest.Performance/2 +-All/TabCapturePerformanceTest.Performance/3 +-CastMirroringServiceHostBrowserTest.CaptureTabVideo +-DesktopCaptureApiTest.ChooseDesktopMedia +-DesktopCaptureApiTest.Delegation -TabCaptureApiTest.ActiveTabPermission -TabCaptureApiTest.ApiTests -TabCaptureApiTest.CaptureInSplitIncognitoMode @@ -812,96 +887,36 @@ -TabCaptureApiTest.FullscreenEvents -TabCaptureApiTest.GrantForChromePages -TabCaptureApiTest.TabIndicator --TabGroupEditorBubbleViewDialogBrowserTest.InvokeUi_default --TabHoverCardBubbleViewBrowserTest.InvokeUi_tab_hover_card --TabHoverCardBubbleViewBrowserTest.WidgetNotVisibleOnMousePressAfterTabFocus --TabHoverCardBubbleViewBrowserTest.WidgetVisibleOnKeyPressAfterTabFocus --TabHoverCardBubbleViewBrowserTest.WidgetVisibleOnTabCloseButtonFocusAfterTabFocus --TabHoverCardBubbleViewBrowserTest.WidgetVisibleOnTabFocus --TabHoverCardBubbleViewBrowserTest.WidgetVisibleOnTabFocusFromKeyboardAccelerator --TabSearchButtonBrowserUITest.InvokeUi_default --TaskManagerBrowserTest.IdleWakeups --TranslateBubbleVisualTest.InvokeUi_advanced --TranslateBubbleVisualTest.InvokeUi_before_translate --TranslateBubbleVisualTest.InvokeUi_error --TranslateBubbleVisualTest.InvokeUi_select_source --TrustSafetySentimentServiceBrowserTest.PageInfoTriggersSurvey_Interaction --TrustSafetySentimentServiceBrowserTest.PageInfoTriggersSurvey_NoInteraction --UkmBrowserTest.ConsentAddedButNoSyncCheck --UkmBrowserTest.HistoryDeleteCheck --UkmBrowserTest.IncognitoPlusRegularCheck --UkmBrowserTest.LogProtoData --UkmBrowserTest.MetricsConsentCheck --UkmBrowserTest.MetricsReportingCheck --UkmBrowserTest.MultiDisableExtensionsSyncCheck --UkmBrowserTest.MultiSyncSignoutCheck --UkmBrowserTest.NetworkProviderPopulatesSystemProfile --UkmBrowserTest.OpenNonSyncCheck --UkmBrowserTest.RegularPlusGuestCheck --UkmBrowserTest.RegularPlusIncognitoCheck --UkmBrowserTest.ServiceListenerInitFailedCheck --UkmBrowserTest.SingleDisableExtensionsSyncCheck --UkmBrowserTestWithSyncTransport.NotEnabledForSecondaryAccountSync --UkmConsentParamBrowserTests/UkmConsentParamBrowserTest.GroupPolicyConsentCheck/0 --UkmConsentParamBrowserTests/UkmConsentParamBrowserTest.GroupPolicyConsentCheck/1 --UpdateRecommendedDialogTest.InvokeUi_default --UsbChooserBrowserTest.InvokeUi_NoDevicesBubble --UsbChooserBrowserTest.InvokeUi_NoDevicesModal --UsbChooserBrowserTest.InvokeUi_WithDevicesBubble --UsbChooserBrowserTest.InvokeUi_WithDevicesModal --UsbInternalsTest.WebUIValueRenderTest --VariationsSafeModeEndToEndBrowserTest.ExtendedSafeModeEndToEnd --VirtualCardSelectionDialogBrowserTest.InvokeUi_OneCard --WebAppUninstallDialogViewInteractiveBrowserTest.InvokeUi_ManualUninstall --WebAudioBrowserTest.VerifyDynamicsCompressorFingerprint --WebNavigationApiBackForwardCacheTest.ForwardBack --WebViewTests/WebViewTest.DownloadCookieIsolation_CrossSession/SiteIsolationForGuestsDisabled --WebViewTests/WebViewTest.DownloadCookieIsolation_CrossSession/SiteIsolationForGuestsEnabled --WebViewTests/WebViewTest.NoPrerenderer/SiteIsolationForGuestsDisabled --WebViewTests/WebViewTest.NoPrerenderer/SiteIsolationForGuestsEnabled --WebauthnDialogBrowserTest.InvokeUi_Offer --WebauthnDialogBrowserTest.InvokeUi_Verify --WorkerDevToolsTest.PauseInSharedWorkerInitialization --ZoomBubbleDialogTest.InvokeUi_default -# TODO(crbug.com/1306610): crbug.com/1306610: Enable once PDF rendering can be -# enabled without PPAPI. --All/PrintBackendPrintBrowserTest.UpdatePrintSettings/0 --All/PrintBackendPrintBrowserTest.UpdatePrintSettings/1 --BackForwardCachePrintBrowserTest.DisableCaching --PdfPluginContextMenuBrowserTest.FullPagePdfFullscreenItems --PdfPluginContextMenuBrowserTest.FullPagePdfHasPageItems --PdfPluginContextMenuBrowserTest.IframedPdfHasNoPageItems --PdfPluginContextMenuBrowserTest.Rotate --PdfToPwgRasterBrowserTest.TestSuccessColor --PdfToPwgRasterBrowserTest.TestSuccessLongDuplex --PdfToPwgRasterBrowserTest.TestSuccessMono --PortalBrowserTest.PdfViewerLoadsInPortal --PrintBackendPrintBrowserTestService.StartPrintingAccessDenied --PrintBackendPrintBrowserTestService.StartPrintingRepeatedAccessDenied --PrintBrowserTest.LazyLoadedIframeFetched --PrintBrowserTest.LazyLoadedImagesFetched --PrintBrowserTest.LegacyLayoutEngineFallback --PrintBrowserTest.MultipagePrint --PrintBrowserTest.NoScrolling --PrintBrowserTest.NoScrollingVerticalRl --PrintBrowserTest.PDFPluginNotKeyboardFocusable --PrintBrowserTest.PrintNup --PrintBrowserTest.ResetPageScaleAfterPrintPreview --PrintBrowserTest.SelectionContainsIframe --PrintBrowserTest.WindowDotPrint --PrintExtensionBrowserTest.PrintOptionPage --PrintPreviewDestinationDialogTest.PrinterList --PrintPreviewDestinationDialogTest.UserAccounts --SitePerProcessPrintBrowserTest.BasicPrint --SitePerProcessPrintBrowserTest.MultipagePrint --SitePerProcessPrintBrowserTest.PrintNup --SitePerProcessPrintBrowserTest.SubframeUnavailableBeforePrint --SitePerProcessPrintBrowserTest.SubframeUnavailableDuringPrint --SitePerProcessPrintExtensionBrowserTest.PrintOptionPage --WebViewTests/WebViewPdfTest.ContextMenuNavigationInMimeHandlerView/SiteIsolationForGuestsDisabled --WebViewTests/WebViewPdfTest.ContextMenuNavigationInMimeHandlerView/SiteIsolationForGuestsEnabled --WebViewTests/WebViewPdfTest.NestedGuestContainerBounds/SiteIsolationForGuestsDisabled --WebViewTests/WebViewPdfTest.NestedGuestContainerBounds/SiteIsolationForGuestsEnabled --WebViewTests/WebViewPdfTest.Shim_TestDialogInPdf/SiteIsolationForGuestsDisabled --WebViewTests/WebViewPdfTest.Shim_TestDialogInPdf/SiteIsolationForGuestsEnabled +# TODO(crbug.com/1251347): Bluetooth not yet supported +-BluetoothApiTest.DeviceEvents +-BluetoothApiTest.DeviceInfo +-BluetoothApiTest.DiscoveryCallback +-BluetoothApiTest.DiscoveryInProgress +-BluetoothApiTest.GetAdapterState +-BluetoothApiTest.GetDevice +-BluetoothApiTest.GetDevices +-BluetoothApiTest.OnAdapterStateChanged +-BluetoothPrivateApiTest.CancelPairing +-BluetoothPrivateApiTest.Connect +-BluetoothPrivateApiTest.DisconnectAll +-BluetoothPrivateApiTest.DiscoveryFilter +-BluetoothPrivateApiTest.ForgetDevice +-BluetoothPrivateApiTest.NoBluetoothAdapter +-BluetoothPrivateApiTest.Pair +-BluetoothPrivateApiTest.PasskeyPairing +-BluetoothPrivateApiTest.PincodePairing +-BluetoothPrivateApiTest.SetAdapterState + +# TODO(crbug.com/1321153): SQLite database could not set locking_mode to normal, Unable to turn on incremental auto-vacuum (3850 disk I/O error) +-AccessContextAuditBrowserTest.CheckSessionOnly +-AccessContextAuditBrowserTest.MultipleAccesses +-AccessContextAuditBrowserTest.RemoveHistory +-AccessContextAuditBrowserTest.RemoveRecords +-AccessContextAuditBrowserTest.TabClosed +-AccessContextAuditBrowserTest.TreeModelDeletion +-AccessContextAuditSessionRestoreBrowserTest.RestoreSession +-All/ChromeBrowsingDataLifetimeManagerScheduledRemovalTest.KeepsOtherTabData/0 +-All/ChromeBrowsingDataLifetimeManagerScheduledRemovalTest.KeepsOtherWindowData/0 +-All/ChromeBrowsingDataLifetimeManagerScheduledRemovalTest.SiteData/0 +-All/ChromeBrowsingDataLifetimeManagerScheduledRemovalTest.SiteData/1
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py index 0cc61c13..dc711845 100755 --- a/testing/buildbot/generate_buildbot_json.py +++ b/testing/buildbot/generate_buildbot_json.py
@@ -87,11 +87,19 @@ def generate(self, waterfall, tester_name, tester_config, input_tests): isolated_scripts = [] for test_name, test_config in sorted(input_tests.items()): - test = self.bb_gen.generate_gpu_telemetry_test( - waterfall, tester_name, tester_config, test_name, test_config, - self._is_android_webview) - if test: - isolated_scripts.append(test) + # Variants allow more than one definition for a given test, and is defined + # in array format from resolve_variants(). + if not isinstance(test_config, list): + test_config = [test_config] + + for config in test_config: + test = self.bb_gen.generate_gpu_telemetry_test(waterfall, tester_name, + tester_config, test_name, + config, + self._is_android_webview) + if test: + isolated_scripts.append(test) + return isolated_scripts def sort(self, tests):
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 8233f4e..d7db45f 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -1577,7 +1577,7 @@ "label": "//components/cronet/android:resource_sizes_cronet_sample_apk", "type": "generated_script", }, - 'resource_sizes_lacros_chrome': { + "resource_sizes_lacros_chrome": { "label": "//chromeos/lacros:resource_sizes_lacros_chrome", "type": "generated_script", },
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 040bcd594..c087c910 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -3081,8 +3081,12 @@ }, 'test_buildbucket_api_gpu_use_cases': { 'remove_from': [ - # crbug.com/1080749 - 'Optional Linux Release (NVIDIA)', + 'Optional Linux Release (NVIDIA)', # crbug.com/1080749 + ], + }, + 'test_buildbucket_api_gpu_use_cases GTX 1660': { + 'remove_from': [ + 'linux_optional_gpu_tests_rel', # crbug.com/1080749 ], }, 'trace_test': { @@ -3184,6 +3188,13 @@ }, }, }, + 'variations_smoke_tests': { + 'modifications': { + 'win-chrome': { + 'experiment_percentage': 100, + }, + }, + }, 'video_decode_accelerator_gl_unittest': { 'remove_from': [ # Windows Intel doesn't have the GL extensions to support this test.
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 51eb9641..5937110 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -3922,7 +3922,7 @@ }, 'ios_chrome_signin_eg2tests_module': { 'swarming': { - 'shards': 2, + 'shards': 5, }, }, 'ios_chrome_ui_eg2tests_module': { @@ -7582,5 +7582,55 @@ ] }, }, + + 'linux_optional_gpu_tests_rel_gpu_telemetry_tests': { + 'gpu_common_and_optional_telemetry_tests': { + 'variants': [ + 'LINUX_INTEL_HD_630_STABLE', + 'LINUX_NVIDIA_GTX_1660_STABLE', + ], + }, + 'gpu_mediapipe_passthrough_telemetry_tests': { + 'variants': [ + 'LINUX_INTEL_HD_630_STABLE', + 'LINUX_NVIDIA_GTX_1660_STABLE', + ], + }, + 'gpu_webcodecs_telemetry_test': { + 'variants': [ + 'LINUX_INTEL_HD_630_STABLE', + 'LINUX_NVIDIA_GTX_1660_STABLE', + ], + }, + 'gpu_webgl2_conformance_gl_passthrough_telemetry_tests': { + 'variants': [ + 'LINUX_INTEL_HD_630_STABLE', + 'LINUX_NVIDIA_GTX_1660_STABLE', + ], + }, + 'gpu_webgl_conformance_gl_passthrough_telemetry_tests': { + 'variants': [ + 'LINUX_INTEL_HD_630_STABLE', + 'LINUX_NVIDIA_GTX_1660_STABLE', + ], + }, + }, + + 'linux_optional_gpu_tests_rel_gtests': { + 'gpu_gles2_conform_gtests': { + 'variants': [ + 'LINUX_INTEL_HD_630_STABLE', + 'LINUX_NVIDIA_GTX_1660_STABLE', + ], + }, + }, + + 'linux_optional_gpu_tests_rel_isolated_scripts': { + 'test_buildbucket_api_gpu_use_cases': { + 'variants': [ + 'LINUX_NVIDIA_GTX_1660_STABLE', + ], + }, + }, } }
diff --git a/testing/buildbot/tryserver.chromium.linux.json b/testing/buildbot/tryserver.chromium.linux.json index defdf498..05a7f303 100644 --- a/testing/buildbot/tryserver.chromium.linux.json +++ b/testing/buildbot/tryserver.chromium.linux.json
@@ -89,5 +89,475 @@ "test_id_prefix": "ninja://:blink_web_tests/" } ] + }, + "linux_optional_gpu_tests_rel": { + "gtest_tests": [ + { + "args": [ + "--use-gpu-in-tests" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "gles2_conform_test GTX 1660", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:2184-440.100", + "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gles2_conform_test", + "test_id_prefix": "ninja://gpu/gles2_conform_support:gles2_conform_test/" + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "gles2_conform_test HD 630", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912-19.0.2", + "os": "Ubuntu-19.04", + "pool": "chromium.tests.gpu" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gles2_conform_test", + "test_id_prefix": "ninja://gpu/gles2_conform_support:gles2_conform_test/" + } + ], + "isolated_scripts": [ + { + "args": [ + "info_collection", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu", + "--expected-vendor-id", + "10de", + "--expected-device-id", + "2184" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "info_collection GTX 1660", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:2184-440.100", + "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "info_collection", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu", + "--expected-vendor-id", + "8086", + "--expected-device-id", + "5912" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "info_collection HD 630", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912-19.0.2", + "os": "Ubuntu-19.04", + "pool": "chromium.tests.gpu" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "mediapipe", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_higher_performance_gpu --use-cmd-decoder=passthrough --use-gl=angle" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "mediapipe_passthrough GTX 1660", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:2184-440.100", + "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "mediapipe", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_higher_performance_gpu --use-cmd-decoder=passthrough --use-gl=angle" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "mediapipe_passthrough HD 630", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912-19.0.2", + "os": "Ubuntu-19.04", + "pool": "chromium.tests.gpu" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "trace_test", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "trace_test GTX 1660", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:2184-440.100", + "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "trace_test", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "trace_test HD 630", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912-19.0.2", + "os": "Ubuntu-19.04", + "pool": "chromium.tests.gpu" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "webcodecs", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "webcodecs GTX 1660", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:2184-440.100", + "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "webcodecs", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "webcodecs HD 630", + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912-19.0.2", + "os": "Ubuntu-19.04", + "pool": "chromium.tests.gpu" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "webgl2_conformance_gl_passthrough_tests GTX 1660", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:2184-440.100", + "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 20 + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "webgl2_conformance_gl_passthrough_tests HD 630", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912-19.0.2", + "os": "Ubuntu-19.04", + "pool": "chromium.tests.gpu" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 20 + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "webgl_conformance_gl_passthrough GTX 1660", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:2184-440.100", + "os": "Ubuntu-18.04.5|Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "webgl_conformance_gl_passthrough HD 630", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912-19.0.2", + "os": "Ubuntu-19.04", + "pool": "chromium.tests.gpu" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + } + ] } }
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index feb5aec..9fddb06 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -22,15 +22,15 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5032.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5033.0/test_ash_chrome', ], - 'identifier': 'Lacros version skew testing ash 103.0.5032.0', + 'identifier': 'Lacros version skew testing ash 103.0.5033.0', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v103.0.5032.0', - 'revision': 'version:103.0.5032.0', + 'location': 'lacros_version_skew_tests_v103.0.5033.0', + 'revision': 'version:103.0.5033.0', }, ], }, @@ -80,6 +80,18 @@ ], }, }, + 'LINUX_INTEL_HD_630_STABLE': { + 'identifier': 'HD 630', + 'mixins': [ + 'linux_intel_hd_630_stable', + ], + }, + 'LINUX_NVIDIA_GTX_1660_STABLE': { + 'identifier': 'GTX 1660', + 'mixins': [ + 'linux_nvidia_gtx_1660_stable', + ], + }, 'SIM_IPAD_AIR_2_14_4': { 'args': [ '--platform', @@ -1127,4 +1139,4 @@ ], }, }, -} \ No newline at end of file +}
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index e7d4c8b6..ca613034 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -6877,6 +6877,15 @@ 'isolated_scripts': 'chromium_webkit_isolated_scripts', }, }, + 'linux_optional_gpu_tests_rel': { + 'os_type': 'linux', + 'browser_config': 'release', + 'test_suites': { + 'gtest_tests': 'linux_optional_gpu_tests_rel_gtests', + 'isolated_scripts': 'linux_optional_gpu_tests_rel_isolated_scripts', + 'gpu_telemetry_tests': 'linux_optional_gpu_tests_rel_gpu_telemetry_tests', + }, + }, }, }, {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 2d3b0464..d7ea038 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -483,16 +483,6 @@ "CrOSLateBootArcVmInitial30Throttle", "CrOSLateBootArcVmInitial70Throttle" ] - }, - { - "name": "throttle_to_30_percent", - "enable_features": [ - "CrOSLateBootArcVmInitial30Throttle" - ], - "disable_features": [ - "CrOSLateBootArcVmInitial50Throttle", - "CrOSLateBootArcVmInitial70Throttle" - ] } ] } @@ -2082,10 +2072,12 @@ ], "experiments": [ { - "name": "CandidateB_HideStartWithSRP", + "name": "CandidateB_FeedsShowLast7Days_8H", "params": { - "hide_start_when_last_visited_tab_is_srp": "true", + "behavioural_targeting": "feeds", "hide_switch_when_no_incognito_tabs": "true", + "num_days_keep_show_start_at_startup": "4", + "num_days_user_click_below_threshold": "1", "open_ntp_instead_of_start": "true", "show_last_active_tab_only": "true", "signin_promo_NTP_count_limit": "5", @@ -2094,7 +2086,8 @@ "start_surface_variation": "single", "support_accessibility": "true", "tab_count_button_on_start_surface": "true", - "tab_switcher_on_return_time_ms": "28800000" + "tab_switcher_on_return_time_ms": "28800000", + "user_clicks_threshold": "1" }, "enable_features": [ "StartSurfaceAndroid",
diff --git a/third_party/blink/public/mojom/payments/payment_request.mojom b/third_party/blink/public/mojom/payments/payment_request.mojom index 6920f944..fcd42b0 100644 --- a/third_party/blink/public/mojom/payments/payment_request.mojom +++ b/third_party/blink/public/mojom/payments/payment_request.mojom
@@ -251,16 +251,6 @@ // Shows the user interface with the payment details. // - // DEPRECATED: Use Show(bool wait_for_updated_details) instead. - // - // |wait_for_updated_details|: It's true when merchant passed in a promise - // into PaymentRequest.show(), so Chrome should disregard the initial payment - // details and show a spinner until the promise resolves with the correct - // payment details. The payment details will be updated with UpdateWith(). - ShowNew(bool wait_for_updated_details); - - // Shows the user interface with the payment details. - // // |wait_for_updated_details|: It's true when merchant passed in a promise // into PaymentRequest.show(), so Chrome should disregard the initial payment // details and show a spinner until the promise resolves with the correct
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom index ca183d1..df2461fb 100644 --- a/third_party/blink/public/mojom/web_feature/web_feature.mojom +++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -3537,6 +3537,7 @@ kCookieHasNotBeenRefreshedIn201To300Days = 4216, kCookieHasNotBeenRefreshedIn301To350Days = 4217, kCookieHasNotBeenRefreshedIn351To400Days = 4218, + kArrayBufferTooBigForWebAPI = 4219, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc b/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc index 22fda19..e300ef1 100644 --- a/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc +++ b/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc
@@ -3,8 +3,9 @@ // found in the LICENSE file. #include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h" - #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/core/frame/web_feature.h" #include "third_party/blink/renderer/core/typed_arrays/typed_flexible_array_buffer_view.h" namespace blink { @@ -214,8 +215,18 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value); - if (LIKELY(array_buffer)) + if (LIKELY(array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBuffer size exceeds the supported range"); + return nullptr; + } return array_buffer; + } exception_state.ThrowTypeError( ExceptionMessages::FailedToConvertJSValue("ArrayBuffer")); @@ -228,8 +239,18 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value); - if (LIKELY(array_buffer)) + if (LIKELY(array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBuffer size exceeds the supported range"); + return nullptr; + } return array_buffer; + } exception_state.ThrowTypeError( ExceptionMessages::ArgumentNotOfType(argument_index, "ArrayBuffer")); @@ -243,8 +264,18 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value); - if (LIKELY(array_buffer)) + if (LIKELY(array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBuffer size exceeds the supported range"); + return nullptr; + } return array_buffer; + } if (LIKELY(value->IsNullOrUndefined())) return nullptr; @@ -260,8 +291,18 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value); - if (LIKELY(array_buffer)) + if (LIKELY(array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBuffer size exceeds the supported range"); + return nullptr; + } return array_buffer; + } if (LIKELY(value->IsNullOrUndefined())) return nullptr; @@ -279,8 +320,18 @@ ExceptionState& exception_state) { DOMSharedArrayBuffer* shared_array_buffer = ToDOMSharedArrayBuffer(isolate, value); - if (LIKELY(shared_array_buffer)) + if (LIKELY(shared_array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(shared_array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The SharedArrayBuffer size exceeds the supported range"); + return nullptr; + } return shared_array_buffer; + } exception_state.ThrowTypeError( ExceptionMessages::FailedToConvertJSValue("SharedArrayBuffer")); @@ -294,8 +345,18 @@ ExceptionState& exception_state) { DOMSharedArrayBuffer* shared_array_buffer = ToDOMSharedArrayBuffer(isolate, value); - if (LIKELY(shared_array_buffer)) + if (LIKELY(shared_array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(shared_array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The SharedArrayBuffer size exceeds the supported range"); + return nullptr; + } return shared_array_buffer; + } exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType( argument_index, "SharedArrayBuffer")); @@ -311,8 +372,18 @@ ExceptionState& exception_state) { DOMSharedArrayBuffer* shared_array_buffer = ToDOMSharedArrayBuffer(isolate, value); - if (LIKELY(shared_array_buffer)) + if (LIKELY(shared_array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(shared_array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The SharedArrayBuffer size exceeds the supported range"); + return nullptr; + } return shared_array_buffer; + } if (LIKELY(value->IsNullOrUndefined())) return nullptr; @@ -330,8 +401,18 @@ ExceptionState& exception_state) { DOMSharedArrayBuffer* shared_array_buffer = ToDOMSharedArrayBuffer(isolate, value); - if (LIKELY(shared_array_buffer)) + if (LIKELY(shared_array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(shared_array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The SharedArrayBuffer size exceeds the supported range"); + return nullptr; + } return shared_array_buffer; + } if (LIKELY(value->IsNullOrUndefined())) return nullptr; @@ -348,13 +429,33 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value); - if (LIKELY(array_buffer)) + if (LIKELY(array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBuffer size exceeds the supported range"); + return nullptr; + } return array_buffer; + } DOMSharedArrayBuffer* shared_array_buffer = ToDOMSharedArrayBuffer(isolate, value); - if (LIKELY(shared_array_buffer)) + if (LIKELY(shared_array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(shared_array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The SharedArrayBuffer size exceeds the supported range"); + return nullptr; + } return shared_array_buffer; + } exception_state.ThrowTypeError( ExceptionMessages::FailedToConvertJSValue("[AllowShared] ArrayBuffer")); @@ -367,13 +468,33 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value); - if (LIKELY(array_buffer)) + if (LIKELY(array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBuffer size exceeds the supported range"); + return nullptr; + } return array_buffer; + } DOMSharedArrayBuffer* shared_array_buffer = ToDOMSharedArrayBuffer(isolate, value); - if (LIKELY(shared_array_buffer)) + if (LIKELY(shared_array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(shared_array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The SharedArrayBuffer size exceeds the supported range"); + return nullptr; + } return shared_array_buffer; + } exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType( argument_index, "[AllowShared] ArrayBuffer")); @@ -388,13 +509,33 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value); - if (LIKELY(array_buffer)) + if (LIKELY(array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBuffer size exceeds the supported range"); + return nullptr; + } return array_buffer; + } DOMSharedArrayBuffer* shared_array_buffer = ToDOMSharedArrayBuffer(isolate, value); - if (LIKELY(shared_array_buffer)) + if (LIKELY(shared_array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(shared_array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The SharedArrayBuffer size exceeds the supported range"); + return nullptr; + } return shared_array_buffer; + } if (LIKELY(value->IsNullOrUndefined())) return nullptr; @@ -411,13 +552,33 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { DOMArrayBuffer* array_buffer = ToDOMArrayBuffer(isolate, value); - if (LIKELY(array_buffer)) + if (LIKELY(array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBuffer size exceeds the supported range"); + return nullptr; + } return array_buffer; + } DOMSharedArrayBuffer* shared_array_buffer = ToDOMSharedArrayBuffer(isolate, value); - if (LIKELY(shared_array_buffer)) + if (LIKELY(shared_array_buffer)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(shared_array_buffer->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The SharedArrayBuffer size exceeds the supported range"); + return nullptr; + } return shared_array_buffer; + } if (LIKELY(value->IsNullOrUndefined())) return nullptr; @@ -437,8 +598,18 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { T* blink_view = ToDOMViewType<T, kNotShared>(isolate, value); - if (LIKELY(blink_view)) + if (LIKELY(blink_view)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(blink_view->byteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBufferView size exceeds the supported range"); + return NotShared<T>(); + } return NotShared<T>(blink_view); + } if (ABVTrait<T>::IsShared(value)) { exception_state.ThrowTypeError( @@ -461,8 +632,18 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { T* blink_view = ToDOMViewType<T, kNotShared>(isolate, value); - if (LIKELY(blink_view)) + if (LIKELY(blink_view)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(blink_view->byteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBufferView size exceeds the supported range"); + return NotShared<T>(); + } return NotShared<T>(blink_view); + } if (ABVTrait<T>::IsShared(value)) { exception_state.ThrowTypeError( @@ -486,8 +667,18 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { T* blink_view = ToDOMViewType<T, kMaybeShared>(isolate, value); - if (LIKELY(blink_view)) + if (LIKELY(blink_view)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(blink_view->byteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBufferView size exceeds the supported range"); + return MaybeShared<T>(); + } return MaybeShared<T>(blink_view); + } exception_state.ThrowTypeError(ExceptionMessages::FailedToConvertJSValue( T::GetStaticWrapperTypeInfo()->interface_name)); @@ -503,8 +694,18 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { T* blink_view = ToDOMViewType<T, kMaybeShared>(isolate, value); - if (LIKELY(blink_view)) + if (LIKELY(blink_view)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(blink_view->byteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBufferView size exceeds the supported range"); + return MaybeShared<T>(); + } return MaybeShared<T>(blink_view); + } exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType( argument_index, T::GetStaticWrapperTypeInfo()->interface_name)); @@ -521,8 +722,18 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { T* blink_view = ToDOMViewType<T, kNotShared>(isolate, value); - if (LIKELY(blink_view)) + if (LIKELY(blink_view)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(blink_view->byteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBufferView size exceeds the supported range"); + return NotShared<T>(); + } return NotShared<T>(blink_view); + } if (LIKELY(value->IsNullOrUndefined())) return NotShared<T>(); @@ -548,8 +759,18 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { T* blink_view = ToDOMViewType<T, kNotShared>(isolate, value); - if (LIKELY(blink_view)) + if (LIKELY(blink_view)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(blink_view->byteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBufferView size exceeds the supported range"); + return NotShared<T>(); + } return NotShared<T>(blink_view); + } if (LIKELY(value->IsNullOrUndefined())) return NotShared<T>(); @@ -576,8 +797,18 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { T* blink_view = ToDOMViewType<T, kMaybeShared>(isolate, value); - if (LIKELY(blink_view)) + if (LIKELY(blink_view)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(blink_view->byteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBufferView size exceeds the supported range"); + return MaybeShared<T>(); + } return MaybeShared<T>(blink_view); + } if (LIKELY(value->IsNullOrUndefined())) return MaybeShared<T>(); @@ -596,8 +827,18 @@ v8::Local<v8::Value> value, ExceptionState& exception_state) { T* blink_view = ToDOMViewType<T, kMaybeShared>(isolate, value); - if (LIKELY(blink_view)) + if (LIKELY(blink_view)) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(blink_view->byteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBufferView size exceeds the supported range"); + return MaybeShared<T>(); + } return MaybeShared<T>(blink_view); + } if (LIKELY(value->IsNullOrUndefined())) return MaybeShared<T>(); @@ -617,8 +858,18 @@ int argument_index, v8::Local<v8::Value> value, ExceptionState& exception_state) { - if (LIKELY(ABVTrait<T>::IsV8ViewType(value))) + if (LIKELY(ABVTrait<T>::IsV8ViewType(value))) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(value.As<typename ABVTrait<T>::V8ViewType>()->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBufferView size exceeds the supported range"); + return T(); + } return T(value.As<typename ABVTrait<T>::V8ViewType>()); + } exception_state.ThrowTypeError(ExceptionMessages::ArgumentNotOfType( argument_index, @@ -636,8 +887,18 @@ int argument_index, v8::Local<v8::Value> value, ExceptionState& exception_state) { - if (LIKELY(ABVTrait<T>::IsV8ViewType(value))) + if (LIKELY(ABVTrait<T>::IsV8ViewType(value))) { + // TODO(chromium:1201109): Remove check once Blink can handle bigger sizes. + if (UNLIKELY(value.As<typename ABVTrait<T>::V8ViewType>()->ByteLength() > + ::partition_alloc::internal::MaxDirectMapped())) { + UseCounter::Count(ExecutionContext::From(isolate->GetCurrentContext()), + WebFeature::kArrayBufferTooBigForWebAPI); + exception_state.ThrowRangeError( + "The ArrayBufferView size exceeds the supported range"); + return T(); + } return T(value.As<typename ABVTrait<T>::V8ViewType>()); + } if (LIKELY(value->IsNullOrUndefined())) return T();
diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc index 8c9c273..28910728 100644 --- a/third_party/blink/renderer/core/animation/animation.cc +++ b/third_party/blink/renderer/core/animation/animation.cc
@@ -2132,7 +2132,7 @@ } Element* target = keyframe_effect->EffectTarget(); - if (target && keyframe_effect->Model()) { + if (target && keyframe_effect->Model() && keyframe_effect->IsCurrent()) { compositor_property_animations_have_no_effect_ = CompositorAnimations::CompositorPropertyAnimationsHaveNoEffect( *target, *keyframe_effect->Model(), paint_artifact_compositor);
diff --git a/third_party/blink/renderer/core/animation/animation_test.cc b/third_party/blink/renderer/core/animation/animation_test.cc index e800d05..cf1628f 100644 --- a/third_party/blink/renderer/core/animation/animation_test.cc +++ b/third_party/blink/renderer/core/animation/animation_test.cc
@@ -107,11 +107,11 @@ KeyframeEffectModelBase* MakeSimpleEffectModel() { PropertyHandle PropertyHandleOpacity(GetCSSPropertyOpacity()); + static CSSNumberInterpolationType opacity_type(PropertyHandleOpacity); TransitionKeyframe* start_keyframe = MakeGarbageCollected<TransitionKeyframe>(PropertyHandleOpacity); start_keyframe->SetValue(std::make_unique<TypedInterpolationValue>( - CSSNumberInterpolationType(PropertyHandleOpacity), - std::make_unique<InterpolableNumber>(1.0))); + opacity_type, std::make_unique<InterpolableNumber>(1.0))); start_keyframe->SetOffset(0.0); // Egregious hack: Sideload the compositor value. // This is usually set in a part of the rendering process SimulateFrame @@ -121,8 +121,7 @@ TransitionKeyframe* end_keyframe = MakeGarbageCollected<TransitionKeyframe>(PropertyHandleOpacity); end_keyframe->SetValue(std::make_unique<TypedInterpolationValue>( - CSSNumberInterpolationType(PropertyHandleOpacity), - std::make_unique<InterpolableNumber>(0.0))); + opacity_type, std::make_unique<InterpolableNumber>(0.0))); end_keyframe->SetOffset(1.0); // Egregious hack: Sideload the compositor value. end_keyframe->SetCompositorValue( @@ -1813,6 +1812,7 @@ scroll_animation->play(); EXPECT_EQ(scroll_animation->CheckCanStartAnimationOnCompositor(nullptr), CompositorAnimations::kNoFailure); + UpdateAllLifecyclePhasesForTest(); // Start the animation on compositor. The time offset of the compositor // keyframe should be unset if we start the animation with its start time. scroll_animation->PreCommit(1, nullptr, true); @@ -1935,6 +1935,7 @@ scroll_animation->play(); EXPECT_EQ(scroll_animation->playState(), "running"); + UpdateAllLifecyclePhasesForTest(); GetDocument().GetPendingAnimations().Update(nullptr, true); EXPECT_TRUE(scroll_animation->HasActiveAnimationsOnCompositor());
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc index f67af71..91465d3 100644 --- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc +++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -184,6 +184,9 @@ } public: + AnimationCompositorAnimationsTest() + : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {} + bool ConvertTimingForCompositor(const Timing& t, CompositorAnimations::CompositorTiming& out, double playback_rate = 1) { @@ -1064,7 +1067,8 @@ EXPECT_NEAR(element_->getBoundingClientRect()->x(), 300.0, 0.001); } -TEST_P(AnimationCompositorAnimationsTest, ForceReduceMotionPageSupportsReduce) { +TEST_P(AnimationCompositorAnimationsTest, + ForceReduceMotionDocumentSupportsReduce) { ScopedForceReduceMotionForTest force_reduce_motion(true); GetDocument().GetSettings()->SetPrefersReducedMotion(true); SetBodyInnerHTML(R"HTML( @@ -1083,12 +1087,62 @@ element_ = GetDocument().getElementById("test"); Animation* animation = element_->getAnimations()[0]; - // The effect should snap between keyframes at the halfway points. + // As the page has indicated support for reduce motion, the effect should not + // jump to the nearest keyframe. animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(500), ASSERT_NO_EXCEPTION); EXPECT_NEAR(element_->getBoundingClientRect()->x(), 150.0, 0.001); } +TEST_P(AnimationCompositorAnimationsTest, + ForceReduceMotionChildDocumentSupportsReduce) { + ScopedForceReduceMotionForTest force_reduce_motion(true); + GetDocument().GetSettings()->SetPrefersReducedMotion(true); + SetBodyInnerHTML(R"HTML( + <iframe></iframe> + <style> + @keyframes slide { + 0% { transform: translateX(100px); } + 100% { transform: translateX(200px); } + } + html, body { + margin: 0; + } + </style> + <div id='parent-anim' style='animation: slide 1s linear'></div> + )HTML"); + SetChildFrameHTML(R"HTML( + <meta name='supports-reduced-motion' content='reduce'> + <style> + @keyframes slide { + 0% { transform: translateX(100px); } + 100% { transform: translateX(200px); } + } + html, body { + margin: 0; + } + </style> + <div id='child-anim' style='animation: slide 1s linear'></div> + )HTML"); + UpdateAllLifecyclePhasesForTest(); + element_ = GetDocument().getElementById("parent-anim"); + Animation* animation = element_->getAnimations()[0]; + + // As the parent document does not support reduce motion, the effect will jump + // to the nearest keyframe. + animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(400), + ASSERT_NO_EXCEPTION); + EXPECT_NEAR(element_->getBoundingClientRect()->x(), 100.0, 0.001); + + // As the child document does support reduce motion, its animation will not be + // snapped. + Element* child_element = ChildDocument().getElementById("child-anim"); + Animation* child_animation = child_element->getAnimations()[0]; + child_animation->setCurrentTime(MakeGarbageCollected<V8CSSNumberish>(400), + ASSERT_NO_EXCEPTION); + EXPECT_NEAR(child_element->getBoundingClientRect()->x(), 140.0, 0.001); +} + TEST_P(AnimationCompositorAnimationsTest, CheckCanStartForceReduceMotion) { ScopedForceReduceMotionForTest force_reduce_motion(true); GetDocument().GetSettings()->SetPrefersReducedMotion(true);
diff --git a/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc b/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc index bf00856..2fbe820 100644 --- a/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc +++ b/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc
@@ -81,11 +81,15 @@ const PropertyHandle& property) const { using ApplicableTypesMap = HashMap<PropertyHandle, std::unique_ptr<const InterpolationTypes>>; - // TODO(iclelland): Combine these two hashmaps into a single map on - // std::pair<bool,property> DEFINE_STATIC_LOCAL(ApplicableTypesMap, all_applicable_types_map, ()); DEFINE_STATIC_LOCAL(ApplicableTypesMap, composited_applicable_types_map, ()); + // Reduce motion currently allows no interpolation. When some properties are + // allowed to interpolate we may need to support the combination of + // reduce_motion && !allow_all_animations_ separately. + DEFINE_STATIC_LOCAL(ApplicableTypesMap, reduce_motion_applicable_types_map, + ()); + // Custom property interpolation types may change over time so don't trust the // applicable_types_map without checking the registry. Also since the static // map is shared between documents, the registered type may be different in @@ -94,10 +98,12 @@ if (const auto* registration = GetRegistration(registry_, property)) return registration->GetInterpolationTypes(); } + bool reduce_motion = document_.ShouldForceReduceMotion(); ApplicableTypesMap& applicable_types_map = - allow_all_animations_ ? all_applicable_types_map - : composited_applicable_types_map; + reduce_motion ? reduce_motion_applicable_types_map + : (allow_all_animations_ ? all_applicable_types_map + : composited_applicable_types_map); auto entry = applicable_types_map.find(property); if (entry != applicable_types_map.end()) @@ -114,8 +120,6 @@ PropertyHandle used_property = property.IsCSSProperty() ? property : PropertyHandle(css_property); - bool reduce_motion = document_.ShouldForceReduceMotion(); - // TODO(crbug.com/838263): Support site-defined list of acceptable properties // through permissions policy declarations. bool property_maybe_blocked_by_permissions_policy =
diff --git a/third_party/blink/renderer/core/animation/keyframe_effect.cc b/third_party/blink/renderer/core/animation/keyframe_effect.cc index 1e3dc0c..18ebb7ec 100644 --- a/third_party/blink/renderer/core/animation/keyframe_effect.cc +++ b/third_party/blink/renderer/core/animation/keyframe_effect.cc
@@ -340,6 +340,11 @@ // no visual result. if (!effect_target_) { reasons |= CompositorAnimations::kInvalidAnimationOrEffect; + } else if (!IsCurrent()) { + // There is no reason to composite an effect that is not current, and + // CheckCanStartAnimationOnCompositor might assert about having some but + // not all properties if we call it on such an animation. + reasons |= CompositorAnimations::kInvalidAnimationOrEffect; } else { if (effect_target_->GetComputedStyle() && effect_target_->GetComputedStyle()->HasOffset())
diff --git a/third_party/blink/renderer/core/animation/keyframe_effect_test.cc b/third_party/blink/renderer/core/animation/keyframe_effect_test.cc index 50651213..c31f45a 100644 --- a/third_party/blink/renderer/core/animation/keyframe_effect_test.cc +++ b/third_party/blink/renderer/core/animation/keyframe_effect_test.cc
@@ -479,6 +479,7 @@ TEST_F(KeyframeEffectTest, CheckCanStartAnimationOnCompositorBadTarget) { const double animation_playback_rate = 1; Timing timing; + timing.iteration_duration = ANIMATION_TIME_DELTA_FROM_SECONDS(1); StringKeyframeVector keyframes(2); keyframes[0] = MakeGarbageCollected<StringKeyframe>(); @@ -495,6 +496,8 @@ MakeGarbageCollected<StringKeyframeEffectModel>(keyframes); auto* keyframe_effect = MakeGarbageCollected<KeyframeEffect>(element, effect_model, timing); + Animation* animation = GetDocument().Timeline().Play(keyframe_effect); + (void)animation; // If the target has a CSS offset we can't composite it. element->SetInlineStyleProperty(CSSPropertyID::kOffsetPosition, "50px 50px");
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index e772810..182d0ca 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -6881,9 +6881,6 @@ } void Document::SupportsReducedMotionMetaChanged() { - if (!IsInOutermostMainFrame()) - return; - auto* root_element = documentElement(); if (!root_element) return;
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 116e7db..55dfa7e 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -2337,10 +2337,10 @@ } if (params.reason == AttributeModificationReason::kByParser && - name == html_names::kInitiallyopenAttr && HasValidPopupAttribute()) { + name == html_names::kDefaultopenAttr && HasValidPopupAttribute()) { DCHECK(RuntimeEnabledFeatures::HTMLPopupAttributeEnabled()); DCHECK(!isConnected()); - GetPopupData()->setHadInitiallyOpenWhenParsed(true); + GetPopupData()->setHadDefaultOpenWhenParsed(true); } if (params.reason == AttributeModificationReason::kDirectly && @@ -2554,14 +2554,14 @@ if (!start_node) return nullptr; // We need to walk up from the start node to see if there is a parent popup, - // or the anchor for a popup, or an invoking element (which has the - // "togglepopup" attribute). There can be multiple popups for a single anchor - // element, and an anchor for one popup can also be an invoker for a different - // popup. We need to stop on the highest such popup in the popup stack. - // Additionally, if start_node is inside an element that has an invoking - // attribute (e.g. togglepopup) but wasn't *used* to invoke that popup, we - // still need to stop on that popup, so that a click on that invoking element - // doesn't immediately light-dismiss its target. + // or the anchor for a popup, or an invoking element (which has one of the + // togglepopup/showpopup/hidepopup attribute). There can be multiple popups + // for a single anchor element, and an anchor for one popup can also be an + // invoker for a different popup. We need to stop on the highest such popup in + // the popup stack. Additionally, if start_node is inside an element that has + // an invoking attribute (e.g. togglepopup) but wasn't *used* to invoke that + // popup, we still need to stop on that popup, so that a click on that + // invoking element doesn't immediately light-dismiss its target. // |anchors_and_invokers| is a map from anchors/invokers to their popups, for // all open popups. @@ -3006,12 +3006,12 @@ CustomElement::TryToUpgrade(*this); } - if (GetPopupData() && GetPopupData()->hadInitiallyOpenWhenParsed()) { - // If a Popup element has the `initiallyopen` attribute upon page + if (GetPopupData() && GetPopupData()->hadDefaultOpenWhenParsed()) { + // If a Popup element has the `defaultopen` attribute upon page // load, and it is the *first* such popup, show it. DCHECK(RuntimeEnabledFeatures::HTMLPopupAttributeEnabled()); DCHECK(isConnected()); - GetPopupData()->setHadInitiallyOpenWhenParsed(false); + GetPopupData()->setHadDefaultOpenWhenParsed(false); GetDocument() .GetTaskRunner(TaskType::kDOMManipulation) ->PostTask(FROM_HERE,
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h index 59a76e6..968d8e8 100644 --- a/third_party/blink/renderer/core/dom/element.h +++ b/third_party/blink/renderer/core/dom/element.h
@@ -166,6 +166,13 @@ constexpr const char* kPopupTypeValueHint = "hint"; constexpr const char* kPopupTypeValueAsync = "async"; +enum class PopupTriggerAction { + kNone, + kToggle, + kShow, + kHide, +}; + typedef HeapVector<Member<Attr>> AttrNodeList; typedef HashMap<AtomicString, SpecificTrustedType> AttrNameToTrustedType;
diff --git a/third_party/blink/renderer/core/dom/element.idl b/third_party/blink/renderer/core/dom/element.idl index 27fca1a..9530b71 100644 --- a/third_party/blink/renderer/core/dom/element.idl +++ b/third_party/blink/renderer/core/dom/element.idl
@@ -140,7 +140,7 @@ [MeasureAs=ElementShowPopup,RuntimeEnabled=HTMLPopupAttribute,RaisesException] void showPopup(); [MeasureAs=ElementHidePopup,RuntimeEnabled=HTMLPopupAttribute,RaisesException] void hidePopup(); [Unscopable,CEReactions,RuntimeEnabled=HTMLPopupAttribute,Reflect] attribute DOMString popup; - [CEReactions,RuntimeEnabled=HTMLPopupAttribute,Reflect] attribute boolean initiallyOpen; + [CEReactions,RuntimeEnabled=HTMLPopupAttribute,Reflect] attribute boolean defaultOpen; // Experimental accessibility API [RuntimeEnabled=ComputedAccessibilityInfo] readonly attribute DOMString? computedRole;
diff --git a/third_party/blink/renderer/core/dom/popup_data.h b/third_party/blink/renderer/core/dom/popup_data.h index ab022d4c..29cf0a4a 100644 --- a/third_party/blink/renderer/core/dom/popup_data.h +++ b/third_party/blink/renderer/core/dom/popup_data.h
@@ -21,11 +21,9 @@ bool open() const { return open_; } void setOpen(bool open) { open_ = open; } - bool hadInitiallyOpenWhenParsed() const { - return had_initiallyopen_when_parsed_; - } - void setHadInitiallyOpenWhenParsed(bool value) { - had_initiallyopen_when_parsed_ = value; + bool hadDefaultOpenWhenParsed() const { return had_defaultopen_when_parsed_; } + void setHadDefaultOpenWhenParsed(bool value) { + had_defaultopen_when_parsed_ = value; } PopupValueType type() const { return type_; } @@ -59,7 +57,7 @@ private: bool open_ = false; - bool had_initiallyopen_when_parsed_ = false; + bool had_defaultopen_when_parsed_ = false; PopupValueType type_ = PopupValueType::kNone; WeakMember<Element> invoker_;
diff --git a/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc b/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc index 615a164..554061c 100644 --- a/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc +++ b/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc
@@ -234,8 +234,10 @@ if (!frame) return; - // Record what source was used to find main frame CSP. - if (frame->IsMainFrame()) { + // Record what source was used to find main frame CSP. Do not record + // this for fence frame roots since they will never become an + // outermost main frame, but we do wish to record this for portals. + if (frame->IsMainFrame() && !frame->IsInFencedFrameTree()) { for (const auto& policy : policies) { switch (policy->header->source) { case network::mojom::ContentSecurityPolicySource::kHTTP:
diff --git a/third_party/blink/renderer/core/html/forms/html_button_element.cc b/third_party/blink/renderer/core/html/forms/html_button_element.cc index 820176af5b..1d79666 100644 --- a/third_party/blink/renderer/core/html/forms/html_button_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_button_element.cc
@@ -26,6 +26,7 @@ #include "third_party/blink/renderer/core/html/forms/html_button_element.h" #include "third_party/blink/renderer/core/dom/attribute.h" +#include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/events/simulated_click_options.h" #include "third_party/blink/renderer/core/events/keyboard_event.h" #include "third_party/blink/renderer/core/frame/web_feature.h" @@ -109,10 +110,15 @@ void HTMLButtonElement::DefaultEventHandler(Event& event) { if (event.type() == event_type_names::kDOMActivate) { - if (Element* popupElement = togglePopupElement()) { - if (popupElement->popupOpen()) { + PopupTriggerAction action; + if (Element* popupElement = togglePopupElement(action)) { + DCHECK_NE(action, PopupTriggerAction::kNone); + if (popupElement->popupOpen() && (action == PopupTriggerAction::kToggle || + action == PopupTriggerAction::kHide)) { popupElement->hidePopup(ASSERT_NO_EXCEPTION); - } else { + } else if (!popupElement->popupOpen() && + (action == PopupTriggerAction::kToggle || + action == PopupTriggerAction::kShow)) { popupElement->InvokePopup(this); } } @@ -134,20 +140,52 @@ HTMLFormControlElement::DefaultEventHandler(event); } -Element* HTMLButtonElement::togglePopupElement() const { +// The element returned if that element a) exists, and b) is a valid Popup +// element. If multiple toggle attributes are present: +// 1. Only one idref will ever be used, if multiple attributes are present. +// 2. If 'togglepopup' is present, its IDREF will be used. +// 3. If 'showpopup' is present and 'togglepopup' isn't, its IDREF will be +// used. +// 4. If both 'showpopup' and 'hidepopup' are present, the behavior is to +// toggle. +Element* HTMLButtonElement::togglePopupElement( + PopupTriggerAction& action) const { + action = PopupTriggerAction::kNone; if (!RuntimeEnabledFeatures::HTMLPopupAttributeEnabled()) return nullptr; - const AtomicString& toggle_id = - FastGetAttribute(html_names::kTogglepopupAttr); - if (toggle_id.IsNull()) - return nullptr; if (!IsInTreeScope()) return nullptr; - Element* popup_element = GetTreeScope().getElementById(toggle_id); - if (!popup_element || !popup_element->HasValidPopupAttribute()) + AtomicString idref; + if (FastHasAttribute(html_names::kTogglepopupAttr)) { + idref = FastGetAttribute(html_names::kTogglepopupAttr); + action = PopupTriggerAction::kToggle; + } else if (FastHasAttribute(html_names::kShowpopupAttr)) { + idref = FastGetAttribute(html_names::kShowpopupAttr); + action = PopupTriggerAction::kShow; + } + if (FastHasAttribute(html_names::kHidepopupAttr)) { + if (idref.IsNull()) { + idref = FastGetAttribute(html_names::kHidepopupAttr); + action = PopupTriggerAction::kHide; + } else if (FastGetAttribute(html_names::kHidepopupAttr) == idref) { + action = PopupTriggerAction::kToggle; + } + } + if (idref.IsNull()) { + DCHECK_EQ(action, PopupTriggerAction::kNone); return nullptr; + } + Element* popup_element = GetTreeScope().getElementById(idref); + if (!popup_element || !popup_element->HasValidPopupAttribute()) { + action = PopupTriggerAction::kNone; + return nullptr; + } return popup_element; } +Element* HTMLButtonElement::togglePopupElement() const { + PopupTriggerAction action; + return togglePopupElement(action); +} bool HTMLButtonElement::HasActivationBehavior() const { return true;
diff --git a/third_party/blink/renderer/core/html/forms/html_button_element.h b/third_party/blink/renderer/core/html/forms/html_button_element.h index 38090444..8cfd2e3 100644 --- a/third_party/blink/renderer/core/html/forms/html_button_element.h +++ b/third_party/blink/renderer/core/html/forms/html_button_element.h
@@ -45,8 +45,9 @@ mojom::blink::FocusType, InputDeviceCapabilities*) override; - // Retrieves the element pointed to by the 'togglepopup' content attribute, - // if that element a) exists, and b) is a valid Popup element. + // Retrieves the element pointed to by 'togglepopup', 'showpopup', and/or + // 'hidepopup' content attributes, if any. + Element* togglePopupElement(PopupTriggerAction& action) const; Element* togglePopupElement() const; private:
diff --git a/third_party/blink/renderer/core/html/html_attribute_names.json5 b/third_party/blink/renderer/core/html/html_attribute_names.json5 index 29ff53f1..bcd7657 100644 --- a/third_party/blink/renderer/core/html/html_attribute_names.json5 +++ b/third_party/blink/renderer/core/html/html_attribute_names.json5
@@ -105,6 +105,7 @@ "headers", "height", "hidden", + "hidepopup", "high", "href", "hreflang", @@ -116,7 +117,7 @@ "imagesrcset", "incremental", "inert", - "initiallyopen", + "defaultopen", "inputmode", "integrity", "is", @@ -312,6 +313,7 @@ "shadowroot", "shadowrootdelegatesfocus", "shape", + "showpopup", "size", "sizes", "slot",
diff --git a/third_party/blink/renderer/core/html/html_link_element.cc b/third_party/blink/renderer/core/html/html_link_element.cc index 6116761..2fdff26 100644 --- a/third_party/blink/renderer/core/html/html_link_element.cc +++ b/third_party/blink/renderer/core/html/html_link_element.cc
@@ -68,7 +68,8 @@ const AtomicString& value = params.new_value; if (name == html_names::kRelAttr) { rel_attribute_ = LinkRelAttribute(value); - if (rel_attribute_.IsMonetization() && !GetDocument().ParentDocument()) { + if (rel_attribute_.IsMonetization() && + GetDocument().IsInOutermostMainFrame()) { // TODO(1031476): The Web Monetization specification is an unofficial // draft, available at https://webmonetization.org/specification.html // Currently it relies on a <meta> tag but there is an open issue about
diff --git a/third_party/blink/renderer/core/html/html_meta_element.cc b/third_party/blink/renderer/core/html/html_meta_element.cc index 1aae2c0..265f103e0 100644 --- a/third_party/blink/renderer/core/html/html_meta_element.cc +++ b/third_party/blink/renderer/core/html/html_meta_element.cc
@@ -618,7 +618,7 @@ // TODO(1031476): The Web Monetization specification is an unofficial draft, // available at https://webmonetization.org/specification.html // For now, only use counters are implemented in Blink. - if (!GetDocument().ParentDocument()) { + if (GetDocument().IsInOutermostMainFrame()) { UseCounter::Count(&GetDocument(), WebFeature::kHTMLMetaElementMonetization); }
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc index b8fb439..e0ce5c9 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
@@ -3171,12 +3171,24 @@ }; HeapVector<ResultAndOffsets> result_and_offsets; + HeapVector<GridItemPlacementData*> out_of_fragmentainer_space_item_placement; BaselineAccumulator baseline_accumulator; LayoutUnit max_row_expansion; wtf_size_t expansion_row_set_index; wtf_size_t breakpoint_row_set_index; bool has_subsequent_children; + auto UpdateBreakpointRowSetIndex = [&](wtf_size_t row_set_index) { + if (row_set_index >= breakpoint_row_set_index) + return; + + // We may have inserted a row-breakpoint due to an item running out of + // fragmentainer space. + // Clear this list if we select a different row-breakpoint. + out_of_fragmentainer_space_item_placement.clear(); + breakpoint_row_set_index = row_set_index; + }; + LayoutUnit fragmentainer_space = FragmentainerSpaceAtBfcStart(ConstraintSpace()); const LayoutUnit previous_consumed_block_size = @@ -3188,6 +3200,7 @@ auto PlaceItems = [&]() { // Reset our state. result_and_offsets.clear(); + out_of_fragmentainer_space_item_placement.clear(); baseline_accumulator = BaselineAccumulator(); max_row_expansion = LayoutUnit(); expansion_row_set_index = kNotFound; @@ -3199,7 +3212,7 @@ for (const auto& grid_item : grid_items.item_data) { // Grab the offsets and break-token (if present) for this child. - const auto& item_placement_data = *(placement_data_it++); + auto& item_placement_data = *(placement_data_it++); const NGBlockBreakToken* break_token = nullptr; if (child_break_token_it != child_break_tokens.end()) { if ((*child_break_token_it)->InputNode() == grid_item.node) @@ -3256,8 +3269,9 @@ // item into the next fragmentainer. if (result->Status() != NGLayoutResult::kSuccess) { DCHECK_EQ(result->Status(), NGLayoutResult::kOutOfFragmentainerSpace); - breakpoint_row_set_index = - std::min(item_row_set_index, breakpoint_row_set_index); + UpdateBreakpointRowSetIndex(item_row_set_index); + out_of_fragmentainer_space_item_placement.push_back( + &item_placement_data); continue; } @@ -3280,7 +3294,7 @@ // The row may have a forced break, move it to the next fragmentainer. if (IsForcedBreakValue(ConstraintSpace(), break_between)) { container_builder_.SetHasForcedBreak(); - breakpoint_row_set_index = item_row_set_index; + UpdateBreakpointRowSetIndex(item_row_set_index); continue; } @@ -3291,7 +3305,7 @@ if (!MovePastBreakpoint(ConstraintSpace(), grid_item.node, *result, fragment_relative_block_offset, appeal_before, /* builder */ nullptr)) { - breakpoint_row_set_index = item_row_set_index; + UpdateBreakpointRowSetIndex(item_row_set_index); // We are choosing to add an early breakpoint at a row. Propagate our // space shortage to the column balancer. @@ -3314,7 +3328,7 @@ // Forced row breaks should have been already handled, accept any // row with an "auto" break-between. if (row_break_between[index] == EBreakBetween::kAuto) { - breakpoint_row_set_index = index; + UpdateBreakpointRowSetIndex(index); break; } } @@ -3396,10 +3410,12 @@ if (breakpoint_row_set_index == kNotFound) return false; - const LayoutUnit fragment_relative_row_offset = + LayoutUnit row_offset = layout_data->Rows()->GetSetOffset(breakpoint_row_set_index) + - (*row_offset_adjustments)[breakpoint_row_set_index] - - previous_consumed_block_size; + (*row_offset_adjustments)[breakpoint_row_set_index]; + + const LayoutUnit fragment_relative_row_offset = + row_offset - previous_consumed_block_size; // We may be within the initial column-balancing pass (where we have an // indefinite fragmentainer size). If we have a forced break, re-run @@ -3417,12 +3433,20 @@ if (row_offset_delta <= LayoutUnit()) return false; + row_offset += row_offset_delta; *intrinsic_block_size += row_offset_delta; AdjustItemOffsets(breakpoint_row_set_index, row_offset_delta); auto* it = row_offset_adjustments->begin() + breakpoint_row_set_index; while (it != row_offset_adjustments->end()) *(it++) += row_offset_delta; + + // For any items that ran out of fragmentainer-space, make them block-start + // aligned (as they may be center/end aligned, and still not have enough + // space). + for (auto* item_placement_data : out_of_fragmentainer_space_item_placement) + item_placement_data->offset.block_offset = row_offset; + return true; };
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index 25fa9b4f..50641ed 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -2767,7 +2767,7 @@ if (response_.IsSignedExchangeInnerResponse()) { CountUse(WebFeature::kSignedExchangeInnerResponse); - CountUse(frame_->IsMainFrame() + CountUse(frame_->IsOutermostMainFrame() ? WebFeature::kSignedExchangeInnerResponseInMainFrame : WebFeature::kSignedExchangeInnerResponseInSubFrame); }
diff --git a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc index e58c4f3..b460595 100644 --- a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc +++ b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc
@@ -203,7 +203,8 @@ return false; const gfx::RectF rect = element->GetBoundingClientRectNoLifecycleUpdate(); - if (!rect.IsEmpty()) { + if (!rect.IsEmpty() && !isnan(rect.x()) && !isnan(rect.y()) && + !isnan(rect.right()) && !isnan(rect.bottom())) { // Expand each corner by the size of fingertips. const int top = ClampTo<int>(rect.y() - finger_radius); const int bottom = ClampTo<int>(rect.bottom() + finger_radius);
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc index 69c35483..9e58ac5 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -1111,13 +1111,13 @@ UseCounter::Count(&execution_context, WebFeature::kXMLHttpRequestSynchronous); if (auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext())) { if (Frame* frame = window->GetFrame()) { - if (frame->IsMainFrame()) { - UseCounter::Count(&execution_context, - WebFeature::kXMLHttpRequestSynchronousInMainFrame); - } else if (frame->IsCrossOriginToMainFrame()) { + if (frame->IsCrossOriginToOutermostMainFrame()) { UseCounter::Count( &execution_context, WebFeature::kXMLHttpRequestSynchronousInCrossOriginSubframe); + } else if (frame->IsMainFrame()) { + UseCounter::Count(&execution_context, + WebFeature::kXMLHttpRequestSynchronousInMainFrame); } else { UseCounter::Count( &execution_context,
diff --git a/third_party/blink/renderer/modules/payments/payment_request_for_invalid_origin_or_ssl_test.cc b/third_party/blink/renderer/modules/payments/payment_request_for_invalid_origin_or_ssl_test.cc index 1eef0c2c..0bfb5717 100644 --- a/third_party/blink/renderer/modules/payments/payment_request_for_invalid_origin_or_ssl_test.cc +++ b/third_party/blink/renderer/modules/payments/payment_request_for_invalid_origin_or_ssl_test.cc
@@ -33,7 +33,6 @@ } void Show(bool wait_for_updated_details) override {} - void ShowNew(bool wait_for_updated_details) override {} void Retry( payments::mojom::blink::PaymentValidationErrorsPtr errors) override { NOTREACHED();
diff --git a/third_party/blink/renderer/modules/payments/payment_request_optional_total_test.cc b/third_party/blink/renderer/modules/payments/payment_request_optional_total_test.cc index e5e13ae..6342867 100644 --- a/third_party/blink/renderer/modules/payments/payment_request_optional_total_test.cc +++ b/third_party/blink/renderer/modules/payments/payment_request_optional_total_test.cc
@@ -30,7 +30,6 @@ } void Show(bool wait_for_updated_details) override { NOTREACHED(); } - void ShowNew(bool wait_for_updated_details) override { NOTREACHED(); } void Retry( payments::mojom::blink::PaymentValidationErrorsPtr errors) override { NOTREACHED();
diff --git a/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc b/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc index 31f9b48b..df8e04e5 100644 --- a/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc +++ b/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
@@ -4,7 +4,9 @@ #include "third_party/blink/renderer/modules/scheduler/dom_scheduler.h" +#include "third_party/blink/renderer/bindings/core/v8/idl_types.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_scheduler_post_task_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_task_signal.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" @@ -13,6 +15,7 @@ #include "third_party/blink/renderer/modules/scheduler/dom_task.h" #include "third_party/blink/renderer/modules/scheduler/dom_task_signal.h" #include "third_party/blink/renderer/platform/bindings/enumeration_base.h" +#include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h" #include "third_party/blink/renderer/platform/scheduler/public/task_attribution_tracker.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" #include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h" @@ -67,8 +70,10 @@ return ScriptPromise(); } if (options->hasSignal() && options->signal()->aborted()) { - exception_state.ThrowDOMException(DOMExceptionCode::kAbortError, - "The task was aborted"); + exception_state.RethrowV8Exception( + ToV8Traits<IDLAny>::ToV8(script_state, + options->signal()->reason(script_state)) + .ToLocalChecked()); return ScriptPromise(); }
diff --git a/third_party/blink/renderer/modules/scheduler/dom_task.cc b/third_party/blink/renderer/modules/scheduler/dom_task.cc index 89e91c2..ebeaf04 100644 --- a/third_party/blink/renderer/modules/scheduler/dom_task.cc +++ b/third_party/blink/renderer/modules/scheduler/dom_task.cc
@@ -8,8 +8,10 @@ #include "base/check_op.h" #include "base/metrics/histogram_macros.h" +#include "third_party/blink/renderer/bindings/core/v8/idl_types.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_scheduler_post_task_callback.h" @@ -162,13 +164,15 @@ return; } - // switch to the resolver's context to let DOMException pick up the resolver's - // JS stack + // Switch to the resolver's context to let DOMException pick up the resolver's + // JS stack. ScriptState::Scope script_state_scope(resolver_script_state); // TODO(crbug.com/1293949): Add an error message. - resolver_->Reject(V8ThrowDOMException::CreateOrDie( - resolver_script_state->GetIsolate(), DOMExceptionCode::kAbortError, "")); + resolver_->Reject( + ToV8Traits<IDLAny>::ToV8(resolver_script_state, + signal_->reason(resolver_script_state)) + .ToLocalChecked()); } void DOMTask::RecordTaskStartMetrics() {
diff --git a/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.cc b/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.cc index 75a6c8c..37be508c 100644 --- a/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.cc +++ b/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.cc
@@ -95,27 +95,27 @@ TaskAttributionTrackerImpl::CreateTaskScope( ScriptState* script_state, absl::optional<TaskId> parent_task_id) { + absl::optional<TaskId> previous_task_id = running_task_id_; + DCHECK(v8_adapter_); + absl::optional<TaskId> previous_v8_task_id = + v8_adapter_->GetValue(script_state); + next_task_id_ = next_task_id_.NextTaskId(); running_task_id_ = next_task_id_; InsertTaskIdPair(next_task_id_, parent_task_id); - running_task_ids_.push_back(next_task_id_); SaveTaskIdStateInV8(script_state, next_task_id_); - return std::make_unique<TaskScopeImpl>(script_state, this, next_task_id_); + return std::make_unique<TaskScopeImpl>(script_state, this, next_task_id_, + previous_task_id, previous_v8_task_id); } -void TaskAttributionTrackerImpl::TaskScopeCompleted(ScriptState* script_state, - TaskId scope_id) { - DCHECK(!running_task_ids_.IsEmpty()); - DCHECK(running_task_ids_.back() == scope_id); - running_task_ids_.pop_back(); - if (!running_task_ids_.IsEmpty()) { - running_task_id_ = running_task_ids_.back(); - } else { - running_task_id_ = absl::nullopt; - } - SaveTaskIdStateInV8(script_state, running_task_id_); +void TaskAttributionTrackerImpl::TaskScopeCompleted( + const TaskScopeImpl& task_scope) { + DCHECK(running_task_id_ == task_scope.GetTaskId()); + running_task_id_ = task_scope.PreviousTaskId(); + SaveTaskIdStateInV8(task_scope.GetScriptState(), + task_scope.PreviousV8TaskId()); } void TaskAttributionTrackerImpl::SaveTaskIdStateInV8( @@ -130,13 +130,17 @@ TaskAttributionTrackerImpl::TaskScopeImpl::TaskScopeImpl( ScriptState* script_state, TaskAttributionTrackerImpl* task_tracker, - TaskId scope_task_id) + TaskId scope_task_id, + absl::optional<TaskId> previous_task_id, + absl::optional<TaskId> previous_v8_task_id) : task_tracker_(task_tracker), scope_task_id_(scope_task_id), + previous_task_id_(previous_task_id), + previous_v8_task_id_(previous_v8_task_id), script_state_(script_state) {} TaskAttributionTrackerImpl::TaskScopeImpl::~TaskScopeImpl() { - task_tracker_->TaskScopeCompleted(script_state_, scope_task_id_); + task_tracker_->TaskScopeCompleted(*this); } // V8Adapter's implementation @@ -148,6 +152,7 @@ return absl::nullopt; } + ScriptState::Scope scope(script_state); v8::Local<v8::Context> context = script_state->GetContext(); DCHECK(!context.IsEmpty()); v8::Local<v8::Value> v8_value =
diff --git a/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.h b/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.h index 193bebb..05348267 100644 --- a/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.h +++ b/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.h
@@ -45,8 +45,6 @@ void SetRunningTaskId(absl::optional<TaskId> id) { running_task_id_ = id; } - void TaskScopeCompleted(ScriptState*, TaskId); - private: struct TaskIdPair { TaskIdPair() = default; @@ -61,14 +59,27 @@ class TaskScopeImpl : public TaskScope { public: - TaskScopeImpl(ScriptState*, TaskAttributionTrackerImpl*, TaskId); + TaskScopeImpl(ScriptState*, + TaskAttributionTrackerImpl*, + TaskId scope_task_id, + absl::optional<TaskId> previous_task_id, + absl::optional<TaskId> previous_v8_task_id); ~TaskScopeImpl() override; TaskScopeImpl(const TaskScopeImpl&) = delete; TaskScopeImpl& operator=(const TaskScopeImpl&) = delete; + TaskId GetTaskId() const { return scope_task_id_; } + absl::optional<TaskId> PreviousTaskId() const { return previous_task_id_; } + absl::optional<TaskId> PreviousV8TaskId() const { + return previous_v8_task_id_; + } + ScriptState* GetScriptState() const { return script_state_; } + private: TaskAttributionTrackerImpl* task_tracker_; TaskId scope_task_id_; + absl::optional<TaskId> previous_task_id_; + absl::optional<TaskId> previous_v8_task_id_; Persistent<ScriptState> script_state_; }; @@ -79,6 +90,7 @@ virtual ~V8Adapter() = default; }; + void TaskScopeCompleted(const TaskScopeImpl&); TaskIdPair& GetTaskIdPairFromTaskContainer(TaskId); void InsertTaskIdPair(TaskId task_id, absl::optional<TaskId> parent_task_id); void SaveTaskIdStateInV8(ScriptState*, absl::optional<TaskId>); @@ -89,7 +101,6 @@ TaskId next_task_id_; absl::optional<TaskId> running_task_id_; - WTF::Vector<TaskId> running_task_ids_; std::unique_ptr<V8Adapter> v8_adapter_;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 7732cac..bb12861a 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -112,7 +112,7 @@ }, { name: "AbortSignalTimeout", - status: "experimental", + status: "stable", }, { name: "Accelerated2dCanvas",
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 1bfe54e..111aee6 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -3365,6 +3365,10 @@ crbug.com/626703 virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/worker-interception.https.html [ Pass ] # ====== Test expectations added to unblock wpt-importer ====== +crbug.com/626703 external/wpt/fetch/metadata/generated/worker-dedicated-constructor.sub.html [ Failure ] +crbug.com/626703 virtual/plz-dedicated-worker/external/wpt/fetch/metadata/generated/worker-dedicated-constructor.sub.html [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/web-bundle/subresource-loading/script-reuse-web-bundle-resource.https.tentative.html [ Failure ] +crbug.com/626703 [ Mac ] external/wpt/web-bundle/subresource-loading/script-reuse-web-bundle-resource.https.tentative.html [ Failure ] crbug.com/626703 virtual/threaded/external/wpt/requestidlecallback/deadline-max-timeout-dynamic.html [ Failure ] crbug.com/626703 external/wpt/service-workers/service-worker/navigation-timing-extended.https.html [ Failure ] crbug.com/626703 fast/animation/scroll-animations/scroll-animation-lifetime.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/grid/grid-nested-columns-crash.html b/third_party/blink/web_tests/external/wpt/css/css-break/grid/grid-nested-columns-crash.html new file mode 100644 index 0000000..8b636ae7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/grid/grid-nested-columns-crash.html
@@ -0,0 +1,11 @@ +<!-- quirks-mode --> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1318608"> +<style> +html, div { + column-count: 2; +} +</style> +<body style="display: grid; align-items: end;"> + <div>a</div> + <div> + <span style="display: block; contain: size;">content</span>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-initiallyopen-2.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-defaultopen-2.tentative.html similarity index 80% rename from third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-initiallyopen-2.tentative.html rename to third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-defaultopen-2.tentative.html index a55d33d..1e54e469 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-initiallyopen-2.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-defaultopen-2.tentative.html
@@ -5,9 +5,9 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<div popup=popup id=p1 initiallyopen> +<div popup=popup id=p1 defaultopen> Outer popup - <div popup=popup id=p2 initiallyopen> + <div popup=popup id=p2 defaultopen> Inner popup </div> </div> @@ -18,7 +18,7 @@ test(function(){ assert_true(p1.matches(':popup-open'),'The first (outermost) popup should be the one that opens in this case'); assert_false(p2.matches(':popup-open'),'The inner popup should not be open'); - }, "The initiallyopen attribute should cause only the first popup to open"); + }, "The defaultopen attribute should cause only the first popup to open"); }); }); </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-initiallyopen-display-ref.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-defaultopen-display-ref.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-initiallyopen-display-ref.tentative.html rename to third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-defaultopen-display-ref.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-defaultopen-display.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-defaultopen-display.tentative.html new file mode 100644 index 0000000..179e071 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-defaultopen-display.tentative.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel=author href="mailto:masonf@chromium.org"> +<link rel=help href="https://open-ui.org/components/popup.research.explainer"> +<link rel=match href="popup-defaultopen-display-ref.tentative.html"> + +<div popup=popup id=p1 defaultopen>This is a popup, which should be open upon load</div> +<div popup=popup id=p2 defaultopen>This is a second popup with defaultopen, which should NOT be open upon load</div> + +<style> + [popup] { + width: fit-content; + height: fit-content; + border: 1px solid; + padding: 1em; + background: white; + color: black; + } + #p1 { + top:0; + } + #p2 { + top:100px; + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-defaultopen.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-defaultopen.tentative.html new file mode 100644 index 0000000..50bf825 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-defaultopen.tentative.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel=author href="mailto:masonf@chromium.org"> +<link rel=help href="https://open-ui.org/components/popup.research.explainer"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div popup=popup id=p1 defaultopen>This is a popup, which should be open upon load</div> +<script></script> <!-- Possibly yield the parser, just to double-check --> +<div popup=popup id=p2 defaultopen>This is a second popup with defaultopen, which should NOT be open upon load</div> +<div popup=hint id=p2b defaultopen>This is a hint popup with defaultopen, which should NOT be open upon load</div> +<div popup=popup id=p3>Also not visible</div> + +<div popup=async id=p4 defaultopen>This is an async popup with defaultopen, which should be open upon load</div> +<div popup=async id=p5 defaultopen>This is an async popup with defaultopen, which should be open upon load</div> + +<script> + requestAnimationFrame(() => { + requestAnimationFrame(() => { + test(function(){ + assert_true(p1.matches(':popup-open'),'defaultopen should open the popup'); + assert_true(p1.hasAttribute('defaultopen')); + assert_true(p1.defaultOpen,'defaultopen should be reflected in the IDL attribute'); + assert_false(p2.matches(':popup-open'), 'Only the first popup with defaultopen should be open on load'); + assert_true(p2.hasAttribute('defaultopen'),'defaultopen should be present/true, even if not opened'); + assert_true(p2.defaultOpen,'defaultopen should be present/true, even if not opened'); + + assert_false(p2b.matches(':popup-open'),'Only the first popup/hint with defaultopen should be open on load'); + assert_true(p4.matches(':popup-open'),'defaultopen should open all async popups'); + assert_true(p5.matches(':popup-open'),'defaultopen should open all async popups'); + + assert_false(p3.matches(':popup-open')); + p3.setAttribute('defaultopen',''); + assert_false(p3.matches(':popup-open'), 'Changing defaultopen should not affect open status'); + assert_true(p3.hasAttribute('defaultopen')); + assert_true(p3.defaultOpen,'defaultopen should still reflect to IDL'); + + p1.removeAttribute('defaultopen'); + assert_true(p1.matches(':popup-open'),'removing defaultopen should not close the popup'); + assert_false(p1.hasAttribute('defaultopen'),'...but it should reflect to IDL'); + + p1.hidePopup(); + }, "The defaultopen attribute should affect page load only"); + }); + }); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-initiallyopen-display.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-initiallyopen-display.tentative.html deleted file mode 100644 index baefeca9..0000000 --- a/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-initiallyopen-display.tentative.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<link rel=author href="mailto:masonf@chromium.org"> -<link rel=help href="https://open-ui.org/components/popup.research.explainer"> -<link rel=match href="popup-initiallyopen-display-ref.tentative.html"> - -<div popup=popup id=p1 initiallyopen>This is a popup, which should be open upon load</div> -<div popup=popup id=p2 initiallyopen>This is a second popup with initiallyopen, which should NOT be open upon load</div> - -<style> - [popup] { - width: fit-content; - height: fit-content; - border: 1px solid; - padding: 1em; - background: white; - color: black; - } - #p1 { - top:0; - } - #p2 { - top:100px; - } -</style>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-initiallyopen.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-initiallyopen.tentative.html deleted file mode 100644 index 9396e01..0000000 --- a/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-initiallyopen.tentative.html +++ /dev/null
@@ -1,46 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<link rel=author href="mailto:masonf@chromium.org"> -<link rel=help href="https://open-ui.org/components/popup.research.explainer"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> - -<div popup=popup id=p1 initiallyopen>This is a popup, which should be open upon load</div> -<script></script> <!-- Possibly yield the parser, just to double-check --> -<div popup=popup id=p2 initiallyopen>This is a second popup with initiallyopen, which should NOT be open upon load</div> -<div popup=hint id=p2b initiallyopen>This is a hint popup with initiallyopen, which should NOT be open upon load</div> -<div popup=popup id=p3>Also not visible</div> - -<div popup=async id=p4 initiallyopen>This is an async popup with initiallyopen, which should be open upon load</div> -<div popup=async id=p5 initiallyopen>This is an async popup with initiallyopen, which should be open upon load</div> - -<script> - requestAnimationFrame(() => { - requestAnimationFrame(() => { - test(function(){ - assert_true(p1.matches(':popup-open'),'initiallyopen should open the popup'); - assert_true(p1.hasAttribute('initiallyopen')); - assert_true(p1.initiallyOpen,'initiallyopen should be reflected in the IDL attribute'); - assert_false(p2.matches(':popup-open'), 'Only the first popup with initiallyopen should be open on load'); - assert_true(p2.hasAttribute('initiallyopen'),'initiallyopen should be present/true, even if not opened'); - assert_true(p2.initiallyOpen,'initiallyopen should be present/true, even if not opened'); - - assert_false(p2b.matches(':popup-open'),'Only the first popup/hint with initiallyopen should be open on load'); - assert_true(p4.matches(':popup-open'),'initiallyopen should open all async popups'); - assert_true(p5.matches(':popup-open'),'initiallyopen should open all async popups'); - - assert_false(p3.matches(':popup-open')); - p3.setAttribute('initiallyopen',''); - assert_false(p3.matches(':popup-open'), 'Changing initiallyopen should not affect open status'); - assert_true(p3.hasAttribute('initiallyopen')); - assert_true(p3.initiallyOpen,'initiallyopen should still reflect to IDL'); - - p1.removeAttribute('initiallyopen'); - assert_true(p1.matches(':popup-open'),'removing initiallyopen should not close the popup'); - assert_false(p1.hasAttribute('initiallyopen'),'...but it should reflect to IDL'); - - p1.hidePopup(); - }, "The initiallyopen attribute should affect page load only"); - }); - }); -</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-invoking-attribute.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-invoking-attribute.tentative.html index 22ffce6b..7108acc 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-invoking-attribute.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/popups/popup-invoking-attribute.tentative.html
@@ -21,47 +21,119 @@ </style> <script> - function clickOn(element) { - const actions = new test_driver.Actions(); - return actions.pointerMove(0, 0, {origin: element}) - .pointerDown({button: actions.ButtonType.LEFT}) - .pointerUp({button: actions.ButtonType.LEFT}) - .send(); - } +function clickOn(element) { + const actions = new test_driver.Actions(); + return actions.pointerMove(0, 0, {origin: element}) + .pointerDown({button: actions.ButtonType.LEFT}) + .pointerUp({button: actions.ButtonType.LEFT}) + .send(); +} - const popup = document.querySelector('[popup]'); - const button = document.querySelector('button'); - let showCount = 0; - let hideCount = 0; - popup.addEventListener('show',() => ++showCount); - popup.addEventListener('hide',() => ++hideCount); +const popup = document.querySelector('[popup]'); +const button = document.querySelector('button'); +let showCount = 0; +let hideCount = 0; +popup.addEventListener('show',() => ++showCount); +popup.addEventListener('hide',() => ++hideCount); - async function assertState(expectOpen,expectShow,expectHide) { - assert_equals(popup.matches(':popup-open'),expectOpen,'Popup open state is incorrect'); - await new Promise(resolve => requestAnimationFrame(resolve)); - assert_equals(showCount,expectShow,'Show count is incorrect'); - assert_equals(hideCount,expectHide,'Hide count is incorrect'); - } +async function assertState(expectOpen,expectShow,expectHide) { + assert_equals(popup.matches(':popup-open'),expectOpen,'Popup open state is incorrect'); + await new Promise(resolve => requestAnimationFrame(resolve)); + assert_equals(showCount,expectShow,'Show count is incorrect'); + assert_equals(hideCount,expectHide,'Hide count is incorrect'); +} - promise_test(async () => { - showCount = hideCount = 0; - await assertState(false,0,0); - await clickOn(button); - await assertState(true,1,0); - popup.hidePopup(); - await assertState(false,1,1); - button.click(); - await assertState(true,2,1); - popup.hidePopup(); - await assertState(false,2,2); - }, "Clicking a togglepopup button opens a closed popup"); +promise_test(async () => { + showCount = hideCount = 0; + await assertState(false,0,0); + await clickOn(button); + await assertState(true,1,0); + popup.hidePopup(); + await assertState(false,1,1); + button.click(); + await assertState(true,2,1); + popup.hidePopup(); + await assertState(false,2,2); +}, "Clicking a togglepopup button opens a closed popup"); - promise_test(async () => { - showCount = hideCount = 0; - await assertState(false,0,0); - await clickOn(button); - await assertState(true,1,0); - await clickOn(button); - await assertState(false,1,1); - }, "Clicking a togglepopup button closes an open popup"); +promise_test(async () => { + showCount = hideCount = 0; + await assertState(false,0,0); + await clickOn(button); + await assertState(true,1,0); + await clickOn(button); + await assertState(false,1,1); +}, "Clicking a togglepopup button closes an open popup"); + +["popup","hint","async"].forEach(type => { + [0,1,2].forEach(t => { + [0,1,2].forEach(s => { + [0,1,2].forEach(h => { + const popup1 = Object.assign(document.createElement('div'),{popup: type, id: 'popup-1'}); + const popup2 = Object.assign(document.createElement('div'),{popup: type, id: 'popup-2'}); + assert_not_equals(popup1.id,popup2.id); + assert_true(!document.getElementById(popup1.id)); + assert_true(!document.getElementById(popup2.id)); + const button = document.createElement('button'); + document.body.appendChild(popup1); + document.body.appendChild(popup2); + document.body.appendChild(button); + if (t) button.setAttribute('togglepopup',t===1 ? popup1.id : popup2.id); + if (s) button.setAttribute('showpopup',s===1 ? popup1.id : popup2.id); + if (h) button.setAttribute('hidepopup',h===1 ? popup1.id : popup2.id); + test(() => { + // This mimics the expected logic: + let expectedBehavior = t ? "toggle" : (s ? "show" : (h ? "hide" : "none")); + let expectedId = t || s || h || 1; + if (!t && s && h) { + // Special case - only use toggle if the show/hide idrefs match. + expectedBehavior = (s === h) ? "toggle" : "show"; + } + const otherId = expectedId !== 1 ? 1 : 2; + function assert_popup(num,state,message) { + assert_true(num>0); + assert_equals((num===1 ? popup1 : popup2).matches(':popup-open'),state,message || ""); + } + assert_popup(expectedId,false); + assert_popup(otherId,false); + button.click(); + assert_popup(otherId,false,'The other popup should never change'); + switch (expectedBehavior) { + case "toggle": + case "show": + assert_popup(expectedId,true,'Toggle or show should show the popup'); + (expectedId===1 ? popup1 : popup2).hidePopup(); // Hide the popup + break; + case "hide": + case "none": + assert_popup(expectedId,false,'Hide or none should leave the popup hidden'); + break; + default: + assert_unreached(); + } + (expectedId===1 ? popup1 : popup2).showPopup(); // Show the popup + assert_popup(expectedId,true); + assert_popup(otherId,false); + button.click(); + assert_popup(otherId,false,'The other popup should never change'); + switch (expectedBehavior) { + case "toggle": + case "hide": + assert_popup(expectedId,false,'Toggle or hide should hide the popup'); + break; + case "show": + case "none": + assert_popup(expectedId,true,'Show or none should leave the popup showing'); + break; + default: + assert_unreached(); + } + },`Test ${button.outerHTML} with popup=${type}`); + button.remove(); + popup1.remove(); + popup2.remove(); + }); + }); + }); +}); </script>
diff --git a/third_party/blink/web_tests/external/wpt/scheduler/post-task-abort-reason.any.js b/third_party/blink/web_tests/external/wpt/scheduler/post-task-abort-reason.any.js new file mode 100644 index 0000000..27eff9f0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/scheduler/post-task-abort-reason.any.js
@@ -0,0 +1,37 @@ +// META: title=Scheduler: postTask uses abort reason +// META: global=window,worker +'use strict'; + +promise_test(t => { + const controller = new TaskController(); + const signal = controller.signal; + const reason = new Error("Custom Abort Error"); + controller.abort(reason); + return promise_rejects_exactly(t, reason, scheduler.postTask(() => {}, {signal})); +}, 'Calling postTask with an aborted TaskSignal rejects the promise with the abort reason'); + +promise_test(t => { + const controller = new AbortController(); + const signal = controller.signal; + const reason = new Error("Custom Abort Error"); + controller.abort(reason); + return promise_rejects_exactly(t, reason, scheduler.postTask(() => {}, {signal})); +}, 'Calling postTask with an aborted AbortSignal rejects the promise with the abort reason'); + +promise_test(t => { + const controller = new TaskController(); + const signal = controller.signal; + const reason = new Error("Custom Abort Error"); + const result = scheduler.postTask(() => {}, {signal}); + controller.abort(reason); + return promise_rejects_exactly(t, reason, result); +}, 'Aborting a TaskSignal rejects the promise of a scheduled task with the abort reason'); + +promise_test(t => { + const reason = new Error("Custom Abort Error"); + const controller = new AbortController(); + const signal = controller.signal; + const result = scheduler.postTask(() => {}, {signal}); + controller.abort(reason); + return promise_rejects_exactly(t, reason, result); +}, 'Aborting an AbortSignal rejects the promise of a scheduled task with the abort reason');
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/crashtests/partially-overlapping-animations-one-not-current-001.html b/third_party/blink/web_tests/external/wpt/web-animations/crashtests/partially-overlapping-animations-one-not-current-001.html new file mode 100644 index 0000000..b943514f4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/web-animations/crashtests/partially-overlapping-animations-one-not-current-001.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html> +<title>CSS Test (Animations): Reparenting an element with a web animation on the compositor</title> +<link rel="author" title="L. David Baron" href="https://dbaron.org/"> +<link rel="author" title="Google" href="http://www.google.com/"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1319304"> +<meta name="assert" content="This should not crash."> + +<script> +window.onload = function(){ + let div = document.querySelector("div"); + let a1 = div.animate([{"transform": "translateX(10px)", "opacity": "0.4"}], { duration: 1000 }); + a1.reverse(); + let a2 = div.animate([{"transform": "translateY(10px)"}], { duration: 1000 }); +} +</script> +<div>X</div>
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index a7c77df..597cbdaa 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -10,6 +10,7 @@ method respondWith interface AbortSignal : EventTarget static method abort + static method timeout attribute @@toStringTag getter aborted getter onabort
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt index d4d323dd..c37bd86 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -11,6 +11,7 @@ [Worker] method constructor [Worker] interface AbortSignal : EventTarget [Worker] static method abort +[Worker] static method timeout [Worker] attribute @@toStringTag [Worker] getter aborted [Worker] getter onabort
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index 0fa413b8..1d2c6224 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -10,6 +10,7 @@ method constructor interface AbortSignal : EventTarget static method abort + static method timeout attribute @@toStringTag getter aborted getter onabort
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt index f99ce36c..46ac889 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -11,6 +11,7 @@ [Worker] method constructor [Worker] interface AbortSignal : EventTarget [Worker] static method abort +[Worker] static method timeout [Worker] attribute @@toStringTag [Worker] getter aborted [Worker] getter onabort
diff --git a/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt b/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt index 6906b179..d399e3ae 100644 --- a/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
@@ -107,6 +107,7 @@ property contains property contentEditable property dataset + property defaultOpen property dir property dispatchEvent property draggable @@ -139,7 +140,6 @@ property hidePopup property id property inert - property initiallyOpen property innerHTML property innerText property inputMode @@ -1342,6 +1342,7 @@ property computedStyleMap property contains property dataset + property defaultOpen property dispatchEvent property elementTiming property firstChild @@ -1368,7 +1369,6 @@ property hasPointerCapture property hidePopup property id - property initiallyOpen property innerHTML property insertAdjacentElement property insertAdjacentHTML
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 788ff8d..07a0d145 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -2241,10 +2241,10 @@ getter clientWidth getter computedName getter computedRole + getter defaultOpen getter elementTiming getter firstElementChild getter id - getter initiallyOpen getter innerHTML getter lastElementChild getter localName @@ -2378,9 +2378,9 @@ setter ariaVirtualContent setter classList setter className + setter defaultOpen setter elementTiming setter id - setter initiallyOpen setter innerHTML setter onbeforecopy setter onbeforecut
diff --git a/third_party/blink/web_tests/wpt_internal/payments/resources/payment-request-mock.js b/third_party/blink/web_tests/wpt_internal/payments/resources/payment-request-mock.js index 79bceb8c..1da6ce7 100644 --- a/third_party/blink/web_tests/wpt_internal/payments/resources/payment-request-mock.js +++ b/third_party/blink/web_tests/wpt_internal/payments/resources/payment-request-mock.js
@@ -22,7 +22,6 @@ } show() {} - showNew() {} updateWith(details) {} onPaymentDetailsNotUpdated() {} abort() {}
diff --git a/third_party/blink/web_tests/wpt_internal/task-tracking/callbacks-in-microtasks.html b/third_party/blink/web_tests/wpt_internal/task-tracking/callbacks-in-microtasks.html new file mode 100644 index 0000000..76c84c7 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/task-tracking/callbacks-in-microtasks.html
@@ -0,0 +1,40 @@ +<!DOCTYPE HTML> +<html> +<head> +<meta charset="utf-8"> +<title>Verify that tasks nested in microtasks can be properly tracked.</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> + +promise_test(t => { + const scriptId = scheduler.taskId; + + return scheduler.postTask(async _ => { + // We should be in a new task. + const postTaskId = scheduler.taskId; + assert_not_equals(scriptId, postTaskId); + + let eventFired = false; + // Set things up so the abort event listener is an ancestor of this task. + const controller = new AbortController(); + controller.signal.onabort = t.step_func(() => { + assert_not_equals(scheduler.taskId, postTaskId); + assert_equals(scheduler.isAncestor(postTaskId), "ancestor"); + eventFired = true; + }); + + await fetch("/resources/blank.html"); + // We're now in a new browser task that is running microtasks. + controller.abort(); + assert_true(eventFired); + // Make sure the previous ID was reset properly. + assert_equals(scheduler.taskId, postTaskId); + }); +}, "Task tracking should work when a new task scope starts during a microtask"); + +</script> +</body> +</html>
diff --git a/third_party/closure_compiler/externs/passwords_private.js b/third_party/closure_compiler/externs/passwords_private.js index dee54f5..aad8fb0 100644 --- a/third_party/closure_compiler/externs/passwords_private.js +++ b/third_party/closure_compiler/externs/passwords_private.js
@@ -348,6 +348,15 @@ chrome.passwordsPrivate.unmuteInsecureCredential = function(credential, callback) {}; /** + * Records that a change password flow was started for |credential|. + * @param {!chrome.passwordsPrivate.InsecureCredential} credential The + * credential for which the flow was triggered. + * @param {boolean} isManualFlow + */ +chrome.passwordsPrivate.recordChangePasswordFlowStarted = function( + credential, isManualFlow) {}; + +/** * Starts a check for insecure passwords. Invokes |callback| on completion. * @param {function(): void=} callback */
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium index 6a5838d..05f7223 100644 --- a/third_party/nearby/README.chromium +++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@ Name: Nearby Connections Library Short Name: Nearby URL: https://github.com/google/nearby-connections -Version: aeff3a96832b094b6ff7d2fe63116c95bb8c1f5c +Version: d09f53a40bb92e1037aed30b8407a090f08cdebe License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/tools/aggregation_service/aggregation_service_tool.cc b/tools/aggregation_service/aggregation_service_tool.cc index 1c6ae54..2d1cd9e8 100644 --- a/tools/aggregation_service/aggregation_service_tool.cc +++ b/tools/aggregation_service/aggregation_service_tool.cc
@@ -99,24 +99,11 @@ base::FilePath json_file(json_file_path); #endif - if (!base::PathExists(json_file)) { - LOG(ERROR) << "aggregation_service_tool failed to open file: " - << json_file.value() << "."; - return false; - } - - std::string json_string; - if (!base::ReadFileToString(json_file, &json_string)) { - LOG(ERROR) << "aggregation_service_tool failed to read file: " - << json_file.value() << "."; - return false; - } - bool succeeded = false; base::RunLoop run_loop; agg_service_->SetPublicKeys( - url, json_string, + url, json_file, base::BindOnce( [](base::OnceClosure quit, bool& succeeded_out, bool succeeded_in) { succeeded_out = succeeded_in;
diff --git a/tools/grit/grit/node/base.py b/tools/grit/grit/node/base.py index 159f763..f1ff1e40 100644 --- a/tools/grit/grit/node/base.py +++ b/tools/grit/grit/node/base.py
@@ -493,14 +493,6 @@ # Set values only for variables that are needed to eval the expression. variable_map = {} for name in variables_in_expr: - - # TODO(crbug.com/1230488): Remove the following check after a few days. - # This is needed to ensure that no occurrences of |chromeos| or |lacros| - # are missed (Grit does not normally catch undefined vars, see - # crbug.com/1316544) - if name == 'chromeos' or name == 'lacros': - assert False, 'chromeos/lacros variables found, use chromeos_ash/chromeos_lacros instead.' - if name == 'os': value = target_platform elif name == 'defs': @@ -538,8 +530,9 @@ elif name in extra_variables: value = extra_variables[name] else: - # Undefined variables default to False. - value = False + # Undefined variables are disallowed. All variables appearing in + # <if expr> conditions need to be defined. + assert False, 'undefined Grit variable found: ' + name variable_map[name] = value
diff --git a/tools/grit/grit/node/base_unittest.py b/tools/grit/grit/node/base_unittest.py index 5e9e0fc..915cceb 100755 --- a/tools/grit/grit/node/base_unittest.py +++ b/tools/grit/grit/node/base_unittest.py
@@ -218,7 +218,7 @@ # test the actual conditions for Chrome OS. AssertExpr(True, "is_linux", {'chromeos_ash': True}, 'linux', {}) AssertExpr(True, "is_linux", {'chromeos_lacros': True}, 'linux', {}) - AssertExpr(False, "is_chromeos", {}, 'linux', {}) + AssertExpr(False, "is_chromeos", {'is_chromeos': False}, 'linux', {}) AssertExpr(True, "is_linux", {'is_chromeos': True}, 'linux', {}) AssertExpr(False, "is_fuchsia", {}, 'linux', {}) AssertExpr(False, "is_linux", {}, 'win32', {}) @@ -248,13 +248,12 @@ AssertExpr(False, "pp_if('foo')", {'bar': True}, 'win32', {}) AssertExpr(True, "foo", {'foo': True}, 'win32', {}) AssertExpr(False, "foo", {'foo': False}, 'win32', {}) - AssertExpr(False, "foo", {'bar': True}, 'win32', {}) + AssertExpr(False, "foo", {'bar': True, 'foo': False}, 'win32', {}) AssertExpr(True, "foo == 'baz'", {'foo': 'baz'}, 'win32', {}) AssertExpr(False, "foo == 'baz'", {'foo': True}, 'win32', {}) - AssertExpr(False, "foo == 'baz'", {}, 'win32', {}) + AssertExpr(False, "foo == 'baz'", {'foo': True, 'baz': False}, 'win32', {}) AssertExpr(True, "lang == 'de'", {}, 'win32', {'lang': 'de'}) AssertExpr(False, "lang == 'de'", {}, 'win32', {'lang': 'fr'}) - AssertExpr(False, "lang == 'de'", {}, 'win32', {}) # Test a couple more complex expressions for good measure. AssertExpr(True, "is_ios and (lang in ['de', 'fr'] or foo)", @@ -264,14 +263,36 @@ 'lang': 'fr', 'context': 'today' }) - AssertExpr(False, "is_ios and (lang in ['de', 'fr'] or foo)", - {'baz': 'bar'}, 'ios', {'lang': 'he', 'context': 'today'}) - AssertExpr(True, "foo == 'bar' or not baz", - {'foo': 'bar', 'fun': True}, 'ios', {'lang': 'en'}) - AssertExpr(True, "foo == 'bar' or not baz", - {}, 'ios', {'lang': 'en', 'context': 'java'}) + AssertExpr(False, "is_ios and (lang in ['de', 'fr'] or foo)", { + 'baz': 'bar', + 'is_ios': True, + 'foo': False + }, 'ios', { + 'lang': 'he', + 'context': 'today' + }) + AssertExpr(True, "foo == 'bar' or not baz", { + 'foo': 'bar', + 'baz': True + }, 'ios', { + 'lang': 'en', + 'context': 'java' + }) AssertExpr(False, "foo == 'bar' or not baz", {'foo': 'ruz', 'baz': True}, 'ios', {'lang': 'en'}) + def testEvaluateExpressionWithUndefinedVariables(self): + def AssertThrows(expr, defs): + with self.assertRaises(AssertionError) as cm: + base.Node.EvaluateExpression(expr, defs, 'linux', {}) + self.assertTrue( + str(cm.exception).startswith('undefined Grit variable found:')) + + AssertThrows("is_chromeos", {}) + AssertThrows("foo == 'baz'", {}) + AssertThrows("is_chromeos", {'is_macosx': True}) + AssertThrows("foo == 'bar' or not baz", {'foo': 'bar', 'fun': True}) + + if __name__ == '__main__': unittest.main()
diff --git a/tools/grit/grit_defines.gni b/tools/grit/grit_defines.gni index b1503b64..f45f358e 100644 --- a/tools/grit/grit_defines.gni +++ b/tools/grit/grit_defines.gni
@@ -33,75 +33,53 @@ # Mac and iOS want Title Case strings. use_titlecase_in_grd_files = is_apple -if (use_titlecase_in_grd_files) { - grit_defines += [ - "-D", - "use_titlecase", - ] -} + +grit_defines += [ + "-D", + "use_titlecase=${use_titlecase_in_grd_files}", + "-D", + "_google_chrome=${is_chrome_branded}", +] if (is_chrome_branded) { grit_defines += [ - "-D", - "_google_chrome", "-E", "CHROMIUM_BUILD=google_chrome", ] } else { grit_defines += [ - "-D", - "_chromium", "-E", "CHROMIUM_BUILD=chromium", ] } -if (is_chromeos_ash) { - grit_defines += [ - "-D", - "chromeos_ash", - ] -} +grit_defines += [ + "-D", + "chromeos_ash=${is_chromeos_ash}", + "-D", + "chromeos_lacros=${is_chromeos_lacros}", -if (is_chromeos_lacros) { - grit_defines += [ - "-D", - "chromeos_lacros", - ] -} - -# This is related to Chrome OS. -if (is_reven) { - grit_defines += [ - "-D", - "reven", - ] -} + # This is related to Chrome OS. + "-D", + "reven=${is_reven}", +] # Prefer using this (and excluding specific platforms) when a resource applies # to (most) desktop platforms. assert(toolkit_views == (is_chromeos_ash || is_chromeos_lacros || is_fuchsia || is_linux || is_mac || is_win)) -if (toolkit_views) { - grit_defines += [ - "-D", - "toolkit_views", - ] -} +grit_defines += [ + "-D", + "toolkit_views=${toolkit_views}", + "-D", + "use_aura=${use_aura}", + "-D", + "use_ozone=${use_ozone}", -if (use_aura) { - grit_defines += [ - "-D", - "use_aura", - ] -} - -if (use_ozone) { - grit_defines += [ - "-D", - "use_ozone", - ] -} + # TODO(crbug.com/1317459): Remove after bug fixed. + "-D", + "desktop_linux=false", +] if (is_android) { grit_defines += [
diff --git a/tools/grit/preprocess_if_expr_test.py b/tools/grit/preprocess_if_expr_test.py index dbe866b..188b129 100644 --- a/tools/grit/preprocess_if_expr_test.py +++ b/tools/grit/preprocess_if_expr_test.py
@@ -43,31 +43,36 @@ self.assertMultiLineEqual(expected, actual) def testPreprocess(self): - self._run_test(['-D', 'foo', '-D', 'bar'], 'test_with_ifexpr.js', - 'test_with_ifexpr_expected.js') + self._run_test( + ['-D', 'foo', '-D', 'bar', '-D', 'apple=false', '-D', 'orange=false'], + 'test_with_ifexpr.js', 'test_with_ifexpr_expected.js') def testPreprocessWithComments(self): - self._run_test(['-D', 'foo', '-D', 'bar', '--enable_removal_comments'], - 'test_with_ifexpr.js', - 'test_with_ifexpr_expected_comments.js') + self._run_test([ + '-D', 'foo', '-D', 'bar', '-D', 'apple=false', '-D', 'orange=false', + '--enable_removal_comments' + ], 'test_with_ifexpr.js', 'test_with_ifexpr_expected_comments.js') def testPreprocessTypescriptWithComments(self): - self._run_test(['-D', 'foo', '-D', 'bar', '--enable_removal_comments'], - 'test_with_ifexpr.ts', 'test_with_ifexpr_expected.ts') + self._run_test([ + '-D', 'foo', '-D', 'bar', '-D', 'orange=false', + '--enable_removal_comments' + ], 'test_with_ifexpr.ts', 'test_with_ifexpr_expected.ts') def testPreprocessHtmlWithComments(self): - self._run_test(['-D', 'foo', '--enable_removal_comments'], - 'test_with_ifexpr.html', 'test_with_ifexpr_expected.html') + self._run_test( + ['-D', 'foo', '-D', 'orange=false', '--enable_removal_comments'], + 'test_with_ifexpr.html', 'test_with_ifexpr_expected.html') def testPreprocessJavaScriptHtmlTemplateWithComments(self): - self._run_test(['-D', 'foo', '--enable_removal_comments'], - 'test_with_ifexpr.html.js', - 'test_with_ifexpr_expected.html.js') + self._run_test( + ['-D', 'foo', '-D', 'bar=false', '--enable_removal_comments'], + 'test_with_ifexpr.html.js', 'test_with_ifexpr_expected.html.js') def testPreprocessTypeScriptHtmlTemplateWithComments(self): - self._run_test(['-D', 'foo', '--enable_removal_comments'], - 'test_with_ifexpr.html.ts', - 'test_with_ifexpr_expected.html.ts') + self._run_test( + ['-D', 'foo', '-D', 'bar=false', '--enable_removal_comments'], + 'test_with_ifexpr.html.ts', 'test_with_ifexpr_expected.html.ts') if __name__ == '__main__':
diff --git a/tools/mb/PRESUBMIT.py b/tools/mb/PRESUBMIT.py index 6d378b30..3d0ff94f 100644 --- a/tools/mb/PRESUBMIT.py +++ b/tools/mb/PRESUBMIT.py
@@ -70,10 +70,12 @@ output_api, '.', [r'^.+_unittest\.py$'], + run_on_python2=False, + run_on_python3=True, skip_shebang_check=True)) # Validate the format of the mb_config.pyl file. - cmd = [input_api.python_executable, 'mb.py', 'validate'] + cmd = [input_api.python3_executable, 'mb.py', 'validate'] kwargs = {'cwd': input_api.PresubmitLocalPath()} results.extend(input_api.RunTests([ input_api.Command(name='mb_validate',
diff --git a/tools/mb/lib/validation.py b/tools/mb/lib/validation.py index 5f73a9f..e0a5a7c 100644 --- a/tools/mb/lib/validation.py +++ b/tools/mb/lib/validation.py
@@ -5,6 +5,7 @@ import ast import collections +import difflib import json import os import re @@ -180,3 +181,35 @@ if builders_json != expectation: return False # Builders' expectation out of sync. return True + + +def CheckKeyOrdering(errs, groups, configs, mixins): + # Check ordering of groups within "builder_groups". + group_names = list(groups.keys()) + sorted_group_names = sorted(group_names) + if group_names != sorted_group_names: + errs.append('\nThe keys in "builder_groups" are not sorted:') + errs.extend(difflib.context_diff(group_names, sorted_group_names)) + + # Check ordering of builders within each group. + for group, builders in groups.items(): + builder_names = list(builders.keys()) + sorted_builder_names = sorted(builder_names) + if builder_names != sorted_builder_names: + errs.append('\nThe builders in group "%s" are not sorted:' % group) + errs.extend(difflib.context_diff(builder_names, sorted_builder_names)) + + # Check ordering of configs names, but don't bother checking the ordering + # of mixins within a config. + config_names = list(configs.keys()) + sorted_config_names = sorted(config_names) + if config_names != sorted_config_names: + errs.append('\nThe config names are not sorted:') + errs.extend(difflib.context_diff(config_names, sorted_config_names)) + + # Check ordering of mixin names. + mixin_names = list(mixins.keys()) + sorted_mixin_names = sorted(mixin_names) + if mixin_names != sorted_mixin_names: + errs.append('\nThe mixin names are not sorted:') + errs.extend(difflib.context_diff(mixin_names, sorted_mixin_names))
diff --git a/tools/mb/mb.py b/tools/mb/mb.py index 69c5c8d..23f7128 100755 --- a/tools/mb/mb.py +++ b/tools/mb/mb.py
@@ -881,6 +881,11 @@ if not validation.CheckExpectations(self, jsonish_blob, expectations_dir): raise MBErr("Expectations out of date. Please run 'mb.py train'.") + validation.CheckKeyOrdering(errs, self.builder_groups, self.configs, + self.mixins) + if errs: + raise MBErr('mb config file not sorted:\n' + '\n'.join(errs)) + if print_ok: self.Print('mb config file %s looks ok.' % self.args.config_file) return 0
diff --git a/tools/mb/mb_unittest.py b/tools/mb/mb_unittest.py index 3af390fb..fb88e01 100755 --- a/tools/mb/mb_unittest.py +++ b/tools/mb/mb_unittest.py
@@ -158,24 +158,27 @@ 'builder_groups': { 'chromium': {}, 'fake_builder_group': { + 'fake_args_bot': 'fake_args_bot', + 'fake_args_file': 'args_file_goma', 'fake_builder': 'rel_bot', 'fake_debug_builder': 'debug_goma', - 'fake_args_bot': 'fake_args_bot', - 'fake_multi_phase': { 'phase_1': 'phase_1', 'phase_2': 'phase_2'}, - 'fake_args_file': 'args_file_goma', 'fake_ios_error': 'ios_error', + 'fake_multi_phase': { 'phase_1': 'phase_1', 'phase_2': 'phase_2'}, }, }, 'configs': { 'args_file_goma': ['fake_args_bot', 'goma'], - 'fake_args_bot': ['fake_args_bot'], - 'rel_bot': ['rel', 'goma', 'fake_feature1'], 'debug_goma': ['debug', 'goma'], + 'fake_args_bot': ['fake_args_bot'], + 'ios_error': ['error'], 'phase_1': ['rel', 'phase_1'], 'phase_2': ['rel', 'phase_2'], - 'ios_error': ['error'], + 'rel_bot': ['rel', 'goma', 'fake_feature1'], }, 'mixins': { + 'debug': { + 'gn_args': 'is_debug=true', + }, 'error': { 'gn_args': 'error', }, @@ -197,9 +200,6 @@ 'rel': { 'gn_args': 'is_debug=false dcheck_always_on=false', }, - 'debug': { - 'gn_args': 'is_debug=true', - }, }, } """
diff --git a/tools/mb/mb_validation_unittest.py b/tools/mb/mb_validation_unittest.py index 21cc0891..4cc38d5 100755 --- a/tools/mb/mb_validation_unittest.py +++ b/tools/mb/mb_validation_unittest.py
@@ -92,6 +92,61 @@ } """ +TEST_CONFIG_UNSORTED_GROUPS = """\ +{ + 'builder_groups': { + 'groupB': {}, + 'groupA': {}, + 'groupC': {}, + }, + 'configs': { + }, + 'mixins': { + }, +} +""" + +TEST_CONFIG_UNSORTED_BUILDERNAMES = """\ +{ + 'builder_groups': { + 'group': { + 'builderB': '', + 'builderA': '' + }, + }, + 'configs': { + }, + 'mixins': { + }, +} +""" + +TEST_CONFIG_UNSORTED_CONFIGS = """\ +{ + 'builder_groups': { + }, + 'configs': { + 'configB': {}, + 'configA': {}, + }, + 'mixins': { + }, +} +""" + +TEST_CONFIG_UNSORTED_MIXINS = """\ +{ + 'builder_groups': { + }, + 'configs': { + }, + 'mixins': { + 'mixinB': {}, + 'mixinA': {}, + }, +} +""" + class UnitTest(unittest.TestCase): def test_GetAllConfigs(self): @@ -210,6 +265,38 @@ '\'some_other_config\'. Please consolidate these configs ' 'into only one unique name per configuration value.', errs) + def test_CheckKeyOrderingOK(self): + mb_config = ast.literal_eval(mb_unittest.TEST_CONFIG) + errs = [] + validation.CheckKeyOrdering(errs, mb_config['builder_groups'], + mb_config['configs'], mb_config['mixins']) + self.assertEqual(errs, []) + + def test_CheckKeyOrderingBad(self): + mb_config = ast.literal_eval(TEST_CONFIG_UNSORTED_GROUPS) + errs = [] + validation.CheckKeyOrdering(errs, mb_config['builder_groups'], + mb_config['configs'], mb_config['mixins']) + self.assertIn('\nThe keys in "builder_groups" are not sorted:', errs) + + mb_config = ast.literal_eval(TEST_CONFIG_UNSORTED_BUILDERNAMES) + errs = [] + validation.CheckKeyOrdering(errs, mb_config['builder_groups'], + mb_config['configs'], mb_config['mixins']) + self.assertIn('\nThe builders in group "group" are not sorted:', errs) + + mb_config = ast.literal_eval(TEST_CONFIG_UNSORTED_CONFIGS) + errs = [] + validation.CheckKeyOrdering(errs, mb_config['builder_groups'], + mb_config['configs'], mb_config['mixins']) + self.assertIn('\nThe config names are not sorted:', errs) + + mb_config = ast.literal_eval(TEST_CONFIG_UNSORTED_MIXINS) + errs = [] + validation.CheckKeyOrdering(errs, mb_config['builder_groups'], + mb_config['configs'], mb_config['mixins']) + self.assertIn('\nThe mixin names are not sorted:', errs) + if __name__ == '__main__': unittest.main()
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index d08a01c..4148925 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -25658,6 +25658,14 @@ <description>Please enter the description of this user action.</description> </action> +<action name="SegmentationPurgeTriggeredByHistoryDelete"> + <owner>ssid@chromium.org</owner> + <description> + Segmentation preferences were purged due to an user triggered history + deletion event. + </description> +</action> + <action name="SelectAll"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 5ed18354..4a27d5c 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -32532,6 +32532,7 @@ <int value="1647" label="OS_DIAGNOSTICS_RUNLANCONNECTIVITYROUTINE"/> <int value="1648" label="LOGIN_REQUESTEXTERNALLOGOUT"/> <int value="1649" label="LOGIN_NOTIFYEXTERNALLOGOUTDONE"/> + <int value="1650" label="PASSWORDSPRIVATE_RECORDCHANGEPASSWORDFLOWSTARTED"/> </enum> <enum name="ExtensionIconState"> @@ -38127,6 +38128,7 @@ <int value="4216" label="CookieHasNotBeenRefreshedIn201To300Days"/> <int value="4217" label="CookieHasNotBeenRefreshedIn301To350Days"/> <int value="4218" label="CookieHasNotBeenRefreshedIn351To400Days"/> + <int value="4219" label="ArrayBufferTooBigForWebAPI"/> </enum> <enum name="FeaturePolicyAllowlistType">
diff --git a/tools/metrics/histograms/metadata/local/histograms.xml b/tools/metrics/histograms/metadata/local/histograms.xml index 5ac7347..f7bd701 100644 --- a/tools/metrics/histograms/metadata/local/histograms.xml +++ b/tools/metrics/histograms/metadata/local/histograms.xml
@@ -282,7 +282,7 @@ </histogram> <histogram name="LocalStorage.RendererAreaCacheHit" - enum="LocalStorageRendererAreaCacheHitEnum" expires_after="2022-05-01"> + enum="LocalStorageRendererAreaCacheHitEnum" expires_after="2023-05-01"> <owner>mek@chromium.org</owner> <owner>chrome-owp-storage@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/storage/histograms.xml b/tools/metrics/histograms/metadata/storage/histograms.xml index d9de8de..b621c96 100644 --- a/tools/metrics/histograms/metadata/storage/histograms.xml +++ b/tools/metrics/histograms/metadata/storage/histograms.xml
@@ -456,17 +456,6 @@ </summary> </histogram> -<histogram name="Storage.Blob.TotalUnsharedSize" units="KB" expires_after="M95"> - <owner>mek@chromium.org</owner> - <owner>dmurph@chromium.org</owner> - <summary> - The total amount of unique memory used to create a blob. Recorded in - BlobStorageContext when the blob is finished being created. This does not - include memory that is shared with other blobs. If multiple of the same blob - item is present, then this number will reflect the size of the single item. - </summary> -</histogram> - <histogram name="Storage.BlobItemSize.File.Unknown" enum="BooleanUnknown" expires_after="M87"> <owner>mek@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/web_core/histograms.xml b/tools/metrics/histograms/metadata/web_core/histograms.xml index a2a288e6..9e9b1d9 100644 --- a/tools/metrics/histograms/metadata/web_core/histograms.xml +++ b/tools/metrics/histograms/metadata/web_core/histograms.xml
@@ -313,17 +313,6 @@ <summary>The reason that a forced-close of a backing store occurred.</summary> </histogram> -<histogram name="WebCore.IndexedDB.Database.OutstandingTransactionCount" - units="transactions" expires_after="2022-08-01"> - <owner>dmurph@chromium.org</owner> - <owner>pwnall@chromium.org</owner> - <owner>storage-dev@chromium.org</owner> - <summary> - Number of outstanding transactions (running, blocked) in database when a new - transaction is created. - </summary> -</histogram> - <histogram name="WebCore.IndexedDB.ErrorDuringForceCloseAborts" enum="LevelDBStatus" expires_after="2022-08-01"> <owner>dmurph@chromium.org</owner>
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index 36d48e5..67a3f85 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -1074,6 +1074,9 @@ 'resultdb': { 'has_native_resultdb_integration': True, }, + 'extra_args': [ + '--arch=amd64', + ], }, ], 'dimension': {
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index ea1f1ef2..34dcf7ab 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -13,8 +13,8 @@ "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "mac": { - "hash": "1e3500cd884a260deb812384198287518971fb0a", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/815e98cfc0a50e24365e4255d0250a995c8324f0/trace_processor_shell" + "hash": "a97d46d8d5793c8f09b20f8f5f663526dfec241e", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/b384c7aa6bb8ac202e0cf0d5da0ec7d602b44b8b/trace_processor_shell" }, "mac_arm64": { "hash": "e1ad4861384b06d911a65f035317914b8cc975c6", @@ -22,7 +22,7 @@ }, "linux": { "hash": "6b7c75037366bb10f21441af9748eabec2e1d608", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/b384c7aa6bb8ac202e0cf0d5da0ec7d602b44b8b/trace_processor_shell" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/02f7958f6551a697b124256d643cee71e4e350a9/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/typescript/definitions/passwords_private.d.ts b/tools/typescript/definitions/passwords_private.d.ts index 4ec5d70..ac94836 100644 --- a/tools/typescript/definitions/passwords_private.d.ts +++ b/tools/typescript/definitions/passwords_private.d.ts
@@ -149,6 +149,8 @@ credential: InsecureCredential, callback?: () => void): void; export function unmuteInsecureCredential( credential: InsecureCredential, callback?: () => void): void; + export function recordChangePasswordFlowStarted( + credential: InsecureCredential, isManualFlow: boolean): void; export function startPasswordCheck(callback?: () => void): void; export function stopPasswordCheck(callback?: () => void): void; export function getPasswordCheckStatus(
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc index dac4fae..0ae2cc5 100644 --- a/ui/aura/window_tree_host.cc +++ b/ui/aura/window_tree_host.cc
@@ -296,15 +296,23 @@ } void WindowTreeHost::ConvertDIPToPixels(gfx::Point* point) const { - auto point_3f = gfx::Point3F(gfx::PointF(*point)); - GetRootTransform().TransformPoint(&point_3f); - *point = gfx::ToFlooredPoint(point_3f.AsPointF()); + gfx::PointF point_f{*point}; + ConvertDIPToPixels(&point_f); + *point = gfx::ToFlooredPoint(point_f); +} + +void WindowTreeHost::ConvertDIPToPixels(gfx::PointF* point) const { + GetRootTransform().TransformPoint(point); } void WindowTreeHost::ConvertPixelsToDIP(gfx::Point* point) const { - auto point_3f = gfx::Point3F(gfx::PointF(*point)); - GetInverseRootTransform().TransformPoint(&point_3f); - *point = gfx::ToFlooredPoint(point_3f.AsPointF()); + gfx::PointF point_f{*point}; + ConvertPixelsToDIP(&point_f); + *point = gfx::ToFlooredPoint(point_f); +} + +void WindowTreeHost::ConvertPixelsToDIP(gfx::PointF* point) const { + GetInverseRootTransform().TransformPoint(point); } void WindowTreeHost::SetCursor(gfx::NativeCursor cursor) { @@ -589,7 +597,7 @@ // ~Window, but by that time any calls to virtual methods overriden here (such // as GetRootWindow()) result in Window's implementation. By destroying here // we ensure GetRootWindow() still returns this. - //window()->RemoveOrDestroyChildren(); + // window()->RemoveOrDestroyChildren(); } void WindowTreeHost::OnAcceleratedWidgetMadeVisible(bool value) {
diff --git a/ui/aura/window_tree_host.h b/ui/aura/window_tree_host.h index c230364..91d2236 100644 --- a/ui/aura/window_tree_host.h +++ b/ui/aura/window_tree_host.h
@@ -35,7 +35,7 @@ class Rect; class Size; class Transform; -} +} // namespace gfx namespace ui { class Compositor; @@ -44,7 +44,7 @@ class InputMethod; class ViewProp; struct PlatformWindowInitProperties; -} +} // namespace ui namespace viz { class FrameSinkId; @@ -151,11 +151,13 @@ // Converts |point| from the root window's coordinate system to the // host window's. - virtual void ConvertDIPToPixels(gfx::Point* point) const; + void ConvertDIPToPixels(gfx::Point* point) const; + virtual void ConvertDIPToPixels(gfx::PointF* point) const; // Converts |point| from the host window's coordinate system to the // root window's. - virtual void ConvertPixelsToDIP(gfx::Point* point) const; + void ConvertPixelsToDIP(gfx::Point* point) const; + virtual void ConvertPixelsToDIP(gfx::PointF* point) const; // Sets the currently-displayed cursor. If the cursor was previously hidden // via ShowCursor(false), it will remain hidden until ShowCursor(true) is
diff --git a/ui/aura/window_tree_host_unittest.cc b/ui/aura/window_tree_host_unittest.cc index b24385c8..2e714a8 100644 --- a/ui/aura/window_tree_host_unittest.cc +++ b/ui/aura/window_tree_host_unittest.cc
@@ -32,6 +32,38 @@ namespace aura { +namespace { + +// A convenient wrapper that makes it easy to invoke this method inside an +// EXPECT_EQ statement. +gfx::Point ConvertDIPToPixels(const WindowTreeHost* host, gfx::Point point) { + host->ConvertDIPToPixels(&point); + return point; +} + +// A convenient wrapper that makes it easy to invoke this method inside an +// EXPECT_EQ statement. +gfx::PointF ConvertDIPToPixels(const WindowTreeHost* host, gfx::PointF point) { + host->ConvertDIPToPixels(&point); + return point; +} + +// A convenient wrapper that makes it easy to invoke this method inside an +// EXPECT_EQ statement. +gfx::Point ConvertPixelsToDIP(const WindowTreeHost* host, gfx::Point point) { + host->ConvertPixelsToDIP(&point); + return point; +} + +// A convenient wrapper that makes it easy to invoke this method inside an +// EXPECT_EQ statement. +gfx::PointF ConvertPixelsToDIP(const WindowTreeHost* host, gfx::PointF point) { + host->ConvertPixelsToDIP(&point); + return point; +} + +} // namespace + using WindowTreeHostTest = test::AuraTestBase; TEST_F(WindowTreeHostTest, DPIWindowSize) { @@ -166,6 +198,103 @@ host()->RemoveEventRewriter(&event_rewriter); } +TEST_F(WindowTreeHostTest, ConvertDIPToPixelsShouldRespectScaleFactor) { + const int width_in_pixels = 400; + const int height_in_pixels = 300; + const int width_in_dip = 200; + const int height_in_dip = 150; + + host()->SetBoundsInPixels(gfx::Rect(0, 0, width_in_pixels, height_in_pixels)); + test_screen()->SetDisplayRotation(display::Display::ROTATE_0); + + test_screen()->SetDeviceScaleFactor(2.f); + + EXPECT_EQ(ConvertDIPToPixels(host(), gfx::Point(0, 0)), gfx::Point(0, 0)); + EXPECT_EQ(ConvertDIPToPixels(host(), gfx::Point(width_in_dip, 0)), + gfx::Point(width_in_pixels, 0)); + EXPECT_EQ(ConvertDIPToPixels(host(), gfx::Point(0, height_in_dip)), + gfx::Point(0, height_in_pixels)); +} + +TEST_F(WindowTreeHostTest, ConvertDIPToPixelsShouldRespectRotation) { + const int width_in_pixels = 400; + const int height_in_pixels = 300; + const int width_in_dip = 300; + const int height_in_dip = 400; + + host()->SetBoundsInPixels(gfx::Rect(0, 0, width_in_pixels, height_in_pixels)); + test_screen()->SetDeviceScaleFactor(1.f); + + test_screen()->SetDisplayRotation(display::Display::ROTATE_90); + + EXPECT_EQ(ConvertDIPToPixels(host(), gfx::Point(0, 0)), + gfx::Point(width_in_pixels, 0)); + EXPECT_EQ(ConvertDIPToPixels(host(), gfx::Point(width_in_dip, 0)), + gfx::Point(width_in_pixels, height_in_pixels)); + EXPECT_EQ(ConvertDIPToPixels(host(), gfx::Point(width_in_dip, height_in_dip)), + gfx::Point(0, height_in_pixels)); + EXPECT_EQ(ConvertDIPToPixels(host(), gfx::Point(0, height_in_dip)), + gfx::Point(0, 0)); +} + +TEST_F(WindowTreeHostTest, ConvertDIPToPixelsShouldWorkWithPointF) { + host()->SetBoundsInPixels(gfx::Rect(0, 0, 400, 400)); + test_screen()->SetDisplayRotation(display::Display::ROTATE_0); + test_screen()->SetDeviceScaleFactor(2.f); + + EXPECT_EQ(ConvertDIPToPixels(host(), gfx::PointF(5.3f, 0)), + gfx::PointF(10.6f, 0)); +} + +TEST_F(WindowTreeHostTest, ConvertPixelsToDIPShouldRespectScaleFactor) { + const int width_in_pixels = 400; + const int height_in_pixels = 300; + const int width_in_dip = 200; + const int height_in_dip = 150; + + host()->SetBoundsInPixels(gfx::Rect(0, 0, width_in_pixels, height_in_pixels)); + test_screen()->SetDisplayRotation(display::Display::ROTATE_0); + + test_screen()->SetDeviceScaleFactor(2.f); + + EXPECT_EQ(ConvertPixelsToDIP(host(), gfx::Point(0, 0)), gfx::Point(0, 0)); + EXPECT_EQ(ConvertPixelsToDIP(host(), gfx::Point(width_in_pixels, 0)), + gfx::Point(width_in_dip, 0)); + EXPECT_EQ(ConvertPixelsToDIP(host(), gfx::Point(0, height_in_pixels)), + gfx::Point(0, height_in_dip)); +} + +TEST_F(WindowTreeHostTest, ConvertPixelsToDIPShouldRespectRotation) { + const int width_in_pixels = 400; + const int height_in_pixels = 300; + const int width_in_dip = 300; + const int height_in_dip = 400; + + host()->SetBoundsInPixels(gfx::Rect(0, 0, width_in_pixels, height_in_pixels)); + test_screen()->SetDeviceScaleFactor(1.f); + + test_screen()->SetDisplayRotation(display::Display::ROTATE_90); + + EXPECT_EQ(ConvertPixelsToDIP(host(), gfx::Point(0, 0)), + gfx::Point(0, height_in_dip)); + EXPECT_EQ(ConvertPixelsToDIP(host(), gfx::Point(width_in_pixels, 0)), + gfx::Point(0, 0)); + EXPECT_EQ( + ConvertPixelsToDIP(host(), gfx::Point(width_in_pixels, height_in_pixels)), + gfx::Point(width_in_dip, 0)); + EXPECT_EQ(ConvertPixelsToDIP(host(), gfx::Point(0, height_in_pixels)), + gfx::Point(width_in_dip, height_in_dip)); +} + +TEST_F(WindowTreeHostTest, ConvertPixelsToDIPShouldWorkWithPointF) { + host()->SetBoundsInPixels(gfx::Rect(0, 0, 400, 400)); + test_screen()->SetDisplayRotation(display::Display::ROTATE_0); + test_screen()->SetDeviceScaleFactor(2.f); + + EXPECT_EQ(ConvertPixelsToDIP(host(), gfx::PointF(10.6f, 0)), + gfx::PointF(5.3f, 0)); +} + class TestWindow : public ui::StubWindow { public: explicit TestWindow(ui::PlatformWindowDelegate* delegate)
diff --git a/ui/base/interaction/interaction_sequence.cc b/ui/base/interaction/interaction_sequence.cc index 14b9c3a8..458fea4 100644 --- a/ui/base/interaction/interaction_sequence.cc +++ b/ui/base/interaction/interaction_sequence.cc
@@ -149,6 +149,11 @@ return *this; } +InteractionSequence::Builder& InteractionSequence::Builder::AddStep( + InteractionSequence::StepBuilder& step_builder) { + return AddStep(step_builder.Build()); +} + InteractionSequence::Builder& InteractionSequence::Builder::SetContext( ElementContext context) { configuration_->context = context;
diff --git a/ui/base/interaction/interaction_sequence.h b/ui/base/interaction/interaction_sequence.h index c701a70..bfc1fdf 100644 --- a/ui/base/interaction/interaction_sequence.h +++ b/ui/base/interaction/interaction_sequence.h
@@ -166,6 +166,9 @@ // one step. Builder& AddStep(std::unique_ptr<Step> step); + // Convenience methods to add a step when using a StepBuilder. + Builder& AddStep(StepBuilder& step_builder); + // Sets the context for this sequence. Must be called if no step is added // by element or has had SetContext() called. Typically the initial step of // a sequence will use WithInitialElement() so it won't be necessary to call
diff --git a/ui/base/interaction/interaction_sequence_unittest.cc b/ui/base/interaction/interaction_sequence_unittest.cc index 4f328baf..ab89e7f3 100644 --- a/ui/base/interaction/interaction_sequence_unittest.cc +++ b/ui/base/interaction/interaction_sequence_unittest.cc
@@ -3380,4 +3380,15 @@ EXPECT_CALL_IN_SCOPE(completed, Run, sequence->RunSynchronouslyForTesting()); } +TEST(InteractionSequenceTest, AddStepWithUnBuildStepBuilder) { + auto sequence = + InteractionSequence::Builder() + .SetContext(kTestContext1) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(kTestIdentifier1) + .SetType(InteractionSequence::StepType::kActivated)) + .Build(); + sequence.reset(); +} + } // namespace ui
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success.svg b/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success.svg index 6165884..076f2b6 100644 --- a/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success.svg +++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success.svg
@@ -1 +1 @@ -<svg width="201" height="200" viewBox="0 0 201 200" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M100.366 109.293c-23.295 0-42.18 18.794-42.18 41.977 0 23.183 18.885 41.976 42.18 41.976 23.295 0 42.179-18.793 42.179-41.976s-18.884-41.977-42.179-41.977zm0 1.908c22.236 0 40.262 17.939 40.262 40.069 0 22.129-18.026 40.068-40.262 40.068s-40.262-17.939-40.262-40.068c0-22.13 18.026-40.069 40.262-40.069z" fill="#D2E3FC"/><path fill-rule="evenodd" clip-rule="evenodd" d="M72.382 80.903c0 15.456 12.528 27.985 27.984 27.985 15.455 0 27.984-12.53 27.984-27.985" fill="#D2E3FC"/><path d="M100.366 124.705c-14.784 0-26.768 11.984-26.768 26.768 0 14.783 11.984 26.767 26.768 26.767 14.783 0 26.767-11.984 26.767-26.767 0-14.784-11.984-26.768-26.767-26.768zm0 2.549c13.375 0 24.218 10.843 24.218 24.219 0 13.375-10.843 24.218-24.218 24.218-13.376 0-24.219-10.843-24.219-24.218 0-13.376 10.843-24.219 24.219-24.219z" fill="#4285F4"/><path d="M106.609 138.351h4.995v22.475h-4.995v-22.475zm-17.48 12.486h4.994v9.989h-4.995v-9.989zm8.74-6.243h4.994v16.232h-4.994v-16.232z" fill="#4285F4"/><path fill-rule="evenodd" clip-rule="evenodd" d="M114.565 49.036l1.13 2.792a2.636 2.636 0 0 1-1.455 3.433l-.003.001-27.656 11.155a2.636 2.636 0 0 1-3.43-1.456l-1.13-2.792a2.636 2.636 0 0 1 1.455-3.433h.003l27.656-11.156a2.637 2.637 0 0 1 3.43 1.456z" fill="#4285F4"/><path d="M100.366 50.643c8.96 0 16.223-7.264 16.223-16.223 0-8.96-7.263-16.223-16.223-16.223-8.96 0-16.223 7.263-16.223 16.223 0 8.96 7.263 16.223 16.223 16.223z" fill="#34A853"/><path fill-rule="evenodd" clip-rule="evenodd" d="M101.896 61.021l8.657 8.643c.476.475.477 1.245.002 1.72l-.002.002-8.657 8.643a1.216 1.216 0 0 1-1.719 0l-8.658-8.643a1.217 1.217 0 0 1-.002-1.72l.002-.002 8.658-8.643a1.217 1.217 0 0 1 1.719 0z" fill="#FBBC04"/><path fill-rule="evenodd" clip-rule="evenodd" d="M94.252 8.37c-.49-.86.123-1.934 1.104-1.934h10.02c.981 0 1.594 1.075 1.103 1.934l-5.01 8.778a1.267 1.267 0 0 1-2.207 0l-5.01-8.778z" fill="#2FE2EA"/><path fill-rule="evenodd" clip-rule="evenodd" d="M111.439 25.828c.66.5.791 1.44.291 2.1l-11.965 15.82a1.5 1.5 0 0 1-2.15.253l-7.03-5.79a1.5 1.5 0 1 1 1.907-2.316l5.824 4.796 11.022-14.57a1.5 1.5 0 0 1 2.101-.292z" fill="#fff"/></svg> \ No newline at end of file +<svg width="201" height="200" viewBox="0 0 201 200" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M100.366 109.293c-23.295 0-42.18 18.794-42.18 41.977 0 23.183 18.885 41.976 42.18 41.976 23.295 0 42.179-18.793 42.179-41.976s-18.884-41.977-42.179-41.977zm0 1.908c22.236 0 40.262 17.939 40.262 40.069 0 22.129-18.026 40.068-40.262 40.068s-40.262-17.939-40.262-40.068c0-22.13 18.026-40.069 40.262-40.069z" fill="#D2E3FC"/><path fill-rule="evenodd" clip-rule="evenodd" d="M72.382 80.903c0 15.456 12.528 27.985 27.984 27.985 15.455 0 27.984-12.53 27.984-27.985" fill="#D2E3FC"/><path d="M100.366 124.705c-14.784 0-26.768 11.984-26.768 26.768 0 14.783 11.984 26.767 26.768 26.767 14.783 0 26.767-11.984 26.767-26.767 0-14.784-11.984-26.768-26.767-26.768zm0 2.549c13.375 0 24.218 10.843 24.218 24.219 0 13.375-10.843 24.218-24.218 24.218-13.376 0-24.219-10.843-24.219-24.218 0-13.376 10.843-24.219 24.219-24.219z" fill="#4285F4"/><path d="M106.609 138.351h4.995v22.475h-4.995v-22.475zm-17.48 12.486h4.994v9.989h-4.995v-9.989zm8.74-6.243h4.994v16.232h-4.994v-16.232z" fill="#4285F4"/><path fill-rule="evenodd" clip-rule="evenodd" d="M114.565 49.036l1.13 2.792a2.636 2.636 0 0 1-1.455 3.433l-.003.001-27.656 11.155a2.636 2.636 0 0 1-3.43-1.456l-1.13-2.792a2.636 2.636 0 0 1 1.455-3.433h.003l27.656-11.156a2.637 2.637 0 0 1 3.43 1.456z" fill="#4285F4"/><path d="M100.366 50.643c8.96 0 16.223-7.264 16.223-16.223 0-8.96-7.263-16.223-16.223-16.223-8.96 0-16.223 7.263-16.223 16.223 0 8.96 7.263 16.223 16.223 16.223z" fill="#34A853"/><path fill-rule="evenodd" clip-rule="evenodd" d="M101.896 61.021l8.657 8.643c.476.475.477 1.245.002 1.72l-.002.002-8.657 8.643a1.216 1.216 0 0 1-1.719 0l-8.658-8.643a1.217 1.217 0 0 1-.002-1.72l.002-.002 8.658-8.643a1.217 1.217 0 0 1 1.719 0z" fill="#FBBC04"/><path fill-rule="evenodd" clip-rule="evenodd" d="M94.252 8.37c-.49-.86.123-1.934 1.104-1.934h10.02c.981 0 1.594 1.075 1.103 1.934l-5.01 8.778c-.49.859-1.716.859-2.207 0l-5.01-8.778z" fill="#2FE2EA"/><path fill-rule="evenodd" clip-rule="evenodd" d="M111.439 25.828c.66.5.791 1.44.291 2.1L99.765 43.748a1.5 1.5 0 0 1-2.15.253l-7.03-5.79a1.5 1.5 0 1 1 1.907-2.316l5.824 4.796 11.022-14.57a1.5 1.5 0 0 1 2.101-.292z" fill="#fff"/></svg>
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success_dark.svg b/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success_dark.svg index d65fee72..d923316 100644 --- a/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success_dark.svg +++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page_success_dark.svg
@@ -1 +1 @@ -<svg width="201" height="200" viewBox="0 0 201 200" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M100.366 109.293c-23.295 0-42.18 18.794-42.18 41.977 0 23.183 18.885 41.976 42.18 41.976 23.295 0 42.179-18.793 42.179-41.976s-18.884-41.977-42.179-41.977zm0 1.908c22.236 0 40.262 17.939 40.262 40.069 0 22.129-18.026 40.068-40.262 40.068s-40.262-17.939-40.262-40.068c0-22.13 18.026-40.069 40.262-40.069z" fill="#8AB4F8" fill-opacity=".4"/><path fill-rule="evenodd" clip-rule="evenodd" d="M72.382 80.903c0 15.456 12.528 27.985 27.984 27.985 15.455 0 27.984-12.53 27.984-27.985" fill="#8AB4F8" fill-opacity=".4"/><path d="M100.366 124.705c-14.784 0-26.768 11.984-26.768 26.768 0 14.783 11.984 26.767 26.768 26.767 14.783 0 26.767-11.984 26.767-26.767 0-14.784-11.984-26.768-26.767-26.768zm0 2.549c13.375 0 24.218 10.843 24.218 24.219 0 13.375-10.843 24.218-24.218 24.218-13.376 0-24.219-10.843-24.219-24.218 0-13.376 10.843-24.219 24.219-24.219z" fill="#669DF6"/><path d="M106.609 138.351h4.995v22.475h-4.995v-22.475zm-17.48 12.486h4.994v9.989h-4.995v-9.989zm8.74-6.243h4.994v16.232h-4.994v-16.232z" fill="#669DF6"/><path fill-rule="evenodd" clip-rule="evenodd" d="M114.565 49.036l1.13 2.792a2.636 2.636 0 0 1-1.455 3.433l-.003.001-27.656 11.155a2.636 2.636 0 0 1-3.43-1.456l-1.13-2.792a2.636 2.636 0 0 1 1.455-3.433h.003l27.656-11.156a2.637 2.637 0 0 1 3.43 1.456z" fill="#669DF6"/><path d="M100.366 50.643c8.96 0 16.223-7.264 16.223-16.223 0-8.96-7.263-16.223-16.223-16.223-8.96 0-16.223 7.263-16.223 16.223 0 8.96 7.263 16.223 16.223 16.223z" fill="#5BB974"/><path fill-rule="evenodd" clip-rule="evenodd" d="M101.896 61.021l8.657 8.643c.476.475.477 1.245.002 1.72l-.002.002-8.657 8.643a1.216 1.216 0 0 1-1.719 0l-8.658-8.643a1.217 1.217 0 0 1-.002-1.72l.002-.002 8.658-8.643a1.217 1.217 0 0 1 1.719 0z" fill="#FCC934"/><path fill-rule="evenodd" clip-rule="evenodd" d="M94.252 8.37c-.49-.86.123-1.934 1.104-1.934h10.02c.981 0 1.594 1.075 1.103 1.934l-5.01 8.778a1.267 1.267 0 0 1-2.207 0l-5.01-8.778z" fill="#5DF1F2"/><path fill-rule="evenodd" clip-rule="evenodd" d="M111.439 25.828c.66.5.791 1.44.291 2.1l-11.965 15.82a1.5 1.5 0 0 1-2.15.253l-7.03-5.79a1.5 1.5 0 1 1 1.907-2.316l5.824 4.796 11.022-14.57a1.5 1.5 0 0 1 2.101-.292z" fill="#323336"/></svg> \ No newline at end of file +<svg width="201" height="200" viewBox="0 0 201 200" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M100.366 109.293c-23.295 0-42.18 18.794-42.18 41.977 0 23.183 18.885 41.976 42.18 41.976 23.295 0 42.179-18.793 42.179-41.976s-18.884-41.977-42.179-41.977zm0 1.908c22.236 0 40.262 17.939 40.262 40.069 0 22.129-18.026 40.068-40.262 40.068s-40.262-17.939-40.262-40.068c0-22.13 18.026-40.069 40.262-40.069z" fill="#8AB4F8" fill-opacity=".4"/><path fill-rule="evenodd" clip-rule="evenodd" d="M72.382 80.903c0 15.456 12.528 27.985 27.984 27.985 15.455 0 27.984-12.53 27.984-27.985" fill="#8AB4F8" fill-opacity=".4"/><path d="M100.366 124.705c-14.784 0-26.768 11.984-26.768 26.768 0 14.783 11.984 26.767 26.768 26.767 14.783 0 26.767-11.984 26.767-26.767 0-14.784-11.984-26.768-26.767-26.768zm0 2.549c13.375 0 24.218 10.843 24.218 24.219 0 13.375-10.843 24.218-24.218 24.218-13.376 0-24.219-10.843-24.219-24.218 0-13.376 10.843-24.219 24.219-24.219z" fill="#669DF6"/><path d="M106.609 138.351h4.995v22.475h-4.995v-22.475zm-17.48 12.486h4.994v9.989h-4.995v-9.989zm8.74-6.243h4.994v16.232h-4.994v-16.232z" fill="#669DF6"/><path fill-rule="evenodd" clip-rule="evenodd" d="M114.565 49.036l1.13 2.792a2.636 2.636 0 0 1-1.455 3.433l-.003.001-27.656 11.155a2.636 2.636 0 0 1-3.43-1.456l-1.13-2.792a2.636 2.636 0 0 1 1.455-3.433h.003l27.656-11.156a2.637 2.637 0 0 1 3.43 1.456z" fill="#669DF6"/><path d="M100.366 50.643c8.96 0 16.223-7.264 16.223-16.223 0-8.96-7.263-16.223-16.223-16.223-8.96 0-16.223 7.263-16.223 16.223 0 8.96 7.263 16.223 16.223 16.223z" fill="#5BB974"/><path fill-rule="evenodd" clip-rule="evenodd" d="M101.896 61.021l8.657 8.643c.476.475.477 1.245.002 1.72l-.002.002-8.657 8.643a1.216 1.216 0 0 1-1.719 0l-8.658-8.643a1.217 1.217 0 0 1-.002-1.72l.002-.002 8.658-8.643a1.217 1.217 0 0 1 1.719 0z" fill="#FCC934"/><path fill-rule="evenodd" clip-rule="evenodd" d="M94.252 8.37c-.49-.86.123-1.934 1.104-1.934h10.02c.981 0 1.594 1.075 1.103 1.934l-5.01 8.778c-.49.859-1.716.859-2.207 0l-5.01-8.778z" fill="#5DF1F2"/><path fill-rule="evenodd" clip-rule="evenodd" d="M111.439 25.828c.66.5.791 1.44.291 2.1L99.765 43.748a1.5 1.5 0 0 1-2.15.253l-7.03-5.79a1.5 1.5 0 1 1 1.907-2.316l5.824 4.796 11.022-14.57a1.5 1.5 0 0 1 2.101-.292z" fill="#323336"/></svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/cellular_0.svg b/ui/webui/resources/cr_components/chromeos/network/cellular_0.svg index 3469d65..a921d4b 100644 --- a/ui/webui/resources/cr_components/chromeos/network/cellular_0.svg +++ b/ui/webui/resources/cr_components/chromeos/network/cellular_0.svg
@@ -1 +1,3 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M15.002 15.002V7.416l-7.586 7.586h7.586zm1 2a1 1 0 0 0 1-1v-11c0-.89-1.077-1.337-1.707-.707l-11 11c-.63.63-.184 1.707.707 1.707h11z"/></svg> \ No newline at end of file +<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M15.002 15.002V7.41622L7.41622 15.002H15.002ZM16.002 17.002C16.5543 17.002 17.002 16.5543 17.002 16.002V5.002C17.002 4.1111 15.9249 3.66493 15.2949 4.2949L4.2949 15.2949C3.66493 15.9249 4.1111 17.002 5.002 17.002H16.002Z" /> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/cellular_0_with_x.svg b/ui/webui/resources/cr_components/chromeos/network/cellular_0_with_x.svg index b1c84acc..39e42cf 100644 --- a/ui/webui/resources/cr_components/chromeos/network/cellular_0_with_x.svg +++ b/ui/webui/resources/cr_components/chromeos/network/cellular_0_with_x.svg
@@ -1 +1,4 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M15.002 15.002V7.416l-7.586 7.586h7.586zm1 2a1 1 0 0 0 1-1v-11c0-.89-1.077-1.337-1.707-.707l-11 11c-.63.63-.184 1.707.707 1.707h11zM6.667 6L8 4.667 7.333 4 6 5.333 4.667 4 4 4.667 5.333 6 4 7.333 4.667 8 6 6.667 7.333 8 8 7.333 6.667 6z"/></svg> \ No newline at end of file +<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M15.002 15.002V7.41622L7.41622 15.002H15.002ZM16.002 17.002C16.5543 17.002 17.002 16.5543 17.002 16.002V5.002C17.002 4.1111 15.9249 3.66493 15.2949 4.2949L4.2949 15.2949C3.66493 15.9249 4.1111 17.002 5.002 17.002H16.002Z" /> +<path fill-rule="evenodd" clip-rule="evenodd" d="M6.66667 6L8 4.66667L7.33333 4L6 5.33333L4.66667 4L4 4.66667L5.33333 6L4 7.33333L4.66667 8L6 6.66667L7.33333 8L8 7.33333L6.66667 6Z"/> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/cellular_1.svg b/ui/webui/resources/cr_components/chromeos/network/cellular_1.svg index cba8cae..66d98d2 100644 --- a/ui/webui/resources/cr_components/chromeos/network/cellular_1.svg +++ b/ui/webui/resources/cr_components/chromeos/network/cellular_1.svg
@@ -1 +1,4 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M15.002 15.002V7.416l-7.586 7.586h7.586zm1 2a1 1 0 0 0 1-1v-11c0-.89-1.077-1.337-1.707-.707l-11 11c-.63.63-.184 1.707.707 1.707h11z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M9.002 16.002a1 1 0 0 1-1 1h-3c-.89 0-1.337-1.077-.707-1.707l3-3c.63-.63 1.707-.184 1.707.707v3z"/></svg> \ No newline at end of file +<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M15.002 15.002V7.41622L7.41622 15.002H15.002ZM16.002 17.002C16.5543 17.002 17.002 16.5543 17.002 16.002V5.002C17.002 4.1111 15.9249 3.66493 15.2949 4.2949L4.2949 15.2949C3.66493 15.9249 4.1111 17.002 5.002 17.002H16.002Z" /> +<path fill-rule="evenodd" clip-rule="evenodd" d="M9.002 16.002C9.002 16.5543 8.55429 17.002 8.002 17.002H5.002C4.1111 17.002 3.66493 15.9249 4.2949 15.2949L7.2949 12.2949C7.92486 11.6649 9.002 12.1111 9.002 13.002V16.002Z" /> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/cellular_2.svg b/ui/webui/resources/cr_components/chromeos/network/cellular_2.svg index 297a6a3..9066c21 100644 --- a/ui/webui/resources/cr_components/chromeos/network/cellular_2.svg +++ b/ui/webui/resources/cr_components/chromeos/network/cellular_2.svg
@@ -1 +1,4 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M15.002 15.002V7.416l-7.586 7.586h7.586zm1 2a1 1 0 0 0 1-1v-11c0-.89-1.077-1.337-1.707-.707l-11 11c-.63.63-.184 1.707.707 1.707h11z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M12.002 16.002a1 1 0 0 1-1 1h-6c-.89 0-1.337-1.077-.707-1.707l6-6c.63-.63 1.707-.184 1.707.707v6z"/></svg> \ No newline at end of file +<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M15.002 15.002V7.41622L7.41622 15.002H15.002ZM16.002 17.002C16.5543 17.002 17.002 16.5543 17.002 16.002V5.002C17.002 4.1111 15.9249 3.66493 15.2949 4.2949L4.2949 15.2949C3.66493 15.9249 4.1111 17.002 5.002 17.002H16.002Z" /> +<path fill-rule="evenodd" clip-rule="evenodd" d="M12.002 16.002C12.002 16.5543 11.5543 17.002 11.002 17.002H5.002C4.1111 17.002 3.66493 15.9249 4.2949 15.2949L10.2949 9.2949C10.9249 8.66493 12.002 9.1111 12.002 10.002V16.002Z" /> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/cellular_3.svg b/ui/webui/resources/cr_components/chromeos/network/cellular_3.svg index c47e217..a3cd603 100644 --- a/ui/webui/resources/cr_components/chromeos/network/cellular_3.svg +++ b/ui/webui/resources/cr_components/chromeos/network/cellular_3.svg
@@ -1 +1,4 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M15.002 15.002V7.416l-7.586 7.586h7.586zm1 2a1 1 0 0 0 1-1v-11c0-.89-1.077-1.337-1.707-.707l-11 11c-.63.63-.184 1.707.707 1.707h11z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M13.5 16.002a1 1 0 0 1-1 1H5.002c-.89 0-1.337-1.077-.707-1.707l7.498-7.502c.63-.63 1.707-.184 1.707.707v7.502z"/></svg> \ No newline at end of file +<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M15.002 15.002V7.41622L7.41622 15.002H15.002ZM16.002 17.002C16.5543 17.002 17.002 16.5543 17.002 16.002V5.002C17.002 4.1111 15.9249 3.66493 15.2949 4.2949L4.2949 15.2949C3.66493 15.9249 4.1111 17.002 5.002 17.002H16.002Z" /> +<path fill-rule="evenodd" clip-rule="evenodd" d="M13.5 16.002C13.5 16.5543 13.0523 17.002 12.5 17.002H5.002C4.1111 17.002 3.66493 15.9249 4.2949 15.2949L11.7929 7.79289C12.4229 7.16293 13.5 7.6091 13.5 8.5V16.002Z" /> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/cellular_4.svg b/ui/webui/resources/cr_components/chromeos/network/cellular_4.svg index a0b353bd..2be87e0 100644 --- a/ui/webui/resources/cr_components/chromeos/network/cellular_4.svg +++ b/ui/webui/resources/cr_components/chromeos/network/cellular_4.svg
@@ -1 +1,3 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M17.002 16.002a1 1 0 0 1-1 1h-11c-.89 0-1.337-1.077-.707-1.707l11-11c.63-.63 1.707-.184 1.707.707v11z"/></svg> \ No newline at end of file +<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M17.002 16.002C17.002 16.5543 16.5543 17.002 16.002 17.002H5.002C4.1111 17.002 3.66493 15.9249 4.2949 15.2949L15.2949 4.2949C15.9249 3.66493 17.002 4.1111 17.002 5.002V16.002Z" /> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/cellular_locked.svg b/ui/webui/resources/cr_components/chromeos/network/cellular_locked.svg index 7912a799..9ed8100 100644 --- a/ui/webui/resources/cr_components/chromeos/network/cellular_locked.svg +++ b/ui/webui/resources/cr_components/chromeos/network/cellular_locked.svg
@@ -1 +1,3 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M14.188 9.59c.276 0 .548.023.812.067V3.825c0-.734-.875-1.1-1.387-.582L2.24 15.594c-.512.519-.15 1.406.574 1.406h7.151a4.97 4.97 0 0 1-.652-2.47c0-2.729 2.182-4.94 4.875-4.94zM16 16v-2h-3v2h3zm-3-3a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1v-.5a1.5 1.5 0 0 0-3 0v.5zm1 0h1v-.5a.5.5 0 0 0-1 0v.5z"/></svg> \ No newline at end of file +<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M14.1876 9.58912C14.4644 9.58912 14.7358 9.6125 15 9.65744V3.82508C15 3.09148 14.1249 2.7241 13.6131 3.24283L2.23957 15.5943C1.72779 16.113 2.09026 17 2.81403 17H9.96527C9.55054 16.2733 9.31317 15.4296 9.31317 14.5297C9.31317 11.8011 11.4955 9.58912 14.1876 9.58912ZM16 16V14H13V16H16ZM13 13C12.4477 13 12 13.4477 12 14V16C12 16.5523 12.4477 17 13 17H16C16.5523 17 17 16.5523 17 16V14C17 13.4477 16.5523 13 16 13V12.5C16 11.6716 15.3284 11 14.5 11C13.6716 11 13 11.6716 13 12.5V13ZM14 13H15V12.5C15 12.2239 14.7761 12 14.5 12C14.2239 12 14 12.2239 14 12.5V13Z"/> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/cellular_off.svg b/ui/webui/resources/cr_components/chromeos/network/cellular_off.svg index 70236ef..4d72a7c 100644 --- a/ui/webui/resources/cr_components/chromeos/network/cellular_off.svg +++ b/ui/webui/resources/cr_components/chromeos/network/cellular_off.svg
@@ -1 +1,3 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M17 16a1 1 0 0 1-1 1H5c-.89 0-1.337-1.077-.707-1.707l11-11C15.923 3.663 17 4.109 17 5v11zm-2-1V7.414L7.414 15H15z"/></svg> \ No newline at end of file +<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M17 16C17 16.5523 16.5523 17 16 17H4.99999C4.10909 17 3.66292 15.9228 4.29288 15.2929L15.2929 4.29288C15.9228 3.66292 17 4.10909 17 4.99999V16ZM15 15V7.41418L7.41418 15H15Z"/> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/ethernet.svg b/ui/webui/resources/cr_components/chromeos/network/ethernet.svg index f5df8eb1..6c0c5f9 100644 --- a/ui/webui/resources/cr_components/chromeos/network/ethernet.svg +++ b/ui/webui/resources/cr_components/chromeos/network/ethernet.svg
@@ -1 +1,5 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M14.09 5l-1.153 1.175L16.685 10l-3.748 3.825L14.091 15 19 10l-4.91-5zM7.064 6.175L5.909 5 1 10l4.91 5 1.153-1.175L3.315 10l3.748-3.825zM7.055 11a.991.991 0 0 0 .981-1c0-.552-.44-1-.981-1a.991.991 0 0 0-.982 1c0 .552.44 1 .982 1zM10 11a.991.991 0 0 0 .982-1c0-.552-.44-1-.982-1a.991.991 0 0 0-.982 1c0 .552.44 1 .982 1zm2.945 0a.991.991 0 0 0 .982-1c0-.552-.44-1-.982-1a.991.991 0 0 0-.981 1c0 .552.44 1 .981 1z"/></svg> \ No newline at end of file +<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> +<g id="ethernet"> +<path id="Shape 1" fill-rule="evenodd" clip-rule="evenodd" d="M14.0909 5L12.9373 6.175L16.6845 10L12.9373 13.825L14.0909 15L19 10L14.0909 5ZM7.06273 6.175L5.90909 5L1 10L5.90909 15L7.06273 13.825L3.31545 10L7.06273 6.175ZM7.05457 11C7.59682 11 8.03639 10.5523 8.03639 10C8.03639 9.44772 7.59682 9 7.05457 9C6.51233 9 6.07275 9.44772 6.07275 10C6.07275 10.5523 6.51233 11 7.05457 11ZM10 11C10.5422 11 10.9818 10.5523 10.9818 10C10.9818 9.44772 10.5422 9 10 9C9.45776 9 9.01819 9.44772 9.01819 10C9.01819 10.5523 9.45776 11 10 11ZM12.9454 11C13.4877 11 13.9273 10.5523 13.9273 10C13.9273 9.44772 13.4877 9 12.9454 9C12.4032 9 11.9636 9.44772 11.9636 10C11.9636 10.5523 12.4032 11 12.9454 11Z" /> +</g> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/roaming_badge.svg b/ui/webui/resources/cr_components/chromeos/network/roaming_badge.svg index f32d940..d4cf40d 100644 --- a/ui/webui/resources/cr_components/chromeos/network/roaming_badge.svg +++ b/ui/webui/resources/cr_components/chromeos/network/roaming_badge.svg
@@ -1 +1,3 @@ -<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1.95 7v.05h1.231V4.796h.444l1.543 2.232.015.022h1.375v-.133l-.009-.013-1.596-2.276c.365-.138.668-.35.907-.638.253-.311.38-.677.38-1.096a1.93 1.93 0 0 0-.258-.997 1.802 1.802 0 0 0-.724-.698C4.954 1.032 4.596.95 4.188.95H1.95V7zm2.844-4.66A.797.797 0 0 1 5 2.877a.742.742 0 0 1-.227.56.817.817 0 0 1-.594.22H3.18v-1.56h1.015c.268 0 .465.083.598.242z" fill="#202124"/></svg> \ No newline at end of file +<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M1.95 7V7.05H2H3.13128H3.18128V7V4.79581H3.62462L5.16837 7.02844L5.18328 7.05H5.2095H6.50838H6.55838V7V6.93296V6.91717L6.54931 6.90425L4.95274 4.6281C5.31836 4.49012 5.62108 4.27747 5.8597 3.99004L5.85999 3.98968C6.11344 3.67864 6.23994 3.31259 6.23994 2.89385C6.23994 2.52279 6.15423 2.18991 5.98174 1.89661C5.80943 1.59801 5.568 1.36533 5.25845 1.19905C4.95376 1.03238 4.59609 0.95 4.18715 0.95H2H1.95V1V7ZM4.79409 2.33939L4.79409 2.3394L4.79462 2.34001C4.93237 2.49896 5.00028 2.67741 5.00028 2.87709C5.00028 3.10476 4.92408 3.28977 4.77253 3.4361C4.62117 3.58224 4.42477 3.6567 4.17877 3.6567H3.18128V2.09749H4.19553C4.46388 2.09749 4.66054 2.18016 4.79409 2.33939Z" fill="#202124"/> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/vpn.svg b/ui/webui/resources/cr_components/chromeos/network/vpn.svg index 960f4d9c..fcb05b4 100644 --- a/ui/webui/resources/cr_components/chromeos/network/vpn.svg +++ b/ui/webui/resources/cr_components/chromeos/network/vpn.svg
@@ -1 +1,3 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"><path d="M6.364 5C3.956 5 2 7.018 2 9.5S3.956 14 6.364 14c1.898 0 3.512-1.252 4.11-3H13.5v3h3v-3H18V8h-7.527c-.597-1.747-2.21-3-4.11-3zm0 6c-.8 0-1.455-.675-1.455-1.5S5.563 8 6.363 8c.8 0 1.454.675 1.454 1.5S7.164 11 6.364 11z"/></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px"> + <path d="M6.364 5C3.956 5 2 7.018 2 9.5S3.956 14 6.364 14c1.898 0 3.512-1.252 4.11-3H13.5v3h3v-3H18V8h-7.527c-.597-1.747-2.21-3-4.11-3zm0 6c-.8 0-1.455-.675-1.455-1.5S5.563 8 6.363 8c.8 0 1.454.675 1.454 1.5S7.164 11 6.364 11z"/> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/wifi_0.svg b/ui/webui/resources/cr_components/chromeos/network/wifi_0.svg index 3620b80..1387407 100644 --- a/ui/webui/resources/cr_components/chromeos/network/wifi_0.svg +++ b/ui/webui/resources/cr_components/chromeos/network/wifi_0.svg
@@ -1 +1,3 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M9.442 16.728a.706.706 0 0 0 1.113 0l7.288-9.232a.734.734 0 0 0-.155-1.055C16.496 5.611 13.733 4 10 4 6.268 4 3.505 5.611 2.312 6.441a.734.734 0 0 0-.155 1.055l7.285 9.232zm-4.83-9.35l5.387 6.827 5.39-6.828C14.143 6.713 12.279 6 10 6c-2.278 0-4.142.713-5.389 1.378z"/></svg> \ No newline at end of file +<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M9.44247 16.7281C9.72802 17.0905 10.2698 17.0905 10.5554 16.7289L17.8425 7.49646C18.1038 7.16533 18.0317 6.68099 17.6876 6.44135C16.4955 5.61135 13.7328 4 10 4C6.26792 4 3.50455 5.61135 2.31239 6.44135C1.96831 6.68099 1.89621 7.16533 2.15749 7.49646L9.44247 16.7281ZM4.61134 7.37751L9.99932 14.2053L15.3886 7.37739C14.1425 6.71268 12.2788 6 10 6C7.72159 6 5.85753 6.71277 4.61134 7.37751Z" /> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/wifi_0_with_x.svg b/ui/webui/resources/cr_components/chromeos/network/wifi_0_with_x.svg index a13bcda..16b158e 100644 --- a/ui/webui/resources/cr_components/chromeos/network/wifi_0_with_x.svg +++ b/ui/webui/resources/cr_components/chromeos/network/wifi_0_with_x.svg
@@ -1 +1,4 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M9.442 16.728a.706.706 0 0 0 1.113 0l7.288-9.232a.734.734 0 0 0-.155-1.055C16.496 5.611 13.733 4 10 4 6.268 4 3.505 5.611 2.312 6.441a.734.734 0 0 0-.155 1.055l7.285 9.232zm-4.83-9.35l5.387 6.827 5.39-6.828C14.143 6.713 12.279 6 10 6c-2.278 0-4.142.713-5.389 1.378z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M10.667 9L12 7.667 11.333 7 10 8.333 8.667 7 8 7.667 9.333 9 8 10.333l.667.667L10 9.667 11.333 11l.667-.667L10.667 9z"/></svg> \ No newline at end of file +<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M9.44247 16.7281C9.72802 17.0905 10.2698 17.0905 10.5554 16.7289L17.8425 7.49646C18.1038 7.16533 18.0317 6.68099 17.6876 6.44135C16.4955 5.61135 13.7328 4 10 4C6.26792 4 3.50455 5.61135 2.31239 6.44135C1.96831 6.68099 1.89621 7.16533 2.15749 7.49646L9.44247 16.7281ZM4.61134 7.37751L9.99932 14.2053L15.3886 7.37739C14.1425 6.71268 12.2788 6 10 6C7.72159 6 5.85753 6.71277 4.61134 7.37751Z" /> +<path fill-rule="evenodd" clip-rule="evenodd" d="M10.6667 9L12 7.66667L11.3333 7L10 8.33333L8.66667 7L8 7.66667L9.33333 9L8 10.3333L8.66667 11L10 9.66667L11.3333 11L12 10.3333L10.6667 9Z" /> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/wifi_1.svg b/ui/webui/resources/cr_components/chromeos/network/wifi_1.svg index 66b94fb..7e4e49c 100644 --- a/ui/webui/resources/cr_components/chromeos/network/wifi_1.svg +++ b/ui/webui/resources/cr_components/chromeos/network/wifi_1.svg
@@ -1 +1,4 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M9.442 16.728a.706.706 0 0 0 1.113 0l7.288-9.232a.734.734 0 0 0-.155-1.055C16.496 5.611 13.733 4 10 4 6.268 4 3.505 5.611 2.312 6.441a.734.734 0 0 0-.155 1.055l7.285 9.232zm-4.83-9.35l5.387 6.827 5.39-6.828C14.143 6.713 12.279 6 10 6c-2.278 0-4.142.713-5.389 1.378z"/><path d="M13.833 12.576A13.122 13.122 0 0 0 10 12c-1.432 0-2.721.237-3.834.576l3.276 4.152a.706.706 0 0 0 1.113 0l3.278-4.152z"/></svg> \ No newline at end of file +<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M9.44247 16.7281C9.72802 17.0905 10.2698 17.0905 10.5554 16.7289L17.8425 7.49646C18.1038 7.16533 18.0317 6.68099 17.6876 6.44135C16.4955 5.61135 13.7328 4 10 4C6.26792 4 3.50455 5.61135 2.31239 6.44135C1.96831 6.68099 1.89621 7.16533 2.15749 7.49646L9.44247 16.7281ZM4.61134 7.37751L9.99932 14.2053L15.3886 7.37739C14.1425 6.71268 12.2788 6 10 6C7.72159 6 5.85753 6.71277 4.61134 7.37751Z"/> +<path d="M13.8332 12.5761C12.7208 12.237 11.4317 12 10 12C8.56817 12 7.27891 12.2372 6.16626 12.5764L9.44247 16.7281C9.72802 17.0905 10.2698 17.0905 10.5554 16.7289L13.8332 12.5761Z" /> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/wifi_2.svg b/ui/webui/resources/cr_components/chromeos/network/wifi_2.svg index 3db1dd9..ce2f84d 100644 --- a/ui/webui/resources/cr_components/chromeos/network/wifi_2.svg +++ b/ui/webui/resources/cr_components/chromeos/network/wifi_2.svg
@@ -1 +1,3 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 4c3.733 0 6.495 1.611 7.688 2.441.344.24.416.724.155 1.055l-7.288 9.233a.706.706 0 0 1-1.113 0L2.157 7.495a.734.734 0 0 1 .155-1.055C3.505 5.611 6.268 4 10 4zm-.001 5c1.237 0 2.352.21 3.312.509l.314.102 1.764-2.234C14.143 6.713 12.279 6 10 6c-2.278 0-4.142.713-5.389 1.378L6.374 9.61A11.186 11.186 0 0 1 9.999 9z"/></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"> + <path fill-rule="evenodd" d="M7.99999976,4.4408921e-15 C11.7328,4.4408921e-15 14.4955,1.61135 15.6876,2.44135 C16.0317,2.68099 16.1038,3.16533 15.8425,3.49646 L15.8425,3.49646 L8.5554,12.7289 C8.2698,13.0905 7.72802,13.0905 7.44247,12.7281 L7.44247,12.7281 L0.15749,3.49646 C-0.10379,3.16533 -0.03169,2.68099 0.31239,2.44135 C1.50455,1.61135 4.26792,4.4408921e-15 7.99999976,4.4408921e-15 Z M7.9986,5 C9.23601,5 10.350948,5.2101302 11.3111193,5.50860386 L11.6254,5.6112 L11.6254,5.6112 C12.314,4.73885 13.3886,3.37739 13.3886,3.37739 C12.1425,2.71268 10.2788,2 8,2 C5.72159,2 3.85753,2.71277 2.61134,3.37751 C2.61134,3.37751 3.36107,4.32758 4.3736,5.61069 C5.40153,5.25916 6.62474,5 7.9986,5 Z" transform="translate(2 4)"/> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/wifi_3.svg b/ui/webui/resources/cr_components/chromeos/network/wifi_3.svg index 8fb754a..38bfe4f 100644 --- a/ui/webui/resources/cr_components/chromeos/network/wifi_3.svg +++ b/ui/webui/resources/cr_components/chromeos/network/wifi_3.svg
@@ -1 +1,3 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.555 16.729a.706.706 0 0 1-1.113 0L2.157 7.495a.734.734 0 0 1 .155-1.055C3.505 5.611 6.268 4 10 4c3.733 0 6.495 1.611 7.688 2.441.344.24.416.724.155 1.055l-7.288 9.233zM5.468 8.463L4.61 7.378C5.858 6.713 7.721 6 10 6c2.279 0 4.143.713 5.389 1.377l-.857 1.086A11.335 11.335 0 0 0 9.998 7.5c-1.804 0-3.348.447-4.531.963z"/></svg> \ No newline at end of file +<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M10.5554 16.7289C10.2698 17.0905 9.72802 17.0905 9.44247 16.7281L2.15749 7.49646C1.89621 7.16533 1.96831 6.68099 2.31239 6.44135C3.50455 5.61135 6.26792 4 10 4C13.7328 4 16.4955 5.61135 17.6876 6.44135C18.0317 6.68099 18.1038 7.16533 17.8425 7.49646L10.5554 16.7289ZM5.46762 8.4626L4.61134 7.37751C5.85753 6.71277 7.72159 6 10 6C12.2788 6 14.1425 6.71268 15.3886 7.37739L14.5315 8.46329C13.348 7.94707 11.8035 7.5 9.99865 7.5C8.19498 7.5 6.65099 7.94668 5.46762 8.4626Z" /> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/wifi_4.svg b/ui/webui/resources/cr_components/chromeos/network/wifi_4.svg index 5945322..c741f5e 100644 --- a/ui/webui/resources/cr_components/chromeos/network/wifi_4.svg +++ b/ui/webui/resources/cr_components/chromeos/network/wifi_4.svg
@@ -1 +1,3 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M17.843 7.496a.734.734 0 0 0-.155-1.055C16.496 5.611 13.733 4 10 4 6.268 4 3.505 5.611 2.312 6.441a.734.734 0 0 0-.155 1.055l7.285 9.232a.706.706 0 0 0 1.113 0l7.288-9.232z"/></svg> \ No newline at end of file +<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M17.8425 7.49646C18.1038 7.16533 18.0317 6.68099 17.6876 6.44135C16.4955 5.61135 13.7328 4 10 4C6.26792 4 3.50455 5.61135 2.31239 6.44135C1.96831 6.68099 1.89621 7.16533 2.15749 7.49646L9.44247 16.7281C9.72802 17.0905 10.2698 17.0905 10.5554 16.7289L17.8425 7.49646Z" /> +</svg>
diff --git a/ui/webui/resources/cr_components/chromeos/network/wifi_off.svg b/ui/webui/resources/cr_components/chromeos/network/wifi_off.svg index 3bad0e18..aa572361 100644 --- a/ui/webui/resources/cr_components/chromeos/network/wifi_off.svg +++ b/ui/webui/resources/cr_components/chromeos/network/wifi_off.svg
@@ -1 +1,3 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M10 6c-2.04 0-3.853.539-5.393 1.372L10 14.205l5.394-6.833A11.244 11.244 0 0 0 10 6zm7.843 1.496l-7.288 9.233a.706.706 0 0 1-1.113 0L2.157 7.495a.734.734 0 0 1 .155-1.055C3.505 5.611 6.268 4 10 4c3.733 0 6.495 1.611 7.688 2.441.344.24.416.724.155 1.055z"/></svg> \ No newline at end of file +<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M10 6C7.96011 6 6.14746 6.5389 4.6073 7.37238L9.99933 14.2053L15.3926 7.37228C13.8524 6.53869 12.0402 6 10 6ZM17.8425 7.49646L10.5554 16.7289C10.2698 17.0905 9.72802 17.0905 9.44247 16.7281L2.15749 7.49646C1.89621 7.16533 1.96831 6.68099 2.31239 6.44135C3.50455 5.61135 6.26792 4 10 4C13.7328 4 16.4955 5.61135 17.6876 6.44135C18.0317 6.68099 18.1038 7.16533 17.8425 7.49646Z" /> +</svg>
diff --git a/ui/webui/resources/images/eol.svg b/ui/webui/resources/images/eol.svg index 144d59a..3f08b30 100644 --- a/ui/webui/resources/images/eol.svg +++ b/ui/webui/resources/images/eol.svg
@@ -1 +1 @@ -<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg"><path d="M4.574 2.916H4.55l.01.01.014-.01zM2.5 4.968v.023a.18.18 0 0 1 .01-.013l-.01-.01zm14.585 10.49v-.024l-.01.013.01.01zm.223 1.817l-.933-.95-4.106-4.11L8.026 7.99 3.675 3.635l-.942-.941-.712-.713L1 3.002l1.733 1.733A9.056 9.056 0 0 0 1.05 9.98c0 1.95.628 3.748 1.683 5.22a9.037 9.037 0 0 0 2.074 2.075 8.918 8.918 0 0 0 5.218 1.684 8.918 8.918 0 0 0 5.218-1.684L16.991 19l1.02-1.021-.703-.704zM15.243 2.684A8.922 8.922 0 0 0 10.025 1a8.922 8.922 0 0 0-5.218 1.684c-.005.003 4.135 4.16 4.135 4.16l1.083-1.814L15.042 11h-1.846l4.11 4.214a8.939 8.939 0 0 0 .011-10.456 9.021 9.021 0 0 0-2.074-2.074zM12 15H7.012v-3.989L4.5 11l2.227-1.876L12 14.6v.4z" fill="#DB4437" fill-rule="evenodd"/></svg> \ No newline at end of file +<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg"><path d="M4.574 2.916H4.55l.01.01.014-.01zM2.5 4.968v.023a.18.18 0 0 1 .01-.013l-.01-.01zm14.585 10.49v-.024l-.01.013.01.01zm.223 1.817l-.933-.95-4.106-4.11L8.026 7.99 3.675 3.635l-.942-.941-.712-.713L1 3.002l1.733 1.733A9.056 9.056 0 0 0 1.05 9.98c0 1.95.628 3.748 1.683 5.22.574.8 1.274 1.501 2.074 2.075a8.918 8.918 0 0 0 5.218 1.684 8.918 8.918 0 0 0 5.218-1.684L16.991 19l1.02-1.021-.703-.704zM15.243 2.684A8.922 8.922 0 0 0 10.025 1a8.922 8.922 0 0 0-5.218 1.684c-.005.003 4.135 4.16 4.135 4.16l1.083-1.814L15.042 11h-1.846l4.11 4.214a8.939 8.939 0 0 0 .011-10.456 9.021 9.021 0 0 0-2.074-2.074zM12 15H7.012v-3.989L4.5 11l2.227-1.876L12 14.6v.4z" fill="#DB4437" fill-rule="evenodd"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/icon_copy_content.svg b/ui/webui/resources/images/icon_copy_content.svg index 9c668b02..c1c4e68 100644 --- a/ui/webui/resources/images/icon_copy_content.svg +++ b/ui/webui/resources/images/icon_copy_content.svg
@@ -1 +1,4 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#757575"><path d="M0 0h24v24H0z" fill="none"/><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="#757575"> + <path d="M0 0h24v24H0z" fill="none"/> + <path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/> +</svg>
diff --git a/ui/webui/resources/images/throbber_medium.svg b/ui/webui/resources/images/throbber_medium.svg index b9e6a30..39fd7b0 100644 --- a/ui/webui/resources/images/throbber_medium.svg +++ b/ui/webui/resources/images/throbber_medium.svg
@@ -1 +1 @@ -<svg version="1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28"><style>@keyframes rotate{0%{transform:rotate(0deg)}}@keyframes fillunfill{0%{stroke-dashoffset:58.8}50%{stroke-dashoffset:0}}@keyframes rot{0%{transform:rotate(0deg)}}@keyframes colors{0%{stroke:#4285f4}}</style><g style="animation-duration:1568.63ms;animation-iteration-count:infinite;animation-name:rotate;animation-timing-function:linear;transform-origin:50% 50%;width:28px;height:28px"><path fill="none" d="M14 1.5A12.5 12.5 0 1 1 1.5 14" stroke-width="3" stroke-linecap="round" style="animation-duration:1333ms,5332ms,5332ms;animation-fill-mode:forwards;animation-iteration-count:infinite,infinite,infinite;animation-name:fillunfill,rot,colors;animation-play-state:running,running,running;animation-timing-function:cubic-bezier(.4,0,.2,1),steps(4),linear;transform-origin:50% 50%" stroke-dasharray="58.9" stroke-dashoffset="58.9"/></g></svg> \ No newline at end of file +<svg version="1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28"><style>@keyframes rotate{0%{transform:rotate(0deg)}to{transform:rotate(360deg)}}@keyframes fillunfill{0%{stroke-dashoffset:58.8}50%{stroke-dashoffset:0}to{stroke-dashoffset:-58.4}}@keyframes rot{0%{transform:rotate(0deg)}to{transform:rotate(-360deg)}}@keyframes colors{0%,to{stroke:#4285f4}}</style><g style="animation-duration:1568.63ms;animation-iteration-count:infinite;animation-name:rotate;animation-timing-function:linear;transform-origin:50% 50%;width:28px;height:28px"><path fill="none" d="M14 1.5A12.5 12.5 0 1 1 1.5 14" stroke-width="3" stroke-linecap="round" style="animation-duration:1333ms,5332ms,5332ms;animation-fill-mode:forwards;animation-iteration-count:infinite,infinite,infinite;animation-name:fillunfill,rot,colors;animation-play-state:running,running,running;animation-timing-function:cubic-bezier(.4,0,.2,1),steps(4),linear;transform-origin:50% 50%" stroke-dasharray="58.9" stroke-dashoffset="58.9"/></g></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/throbber_small.svg b/ui/webui/resources/images/throbber_small.svg index 2461a27..8f0d9cb 100644 --- a/ui/webui/resources/images/throbber_small.svg +++ b/ui/webui/resources/images/throbber_small.svg
@@ -1 +1 @@ -<svg version="1" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><style>@keyframes rotate{0%{transform:rotate(0deg)}}@keyframes fillunfill{0%{stroke-dashoffset:32.3}50%{stroke-dashoffset:0}}@keyframes rot{0%{transform:rotate(0deg)}}@keyframes colors{0%{stroke:#4285f4}}</style><g style="animation-duration:1568.63ms;animation-iteration-count:infinite;animation-name:rotate;animation-timing-function:linear;transform-origin:50% 50%;width:16px;height:16px"><path fill="none" d="M8 1.125A6.875 6.875 0 1 1 1.125 8" stroke-width="2.25" stroke-linecap="round" style="animation-duration:1333ms,5332ms,5332ms;animation-fill-mode:forwards;animation-iteration-count:infinite,infinite,infinite;animation-name:fillunfill,rot,colors;animation-play-state:running,running,running;animation-timing-function:cubic-bezier(.4,0,.2,1),steps(4),linear;transform-origin:50% 50%" stroke-dasharray="32.4" stroke-dashoffset="32.4"/></g></svg> \ No newline at end of file +<svg version="1" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><style>@keyframes rotate{0%{transform:rotate(0deg)}to{transform:rotate(360deg)}}@keyframes fillunfill{0%{stroke-dashoffset:32.3}50%{stroke-dashoffset:0}to{stroke-dashoffset:-31.9}}@keyframes rot{0%{transform:rotate(0deg)}to{transform:rotate(-360deg)}}@keyframes colors{0%,to{stroke:#4285f4}}</style><g style="animation-duration:1568.63ms;animation-iteration-count:infinite;animation-name:rotate;animation-timing-function:linear;transform-origin:50% 50%;width:16px;height:16px"><path fill="none" d="M8 1.125A6.875 6.875 0 1 1 1.125 8" stroke-width="2.25" stroke-linecap="round" style="animation-duration:1333ms,5332ms,5332ms;animation-fill-mode:forwards;animation-iteration-count:infinite,infinite,infinite;animation-name:fillunfill,rot,colors;animation-play-state:running,running,running;animation-timing-function:cubic-bezier(.4,0,.2,1),steps(4),linear;transform-origin:50% 50%" stroke-dasharray="32.4" stroke-dashoffset="32.4"/></g></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/throbber_small_dark.svg b/ui/webui/resources/images/throbber_small_dark.svg index 6bc1ed2f..a236ecf 100644 --- a/ui/webui/resources/images/throbber_small_dark.svg +++ b/ui/webui/resources/images/throbber_small_dark.svg
@@ -1 +1 @@ -<svg version="1" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><style>@keyframes rotate{0%{transform:rotate(0deg)}}@keyframes fillunfill{0%{stroke-dashoffset:32.3}50%{stroke-dashoffset:0}}@keyframes rot{0%{transform:rotate(0deg)}}@keyframes colors{0%{stroke:#8ab4f8}}</style><g style="animation-duration:1568.63ms;animation-iteration-count:infinite;animation-name:rotate;animation-timing-function:linear;transform-origin:50% 50%;width:16px;height:16px"><path fill="none" d="M8 1.125A6.875 6.875 0 1 1 1.125 8" stroke-width="2.25" stroke-linecap="round" style="animation-duration:1333ms,5332ms,5332ms;animation-fill-mode:forwards;animation-iteration-count:infinite,infinite,infinite;animation-name:fillunfill,rot,colors;animation-play-state:running,running,running;animation-timing-function:cubic-bezier(.4,0,.2,1),steps(4),linear;transform-origin:50% 50%" stroke-dasharray="32.4" stroke-dashoffset="32.4"/></g></svg> \ No newline at end of file +<svg version="1" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><style>@keyframes rotate{0%{transform:rotate(0deg)}to{transform:rotate(360deg)}}@keyframes fillunfill{0%{stroke-dashoffset:32.3}50%{stroke-dashoffset:0}to{stroke-dashoffset:-31.9}}@keyframes rot{0%{transform:rotate(0deg)}to{transform:rotate(-360deg)}}@keyframes colors{0%,to{stroke:#8ab4f8}}</style><g style="animation-duration:1568.63ms;animation-iteration-count:infinite;animation-name:rotate;animation-timing-function:linear;transform-origin:50% 50%;width:16px;height:16px"><path fill="none" d="M8 1.125A6.875 6.875 0 1 1 1.125 8" stroke-width="2.25" stroke-linecap="round" style="animation-duration:1333ms,5332ms,5332ms;animation-fill-mode:forwards;animation-iteration-count:infinite,infinite,infinite;animation-name:fillunfill,rot,colors;animation-play-state:running,running,running;animation-timing-function:cubic-bezier(.4,0,.2,1),steps(4),linear;transform-origin:50% 50%" stroke-dasharray="32.4" stroke-dashoffset="32.4"/></g></svg> \ No newline at end of file
diff --git a/weblayer/browser/autofill_client_impl.cc b/weblayer/browser/autofill_client_impl.cc index 3bae229b..9dbfeaf 100644 --- a/weblayer/browser/autofill_client_impl.cc +++ b/weblayer/browser/autofill_client_impl.cc
@@ -7,7 +7,6 @@ #include "build/build_config.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/ui/suggestion.h" -#include "components/ukm/content/source_url_recorder.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/ssl_status.h" #include "content/public/browser/web_contents.h"
diff --git a/weblayer/browser/browser_controls_navigation_state_handler.cc b/weblayer/browser/browser_controls_navigation_state_handler.cc index 5b6c5f2..3b8701a 100644 --- a/weblayer/browser/browser_controls_navigation_state_handler.cc +++ b/weblayer/browser/browser_controls_navigation_state_handler.cc
@@ -52,9 +52,6 @@ void BrowserControlsNavigationStateHandler::DidStartNavigation( content::NavigationHandle* navigation_handle) { is_crashed_ = false; - // TODO(https://crbug.com/1218946): With MPArch there may be multiple main - // frames. This caller was converted automatically to the primary main frame - // to preserve its semantics. Follow up to confirm correctness. if (navigation_handle->IsInPrimaryMainFrame() && !navigation_handle->IsSameDocument()) { forced_show_during_load_timer_.Stop(); @@ -64,9 +61,6 @@ void BrowserControlsNavigationStateHandler::DidFinishNavigation( content::NavigationHandle* navigation_handle) { - // TODO(https://crbug.com/1218946): With MPArch there may be multiple main - // frames. This caller was converted automatically to the primary main frame - // to preserve its semantics. Follow up to confirm correctness. if (navigation_handle->IsInPrimaryMainFrame()) { if (!navigation_handle->HasCommitted()) { // There will be no DidFinishLoad or DidFailLoad, so hide the topview
diff --git a/weblayer/renderer/content_renderer_client_impl.cc b/weblayer/renderer/content_renderer_client_impl.cc index 3177eb7..5046b82 100644 --- a/weblayer/renderer/content_renderer_client_impl.cc +++ b/weblayer/renderer/content_renderer_client_impl.cc
@@ -217,9 +217,11 @@ media::GetSupportedKeySystemsCB cb) { media::KeySystemPropertiesVector key_systems; #if BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(ENABLE_WIDEVINE) cdm::AddAndroidWidevine(&key_systems); +#endif // BUILDFLAG(ENABLE_WIDEVINE) cdm::AddAndroidPlatformKeySystems(&key_systems); -#endif +#endif // BUILDFLAG(IS_ANDROID) std::move(cb).Run(std::move(key_systems)); }