diff --git a/DEPS b/DEPS index 5a0f408b..738651c 100644 --- a/DEPS +++ b/DEPS
@@ -304,7 +304,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': '9dfd1bdccb678e544b23440524ccf7ae7d5266a1', + 'skia_revision': '89742d768c973ea0e07676713825a105039b9a5d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -312,15 +312,15 @@ # 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': '645a37537f7b5e087fed63dacb2f0825d31d8304', + 'angle_revision': '7d8cbb600e5ef9bc63d039bd422af8e5c3e2a281', # 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': 'bcbc10b1bed498c81d9f7fc801e14635e821cc7c', + 'swiftshader_revision': 'd0aa9ad9447025a42f17df1b93bd71183e9b2d1f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'a72813f8d47fbee57aa04531dab7dd2322155212', + 'pdfium_revision': '355229b748b7843e23dcfb24d80f7bc16b159f33', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -331,7 +331,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Fuchsia sdk # and whatever else without interference from each other. - 'fuchsia_version': 'version:11.20221221.3.1', + 'fuchsia_version': 'version:11.20221222.0.1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -375,7 +375,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '2863c8e12d8bfb01108f785fddd92c94a2357829', + 'catapult_revision': 'b10b1305cef856fefe0827de2a1ba20d52c0580a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -383,7 +383,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': 'e7c9643691efe717cd2fd680856e58e02b5f8a2c', + 'devtools_frontend_revision': '37d35582c97bf3017430fb6e93e167911e64316e', # 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. @@ -419,7 +419,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'a1f5334e72bfd13bc2ad04a80deac2bae540aea0', + 'dawn_revision': '906fc9df206d668191e9660a16688e27eb3d97ce', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -776,12 +776,12 @@ 'src/clank': { 'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' + - '90a1af0a3e8734263fa979dc1d9ce29371378ad1', + '3e0d5ccc185f18759008e2f588f33e31cdf52104', 'condition': 'checkout_android and checkout_src_internal', }, 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + 'a21816a490b5ed39b53b42b9ac3b60711cc7955d', + 'url': Var('chromium_git') + '/website.git' + '@' + 'c924b5f5698e14acc886597b5a53d4b44f4daf9d', }, 'src/ios/third_party/earl_grey2/src': { @@ -875,7 +875,7 @@ 'packages': [ { 'package': 'chromium/rts/model/linux-amd64', - 'version': '83J3_x65NJaReq3LxP1CYYLLz4srstFe_B45yvUJOMkC', + 'version': 'IFpn8u0Ljf32cafxbLxFH0fquMy0UIuilH4Lmue_jW8C', }, ], 'dep_type': 'cipd', @@ -886,7 +886,7 @@ 'packages': [ { 'package': 'chromium/rts/model/mac-amd64', - 'version': 'PoA0W8Yg7Qu5D7PFntq-bL3o0aEleoQpOpdbtbIqEroC', + 'version': 'pAOncX-hjOcTBopPDGrahps7xWbo3Hazwv_AunHS83YC', }, ], 'dep_type': 'cipd', @@ -897,7 +897,7 @@ 'packages': [ { 'package': 'chromium/rts/model/windows-amd64', - 'version': 'dhmAQzV1Vclxd-eirwEzMitzu3VMtF0eLvj9DRfdISkC', + 'version': '_QEkP2xIpyusNbBkiOOePdTsM49L-MIzYeM-d8QDvwMC', }, ], 'dep_type': 'cipd', @@ -965,7 +965,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': '1CRXG22riAUf6hHMXngSF6stzqJ7eNsJvCWfVXpC0EQC', + 'version': 'XNQCcCxsa8Vznu546BS4QiWwlsCp1_1rV1J_5rSghKwC', }, ], 'condition': 'checkout_android', @@ -1182,7 +1182,7 @@ # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9fd66e7fbbb6eb79324e57df2c8b950a81d2e677', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '1702ac7f02e50fac5e5cf0a5bc388420023ab03e', 'condition': 'checkout_chromeos', }, @@ -1216,7 +1216,7 @@ Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '301cc781b9ace83fe8c98fe178e224cadfde93d1', + 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'aefadfcacebbc1d64d8fd81f07a7dbf4bf12cec2', 'condition': 'checkout_src_internal', }, @@ -1428,7 +1428,7 @@ Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git' + '@' + Var('libfuzzer_revision'), 'src/third_party/libaddressinput/src': - Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'df35d6c42da4fa2759e4cfb592afe33817993b89', + Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'e8712e415627f22d0b00ebee8db99547077f39bd', 'src/third_party/libaom/source/libaom': Var('aomedia_git') + '/aom.git' + '@' + 'a84503456d4276348da3e80de7569adb1b389a60', @@ -1645,7 +1645,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'b177a9b77d364faf675687204c9e48b8fd4d813c', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '2e920f3a489071ad7c98f6c84eba83f259f107a2', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1790,7 +1790,7 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@3a028e4c1f4a85437451406b23ed4d416aa0b92d', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@048d14e9ffed1f6d841a03a17d7c0406a87736df', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907', @@ -1830,7 +1830,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '5f2708ddda33a293c6a0339029c44e144d7f8f0a', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '6f5c314f07724469071fd5f347ac5479d138a033', + Var('webrtc_git') + '/src.git' + '@' + 'd29b12f90ca101e3bece49a6a67ea6da4a168111', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -1900,7 +1900,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b2f943a50d07e32f0c5da0bd600935c6a8e403ee', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0eb5bc35c0153313afefab2a3b3e1b4196c6640a', 'condition': 'checkout_src_internal', }, @@ -1930,7 +1930,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'Yp4Y5WdgXCymktb8BtHnW0KiCkx3yNSnzAZtSIg1VAUC', + 'version': '0CNuEKi70Ay8wLTnPEfahWZpa2N9aLoQbUL2gIpeYQ8C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -1941,7 +1941,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'vceV-IT5iWElElMojwOfHxwBy69Y2M7ZqmpbCF1YWRwC', + 'version': 'nizpzYofOoqUn01F6h98ktdDl-LpP7GciWj1F2a5CZ0C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 80ba73c..e5d93a18 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1080,12 +1080,17 @@ "style/style_viewer/system_ui_components_grid_view_factories.h", "style/style_viewer/system_ui_components_style_viewer_view.cc", "style/style_viewer/system_ui_components_style_viewer_view.h", + "style/style_viewer/tab_slider_instances_grid_view_factory.cc", "style/system_shadow.cc", "style/system_shadow.h", "style/system_shadow_on_nine_patch_layer.cc", "style/system_shadow_on_nine_patch_layer.h", "style/system_shadow_on_texture_layer.cc", "style/system_shadow_on_texture_layer.h", + "style/system_textfield.cc", + "style/system_textfield.h", + "style/system_textfield_controller.cc", + "style/system_textfield_controller.h", "style/system_toast_style.cc", "style/system_toast_style.h", "style/tab_slider.cc",
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc index bcbc99c..1dcd245 100644 --- a/ash/accelerators/accelerator_controller_unittest.cc +++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -1559,9 +1559,9 @@ // Tests that |side_volume_button_location_| is read correctly if the location // file exists. - base::DictionaryValue location; - location.SetString(kVolumeButtonRegion, kVolumeButtonRegionScreen); - location.SetString(kVolumeButtonSide, kVolumeButtonSideLeft); + base::Value::Dict location; + location.Set(kVolumeButtonRegion, kVolumeButtonRegionScreen); + location.Set(kVolumeButtonSide, kVolumeButtonSideLeft); std::string json_location; base::JSONWriter::Write(location, &json_location); base::ScopedTempDir file_tmp_dir;
diff --git a/ash/accessibility/magnifier/fullscreen_magnifier_controller.cc b/ash/accessibility/magnifier/fullscreen_magnifier_controller.cc index 64148b3..4245ce21 100644 --- a/ash/accessibility/magnifier/fullscreen_magnifier_controller.cc +++ b/ash/accessibility/magnifier/fullscreen_magnifier_controller.cc
@@ -67,11 +67,6 @@ // MoveMagnifierWindowFollowPoint() when |reduce_bottom_margin| is true. constexpr int kKeyboardBottomPanningMargin = 10; -void MoveCursorTo(aura::WindowTreeHost* host, const gfx::Point& root_location) { - host->MoveCursorToLocationInPixels(gfx::ToCeiledPoint( - host->GetRootTransform().MapPoint(gfx::PointF(root_location)))); -} - } // namespace class FullscreenMagnifierController::GestureProviderClient @@ -273,7 +268,7 @@ void FullscreenMagnifierController::OnImplicitAnimationsCompleted() { if (move_cursor_after_animation_) { - MoveCursorTo(root_window_->GetHost(), position_after_animation_); + MoveCursorTo(position_after_animation_); move_cursor_after_animation_ = false; aura::client::CursorClient* cursor_client = @@ -524,7 +519,9 @@ y = max_y; // Does nothing if both the origin and the scale are not changed. - if (origin_.x() == x && origin_.y() == y && scale == scale_) { + // Cast origin points back to int, as viewport can only be integer values. + if (static_cast<int>(origin_.x()) == static_cast<int>(x) && + static_cast<int>(origin_.y()) == static_cast<int>(y) && scale == scale_) { return false; } @@ -892,7 +889,7 @@ // good already). if ((x_diff != 0 || y_diff != 0) && mouse_following_mode_ != MagnifierMouseFollowingMode::kContinuous) { - MoveCursorTo(root_window_->GetHost(), point); + MoveCursorTo(point); } } } @@ -967,4 +964,15 @@ } } +void FullscreenMagnifierController::MoveCursorTo( + const gfx::Point& root_location) { + aura::WindowTreeHost* host = root_window_->GetHost(); + host->MoveCursorToLocationInPixels(gfx::ToCeiledPoint( + host->GetRootTransform().MapPoint(gfx::PointF(root_location)))); + + if (cursor_moved_callback_for_testing_) { + cursor_moved_callback_for_testing_.Run(root_location); + } +} + } // namespace ash
diff --git a/ash/accessibility/magnifier/fullscreen_magnifier_controller.h b/ash/accessibility/magnifier/fullscreen_magnifier_controller.h index 65ab4ae..f0fe62c9 100644 --- a/ash/accessibility/magnifier/fullscreen_magnifier_controller.h +++ b/ash/accessibility/magnifier/fullscreen_magnifier_controller.h
@@ -10,6 +10,7 @@ #include "ash/ash_export.h" #include "ash/public/cpp/accessibility_controller_enums.h" +#include "base/functional/callback.h" #include "ui/aura/window_observer.h" #include "ui/compositor/layer_animation_observer.h" #include "ui/events/event_handler.h" @@ -142,6 +143,11 @@ // Returns the current number of touch points. int32_t GetTouchPointsForTesting() const { return touch_points_; } + void set_cursor_moved_callback_for_testing( + base::RepeatingCallback<void(const gfx::Point&)> callback) { + cursor_moved_callback_for_testing_ = std::move(callback); + } + private: class GestureProviderClient; @@ -244,6 +250,9 @@ // to center the |rect| in that dimension. void MoveMagnifierWindowFollowRect(const gfx::Rect& rect); + // Moves the cursor to the given location in the root window. + void MoveCursorTo(const gfx::Point& root_location); + // Target root window. This must not be NULL. aura::Window* root_window_; @@ -306,6 +315,10 @@ // Flag to draw a preview box around magnifier viewport area instead of // magnifying the screen for debugging. bool magnifier_debug_draw_rect_ = false; + + // Called every time MoveCursorTo is called, when set in tests. + base::RepeatingCallback<void(const gfx::Point&)> + cursor_moved_callback_for_testing_; }; } // namespace ash
diff --git a/ash/accessibility/magnifier/fullscreen_magnifier_controller_unittest.cc b/ash/accessibility/magnifier/fullscreen_magnifier_controller_unittest.cc index 08623a2..3d9a2d9 100644 --- a/ash/accessibility/magnifier/fullscreen_magnifier_controller_unittest.cc +++ b/ash/accessibility/magnifier/fullscreen_magnifier_controller_unittest.cc
@@ -16,6 +16,7 @@ #include "base/command_line.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" +#include "base/test/bind.h" #include "ui/aura/env.h" #include "ui/aura/test/aura_test_utils.h" #include "ui/aura/window_tree_host.h" @@ -1080,4 +1081,36 @@ } } +TEST_F(FullscreenMagnifierControllerTest, DoesNotRedrawIfViewportIsNotChanged) { + auto* magnifier = GetFullscreenMagnifierController(); + // Picking a floating point scale makes the float/int conversion + // more likely to fail (which is what this test guards against). + magnifier->SetEnabled(true); + magnifier->set_mouse_following_mode(MagnifierMouseFollowingMode::kEdge); + magnifier->SetScale(10.345, /*animate=*/false); + int num_cursor_moves = 0; + magnifier->set_cursor_moved_callback_for_testing(base::BindLambdaForTesting( + [&num_cursor_moves](const gfx::Point& point) { num_cursor_moves++; })); + + ui::test::EventGenerator* event_generator = GetEventGenerator(); + + // Move until viewport is in bottom right corner, asymetrically. + gfx::Point bottom_right(kRootWidth - 70, kRootHeight - 53); + while (GetViewport().ToString() != "722,542 78x58") { + event_generator->MoveMouseToInHost(bottom_right); + } + + // The cursor has been moved. + EXPECT_GT(num_cursor_moves, 1); + + num_cursor_moves = 0; + + // Moving around further doesn't try to move the cursor position and + // doesn't change the viewport. + // If this were to happen we could end up in an infinite cursor-moving loop. + event_generator->MoveMouseToInHost(bottom_right); + EXPECT_EQ(GetViewport().ToString(), "722,542 78x58"); + EXPECT_EQ(0, num_cursor_moves); +} + } // namespace ash
diff --git a/ash/app_list/app_list_color_provider_impl.cc b/ash/app_list/app_list_color_provider_impl.cc index 6b40cd6..ef832b0 100644 --- a/ash/app_list/app_list_color_provider_impl.cc +++ b/ash/app_list/app_list_color_provider_impl.cc
@@ -40,14 +40,6 @@ kColorAshButtonIconColor); } -SkColor AppListColorProviderImpl::GetFolderBackgroundColor( - const views::Widget* app_list_widget) const { - DCHECK(app_list_widget); - - return app_list_widget->GetColorProvider()->GetColor( - kColorAshShieldAndBase80); -} - SkColor AppListColorProviderImpl::GetFolderNotificationBadgeColor( const views::Widget* app_list_widget) const { DCHECK(app_list_widget);
diff --git a/ash/app_list/app_list_color_provider_impl.h b/ash/app_list/app_list_color_provider_impl.h index a36b6d0..321c78dc 100644 --- a/ash/app_list/app_list_color_provider_impl.h +++ b/ash/app_list/app_list_color_provider_impl.h
@@ -16,8 +16,6 @@ // AppListColorProvider: SkColor GetPageSwitcherButtonColor( const views::Widget* app_list_widget) const override; - SkColor GetFolderBackgroundColor( - const views::Widget* app_list_widget) const override; SkColor GetFolderNotificationBadgeColor( const views::Widget* app_list_widget) const override; SkColor GetGridBackgroundCardActiveColor(
diff --git a/ash/app_list/views/app_list_folder_view.cc b/ash/app_list/views/app_list_folder_view.cc index d470d75..9268a92 100644 --- a/ash/app_list/views/app_list_folder_view.cc +++ b/ash/app_list/views/app_list_folder_view.cc
@@ -78,6 +78,8 @@ constexpr int kScrollViewGradientSize = 16; +constexpr int kFolderBackgroundRadius = 12; + // Insets for the vertical scroll bar. The top is pushed down slightly to align // with the icons, which keeps the scroll bar out of the rounded corner area. constexpr auto kVerticalScrollInsets = @@ -88,13 +90,6 @@ // for flying in or out the folder. constexpr base::TimeDelta kFolderTransitionDuration = base::Milliseconds(250); -// A utility function for `background_view` to update its background color. -void SetBackgroundViewColor(views::View* background_view, SkColor color) { - background_view->SetBackground(color == SK_ColorTRANSPARENT - ? nullptr - : views::CreateSolidBackground(color)); -} - // Returns true if ChromeVox (spoken feedback) is enabled. bool IsSpokenFeedbackEnabled() { return Shell::HasInstance() && // May be null in tests. @@ -110,22 +105,18 @@ public: BackgroundAnimation(bool show, AppListFolderView* folder_view, - views::View* background_view) + views::View* animating_view) : show_(show), folder_view_(folder_view), - background_view_(background_view), + animating_view_(animating_view), shadow_(folder_view->shadow()) { - background_view_observer_.Observe(background_view_); - shadow_->GetLayer()->SetVisible(true); + background_view_observer_.Observe(animating_view_); } BackgroundAnimation(const BackgroundAnimation&) = delete; BackgroundAnimation& operator=(const BackgroundAnimation&) = delete; - ~BackgroundAnimation() override { - if (!show_) - shadow_->GetLayer()->SetVisible(false); - } + ~BackgroundAnimation() override = default; private: // AppListFolderView::Animation: @@ -136,37 +127,37 @@ // Calculate the source and target states. const int icon_radius = folder_view_->GetAppListConfig()->folder_icon_radius(); - const int folder_radius = - folder_view_->GetAppListConfig()->folder_background_radius(); - const int from_radius = show_ ? icon_radius : folder_radius; - const int to_radius = show_ ? folder_radius : icon_radius; + const int from_radius = show_ ? icon_radius : kFolderBackgroundRadius; + const int to_radius = show_ ? kFolderBackgroundRadius : icon_radius; gfx::Rect from_rect = show_ ? folder_view_->folder_item_icon_bounds() - : background_view_->bounds(); - from_rect -= background_view_->bounds().OffsetFromOrigin(); - gfx::Rect to_rect = show_ ? background_view_->bounds() + : animating_view_->bounds(); + from_rect -= animating_view_->bounds().OffsetFromOrigin(); + gfx::Rect to_rect = show_ ? animating_view_->bounds() : folder_view_->folder_item_icon_bounds(); - to_rect -= background_view_->bounds().OffsetFromOrigin(); + to_rect -= animating_view_->bounds().OffsetFromOrigin(); const views::Widget* app_list_widget = folder_view_->GetWidget(); const SkColor background_color = - AppListColorProvider::Get()->GetFolderBackgroundColor(app_list_widget); + app_list_widget->GetColorProvider()->GetColor(kColorAshShieldAndBase80); const SkColor bubble_color = app_list_widget->GetColorProvider()->GetColor( kColorAshControlBackgroundColorInactive); const SkColor from_color = show_ ? bubble_color : background_color; const SkColor to_color = show_ ? background_color : bubble_color; - SetBackgroundViewColor(background_view_, from_color); - background_view_->layer()->SetClipRect(from_rect); - background_view_->layer()->SetRoundedCornerRadius( + animating_view_->layer()->SetColor(from_color); + animating_view_->layer()->SetClipRect(from_rect); + animating_view_->layer()->SetRoundedCornerRadius( gfx::RoundedCornersF(from_radius)); + AlignShadowWithAnimatingBackground(); + ui::ScopedLayerAnimationSettings settings( - background_view_->layer()->GetAnimator()); + animating_view_->layer()->GetAnimator()); settings.SetTransitionDuration(kFolderTransitionDuration); settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN); settings.AddObserver(this); - SetBackgroundViewColor(background_view_, to_color); - background_view_->layer()->SetClipRect(to_rect); - background_view_->layer()->SetRoundedCornerRadius( + animating_view_->layer()->SetColor(to_color); + animating_view_->layer()->SetClipRect(to_rect); + animating_view_->layer()->SetRoundedCornerRadius( gfx::RoundedCornersF(to_radius)); is_animating_ = true; } @@ -174,19 +165,9 @@ bool IsAnimationRunning() override { return is_animating_; } // ui::ImplicitAnimationObserver: - void OnImplicitAnimationsScheduled() override { - // Remove the highlight border at the start of the closing animation. - if (!show_) - folder_view_->UpdateHighlightBorder(false); - } - - // ui::ImplicitAnimationObserver: void OnImplicitAnimationsCompleted() override { - // Add the highlight border when the showing animation is completed. - if (show_) - folder_view_->UpdateHighlightBorder(true); - is_animating_ = false; + folder_view_->RecordAnimationSmoothness(); if (completion_callback_) @@ -200,11 +181,15 @@ // attributes. We need to use the intermediate clip rect shape from // background animation to update shadow's contents bounds and corner // radius. - DCHECK_EQ(observed_view, background_view_); + DCHECK_EQ(observed_view, animating_view_); + AlignShadowWithAnimatingBackground(); + } + + void AlignShadowWithAnimatingBackground() { // If layer clip rect is not empty, we use the clip rect to update the // shadow's contents bounds. Otherwise, we use the layer bounds. - const auto* background_layer = background_view_->layer(); + const auto* background_layer = animating_view_->layer(); const gfx::Rect& background_bounds = background_layer->bounds(); const gfx::Rect& clip_rect = background_layer->clip_rect(); const gfx::Rect& content_bounds = @@ -219,9 +204,9 @@ const bool show_; bool is_animating_ = false; - AppListFolderView* const folder_view_; // Not owned. - views::View* const background_view_; // Not owned. - SystemShadow* const shadow_; // Not owned. + AppListFolderView* const folder_view_; + views::View* const animating_view_; + SystemShadow* const shadow_; // Observes the rect clip change of background view. base::ScopedObservation<views::View, views::ViewObserver> @@ -362,7 +347,8 @@ // Add the transitional views into child views, and set its bounds to the // same location of the item in the folder list view. top_icon_views_.push_back( - folder_view_->background_view()->AddChildView(std::move(icon_view))); + folder_view_->animating_background()->AddChildView( + std::move(icon_view))); icon_view_ptr->SetBoundsRect(first_page_item_views_bounds[i]); icon_view_ptr->TransformView(kFolderTransitionDuration); } @@ -531,10 +517,6 @@ layer->SetTransform(transform); layer->SetOpacity(show_ ? 0.0f : 1.0f); - // The folder should be set visible only after it is scaled down and - // transparent to prevent the flash of the view right before the animation. - folder_view_->SetVisible(true); - ui::ScopedLayerAnimationSettings animation(layer->GetAnimator()); animation.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN); animation.AddObserver(this); @@ -643,6 +625,24 @@ ColorProvider::kBackgroundBlurSigma); background_view_->layer()->SetBackdropFilterQuality( ColorProvider::kBackgroundBlurQuality); + background_view_->layer()->SetRoundedCornerRadius( + gfx::RoundedCornersF(kFolderBackgroundRadius)); + background_view_->layer()->SetIsFastRoundedCorner(true); + background_view_->SetBorder(std::make_unique<views::HighlightBorder>( + kFolderBackgroundRadius, views::HighlightBorder::Type::kHighlightBorder1, + /*use_light_colors=*/!features::IsDarkLightModeEnabled())); + background_view_->SetBackground( + views::CreateThemedSolidBackground(kColorAshShieldAndBase80)); + background_view_->SetVisible(false); + + animating_background_ = AddChildView(std::make_unique<views::View>()); + animating_background_->SetPaintToLayer(ui::LAYER_SOLID_COLOR); + animating_background_->layer()->SetBackgroundBlur( + ColorProvider::kBackgroundBlurSigma); + animating_background_->layer()->SetBackdropFilterQuality( + ColorProvider::kBackgroundBlurQuality); + animating_background_->layer()->SetFillsBoundsOpaquely(false); + animating_background_->SetVisible(false); contents_container_ = AddChildView(std::make_unique<views::View>()); contents_container_->SetPaintToLayer(ui::LAYER_NOT_DRAWN); @@ -653,7 +653,6 @@ shadow_ = SystemShadow::CreateShadowOnNinePatchLayer( SystemShadow::Type::kElevation8); background_view_->AddLayerBeneathView(shadow_->GetLayer()); - shadow_->GetLayer()->SetVisible(false); AppListModelProvider::Get()->AddObserver(this); } @@ -779,7 +778,7 @@ // Animate the background corner radius, opacity and bounds. folder_visibility_animations_.push_back( - std::make_unique<BackgroundAnimation>(show, this, background_view_)); + std::make_unique<BackgroundAnimation>(show, this, animating_background_)); // Animate the folder item's title's opacity. views::View* const folder_title = folder_item_view_->title(); @@ -811,6 +810,12 @@ weak_ptr_factory_.GetWeakPtr())); } + SetVisible(true); + + background_view_->SetVisible(false); + animating_background_->SetVisible(true); + shadow_->GetLayer()->SetVisible(true); + for (auto& animation : folder_visibility_animations_) animation->ScheduleAnimation(animation_completion_callback); } @@ -896,7 +901,8 @@ // Transition all the states immediately to the end of folder closing // animation. - SetBackgroundViewColor(background_view_, SK_ColorTRANSPARENT); + background_view_->SetVisible(false); + if (restore_folder_item_view_state && folder_item_view_) { folder_item_view_->SetIconVisible(true); folder_item_view_->title()->DestroyLayer(); @@ -910,11 +916,17 @@ } void AppListFolderView::OnShowAnimationDone() { + animating_background_->SetVisible(false); + background_view_->SetVisible(true); + if (animation_done_test_callback_) std::move(animation_done_test_callback_).Run(); } void AppListFolderView::OnHideAnimationDone(bool hide_for_reparent) { + animating_background_->SetVisible(false); + shadow_->GetLayer()->SetVisible(false); + a11y_announcer_->AnnounceFolderClosed(); // If the folder view is hiding for folder closure, reset the @@ -937,18 +949,6 @@ std::move(animation_done_test_callback_).Run(); } -void AppListFolderView::UpdateHighlightBorder(bool show) { - if (!show) { - background_view_->SetBorder(nullptr); - return; - } - - background_view_->SetBorder(std::make_unique<views::HighlightBorder>( - GetAppListConfig()->folder_background_radius(), - views::HighlightBorder::Type::kHighlightBorder1, - /*use_light_colors=*/!features::IsDarkLightModeEnabled())); -} - void AppListFolderView::UpdatePreferredBounds() { if (!folder_item_view_) return;
diff --git a/ash/app_list/views/app_list_folder_view.h b/ash/app_list/views/app_list_folder_view.h index 9d252901..eeb74b1 100644 --- a/ash/app_list/views/app_list_folder_view.h +++ b/ash/app_list/views/app_list_folder_view.h
@@ -140,10 +140,6 @@ // to be in the parent view's coordinate system. void SetBoundingBox(const gfx::Rect& bounding_box); - // Updates the highlight border of the folder view according to the folder - // animation. - void UpdateHighlightBorder(bool show); - // Sets the callback that runs when the folder animation ends. void SetAnimationDoneTestCallback(base::OnceClosure animation_done_callback); @@ -151,7 +147,7 @@ FolderHeaderView* folder_header_view() { return folder_header_view_; } - views::View* background_view() { return background_view_; } + views::View* animating_background() { return animating_background_; } views::View* contents_container() { return contents_container_; } @@ -236,7 +232,8 @@ AppListA11yAnnouncer* const a11y_announcer_; // The view is used to draw a background with corner radius. - views::View* background_view_; // Owned by views hierarchy. + views::View* background_view_; + views::View* animating_background_; // The view is used as a container for all following views. views::View* contents_container_; // Owned by views hierarchy.
diff --git a/ash/assistant/assistant_web_view_delegate_impl.cc b/ash/assistant/assistant_web_view_delegate_impl.cc index 0d43831..1c7779e 100644 --- a/ash/assistant/assistant_web_view_delegate_impl.cc +++ b/ash/assistant/assistant_web_view_delegate_impl.cc
@@ -37,7 +37,6 @@ case views::CAPTION_BUTTON_ICON_BACK: return back_button_visibility_; - case views::CAPTION_BUTTON_ICON_FLOAT: case views::CAPTION_BUTTON_ICON_MINIMIZE: case views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE: case views::CAPTION_BUTTON_ICON_LEFT_TOP_SNAPPED:
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 9402108..1d70c01a4 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -756,11 +756,6 @@ "EnableLogControllerForDiagnosticsApp", base::FEATURE_ENABLED_BY_DEFAULT); -// If enabled, the networking cards will be shown in the diagnostics app. -BASE_FEATURE(kEnableNetworkingInDiagnosticsApp, - "EnableNetworkingInDiagnosticsApp", - base::FEATURE_ENABLED_BY_DEFAULT); - // Enables OAuth support when printing via the IPP protocol. BASE_FEATURE(kEnableOAuthIpp, "EnableOAuthIpp", @@ -919,12 +914,6 @@ "FastPairSoftwareScanning", base::FEATURE_DISABLED_BY_DEFAULT); -// Enables the "Subsequent Pairing" Fast Pair scenario in Bluetooth Settings -// and Quick Settings. -BASE_FEATURE(kFastPairSubsequentPairingUX, - "FastPairSubsequentPairingUX", - base::FEATURE_DISABLED_BY_DEFAULT); - // Enables the "Saved Devices" Fast Pair page in scenario in Bluetooth Settings. BASE_FEATURE(kFastPairSavedDevices, "FastPairSavedDevices", @@ -1504,16 +1493,14 @@ "OobeHidDetectionRevamp", base::FEATURE_DISABLED_BY_DEFAULT); +// Enables OOBE Jelly features. +BASE_FEATURE(kOobeJelly, "OobeJelly", base::FEATURE_DISABLED_BY_DEFAULT); + // Enables or disables the Oobe quick start flow. BASE_FEATURE(kOobeQuickStart, "OobeQuickStart", base::FEATURE_DISABLED_BY_DEFAULT); -// Enables OOBE Material Next features. -BASE_FEATURE(kOobeMaterialNext, - "OobeMaterialNext", - base::FEATURE_DISABLED_BY_DEFAULT); - // Removes "Shut down" button from OOBE, except first login screen and // successful enrollment step. BASE_FEATURE(kOobeRemoveShutdownButton, @@ -2315,10 +2302,6 @@ return base::FeatureList::IsEnabled(kArcInputOverlayAlphaV2); } -bool IsArcNetworkDiagnosticsButtonEnabled() { - return IsNetworkingInDiagnosticsAppEnabled(); -} - bool IsAssistantNativeIconsEnabled() { return base::FeatureList::IsEnabled(kAssistantNativeIcons); } @@ -2554,10 +2537,6 @@ return base::FeatureList::IsEnabled(kFastPairSoftwareScanning); } -bool IsFastPairSubsequentPairingUXEnabled() { - return base::FeatureList::IsEnabled(kFastPairSubsequentPairingUX); -} - bool IsFastPairSavedDevicesEnabled() { return base::FeatureList::IsEnabled(kFastPairSavedDevices); } @@ -2809,10 +2788,6 @@ return base::FeatureList::IsEnabled(kNearbyKeepAliveFix); } -bool IsNetworkingInDiagnosticsAppEnabled() { - return base::FeatureList::IsEnabled(kEnableNetworkingInDiagnosticsApp); -} - bool IsOAuthIppEnabled() { return base::FeatureList::IsEnabled(kEnableOAuthIpp); } @@ -2857,8 +2832,8 @@ return base::FeatureList::IsEnabled(kEnableKioskLoginScreen); } -bool IsOobeMaterialNextEnabled() { - return IsJellyEnabled() && base::FeatureList::IsEnabled(kOobeMaterialNext); +bool IsOobeJellyEnabled() { + return IsJellyEnabled() && base::FeatureList::IsEnabled(kOobeJelly); } bool IsOobeNetworkScreenSkipEnabled() {
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index 7e0c696..c850257 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -226,8 +226,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kEnableLocalSearchService); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kEnableLogControllerForDiagnosticsApp); -COMPONENT_EXPORT(ASH_CONSTANTS) -BASE_DECLARE_FEATURE(kEnableNetworkingInDiagnosticsApp); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kEnableOAuthIpp); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kEnableOobeChromeVoxHint); COMPONENT_EXPORT(ASH_CONSTANTS) @@ -271,8 +269,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::FeatureParam<double> kFastPairLowPowerInactiveSeconds; COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kFastPairSoftwareScanning); -COMPONENT_EXPORT(ASH_CONSTANTS) -BASE_DECLARE_FEATURE(kFastPairSubsequentPairingUX); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kFastPairSavedDevices); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kFastPairSavedDevicesStrictOptIn); @@ -428,8 +424,8 @@ COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kOobeChoobe); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kOobeConsolidatedConsent); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kOobeHidDetectionRevamp); +COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kOobeJelly); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kOobeQuickStart); -COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kOobeMaterialNext); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kOobeNewRecommendApps); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kOobeRemoveShutdownButton); COMPONENT_EXPORT(ASH_CONSTANTS) @@ -636,7 +632,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool IsArcFuseBoxFileSharingEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsArcInputOverlayAlphaV2Enabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsArcInputOverlayBetaEnabled(); -COMPONENT_EXPORT(ASH_CONSTANTS) bool IsArcNetworkDiagnosticsButtonEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsAssistantNativeIconsEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsAssistiveMultiWordEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsAudioSettingsPageEnabled(); @@ -699,7 +694,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFastPairPreventNotificationsForRecentlyLostDeviceEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFastPairSoftwareScanningEnabled(); -COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFastPairSubsequentPairingUXEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFastPairSavedDevicesEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFastPairSavedDevicesStrictOptInEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFederatedServiceEnabled(); @@ -761,7 +755,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool IsMicMuteNotificationsEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsMinimumChromeVersionEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsNearbyKeepAliveFixEnabled(); -COMPONENT_EXPORT(ASH_CONSTANTS) bool IsNetworkingInDiagnosticsAppEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsEducationEnrollmentOobeFlowEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsNewLockScreenReauthLayoutEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsNotificationExpansionAnimationEnabled(); @@ -774,9 +767,9 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeChoobeEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeChromeVoxHintEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeHidDetectionRevampEnabled(); +COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeJellyEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsKioskEnrollmentInOobeEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsKioskLoginScreenEnabled(); -COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeMaterialNextEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeNetworkScreenSkipEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeConsolidatedConsentEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeQuickStartEnabled();
diff --git a/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc b/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc index fb2ed4a8..6193ec4 100644 --- a/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc +++ b/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
@@ -342,58 +342,24 @@ EXPECT_TRUE(window_state->IsSnapped()); } -// Test float button requires kFloatWindow feature to be enabled during setup. -class WindowFloatButtonTest : public FrameCaptionButtonContainerViewTest { +// Test float button requires `kFloatWindow` feature to be enabled during setup. +class FrameCaptionButtonContainerViewWithFloatTest + : public FrameCaptionButtonContainerViewTest { public: - WindowFloatButtonTest() + FrameCaptionButtonContainerViewWithFloatTest() : scoped_feature_list_(chromeos::wm::features::kFloatWindow) {} - WindowFloatButtonTest(const WindowFloatButtonTest&) = delete; - WindowFloatButtonTest& operator=(const WindowFloatButtonTest&) = delete; - ~WindowFloatButtonTest() override = default; - - void ClickFloatButton(FrameCaptionButtonContainerView::TestApi* test_api) { - ui::test::EventGenerator* generator = GetEventGenerator(); - auto* float_button = test_api->float_button(); - generator->MoveMouseTo(float_button->GetBoundsInScreen().CenterPoint()); - generator->ClickLeftButton(); - } + FrameCaptionButtonContainerViewWithFloatTest( + const FrameCaptionButtonContainerViewWithFloatTest&) = delete; + FrameCaptionButtonContainerViewWithFloatTest& operator=( + const FrameCaptionButtonContainerViewWithFloatTest&) = delete; + ~FrameCaptionButtonContainerViewWithFloatTest() override = default; private: base::test::ScopedFeatureList scoped_feature_list_; }; -TEST_F(WindowFloatButtonTest, TestFloatButtonBehavior) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshDeveloperShortcuts); - - auto* widget = CreateTestWidget(MAXIMIZE_ALLOWED, MINIMIZE_ALLOWED, - CLOSE_BUTTON_VISIBLE); - auto* window = widget->GetNativeWindow(); - window->SetProperty(aura::client::kAppType, - static_cast<int>(ash::AppType::BROWSER)); - widget->Show(); - - FrameCaptionButtonContainerView container(widget); - InitContainer(&container); - widget->GetContentsView()->AddChildView(&container); - views::test::RunScheduledLayout(&container); - FrameCaptionButtonContainerView::TestApi testApi(&container); - - ClickFloatButton(&testApi); - auto* window_state = WindowState::Get(window); - // Check if window is floated. - EXPECT_TRUE(window_state->IsFloated()); - EXPECT_EQ(window->GetProperty(chromeos::kWindowStateTypeKey), - chromeos::WindowStateType::kFloated); - - ClickFloatButton(&testApi); - // Check if window is unfloated. - EXPECT_FALSE(window_state->IsFloated()); - EXPECT_EQ(window->GetProperty(chromeos::kWindowStateTypeKey), - chromeos::WindowStateType::kNormal); -} - -TEST_F(WindowFloatButtonTest, TabletSizeButtonVisibility) { +TEST_F(FrameCaptionButtonContainerViewWithFloatTest, + TabletSizeButtonVisibility) { Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true); // Create a window in tablet mode. It should be maximized and the size button
diff --git a/ash/public/cpp/app_list/app_list_color_provider.h b/ash/public/cpp/app_list/app_list_color_provider.h index 630a9518..693d6c0 100644 --- a/ash/public/cpp/app_list/app_list_color_provider.h +++ b/ash/public/cpp/app_list/app_list_color_provider.h
@@ -20,8 +20,6 @@ virtual SkColor GetPageSwitcherButtonColor( const views::Widget* app_list_widget) const = 0; - virtual SkColor GetFolderBackgroundColor( - const views::Widget* app_list_widget) const = 0; virtual SkColor GetFolderNotificationBadgeColor( const views::Widget* app_list_widget) const = 0; virtual SkColor GetGridBackgroundCardActiveColor(
diff --git a/ash/public/cpp/app_list/app_list_config.cc b/ash/public/cpp/app_list/app_list_config.cc index e37acc5c..d2584b3 100644 --- a/ash/public/cpp/app_list/app_list_config.cc +++ b/ash/public/cpp/app_list/app_list_config.cc
@@ -175,7 +175,6 @@ folder_unclipped_icon_dimension_( FolderUnclippedIconDimensionForType(type)), folder_icon_radius_(FolderClippedIconDimensionForType(type) / 2), - folder_background_radius_(12), item_icon_in_folder_icon_dimension_( ItemIconInFolderIconDimensionForType(type)), item_icon_in_folder_icon_margin_(4), @@ -203,8 +202,6 @@ folder_unclipped_icon_dimension_( Scale(base_config.folder_unclipped_icon_dimension_, scale_x)), folder_icon_radius_(Scale(base_config.folder_icon_radius_, scale_x)), - folder_background_radius_( - Scale(base_config.folder_background_radius_, scale_x)), item_icon_in_folder_icon_dimension_( Scale(base_config.item_icon_in_folder_icon_dimension_, scale_x)), item_icon_in_folder_icon_margin_(
diff --git a/ash/public/cpp/app_list/app_list_config.h b/ash/public/cpp/app_list/app_list_config.h index 9da6206..6d35ab8 100644 --- a/ash/public/cpp/app_list/app_list_config.h +++ b/ash/public/cpp/app_list/app_list_config.h
@@ -189,7 +189,6 @@ return folder_unclipped_icon_dimension_; } int folder_icon_radius() const { return folder_icon_radius_; } - int folder_background_radius() const { return folder_background_radius_; } int item_icon_in_folder_icon_dimension() const { return item_icon_in_folder_icon_dimension_; } @@ -280,9 +279,6 @@ // The corner radius of folder icon. const int folder_icon_radius_; - // The corner radius of folder background. - const int folder_background_radius_; - // The dimension of the item icon in folder icon. const int item_icon_in_folder_icon_dimension_;
diff --git a/ash/public/cpp/test/test_app_list_color_provider.cc b/ash/public/cpp/test/test_app_list_color_provider.cc index 0a32ca9..4e2cbe2 100644 --- a/ash/public/cpp/test/test_app_list_color_provider.cc +++ b/ash/public/cpp/test/test_app_list_color_provider.cc
@@ -9,11 +9,6 @@ namespace ash { -SkColor TestAppListColorProvider::GetFolderBackgroundColor( - const views::Widget* app_list_widget) const { - return gfx::kGoogleGrey900; -} - SkColor TestAppListColorProvider::GetPageSwitcherButtonColor( const views::Widget* app_list_widget) const { return gfx::kGoogleGrey700;
diff --git a/ash/public/cpp/test/test_app_list_color_provider.h b/ash/public/cpp/test/test_app_list_color_provider.h index 2866de2..b931ca57 100644 --- a/ash/public/cpp/test/test_app_list_color_provider.h +++ b/ash/public/cpp/test/test_app_list_color_provider.h
@@ -19,8 +19,6 @@ // AppListColorProvider: SkColor GetPageSwitcherButtonColor( const views::Widget* app_list_widget) const override; - SkColor GetFolderBackgroundColor( - const views::Widget* app_list_widget) const override; SkColor GetFolderNotificationBadgeColor( const views::Widget* app_list_widget) const override; SkColor GetGridBackgroundCardActiveColor(
diff --git a/ash/quick_pair/common/fast_pair/fast_pair_metrics.cc b/ash/quick_pair/common/fast_pair/fast_pair_metrics.cc index bafd3c99e..222feda 100644 --- a/ash/quick_pair/common/fast_pair/fast_pair_metrics.cc +++ b/ash/quick_pair/common/fast_pair/fast_pair_metrics.cc
@@ -34,6 +34,16 @@ // Model IDs associated with the same device (for example, each Pixel Bud Pros // have different Model IDs for each different color) so we append '_*' to the // naming for subsequent Model IDs after the first one. +const char kPopularPeripheral_BoatRockerz255Pro_ModelId[] = "CFF121"; +const char kPopularPeripheral_BoatRockerz255Pro_Name[] = "BoatRockerz255Pro"; + +const char kPopularPeripheral_BoseQuietComfort35II_ModelId[] = "0100F0"; +const char kPopularPeripheral_BoseQuietComfort35II_Name[] = + "BoseQuietComfort35II"; +const char kPopularPeripheral_BoseQuietComfort35II_1_ModelId[] = "0000F0"; +const char kPopularPeripheral_BoseQuietComfort35II_1_Name[] = + "BoseQuietComfort35II_1"; + const char kPopularPeripheral_JBLLIVEPROTWS_ModelId[] = "461BB8"; const char kPopularPeripheral_JBLLIVEPROTWS_Name[] = "JBLLIVEPROTWS"; const char kPopularPeripheral_JBLLIVEPROTWS_1_ModelId[] = "C6936A"; @@ -80,6 +90,15 @@ const char kPopularPeripheral_JBLTUNE125TWS_5_ModelId[] = "BD193B"; const char kPopularPeripheral_JBLTUNE125TWS_5_Name[] = "JBLTUNE125TWS_5"; +const char kPopularPeripheral_JBLTUNE130NCTWS_ModelId[] = "BDB433"; +const char kPopularPeripheral_JBLTUNE130NCTWS_Name[] = "JBLTUNE130NCTWS"; +const char kPopularPeripheral_JBLTUNE130NCTWS_1_ModelId[] = "1115E7"; +const char kPopularPeripheral_JBLTUNE130NCTWS_1_Name[] = "JBLTUNE130NCTWS_1"; +const char kPopularPeripheral_JBLTUNE130NCTWS_2_ModelId[] = "436FD1"; +const char kPopularPeripheral_JBLTUNE130NCTWS_2_Name[] = "JBLTUNE130NCTWS_2"; +const char kPopularPeripheral_JBLTUNE130NCTWS_3_ModelId[] = "B73DBA"; +const char kPopularPeripheral_JBLTUNE130NCTWS_3_Name[] = "JBLTUNE130NCTWS_3"; + const char kPopularPeripheral_JBLTUNE225TWS_ModelId[] = "5C0C84"; const char kPopularPeripheral_JBLTUNE225TWS_Name[] = "JBLTUNE225TWS"; const char kPopularPeripheral_JBLTUNE225TWS_1_ModelId[] = "FAA6C3"; @@ -93,20 +112,27 @@ const char kPopularPeripheral_JBLTUNE225TWS_5_ModelId[] = "9C98DB"; const char kPopularPeripheral_JBLTUNE225TWS_5_Name[] = "JBLTUNE225TWS_5"; -const char kPopularPeripheral_JBLTUNE130NCTWS_ModelId[] = "BDB433"; -const char kPopularPeripheral_JBLTUNE130NCTWS_Name[] = "JBLTUNE130NCTWS"; -const char kPopularPeripheral_JBLTUNE130NCTWS_1_ModelId[] = "1115E7"; -const char kPopularPeripheral_JBLTUNE130NCTWS_1_Name[] = "JBLTUNE130NCTWS_1"; -const char kPopularPeripheral_JBLTUNE130NCTWS_2_ModelId[] = "436FD1"; -const char kPopularPeripheral_JBLTUNE130NCTWS_2_Name[] = "JBLTUNE130NCTWS_2"; -const char kPopularPeripheral_JBLTUNE130NCTWS_3_ModelId[] = "B73DBA"; -const char kPopularPeripheral_JBLTUNE130NCTWS_3_Name[] = "JBLTUNE130NCTWS_3"; +const char kPopularPeripheral_JBLTUNE230NCTWS_ModelId[] = "96C12E"; +const char kPopularPeripheral_JBLTUNE230NCTWS_Name[] = "JBLTUNE230NCTWS"; +const char kPopularPeripheral_JBLTUNE230NCTWS_1_ModelId[] = "71F20A"; +const char kPopularPeripheral_JBLTUNE230NCTWS_1_Name[] = "JBLTUNE230NCTWS_1"; +const char kPopularPeripheral_JBLTUNE230NCTWS_2_ModelId[] = "EB01C0"; +const char kPopularPeripheral_JBLTUNE230NCTWS_2_Name[] = "JBLTUNE230NCTWS_2"; +const char kPopularPeripheral_JBLTUNE230NCTWS_3_ModelId[] = "A9394A"; +const char kPopularPeripheral_JBLTUNE230NCTWS_3_Name[] = "JBLTUNE230NCTWS_3"; const char kPopularPeripheral_NothingEar1_ModelId[] = "31D53D"; const char kPopularPeripheral_NothingEar1_Name[] = "NOTHINGEAR1"; const char kPopularPeripheral_NothingEar1_1_ModelId[] = "624011"; const char kPopularPeripheral_NothingEar1_1_Name[] = "NOTHINGEAR1_1"; +const char kPopularPeripheral_OnePlusBuds_ModelId[] = "5F5806"; +const char kPopularPeripheral_OnePlusBuds_Name[] = "OnePlusBuds"; +const char kPopularPeripheral_OnePlusBuds_1_ModelId[] = "81B915"; +const char kPopularPeripheral_OnePlusBuds_1_Name[] = "OnePlusBuds_1"; +const char kPopularPeripheral_OnePlusBuds_2_ModelId[] = "6C73F1"; +const char kPopularPeripheral_OnePlusBuds_2_Name[] = "OnePlusBuds_2"; + const char kPopularPeripheral_OnePlusBudsZ_ModelId[] = "A41C91"; const char kPopularPeripheral_OnePlusBudsZ_Name[] = "OnePlusBudsZ"; const char kPopularPeripheral_OnePlusBudsZ_1_ModelId[] = "1393DE"; @@ -148,6 +174,19 @@ const char kPopularPeripheral_RealMeBudsAir2Neo_ModelId[] = "0B5374"; const char kPopularPeripheral_RealMeBudsAir2Neo_Name[] = "RealMeBudsAir2Neo"; +const char kPopularPeripheral_RealMeBudsQ2TWS_ModelId[] = "72C415"; +const char kPopularPeripheral_RealMeBudsQ2TWS_Name[] = "RealMeBudsQ2TWS"; + +const char kPopularPeripheral_RealMeTechLifeBudsT100_ModelId[] = "29C992"; +const char kPopularPeripheral_RealMeTechLifeBudsT100_Name[] = + "RealMeTechLifeBudsT100"; +const char kPopularPeripheral_RealMeTechLifeBudsT100_1_ModelId[] = "D5C6CE"; +const char kPopularPeripheral_RealMeTechLifeBudsT100_1_Name[] = + "RealMeTechLifeBudsT100_1"; +const char kPopularPeripheral_RealMeTechLifeBudsT100_2_ModelId[] = "62E69F"; +const char kPopularPeripheral_RealMeTechLifeBudsT100_2_Name[] = + "RealMeTechLifeBudsT100_2"; + const char kPopularPeripheral_SonyWF1000XM3_ModelId[] = "38C95C"; const char kPopularPeripheral_SonyWF1000XM3_Name[] = "SonyWF1000XM3"; const char kPopularPeripheral_SonyWF1000XM3_1_ModelId[] = "9C98DB"; @@ -170,6 +209,19 @@ const char kPopularPeripheral_SonyWH1000XM3_1_ModelId[] = "AC95C"; const char kPopularPeripheral_SonyWH1000XM3_1_Name[] = "SonyWH1000XM3_1"; +const char kPopularPeripheral_SRSXB13_ModelId[] = "741594"; +const char kPopularPeripheral_SRSXB13_Name[] = "SRSXB13"; +const char kPopularPeripheral_SRSXB13_1_ModelId[] = "DF4B02"; +const char kPopularPeripheral_SRSXB13_1_Name[] = "SRSXB13_1"; +const char kPopularPeripheral_SRSXB13_2_ModelId[] = "F5CEC7"; +const char kPopularPeripheral_SRSXB13_2_Name[] = "SRSXB13_2"; +const char kPopularPeripheral_SRSXB13_3_ModelId[] = "FFB35B"; +const char kPopularPeripheral_SRSXB13_3_Name[] = "SRSXB13_3"; +const char kPopularPeripheral_SRSXB13_4_ModelId[] = "36EFA5"; +const char kPopularPeripheral_SRSXB13_4_Name[] = "SRSXB13_4"; +const char kPopularPeripheral_SRSXB13_5_ModelId[] = "3E6B5B"; +const char kPopularPeripheral_SRSXB13_5_Name[] = "SRSXB13_5"; + const char kPopularPeripheral_SRSXB23_ModelId[] = "30D222"; const char kPopularPeripheral_SRSXB23_Name[] = "SRSXB23"; const char kPopularPeripheral_SRSXB23_1_ModelId[] = "438188"; @@ -193,161 +245,297 @@ const char kPopularPeripheral_Other_Name[] = "Other"; const std::string GetFastPairTrackedModelId(const std::string& model_id) { - if (model_id == kPopularPeripheral_JBLLIVE300TWS_ModelId) - return kPopularPeripheral_JBLLIVE300TWS_Name; - if (model_id == kPopularPeripheral_JBLLIVE300TWS_1_ModelId) - return kPopularPeripheral_JBLLIVE300TWS_1_Name; - if (model_id == kPopularPeripheral_JBLLIVE300TWS_2_ModelId) - return kPopularPeripheral_JBLLIVE300TWS_2_Name; + if (model_id == kPopularPeripheral_BoatRockerz255Pro_ModelId) { + return kPopularPeripheral_BoatRockerz255Pro_Name; + } - if (model_id == kPopularPeripheral_JBLLIVE400BT_ModelId) - return kPopularPeripheral_JBLLIVE400BT_Name; - if (model_id == kPopularPeripheral_JBLLIVE400BT_1_ModelId) - return kPopularPeripheral_JBLLIVE400BT_1_Name; - if (model_id == kPopularPeripheral_JBLLIVE400BT_2_ModelId) - return kPopularPeripheral_JBLLIVE400BT_2_Name; - if (model_id == kPopularPeripheral_JBLLIVE400BT_3_ModelId) - return kPopularPeripheral_JBLLIVE400BT_3_Name; - if (model_id == kPopularPeripheral_JBLLIVE400BT_4_ModelId) - return kPopularPeripheral_JBLLIVE400BT_4_Name; + if (model_id == kPopularPeripheral_BoseQuietComfort35II_ModelId) { + return kPopularPeripheral_BoseQuietComfort35II_Name; + } + if (model_id == kPopularPeripheral_BoseQuietComfort35II_1_ModelId) { + return kPopularPeripheral_BoseQuietComfort35II_1_Name; + } - if (model_id == kPopularPeripheral_JBLTUNE125TWS_ModelId) - return kPopularPeripheral_JBLTUNE125TWS_Name; - if (model_id == kPopularPeripheral_JBLTUNE125TWS_1_ModelId) - return kPopularPeripheral_JBLTUNE125TWS_1_Name; - if (model_id == kPopularPeripheral_JBLTUNE125TWS_2_ModelId) - return kPopularPeripheral_JBLTUNE125TWS_2_Name; - if (model_id == kPopularPeripheral_JBLTUNE125TWS_3_ModelId) - return kPopularPeripheral_JBLTUNE125TWS_3_Name; - if (model_id == kPopularPeripheral_JBLTUNE125TWS_4_ModelId) - return kPopularPeripheral_JBLTUNE125TWS_4_Name; - if (model_id == kPopularPeripheral_JBLTUNE125TWS_5_ModelId) - return kPopularPeripheral_JBLTUNE125TWS_5_Name; - - if (model_id == kPopularPeripheral_JBLTUNE225TWS_ModelId) - return kPopularPeripheral_JBLTUNE225TWS_Name; - if (model_id == kPopularPeripheral_JBLTUNE225TWS_1_ModelId) - return kPopularPeripheral_JBLTUNE225TWS_1_Name; - if (model_id == kPopularPeripheral_JBLTUNE225TWS_2_ModelId) - return kPopularPeripheral_JBLTUNE225TWS_2_Name; - if (model_id == kPopularPeripheral_JBLTUNE225TWS_3_ModelId) - return kPopularPeripheral_JBLTUNE225TWS_3_Name; - if (model_id == kPopularPeripheral_JBLTUNE225TWS_4_ModelId) - return kPopularPeripheral_JBLTUNE225TWS_4_Name; - if (model_id == kPopularPeripheral_JBLTUNE225TWS_5_ModelId) - return kPopularPeripheral_JBLTUNE225TWS_5_Name; - - if (model_id == kPopularPeripheral_OnePlusBudsZ_ModelId) - return kPopularPeripheral_OnePlusBudsZ_Name; - if (model_id == kPopularPeripheral_OnePlusBudsZ_1_ModelId) - return kPopularPeripheral_OnePlusBudsZ_1_Name; - if (model_id == kPopularPeripheral_OnePlusBudsZ_2_ModelId) - return kPopularPeripheral_OnePlusBudsZ_2_Name; - - if (model_id == kPopularPeripheral_PixelBuds_ModelId) - return kPopularPeripheral_PixelBuds_Name; - - if (model_id == kPopularPeripheral_PixelBudsASeries_ModelId) - return kPopularPeripheral_PixelBudsASeries_Name; - if (model_id == kPopularPeripheral_PixelBudsASeries_1_ModelId) - return kPopularPeripheral_PixelBudsASeries_1_Name; - if (model_id == kPopularPeripheral_PixelBudsASeries_2_ModelId) - return kPopularPeripheral_PixelBudsASeries_2_Name; - - if (model_id == kPopularPeripheral_PixelBudsPro_ModelId) - return kPopularPeripheral_PixelBudsPro_Name; - if (model_id == kPopularPeripheral_PixelBudsPro_1_ModelId) - return kPopularPeripheral_PixelBudsPro_1_Name; - if (model_id == kPopularPeripheral_PixelBudsPro_2_ModelId) - return kPopularPeripheral_PixelBudsPro_2_Name; - if (model_id == kPopularPeripheral_PixelBudsPro_3_ModelId) - return kPopularPeripheral_PixelBudsPro_3_Name; - if (model_id == kPopularPeripheral_PixelBudsPro_4_ModelId) - return kPopularPeripheral_PixelBudsPro_4_Name; - - if (model_id == kPopularPeripheral_RealMeBudsAir2_ModelId) - return kPopularPeripheral_RealMeBudsAir2_Name; - - if (model_id == kPopularPeripheral_SonyWF1000XM3_ModelId) - return kPopularPeripheral_SonyWF1000XM3_Name; - if (model_id == kPopularPeripheral_SonyWF1000XM3_1_ModelId) - return kPopularPeripheral_SonyWF1000XM3_1_Name; - if (model_id == kPopularPeripheral_SonyWF1000XM3_2_ModelId) - return kPopularPeripheral_SonyWF1000XM3_2_Name; - if (model_id == kPopularPeripheral_SonyWF1000XM3_3_ModelId) - return kPopularPeripheral_SonyWF1000XM3_3_Name; - if (model_id == kPopularPeripheral_SonyWF1000XM3_4_ModelId) - return kPopularPeripheral_SonyWF1000XM3_4_Name; - if (model_id == kPopularPeripheral_SonyWF1000XM3_5_ModelId) - return kPopularPeripheral_SonyWF1000XM3_5_Name; - if (model_id == kPopularPeripheral_SonyWF1000XM3_6_ModelId) - return kPopularPeripheral_SonyWF1000XM3_6_Name; - if (model_id == kPopularPeripheral_SonyWF1000XM3_7_ModelId) - return kPopularPeripheral_SonyWF1000XM3_7_Name; - - if (model_id == kPopularPeripheral_NothingEar1_ModelId) - return kPopularPeripheral_NothingEar1_Name; - if (model_id == kPopularPeripheral_NothingEar1_1_ModelId) - return kPopularPeripheral_NothingEar1_1_Name; - - if (model_id == kPopularPeripheral_RealMeBudsAir2Neo_ModelId) - return kPopularPeripheral_RealMeBudsAir2Neo_Name; - - if (model_id == kPopularPeripheral_JBLTUNE130NCTWS_ModelId) - return kPopularPeripheral_JBLTUNE130NCTWS_Name; - if (model_id == kPopularPeripheral_JBLTUNE130NCTWS_1_ModelId) - return kPopularPeripheral_JBLTUNE130NCTWS_1_Name; - if (model_id == kPopularPeripheral_JBLTUNE130NCTWS_2_ModelId) - return kPopularPeripheral_JBLTUNE130NCTWS_2_Name; - if (model_id == kPopularPeripheral_JBLTUNE130NCTWS_3_ModelId) - return kPopularPeripheral_JBLTUNE130NCTWS_3_Name; - - if (model_id == kPopularPeripheral_SonyWH1000XM3_ModelId) - return kPopularPeripheral_SonyWH1000XM3_Name; - if (model_id == kPopularPeripheral_SonyWH1000XM3_1_ModelId) - return kPopularPeripheral_SonyWH1000XM3_1_Name; - - if (model_id == kPopularPeripheral_JBLLIVEPROTWS_ModelId) + if (model_id == kPopularPeripheral_JBLLIVEPROTWS_ModelId) { return kPopularPeripheral_JBLLIVEPROTWS_Name; - if (model_id == kPopularPeripheral_JBLLIVEPROTWS_1_ModelId) + } + if (model_id == kPopularPeripheral_JBLLIVEPROTWS_1_ModelId) { return kPopularPeripheral_JBLLIVEPROTWS_1_Name; - if (model_id == kPopularPeripheral_JBLLIVEPROTWS_2_ModelId) + } + if (model_id == kPopularPeripheral_JBLLIVEPROTWS_2_ModelId) { return kPopularPeripheral_JBLLIVEPROTWS_2_Name; - if (model_id == kPopularPeripheral_JBLLIVEPROTWS_3_ModelId) + } + if (model_id == kPopularPeripheral_JBLLIVEPROTWS_3_ModelId) { return kPopularPeripheral_JBLLIVEPROTWS_3_Name; - if (model_id == kPopularPeripheral_JBLLIVEPROTWS_4_ModelId) + } + if (model_id == kPopularPeripheral_JBLLIVEPROTWS_4_ModelId) { return kPopularPeripheral_JBLLIVEPROTWS_4_Name; - if (model_id == kPopularPeripheral_JBLLIVEPROTWS_5_ModelId) + } + if (model_id == kPopularPeripheral_JBLLIVEPROTWS_5_ModelId) { return kPopularPeripheral_JBLLIVEPROTWS_5_Name; - if (model_id == kPopularPeripheral_JBLLIVEPROTWS_6_ModelId) + } + if (model_id == kPopularPeripheral_JBLLIVEPROTWS_6_ModelId) { return kPopularPeripheral_JBLLIVEPROTWS_6_Name; + } - if (model_id == kPopularPeripheral_RealMeBudsAirPro_ModelId) + if (model_id == kPopularPeripheral_JBLLIVE300TWS_ModelId) { + return kPopularPeripheral_JBLLIVE300TWS_Name; + } + if (model_id == kPopularPeripheral_JBLLIVE300TWS_1_ModelId) { + return kPopularPeripheral_JBLLIVE300TWS_1_Name; + } + if (model_id == kPopularPeripheral_JBLLIVE300TWS_2_ModelId) { + return kPopularPeripheral_JBLLIVE300TWS_2_Name; + } + + if (model_id == kPopularPeripheral_JBLLIVE400BT_ModelId) { + return kPopularPeripheral_JBLLIVE400BT_Name; + } + if (model_id == kPopularPeripheral_JBLLIVE400BT_1_ModelId) { + return kPopularPeripheral_JBLLIVE400BT_1_Name; + } + if (model_id == kPopularPeripheral_JBLLIVE400BT_2_ModelId) { + return kPopularPeripheral_JBLLIVE400BT_2_Name; + } + if (model_id == kPopularPeripheral_JBLLIVE400BT_3_ModelId) { + return kPopularPeripheral_JBLLIVE400BT_3_Name; + } + if (model_id == kPopularPeripheral_JBLLIVE400BT_4_ModelId) { + return kPopularPeripheral_JBLLIVE400BT_4_Name; + } + + if (model_id == kPopularPeripheral_JBLTUNE125TWS_ModelId) { + return kPopularPeripheral_JBLTUNE125TWS_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE125TWS_1_ModelId) { + return kPopularPeripheral_JBLTUNE125TWS_1_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE125TWS_2_ModelId) { + return kPopularPeripheral_JBLTUNE125TWS_2_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE125TWS_3_ModelId) { + return kPopularPeripheral_JBLTUNE125TWS_3_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE125TWS_4_ModelId) { + return kPopularPeripheral_JBLTUNE125TWS_4_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE125TWS_5_ModelId) { + return kPopularPeripheral_JBLTUNE125TWS_5_Name; + } + + if (model_id == kPopularPeripheral_JBLTUNE130NCTWS_ModelId) { + return kPopularPeripheral_JBLTUNE130NCTWS_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE130NCTWS_1_ModelId) { + return kPopularPeripheral_JBLTUNE130NCTWS_1_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE130NCTWS_2_ModelId) { + return kPopularPeripheral_JBLTUNE130NCTWS_2_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE130NCTWS_3_ModelId) { + return kPopularPeripheral_JBLTUNE130NCTWS_3_Name; + } + + if (model_id == kPopularPeripheral_JBLTUNE225TWS_ModelId) { + return kPopularPeripheral_JBLTUNE225TWS_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE225TWS_1_ModelId) { + return kPopularPeripheral_JBLTUNE225TWS_1_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE225TWS_2_ModelId) { + return kPopularPeripheral_JBLTUNE225TWS_2_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE225TWS_3_ModelId) { + return kPopularPeripheral_JBLTUNE225TWS_3_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE225TWS_4_ModelId) { + return kPopularPeripheral_JBLTUNE225TWS_4_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE225TWS_5_ModelId) { + return kPopularPeripheral_JBLTUNE225TWS_5_Name; + } + + if (model_id == kPopularPeripheral_JBLTUNE230NCTWS_ModelId) { + return kPopularPeripheral_JBLTUNE230NCTWS_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE230NCTWS_1_ModelId) { + return kPopularPeripheral_JBLTUNE230NCTWS_1_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE230NCTWS_2_ModelId) { + return kPopularPeripheral_JBLTUNE230NCTWS_2_Name; + } + if (model_id == kPopularPeripheral_JBLTUNE230NCTWS_3_ModelId) { + return kPopularPeripheral_JBLTUNE230NCTWS_3_Name; + } + + if (model_id == kPopularPeripheral_NothingEar1_ModelId) { + return kPopularPeripheral_NothingEar1_Name; + } + if (model_id == kPopularPeripheral_NothingEar1_1_ModelId) { + return kPopularPeripheral_NothingEar1_1_Name; + } + + if (model_id == kPopularPeripheral_OnePlusBuds_ModelId) { + return kPopularPeripheral_OnePlusBuds_Name; + } + if (model_id == kPopularPeripheral_OnePlusBuds_1_ModelId) { + return kPopularPeripheral_OnePlusBuds_1_Name; + } + if (model_id == kPopularPeripheral_OnePlusBuds_2_ModelId) { + return kPopularPeripheral_OnePlusBuds_2_Name; + } + + if (model_id == kPopularPeripheral_OnePlusBudsZ_ModelId) { + return kPopularPeripheral_OnePlusBudsZ_Name; + } + if (model_id == kPopularPeripheral_OnePlusBudsZ_1_ModelId) { + return kPopularPeripheral_OnePlusBudsZ_1_Name; + } + if (model_id == kPopularPeripheral_OnePlusBudsZ_2_ModelId) { + return kPopularPeripheral_OnePlusBudsZ_2_Name; + } + + if (model_id == kPopularPeripheral_PixelBuds_ModelId) { + return kPopularPeripheral_PixelBuds_Name; + } + + if (model_id == kPopularPeripheral_PixelBudsASeries_ModelId) { + return kPopularPeripheral_PixelBudsASeries_Name; + } + if (model_id == kPopularPeripheral_PixelBudsASeries_1_ModelId) { + return kPopularPeripheral_PixelBudsASeries_1_Name; + } + if (model_id == kPopularPeripheral_PixelBudsASeries_2_ModelId) { + return kPopularPeripheral_PixelBudsASeries_2_Name; + } + + if (model_id == kPopularPeripheral_PixelBudsPro_ModelId) { + return kPopularPeripheral_PixelBudsPro_Name; + } + if (model_id == kPopularPeripheral_PixelBudsPro_1_ModelId) { + return kPopularPeripheral_PixelBudsPro_1_Name; + } + if (model_id == kPopularPeripheral_PixelBudsPro_2_ModelId) { + return kPopularPeripheral_PixelBudsPro_2_Name; + } + if (model_id == kPopularPeripheral_PixelBudsPro_3_ModelId) { + return kPopularPeripheral_PixelBudsPro_3_Name; + } + if (model_id == kPopularPeripheral_PixelBudsPro_4_ModelId) { + return kPopularPeripheral_PixelBudsPro_4_Name; + } + + if (model_id == kPopularPeripheral_RealMeBudsAir2_ModelId) { + return kPopularPeripheral_RealMeBudsAir2_Name; + } + + if (model_id == kPopularPeripheral_RealMeBudsAir2Neo_ModelId) { + return kPopularPeripheral_RealMeBudsAir2Neo_Name; + } + + if (model_id == kPopularPeripheral_RealMeBudsAirPro_ModelId) { return kPopularPeripheral_RealMeBudsAirPro_Name; - if (model_id == kPopularPeripheral_RealMeBudsAirPro_1_ModelId) + } + if (model_id == kPopularPeripheral_RealMeBudsAirPro_1_ModelId) { return kPopularPeripheral_RealMeBudsAirPro_1_Name; - if (model_id == kPopularPeripheral_RealMeBudsAirPro_2_ModelId) + } + if (model_id == kPopularPeripheral_RealMeBudsAirPro_2_ModelId) { return kPopularPeripheral_RealMeBudsAirPro_2_Name; + } - if (model_id == kPopularPeripheral_SRSXB33_ModelId) + if (model_id == kPopularPeripheral_RealMeBudsQ2TWS_ModelId) { + return kPopularPeripheral_RealMeBudsQ2TWS_Name; + } + + if (model_id == kPopularPeripheral_RealMeTechLifeBudsT100_ModelId) { + return kPopularPeripheral_RealMeTechLifeBudsT100_Name; + } + if (model_id == kPopularPeripheral_RealMeTechLifeBudsT100_1_ModelId) { + return kPopularPeripheral_RealMeTechLifeBudsT100_1_Name; + } + if (model_id == kPopularPeripheral_RealMeTechLifeBudsT100_2_ModelId) { + return kPopularPeripheral_RealMeTechLifeBudsT100_2_Name; + } + + if (model_id == kPopularPeripheral_SonyWF1000XM3_ModelId) { + return kPopularPeripheral_SonyWF1000XM3_Name; + } + if (model_id == kPopularPeripheral_SonyWF1000XM3_1_ModelId) { + return kPopularPeripheral_SonyWF1000XM3_1_Name; + } + if (model_id == kPopularPeripheral_SonyWF1000XM3_2_ModelId) { + return kPopularPeripheral_SonyWF1000XM3_2_Name; + } + if (model_id == kPopularPeripheral_SonyWF1000XM3_3_ModelId) { + return kPopularPeripheral_SonyWF1000XM3_3_Name; + } + if (model_id == kPopularPeripheral_SonyWF1000XM3_4_ModelId) { + return kPopularPeripheral_SonyWF1000XM3_4_Name; + } + if (model_id == kPopularPeripheral_SonyWF1000XM3_5_ModelId) { + return kPopularPeripheral_SonyWF1000XM3_5_Name; + } + if (model_id == kPopularPeripheral_SonyWF1000XM3_6_ModelId) { + return kPopularPeripheral_SonyWF1000XM3_6_Name; + } + if (model_id == kPopularPeripheral_SonyWF1000XM3_7_ModelId) { + return kPopularPeripheral_SonyWF1000XM3_7_Name; + } + + if (model_id == kPopularPeripheral_SonyWH1000XM3_ModelId) { + return kPopularPeripheral_SonyWH1000XM3_Name; + } + if (model_id == kPopularPeripheral_SonyWH1000XM3_1_ModelId) { + return kPopularPeripheral_SonyWH1000XM3_1_Name; + } + + if (model_id == kPopularPeripheral_SRSXB33_ModelId) { return kPopularPeripheral_SRSXB33_Name; - if (model_id == kPopularPeripheral_SRSXB33_1_ModelId) + } + if (model_id == kPopularPeripheral_SRSXB33_1_ModelId) { return kPopularPeripheral_SRSXB33_1_Name; - if (model_id == kPopularPeripheral_SRSXB33_2_ModelId) + } + if (model_id == kPopularPeripheral_SRSXB33_2_ModelId) { return kPopularPeripheral_SRSXB33_2_Name; - if (model_id == kPopularPeripheral_SRSXB33_3_ModelId) + } + if (model_id == kPopularPeripheral_SRSXB33_3_ModelId) { return kPopularPeripheral_SRSXB33_3_Name; + } - if (model_id == kPopularPeripheral_SRSXB23_ModelId) + if (model_id == kPopularPeripheral_SRSXB23_ModelId) { return kPopularPeripheral_SRSXB23_Name; - if (model_id == kPopularPeripheral_SRSXB23_1_ModelId) + } + if (model_id == kPopularPeripheral_SRSXB23_1_ModelId) { return kPopularPeripheral_SRSXB23_1_Name; - if (model_id == kPopularPeripheral_SRSXB23_2_ModelId) + } + if (model_id == kPopularPeripheral_SRSXB23_2_ModelId) { return kPopularPeripheral_SRSXB23_2_Name; - if (model_id == kPopularPeripheral_SRSXB23_3_ModelId) + } + if (model_id == kPopularPeripheral_SRSXB23_3_ModelId) { return kPopularPeripheral_SRSXB23_3_Name; - if (model_id == kPopularPeripheral_SRSXB23_4_ModelId) + } + if (model_id == kPopularPeripheral_SRSXB23_4_ModelId) { return kPopularPeripheral_SRSXB23_4_Name; + } + + if (model_id == kPopularPeripheral_SRSXB13_ModelId) { + return kPopularPeripheral_SRSXB13_Name; + } + if (model_id == kPopularPeripheral_SRSXB13_1_ModelId) { + return kPopularPeripheral_SRSXB13_1_Name; + } + if (model_id == kPopularPeripheral_SRSXB13_2_ModelId) { + return kPopularPeripheral_SRSXB13_2_Name; + } + if (model_id == kPopularPeripheral_SRSXB13_3_ModelId) { + return kPopularPeripheral_SRSXB13_3_Name; + } + if (model_id == kPopularPeripheral_SRSXB13_4_ModelId) { + return kPopularPeripheral_SRSXB13_4_Name; + } + if (model_id == kPopularPeripheral_SRSXB13_5_ModelId) { + return kPopularPeripheral_SRSXB13_5_Name; + } return kPopularPeripheral_Other_Name; }
diff --git a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.cc b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.cc index 746312d..2c74212a 100644 --- a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.cc +++ b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.cc
@@ -79,7 +79,6 @@ std::unique_ptr<FastPairPairer> FastPairPairerImpl::Factory::Create( scoped_refptr<device::BluetoothAdapter> adapter, scoped_refptr<Device> device, - base::OnceCallback<void(scoped_refptr<Device>)> handshake_complete_callback, base::OnceCallback<void(scoped_refptr<Device>)> paired_callback, base::OnceCallback<void(scoped_refptr<Device>, PairFailure)> pair_failed_callback, @@ -89,16 +88,14 @@ pairing_procedure_complete) { if (g_test_factory_) { return g_test_factory_->CreateInstance( - std::move(adapter), std::move(device), - std::move(handshake_complete_callback), std::move(paired_callback), + std::move(adapter), std::move(device), std::move(paired_callback), std::move(pair_failed_callback), std::move(account_key_failure_callback), std::move(pairing_procedure_complete)); } return base::WrapUnique(new FastPairPairerImpl( - std::move(adapter), std::move(device), - std::move(handshake_complete_callback), std::move(paired_callback), + std::move(adapter), std::move(device), std::move(paired_callback), std::move(pair_failed_callback), std::move(account_key_failure_callback), std::move(pairing_procedure_complete))); } @@ -114,7 +111,6 @@ FastPairPairerImpl::FastPairPairerImpl( scoped_refptr<device::BluetoothAdapter> adapter, scoped_refptr<Device> device, - base::OnceCallback<void(scoped_refptr<Device>)> handshake_complete_callback, base::OnceCallback<void(scoped_refptr<Device>)> paired_callback, base::OnceCallback<void(scoped_refptr<Device>, PairFailure)> pair_failed_callback, @@ -123,7 +119,6 @@ base::OnceCallback<void(scoped_refptr<Device>)> pairing_procedure_complete) : adapter_(std::move(adapter)), device_(std::move(device)), - handshake_complete_callback_(std::move(handshake_complete_callback)), paired_callback_(std::move(paired_callback)), pair_failed_callback_(std::move(pair_failed_callback)), account_key_failure_callback_(std::move(account_key_failure_callback)), @@ -149,66 +144,9 @@ fast_pair_handshake_ = FastPairHandshakeLookup::GetInstance()->Get(device_); - if (fast_pair_handshake_) { - // Handle cases where we are retrying pair after a non-handshake related - // error occurs. - if (fast_pair_handshake_->completed_successfully()) { - QP_LOG(VERBOSE) << __func__ - << ": Reusing handshake for retried pair attempt."; - RecordFastPairInitializePairingProcessEvent( - *device_, FastPairInitializePairingProcessEvent::kHandshakeReused); - OnHandshakeComplete(device_, /*failure=*/absl::nullopt); - return; - } - - // Handles cases where we are retrying pair after an error occurred when - // creating the handshake. - QP_LOG(VERBOSE) << __func__ - << ": Clearing failed handshake for retried pair attempt."; - FastPairHandshakeLookup::GetInstance()->Erase(device_); - fast_pair_handshake_ = nullptr; - } - - QP_LOG(VERBOSE) << __func__ << ": Creating new handshake for pair attempt."; - FastPairHandshakeLookup::GetInstance()->Create( - adapter_, device_, - base::BindOnce(&FastPairPairerImpl::OnHandshakeComplete, - weak_ptr_factory_.GetWeakPtr())); -} - -void FastPairPairerImpl::OnHandshakeComplete( - scoped_refptr<Device> device, - absl::optional<PairFailure> failure) { - // TODO(b/259429032) : Log with `RecordInitializationRetriesBeforeSuccess` - // the number of handshake retries occurred before success. Log with - // `FastPairInitializePairingProcessEvent` if we have exhausted the retries. - - if (failure.has_value()) { - QP_LOG(WARNING) << __func__ << ": Handshake failed with " << device - << " because: " << failure.value(); - RecordInitializationFailureReason(*device, failure.value()); - std::move(pair_failed_callback_).Run(device_, failure.value()); - // |this| may be destroyed after this line. - return; - } - - // During handshake, the device address can be set to null. - if (!device_->classic_address()) { - QP_LOG(WARNING) << __func__ << ": Device lost during handshake."; - RecordInitializationFailureReason(*device, PairFailure::kPairingDeviceLost); - std::move(pair_failed_callback_) - .Run(device_, PairFailure::kPairingDeviceLost); - // |this| may be destroyed after this line. - return; - } - - fast_pair_handshake_ = FastPairHandshakeLookup::GetInstance()->Get(device_); - DCHECK(fast_pair_handshake_); DCHECK(fast_pair_handshake_->completed_successfully()); - std::move(handshake_complete_callback_).Run(device_); - fast_pair_gatt_service_client_ = fast_pair_handshake_->fast_pair_gatt_service_client(); @@ -225,7 +163,6 @@ void FastPairPairerImpl::StartPairing() { RecordProtocolPairingStep(FastPairProtocolPairingSteps::kPairingStarted, *device_); - std::string device_address = device_->classic_address().value(); device::BluetoothDevice* bt_device = adapter_->GetDevice(device_address); switch (device_->protocol) {
diff --git a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.h b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.h index 6bbc0f4..9db4d0ed 100644 --- a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.h +++ b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.h
@@ -44,8 +44,6 @@ static std::unique_ptr<FastPairPairer> Create( scoped_refptr<device::BluetoothAdapter> adapter, scoped_refptr<Device> device, - base::OnceCallback<void(scoped_refptr<Device>)> - handshake_complete_callback, base::OnceCallback<void(scoped_refptr<Device>)> paired_callback, base::OnceCallback<void(scoped_refptr<Device>, PairFailure)> pair_failed_callback, @@ -62,8 +60,6 @@ virtual std::unique_ptr<FastPairPairer> CreateInstance( scoped_refptr<device::BluetoothAdapter> adapter, scoped_refptr<Device> device, - base::OnceCallback<void(scoped_refptr<Device>)> - handshake_complete_callback, base::OnceCallback<void(scoped_refptr<Device>)> paired_callback, base::OnceCallback<void(scoped_refptr<Device>, PairFailure)> pair_failed_callback, @@ -79,8 +75,6 @@ FastPairPairerImpl( scoped_refptr<device::BluetoothAdapter> adapter, scoped_refptr<Device> device, - base::OnceCallback<void(scoped_refptr<Device>)> - handshake_complete_callback, base::OnceCallback<void(scoped_refptr<Device>)> paired_callback, base::OnceCallback<void(scoped_refptr<Device>, PairFailure)> pair_failed_callback, @@ -176,7 +170,6 @@ scoped_refptr<Device> device_; FastPairGattServiceClient* fast_pair_gatt_service_client_; std::string pairing_device_address_; - base::OnceCallback<void(scoped_refptr<Device>)> handshake_complete_callback_; base::OnceCallback<void(scoped_refptr<Device>)> paired_callback_; base::OnceCallback<void(scoped_refptr<Device>, PairFailure)> pair_failed_callback_;
diff --git a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl_unittest.cc b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl_unittest.cc index 5804b6ee..441c426b 100644 --- a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl_unittest.cc +++ b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl_unittest.cc
@@ -110,16 +110,6 @@ "FastPair.SubsequentPairing.Pairing"; constexpr char kInitializePairingProcessInitial[] = "FastPair.InitialPairing.Initialization"; -constexpr char kInitializePairingProcessSubsequent[] = - "FastPair.SubsequentPairing.Initialization"; -constexpr char kInitializePairingProcessRetroactive[] = - "FastPair.RetroactivePairing.Initialization"; -constexpr char kInitializePairingProcessFailureReasonInitial[] = - "FastPair.InitialPairing.Initialization.FailureReason"; -constexpr char kInitializePairingProcessFailureReasonSubsequent[] = - "FastPair.SubsequentPairing.Initialization.FailureReason"; -constexpr char kInitializePairingProcessFailureReasonRetroactive[] = - "FastPair.RetroactivePairing.Initialization.FailureReason"; class FakeBluetoothAdapter : public testing::NiceMock<device::MockBluetoothAdapter> { @@ -296,8 +286,6 @@ AshTestBase::SetUp(); FastPairGattServiceClientImpl::Factory::SetFactoryForTesting( &fast_pair_gatt_service_factory_); - FastPairHandshakeLookup::SetCreateFunctionForTesting(base::BindRepeating( - &FastPairPairerImplTest::CreateHandshake, base::Unretained(this))); adapter_ = base::MakeRefCounted<FakeBluetoothAdapter>(); @@ -339,7 +327,16 @@ FastPairHandshakeLookup::GetInstance()->Erase(device_); } - std::unique_ptr<FastPairHandshake> CreateHandshake( + void AddConnectedHandshake() { + FastPairHandshakeLookup::SetCreateFunctionForTesting( + base::BindRepeating(&FastPairPairerImplTest::CreateConnectedHandshake, + base::Unretained(this))); + + FastPairHandshakeLookup::GetInstance()->Create(adapter_, device_, + base::DoNothing()); + } + + std::unique_ptr<FastPairHandshake> CreateConnectedHandshake( scoped_refptr<Device> device, FastPairHandshake::OnCompleteCallback callback) { // This is the only place where data_encryptor_unique_ is used. We assume @@ -453,8 +450,7 @@ // This is done on-demand to enable setting up mock expectations first. void CreatePairer() { pairer_ = std::make_unique<FastPairPairerImpl>( - adapter_, device_, handshake_complete_callback_.Get(), - paired_callback_.Get(), + adapter_, device_, paired_callback_.Get(), base::BindOnce(&FastPairPairerImplTest::PairFailedCallback, weak_ptr_factory_.GetWeakPtr()), account_key_failure_callback_.Get(), pairing_procedure_complete_.Get()); @@ -462,8 +458,7 @@ void CreatePairerAsFactory() { pairer_ = FastPairPairerImpl::Factory::Create( - adapter_, device_, handshake_complete_callback_.Get(), - paired_callback_.Get(), + adapter_, device_, paired_callback_.Get(), base::BindOnce(&FastPairPairerImplTest::PairFailedCallback, weak_ptr_factory_.GetWeakPtr()), account_key_failure_callback_.Get(), pairing_procedure_complete_.Get()); @@ -472,25 +467,24 @@ void CreateDevice(DeviceFastPairVersion version) { CreateMockDevice(version, /*protocol=*/Protocol::kFastPairInitial); + + // Adds a connected handshake that has completed successfully in + // 'FastPairHandshakeLookup' for the mock device. + SetGetDeviceNullptr(); + AddConnectedHandshake(); + fake_fast_pair_handshake_->InvokeCallback(); CreatePairer(); if (version == DeviceFastPairVersion::kHigherThanV1) { SetPublicKey(); - // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. - SetGetDeviceNullptr(); - fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); } } void PerformAndCheckSuccessfulPairingCallbacks() { RunWritePasskeyCallback(kResponseBytes); - base::RunLoop().RunUntilIdle(); EXPECT_CALL(pairing_procedure_complete_, Run).Times(1); EXPECT_EQ(DeviceFastPairVersion::kHigherThanV1, device_->version().value()); adapter_->DevicePairedChanged(fake_bluetooth_device_ptr_, true); @@ -523,84 +517,37 @@ base::WeakPtrFactory<FastPairPairerImplTest> weak_ptr_factory_{this}; }; -TEST_F(FastPairPairerImplTest, NoPairingIfHandshakeFailed_Initial) { - Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); - CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, - /*protocol=*/Protocol::kFastPairInitial); - CreatePairer(); - fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(GetPairFailure(), PairFailure::kCreateGattConnection); - EXPECT_EQ(histogram_tester_.GetBucketCount( - kInitializePairingProcessFailureReasonInitial, - PairFailure::kCreateGattConnection), - 1); -} - -TEST_F(FastPairPairerImplTest, NoPairingIfHandshakeFailed_Subsequent) { - Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); - CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, - /*protocol=*/Protocol::kFastPairSubsequent); - CreatePairer(); - fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(GetPairFailure(), PairFailure::kCreateGattConnection); - EXPECT_EQ(histogram_tester_.GetBucketCount( - kInitializePairingProcessFailureReasonSubsequent, - PairFailure::kCreateGattConnection), - 1); -} - -TEST_F(FastPairPairerImplTest, NoPairingIfHandshakeFailed_Retroactive) { - Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); - CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, - /*protocol=*/Protocol::kFastPairRetroactive); - CreatePairer(); - fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(GetPairFailure(), PairFailure::kCreateGattConnection); - EXPECT_EQ(histogram_tester_.GetBucketCount( - kInitializePairingProcessFailureReasonRetroactive, - PairFailure::kCreateGattConnection), - 1); -} - TEST_F(FastPairPairerImplTest, NoCallbackIsInvokedOnGattSuccess_Initial) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); } TEST_F(FastPairPairerImplTest, NoCallbackIsInvokedOnGattSuccess_Retroactive) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairRetroactive); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); } TEST_F(FastPairPairerImplTest, NoCallbackIsInvokedOnGattSuccess_Subsequent) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); } @@ -608,16 +555,15 @@ // most other tests in this file. TEST_F(FastPairPairerImplTest, PairByDeviceFailure_Initial) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kPairDeviceResult, 0); histogram_tester().ExpectTotalCount(kPairDeviceErrorReason, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); SetPairFailure(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), PairFailure::kPairingConnect); histogram_tester().ExpectTotalCount(kPairDeviceResult, 1); histogram_tester().ExpectTotalCount(kPairDeviceErrorReason, 1); @@ -625,17 +571,16 @@ TEST_F(FastPairPairerImplTest, PairByDeviceFailure_Initial_CancelsPairing) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); SetPairFailure(); + AddConnectedHandshake(); + fake_fast_pair_handshake_->InvokeCallback(); CreatePairer(); // Mock that the device was paired unsuccessfully. EXPECT_CALL(*fake_bluetooth_device_ptr_, IsPaired()).WillOnce(Return(false)); - fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); // Check to make sure that, when pairing fails, we call CancelPairing. EXPECT_CALL(*fake_bluetooth_device_ptr_, CancelPairing()).Times(1); @@ -643,16 +588,15 @@ TEST_F(FastPairPairerImplTest, PairByDeviceFailure_Subsequent) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kPairDeviceResult, 0); histogram_tester().ExpectTotalCount(kPairDeviceErrorReason, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); SetPairFailure(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), PairFailure::kPairingConnect); histogram_tester().ExpectTotalCount(kPairDeviceResult, 1); histogram_tester().ExpectTotalCount(kPairDeviceErrorReason, 1); @@ -662,13 +606,12 @@ TEST_F(FastPairPairerImplTest, PairByDeviceSuccess_Initial) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); ExpectStepMetrics(kProtocolPairingStepInitial, {FastPairProtocolPairingSteps::kPairingStarted, @@ -678,17 +621,17 @@ TEST_F(FastPairPairerImplTest, PairByDeviceSuccess_Initial_AlreadyClassicPaired) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); - CreatePairer(); + AddConnectedHandshake(); + fake_fast_pair_handshake_->InvokeCallback(); + // Mock that the device is already paired. EXPECT_CALL(*fake_bluetooth_device_ptr_, IsBonded()).WillOnce(Return(true)); - EXPECT_CALL(paired_callback_, Run); - fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); + EXPECT_EQ(GetPairFailure(), absl::nullopt); // For an already classic paired device, we skip right to Account Key writing. @@ -703,11 +646,12 @@ TEST_F(FastPairPairerImplTest, PairByDeviceSuccess_Initial_AlreadyFastPaired) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); - CreatePairer(); + AddConnectedHandshake(); + fake_fast_pair_handshake_->InvokeCallback(); + // Mock that the device is already fast paired (and saved to Footprints). fast_pair_repository_.SaveMacAddressToAccount(kBluetoothCanonicalizedAddress); EXPECT_CALL(*fake_bluetooth_device_ptr_, IsBonded()).WillOnce(Return(true)); @@ -715,8 +659,8 @@ // For an already fast paired device, we skip the Account Key writing. EXPECT_CALL(paired_callback_, Run); EXPECT_CALL(pairing_procedure_complete_, Run); - fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); + EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_EQ( histogram_tester().GetBucketCount( @@ -732,17 +676,17 @@ TEST_F(FastPairPairerImplTest, PairByDeviceSuccess_Subsequent_AlreadyClassicPaired) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); - CreatePairer(); + AddConnectedHandshake(); + fake_fast_pair_handshake_->InvokeCallback(); + // Mock that the device is already paired. EXPECT_CALL(*fake_bluetooth_device_ptr_, IsBonded()).WillOnce(Return(true)); EXPECT_CALL(paired_callback_, Run); - fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); ExpectStepMetrics(kProtocolPairingStepSubsequent, {FastPairProtocolPairingSteps::kPairingStarted, @@ -753,11 +697,12 @@ TEST_F(FastPairPairerImplTest, PairByDeviceSuccess_Subsequent_AlreadyFastPaired) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); - CreatePairer(); + AddConnectedHandshake(); + fake_fast_pair_handshake_->InvokeCallback(); + // Mock that the device is already fast paired (and saved to Footprints). fast_pair_repository_.SaveMacAddressToAccount(kBluetoothCanonicalizedAddress); EXPECT_CALL(*fake_bluetooth_device_ptr_, IsBonded()).WillOnce(Return(true)); @@ -765,8 +710,7 @@ // For an already fast paired device, we skip the Account Key writing. EXPECT_CALL(paired_callback_, Run); EXPECT_CALL(pairing_procedure_complete_, Run); - fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); ExpectStepMetrics(kProtocolPairingStepSubsequent, {FastPairProtocolPairingSteps::kPairingStarted, @@ -776,13 +720,12 @@ TEST_F(FastPairPairerImplTest, PairByDeviceSuccess_Subsequent) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); ExpectStepMetrics(kProtocolPairingStepSubsequent, {FastPairProtocolPairingSteps::kPairingStarted, @@ -791,18 +734,19 @@ TEST_F(FastPairPairerImplTest, ConnectFailure_Initial) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kConnectDeviceResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); SetConnectFailure(); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), PairFailure::kAddressConnect); histogram_tester().ExpectTotalCount(kConnectDeviceResult, 1); @@ -812,18 +756,19 @@ TEST_F(FastPairPairerImplTest, ConnectFailure_Subsequent) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kConnectDeviceResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); SetConnectFailure(); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), PairFailure::kAddressConnect); histogram_tester().ExpectTotalCount(kConnectDeviceResult, 1); ExpectStepMetrics(kProtocolPairingStepSubsequent, @@ -832,7 +777,6 @@ TEST_F(FastPairPairerImplTest, ConnectSuccess_Initial) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kWritePasskeyCharacteristicResultMetric, 0); @@ -840,12 +784,14 @@ kWritePasskeyCharacteristicPairFailureMetric, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); histogram_tester().ExpectTotalCount(kWritePasskeyCharacteristicResultMetric, 0); @@ -858,7 +804,6 @@ TEST_F(FastPairPairerImplTest, ConnectSuccess_Subsequent) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kWritePasskeyCharacteristicResultMetric, 0); @@ -866,12 +811,14 @@ kWritePasskeyCharacteristicPairFailureMetric, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); histogram_tester().ExpectTotalCount(kWritePasskeyCharacteristicResultMetric, 0); @@ -884,7 +831,6 @@ TEST_F(FastPairPairerImplTest, ParseDecryptedPasskeyFailure_Initial) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kWritePasskeyCharacteristicResultMetric, 0); @@ -894,15 +840,16 @@ histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback({}, PairFailure::kPasskeyPairingCharacteristicWrite); EXPECT_EQ(GetPairFailure(), PairFailure::kPasskeyPairingCharacteristicWrite); @@ -921,7 +868,6 @@ TEST_F(FastPairPairerImplTest, ParseDecryptedPasskeyFailure_Subsequent) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kWritePasskeyCharacteristicResultMetric, 0); @@ -931,15 +877,16 @@ histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback({}, PairFailure::kPasskeyPairingCharacteristicWrite); EXPECT_EQ(GetPairFailure(), PairFailure::kPasskeyPairingCharacteristicWrite); histogram_tester().ExpectTotalCount(kWritePasskeyCharacteristicResultMetric, @@ -958,23 +905,23 @@ TEST_F(FastPairPairerImplTest, ParseDecryptedPasskeyIncorrectMessageType_Initial_SeekersPasskey) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); SetDecryptPasskeyForIncorrectMessageType( FastPairMessageType::kSeekersPasskey); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kIncorrectPasskeyResponseType); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); @@ -990,23 +937,23 @@ FastPairPairerImplTest, ParseDecryptedPasskeyIncorrectMessageType_Initial_KeyBasedPairingRequest) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); SetDecryptPasskeyForIncorrectMessageType( FastPairMessageType::kKeyBasedPairingRequest); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kIncorrectPasskeyResponseType); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); @@ -1022,23 +969,23 @@ FastPairPairerImplTest, ParseDecryptedPasskeyIncorrectMessageType_Initial_KeyBasedPairingResponse) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); SetDecryptPasskeyForIncorrectMessageType( FastPairMessageType::kKeyBasedPairingResponse); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kIncorrectPasskeyResponseType); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); @@ -1052,22 +999,22 @@ TEST_F(FastPairPairerImplTest, ParseDecryptedPasskeyNoPasskey) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); SetDecryptPasskeyForNoPasskey(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kPasskeyDecryptFailure); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); @@ -1082,23 +1029,23 @@ TEST_F(FastPairPairerImplTest, ParseDecryptedPasskeyIncorrectMessageType_Subsequent) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); SetDecryptPasskeyForIncorrectMessageType( FastPairMessageType::kKeyBasedPairingResponse); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kIncorrectPasskeyResponseType); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); @@ -1112,22 +1059,22 @@ TEST_F(FastPairPairerImplTest, ParseDecryptedPasskeyMismatch_Initial) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); SetDecryptPasskeyForPasskeyMismatch(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kPasskeyMismatch); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); @@ -1142,22 +1089,22 @@ TEST_F(FastPairPairerImplTest, ParseDecryptedPasskeyMismatch_Subsequent) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); SetDecryptPasskeyForPasskeyMismatch(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kPasskeyMismatch); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); @@ -1172,18 +1119,19 @@ TEST_F(FastPairPairerImplTest, PairedDeviceLost_Initial) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); SetDecryptPasskeyForSuccess(); @@ -1191,7 +1139,6 @@ // Passkey exchange. SetGetDeviceNullptr(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kPairingDeviceLost); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 1); @@ -1207,18 +1154,19 @@ TEST_F(FastPairPairerImplTest, PairedDeviceLost_Subsequent) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); SetDecryptPasskeyForSuccess(); @@ -1226,7 +1174,6 @@ // Passkey exchange. SetGetDeviceNullptr(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kPairingDeviceLost); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 1); @@ -1242,24 +1189,24 @@ TEST_F(FastPairPairerImplTest, PairSuccess_Initial) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kConfirmPasskeyAskTime, 0); histogram_tester().ExpectTotalCount(kConfirmPasskeyConfirmTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_TRUE(IsDevicePaired()); @@ -1281,16 +1228,17 @@ TEST_F(FastPairPairerImplTest, BleDeviceLostMidPair) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); SetDecryptPasskeyForSuccess(); @@ -1298,7 +1246,6 @@ EraseHandshake(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); EXPECT_EQ(PairFailure::kBleDeviceLostMidPair, GetPairFailure()); EXPECT_FALSE(IsDevicePaired()); @@ -1306,24 +1253,24 @@ TEST_F(FastPairPairerImplTest, PairSuccess_Initial_FactoryCreate) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kConfirmPasskeyAskTime, 0); histogram_tester().ExpectTotalCount(kConfirmPasskeyConfirmTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairerAsFactory(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairerAsFactory(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_TRUE(IsDevicePaired()); @@ -1344,7 +1291,6 @@ /*disabled_features=*/{}); fast_pair_repository_.SetOptInStatus( nearby::fastpair::OptInStatus::STATUS_OPTED_IN); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kConfirmPasskeyAskTime, 0); histogram_tester().ExpectTotalCount(kConfirmPasskeyConfirmTime, 0); @@ -1352,17 +1298,18 @@ histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); EXPECT_CALL(pairing_procedure_complete_, Run); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); @@ -1392,7 +1339,6 @@ features::kFastPairSavedDevicesStrictOptIn}); fast_pair_repository_.SetOptInStatus( nearby::fastpair::OptInStatus::STATUS_OPTED_OUT); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kConfirmPasskeyAskTime, 0); histogram_tester().ExpectTotalCount(kConfirmPasskeyConfirmTime, 0); @@ -1400,17 +1346,18 @@ histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); EXPECT_CALL(pairing_procedure_complete_, Run); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); @@ -1431,7 +1378,6 @@ /*disabled_features=*/{features::kFastPairSavedDevicesStrictOptIn}); fast_pair_repository_.SetOptInStatus( nearby::fastpair::OptInStatus::STATUS_OPTED_OUT); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount(kConfirmPasskeyAskTime, 0); histogram_tester().ExpectTotalCount(kConfirmPasskeyConfirmTime, 0); @@ -1439,17 +1385,18 @@ histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); EXPECT_CALL(pairing_procedure_complete_, Run); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); @@ -1471,29 +1418,30 @@ /*disabled_features=*/{}); fast_pair_repository_.SetOptInStatus( nearby::fastpair::OptInStatus::STATUS_OPTED_IN); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); SetPublicKey(); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_TRUE(IsDevicePaired()); EXPECT_CALL(pairing_procedure_complete_, Run); EXPECT_EQ(DeviceFastPairVersion::kHigherThanV1, device_->version().value()); + // Ensure that the account key is not written to the peripheral until the // peripheral is successfully paired. EXPECT_FALSE(IsAccountKeySavedToFootprints()); @@ -1513,29 +1461,30 @@ features::kFastPairSavedDevicesStrictOptIn}); fast_pair_repository_.SetOptInStatus( nearby::fastpair::OptInStatus::STATUS_OPTED_OUT); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); SetPublicKey(); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_TRUE(IsDevicePaired()); EXPECT_CALL(pairing_procedure_complete_, Run); EXPECT_EQ(DeviceFastPairVersion::kHigherThanV1, device_->version().value()); + // Ensure that the account key is not written to the peripheral until the // peripheral is successfully paired. EXPECT_FALSE(IsAccountKeySavedToFootprints()); @@ -1554,29 +1503,30 @@ /*disabled_features=*/{features::kFastPairSavedDevicesStrictOptIn}); fast_pair_repository_.SetOptInStatus( nearby::fastpair::OptInStatus::STATUS_OPTED_OUT); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); SetPublicKey(); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_TRUE(IsDevicePaired()); EXPECT_CALL(pairing_procedure_complete_, Run); EXPECT_EQ(DeviceFastPairVersion::kHigherThanV1, device_->version().value()); + // Ensure that the account key is not written to the peripheral until the // peripheral is successfully paired. EXPECT_FALSE(IsAccountKeySavedToFootprints()); @@ -1589,24 +1539,24 @@ TEST_F(FastPairPairerImplTest, WriteAccountKey_Initial_GuestLoggedIn) { Login(user_manager::UserType::USER_TYPE_GUEST); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); SetPublicKey(); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); EXPECT_CALL(pairing_procedure_complete_, Run); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); @@ -1623,24 +1573,24 @@ TEST_F(FastPairPairerImplTest, WriteAccountKey_Initial_KioskAppLoggedIn) { Login(user_manager::UserType::USER_TYPE_KIOSK_APP); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); SetPublicKey(); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); EXPECT_CALL(pairing_procedure_complete_, Run); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); @@ -1657,17 +1607,18 @@ CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); SetPublicKey(); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_TRUE(IsDevicePaired()); @@ -1684,17 +1635,18 @@ CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); SetPublicKey(); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_TRUE(IsDevicePaired()); @@ -1713,26 +1665,27 @@ /*disabled_features=*/{}); fast_pair_repository_.SetOptInStatus( nearby::fastpair::OptInStatus::STATUS_OPTED_IN); - base::RunLoop().RunUntilIdle(); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); EXPECT_CALL(pairing_procedure_complete_, Run); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_TRUE(IsDevicePaired()); EXPECT_EQ(DeviceFastPairVersion::kHigherThanV1, device_->version().value()); + // Ensure that the account key is not written to the peripheral until the // peripheral is successfully paired. EXPECT_FALSE(IsAccountKeySavedToFootprints()); @@ -1754,26 +1707,27 @@ /*enabled_features=*/{}, /*disabled_features=*/{features::kFastPairSavedDevices, features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); EXPECT_CALL(pairing_procedure_complete_, Run); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_TRUE(IsDevicePaired()); EXPECT_EQ(DeviceFastPairVersion::kHigherThanV1, device_->version().value()); + // Ensure that the account key is not written to the peripheral until the // peripheral is successfully paired. EXPECT_FALSE(IsAccountKeySavedToFootprints()); @@ -1794,26 +1748,27 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kFastPairSavedDevices}, /*disabled_features=*/{features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); EXPECT_CALL(pairing_procedure_complete_, Run); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_TRUE(IsDevicePaired()); EXPECT_EQ(DeviceFastPairVersion::kHigherThanV1, device_->version().value()); + // Ensure that the account key is not written to the peripheral until the // peripheral is successfully paired. EXPECT_FALSE(IsAccountKeySavedToFootprints()); @@ -1835,18 +1790,19 @@ /*enabled_features=*/{features::kFastPairSavedDevices, features::kFastPairSavedDevicesStrictOptIn}, /*disabled_features=*/{}); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairRetroactive); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_CALL(pairing_procedure_complete_, Run); RunWriteAccountKeyCallback(); histogram_tester().ExpectTotalCount( @@ -1862,18 +1818,19 @@ /*enabled_features=*/{}, /*disabled_features=*/{features::kFastPairSavedDevices, features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairRetroactive); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_CALL(pairing_procedure_complete_, Run); RunWriteAccountKeyCallback(); histogram_tester().ExpectTotalCount( @@ -1888,18 +1845,19 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kFastPairSavedDevices}, /*disabled_features=*/{features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairRetroactive); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_CALL(pairing_procedure_complete_, Run); RunWriteAccountKeyCallback(); histogram_tester().ExpectTotalCount( @@ -1915,7 +1873,6 @@ /*enabled_features=*/{}, /*disabled_features=*/{features::kFastPairSavedDevices, features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); @@ -1941,7 +1898,6 @@ /*enabled_features=*/{}, /*disabled_features=*/{features::kFastPairSavedDevices, features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); @@ -1967,7 +1923,6 @@ /*enabled_features=*/{}, /*disabled_features=*/{features::kFastPairSavedDevices, features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); @@ -1993,7 +1948,6 @@ /*enabled_features=*/{}, /*disabled_features=*/{features::kFastPairSavedDevices, features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); @@ -2019,7 +1973,6 @@ /*enabled_features=*/{}, /*disabled_features=*/{features::kFastPairSavedDevices, features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); @@ -2045,7 +1998,6 @@ /*enabled_features=*/{}, /*disabled_features=*/{features::kFastPairSavedDevices, features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); @@ -2071,7 +2023,6 @@ /*enabled_features=*/{}, /*disabled_features=*/{features::kFastPairSavedDevices, features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); @@ -2097,7 +2048,6 @@ /*disabled_features=*/{features::kFastPairSavedDevices, features::kFastPairSavedDevicesStrictOptIn}); Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); @@ -2122,7 +2072,6 @@ /*enabled_features=*/{}, /*disabled_features=*/{features::kFastPairSavedDevices, features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); CreateDevice(DeviceFastPairVersion::kHigherThanV1); RunWritePasskeyCallback(kResponseBytes); @@ -2142,7 +2091,6 @@ TEST_F(FastPairPairerImplTest, FastPairVersionOne_DevicePaired) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); CreateDevice(DeviceFastPairVersion::kV1); EXPECT_EQ(GetSystemTrayClient()->show_bluetooth_pairing_dialog_count(), 1); @@ -2158,7 +2106,6 @@ TEST_F(FastPairPairerImplTest, FastPairVersionOne_DeviceUnpaired) { Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); CreateDevice(DeviceFastPairVersion::kV1); EXPECT_EQ(GetSystemTrayClient()->show_bluetooth_pairing_dialog_count(), 1); @@ -2181,7 +2128,6 @@ /*enabled_features=*/{features::kFastPairSavedDevices, features::kFastPairSavedDevicesStrictOptIn}, /*disabled_features=*/{}); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); @@ -2192,7 +2138,6 @@ histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); RunWritePasskeyCallback(kResponseBytes); - base::RunLoop().RunUntilIdle(); } TEST_F(FastPairPairerImplTest, WriteAccount_OptedIn_FlagDisabled) { @@ -2204,13 +2149,11 @@ /*enabled_features=*/{}, /*disabled_features=*/{features::kFastPairSavedDevices, features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); CreateDevice(DeviceFastPairVersion::kHigherThanV1); RunWritePasskeyCallback(kResponseBytes); - base::RunLoop().RunUntilIdle(); EXPECT_CALL(pairing_procedure_complete_, Run).Times(1); EXPECT_EQ(DeviceFastPairVersion::kHigherThanV1, device_->version().value()); adapter_->DevicePairedChanged(fake_bluetooth_device_ptr_, true); @@ -2235,7 +2178,6 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kFastPairSavedDevices}, /*disabled_features=*/{features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); @@ -2262,7 +2204,6 @@ /*enabled_features=*/{}, /*disabled_features=*/{features::kFastPairSavedDevices, features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); @@ -2288,7 +2229,6 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kFastPairSavedDevices}, /*disabled_features=*/{features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); @@ -2315,7 +2255,6 @@ /*disabled_features=*/{}); fast_pair_repository_.SetOptInStatus( nearby::fastpair::OptInStatus::STATUS_UNKNOWN); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); @@ -2327,7 +2266,6 @@ histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); RunWritePasskeyCallback(kResponseBytes); - base::RunLoop().RunUntilIdle(); } TEST_F(FastPairPairerImplTest, WriteAccount_StatusUnknown_FlagDisabled) { @@ -2339,7 +2277,6 @@ features::kFastPairSavedDevicesStrictOptIn}); fast_pair_repository_.SetOptInStatus( nearby::fastpair::OptInStatus::STATUS_UNKNOWN); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); @@ -2365,26 +2302,25 @@ /*disabled_features=*/{features::kFastPairSavedDevicesStrictOptIn}); fast_pair_repository_.SetOptInStatus( nearby::fastpair::OptInStatus::STATUS_UNKNOWN); - base::RunLoop().RunUntilIdle(); histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); SetPublicKey(); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); - base::RunLoop().RunUntilIdle(); EXPECT_CALL(pairing_procedure_complete_, Run).Times(1); EXPECT_EQ(DeviceFastPairVersion::kHigherThanV1, device_->version().value()); adapter_->DevicePairedChanged(fake_bluetooth_device_ptr_, true); @@ -2417,7 +2353,6 @@ histogram_tester().ExpectBucketCount( kSavedDeviceUpdateOptInStatusInitialResult, /*success=*/false, 0); - base::RunLoop().RunUntilIdle(); // Pair the device via Initial Pairing protocol. histogram_tester().ExpectTotalCount( @@ -2425,17 +2360,18 @@ CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); SetPublicKey(); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_TRUE(IsDevicePaired()); @@ -2472,23 +2408,24 @@ feature_list.InitWithFeatures( /*enabled_features=*/{features::kFastPairSavedDevices}, /*disabled_features=*/{features::kFastPairSavedDevicesStrictOptIn}); - base::RunLoop().RunUntilIdle(); // Retroactive pair histogram_tester().ExpectTotalCount( kWriteAccountKeyCharacteristicResultMetric, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairRetroactive); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_CALL(pairing_procedure_complete_, Run); RunWriteAccountKeyCallback(); - // Expect that the user is now opted in + // Expect that the user is now opted in. EXPECT_EQ(nearby::fastpair::OptInStatus::STATUS_OPTED_IN, fast_pair_repository_.GetOptInStatus()); histogram_tester().ExpectBucketCount( @@ -2519,17 +2456,18 @@ // Subsequent pair CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); - base::RunLoop().RunUntilIdle(); + CreatePairer(); EXPECT_EQ(GetPairFailure(), absl::nullopt); EXPECT_CALL(paired_callback_, Run); SetDecryptPasskeyForSuccess(); NotifyConfirmPasskey(); - base::RunLoop().RunUntilIdle(); EXPECT_CALL(pairing_procedure_complete_, Run); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), absl::nullopt); @@ -2537,7 +2475,7 @@ EXPECT_EQ(DeviceFastPairVersion::kHigherThanV1, device_->version().value()); adapter_->DevicePairedChanged(fake_bluetooth_device_ptr_, true); - // Expect that the user is opted in now + // Expect that the user is opted in now. EXPECT_EQ(nearby::fastpair::OptInStatus::STATUS_OPTED_IN, fast_pair_repository_.GetOptInStatus()); histogram_tester().ExpectBucketCount( @@ -2557,9 +2495,10 @@ CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); - CreatePairer(); - SetPairTimeout(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); + SetPairTimeout(); + CreatePairer(); task_environment()->FastForwardBy(kCreateBondTimeout); EXPECT_EQ(GetPairFailure(), PairFailure::kCreateBondTimeout); } @@ -2578,9 +2517,10 @@ // This call mocks the scenario in which |adapter_| does not know |device_|'s // address. SetGetDeviceNullptr(); - CreatePairer(); - SetConnectDeviceTimeout(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); + SetConnectDeviceTimeout(); + CreatePairer(); task_environment()->FastForwardBy(kCreateBondTimeout); EXPECT_EQ(GetPairFailure(), PairFailure::kCreateBondTimeout); } @@ -2595,11 +2535,14 @@ /*disabled_features=*/{features::kFastPairSavedDevicesStrictOptIn}); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairRetroactive); + // When pairing starts, if the classic address can't be resolved to - // a device then we pair via address. + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); + CreatePairer(); EXPECT_CALL(pairing_procedure_complete_, Run); RunWriteAccountKeyCallback(); histogram_tester().ExpectTotalCount( @@ -2624,8 +2567,9 @@ CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); + CreatePairer(); task_environment()->FastForwardBy(kConfirmPasskeyTimeout); EXPECT_EQ(GetPairFailure(), PairFailure::kConfirmPasskeyTimeout); } @@ -2637,68 +2581,16 @@ CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); - // This call mocks the scenario in which |adapter_| does not know |device_|'s - // address. + // When pairing starts, if the classic address can't be resolved to + // a device then we pair via address. 'SetGetDeviceNullptr' tells the adapter + // to return null when queried for the device to mock this behavior. SetGetDeviceNullptr(); - CreatePairer(); + AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); + CreatePairer(); task_environment()->FastForwardBy(kConfirmPasskeyTimeout); EXPECT_EQ(GetPairFailure(), PairFailure::kConfirmPasskeyTimeout); } -TEST_F(FastPairPairerImplTest, HandshakeReused_Initial) { - Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); - - CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, - /*protocol=*/Protocol::kFastPairInitial); - - // Simulate Handshake already created before attempt - SetReuseHandshake(); - SetGetDeviceNullptr(); - CreatePairer(); - - EXPECT_EQ(histogram_tester().GetBucketCount( - kInitializePairingProcessInitial, - FastPairInitializePairingProcessEvent::kHandshakeReused), - 1); -} - -TEST_F(FastPairPairerImplTest, HandshakeReused_Subsequent) { - Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); - - CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, - /*protocol=*/Protocol::kFastPairSubsequent); - - // Simulate Handshake already created before attempt - SetReuseHandshake(); - SetGetDeviceNullptr(); - CreatePairer(); - - EXPECT_EQ(histogram_tester().GetBucketCount( - kInitializePairingProcessSubsequent, - FastPairInitializePairingProcessEvent::kHandshakeReused), - 1); -} - -TEST_F(FastPairPairerImplTest, HandshakeReused_Retroactive) { - Login(user_manager::UserType::USER_TYPE_REGULAR); - base::RunLoop().RunUntilIdle(); - - CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, - /*protocol=*/Protocol::kFastPairRetroactive); - - // Simulate Handshake already created before attempt - SetReuseHandshake(); - SetGetDeviceNullptr(); - CreatePairer(); - - EXPECT_EQ(histogram_tester().GetBucketCount( - kInitializePairingProcessRetroactive, - FastPairInitializePairingProcessEvent::kHandshakeReused), - 1); -} - } // namespace quick_pair } // namespace ash
diff --git a/ash/quick_pair/pairing/pairer_broker_impl.cc b/ash/quick_pair/pairing/pairer_broker_impl.cc index 50f698e..b22802f 100644 --- a/ash/quick_pair/pairing/pairer_broker_impl.cc +++ b/ash/quick_pair/pairing/pairer_broker_impl.cc
@@ -12,6 +12,7 @@ #include "ash/quick_pair/common/logging.h" #include "ash/quick_pair/common/pair_failure.h" #include "ash/quick_pair/common/protocol.h" +#include "ash/quick_pair/fast_pair_handshake/fast_pair_handshake.h" #include "ash/quick_pair/fast_pair_handshake/fast_pair_handshake_lookup.h" #include "ash/quick_pair/pairing/fast_pair/fast_pair_pairer.h" #include "ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.h" @@ -62,6 +63,8 @@ case Protocol::kFastPairInitial: case Protocol::kFastPairRetroactive: case Protocol::kFastPairSubsequent: + did_handshake_previously_complete_successfully_map_.insert_or_assign( + device->ble_address, false); PairFastPairDevice(std::move(device)); break; } @@ -74,6 +77,8 @@ pair_failure_counts_.erase(device->ble_address); fast_pair_pairers_.erase(device->ble_address); FastPairHandshakeLookup::GetInstance()->Erase(device); + did_handshake_previously_complete_successfully_map_.insert_or_assign( + device->ble_address, false); } bool PairerBrokerImpl::IsPairing() { @@ -95,6 +100,88 @@ return; } + // If this is a v1 pairing, we don't have to make a handshake before bonding + // because we will pass off pairing to the classic Bluetooth pairing dialog in + // 'FastPairPairer', so skip straight to 'StartBondingAttempt'. + if (device->version().value() == DeviceFastPairVersion::kV1) { + StartBondingAttempt(device); + return; + } + + // Otherwise, try to create a handshake. + CreateHandshake(std::move(device)); +} + +void PairerBrokerImpl::CreateHandshake(scoped_refptr<Device> device) { + // TODO(b/259429032): Add 3 retries for this handshake. + auto* fast_pair_handshake = + FastPairHandshakeLookup::GetInstance()->Get(device); + if (fast_pair_handshake && fast_pair_handshake->completed_successfully()) { + QP_LOG(INFO) << __func__ + << ": Reusing existing handshake for pair attempt."; + RecordFastPairInitializePairingProcessEvent( + *device, FastPairInitializePairingProcessEvent::kHandshakeReused); + StartBondingAttempt(device); + return; + } + + QP_LOG(INFO) << __func__ << ": Creating new handshake for pair attempt."; + FastPairHandshakeLookup::GetInstance()->Create( + adapter_, device, + base::BindOnce(&PairerBrokerImpl::OnHandshakeComplete, + weak_pointer_factory_.GetWeakPtr())); +} + +void PairerBrokerImpl::OnHandshakeComplete( + scoped_refptr<Device> device, + absl::optional<PairFailure> failure) { + if (failure.has_value()) { + QP_LOG(WARNING) << __func__ << ": Handshake failed with " << device + << " because: " << failure.value(); + OnHandshakeFailure(device, failure.value()); + return; + } + + // During handshake, the device address can be set to null. + if (!device->classic_address()) { + QP_LOG(WARNING) << __func__ << ": Device lost during handshake."; + OnHandshakeFailure(device, PairFailure::kPairingDeviceLost); + return; + } + + if (!did_handshake_previously_complete_successfully_map_[device + ->ble_address]) { + // Currently the only observer is |QuickPairMetricsLogger|. To keep metrics + // consistent we should only call the observer the first time a handshake + // completes. If another observer is added, this logic should be + // reevaluated. + int num_observers = 0; + for (auto& observer : observers_) { + num_observers++; + observer.OnHandshakeComplete(device); + } + DCHECK(num_observers == 1); + did_handshake_previously_complete_successfully_map_.insert_or_assign( + device->ble_address, true); + } + + StartBondingAttempt(device); +} + +void PairerBrokerImpl::OnHandshakeFailure(scoped_refptr<Device> device, + PairFailure failure) { + QP_LOG(INFO) << __func__ + << ": Handshake failed to be created. Notifying observers."; + RecordInitializationFailureReason(*device, failure); + for (auto& observer : observers_) { + observer.OnPairFailure(device, failure); + } + + FastPairHandshakeLookup::GetInstance()->Erase(device); + return; +} + +void PairerBrokerImpl::StartBondingAttempt(scoped_refptr<Device> device) { if (!base::Contains(pair_failure_counts_, device->ble_address)) pair_failure_counts_[device->ble_address] = 0; @@ -107,11 +194,9 @@ DCHECK(adapter_); fast_pair_pairers_[device->ble_address] = FastPairPairerImpl::Factory::Create( adapter_, device, - base::BindOnce(&PairerBrokerImpl::OnFastPairHandshakeComplete, + base::BindOnce(&PairerBrokerImpl::OnFastPairDeviceBonded, weak_pointer_factory_.GetWeakPtr()), - base::BindOnce(&PairerBrokerImpl::OnFastPairDevicePaired, - weak_pointer_factory_.GetWeakPtr()), - base::BindOnce(&PairerBrokerImpl::OnFastPairPairingFailure, + base::BindOnce(&PairerBrokerImpl::OnFastPairBondingFailure, weak_pointer_factory_.GetWeakPtr()), base::BindOnce(&PairerBrokerImpl::OnAccountKeyFailure, weak_pointer_factory_.GetWeakPtr()), @@ -119,15 +204,7 @@ weak_pointer_factory_.GetWeakPtr())); } -void PairerBrokerImpl::OnFastPairHandshakeComplete( - scoped_refptr<Device> device) { - QP_LOG(INFO) << __func__ << ": Device=" << device; - for (auto& observer : observers_) { - observer.OnHandshakeComplete(device); - } -} - -void PairerBrokerImpl::OnFastPairDevicePaired(scoped_refptr<Device> device) { +void PairerBrokerImpl::OnFastPairDeviceBonded(scoped_refptr<Device> device) { QP_LOG(INFO) << __func__ << ": Device=" << device; for (auto& observer : observers_) { @@ -139,7 +216,7 @@ pair_failure_counts_.erase(device->ble_address); } -void PairerBrokerImpl::OnFastPairPairingFailure(scoped_refptr<Device> device, +void PairerBrokerImpl::OnFastPairBondingFailure(scoped_refptr<Device> device, PairFailure failure) { ++pair_failure_counts_[device->ble_address]; QP_LOG(INFO) << __func__ << ": Device=" << device << ", Failure=" << failure
diff --git a/ash/quick_pair/pairing/pairer_broker_impl.h b/ash/quick_pair/pairing/pairer_broker_impl.h index f53644d..0a645117 100644 --- a/ash/quick_pair/pairing/pairer_broker_impl.h +++ b/ash/quick_pair/pairing/pairer_broker_impl.h
@@ -49,13 +49,17 @@ private: void PairFastPairDevice(scoped_refptr<Device> device); - void OnFastPairHandshakeComplete(scoped_refptr<Device> device); - void OnFastPairDevicePaired(scoped_refptr<Device> device); - void OnFastPairPairingFailure(scoped_refptr<Device> device, + void OnFastPairDeviceBonded(scoped_refptr<Device> device); + void OnFastPairBondingFailure(scoped_refptr<Device> device, PairFailure failure); void OnAccountKeyFailure(scoped_refptr<Device> device, AccountKeyFailure failure); void OnFastPairProcedureComplete(scoped_refptr<Device> device); + void CreateHandshake(scoped_refptr<Device> device); + void OnHandshakeComplete(scoped_refptr<Device> device, + absl::optional<PairFailure> failure); + void OnHandshakeFailure(scoped_refptr<Device> device, PairFailure failure); + void StartBondingAttempt(scoped_refptr<Device> device); // Internal method called by BluetoothAdapterFactory to provide the adapter // object. @@ -63,9 +67,13 @@ void EraseHandshakeAndFromPairers(scoped_refptr<Device> device); + // The key for all the following maps is a device BLE address. base::flat_map<std::string, std::unique_ptr<FastPairPairer>> fast_pair_pairers_; base::flat_map<std::string, int> pair_failure_counts_; + base::flat_map<std::string, bool> + did_handshake_previously_complete_successfully_map_; + scoped_refptr<device::BluetoothAdapter> adapter_; std::unique_ptr<FastPairUnpairHandler> fast_pair_unpair_handler_; base::ObserverList<Observer> observers_;
diff --git a/ash/quick_pair/pairing/pairer_broker_impl_unittest.cc b/ash/quick_pair/pairing/pairer_broker_impl_unittest.cc index 28f496d8..849c4e7 100644 --- a/ash/quick_pair/pairing/pairer_broker_impl_unittest.cc +++ b/ash/quick_pair/pairing/pairer_broker_impl_unittest.cc
@@ -3,12 +3,19 @@ // found in the LICENSE file. #include "ash/quick_pair/pairing/pairer_broker_impl.h" - #include "ash/quick_pair/common/account_key_failure.h" #include "ash/quick_pair/common/device.h" #include "ash/quick_pair/common/fast_pair/fast_pair_metrics.h" #include "ash/quick_pair/common/pair_failure.h" #include "ash/quick_pair/common/protocol.h" +#include "ash/quick_pair/fast_pair_handshake/fake_fast_pair_data_encryptor.h" +#include "ash/quick_pair/fast_pair_handshake/fake_fast_pair_gatt_service_client.h" +#include "ash/quick_pair/fast_pair_handshake/fake_fast_pair_handshake.h" +#include "ash/quick_pair/fast_pair_handshake/fast_pair_data_encryptor.h" +#include "ash/quick_pair/fast_pair_handshake/fast_pair_data_encryptor_impl.h" +#include "ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client.h" +#include "ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_impl.h" +#include "ash/quick_pair/fast_pair_handshake/fast_pair_handshake_lookup.h" #include "ash/quick_pair/feature_status_tracker/fake_bluetooth_adapter.h" #include "ash/quick_pair/pairing/fast_pair/fast_pair_pairer.h" #include "ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.h" @@ -40,6 +47,12 @@ "FastPair.SubsequentPairing.Initialization"; constexpr char kInitializePairingProcessRetroactive[] = "FastPair.RetroactivePairing.Initialization"; +constexpr char kInitializePairingProcessFailureReasonInitial[] = + "FastPair.InitialPairing.Initialization.FailureReason"; +constexpr char kInitializePairingProcessFailureReasonSubsequent[] = + "FastPair.SubsequentPairing.Initialization.FailureReason"; +constexpr char kInitializePairingProcessFailureReasonRetroactive[] = + "FastPair.RetroactivePairing.Initialization.FailureReason"; constexpr char kProtocolPairingStepInitial[] = "FastPair.InitialPairing.Pairing"; @@ -52,8 +65,6 @@ scoped_refptr<device::BluetoothAdapter> adapter, scoped_refptr<ash::quick_pair::Device> device, base::OnceCallback<void(scoped_refptr<ash::quick_pair::Device>)> - handshake_complete_callback, - base::OnceCallback<void(scoped_refptr<ash::quick_pair::Device>)> paired_callback, base::OnceCallback<void(scoped_refptr<ash::quick_pair::Device>, ash::quick_pair::PairFailure)> @@ -65,7 +76,6 @@ pairing_procedure_complete) : adapter_(adapter), device_(device), - handshake_complete_callback_(std::move(handshake_complete_callback)), paired_callback_(std::move(paired_callback)), pair_failed_callback_(std::move(pair_failed_callback)), account_key_failure_callback_(std::move(account_key_failure_callback)), @@ -73,11 +83,6 @@ ~FakeFastPairPairer() override = default; - void TriggerHandshakeCompleteCallback() { - EXPECT_TRUE(handshake_complete_callback_); - std::move(handshake_complete_callback_).Run(device_); - } - void TriggerPairedCallback() { EXPECT_TRUE(paired_callback_); std::move(paired_callback_).Run(device_); @@ -103,8 +108,6 @@ scoped_refptr<device::BluetoothAdapter> adapter_; scoped_refptr<ash::quick_pair::Device> device_; base::OnceCallback<void(scoped_refptr<ash::quick_pair::Device>)> - handshake_complete_callback_; - base::OnceCallback<void(scoped_refptr<ash::quick_pair::Device>)> paired_callback_; base::OnceCallback<void(scoped_refptr<ash::quick_pair::Device>, ash::quick_pair::PairFailure)> @@ -123,8 +126,6 @@ scoped_refptr<device::BluetoothAdapter> adapter, scoped_refptr<ash::quick_pair::Device> device, base::OnceCallback<void(scoped_refptr<ash::quick_pair::Device>)> - handshake_complete_callback, - base::OnceCallback<void(scoped_refptr<ash::quick_pair::Device>)> paired_callback, base::OnceCallback<void(scoped_refptr<ash::quick_pair::Device>, ash::quick_pair::PairFailure)> @@ -135,8 +136,7 @@ base::OnceCallback<void(scoped_refptr<ash::quick_pair::Device>)> pairing_procedure_complete) override { auto fake_fast_pair_pairer = std::make_unique<FakeFastPairPairer>( - std::move(adapter), std::move(device), - std::move(handshake_complete_callback), std::move(paired_callback), + std::move(adapter), std::move(device), std::move(paired_callback), std::move(pair_failed_callback), std::move(account_key_failure_callback), std::move(pairing_procedure_complete)); @@ -152,6 +152,35 @@ FakeFastPairPairer* fake_fast_pair_pairer_ = nullptr; }; +class FakeFastPairGattServiceClientImplFactory + : public ash::quick_pair::FastPairGattServiceClientImpl::Factory { + public: + ~FakeFastPairGattServiceClientImplFactory() override = default; + + ash::quick_pair::FakeFastPairGattServiceClient* + fake_fast_pair_gatt_service_client() { + return fake_fast_pair_gatt_service_client_; + } + + private: + // FastPairGattServiceClientImpl::Factory: + std::unique_ptr<ash::quick_pair::FastPairGattServiceClient> CreateInstance( + device::BluetoothDevice* device, + scoped_refptr<device::BluetoothAdapter> adapter, + base::OnceCallback<void(absl::optional<ash::quick_pair::PairFailure>)> + on_initialized_callback) override { + auto fake_fast_pair_gatt_service_client = + std::make_unique<ash::quick_pair::FakeFastPairGattServiceClient>( + device, adapter, std::move(on_initialized_callback)); + fake_fast_pair_gatt_service_client_ = + fake_fast_pair_gatt_service_client.get(); + return fake_fast_pair_gatt_service_client; + } + + ash::quick_pair::FakeFastPairGattServiceClient* + fake_fast_pair_gatt_service_client_ = nullptr; +}; + } // namespace namespace ash { @@ -173,8 +202,60 @@ FastPairPairerImpl::Factory::SetFactoryForTesting( fast_pair_pairer_factory_.get()); + FastPairGattServiceClientImpl::Factory::SetFactoryForTesting( + &fast_pair_gatt_service_factory_); + FastPairHandshakeLookup::SetCreateFunctionForTesting(base::BindRepeating( + &PairerBrokerImplTest::CreateHandshake, base::Unretained(this))); + pairer_broker_ = std::make_unique<PairerBrokerImpl>(); pairer_broker_->AddObserver(this); + + gatt_service_client_ = FastPairGattServiceClientImpl::Factory::Create( + mock_bluetooth_device_ptr_, adapter_.get(), base::DoNothing()); + + // We have to pass in a unique_ptr when we create a Handshake, however + // we also want to be able to set fake responses on the encryptor. Thus + // we maintain 2 pointers. We won't touch fake_fast_pair_data_encryptor_ + // aside from CreateHandshake. + fake_fast_pair_data_encryptor_ = + std::make_unique<FakeFastPairDataEncryptor>(); + } + + void CreateMockDevice(DeviceFastPairVersion version, Protocol protocol) { + device_ = base::MakeRefCounted<Device>(kValidModelId, kTestDeviceAddress, + protocol); + device_->set_classic_address(kBluetoothCanonicalizedAddress); + + device_->set_version(version); + + // Add a matching mock device to the bluetooth adapter with the + // same address to mock the relationship between Device and + // device::BluetoothDevice. + mock_bluetooth_device_ = + std::make_unique<testing::NiceMock<device::MockBluetoothDevice>>( + adapter_.get(), /*bluetooth_class=*/0, kDeviceName, + kBluetoothCanonicalizedAddress, + /*initially_paired=*/true, /*connected=*/false); + mock_bluetooth_device_ptr_ = mock_bluetooth_device_.get(); + adapter_->AddMockDevice(std::move(mock_bluetooth_device_)); + } + + void EraseHandshake() { + FastPairHandshakeLookup::GetInstance()->Erase(device_); + } + + std::unique_ptr<FastPairHandshake> CreateHandshake( + scoped_refptr<Device> device, + FastPairHandshake::OnCompleteCallback callback) { + // This is the only place where fake_fast_pair_data_encryptor_ is used. We + // assume that CreateHandshake is only called once. + auto fake = std::make_unique<FakeFastPairHandshake>( + adapter_, device, std::move(callback), + std::move(fake_fast_pair_data_encryptor_), + std::move(gatt_service_client_)); + + fake_fast_pair_handshake_ = fake.get(); + return fake; } void TearDown() override { @@ -223,13 +304,23 @@ std::unique_ptr<FakeFastPairPairerFactory> fast_pair_pairer_factory_; std::unique_ptr<PairerBroker> pairer_broker_; + FakeFastPairHandshake* fake_fast_pair_handshake_ = nullptr; + std::unique_ptr<FastPairGattServiceClient> gatt_service_client_; + FakeFastPairGattServiceClientImplFactory fast_pair_gatt_service_factory_; + std::unique_ptr<FakeFastPairDataEncryptor> fake_fast_pair_data_encryptor_; + std::unique_ptr<testing::NiceMock<device::MockBluetoothDevice>> + mock_bluetooth_device_ = nullptr; + scoped_refptr<Device> device_; }; TEST_F(PairerBrokerImplTest, PairDevice_Initial) { histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 0); - auto device = base::MakeRefCounted<Device>(kValidModelId, kTestDeviceAddress, - Protocol::kFastPairInitial); - pairer_broker_->PairDevice(device); + + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairInitial); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); + EXPECT_TRUE(pairer_broker_->IsPairing()); fast_pair_pairer_factory_->fake_fast_pair_pairer()->TriggerPairedCallback(); @@ -245,17 +336,14 @@ TEST_F(PairerBrokerImplTest, PairDevice_Subsequent) { histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 0); - auto device = base::MakeRefCounted<Device>(kValidModelId, kTestDeviceAddress, - Protocol::kFastPairSubsequent); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairSubsequent); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); - pairer_broker_->PairDevice(device); EXPECT_TRUE(pairing_started_); EXPECT_TRUE(pairer_broker_->IsPairing()); - fast_pair_pairer_factory_->fake_fast_pair_pairer() - ->TriggerHandshakeCompleteCallback(); - EXPECT_TRUE(handshake_complete_); - fast_pair_pairer_factory_->fake_fast_pair_pairer()->TriggerPairedCallback(); EXPECT_TRUE(pairer_broker_->IsPairing()); @@ -270,10 +358,11 @@ TEST_F(PairerBrokerImplTest, PairDevice_Retroactive) { histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 0); - auto device = base::MakeRefCounted<Device>(kValidModelId, kTestDeviceAddress, - Protocol::kFastPairRetroactive); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairRetroactive); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); - pairer_broker_->PairDevice(device); EXPECT_TRUE(pairer_broker_->IsPairing()); fast_pair_pairer_factory_->fake_fast_pair_pairer()->TriggerPairedCallback(); @@ -289,11 +378,11 @@ TEST_F(PairerBrokerImplTest, AlreadyPairingDevice_Initial) { histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 0); - auto device = base::MakeRefCounted<Device>(kValidModelId, kTestDeviceAddress, - Protocol::kFastPairInitial); - - pairer_broker_->PairDevice(device); - pairer_broker_->PairDevice(device); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairInitial); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); + pairer_broker_->PairDevice(device_); EXPECT_TRUE(pairer_broker_->IsPairing()); fast_pair_pairer_factory_->fake_fast_pair_pairer()->TriggerPairedCallback(); @@ -309,12 +398,13 @@ TEST_F(PairerBrokerImplTest, AlreadyPairingDevice_Subsequent) { histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 0); - auto device = base::MakeRefCounted<Device>(kValidModelId, kTestDeviceAddress, - Protocol::kFastPairSubsequent); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairSubsequent); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); - pairer_broker_->PairDevice(device); - pairer_broker_->PairDevice(device); - base::RunLoop().RunUntilIdle(); + pairer_broker_->PairDevice(device_); + EXPECT_TRUE(pairer_broker_->IsPairing()); fast_pair_pairer_factory_->fake_fast_pair_pairer()->TriggerPairedCallback(); @@ -330,12 +420,13 @@ TEST_F(PairerBrokerImplTest, AlreadyPairingDevice_Retroactive) { histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 0); - auto device = base::MakeRefCounted<Device>(kValidModelId, kTestDeviceAddress, - Protocol::kFastPairRetroactive); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairRetroactive); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); - pairer_broker_->PairDevice(device); - pairer_broker_->PairDevice(device); - base::RunLoop().RunUntilIdle(); + pairer_broker_->PairDevice(device_); + EXPECT_TRUE(pairer_broker_->IsPairing()); fast_pair_pairer_factory_->fake_fast_pair_pairer()->TriggerPairedCallback(); @@ -352,22 +443,11 @@ TEST_F(PairerBrokerImplTest, PairAfterCancelPairing) { histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 0); - auto device = base::MakeRefCounted<Device>(kValidModelId, kTestDeviceAddress, - Protocol::kFastPairInitial); - device->set_classic_address(kBluetoothCanonicalizedAddress); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairInitial); - // Add a matching mock device to the bluetooth adapter with the - // same address to mock the relationship between Device and - // device::BluetoothDevice. - std::unique_ptr<testing::NiceMock<device::MockBluetoothDevice>> - mock_bluetooth_device_ = - std::make_unique<testing::NiceMock<device::MockBluetoothDevice>>( - adapter_.get(), 0, kDeviceName, kBluetoothCanonicalizedAddress, - true, false); - mock_bluetooth_device_ptr_ = mock_bluetooth_device_.get(); - adapter_->AddMockDevice(std::move(mock_bluetooth_device_)); - - pairer_broker_->PairDevice(device); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); EXPECT_TRUE(pairer_broker_->IsPairing()); EXPECT_CALL(*mock_bluetooth_device_ptr_, IsPaired()) .WillOnce(testing::Return(false)); @@ -390,10 +470,11 @@ TEST_F(PairerBrokerImplTest, PairDeviceFailureMax_Initial) { histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 0); - auto device = base::MakeRefCounted<Device>(kValidModelId, kTestDeviceAddress, - Protocol::kFastPairInitial); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairInitial); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); - pairer_broker_->PairDevice(device); EXPECT_TRUE(pairer_broker_->IsPairing()); fast_pair_pairer_factory_->fake_fast_pair_pairer() @@ -414,10 +495,11 @@ TEST_F(PairerBrokerImplTest, PairDeviceFailureMax_Subsequent) { histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 0); - auto device = base::MakeRefCounted<Device>(kValidModelId, kTestDeviceAddress, - Protocol::kFastPairSubsequent); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairSubsequent); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); - pairer_broker_->PairDevice(device); EXPECT_TRUE(pairer_broker_->IsPairing()); fast_pair_pairer_factory_->fake_fast_pair_pairer() ->TriggerPairFailureCallback( @@ -437,10 +519,11 @@ TEST_F(PairerBrokerImplTest, PairDeviceFailureMax_Retroactive) { histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 0); - auto device = base::MakeRefCounted<Device>(kValidModelId, kTestDeviceAddress, - Protocol::kFastPairRetroactive); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairRetroactive); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); - pairer_broker_->PairDevice(device); EXPECT_TRUE(pairer_broker_->IsPairing()); fast_pair_pairer_factory_->fake_fast_pair_pairer() ->TriggerPairFailureCallback( @@ -458,10 +541,11 @@ } TEST_F(PairerBrokerImplTest, AccountKeyFailure_Initial) { - auto device = base::MakeRefCounted<Device>(kValidModelId, kTestDeviceAddress, - Protocol::kFastPairInitial); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairInitial); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); - pairer_broker_->PairDevice(device); EXPECT_TRUE(pairer_broker_->IsPairing()); fast_pair_pairer_factory_->fake_fast_pair_pairer() @@ -473,10 +557,10 @@ } TEST_F(PairerBrokerImplTest, AccountKeyFailure_Subsequent) { - auto device = base::MakeRefCounted<Device>(kValidModelId, kTestDeviceAddress, - Protocol::kFastPairSubsequent); - - pairer_broker_->PairDevice(device); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairSubsequent); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); EXPECT_TRUE(pairer_broker_->IsPairing()); fast_pair_pairer_factory_->fake_fast_pair_pairer() @@ -488,10 +572,11 @@ } TEST_F(PairerBrokerImplTest, AccountKeyFailure_Retroactive) { - auto device = base::MakeRefCounted<Device>(kValidModelId, kTestDeviceAddress, - Protocol::kFastPairRetroactive); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairRetroactive); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); - pairer_broker_->PairDevice(device); EXPECT_TRUE(pairer_broker_->IsPairing()); fast_pair_pairer_factory_->fake_fast_pair_pairer() @@ -503,10 +588,11 @@ } TEST_F(PairerBrokerImplTest, StopPairing) { - auto device = base::MakeRefCounted<Device>(kValidModelId, kTestDeviceAddress, - Protocol::kFastPairInitial); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairInitial); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); - pairer_broker_->PairDevice(device); EXPECT_TRUE(pairer_broker_->IsPairing()); // Stop Pairing mid pair. @@ -519,5 +605,144 @@ EXPECT_FALSE(pairer_broker_->IsPairing()); } +TEST_F(PairerBrokerImplTest, ReuseHandshake_Initial) { + histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 0); + + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairInitial); + + // Create a Handshake that to mimic a Handshake already existing. + FastPairHandshakeLookup::GetInstance()->Create(adapter_, device_, + base::DoNothing()); + fake_fast_pair_handshake_->set_completed_successfully( + /*completed_successfully=*/true); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); + + EXPECT_TRUE(pairer_broker_->IsPairing()); + + fast_pair_pairer_factory_->fake_fast_pair_pairer()->TriggerPairedCallback(); + + EXPECT_TRUE(pairer_broker_->IsPairing()); + EXPECT_EQ(device_paired_count_, 1); + histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 1); + + fast_pair_pairer_factory_->fake_fast_pair_pairer() + ->TriggerPairingProcedureCompleteCallback(); + EXPECT_FALSE(pairer_broker_->IsPairing()); + EXPECT_EQ(histogram_tester_.GetBucketCount( + kInitializePairingProcessInitial, + FastPairInitializePairingProcessEvent::kHandshakeReused), + 1); +} + +TEST_F(PairerBrokerImplTest, ReuseHandshake_Subsequent) { + histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 0); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairSubsequent); + + // Create a Handshake that to mimic a Handshake already existing. + FastPairHandshakeLookup::GetInstance()->Create(adapter_, device_, + base::DoNothing()); + fake_fast_pair_handshake_->set_completed_successfully( + /*completed_successfully=*/true); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); + + EXPECT_TRUE(pairing_started_); + EXPECT_TRUE(pairer_broker_->IsPairing()); + + fast_pair_pairer_factory_->fake_fast_pair_pairer()->TriggerPairedCallback(); + + EXPECT_TRUE(pairer_broker_->IsPairing()); + EXPECT_EQ(device_paired_count_, 1); + histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 1); + + fast_pair_pairer_factory_->fake_fast_pair_pairer() + ->TriggerPairingProcedureCompleteCallback(); + EXPECT_FALSE(pairer_broker_->IsPairing()); + EXPECT_TRUE(device_pair_complete_); + + EXPECT_EQ(histogram_tester_.GetBucketCount( + kInitializePairingProcessSubsequent, + FastPairInitializePairingProcessEvent::kHandshakeReused), + 1); +} + +TEST_F(PairerBrokerImplTest, ReuseHandshake_Retroactive) { + histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 0); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairRetroactive); + + // Create a Handshake that to mimic a Handshake already existing. + FastPairHandshakeLookup::GetInstance()->Create(adapter_, device_, + base::DoNothing()); + fake_fast_pair_handshake_->set_completed_successfully( + /*completed_successfully=*/true); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(); + + EXPECT_TRUE(pairer_broker_->IsPairing()); + + fast_pair_pairer_factory_->fake_fast_pair_pairer()->TriggerPairedCallback(); + + EXPECT_TRUE(pairer_broker_->IsPairing()); + EXPECT_EQ(device_paired_count_, 1); + histogram_tester_.ExpectTotalCount(kFastPairRetryCountMetricName, 1); + + fast_pair_pairer_factory_->fake_fast_pair_pairer() + ->TriggerPairingProcedureCompleteCallback(); + EXPECT_FALSE(pairer_broker_->IsPairing()); + + EXPECT_EQ(histogram_tester_.GetBucketCount( + kInitializePairingProcessRetroactive, + FastPairInitializePairingProcessEvent::kHandshakeReused), + 1); +} + +TEST_F(PairerBrokerImplTest, NoPairingIfHandshakeFailed_Initial) { + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairInitial); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); + EXPECT_FALSE(pairer_broker_->IsPairing()); + + EXPECT_EQ(device_paired_count_, 0); + EXPECT_EQ(pair_failure_count_, 1); + EXPECT_EQ(histogram_tester_.GetBucketCount( + kInitializePairingProcessFailureReasonInitial, + PairFailure::kCreateGattConnection), + 1); +} + +TEST_F(PairerBrokerImplTest, NoPairingIfHandshakeFailed_Subsequent) { + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairSubsequent); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); + EXPECT_FALSE(pairer_broker_->IsPairing()); + + EXPECT_EQ(device_paired_count_, 0); + EXPECT_EQ(pair_failure_count_, 1); + EXPECT_EQ(histogram_tester_.GetBucketCount( + kInitializePairingProcessFailureReasonSubsequent, + PairFailure::kCreateGattConnection), + 1); +} + +TEST_F(PairerBrokerImplTest, NoPairingIfHandshakeFailed_Retroactive) { + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairRetroactive); + pairer_broker_->PairDevice(device_); + fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); + EXPECT_FALSE(pairer_broker_->IsPairing()); + + EXPECT_EQ(device_paired_count_, 0); + EXPECT_EQ(pair_failure_count_, 1); + EXPECT_EQ(histogram_tester_.GetBucketCount( + kInitializePairingProcessFailureReasonRetroactive, + PairFailure::kCreateGattConnection), + 1); +} } // namespace quick_pair } // namespace ash
diff --git a/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc b/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc index 5c53335..1f8ea07 100644 --- a/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc +++ b/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc
@@ -42,6 +42,16 @@ } } +// Enforce a 60 second timeout to discover a device for the retroactive pairing +// scenario to align with Android implementation and adhere to the Fast Pair +// spec where providers can only allow account keys to be written within the +// 60 seconds following classic Bluetooth pairing: +// https://developers.google.com/nearby/fast-pair/specifications/extensions/retroactiveacctkey#RetroactivelyWritingAccountKey +// The device is expected to enforce this requirement, however as mentioned +// above, to align with Android, ChromeOS will include consideration for the +// 60 seconds expected to retroactively write the account key. +constexpr base::TimeDelta kRetroactiveDevicePairingTimeout = base::Seconds(60); + } // namespace namespace ash { @@ -173,6 +183,7 @@ // |potential_retroactive_addresses_|. const std::string& classic_address = device->GetAddress(); potential_retroactive_addresses_.insert(classic_address); + AddDevicePairingInformation(classic_address); // In order to confirm that this device is a retroactive pairing, we need to // first check if it has already been saved to the user's account. If it has @@ -220,11 +231,29 @@ GetModelIdAndAddressFromMessageStream(device_address, message_stream); } +void RetroactivePairingDetectorImpl::AddDevicePairingInformation( + const std::string& device_address) { + QP_LOG(VERBOSE) << __func__; + DCHECK(device_pairing_information_.find(device_address) == + device_pairing_information_.end()); + RetroactivePairingInformation info; + device_pairing_information_[device_address] = info; + device_pairing_information_[device_address].expiry_timestamp = + base::Time::Now() + kRetroactiveDevicePairingTimeout; + + // Anytime |device_pairing_information_| is updated, parse list to remove + // expired devices. + RemoveExpiredDevicesFromStoredDeviceData(); +} + void RetroactivePairingDetectorImpl::GetModelIdAndAddressFromMessageStream( const std::string& device_address, MessageStream* message_stream) { DCHECK(message_stream); - DCHECK(device_pairing_information_.find(device_address) == + + // The device at |device_address| is expected to be added in + // `AddDevicePairingInformation` once discovered. + DCHECK(device_pairing_information_.find(device_address) != device_pairing_information_.end()); // If the MessageStream is immediately available and |DevicePairedChanged| @@ -234,9 +263,6 @@ if (!base::Contains(potential_retroactive_addresses_, device_address)) return; - RetroactivePairingInformation info; - device_pairing_information_[device_address] = info; - // Iterate over messages for ble address and model id, which is what we // need for retroactive pairing. for (auto& message : message_stream->messages()) { @@ -270,11 +296,33 @@ return; } + // At this point, we have both the model id and BLE address for the device, + // but we check if it has reached its expiry timeout. If so, we do not + // notify of the scenario being detected. `CheckAndRemoveIfDeviceExpired` + // will remove corresponding device information if it has expired. + if (CheckAndRemoveIfDeviceExpired(device_address)) { + return; + } + NotifyDeviceFound(device_pairing_information_[device_address].model_id, device_pairing_information_[device_address].ble_address, device_address); } +bool RetroactivePairingDetectorImpl::CheckAndRemoveIfDeviceExpired( + const std::string& device_address) { + if (base::Time::Now() >= + device_pairing_information_[device_address].expiry_timestamp) { + QP_LOG(VERBOSE) << __func__ << ": device at " << device_address + << " has exceeded the time allotted for detecting " + "retroactive scenario. Removing device information."; + RemoveDeviceInformation(device_address); + return true; + } + + return false; +} + void RetroactivePairingDetectorImpl::OnModelIdMessage( const std::string& device_address, const std::string& model_id) { @@ -295,15 +343,21 @@ void RetroactivePairingDetectorImpl::CheckPairingInformation( const std::string& device_address) { + // The device at |device_address| is expected to be added in + // `AddDevicePairingInformation` once discovered. DCHECK(device_pairing_information_.find(device_address) != device_pairing_information_.end()); // If the MessageStream is immediately available and |DevicePairedChanged| // fires before FastPair's |OnDevicePaired|, it might be possible for us to // find a false positive for a retroactive pairing scenario which we mitigate - // here. - if (!base::Contains(potential_retroactive_addresses_, device_address)) + // here. Also check if the device has expired for detecting scenario, if so + // do not continue. `CheckAndRemoveIfDeviceExpired` will remove device + // information if it has expired. + if (!base::Contains(potential_retroactive_addresses_, device_address) || + CheckAndRemoveIfDeviceExpired(device_address)) { return; + } if (device_pairing_information_[device_address].model_id.empty() || device_pairing_information_[device_address].ble_address.empty()) { @@ -413,6 +467,15 @@ void RetroactivePairingDetectorImpl::RemoveDeviceInformation( const std::string& device_address) { QP_LOG(VERBOSE) << __func__ << ": device = " << device_address; + RemoveDeviceInformationHelper(device_address); + + // Anytime |device_pairing_information_| is updated, parse list to remove + // expired devices. + RemoveExpiredDevicesFromStoredDeviceData(); +} + +void RetroactivePairingDetectorImpl::RemoveDeviceInformationHelper( + const std::string& device_address) { potential_retroactive_addresses_.erase(device_address); device_pairing_information_.erase(device_address); @@ -420,11 +483,29 @@ // before the MessageStreams are observed, connected, and/or added to our // list here if we get a false positive instance of a potential retroactive // pairing device. - if (!base::Contains(message_streams_, device_address)) - return; + if (base::Contains(message_streams_, device_address)) { + message_streams_[device_address]->RemoveObserver(this); + message_streams_.erase(device_address); + } +} - message_streams_[device_address]->RemoveObserver(this); - message_streams_.erase(device_address); +void RetroactivePairingDetectorImpl:: + RemoveExpiredDevicesFromStoredDeviceData() { + // If the RetroactivePairingDetector never receives the model id or + // BLE address from the MessageStream, it will not be removed in + // `CheckPairingInformation` if it has exceeded the allotted time for + // detecting the scenario (kDetectRetroactiveScenarioTimeout). We clean up + // these devices here. + for (auto it = device_pairing_information_.begin(); + it != device_pairing_information_.end(); ++it) { + if (base::Time::Now() >= it->second.expiry_timestamp) { + const std::string device_address = it->first; + QP_LOG(VERBOSE) << __func__ << "Removing device at " << device_address + << "that has exceeded the time allotted for detecting " + "retroactive scenario."; + RemoveDeviceInformationHelper(it->first); + } + } } void RetroactivePairingDetectorImpl::OnPairFailure(scoped_refptr<Device> device,
diff --git a/ash/quick_pair/pairing/retroactive_pairing_detector_impl.h b/ash/quick_pair/pairing/retroactive_pairing_detector_impl.h index 67b038a..6187d02 100644 --- a/ash/quick_pair/pairing/retroactive_pairing_detector_impl.h +++ b/ash/quick_pair/pairing/retroactive_pairing_detector_impl.h
@@ -24,6 +24,7 @@ #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/scoped_observation.h" +#include "base/time/time.h" #include "base/timer/timer.h" #include "device/bluetooth/bluetooth_adapter.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -70,6 +71,7 @@ struct RetroactivePairingInformation { std::string model_id; std::string ble_address; + base::Time expiry_timestamp; }; // SessionObserver: @@ -103,15 +105,29 @@ // object. void OnGetAdapter(scoped_refptr<device::BluetoothAdapter> adapter); - // Parses MessageStream messages for model id and ble address, and - // notifies observers if they exist. + // Parses MessageStream messages for model id and BLE address, and + // notifies observers if they exist within the |expiry_timeout| time period. void GetModelIdAndAddressFromMessageStream(const std::string& device_address, MessageStream* message_stream); - // Checks |device_pairing_information_| for a ble address and model id - // needed for retroactive pairing, and notifies observers. + // Checks |device_pairing_information_| for a BLE address and model id + // needed for retroactive pairing, and notifies observers if within the + // |expiry_timeout| time period. void CheckPairingInformation(const std::string& device_address); + // Adds |device_pairing_information_| entry for a device at |device_address| + // with the |expiry_timeout| field. BLE address and model id are added once + // the `MessageStream` is connected. + void AddDevicePairingInformation(const std::string& device_address); + + // Checks if the |device_pairing_information_| at |device_address| has + // exceeded its expiry timeout. If so, removes all references to device in + // |device_pairing_information_|, |potential_retroactive_addresses_|, and + // removes an observer for a corresponding MessageStream and from + // |message_streams_| if a MessageStream exists for the device, and returns + // `true`. Otherwise if the device has not expired, returns `false`. + bool CheckAndRemoveIfDeviceExpired(const std::string& device_address); + // FastPairRepository::IsDeviceSavedToAccount callback void AttemptRetroactivePairing(const std::string& classic_address, bool is_device_saved_to_account); @@ -132,6 +148,14 @@ const std::string& classic_address); void RemoveDeviceInformation(const std::string& device_address); + void RemoveDeviceInformationHelper(const std::string& device_address); + + // Iterates over |device_pairing_information_| and if a device's + // |expiry_timestamp| has been reached, removes devices from + // |device_pairing_information_|, |potential_retroactive_addresses_|, and + // removes an observer for a corresponding MessageStream and from + // |message_streams_| if a MessageStream exists for the device. + void RemoveExpiredDevicesFromStoredDeviceData(); // The classic pairing addresses of potential Retroactive Pair supported // devices that are found in the adapter. We have to store them and wait for a
diff --git a/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc b/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc index 2b2ff53..b8683b1 100644 --- a/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc +++ b/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc
@@ -41,7 +41,9 @@ namespace { +constexpr base::TimeDelta kRetroactiveDevicePairingTimeout = base::Seconds(60); constexpr char kTestDeviceAddress[] = "11:12:13:14:15:16"; +constexpr char kTestDeviceAddress2[] = "11:12:13:14:15:17"; constexpr char kTestBleDeviceName[] = "Test Device Name"; constexpr char kValidModelId[] = "718c17"; const std::string kUserEmail = "test@test.test"; @@ -123,6 +125,9 @@ : public AshTestBase, public RetroactivePairingDetector::Observer { public: + RetroactivePairingDetectorTest() + : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} + void SetUp() override { AshTestBase::SetUp(); adapter_ = @@ -1779,5 +1784,138 @@ EXPECT_FALSE(retroactive_pair_found_); } +// There are two ways to get to `CheckAndRemoveIfDeviceExpired `. One is by +// `GetModelIdAndAddressFromMessageStream` which is triggered when the +// MessageStream already has the model id and BLE address messages on +// connection. The second way is through `CheckPairingInformation` which is +// triggered when the MessageStream does not have the model id and BLE +// address on connection, and the model id and BLE address are observed later +// on. +TEST_F(RetroactivePairingDetectorTest, + DontNotify_ExpiryTimeoutReached_GetModelIdAndAddressFromMessageStream) { + Login(user_manager::UserType::USER_TYPE_REGULAR); + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + /*enabled_features=*/{features::kFastPairSavedDevices}, + /*disabled_features=*/{features::kFastPairSavedDevicesStrictOptIn}); + fast_pair_repository_.SetOptInStatus( + nearby::fastpair::OptInStatus::STATUS_OPTED_OUT); + base::RunLoop().RunUntilIdle(); + CreateRetroactivePairingDetector(); + + EXPECT_FALSE(retroactive_pair_found_); + + // Pair a device with classic Bluetooth pairing and set the MessageStream + // with model id and BLE address bytes to successfully detect the scenario. + // At this point, the device is in the `device_pairing_information_` map with + // an expiry timestamp. + SetMessageStream(kModelIdBleAddressBytes); + PairFastPairDeviceWithClassicBluetooth( + /*new_paired_status=*/true, kTestDeviceAddress); + + // Fast forward by |kRetroactiveDevicePairingTimeout| in order to simulate + // that the device's |expiry_timestamp| has been reached. Because the + // timeout has been reached, we expect that the retroactive pairing + // scenario to not be triggered. + task_environment()->FastForwardBy(kRetroactiveDevicePairingTimeout); + fake_socket_->TriggerReceiveCallback(); + NotifyMessageStreamConnected(kTestDeviceAddress); + base::RunLoop().RunUntilIdle(); + + EXPECT_FALSE(retroactive_pair_found_); +} + +TEST_F(RetroactivePairingDetectorTest, + DontNotify_ExpiryTimeoutReached_CheckPairingInformation) { + Login(user_manager::UserType::USER_TYPE_REGULAR); + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + /*enabled_features=*/{features::kFastPairSavedDevices}, + /*disabled_features=*/{features::kFastPairSavedDevicesStrictOptIn}); + fast_pair_repository_.SetOptInStatus( + nearby::fastpair::OptInStatus::STATUS_OPTED_OUT); + base::RunLoop().RunUntilIdle(); + CreateRetroactivePairingDetector(); + + EXPECT_FALSE(retroactive_pair_found_); + + // Pair a device with classic Bluetooth pairing and set the MessageStream + // with no bytes to successfully detect the scenario. + // At this point, the device is in the `device_pairing_information_` map with + // an expiry timestamp. Because there are no BLE address bytes or model id + // bytes in the connected MessageStream, the RetroactivePairingDetector adds + // itself as an observer to wait for these messages. + PairFastPairDeviceWithClassicBluetooth( + /*new_paired_status=*/true, kTestDeviceAddress); + NotifyMessageStreamConnected(kTestDeviceAddress); + + // Fast forward by |kRetroactiveDevicePairingTimeout| in order to simulate + // that the device's |expiry_timestamp| has been reached. Because the + // timeout has been reached, we expect that the retroactive pairing + // scenario to not be triggered. + task_environment()->FastForwardBy(kRetroactiveDevicePairingTimeout); + + // Set up the socket with the model id bytes and BLE address bytes to + // successfully detect the scenario, and trigger the bytes being received + // after the timeout to trigger the check in `CheckPairingInformation` + // which happens in the overridden observed red functions for + // `OnModelIdMessage` and `OnBleAddressUpdateMessage`. + fake_socket_->SetIOBufferFromBytes(kModelIdBleAddressBytes); + + // TODO(b/263391358): Refactor `TriggerReceiveCallback` to take a + // base::RunLoop parameter and remove `base::RunLoop().RunUntilIdle()`. + fake_socket_->TriggerReceiveCallback(); + base::RunLoop().RunUntilIdle(); + + EXPECT_FALSE(retroactive_pair_found_); +} + +TEST_F(RetroactivePairingDetectorTest, + DontNotify_ExpiryTimeoutReached_DifferentDeviceTriggerRemoval) { + Login(user_manager::UserType::USER_TYPE_REGULAR); + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + /*enabled_features=*/{features::kFastPairSavedDevices}, + /*disabled_features=*/{features::kFastPairSavedDevicesStrictOptIn}); + fast_pair_repository_.SetOptInStatus( + nearby::fastpair::OptInStatus::STATUS_OPTED_OUT); + base::RunLoop().RunUntilIdle(); + CreateRetroactivePairingDetector(); + + EXPECT_FALSE(retroactive_pair_found_); + + // Simulate a first device being found with classic Bluetooth pairing. + // At this point, the device is in the `device_pairing_information_` map with + // an expiry timestamp. This device does not have a MessageStream associated, + // so `CheckPairingInformation` will never be fired because it doesn't have + // a model id or BLE event, and thus alone, its expiry event will never be + // triggered. + PairFastPairDeviceWithClassicBluetooth( + /*new_paired_status=*/true, kTestDeviceAddress); + + // Fast forward by |kRetroactiveDevicePairingTimeout| in order to simulate + // that the device's |expiry_timestamp| has been reached. + task_environment()->FastForwardBy(kRetroactiveDevicePairingTimeout); + + // Simulate another device being found for retroactive pairing. This device + // will also be added to `device_pairing_information_` map with an expiry + // timeout, and its addition will trigger + // `RemoveExpiredDevicesFromStoredDeviceData`, which will remove the + // first device since it has expired. + PairFastPairDeviceWithClassicBluetooth( + /*new_paired_status=*/true, kTestDeviceAddress2); + + // Trigger a Message Stream event for the first device with the model id and + // BLE address. Although there is a check in `CheckPairingInformation`, + // the device was already removed in + // `RemoveExpiredDevicesFromStoredDeviceData`. + SetMessageStream(kModelIdBleAddressBytes); + fake_socket_->TriggerReceiveCallback(); + NotifyMessageStreamConnected(kTestDeviceAddress); + base::RunLoop().RunUntilIdle(); + + EXPECT_FALSE(retroactive_pair_found_); +} + } // namespace quick_pair } // namespace ash
diff --git a/ash/style/style_viewer/system_ui_components_grid_view_factories.h b/ash/style/style_viewer/system_ui_components_grid_view_factories.h index acf6203..e20e5fd6 100644 --- a/ash/style/style_viewer/system_ui_components_grid_view_factories.h +++ b/ash/style/style_viewer/system_ui_components_grid_view_factories.h
@@ -24,6 +24,7 @@ std::unique_ptr<SystemUIComponentsGridView> CreateRadioButtonGroupInstancesGridView(); std::unique_ptr<SystemUIComponentsGridView> CreateKnobSwitchInstancesGridView(); +std::unique_ptr<SystemUIComponentsGridView> CreateTabSliderInstancesGridView(); } // namespace ash
diff --git a/ash/style/style_viewer/system_ui_components_style_viewer_view.cc b/ash/style/style_viewer/system_ui_components_style_viewer_view.cc index 5a46ed25..0efd46e 100644 --- a/ash/style/style_viewer/system_ui_components_style_viewer_view.cc +++ b/ash/style/style_viewer/system_ui_components_style_viewer_view.cc
@@ -167,6 +167,9 @@ base::BindRepeating(&CreateRadioButtonGroupInstancesGridView)); viewer_view->AddComponent( u"KnobSwitch", base::BindRepeating(&CreateKnobSwitchInstancesGridView)); + viewer_view->AddComponent( + u"TabSlider", base::BindRepeating(&CreateTabSliderInstancesGridView)); + // Show PillButton on start. viewer_view->ShowComponentInstances(u"PillButton");
diff --git a/ash/style/style_viewer/tab_slider_instances_grid_view_factory.cc b/ash/style/style_viewer/tab_slider_instances_grid_view_factory.cc new file mode 100644 index 0000000..0514028 --- /dev/null +++ b/ash/style/style_viewer/tab_slider_instances_grid_view_factory.cc
@@ -0,0 +1,131 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/style/style_viewer/system_ui_components_grid_view_factories.h" + +#include "ash/resources/vector_icons/vector_icons.h" +#include "ash/style/style_viewer/system_ui_components_grid_view.h" +#include "ash/style/tab_slider.h" +#include "ash/style/tab_slider_button.h" + +namespace ash { + +namespace { + +// Configurations of grid view for `TabSlider` instances. +constexpr size_t kGridViewRowNum = 6; +constexpr size_t kGridViewColNum = 1; +constexpr size_t kGridViewRowGroupSize = 3; +constexpr size_t kGirdViewColGroupSize = 1; + +} // namespace + +std::unique_ptr<SystemUIComponentsGridView> CreateTabSliderInstancesGridView() { + auto grid_view = std::make_unique<SystemUIComponentsGridView>( + kGridViewRowNum, kGridViewColNum, kGridViewRowGroupSize, + kGirdViewColGroupSize); + + // Create an instance of icon slider with two buttons, a slider background, + // the recommended layout, and a selector animation. + auto icon_slider_two = std::make_unique<TabSlider>(); + // Add the buttons with `IconSliderButton` unique pointer. + auto* image_button = + icon_slider_two->AddButton(std::make_unique<IconSliderButton>( + IconSliderButton::PressedCallback(), &kCaptureModeImageIcon, + u"image mode")); + image_button->SetSelected(true); + icon_slider_two->AddButton(std::make_unique<IconSliderButton>( + IconSliderButton::PressedCallback(), &kCaptureModeCameraIcon, + u"video mode")); + + // Create an instance of icon slider with three buttons, no background, a + // customized layout, and no slider animation. + auto icon_slider_three = std::make_unique<TabSlider>( + /*has_background_=*/false, /*has_slider_background_animation=*/false); + icon_slider_three->SetCustomLayout( + {/*button_container_spacing=*/0, /*between_buttons_spacing=*/16}); + // Add the buttons with ctor arguments of `IconSliderButton`. + auto* fullscreen_button = icon_slider_three->AddButton<IconSliderButton>( + IconSliderButton::PressedCallback(), &kCaptureModeFullscreenIcon, + u"fullscreen mode"); + fullscreen_button->SetSelected(true); + icon_slider_three->AddButton<IconSliderButton>( + IconSliderButton::PressedCallback(), &kCaptureModeRegionIcon, + u"region mode"); + icon_slider_three->AddButton<IconSliderButton>( + IconSliderButton::PressedCallback(), &kCaptureModeWindowIcon, + u"window mode"); + + // Create an instance of disabled icon slider with two buttons. + auto icon_slider_two_disabled = std::make_unique<TabSlider>(); + auto* disabled_image_button = + icon_slider_two_disabled->AddButton<IconSliderButton>( + IconSliderButton::PressedCallback(), &kCaptureModeImageIcon, + u"image mode"); + disabled_image_button->SetSelected(true); + icon_slider_two_disabled->AddButton<IconSliderButton>( + IconSliderButton::PressedCallback(), &kCaptureModeCameraIcon, + u"video mode"); + icon_slider_two_disabled->SetEnabled(false); + + // Create an instance of label slider with two buttons. + auto label_slider_two = std::make_unique<TabSlider>(); + // Add the buttons with `TabSliderButton` unique pointer. + auto* label_button = + label_slider_two->AddButton(std::make_unique<LabelSliderButton>( + LabelSliderButton::PressedCallback(), u"Label 1", u"label 1")); + label_button->SetSelected(true); + label_slider_two->AddButton(std::make_unique<LabelSliderButton>( + LabelSliderButton::PressedCallback(), u"Label 2", u"label 2")); + + // Create an instance of label slider with three buttons with customized + // layout. + auto label_slider_three = std::make_unique<TabSlider>(); + label_slider_three->SetCustomLayout( + {/*button_container_spacing=*/2, /*between_buttons_spacing=*/16}); + // Add the buttons with ctor arguments of `TabSliderButton`. + auto* label_button_1 = label_slider_three->AddButton<LabelSliderButton>( + LabelSliderButton::PressedCallback(), u"Label 1", u"label 1"); + label_button_1->SetSelected(true); + label_slider_three->AddButton<LabelSliderButton>( + LabelSliderButton::PressedCallback(), u"Label 2", u"label 2"); + label_slider_three->AddButton<LabelSliderButton>( + LabelSliderButton::PressedCallback(), u"Label 3", u"label 3"); + + // Create an instance of disabled label slider with two buttons. + auto label_slider_two_disabled = std::make_unique<TabSlider>(); + auto* disabled_label_button = + label_slider_two_disabled->AddButton<LabelSliderButton>( + LabelSliderButton::PressedCallback(), u"Label 1", u"label 1"); + disabled_label_button->SetSelected(true); + label_slider_two_disabled->AddButton<LabelSliderButton>( + LabelSliderButton::PressedCallback(), u"Label 2", u"label 2"); + label_slider_two_disabled->SetEnabled(false); + + grid_view->AddInstance( + u"Icon tab slider with 2 buttons, recommended layout, selector " + u"animation, and background", + std::move(icon_slider_two)); + grid_view->AddInstance( + u"Icon tab slider with 3 buttons, custom layout, no selector " + u"animation, and no background", + std::move(icon_slider_three)); + grid_view->AddInstance(u"Disabled icon slider with 2 buttons", + std::move(icon_slider_two_disabled)); + + grid_view->AddInstance( + u"Label tab slider with 2 buttons, recommended layout, selector " + u"animation, and background", + std::move(label_slider_two)); + grid_view->AddInstance( + u"Label tab slider with 3 buttons, recommended layout, selector " + u"animation, and background", + std::move(label_slider_three)); + grid_view->AddInstance(u"Disabled label slider with 2 buttons", + std::move(label_slider_two_disabled)); + + return grid_view; +} + +} // namespace ash
diff --git a/ash/style/system_textfield.cc b/ash/style/system_textfield.cc new file mode 100644 index 0000000..1f99590 --- /dev/null +++ b/ash/style/system_textfield.cc
@@ -0,0 +1,218 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/style/system_textfield.h" + +#include "ash/style/system_textfield_controller.h" +#include "system_textfield.h" +#include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/chromeos/styles/cros_tokens_color_mappings.h" +#include "ui/color/color_provider.h" +#include "ui/gfx/canvas.h" +#include "ui/views/background.h" +#include "ui/views/border.h" +#include "ui/views/controls/focus_ring.h" +#include "ui/views/controls/highlight_path_generator.h" + +namespace ash { + +namespace { + +// The name of font family. +constexpr char kGoogleSansFont[] = "Google Sans"; +// The heights of textfield containers for different font sizes. +constexpr int kSmallContainerHeight = 24; +constexpr int kMediumContainerHeight = 28; +constexpr int kLargeContainerHeight = 28; +// The font sizes in pixels. +constexpr int kSmallFontSize = 12; +constexpr int kMediumFontSize = 14; +constexpr int kLargeFontSize = 16; +// The minimum textfield container width. +constexpr int kMinWidth = 80; +// The gap between the focus ring and textfield container. +constexpr float kFocusRingGap = 2.0f; +// The border insets to add horizontal paddings in container. +constexpr gfx::Insets kBorderInsets = gfx::Insets::VH(0, 8); +// The rounded conner radius of textfield container. +constexpr int kCornerRadius = 4; + +// Gets textfield container heights for different types. +int GetContainerHeightFromType(SystemTextfield::Type type) { + int container_height; + switch (type) { + case SystemTextfield::Type::kSmall: + container_height = kSmallContainerHeight; + break; + case SystemTextfield::Type::kMedium: + container_height = kMediumContainerHeight; + break; + case SystemTextfield::Type::kLarge: + container_height = kLargeContainerHeight; + break; + } + return container_height; +} + +// Gets font list for different types. +gfx::FontList GetFontListFromType(SystemTextfield::Type type) { + int font_size; + switch (type) { + case SystemTextfield::Type::kSmall: + font_size = kSmallFontSize; + break; + case SystemTextfield::Type::kMedium: + font_size = kMediumFontSize; + break; + case SystemTextfield::Type::kLarge: + font_size = kLargeFontSize; + break; + } + return gfx::FontList({kGoogleSansFont}, gfx::Font::NORMAL, font_size, + gfx::Font::Weight::NORMAL); +} + +} // namespace + +SystemTextfield::SystemTextfield(Type type) : type_(type) { + SetFontList(GetFontListFromType(type_)); + SetBorder(views::CreateEmptyBorder(kBorderInsets)); + + // Configure focus ring. + auto* focus_ring = views::FocusRing::Get(this); + DCHECK(focus_ring); + const float halo_thickness = focus_ring->GetHaloThickness(); + focus_ring->SetHaloInset(-kFocusRingGap - 0.5f * halo_thickness); + focus_ring->SetColorId(cros_tokens::kCrosSysFocusRing); + + enabled_changed_subscription_ = AddEnabledChangedCallback(base::BindRepeating( + &SystemTextfield::OnEnabledStateChanged, base::Unretained(this))); +} + +SystemTextfield::~SystemTextfield() = default; + +void SystemTextfield::SetActive(bool active) { + if (active_ == active) + return; + + active_ = active; + + if (active_) { + // Activate the textfield and record the text content. + views::Textfield::OnFocus(); + restored_text_content_ = GetText(); + } else { + // Clear selection when the textfield is deactivated. + ClearSelection(); + views::Textfield::OnBlur(); + } + + views::FocusRing::Get(this)->SchedulePaint(); +} + +void SystemTextfield::RestoreText() { + SetText(restored_text_content_); +} + +gfx::Size SystemTextfield::CalculatePreferredSize() const { + // The width of container equals to the content width with horizontal padding. + // The height of the container dependents on the type. + const std::u16string& text = GetText(); + int width = 0; + int height = 0; + gfx::Canvas::SizeStringInt(text.empty() ? GetPlaceholderText() : text, + GetFontListFromType(type_), &width, &height, 0, + gfx::Canvas::NO_ELLIPSIS); + return gfx::Size( + std::max(width + GetCaretBounds().width() + GetInsets().width(), + kMinWidth), + GetContainerHeightFromType(type_)); +} + +void SystemTextfield::SetBorder(std::unique_ptr<views::Border> b) { + // The base `Textfield` has a preset border. When a new border is set, the + // focus ring will be removed. The `SystemTextfield` needs an empty border for + // horizontal padding and keeps the focus ring. + views::View::SetBorder(std::move(b)); +} + +void SystemTextfield::OnMouseEntered(const ui::MouseEvent& event) { + UpdateBackground(); +} + +void SystemTextfield::OnMouseExited(const ui::MouseEvent& event) { + UpdateBackground(); +} + +void SystemTextfield::OnThemeChanged() { + views::View::OnThemeChanged(); + + // Only update the text color since the background color will be handled by + // themed background. + UpdateTextColor(); +} + +void SystemTextfield::OnFocus() { + if (delegate_) { + delegate_->OnTextfieldFocused(this); + } else { + views::Textfield::OnFocus(); + } + + UpdateBackground(); +} + +void SystemTextfield::OnBlur() { + if (delegate_) { + delegate_->OnTextfieldBlurred(this); + } else { + views::Textfield::OnBlur(); + } + + UpdateBackground(); +} + +void SystemTextfield::OnEnabledStateChanged() { + UpdateBackground(); + UpdateTextColor(); + SchedulePaint(); +} + +void SystemTextfield::UpdateTextColor() { + if (!GetWidget()) + return; + + // Set text color. + auto* color_provider = GetColorProvider(); + gfx::RenderText* render_text = GetRenderText(); + if (!GetEnabled()) { + SetColor(color_provider->GetColor(cros_tokens::kCrosSysDisabled)); + return; + } + + // Set text color and selection text and background (highlight part) colors. + SetColor(color_provider->GetColor(cros_tokens::kCrosSysOnSurface)); + render_text->set_selection_color( + color_provider->GetColor(cros_tokens::kCrosSysOnSurface)); + render_text->set_selection_background_focused_color( + color_provider->GetColor(cros_tokens::kCrosSysHighlightText)); +} + +void SystemTextfield::UpdateBackground() { + // Create a themed rounded rect background when the mouse hovers on the + // textfield or the textfield is focused. + if (IsMouseHovered() || HasFocus()) { + SetBackground(views::CreateThemedRoundedRectBackground( + cros_tokens::kCrosSysHoverOnSubtle, kCornerRadius)); + return; + } + + // In other cases, use a transparent background. + SetBackground(nullptr); +} + +BEGIN_METADATA(SystemTextfield, views::Textfield) +END_METADATA + +} // namespace ash
diff --git a/ash/style/system_textfield.h b/ash/style/system_textfield.h new file mode 100644 index 0000000..c88d3a7 --- /dev/null +++ b/ash/style/system_textfield.h
@@ -0,0 +1,81 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_STYLE_SYSTEM_TEXTFIELD_H_ +#define ASH_STYLE_SYSTEM_TEXTFIELD_H_ + +#include "ash/ash_export.h" +#include "ui/base/metadata/metadata_header_macros.h" +#include "ui/color/color_id.h" +#include "ui/views/controls/textfield/textfield.h" + +namespace ash { + +class SystemTextfieldController; + +// SystemTextfield is an extension of `Views::Textfield` used for system UIs. It +// has specific small, medium, and large types and applies dynamic colors. +class ASH_EXPORT SystemTextfield : public views::Textfield { + public: + METADATA_HEADER(SystemTextfield); + + enum class Type { + kSmall, + kMedium, + kLarge, + }; + + // The delegate that handles the textfield behaviors on focused and blurred. + class Delegate { + public: + virtual void OnTextfieldFocused(SystemTextfield* textfield) = 0; + virtual void OnTextfieldBlurred(SystemTextfield* textfield) = 0; + + protected: + virtual ~Delegate() = default; + }; + + explicit SystemTextfield(Type type); + SystemTextfield(const SystemTextfield&) = delete; + SystemTextfield& operator=(const SystemTextfield&) = delete; + ~SystemTextfield() override; + + void set_delegate(Delegate* delegate) { delegate_ = delegate; } + + // Activates or deactivates the textfield. The method is mainly used by + // `SystemTextfieldController`. + void SetActive(bool active); + bool active() const { return active_; } + // Restores to previous text when the changes are discarded. + void RestoreText(); + + // views::Textfield: + gfx::Size CalculatePreferredSize() const override; + void SetBorder(std::unique_ptr<views::Border> b) override; + void OnMouseEntered(const ui::MouseEvent& event) override; + void OnMouseExited(const ui::MouseEvent& event) override; + void OnThemeChanged() override; + void OnFocus() override; + void OnBlur() override; + + private: + // Called when the enabled state is changed. + void OnEnabledStateChanged(); + // Updates text and selection text colors. + void UpdateTextColor(); + // Creates themed or transparent background according to the textfield states. + void UpdateBackground(); + + Type type_; + bool active_ = false; + // Text content to restore when changes are discarded. + std::u16string restored_text_content_; + Delegate* delegate_ = nullptr; + // Enabled state changed callback. + base::CallbackListSubscription enabled_changed_subscription_; +}; + +} // namespace ash + +#endif // ASH_STYLE_SYSTEM_TEXTFIELD_H_
diff --git a/ash/style/system_textfield_controller.cc b/ash/style/system_textfield_controller.cc new file mode 100644 index 0000000..4b239d4 --- /dev/null +++ b/ash/style/system_textfield_controller.cc
@@ -0,0 +1,104 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/style/system_textfield_controller.h" + +#include "ui/views/controls/focus_ring.h" +#include "ui/views/focus/focus_manager.h" +#include "ui/views/widget/widget.h" + +namespace ash { +SystemTextfieldController::SystemTextfieldController(SystemTextfield* textfield) + : textfield_(textfield) { + textfield_->SetController(this); + textfield_->set_delegate(this); + views::FocusRing::Get(textfield_) + ->SetHasFocusPredicate( + [&](views::View* view) { return textfield_->active(); }); +} + +SystemTextfieldController::~SystemTextfieldController() = default; + +void SystemTextfieldController::OnTextfieldFocused(SystemTextfield* textfield) { + DCHECK_EQ(textfield_, textfield); + // Do not activate the textfield immediately on focus. +} + +void SystemTextfieldController::OnTextfieldBlurred(SystemTextfield* textfield) { + DCHECK_EQ(textfield_, textfield); + // Deactivate the textfield on blur. + textfield_->SetActive(false); +} + +bool SystemTextfieldController::HandleKeyEvent(views::Textfield* sender, + const ui::KeyEvent& key_event) { + DCHECK_EQ(textfield_, sender); + + if (key_event.type() != ui::ET_KEY_PRESSED) + return false; + + const bool active = textfield_->active(); + if (key_event.key_code() == ui::VKEY_RETURN) { + // If the textfield is focused but not active, activate the textfield and + // highlight all the text. + if (!active) { + textfield_->SetActive(true); + textfield_->SelectAll(false); + return true; + } + + // Otherwise, commit the changes and deactivate the textfield. + textfield_->SetActive(false); + return true; + } + + if (key_event.key_code() == ui::VKEY_ESCAPE) { + // If the textfield is active, discard the changes, deactivate the + // textfield. + if (active) { + textfield_->RestoreText(); + textfield_->SetActive(false); + return true; + } + } + + return false; +} + +bool SystemTextfieldController::HandleMouseEvent( + views::Textfield* sender, + const ui::MouseEvent& mouse_event) { + DCHECK_EQ(textfield_, sender); + + if (!mouse_event.IsOnlyLeftMouseButton() && + !mouse_event.IsOnlyRightMouseButton()) { + return false; + } + + switch (mouse_event.type()) { + case ui::ET_MOUSE_PRESSED: + // When the mouse is pressed and the textfield is not active, activate + // the textfield but defer selecting all text until the mouse is + // released. + if (!textfield_->active()) { + defer_select_all_ = true; + textfield_->SetActive(true); + } + break; + case ui::ET_MOUSE_RELEASED: + // When selecting all text was deferred, do it if there is no selection. + if (defer_select_all_) { + defer_select_all_ = false; + if (!textfield_->HasSelection()) + textfield_->SelectAll(false); + return true; + } + break; + default: + break; + } + return false; +} + +} // namespace ash \ No newline at end of file
diff --git a/ash/style/system_textfield_controller.h b/ash/style/system_textfield_controller.h new file mode 100644 index 0000000..a2e0b1d --- /dev/null +++ b/ash/style/system_textfield_controller.h
@@ -0,0 +1,53 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_STYLE_SYSTEM_TEXTFIELD_CONTROLLER_H_ +#define ASH_STYLE_SYSTEM_TEXTFIELD_CONTROLLER_H_ + +#include "ash/ash_export.h" +#include "ash/style/system_textfield.h" +#include "ui/views/controls/textfield/textfield_controller.h" + +namespace ash { + +// Defines the following textfield behaviors of system UI. Note that the +// controller can only be set to one textfield at a time: +// - When the textfield just gets focused with Tab key, it will not be activated +// until the user presses RETURN. +// - Clicking the textfield will both focus and activate the textfield. Single +// clicking will highlight all the text. +// - While editing the textfield, pressing RETURN will commit the changes and +// deactivate the textfield but keep focus. +// - While editing the textfield, pressing ESCAPE will discard the changes and +// deactivate the textfield but keep focus. +// - The focus ring would only show on active. +class ASH_EXPORT SystemTextfieldController : public views::TextfieldController, + public SystemTextfield::Delegate { + public: + explicit SystemTextfieldController(SystemTextfield* textfield); + SystemTextfieldController(const SystemTextfieldController&) = delete; + SystemTextfieldController& operator=(const SystemTextfieldController&) = + delete; + ~SystemTextfieldController() override; + + // SystemTextfield::Delegate: + void OnTextfieldFocused(SystemTextfield* textfield) override; + void OnTextfieldBlurred(SystemTextfield* textfield) override; + + // views::TextfieldController: + bool HandleKeyEvent(views::Textfield* sender, + const ui::KeyEvent& key_event) override; + bool HandleMouseEvent(views::Textfield* sender, + const ui::MouseEvent& mouse_event) override; + + private: + // The textfield that the controller binds with. + SystemTextfield* const textfield_; + // Indicates if selecting all text should be deferred. + bool defer_select_all_ = false; +}; + +} // namespace ash + +#endif // ASH_STYLE_SYSTEM_TEXTFIELD_CONTROLLER_H_ \ No newline at end of file
diff --git a/ash/system/diagnostics/diagnostics_log_controller.cc b/ash/system/diagnostics/diagnostics_log_controller.cc index 94b1b16..9894a68 100644 --- a/ash/system/diagnostics/diagnostics_log_controller.cc +++ b/ash/system/diagnostics/diagnostics_log_controller.cc
@@ -150,21 +150,19 @@ // Add the routine section for the system category. log_pieces.push_back(GetRoutineResultsString(system_routines)); - if (features::IsNetworkingInDiagnosticsAppEnabled()) { - // Add networking category. - log_pieces.push_back(kNetworkingLogSectionHeader); + // Add networking category. + log_pieces.push_back(kNetworkingLogSectionHeader); - // Add the network info section. - log_pieces.push_back(networking_log_->GetNetworkInfo()); + // Add the network info section. + log_pieces.push_back(networking_log_->GetNetworkInfo()); - // Add the routine section for the network category. - const std::string network_routines = routine_log_->GetContentsForCategory( - RoutineLog::RoutineCategory::kNetwork); - log_pieces.push_back(GetRoutineResultsString(network_routines)); + // Add the routine section for the network category. + const std::string network_routines = routine_log_->GetContentsForCategory( + RoutineLog::RoutineCategory::kNetwork); + log_pieces.push_back(GetRoutineResultsString(network_routines)); - // Add the network events section. - log_pieces.push_back(networking_log_->GetNetworkEvents()); - } + // Add the network events section. + log_pieces.push_back(networking_log_->GetNetworkEvents()); if (features::IsInputInDiagnosticsAppEnabled()) { std::string input_log_contents = keyboard_input_log_->GetLogContents();
diff --git a/ash/system/network/managed_sim_lock_notifier_unittest.cc b/ash/system/network/managed_sim_lock_notifier_unittest.cc index e02f6fe..cc570bc 100644 --- a/ash/system/network/managed_sim_lock_notifier_unittest.cc +++ b/ash/system/network/managed_sim_lock_notifier_unittest.cc
@@ -107,13 +107,13 @@ } void SetAllowCellularSimLock(bool allow_cellular_sim_lock) { - base::DictionaryValue global_config; - global_config.SetBoolKey( - ::onc::global_network_config::kAllowCellularSimLock, - allow_cellular_sim_lock); + base::Value::Dict global_config; + global_config.Set(::onc::global_network_config::kAllowCellularSimLock, + allow_cellular_sim_lock); managed_network_configuration_handler()->SetPolicy( ::onc::ONC_SOURCE_DEVICE_POLICY, /*userhash=*/std::string(), - base::Value(base::Value::Type::LIST), global_config); + base::Value(base::Value::Type::LIST), + base::Value(std::move(global_config))); base::RunLoop().RunUntilIdle(); }
diff --git a/ash/system/network/network_info_bubble_unittest.cc b/ash/system/network/network_info_bubble_unittest.cc index f14f7af..a527535 100644 --- a/ash/system/network/network_info_bubble_unittest.cc +++ b/ash/system/network/network_info_bubble_unittest.cc
@@ -131,18 +131,18 @@ } void AddDefaultNetworkWithIPAddresses() { - base::DictionaryValue ipv4; - ipv4.SetKey(shill::kAddressProperty, base::Value(kIpv4Address)); - ipv4.SetKey(shill::kMethodProperty, base::Value(shill::kTypeIPv4)); + base::Value::Dict ipv4; + ipv4.Set(shill::kAddressProperty, base::Value(kIpv4Address)); + ipv4.Set(shill::kMethodProperty, base::Value(shill::kTypeIPv4)); - base::DictionaryValue ipv6; - ipv6.SetKey(shill::kAddressProperty, base::Value(kIpv6Address)); - ipv6.SetKey(shill::kMethodProperty, base::Value(shill::kTypeIPv6)); + base::Value::Dict ipv6; + ipv6.Set(shill::kAddressProperty, base::Value(kIpv6Address)); + ipv6.Set(shill::kMethodProperty, base::Value(shill::kTypeIPv6)); network_config_helper_.network_state_helper().ip_config_test()->AddIPConfig( - kIPv4ConfigPath, ipv4); + kIPv4ConfigPath, base::Value(std::move(ipv4))); network_config_helper_.network_state_helper().ip_config_test()->AddIPConfig( - kIPv6ConfigPath, ipv6); + kIPv6ConfigPath, base::Value(std::move(ipv6))); base::Value::List ip_configs; ip_configs.Append(kIPv4ConfigPath);
diff --git a/ash/system/network/sms_observer_unittest.cc b/ash/system/network/sms_observer_unittest.cc index 85ceab87..97e783d 100644 --- a/ash/system/network/sms_observer_unittest.cc +++ b/ash/system/network/sms_observer_unittest.cc
@@ -21,18 +21,17 @@ namespace { -std::unique_ptr<base::DictionaryValue> CreateMessage( +base::Value::Dict CreateMessage( const char* kDefaultMessage = "FakeSMSClient: \xF0\x9F\x98\x8A", const char* kDefaultNumber = "000-000-0000", const char* kDefaultTimestamp = "Fri Jun 8 13:26:04 EDT 2016") { - std::unique_ptr<base::DictionaryValue> sms = - std::make_unique<base::DictionaryValue>(); + base::Value::Dict sms; if (kDefaultNumber) - sms->SetStringKey("number", kDefaultNumber); + sms.Set("number", kDefaultNumber); if (kDefaultMessage) - sms->SetStringKey("text", kDefaultMessage); + sms.Set("text", kDefaultMessage); if (kDefaultTimestamp) - sms->SetStringKey("timestamp", kDefaultMessage); + sms.Set("timestamp", kDefaultMessage); return sms; } @@ -56,8 +55,7 @@ SmsObserver* sms_observer = GetSmsObserver(); EXPECT_EQ(0u, MessageCenter::Get()->GetVisibleNotifications().size()); - std::unique_ptr<base::DictionaryValue> sms(CreateMessage()); - sms_observer->MessageReceived(*sms); + sms_observer->MessageReceived(base::Value(CreateMessage())); const message_center::NotificationList::Notifications notifications = MessageCenter::Get()->GetVisibleNotifications(); @@ -76,9 +74,8 @@ SmsObserver* sms_observer = GetSmsObserver(); EXPECT_EQ(0u, MessageCenter::Get()->GetVisibleNotifications().size()); - std::unique_ptr<base::DictionaryValue> sms( - CreateMessage("FakeSMSClient: Test Message.", nullptr)); - sms_observer->MessageReceived(*sms); + sms_observer->MessageReceived( + base::Value(CreateMessage("FakeSMSClient: Test Message.", nullptr))); EXPECT_EQ(0u, MessageCenter::Get()->GetVisibleNotifications().size()); } @@ -87,8 +84,7 @@ SmsObserver* sms_observer = GetSmsObserver(); EXPECT_EQ(0u, MessageCenter::Get()->GetVisibleNotifications().size()); - std::unique_ptr<base::DictionaryValue> sms(CreateMessage("")); - sms_observer->MessageReceived(*sms); + sms_observer->MessageReceived(base::Value(CreateMessage(""))); EXPECT_EQ(0u, MessageCenter::Get()->GetVisibleNotifications().size()); } @@ -96,8 +92,7 @@ TEST_F(SmsObserverTest, TextMessageMissingText) { SmsObserver* sms_observer = GetSmsObserver(); EXPECT_EQ(0u, MessageCenter::Get()->GetVisibleNotifications().size()); - std::unique_ptr<base::DictionaryValue> sms(CreateMessage("")); - sms_observer->MessageReceived(*sms); + sms_observer->MessageReceived(base::Value(CreateMessage(""))); EXPECT_EQ(0u, MessageCenter::Get()->GetVisibleNotifications().size()); } @@ -107,10 +102,8 @@ SmsObserver* sms_observer = GetSmsObserver(); EXPECT_EQ(0u, MessageCenter::Get()->GetVisibleNotifications().size()); - std::unique_ptr<base::DictionaryValue> sms(CreateMessage("first message")); - sms_observer->MessageReceived(*sms); - std::unique_ptr<base::DictionaryValue> sms2(CreateMessage("second message")); - sms_observer->MessageReceived(*sms2); + sms_observer->MessageReceived(base::Value(CreateMessage("first message"))); + sms_observer->MessageReceived(base::Value(CreateMessage("second message"))); const message_center::NotificationList::Notifications notifications = MessageCenter::Get()->GetVisibleNotifications(); EXPECT_EQ(2u, notifications.size());
diff --git a/ash/system/power/power_button_controller_unittest.cc b/ash/system/power/power_button_controller_unittest.cc index d64c4be8..5751c5d 100644 --- a/ash/system/power/power_button_controller_unittest.cc +++ b/ash/system/power/power_button_controller_unittest.cc
@@ -1085,29 +1085,29 @@ public testing::WithParamInterface<PowerButtonPosition> { public: PowerButtonControllerWithPositionTest() : power_button_position_(GetParam()) { - base::DictionaryValue position_info; + base::Value::Dict position_info; switch (power_button_position_) { case PowerButtonPosition::LEFT: - position_info.SetStringKey(PowerButtonController::kEdgeField, - PowerButtonController::kLeftEdge); + position_info.Set(PowerButtonController::kEdgeField, + PowerButtonController::kLeftEdge); break; case PowerButtonPosition::RIGHT: - position_info.SetStringKey(PowerButtonController::kEdgeField, - PowerButtonController::kRightEdge); + position_info.Set(PowerButtonController::kEdgeField, + PowerButtonController::kRightEdge); break; case PowerButtonPosition::TOP: - position_info.SetStringKey(PowerButtonController::kEdgeField, - PowerButtonController::kTopEdge); + position_info.Set(PowerButtonController::kEdgeField, + PowerButtonController::kTopEdge); break; case PowerButtonPosition::BOTTOM: - position_info.SetStringKey(PowerButtonController::kEdgeField, - PowerButtonController::kBottomEdge); + position_info.Set(PowerButtonController::kEdgeField, + PowerButtonController::kBottomEdge); break; default: return; } - position_info.SetDoubleKey(PowerButtonController::kPositionField, - kPowerButtonPercentage); + position_info.Set(PowerButtonController::kPositionField, + kPowerButtonPercentage); std::string json_position_info; base::JSONWriter::Write(position_info, &json_position_info);
diff --git a/ash/system/video_conference/bubble/set_value_effects_view.cc b/ash/system/video_conference/bubble/set_value_effects_view.cc index 7c6bec1..b9ede5e 100644 --- a/ash/system/video_conference/bubble/set_value_effects_view.cc +++ b/ash/system/video_conference/bubble/set_value_effects_view.cc
@@ -35,6 +35,7 @@ } // Add a button for each state. + const int current_state = effect->get_state_callback().Run(); for (int i = 0; i < effect->GetNumStates(); ++i) { const VcEffectState* state = effect->GetState(/*index=*/i); std::unique_ptr<views::RadioButton> state_button = @@ -49,6 +50,11 @@ ? BubbleViewID::kSetValueButtonMin + i : BubbleViewID::kSetValueButtonMax); + // Set-value effects require an actual integer state. Mark it checked + // (selected) if the current state of the effect is this state's value, + DCHECK(state->state().has_value()); + state_button->SetChecked(state->state().value() == current_state); + AddChildView(std::move(state_button)); }
diff --git a/ash/system/video_conference/bubble/toggle_effects_view.cc b/ash/system/video_conference/bubble/toggle_effects_view.cc index 6d1907b..753c9fe 100644 --- a/ash/system/video_conference/bubble/toggle_effects_view.cc +++ b/ash/system/video_conference/bubble/toggle_effects_view.cc
@@ -10,6 +10,7 @@ #include "ash/system/video_conference/bubble/bubble_view_ids.h" #include "ash/system/video_conference/effects/video_conference_tray_effects_manager_types.h" #include "ash/system/video_conference/video_conference_tray_controller.h" +#include "ui/chromeos/styles/cros_tokens_color_mappings.h" #include "ui/views/background.h" #include "ui/views/border.h" #include "ui/views/controls/label.h" @@ -21,10 +22,11 @@ // A single toggle button for a video conference effect, combined with a text // label. -class ButtonContainer : public views::View { +class ButtonContainer : public views::View, public IconButton::Delegate { public: ButtonContainer(views::Button::PressedCallback callback, const gfx::VectorIcon* icon, + bool toggle_state, const std::u16string& label_text, const int accessible_name_id) { views::FlexLayout* layout = @@ -35,11 +37,26 @@ AddChildView(std::make_unique<views::Label>(label_text)); + // Construct the `IconButton`, set ID and initial toggle state (from the + // passed-in value, which is the current state of the effect). std::unique_ptr<IconButton> button = std::make_unique<IconButton>( callback, IconButton::Type::kMedium, icon, accessible_name_id, /*is_togglable=*/true, /*has_border=*/true); button->SetID(video_conference::BubbleViewID::kToggleEffectsButton); + button->SetToggled(toggle_state); + + // Delegate is the `ButtonContainer`, which changes the toggle-state of the + // button when clicked. + button->set_delegate(this); + + // TODO(b/253249205): This is temporary, will be replaced wholesale when the + // effect toggle buttons are made to conform with the spec. + button->SetBackgroundToggledColorId( + cros_tokens::kCrosSysSystemNegativeContainer); + button->SetIconToggledColorId( + cros_tokens::kCrosSysSystemOnNegativeContainer); + AddChildView(std::move(button)); SetBorder(views::CreateEmptyBorder(gfx::Insets::VH(10, 10))); @@ -51,6 +68,12 @@ ButtonContainer& operator=(const ButtonContainer&) = delete; ~ButtonContainer() override = default; + + // IconButton::Delegate: + void OnButtonToggled(IconButton* button) override {} + void OnButtonClicked(IconButton* button) override { + button->SetToggled(!button->toggled()); + } }; } // namespace @@ -86,8 +109,10 @@ DCHECK_EQ(tile->type(), VcEffectType::kToggle); DCHECK_EQ(tile->GetNumStates(), 1); const VcEffectState* state = tile->GetState(/*index=*/0); + bool current_state = tile->get_state_callback().Run(); row_view->AddChildView(std::make_unique<ButtonContainer>( - state->button_callback(), state->icon(), state->label_text(), + state->button_callback(), state->icon(), + /*toggle_state=*/current_state, state->label_text(), state->accessible_name_id())); }
diff --git a/ash/system/video_conference/effects/fake_video_conference_effects.cc b/ash/system/video_conference/effects/fake_video_conference_effects.cc index e6874c7..c8d560e 100644 --- a/ash/system/video_conference/effects/fake_video_conference_effects.cc +++ b/ash/system/video_conference/effects/fake_video_conference_effects.cc
@@ -21,19 +21,24 @@ /*icon=*/absl::nullopt, /*accessible_name_id=*/absl::nullopt) {} +SimpleToggleEffect::~SimpleToggleEffect() = default; + SimpleToggleEffect::SimpleToggleEffect( const std::u16string& label_text, absl::optional<const gfx::VectorIcon*> icon, absl::optional<int> accessible_name_id) { - std::unique_ptr<VcHostedEffect> effect = - std::make_unique<VcHostedEffect>(VcEffectType::kToggle); + std::unique_ptr<VcHostedEffect> effect = std::make_unique<VcHostedEffect>( + VcEffectType::kToggle, + base::BindRepeating(&SimpleToggleEffect::GetEffectState, + base::Unretained(this), + /*effect_id=*/VcEffectState::kUnusedId)); // Use default `icon` and/or `accessible_name_id` if none was passed in. std::unique_ptr<VcEffectState> state = std::make_unique<VcEffectState>( icon.value_or(&ash::kPrivacyIndicatorsCameraIcon), label_text, accessible_name_id.value_or(IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA), base::BindRepeating(&SimpleToggleEffect::OnEffectControlActivated, - base::Unretained(this), + weak_factory_.GetWeakPtr(), /*effect_id=*/VcEffectState::kUnusedId, /*value=*/0)); effect->AddState(std::move(state)); @@ -79,42 +84,22 @@ // Delegates that host a set-value effect. ShaggyFurEffect::ShaggyFurEffect() { - std::unique_ptr<VcHostedEffect> effect = - std::make_unique<VcHostedEffect>(VcEffectType::kSetValue); - std::unique_ptr<VcEffectState> bald_state = std::make_unique<VcEffectState>( - /*icon=*/nullptr, - /*label_text=*/u"Bald", - /*accessible_name_id=*/IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA, - /*button_callback=*/ - base::BindRepeating(&ShaggyFurEffect::OnEffectControlActivated, + std::unique_ptr<VcHostedEffect> effect = std::make_unique<VcHostedEffect>( + VcEffectType::kSetValue, + base::BindRepeating(&ShaggyFurEffect::GetEffectState, base::Unretained(this), - /*effect_id=*/0, - /*value=*/static_cast<int>(FurShagginess::kBald))); - std::unique_ptr<VcEffectState> buzzcut_state = - std::make_unique<VcEffectState>( - /*icon=*/nullptr, - /*label_text=*/u"Buzzcut", - /*accessible_name_id=*/IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA, - /*button_callback=*/ - base::BindRepeating( - &ShaggyFurEffect::OnEffectControlActivated, - base::Unretained(this), - /*effect_id=*/0, - /*value=*/static_cast<int>(FurShagginess::kBuzzcut))); - std::unique_ptr<VcEffectState> thick_state = std::make_unique<VcEffectState>( - /*icon=*/nullptr, - /*label_text=*/u"Thick", - /*accessible_name_id=*/IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA, - /*button_callback=*/ - base::BindRepeating(&ShaggyFurEffect::OnEffectControlActivated, - base::Unretained(this), - /*effect_id=*/0, - /*value=*/static_cast<int>(FurShagginess::kThick))); - effect->AddState(std::move(bald_state)); - effect->AddState(std::move(buzzcut_state)); - effect->AddState(std::move(thick_state)); + /*effect_id=*/0)); effect->set_label_text(u"Shaggy Fur"); effect->set_id(100); + AddStateToEffect(effect.get(), + /*state_value=*/static_cast<int>(FurShagginess::kBald), + /*label_text=*/u"Bald"); + AddStateToEffect(effect.get(), + /*state_value=*/static_cast<int>(FurShagginess::kBuzzcut), + /*label_text=*/u"Buzzcut"); + AddStateToEffect(effect.get(), + /*state_value=*/static_cast<int>(FurShagginess::kThick), + /*label_text=*/u"Thick"); AddEffect(std::move(effect)); // Initialize click counts. @@ -139,55 +124,41 @@ return num_activations_for_testing_[value]; } -SuperCutnessEffect::SuperCutnessEffect() { - std::unique_ptr<VcHostedEffect> effect = - std::make_unique<VcHostedEffect>(VcEffectType::kSetValue); - std::unique_ptr<VcEffectState> ugly_dog_state = - std::make_unique<VcEffectState>( - /*icon=*/nullptr, - /*label_text=*/u"Ugly Dog", - /*accessible_name_id=*/IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA, - /*button_callback=*/ - base::BindRepeating(&SuperCutnessEffect::OnEffectControlActivated, - base::Unretained(this), - /*effect_id=*/0, - /*value=*/static_cast<int>(HowCute::kUglyDog))); - std::unique_ptr<VcEffectState> teddy_bear_state = - std::make_unique<VcEffectState>( - /*icon=*/nullptr, - /*label_text=*/u"Teddy Bear", - /*accessible_name_id=*/IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA, - /*button_callback=*/ - base::BindRepeating(&SuperCutnessEffect::OnEffectControlActivated, - base::Unretained(this), - /*effect_id=*/0, - /*value=*/static_cast<int>(HowCute::kTeddyBear))); - std::unique_ptr<VcEffectState> zara_state = std::make_unique<VcEffectState>( +void ShaggyFurEffect::AddStateToEffect(VcHostedEffect* effect, + int state_value, + std::u16string label_text) { + DCHECK(effect); + effect->AddState(std::make_unique<VcEffectState>( /*icon=*/nullptr, - /*label_text=*/u"Zara", + /*label_text=*/label_text, /*accessible_name_id=*/IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA, /*button_callback=*/ - base::BindRepeating(&SuperCutnessEffect::OnEffectControlActivated, + base::BindRepeating(&ShaggyFurEffect::OnEffectControlActivated, + weak_factory_.GetWeakPtr(), /*effect_id=*/0, + /*value=*/state_value), + /*state=*/state_value)); +} + +SuperCutnessEffect::SuperCutnessEffect() { + std::unique_ptr<VcHostedEffect> effect = std::make_unique<VcHostedEffect>( + VcEffectType::kSetValue, + base::BindRepeating(&SuperCutnessEffect::GetEffectState, base::Unretained(this), - /*effect_id=*/0, - /*value=*/static_cast<int>(HowCute::kZara))); - std::unique_ptr<VcEffectState> inscrutable_state = - std::make_unique<VcEffectState>( - /*icon=*/nullptr, - /*label_text=*/u"Inscrutable", - /*accessible_name_id=*/IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA, - /*button_callback=*/ - base::BindRepeating( - &SuperCutnessEffect::OnEffectControlActivated, - base::Unretained(this), - /*effect_id=*/0, - /*value=*/static_cast<int>(HowCute::kInscrutable))); - effect->AddState(std::move(ugly_dog_state)); - effect->AddState(std::move(teddy_bear_state)); - effect->AddState(std::move(zara_state)); - effect->AddState(std::move(inscrutable_state)); + /*effect_id=*/0)); effect->set_label_text(u"Super Cuteness"); effect->set_id(200); + AddStateToEffect(effect.get(), + /*state_value=*/static_cast<int>(HowCute::kUglyDog), + /*label_text=*/u"Ugly Dog"); + AddStateToEffect(effect.get(), + /*state_value=*/static_cast<int>(HowCute::kTeddyBear), + /*label_text=*/u"Teddy Bear"); + AddStateToEffect(effect.get(), + /*state_value=*/static_cast<int>(HowCute::kZara), + /*label_text=*/u"Zara"); + AddStateToEffect(effect.get(), + /*state_value=*/static_cast<int>(HowCute::kInscrutable), + /*label_text=*/u"Inscrutable"); AddEffect(std::move(effect)); // Initialize click counts. @@ -212,6 +183,21 @@ return num_activations_for_testing_[value]; } +void SuperCutnessEffect::AddStateToEffect(VcHostedEffect* effect, + int state_value, + std::u16string label_text) { + DCHECK(effect); + effect->AddState(std::make_unique<VcEffectState>( + /*icon=*/nullptr, + /*label_text=*/label_text, + /*accessible_name_id=*/IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA, + /*button_callback=*/ + base::BindRepeating(&SuperCutnessEffect::OnEffectControlActivated, + weak_factory_.GetWeakPtr(), /*effect_id=*/0, + /*value=*/state_value), + /*state=*/state_value)); +} + // This registers/unregisters all effects owned by `EffectRepository`. // Comment-out the `RegisterDelegate`/`UnregisterDelegate` calls for effects // that are not needed e.g. to test `ash::video_conference::BubbleView` with
diff --git a/ash/system/video_conference/effects/fake_video_conference_effects.h b/ash/system/video_conference/effects/fake_video_conference_effects.h index f0a61bc..00ede90e 100644 --- a/ash/system/video_conference/effects/fake_video_conference_effects.h +++ b/ash/system/video_conference/effects/fake_video_conference_effects.h
@@ -9,6 +9,7 @@ #include "ash/ash_export.h" #include "ash/system/video_conference/effects/video_conference_tray_effects_delegate.h" +#include "base/memory/weak_ptr.h" #include "ui/views/controls/button/button.h" namespace gfx { @@ -36,7 +37,7 @@ SimpleToggleEffect(const SimpleToggleEffect&) = delete; SimpleToggleEffect& operator=(const SimpleToggleEffect&) = delete; - ~SimpleToggleEffect() override = default; + ~SimpleToggleEffect() override; // VcEffectsDelegate: int GetEffectState(int effect_id) override; @@ -47,6 +48,8 @@ private: // Number of times the control has been activated, used by unit tests. int num_activations_for_testing_ = 0; + + base::WeakPtrFactory<SimpleToggleEffect> weak_factory_{this}; }; // Delegates that host a series of "fake" effects used in unit tests and the @@ -149,9 +152,16 @@ int GetNumActivationsForTesting(int value); private: + // Adds a `std::unique_ptr<VcEffectState>` to `effect`. + void AddStateToEffect(VcHostedEffect* effect, + int state_value, + std::u16string label_text); + // Number of times each value has been clicked, one count for each value in // `FurShagginess`. std::vector<int> num_activations_for_testing_; + + base::WeakPtrFactory<ShaggyFurEffect> weak_factory_{this}; }; class ASH_EXPORT SuperCutnessEffect : public VcEffectsDelegate { @@ -180,9 +190,16 @@ int GetNumActivationsForTesting(int value); private: + // Adds a `std::unique_ptr<VcEffectState>` to `effect`. + void AddStateToEffect(VcHostedEffect* effect, + int state_value, + std::u16string label_text); + // Number of times each value has been clicked, one count for each value in // `HowCute`. std::vector<int> num_activations_for_testing_; + + base::WeakPtrFactory<SuperCutnessEffect> weak_factory_{this}; }; // A simple residence for any fake effects used for testing. For all of these
diff --git a/ash/system/video_conference/effects/video_conference_tray_effects_manager_types.cc b/ash/system/video_conference/effects/video_conference_tray_effects_manager_types.cc index 5f77269..c6b4476 100644 --- a/ash/system/video_conference/effects/video_conference_tray_effects_manager_types.cc +++ b/ash/system/video_conference/effects/video_conference_tray_effects_manager_types.cc
@@ -15,16 +15,21 @@ VcEffectState::VcEffectState(const gfx::VectorIcon* icon, const std::u16string& label_text, int accessible_name_id, - views::Button::PressedCallback button_callback) + views::Button::PressedCallback button_callback, + absl::optional<int> state /*= absl::nullopt*/) : icon_(icon), label_text_(label_text), accessible_name_id_(accessible_name_id), - button_callback_(button_callback) {} + button_callback_(button_callback), + state_(state) {} VcEffectState::~VcEffectState() = default; -VcHostedEffect::VcHostedEffect(VcEffectType type) - : type_(type), id_(VcEffectState::kUnusedId) {} +VcHostedEffect::VcHostedEffect(VcEffectType type, + GetEffectStateCallback get_state_callback) + : type_(type), + get_state_callback_(get_state_callback), + id_(VcEffectState::kUnusedId) {} VcHostedEffect::~VcHostedEffect() = default;
diff --git a/ash/system/video_conference/effects/video_conference_tray_effects_manager_types.h b/ash/system/video_conference/effects/video_conference_tray_effects_manager_types.h index 94ecf838d..6706ce42 100644 --- a/ash/system/video_conference/effects/video_conference_tray_effects_manager_types.h +++ b/ash/system/video_conference/effects/video_conference_tray_effects_manager_types.h
@@ -36,16 +36,21 @@ // // `button_callback` - A callback that's invoked when the user sets the effect // to this state. + // + // `state` - The actual state value. Optional because only certain types of + // effects (e.g. set-value) actually need it. VcEffectState(const gfx::VectorIcon* icon, const std::u16string& label_text, int accessible_name_id, - views::Button::PressedCallback button_callback); + views::Button::PressedCallback button_callback, + absl::optional<int> state = absl::nullopt); VcEffectState(const VcEffectState&) = delete; VcEffectState& operator=(const VcEffectState&) = delete; ~VcEffectState(); + absl::optional<int> state() const { return state_; } const gfx::VectorIcon* icon() const { return icon_; } const std::u16string& label_text() const { return label_text_; } int accessible_name_id() const { return accessible_name_id_; } @@ -68,6 +73,9 @@ // with the effect's ID and the actual (integer) value (e.g. // kBackgroundBlurMedium) member as arguments. views::Button::PressedCallback button_callback_; + + // The state value. + absl::optional<int> state_; }; // Designates the type of user-adjustments made to this effect. @@ -92,8 +100,13 @@ kOn = 1, }; + // Callback for obtaining the current state of the effect. The callback must + // have the effect ID bound as an argument. + using GetEffectStateCallback = base::RepeatingCallback<int(void)>; + // `type` is the type of value adjustment allowed. - explicit VcHostedEffect(VcEffectType type); + explicit VcHostedEffect(VcEffectType type, + GetEffectStateCallback get_state_callback); VcHostedEffect(const VcHostedEffect&) = delete; VcHostedEffect& operator=(const VcHostedEffect&) = delete; @@ -111,6 +124,9 @@ VcEffectType type() const { return type_; } void set_id(int id) { id_ = id; } + const GetEffectStateCallback& get_state_callback() const { + return get_state_callback_; + } int id() const { return id_; } void set_label_text(const std::u16string label_text) { label_text_ = label_text; @@ -122,10 +138,14 @@ // user-supplied ID. VcEffectType type_; + // Callback supplied by the parent `VcEffectsDelegate`, for obtaining the + // state of the effect. + GetEffectStateCallback get_state_callback_; + // Unique ID of the effect, if desired. int id_; - // Label text for the effect itself (that's separate from the label text of + // Label text for the effect (that's separate from the label text of // individual child states). std::u16string label_text_;
diff --git a/ash/webui/common/resources/network_health/network_diagnostics.html b/ash/webui/common/resources/network_health/network_diagnostics.html index 16d6f7f..8625e02 100644 --- a/ash/webui/common/resources/network_health/network_diagnostics.html +++ b/ash/webui/common/resources/network_health/network_diagnostics.html
@@ -20,8 +20,6 @@ routines= "[[getRoutineGroup_(routines_.*, RoutineGroup_.GOOGLE_SERVICES)]]"> </routine-group> -<template is="dom-if" if="[[areArcNetworkingRoutinesEnabled_]]" restamp> - <routine-group name="[[i18n('NetworkDiagnosticsArcGroup')]]" - routines="[[getRoutineGroup_(routines_.*, RoutineGroup_.ARC)]]"> - </routine-group> -</template> +<routine-group name="[[i18n('NetworkDiagnosticsArcGroup')]]" + routines="[[getRoutineGroup_(routines_.*, RoutineGroup_.ARC)]]"> +</routine-group>
diff --git a/ash/webui/common/resources/network_health/network_diagnostics.js b/ash/webui/common/resources/network_health/network_diagnostics.js index d6b02f2f..5d3f5ca 100644 --- a/ash/webui/common/resources/network_health/network_diagnostics.js +++ b/ash/webui/common/resources/network_health/network_diagnostics.js
@@ -5,7 +5,6 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.js'; import './routine_group.js'; -import {loadTimeData} from '//resources/ash/common/load_time_data.m.js'; import {Polymer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {I18nBehavior} from 'chrome://resources/ash/common/i18n_behavior.js'; import {ArcDnsResolutionProblem, ArcHttpProblem, ArcPingProblem, CaptivePortalProblem, DnsLatencyProblem, DnsResolutionProblem, DnsResolverPresentProblem, GatewayCanBePingedProblem, HasSecureWiFiConnectionProblem, HttpFirewallProblem, HttpsFirewallProblem, HttpsLatencyProblem, RoutineProblems, RoutineType, RoutineVerdict, SignalStrengthProblem, VideoConferencingProblem} from 'chrome://resources/mojo/chromeos/services/network_health/public/mojom/network_diagnostics.mojom-webui.js'; @@ -48,14 +47,6 @@ ], properties: { - /** @private */ - areArcNetworkingRoutinesEnabled_: { - type: Boolean, - value() { - return loadTimeData.getBoolean('enableArcNetworkDiagnostics'); - }, - }, - /** * List of Diagnostics Routines * @private {!Array<!Routine>} @@ -166,9 +157,7 @@ }, ], }, - ]; - if (this.areArcNetworkingRoutinesEnabled_) { - routineGroups.push({ + { group: RoutineGroup.ARC, routines: [ { @@ -188,8 +177,8 @@ getNetworkDiagnosticsService().runArcDnsResolution(), }, ], - }); - } + }, + ]; const routines = []; for (const group of routineGroups) {
diff --git a/ash/webui/diagnostics_ui/backend/connectivity/network_health_provider.cc b/ash/webui/diagnostics_ui/backend/connectivity/network_health_provider.cc index 6bef6f26..798fc45 100644 --- a/ash/webui/diagnostics_ui/backend/connectivity/network_health_provider.cc +++ b/ash/webui/diagnostics_ui/backend/connectivity/network_health_provider.cc
@@ -7,7 +7,6 @@ #include <string> #include <utility> -#include "ash/constants/ash_features.h" #include "ash/system/diagnostics/networking_log.h" #include "ash/webui/diagnostics_ui/backend/common/histogram_util.h" #include "base/bind.h" @@ -632,7 +631,6 @@ void NetworkHealthProvider::BindInterface( mojo::PendingReceiver<mojom::NetworkHealthProvider> pending_receiver) { - DCHECK(features::IsNetworkingInDiagnosticsAppEnabled()); receiver_.reset(); receiver_.Bind(std::move(pending_receiver)); }
diff --git a/ash/webui/diagnostics_ui/backend/connectivity/network_health_provider_unittest.cc b/ash/webui/diagnostics_ui/backend/connectivity/network_health_provider_unittest.cc index 638215d..efe5179 100644 --- a/ash/webui/diagnostics_ui/backend/connectivity/network_health_provider_unittest.cc +++ b/ash/webui/diagnostics_ui/backend/connectivity/network_health_provider_unittest.cc
@@ -6,14 +6,11 @@ #include <utility> -#include "ash/constants/ash_features.h" #include "ash/system/diagnostics/networking_log.h" #include "ash/webui/diagnostics_ui/backend/common/histogram_util.h" -#include "base/feature_list.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/ptr_util.h" #include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/values.h" #include "chromeos/ash/components/dbus/shill/shill_ipconfig_client.h" @@ -1477,8 +1474,6 @@ // This test simulates a user refreshing the WebUI page. The receiver should // be reset before binding the new receiver. Otherwise we would get a DCHECK // error from mojo::Receiver - base::test::ScopedFeatureList features; - features.InitAndEnableFeature(features::kEnableNetworkingInDiagnosticsApp); mojo::Remote<mojom::NetworkHealthProvider> remote; network_health_provider_->BindInterface(remote.BindNewPipeAndPassReceiver()); base::RunLoop().RunUntilIdle();
diff --git a/ash/webui/diagnostics_ui/backend/diagnostics_manager.cc b/ash/webui/diagnostics_ui/backend/diagnostics_manager.cc index 66215c3d..354165a 100644 --- a/ash/webui/diagnostics_ui/backend/diagnostics_manager.cc +++ b/ash/webui/diagnostics_ui/backend/diagnostics_manager.cc
@@ -27,11 +27,8 @@ DiagnosticsLogController::Get()->GetTelemetryLog()); system_routine_controller_ = std::make_unique<SystemRoutineController>( DiagnosticsLogController::Get()->GetRoutineLog()); - - if (features::IsNetworkingInDiagnosticsAppEnabled()) { - network_health_provider_ = std::make_unique<NetworkHealthProvider>( - DiagnosticsLogController::Get()->GetNetworkingLog()); - } + network_health_provider_ = std::make_unique<NetworkHealthProvider>( + DiagnosticsLogController::Get()->GetNetworkingLog()); } else { // TODO(b/226574520): Remove else block as part of DiagnosticsLogController // flag clean up. @@ -39,18 +36,14 @@ session_log_handler->GetTelemetryLog()); system_routine_controller_ = std::make_unique<SystemRoutineController>( session_log_handler->GetRoutineLog()); - - if (features::IsNetworkingInDiagnosticsAppEnabled()) { - network_health_provider_ = std::make_unique<NetworkHealthProvider>( - session_log_handler->GetNetworkingLog()); - } + network_health_provider_ = std::make_unique<NetworkHealthProvider>( + session_log_handler->GetNetworkingLog()); } } DiagnosticsManager::~DiagnosticsManager() = default; NetworkHealthProvider* DiagnosticsManager::GetNetworkHealthProvider() const { - DCHECK(features::IsNetworkingInDiagnosticsAppEnabled()); return network_health_provider_.get(); }
diff --git a/ash/webui/diagnostics_ui/backend/session_log_async_helper.cc b/ash/webui/diagnostics_ui/backend/session_log_async_helper.cc index aafa214..356389b4 100644 --- a/ash/webui/diagnostics_ui/backend/session_log_async_helper.cc +++ b/ash/webui/diagnostics_ui/backend/session_log_async_helper.cc
@@ -7,7 +7,6 @@ #include <memory> #include <string> -#include "ash/constants/ash_features.h" #include "ash/system/diagnostics/networking_log.h" #include "ash/system/diagnostics/routine_log.h" #include "ash/system/diagnostics/telemetry_log.h" @@ -67,20 +66,20 @@ // Add the routine section for the system category. pieces.push_back(GetRoutineResultsString(system_routines)); - if (features::IsNetworkingInDiagnosticsAppEnabled()) { - // Add networking category. - pieces.push_back(kNetworkingLogSectionHeader); + // Add networking category. + pieces.push_back(kNetworkingLogSectionHeader); - // Add the network info section. - if (networking_log) - pieces.push_back(networking_log->GetNetworkInfo()); + // Add the network info section. + if (networking_log) { + pieces.push_back(networking_log->GetNetworkInfo()); + } - // Add the routine section for the network category. - pieces.push_back(GetRoutineResultsString(network_routines)); + // Add the routine section for the network category. + pieces.push_back(GetRoutineResultsString(network_routines)); - // Add the network events section. - if (networking_log) - pieces.push_back(networking_log->GetNetworkEvents()); + // Add the network events section. + if (networking_log) { + pieces.push_back(networking_log->GetNetworkEvents()); } return base::WriteFile(file_path, base::JoinString(pieces, "\n"));
diff --git a/ash/webui/diagnostics_ui/diagnostics_ui.cc b/ash/webui/diagnostics_ui/diagnostics_ui.cc index 6ab470e..2a659bd 100644 --- a/ash/webui/diagnostics_ui/diagnostics_ui.cc +++ b/ash/webui/diagnostics_ui/diagnostics_ui.cc
@@ -378,14 +378,10 @@ source->AddBoolean("isLoggedIn", LoginState::Get()->IsUserLoggedIn()); source->AddBoolean("isInputEnabled", features::IsInputInDiagnosticsAppEnabled()); - source->AddBoolean("isNetworkingEnabled", - features::IsNetworkingInDiagnosticsAppEnabled()); source->AddBoolean("isTouchpadEnabled", features::IsTouchpadInDiagnosticsAppEnabled()); source->AddBoolean("isTouchscreenEnabled", features::IsTouchscreenInDiagnosticsAppEnabled()); - source->AddBoolean("enableArcNetworkDiagnostics", - features::IsArcNetworkDiagnosticsButtonEnabled()); } void SetUpPluralStringHandler(content::WebUI* web_ui) { @@ -457,12 +453,10 @@ void DiagnosticsDialogUI::BindInterface( mojo::PendingReceiver<diagnostics::mojom::NetworkHealthProvider> receiver) { - if (features::IsNetworkingInDiagnosticsAppEnabled()) { - diagnostics::NetworkHealthProvider* network_health_provider = - diagnostics_manager_->GetNetworkHealthProvider(); - if (network_health_provider) { - network_health_provider->BindInterface(std::move(receiver)); - } + diagnostics::NetworkHealthProvider* network_health_provider = + diagnostics_manager_->GetNetworkHealthProvider(); + if (network_health_provider) { + network_health_provider->BindInterface(std::move(receiver)); } }
diff --git a/ash/webui/diagnostics_ui/resources/connectivity_card.ts b/ash/webui/diagnostics_ui/resources/connectivity_card.ts index 4dd568f..acf1ea5 100644 --- a/ash/webui/diagnostics_ui/resources/connectivity_card.ts +++ b/ash/webui/diagnostics_ui/resources/connectivity_card.ts
@@ -9,7 +9,6 @@ import './network_info.js'; import './routine_section.js'; -import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js'; import {assert} from 'chrome://resources/js/assert_ts.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -54,12 +53,12 @@ activeGuid: { type: String, value: '', - observer: 'activeGuidChanged_', + observer: ConnectivityCardElement.prototype.activeGuidChanged_, }, isActive: { type: Boolean, - observer: 'isActiveChanged_', + observer: ConnectivityCardElement.prototype.isActiveChanged_, }, network: { @@ -135,9 +134,7 @@ this.macAddress_ = network.macAddress || ''; if (this.testSuiteStatus === TestSuiteStatus.NOT_RUNNING) { - const isArcEnabled = - loadTimeData.getBoolean('enableArcNetworkDiagnostics'); - this.routineGroups_ = getRoutineGroups(network.type, isArcEnabled); + this.routineGroups_ = getRoutineGroups(network.type); this.getRoutineSectionElem_().runTests(); }
diff --git a/ash/webui/diagnostics_ui/resources/diagnostics_utils.ts b/ash/webui/diagnostics_ui/resources/diagnostics_utils.ts index 89cf0163..005022e 100644 --- a/ash/webui/diagnostics_ui/resources/diagnostics_utils.ts +++ b/ash/webui/diagnostics_ui/resources/diagnostics_utils.ts
@@ -104,12 +104,12 @@ return {routine, blocking}; } -export function getRoutineGroups( - type: NetworkType, isArcEnabled: boolean): RoutineGroup[] { +export function getRoutineGroups(type: NetworkType): RoutineGroup[] { const localNetworkGroup = new RoutineGroup( [ createRoutine(RoutineType.kGatewayCanBePinged, false), createRoutine(RoutineType.kLanConnectivity, true), + createRoutine(RoutineType.kArcPing, false), ], 'localNetworkGroupLabel'); @@ -118,6 +118,7 @@ createRoutine(RoutineType.kDnsResolverPresent, true), createRoutine(RoutineType.kDnsResolution, true), createRoutine(RoutineType.kDnsLatency, true), + createRoutine(RoutineType.kArcDnsResolution, false), ], 'nameResolutionGroupLabel'); @@ -133,18 +134,10 @@ createRoutine(RoutineType.kHttpsFirewall, true), createRoutine(RoutineType.kHttpFirewall, true), createRoutine(RoutineType.kHttpsLatency, true), + createRoutine(RoutineType.kArcHttp, false), ], 'internetConnectivityGroupLabel'); - if (isArcEnabled) { - // Add ARC routines to their corresponding groups. - nameResolutionGroup.addRoutine( - (createRoutine(RoutineType.kArcDnsResolution, false))); - localNetworkGroup.addRoutine((createRoutine(RoutineType.kArcPing, false))); - internetConnectivityGroup.addRoutine( - (createRoutine(RoutineType.kArcHttp, false))); - } - const groupsToAdd = type === NetworkType.kWiFi ? [wifiGroup, internetConnectivityGroup] : [internetConnectivityGroup]; @@ -187,10 +180,6 @@ return pieces.join('.'); } -export function isNavEnabled(): boolean { - return loadTimeData.getBoolean('isNetworkingEnabled'); -} - export function formatMacAddress(macAddress: string): string { return `${loadTimeData.getString('macAddressLabel')}: ${macAddress}`;
diff --git a/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.js b/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.js index 0f319c51..61b8458 100644 --- a/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.js +++ b/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.js
@@ -11,7 +11,6 @@ import {assert} from 'chrome://resources/ash/common/assert.js'; import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {isNavEnabled} from './diagnostics_utils.js'; import {getTemplate} from './realtime_cpu_chart.html.js'; /** @@ -187,9 +186,8 @@ updateChartWidth_() { // parseFloat() is used to convert the string returned by // getComputedStyleValue() into a number ("642px" --> 642). - const chartVar = isNavEnabled() ? '--chart-width-nav' : '--chart-width'; - this.width_ = - parseFloat(window.getComputedStyle(this).getPropertyValue(chartVar)); + this.width_ = parseFloat( + window.getComputedStyle(this).getPropertyValue('--chart-width-nav')); } /**
diff --git a/ash/webui/diagnostics_ui/resources/system_page.html b/ash/webui/diagnostics_ui/resources/system_page.html index c0a24e0..8896fca 100644 --- a/ash/webui/diagnostics_ui/resources/system_page.html +++ b/ash/webui/diagnostics_ui/resources/system_page.html
@@ -1,23 +1,4 @@ <style include="cr-shared-style diagnostics-shared"> - #banner { - align-items: center; - background-color: var(--google-blue-50); - display: flex; - height: 56px; - position: sticky; - top: 0; - width: 100vw; - z-index: 1; - } - - #bannerIcon { - --iron-icon-height: 20px; - --iron-icon-width: 20px; - fill: var(--cros-icon-color-prominent); - padding-inline-end: 16px; - padding-inline-start: 40px; - } - #diagnosticsContainer { align-items: center; box-sizing: border-box; @@ -34,10 +15,6 @@ right: 4px; } - .elevation-2 { - box-shadow: var(--diagnostics-box-shadow-elevation-2); - } - #header { align-self: flex-start; color: var(--cros-text-color-primary); @@ -64,17 +41,10 @@ } </style> <div id="diagnosticsContainer" hidden="[[!systemInfoReceived_]]"> - <div id="header" hidden$="[[isNetworkingEnabled]]"> - [[i18n('diagnosticsTitle')]] - </div> - <div id="banner" hidden="[[!bannerMessage]]" class$="[[scrollingClass_]]"> - <iron-icon icon="diagnostics:info" id="bannerIcon"></iron-icon> - <span id="bannerMsg" class="diagnostics-caution-banner-font">[[bannerMessage]]</span> - </div> <div class="overview-container"> <overview-card id="overviewCard"></overview-card> </div> - <div class$="[[getCardContainerClass_(isNetworkingEnabled)]]"> + <div class$="diagnostics-cards-container-nav"> <template is="dom-if" if="[[showBatteryStatusCard_]]" restamp> <div class="card-width"> <battery-status-card id="batteryStatusCard" @@ -96,15 +66,6 @@ </memory-card> </div> </div> - <template is="dom-if" if="[[!isNetworkingEnabled]]"> - <div class="session-log-container"> - <cr-button on-click="onSessionLogClick_" class="session-log-button" - disabled="[[!saveSessionLogEnabled_]]" hidden="[[!isLoggedIn_]]"> - <iron-icon icon="diagnostics:download" id="download-icon"></iron-icon> - <span>[[i18n('sessionLog')]]</span> - </cr-button> - </div> - </template> <cr-toast id="toast" duration="2500"> <span>[[toastText_]]</span> </cr-toast>
diff --git a/ash/webui/diagnostics_ui/resources/system_page.ts b/ash/webui/diagnostics_ui/resources/system_page.ts index ed5eead..12f68e1 100644 --- a/ash/webui/diagnostics_ui/resources/system_page.ts +++ b/ash/webui/diagnostics_ui/resources/system_page.ts
@@ -20,7 +20,6 @@ import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {DiagnosticsBrowserProxyImpl} from './diagnostics_browser_proxy.js'; -import {ShowCautionBannerEvent} from './diagnostics_sticky_banner.js'; import {getSystemDataProvider} from './mojo_interface_provider.js'; import {OverviewCardElement} from './overview_card.js'; import {TestSuiteStatus} from './routine_list_executor.js'; @@ -82,45 +81,21 @@ value: loadTimeData.getBoolean('isLoggedIn'), }, - bannerMessage: { - type: String, - value: '', - }, - - scrollingClass_: { - type: String, - value: '', - }, - - scrollTimerId_: { - type: Number, - value: -1, - }, - isActive: { type: Boolean, value: true, }, - isNetworkingEnabled: { - type: Boolean, - value: loadTimeData.getBoolean('isNetworkingEnabled'), - }, - }; } testSuiteStatus: TestSuiteStatus; - bannerMessage: string; isActive: boolean; - isNetworkingEnabled: boolean; protected systemInfoReceived_: boolean; protected saveSessionLogEnabled_: boolean; private showBatteryStatusCard_: boolean; private toastText_: string; private isLoggedIn_: boolean; - private scrollingClass_: string; - private scrollTimerId_: number; private systemDataProvider_: SystemDataProviderInterface = getSystemDataProvider(); private browserProxy_: DiagnosticsBrowserProxyImpl = @@ -130,11 +105,6 @@ super(); this.fetchSystemInfo_(); this.browserProxy_.initialize(); - - // Only use inner banner behavior if system page is in stand-alone mode. - if (!this.isNetworkingEnabled) { - this.addCautionBannerEventListeners_(); - } } private fetchSystemInfo_(): void { @@ -176,35 +146,6 @@ }); } - private addCautionBannerEventListeners_(): void { - window.addEventListener('show-caution-banner', (e) => { - const event = e as ShowCautionBannerEvent; - assert(event.detail.message); - this.bannerMessage = event.detail.message; - }); - - window.addEventListener('dismiss-caution-banner', () => { - this.bannerMessage = ''; - }); - - window.addEventListener('scroll', () => { - if (!this.bannerMessage) { - return; - } - - // Reset timer since we've received another 'scroll' event. - if (this.scrollTimerId_ !== -1) { - this.scrollingClass_ = 'elevation-2'; - clearTimeout(this.scrollTimerId_); - } - - // Remove box shadow from banner since the user has stopped scrolling - // for at least 300ms. - this.scrollTimerId_ = - window.setTimeout(() => this.scrollingClass_ = '', 300); - }); - } - /** * 'navigation-view-panel' is responsible for calling this function when * the active page changes. @@ -225,11 +166,6 @@ this.browserProxy_.recordNavigation('system'); } } - - protected getCardContainerClass_(): string { - const cardContainer = 'diagnostics-cards-container'; - return `${cardContainer}${this.isNetworkingEnabled ? '-nav' : ''}`; - } } customElements.define(SystemPageElement.is, SystemPageElement);
diff --git a/ash/webui/firmware_update_ui/resources/firmware_update_dialog.js b/ash/webui/firmware_update_ui/resources/firmware_update_dialog.js index ceacb8dc..1b4647011 100644 --- a/ash/webui/firmware_update_ui/resources/firmware_update_dialog.js +++ b/ash/webui/firmware_update_ui/resources/firmware_update_dialog.js
@@ -65,7 +65,7 @@ installationProgress: { type: Object, value: {percentage: 0, state: UpdateState.kIdle}, - observer: 'progressChanged_', + observer: FirmwareUpdateDialogElement.prototype.progressChanged_, }, /** @private {boolean} */
diff --git a/ash/webui/network_ui/network_diagnostics_resource_provider.cc b/ash/webui/network_ui/network_diagnostics_resource_provider.cc index cceab7bcd..8180cff 100644 --- a/ash/webui/network_ui/network_diagnostics_resource_provider.cc +++ b/ash/webui/network_ui/network_diagnostics_resource_provider.cc
@@ -4,7 +4,6 @@ #include "ash/webui/network_ui/network_diagnostics_resource_provider.h" -#include "ash/constants/ash_features.h" #include "chromeos/strings/grit/chromeos_strings.h" #include "content/public/browser/web_ui_data_source.h" #include "ui/base/webui/web_ui_util.h" @@ -156,9 +155,6 @@ void AddResources(content::WebUIDataSource* html_source) { html_source->AddLocalizedStrings(kLocalizedStrings); - html_source->AddBoolean( - "enableArcNetworkDiagnostics", - ash::features::IsArcNetworkDiagnosticsButtonEnabled()); for (const auto& resource : kResources) html_source->AddResourcePath(resource.name, resource.id);
diff --git a/ash/webui/os_feedback_ui/resources/share_data_page.js b/ash/webui/os_feedback_ui/resources/share_data_page.js index bbcb11727..59abb513 100644 --- a/ash/webui/os_feedback_ui/resources/share_data_page.js +++ b/ash/webui/os_feedback_ui/resources/share_data_page.js
@@ -47,7 +47,7 @@ type: FeedbackContext, readOnly: false, notify: true, - observer: 'onFeedbackContextChanged_', + observer: ShareDataPageElement.prototype.onFeedbackContextChanged_, }, screenshotUrl: {type: String, readOnly: false, notify: true},
diff --git a/ash/webui/personalization_app/resources/js/theme/dynamic_color_element.ts b/ash/webui/personalization_app/resources/js/theme/dynamic_color_element.ts index 07f0745..7ce3b55 100644 --- a/ash/webui/personalization_app/resources/js/theme/dynamic_color_element.ts +++ b/ash/webui/personalization_app/resources/js/theme/dynamic_color_element.ts
@@ -125,6 +125,8 @@ } automaticSeedColorEnabled: boolean; + private previousStaticColorSelected_: SkColor|null; + private previousColorSchemeSelected_: ColorScheme|null; private staticColorSelected_: SkColor|null; private colorSchemeSelected_: ColorScheme|null; private staticColors_: string[]; @@ -164,10 +166,14 @@ private onToggleChanged_() { if (this.automaticSeedColorEnabled) { - const staticColor = this.staticColorSelected_ || DEFAULT_STATIC_COLOR; + this.previousColorSchemeSelected_ = this.colorSchemeSelected_; + const staticColor = + this.previousStaticColorSelected_ || DEFAULT_STATIC_COLOR; setStaticColorPref(staticColor, getThemeProvider(), this.getStore()); } else { - const colorScheme = this.colorSchemeSelected_ || DEFAULT_COLOR_SCHEME; + this.previousStaticColorSelected_ = this.staticColorSelected_; + const colorScheme = + this.previousColorSchemeSelected_ || DEFAULT_COLOR_SCHEME; setColorSchemePref(colorScheme, getThemeProvider(), this.getStore()); } }
diff --git a/ash/webui/shortcut_customization_ui/resources/index.html b/ash/webui/shortcut_customization_ui/resources/index.html index 4b5fb1bd..2bcc39c 100644 --- a/ash/webui/shortcut_customization_ui/resources/index.html +++ b/ash/webui/shortcut_customization_ui/resources/index.html
@@ -7,6 +7,10 @@ <title></title> <meta charset="utf-8"> <style> + html { + background-color: var(--cros-bg-color); + } + body { margin: 0; }
diff --git a/ash/webui/shortcut_customization_ui/resources/js/input_key.html b/ash/webui/shortcut_customization_ui/resources/js/input_key.html index 222a906..80c07b6 100644 --- a/ash/webui/shortcut_customization_ui/resources/js/input_key.html +++ b/ash/webui/shortcut_customization_ui/resources/js/input_key.html
@@ -3,7 +3,6 @@ align-items: center; border-radius: 5px; box-sizing: border-box; - color: var(--cros-text-color-secondary); display: flex; font-weight: 500; height: 28px; @@ -13,6 +12,10 @@ padding-inline: 8px; } + #key-text { + color: var(--cros-text-color-secondary); + } + :host([key-state='not-selected']) .key-container { border-color: var(--google-grey-200); border-style: solid; @@ -21,15 +24,15 @@ } :host([key-state='modifier-selected']) .key-container { - background-color: var(--google-blue-50); + background-color: var(--cros-highlight-color); border: none; - box-shadow: 0 1px 1px var(--google-blue-50); + box-shadow: 0 1px 1px var(--cros-highlight-color); } :host([key-state='alpha-numeric-selected']) .key-container { - background-color: var(--google-grey-100); + background-color: var(--cros-bg-color-dropped-elevation-1); border: none; - box-shadow: 0 1px 1px var(--google-grey-100); + box-shadow: 0 1px 1px var(--cros-bg-color-dropped-elevation-1); } :host(#ctrlKey) .key-container,
diff --git a/ash/webui/shortcut_customization_ui/resources/js/shortcut_customization_app.html b/ash/webui/shortcut_customization_ui/resources/js/shortcut_customization_app.html index 5d4490e..060ff895 100644 --- a/ash/webui/shortcut_customization_ui/resources/js/shortcut_customization_app.html +++ b/ash/webui/shortcut_customization_ui/resources/js/shortcut_customization_app.html
@@ -23,14 +23,14 @@ #keyboardSettingsLinkContainer a { align-items: center; - color: var(--cros-text-color-secondary); + color: var(--cros-link-color); display: flex; font-weight: var(--shortcuts-font-weight-medium); text-decoration: none; } #keyboardSettingsLinkContainer a iron-icon { - fill: var(--cros-text-color-secondary); + fill: var(--cros-link-color); margin-inline-start: 4px; }
diff --git a/ash/wm/float/COMMON_METADATA b/ash/wm/float/COMMON_METADATA new file mode 100644 index 0000000..81be4693 --- /dev/null +++ b/ash/wm/float/COMMON_METADATA
@@ -0,0 +1,10 @@ +team_email: "chromeos-wm-corexp@google.com" +buganizer: { + component_id:1252568 +} +buganizer_public: { + component_id:1253054 +} +monorail { + component: "UI>Shell>WindowManager>FloatingWindow" +} \ No newline at end of file
diff --git a/ash/wm/float/DIR_METADATA b/ash/wm/float/DIR_METADATA index c1b5a4b..1ecfe34 100644 --- a/ash/wm/float/DIR_METADATA +++ b/ash/wm/float/DIR_METADATA
@@ -1,10 +1 @@ -team_email: "chromeos-wm-corexp@google.com" -buganizer: { - component_id:1252568 -} -buganizer_public: { - component_id:1253054 -} -monorail { - component: "UI>Shell>WindowManager>FloatingWindow" -} +mixins: "//ash/wm/float/COMMON_METADATA"
diff --git a/ash/wm/float/OWNERS b/ash/wm/float/OWNERS index fe8e5fb..3ec8fe5 100644 --- a/ash/wm/float/OWNERS +++ b/ash/wm/float/OWNERS
@@ -1 +1,2 @@ +sammiequon@chromium.org shidi@chromium.org
diff --git a/ash/wm/tablet_mode/OWNERS b/ash/wm/tablet_mode/OWNERS index 2656212c..34200d8 100644 --- a/ash/wm/tablet_mode/OWNERS +++ b/ash/wm/tablet_mode/OWNERS
@@ -1 +1,3 @@ xdai@chromium.org + +per-file *multitask*=file://ash/wm/float/OWNERS
diff --git a/base/values.cc b/base/values.cc index 0f64764..0d7e0e5 100644 --- a/base/values.cc +++ b/base/values.cc
@@ -218,20 +218,6 @@ Value::Value(List&& value) noexcept : data_(std::move(value)) {} -Value::Value(const LegacyDictStorage& storage) - : data_(absl::in_place_type_t<Dict>()) { - dict().reserve(storage.size()); - for (const auto& it : storage) { - dict().try_emplace(dict().end(), it.first, - std::make_unique<Value>(it.second->Clone())); - } -} - -Value::Value(LegacyDictStorage&& storage) noexcept - : data_(absl::in_place_type_t<Dict>()) { - dict() = std::move(storage); -} - Value::Value(absl::monostate) {} Value::Value(DoubleStorage storage) : data_(std::move(storage)) {} @@ -1595,12 +1581,6 @@ DictionaryValue::DictionaryValue() : Value(Type::DICTIONARY) {} -DictionaryValue::DictionaryValue(const LegacyDictStorage& storage) - : Value(storage) {} - -DictionaryValue::DictionaryValue(LegacyDictStorage&& storage) noexcept - : Value(std::move(storage)) {} - Value* DictionaryValue::Set(StringPiece path, std::unique_ptr<Value> in_value) { DCHECK(IsStringUTF8AllowingNoncharacters(path)); DCHECK(in_value);
diff --git a/base/values.h b/base/values.h index 8929779..1d0effd 100644 --- a/base/values.h +++ b/base/values.h
@@ -1093,10 +1093,6 @@ const ListStorage& list() const { return GetList().storage_; } ListStorage& list() { return GetList().storage_; } - // Internal constructors, allowing the simplify the implementation of Clone(). - explicit Value(const LegacyDictStorage& storage); - explicit Value(LegacyDictStorage&& storage) noexcept; - private: // For access to DoubleStorage. friend class ValueView; @@ -1255,8 +1251,6 @@ static std::unique_ptr<DictionaryValue> From(std::unique_ptr<Value> value); DictionaryValue(); - explicit DictionaryValue(const LegacyDictStorage& in_dict); - explicit DictionaryValue(LegacyDictStorage&& in_dict) noexcept; // Sets the Value associated with the given path starting from this object. // A path has the form "<key>" or "<key>.<key>.[...]", where "." indexes
diff --git a/build/android/pylib/local/emulator/avd.py b/build/android/pylib/local/emulator/avd.py index 45baea5..8e61a98 100644 --- a/build/android/pylib/local/emulator/avd.py +++ b/build/android/pylib/local/emulator/avd.py
@@ -357,6 +357,29 @@ def _features_ini_path(self): return os.path.join(self.emulator_home, 'advancedFeatures.ini') + @property + def xdg_config_dir(self): + """The base directory to store qt config file. + + This dir should be added to the env variable $XDG_CONFIG_DIRS so that + _qt_config_path can take effect. See https://bit.ly/3HIQRZ3 for context. + """ + config_dir = os.path.join(self.emulator_home, '.config') + if not os.path.exists(config_dir): + os.makedirs(config_dir) + + return config_dir + + @property + def _qt_config_path(self): + """The qt config file for emulator.""" + qt_config_dir = os.path.join(self.xdg_config_dir, + 'Android Open Source Project') + if not os.path.exists(qt_config_dir): + os.makedirs(qt_config_dir) + + return os.path.join(qt_config_dir, 'Emulator.conf') + def HasSnapshot(self, snapshot_name): """Check if a given snapshot exists or not.""" snapshot_path = os.path.join(self._avd_dir, 'snapshots', snapshot_name) @@ -731,16 +754,17 @@ * Emulator instance can be booted correctly. * The snapshot can be loaded successfully. """ + logging.info('Updating AVD configurations.') # Update the absolute avd path in root_ini file with ini.update_ini_file(self._root_ini_path) as r_ini_contents: r_ini_contents['path'] = self._avd_dir # Update hardware settings. - config_files = [self._config_ini_path] + config_paths = [self._config_ini_path] # The file hardware.ini within each snapshot need to be updated as well. hw_ini_glob_pattern = os.path.join(self._avd_dir, 'snapshots', '*', 'hardware.ini') - config_files.extend(glob.glob(hw_ini_glob_pattern)) + config_paths.extend(glob.glob(hw_ini_glob_pattern)) properties = {} # Update hw.sdCard.path if applicable @@ -748,10 +772,14 @@ if os.path.exists(sdcard_path): properties['hw.sdCard.path'] = sdcard_path - for config_file in config_files: - with ini.update_ini_file(config_file) as config_contents: + for config_path in config_paths: + with ini.update_ini_file(config_path) as config_contents: config_contents.update(properties) + # Create qt config file to disable adb warning when launched in window mode. + with ini.update_ini_file(self._qt_config_path) as config_contents: + config_contents['set'] = {'autoFindAdb': 'false'} + def _Initialize(self): if self._initialized: return @@ -882,9 +910,9 @@ emulator_env = { # kill immediately when emulator hang. 'ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL': '0', + # Sets the emulator configuration directory + 'ANDROID_EMULATOR_HOME': self._emulator_home, } - if self._emulator_home: - emulator_env['ANDROID_EMULATOR_HOME'] = self._emulator_home if 'DISPLAY' in os.environ: emulator_env['DISPLAY'] = os.environ.get('DISPLAY') if window: @@ -893,6 +921,12 @@ else: emulator_cmd.append('-no-window') + # Need this for the qt config file to take effect. + xdg_config_dirs = [self._avd_config.xdg_config_dir] + if 'XDG_CONFIG_DIRS' in os.environ: + xdg_config_dirs.append(os.environ.get('XDG_CONFIG_DIRS')) + emulator_env['XDG_CONFIG_DIRS'] = ':'.join(xdg_config_dirs) + sock.listen(1) logging.info('Starting emulator...')
diff --git a/build/android/pylib/local/emulator/ini.py b/build/android/pylib/local/emulator/ini.py index 396874a..79eb015 100644 --- a/build/android/pylib/local/emulator/ini.py +++ b/build/android/pylib/local/emulator/ini.py
@@ -2,22 +2,59 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Basic .ini encoding and decoding.""" +"""Basic .ini encoding and decoding. + +The basic element in an ini file is the key. Every key is constructed by a name +and a value, delimited by an equals sign (=). + +Keys may be grouped into sections. The secetion name will be a line by itself, +in square brackets ([ and ]). All keys after the section are associated with +that section until another section occurs. + +Keys that are not under any section are considered at the top level. + +Section and key names are case sensitive. +""" import contextlib import os +def add_key(line, config, strict=True): + key, val = line.split('=', 1) + key = key.strip() + val = val.strip() + if strict and key in config: + raise ValueError('Multiple entries present for key "%s"' % key) + config[key] = val + + def loads(ini_str, strict=True): + """Deserialize int_str to a dict (nested dict when has sections) object. + + Duplicated sections will merge their keys. + + When there are multiple entries for a key, at the top level, or under the + same section: + - If strict is true, ValueError will be raised. + - If strict is false, only the last occurrence will be stored. + """ ret = {} + section = None for line in ini_str.splitlines(): - key, val = line.split('=', 1) - key = key.strip() - val = val.strip() - if strict and key in ret: - raise ValueError('Multiple entries present for key "%s"' % key) - ret[key] = val + # Empty line + if not line: + continue + # Section line + if line[0] == '[' and line[-1] == ']': + section = line[1:-1] + if section not in ret: + ret[section] = {} + # Key line + else: + config = ret if section is None else ret[section] + add_key(line, config, strict=strict) return ret @@ -27,10 +64,20 @@ def dumps(obj): - ret = '' + results = [] + key_str = '' + for k, v in sorted(obj.items()): - ret += '%s = %s\n' % (k, str(v)) - return ret + if isinstance(v, dict): + results.append('[%s]\n' % k + dumps(v)) + else: + key_str += '%s = %s\n' % (k, str(v)) + + # Insert key_str at the first position, before any sections + if key_str: + results.insert(0, key_str) + + return '\n'.join(results) def dump(obj, fp): @@ -46,11 +93,10 @@ Yields: The contents of the file, as a dict """ + ini_contents = {} if os.path.exists(ini_file_path): with open(ini_file_path) as ini_file: ini_contents = load(ini_file) - else: - ini_contents = {} yield ini_contents
diff --git a/build/android/pylib/local/emulator/ini_test.py b/build/android/pylib/local/emulator/ini_test.py index 752a835..327d6bf7 100755 --- a/build/android/pylib/local/emulator/ini_test.py +++ b/build/android/pylib/local/emulator/ini_test.py
@@ -5,9 +5,13 @@ """Tests for ini.py.""" +import os +import sys import textwrap import unittest +sys.path.append( + os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))) from pylib.local.emulator import ini @@ -17,15 +21,35 @@ foo.bar = 1 foo.baz= example bar.bad =/path/to/thing + + [section_1] + foo.bar = 1 + foo.baz= example + + [section_2] + foo.baz= example + bar.bad =/path/to/thing + + [section_1] + bar.bad =/path/to/thing """) expected = { 'foo.bar': '1', 'foo.baz': 'example', 'bar.bad': '/path/to/thing', + 'section_1': { + 'foo.bar': '1', + 'foo.baz': 'example', + 'bar.bad': '/path/to/thing', + }, + 'section_2': { + 'foo.baz': 'example', + 'bar.bad': '/path/to/thing', + }, } self.assertEqual(expected, ini.loads(ini_str)) - def testLoadsStrictFailure(self): + def testLoadsDuplicatedKeysStrictFailure(self): ini_str = textwrap.dedent("""\ foo.bar = 1 foo.baz = example @@ -35,17 +59,39 @@ with self.assertRaises(ValueError): ini.loads(ini_str, strict=True) + def testLoadsDuplicatedKeysInSectionStrictFailure(self): + ini_str = textwrap.dedent("""\ + [section_1] + foo.bar = 1 + foo.baz = example + bar.bad = /path/to/thing + foo.bar = duplicate + """) + with self.assertRaises(ValueError): + ini.loads(ini_str, strict=True) + def testLoadsPermissive(self): ini_str = textwrap.dedent("""\ foo.bar = 1 foo.baz = example bar.bad = /path/to/thing foo.bar = duplicate + + [section_1] + foo.bar = 1 + foo.baz = example + bar.bad = /path/to/thing + foo.bar = duplicate """) expected = { 'foo.bar': 'duplicate', 'foo.baz': 'example', 'bar.bad': '/path/to/thing', + 'section_1': { + 'foo.bar': 'duplicate', + 'foo.baz': 'example', + 'bar.bad': '/path/to/thing', + }, } self.assertEqual(expected, ini.loads(ini_str, strict=False)) @@ -54,13 +100,53 @@ 'foo.bar': '1', 'foo.baz': 'example', 'bar.bad': '/path/to/thing', + 'section_2': { + 'foo.baz': 'example', + 'bar.bad': '/path/to/thing', + }, + 'section_1': { + 'foo.bar': '1', + 'foo.baz': 'example', + }, } # ini.dumps is expected to dump to string alphabetically - # by key. + # by key and section name. expected = textwrap.dedent("""\ bar.bad = /path/to/thing foo.bar = 1 foo.baz = example + + [section_1] + foo.bar = 1 + foo.baz = example + + [section_2] + bar.bad = /path/to/thing + foo.baz = example + """) + self.assertEqual(expected, ini.dumps(ini_contents)) + + def testDumpsSections(self): + ini_contents = { + 'section_2': { + 'foo.baz': 'example', + 'bar.bad': '/path/to/thing', + }, + 'section_1': { + 'foo.bar': '1', + 'foo.baz': 'example', + }, + } + # ini.dumps is expected to dump to string alphabetically + # by key first, and then by section and the associated keys + expected = textwrap.dedent("""\ + [section_1] + foo.bar = 1 + foo.baz = example + + [section_2] + bar.bad = /path/to/thing + foo.baz = example """) self.assertEqual(expected, ini.dumps(ini_contents))
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index b2f7fc9..d272842 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -618,7 +618,7 @@ } } else if (is_win) { cflags_c += [ "/std:c11" ] - if (use_cxx17 || (is_clang && defined(msvc_use_cxx17) && msvc_use_cxx17)) { + if (use_cxx17 || (!is_clang && defined(msvc_use_cxx17) && msvc_use_cxx17)) { cflags_cc += [ "/std:c++17" ] } else { cflags_cc += [ "/std:c++20" ]
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1 index 4cc1d84..80e2d539 100644 --- a/build/fuchsia/linux_internal.sdk.sha1 +++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@ -11.20221221.3.1 +11.20221222.0.1
diff --git a/chrome/VERSION b/chrome/VERSION index 96bd757..a66d22f 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=111 MINOR=0 -BUILD=5493 +BUILD=5494 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index d2175db..88ad8428 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -2628,6 +2628,7 @@ "java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationService.java", "java/src/org/chromium/chrome/browser/media/MediaCaptureNotificationService.java", "java/src/org/chromium/chrome/browser/media/ui/ChromeMediaNotificationControllerServices.java", + "java/src/org/chromium/chrome/browser/metrics/SimpleStartupForegroundSessionDetector.java", "java/src/org/chromium/chrome/browser/metrics/UmaUtils.java", "java/src/org/chromium/chrome/browser/notifications/NotificationJobService.java", "java/src/org/chromium/chrome/browser/notifications/NotificationService.java",
diff --git a/chrome/android/features/cablev2_authenticator/native/cablev2_authenticator_android.cc b/chrome/android/features/cablev2_authenticator/native/cablev2_authenticator_android.cc index 613a19d..9d85afb 100644 --- a/chrome/android/features/cablev2_authenticator/native/cablev2_authenticator_android.cc +++ b/chrome/android/features/cablev2_authenticator/native/cablev2_authenticator_android.cc
@@ -701,25 +701,25 @@ return ++global_data.instance_num; } -std::tuple<base::span<const uint8_t, device::kP256X962Length>, - base::span<const uint8_t, device::cablev2::kQRSecretSize>, +std::tuple<std::array<uint8_t, device::kP256X962Length>, + std::array<uint8_t, device::cablev2::kQRSecretSize>, std::array<uint8_t, device::cablev2::kTunnelIdSize>> ParseServerLinkData(JNIEnv* env, const JavaParamRef<jbyteArray>& server_link_data_java) { - constexpr size_t kDataSize = - device::kP256X962Length + device::cablev2::kQRSecretSize; - const std::vector<uint8_t> server_link_data_vec = + const std::vector<uint8_t> server_link_data = JavaByteArrayToByteVector(env, server_link_data_java); // validateServerLinkData should have been called to check this already. - CHECK_EQ(server_link_data_vec.size(), kDataSize); - base::span<const uint8_t> server_link_data = - base::make_span(server_link_data_vec); + CHECK_EQ(server_link_data.size(), + device::kP256X962Length + device::cablev2::kQRSecretSize); - const base::span<const uint8_t, device::kP256X962Length> peer_identity = - server_link_data.subspan<0, device::kP256X962Length>(); - const base::span<const uint8_t, device::cablev2::kQRSecretSize> qr_secret = - server_link_data - .subspan<device::kP256X962Length, device::cablev2::kQRSecretSize>(); + std::array<uint8_t, device::kP256X962Length> peer_identity; + memcpy(peer_identity.data(), server_link_data.data(), + device::kP256X962Length); + + std::array<uint8_t, device::cablev2::kQRSecretSize> qr_secret; + memcpy(qr_secret.data(), server_link_data.data() + device::kP256X962Length, + device::cablev2::kQRSecretSize); + const std::array<uint8_t, device::cablev2::kTunnelIdSize> tunnel_id = device::cablev2::Derive<device::cablev2::kTunnelIdSize>( qr_secret, base::span<uint8_t>(),
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 f0c023b..220e7ae 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -257,9 +257,6 @@ private static final String ACTION_CLOSE_TABS = "com.google.android.apps.chrome.ACTION_CLOSE_TABS"; - @VisibleForTesting - public static final String STARTUP_UMA_HISTOGRAM_SUFFIX = ".Tabbed"; - // Name of the ChromeTabbedActivity alias that handles MAIN intents. public static final String MAIN_LAUNCHER_ACTIVITY_NAME = "com.google.android.apps.chrome.Main"; @@ -1206,7 +1203,7 @@ assert getActivityTabStartupMetricsTracker() != null; if (shouldTrackColdStartupMetrics) { - getActivityTabStartupMetricsTracker().trackStartupMetrics(STARTUP_UMA_HISTOGRAM_SUFFIX); + getActivityTabStartupMetricsTracker().setHistogramSuffix(ActivityType.TABBED); } else { getActivityTabStartupMetricsTracker().cancelTrackingStartupMetrics(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java index be2eccc4..6f4a0c2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
@@ -82,7 +82,6 @@ add(ChromeFeatureList.sCctIncognitoAvailableToThirdParty); add(ChromeFeatureList.sCctRemoveRemoteViewIds); add(ChromeFeatureList.sCctResizable90MaximumHeight); - add(ChromeFeatureList.sCctResizableAllowResizeByUserGesture); add(ChromeFeatureList.sCctResizableForThirdParties); add(ChromeFeatureList.sCctResizableSideSheet); add(ChromeFeatureList.sCctRetainableStateInMemory); @@ -142,6 +141,7 @@ add(BrandingController.BRANDING_CADENCE_MS); add(BrandingController.MAX_BLANK_TOOLBAR_TIMEOUT_MS); add(BrandingController.USE_TEMPORARY_STORAGE); + add(BrandingController.ANIMATE_TOOLBAR_ICON_TRANSITION); add(ChimeFeatures.ALWAYS_REGISTER); add(StartSurfaceConfiguration.BEHAVIOURAL_TARGETING); add(ConditionalTabStripUtils.CONDITIONAL_TAB_STRIP_INFOBAR_LIMIT);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHandleStrategy.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHandleStrategy.java index 6e6d757..80031c0e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHandleStrategy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHandleStrategy.java
@@ -15,7 +15,6 @@ import org.chromium.base.supplier.Supplier; import org.chromium.chrome.browser.customtabs.PartialCustomTabHeightStrategy.HeightStatus; import org.chromium.chrome.browser.customtabs.features.toolbar.CustomTabToolbar; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import java.util.function.BooleanSupplier; @@ -83,10 +82,6 @@ @Override public boolean onTouchEvent(MotionEvent event) { - if (!ChromeFeatureList.sCctResizableAllowResizeByUserGesture.isEnabled()) { - return false; - } - if (mStatus.get() == HeightStatus.TRANSITION) { return true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java index 2f9af2f2..d5e20b3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
@@ -759,6 +759,7 @@ private final Runnable[] mAfterBrandingRunnables = new Runnable[TOTAL_POST_BRANDING_KEYS]; private boolean mCurrentlyShowingBranding; private boolean mBrandingStarted; + private boolean mAnimateIconTransition = true; private CallbackController mCallbackController = new CallbackController(); // Cached the state before branding start so we can reset to the state when its done. private @Nullable Integer mPreBandingState; @@ -846,6 +847,11 @@ MIN_URL_BAR_VISIBLE_TIME_POST_BRANDING_MS); } + @Override + public void setIconTransitionEnabled(boolean enabled) { + mAnimateIconTransition = enabled; + } + private void cacheRegularState() { String assertMsg = "mPreBandingState already exists! mPreBandingState = " + mPreBandingState; @@ -1068,7 +1074,7 @@ ColorStateList colorStateList = AppCompatResources.getColorStateList( getContext(), mLocationBarDataProvider.getSecurityIconColorStateList()); ApiCompatibilityUtils.setImageTintList(mSecurityButton, colorStateList); - mAnimDelegate.updateSecurityButton(R.drawable.chromelogo16); + mAnimDelegate.updateSecurityButton(R.drawable.chromelogo16, mAnimateIconTransition); mUrlBar.setText(R.string.twa_running_in_chrome); } @@ -1099,7 +1105,7 @@ getContext(), mLocationBarDataProvider.getSecurityIconColorStateList()); ApiCompatibilityUtils.setImageTintList(mSecurityButton, colorStateList); } - mAnimDelegate.updateSecurityButton(securityIconResource); + mAnimDelegate.updateSecurityButton(securityIconResource, mAnimateIconTransition); int contentDescriptionId = mLocationBarDataProvider.getSecurityIconContentDescriptionResourceId();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarAnimationDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarAnimationDelegate.java index 174f2a3..eeae118 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarAnimationDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarAnimationDelegate.java
@@ -151,16 +151,16 @@ * @param securityIconResource The updated resource to be assigned to the security status icon. * When this is null, the icon is animated to the left and faded out. */ - void updateSecurityButton(@DrawableRes int securityIconResource) { - if (mUseRotationTransition) { + void updateSecurityButton(@DrawableRes int securityIconResource, boolean animate) { + if (mUseRotationTransition && animate) { mBrandingAnimationDelegate.updateDrawableResource(securityIconResource); } else { boolean isActualResourceChange = true; if (ToolbarFeatures.shouldSuppressCaptures()) { isActualResourceChange = securityIconResource != mSecurityIconRes; } - mSecurityButtonAnimationDelegate.updateSecurityButton(securityIconResource, - /*animate=*/true, isActualResourceChange); + mSecurityButtonAnimationDelegate.updateSecurityButton( + securityIconResource, animate, isActualResourceChange); } mSecurityIconRes = securityIconResource; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java index 487be0e..23ccc16 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java
@@ -21,6 +21,7 @@ import org.chromium.base.supplier.OneshotSupplierImpl; import org.chromium.chrome.browser.customtabs.CustomTabsConnection; import org.chromium.chrome.browser.init.AsyncInitializationActivity; +import org.chromium.chrome.browser.metrics.SimpleStartupForegroundSessionDetector; import org.chromium.chrome.browser.metrics.UmaUtils; import org.chromium.chrome.browser.policy.PolicyServiceFactory; import org.chromium.chrome.browser.profiles.ProfileManagerUtils; @@ -112,6 +113,7 @@ @Override public void onResume() { + SimpleStartupForegroundSessionDetector.discardSession(); super.onResume(); // Since the FRE may be shown before any tab is shown, mark that this is the point at which // Chrome went to foreground. Other activities can only
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java index 3f92ef9..f623997 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java
@@ -39,6 +39,7 @@ import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; +import org.chromium.chrome.browser.metrics.SimpleStartupForegroundSessionDetector; import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher; import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcherImpl; import org.chromium.chrome.browser.profiles.Profile; @@ -509,12 +510,14 @@ mIsWarmOnResume = !mFirstResumePending || hadWarmStart(); mFirstResumePending = false; + SimpleStartupForegroundSessionDetector.onTransitionToForeground(); mNativeInitializationController.onResume(); } @CallSuper @Override public void onPause() { + SimpleStartupForegroundSessionDetector.discardSession(); mNativeInitializationController.onPause(); super.onPause(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/ActivityTabStartupMetricsTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/ActivityTabStartupMetricsTracker.java index 7304945..f05a354 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/ActivityTabStartupMetricsTracker.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/ActivityTabStartupMetricsTracker.java
@@ -8,6 +8,7 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.supplier.ObservableSupplier; +import org.chromium.chrome.browser.flags.ActivityType; import org.chromium.chrome.browser.paint_preview.StartupPaintPreviewHelper; import org.chromium.chrome.browser.paint_preview.StartupPaintPreviewMetrics.PaintPreviewMetricsObserver; import org.chromium.chrome.browser.tab.Tab; @@ -26,7 +27,6 @@ * startup. */ public class ActivityTabStartupMetricsTracker { - private static final String UMA_HISTOGRAM_TABBED_SUFFIX = ".Tabbed"; private static final String FIRST_COMMIT_OCCURRED_PRE_FOREGROUND_HISTOGRAM = "Startup.Android.Cold.FirstNavigationCommitOccurredPreForeground"; private static final String FIRST_PAINT_OCCURRED_PRE_FOREGROUND_HISTOGRAM = @@ -60,10 +60,9 @@ // Event duration recorded from the |mActivityStartTimeMs|. private long mFirstCommitTimeMs; - private String mHistogramSuffix; + private @ActivityType int mHistogramSuffix; private TabModelSelectorTabObserver mTabModelSelectorTabObserver; private PageLoadMetricsObserverImpl mPageLoadMetricsObserver; - private UmaUtils.Observer mUmaUtilsObserver; private boolean mShouldTrackStartupMetrics; private boolean mFirstVisibleContentRecorded; private boolean mVisibleContentRecorded; @@ -85,7 +84,7 @@ public ActivityTabStartupMetricsTracker( ObservableSupplier<TabModelSelector> tabModelSelectorSupplier) { mActivityStartTimeMs = SystemClock.uptimeMillis(); - tabModelSelectorSupplier.addObserver((selector) -> registerObservers(selector)); + tabModelSelectorSupplier.addObserver(this::registerObservers); SafeBrowsingApiBridge.setOneTimeUrlCheckObserver(this::updateSafeBrowsingCheckTime); } @@ -93,6 +92,16 @@ mFirstSafeBrowsingResponseTimeMicros.compareAndSet(0, urlCheckTimeDeltaMicros); } + /** + * Choose the UMA histogram to record later. The {@link ActivityType} parameter indicates the + * kind of startup scenario to track. Only two scenarios are supported. + * @param activityType Either TABBED or WEB_APK. + */ + public void setHistogramSuffix(@ActivityType int activityType) { + mHistogramSuffix = activityType; + mShouldTrackStartupMetrics = true; + } + // Note: In addition to returning false when startup metrics are not being tracked at all, this // method will also return false after first navigation commit has occurred. public boolean isTrackingStartupMetrics() { @@ -138,15 +147,14 @@ }; mPageLoadMetricsObserver = new PageLoadMetricsObserverImpl(); PageLoadMetrics.addObserver(mPageLoadMetricsObserver, false); - mUmaUtilsObserver = this::registerHasComeToForeground; - UmaUtils.addObserver(mUmaUtilsObserver); + UmaUtils.setObserver(this::registerHasComeToForegroundWithNative); } /** * Registers the fact that UmaUtils#hasComeToForeground() has just become true for the first * time. */ - private void registerHasComeToForeground() { + private void registerHasComeToForegroundWithNative() { // Record cases where first navigation commit and/or StartupPaintPreview's first // paint happened pre-foregrounding. if (mRegisteredFirstCommitPreForeground) { @@ -158,7 +166,7 @@ FIRST_PAINT_OCCURRED_PRE_FOREGROUND_HISTOGRAM, true); } - clearUmaUtilsObserver(); + UmaUtils.removeObserver(); } /** @@ -189,15 +197,6 @@ } /** - * Marks that startup metrics should be tracked with the |histogramSuffix|. - * Must only be called on the UI thread. - */ - public void trackStartupMetrics(String histogramSuffix) { - mHistogramSuffix = histogramSuffix; - mShouldTrackStartupMetrics = true; - } - - /** * Cancels tracking the startup metrics. * Must only be called on the UI thread. */ @@ -207,14 +206,13 @@ // Ensure we haven't tried to record metrics already. assert mFirstCommitTimeMs == 0; - mHistogramSuffix = null; mShouldTrackStartupMetrics = false; } public void destroy() { mShouldTrackStartupMetrics = false; clearNavigationObservers(); - clearUmaUtilsObserver(); + UmaUtils.removeObserver(); } private void clearNavigationObservers() { @@ -229,13 +227,6 @@ } } - private void clearUmaUtilsObserver() { - if (mUmaUtilsObserver != null) { - UmaUtils.removeObserver(mUmaUtilsObserver); - mUmaUtilsObserver = null; - } - } - /** * Registers the fact that a navigation has finished. Based on this fact, may discard recording * histograms later. @@ -247,9 +238,10 @@ && !UmaUtils.hasComeToBackgroundWithNative()) { mFirstCommitTimeMs = SystemClock.uptimeMillis() - mActivityStartTimeMs; RecordHistogram.recordMediumTimesHistogram( - "Startup.Android.Cold.TimeToFirstNavigationCommit" + mHistogramSuffix, + "Startup.Android.Cold.TimeToFirstNavigationCommit" + + activityTypeToSuffix(mHistogramSuffix), mFirstCommitTimeMs); - if (mHistogramSuffix.equals(UMA_HISTOGRAM_TABBED_SUFFIX)) { + if (mHistogramSuffix == ActivityType.TABBED) { recordFirstVisibleContent(mFirstCommitTimeMs); recordFirstSafeBrowsingResponseTime(); } @@ -260,9 +252,21 @@ mRegisteredFirstCommitPreForeground = true; } + if (mHistogramSuffix == ActivityType.TABBED && isTrackedPage + && SimpleStartupForegroundSessionDetector.runningCleanForegroundSession()) { + RecordHistogram.recordMediumTimesHistogram( + "Startup.Android.Cold.TimeToFirstNavigationCommit2.Tabbed", mFirstCommitTimeMs); + } + mShouldTrackStartupMetrics = false; } + private String activityTypeToSuffix(@ActivityType int type) { + if (type == ActivityType.TABBED) return ".Tabbed"; + assert type == ActivityType.WEB_APK; + return ".WebApk"; + } + private void recordFirstSafeBrowsingResponseTime() { long deltaMicros = mFirstSafeBrowsingResponseTimeMicros.getAndSet(0); if (deltaMicros == 0) return; @@ -283,9 +287,10 @@ if (UmaUtils.hasComeToForegroundWithNative() && !UmaUtils.hasComeToBackgroundWithNative()) { long durationMs = firstContentfulPaintMs - mActivityStartTimeMs; RecordHistogram.recordMediumTimesHistogram( - "Startup.Android.Cold.TimeToFirstContentfulPaint" + mHistogramSuffix, + "Startup.Android.Cold.TimeToFirstContentfulPaint" + + activityTypeToSuffix(mHistogramSuffix), durationMs); - if (mHistogramSuffix.equals(UMA_HISTOGRAM_TABBED_SUFFIX)) { + if (mHistogramSuffix == ActivityType.TABBED) { recordVisibleContent(durationMs); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/SimpleStartupForegroundSessionDetector.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/SimpleStartupForegroundSessionDetector.java new file mode 100644 index 0000000..ca48f6fc --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/SimpleStartupForegroundSessionDetector.java
@@ -0,0 +1,34 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.metrics; + +/** + * Determines whether the browsing session early at startup is good enough for startup metrics. + * Transitioning the activity to background would recommend omitting the metrics because of + * background restrictions and throttling. Must be subscribed to pause/resume events. + */ +public class SimpleStartupForegroundSessionDetector { + private static boolean sSessionDiscarded; + private static boolean sReachedForeground; + + public static void onTransitionToForeground() { + if (sReachedForeground) { + sSessionDiscarded = true; + return; + } + sReachedForeground = true; + } + + public static void discardSession() { + sSessionDiscarded = true; + } + + /** + * @return whether the startup happened cleanly in the foreground. + */ + public static boolean runningCleanForegroundSession() { + return sReachedForeground && !sSessionDiscarded; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaUtils.java index 087d6ae..1d5ca72 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaUtils.java
@@ -14,7 +14,6 @@ import androidx.annotation.IntDef; import org.chromium.base.ContextUtils; -import org.chromium.base.ObserverList; import org.chromium.base.ThreadUtils; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; @@ -30,25 +29,25 @@ /** Observer for this class. */ public interface Observer { /** - * Called when hasComeToForeground() changes from false to true. + * Called when hasComeToForeground() changes from false to true for the first time after + * post-native initialization has started. */ - void onHasComeToForeground(); + void onHasComeToForegroundWithNative(); } - private static ObserverList<Observer> sObservers; + private static Observer sObserver; - /** Adds an observer. */ - public static boolean addObserver(Observer observer) { + /** Sets the observer. */ + public static void setObserver(Observer observer) { ThreadUtils.assertOnUiThread(); - if (sObservers == null) sObservers = new ObserverList<>(); - return sObservers.addObserver(observer); + assert sObserver == null; + sObserver = observer; } - /** Removes an observer. */ - public static boolean removeObserver(Observer observer) { + /** Removes the observer. */ + public static void removeObserver() { ThreadUtils.assertOnUiThread(); - if (sObservers == null) return false; - return sObservers.removeObserver(observer); + sObserver = null; } // All these values originate from SystemClock.uptimeMillis(). @@ -113,10 +112,8 @@ // Chrome has been sent to background since the last foreground time. if (sForegroundStartWithNativeTimeMs == 0 || sForegroundStartWithNativeTimeMs < sBackgroundWithNativeTimeMs) { - if (sObservers != null && sForegroundStartWithNativeTimeMs == 0) { - for (Observer observer : sObservers) { - observer.onHasComeToForeground(); - } + if (sObserver != null && sForegroundStartWithNativeTimeMs == 0) { + sObserver.onHasComeToForegroundWithNative(); } sForegroundStartWithNativeTimeMs = SystemClock.uptimeMillis(); } @@ -254,9 +251,6 @@ @CalledByNative public static long getProcessStartTime() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - return 0; - } return ApiHelperForN.getStartUptimeMillis(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivityLifecycleUmaTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivityLifecycleUmaTracker.java index e7fbad7..f3c2e36f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivityLifecycleUmaTracker.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivityLifecycleUmaTracker.java
@@ -11,8 +11,6 @@ import android.os.Bundle; import android.os.SystemClock; -import androidx.annotation.VisibleForTesting; - import org.chromium.base.ActivityState; import org.chromium.base.ApplicationStatus; import org.chromium.base.ApplicationStatus.ActivityStateListener; @@ -25,6 +23,7 @@ import org.chromium.chrome.browser.browserservices.metrics.WebApkUmaRecorder; import org.chromium.chrome.browser.browserservices.ui.splashscreen.SplashController; import org.chromium.chrome.browser.dependency_injection.ActivityScope; +import org.chromium.chrome.browser.flags.ActivityType; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.lifecycle.InflationObserver; import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver; @@ -42,9 +41,6 @@ @ActivityScope public class WebApkActivityLifecycleUmaTracker implements ActivityStateListener, InflationObserver, PauseResumeWithNativeObserver { - @VisibleForTesting - public static final String STARTUP_UMA_HISTOGRAM_SUFFIX = ".WebApk"; - private final Activity mActivity; private final BrowserServicesIntentDataProvider mIntentDataProvider; private final SplashController mSplashController; @@ -93,7 +89,7 @@ // Decide whether to record startup UMA histograms. This is a similar check to the one done // in ChromeTabbedActivity.performPreInflationStartup refer to the comment there for why. if (!LibraryLoader.getInstance().isInitialized()) { - mStartupMetricsTracker.get().trackStartupMetrics(STARTUP_UMA_HISTOGRAM_SUFFIX); + mStartupMetricsTracker.get().setHistogramSuffix(ActivityType.WEB_APK); // If there is a saved instance state, then the intent (and its stored timestamp) might // be stale (Android replays intents if there is a recents entry for the activity). if (mSavedInstanceStateSupplier.get() == null) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java index 455405e..fabcfe5d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java
@@ -28,10 +28,8 @@ import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.JniMocker; -import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.webapps.WebApkActivityLifecycleUmaTracker; import org.chromium.chrome.browser.webapps.WebApkActivityTestRule; import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; @@ -55,6 +53,8 @@ private static final String SLOW_PAGE = "/slow?2"; private static final String FIRST_COMMIT_HISTOGRAM = "Startup.Android.Cold.TimeToFirstNavigationCommit"; + private static final String FIRST_COMMIT_HISTOGRAM2 = + "Startup.Android.Cold.TimeToFirstNavigationCommit2.Tabbed"; private static final String FIRST_CONTENTFUL_PAINT_HISTOGRAM = "Startup.Android.Cold.TimeToFirstContentfulPaint"; private static final String FIRST_VISIBLE_CONTENT_HISTOGRAM = @@ -64,9 +64,8 @@ private static final String FIRST_COMMIT_OCCURRED_PRE_FOREGROUND_HISTOGRAM = "Startup.Android.Cold.FirstNavigationCommitOccurredPreForeground"; - private static final String TABBED_SUFFIX = ChromeTabbedActivity.STARTUP_UMA_HISTOGRAM_SUFFIX; - private static final String WEBAPK_SUFFIX = - WebApkActivityLifecycleUmaTracker.STARTUP_UMA_HISTOGRAM_SUFFIX; + private static final String TABBED_SUFFIX = ".Tabbed"; + private static final String WEB_APK_SUFFIX = ".WebApk"; @Rule public ChromeTabbedActivityTestRule mTabbedActivityTestRule = @@ -140,6 +139,8 @@ FIRST_VISIBLE_CONTENT_HISTOGRAM)); Assert.assertEquals(expectedCount, RecordHistogram.getHistogramTotalCountForTesting(VISIBLE_CONTENT_HISTOGRAM)); + Assert.assertEquals(expectedCount, + RecordHistogram.getHistogramTotalCountForTesting(FIRST_COMMIT_HISTOGRAM2)); } if (expectedCount > 0) { @@ -169,9 +170,9 @@ public void testWebApkStartRecorded() throws Exception { runAndWaitForPageLoadMetricsRecorded( () -> mWebApkActivityTestRule.startWebApkActivity(mTestPage)); - assertHistogramsRecorded(1, WEBAPK_SUFFIX); + assertHistogramsRecorded(1, WEB_APK_SUFFIX); loadUrlAndWaitForPageLoadMetricsRecorded(mWebApkActivityTestRule, mTestPage2); - assertHistogramsRecorded(1, WEBAPK_SUFFIX); + assertHistogramsRecorded(1, WEB_APK_SUFFIX); } /** @@ -239,9 +240,9 @@ public void testWebApkErrorPageNotRecorded() throws Exception { runAndWaitForPageLoadMetricsRecorded( () -> mWebApkActivityTestRule.startWebApkActivity(mErrorPage)); - assertHistogramsRecorded(0, WEBAPK_SUFFIX); + assertHistogramsRecorded(0, WEB_APK_SUFFIX); loadUrlAndWaitForPageLoadMetricsRecorded(mWebApkActivityTestRule, mTestPage2); - assertHistogramsRecorded(0, WEBAPK_SUFFIX); + assertHistogramsRecorded(0, WEB_APK_SUFFIX); } /** @@ -303,6 +304,10 @@ Assert.assertEquals(0, RecordHistogram.getHistogramTotalCountForTesting(FIRST_VISIBLE_CONTENT_HISTOGRAM)); + // The metric based on early foreground notification should be recorded. + Assert.assertEquals( + 1, RecordHistogram.getHistogramTotalCountForTesting(FIRST_COMMIT_HISTOGRAM2)); + // The metric for the first navigation commit having occurred pre-foregrounding should also // not have been recorded at this point, as there hasn't yet been a notification that the // browser has come to the foreground.
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java index 353d3c6..1648978 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java
@@ -10,6 +10,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; @@ -237,6 +238,17 @@ @Test public void testToolbarBrandingDelegateImpl_EmptyToBranding() { + mLocationBar.setIconTransitionEnabled(true); + doTestToolbarBrandingDelegateImpl_EmptyToBranding(true); + } + + @Test + public void testToolbarBrandingDelegateImpl_EmptyToBranding_DisableTransition() { + mLocationBar.setIconTransitionEnabled(false); + doTestToolbarBrandingDelegateImpl_EmptyToBranding(false); + } + + private void doTestToolbarBrandingDelegateImpl_EmptyToBranding(boolean animateIconTransition) { ChromeFeatureList.sCctBrandTransparency.setForTesting(true); assertUrlAndTitleVisible(/*titleVisible=*/false, /*urlVisible=*/true); @@ -251,6 +263,7 @@ mLocationBar.showBrandingLocationBar(); assertUrlAndTitleVisible(/*titleVisible=*/false, /*urlVisible=*/true); + verify(mAnimationDelegate).updateSecurityButton(anyInt(), eq(animateIconTransition)); // Attempt to update title and URL to show Title only - should be ignored during branding. reset(mLocationBarModel);
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 7825078..cdc2630 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -6065,6 +6065,20 @@ <message name="IDS_PASSWORD_MANAGER_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION" desc="The description of the Google Password Manager's update password message when the user is signed in."> In Google Password Manager for <ph name="ACCOUNT">$1<ex>user@gmail.com</ex></ph> </message> + <if expr="is_android"> + <message name="IDS_PASSWORD_MANAGER_SAVE_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V1" desc="The description of the Google Password Manager's save/update password prompt when the user is signed in."> + Google Password Manager <ph name="SEPARATOR">•</ph> <ph name="ACCOUNT">$1<ex>user@gmail.com</ex></ph> + </message> + <message name="IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V2" desc="The description of the Google Password Manager's save password prompt when the user is signed in."> + To your Google Account, for <ph name="ACCOUNT">$1<ex>user@gmail.com</ex></ph> + </message> + <message name="IDS_PASSWORD_MANAGER_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V2" desc="The description of the Google Password Manager's save password prompt when the user is signed in."> + In your Google Account, for <ph name="ACCOUNT">$1<ex>user@gmail.com</ex></ph> + </message> + <message name="IDS_PASSWORD_MANAGER_SAVE_UPDATE_PASSWORD_SIGNED_OUT_MESSAGE_DESCRIPTION_V1" desc="The description of the Google Password Manager's save password prompt when the user is signed out and passwords are only stored locally."> + Only on this device + </message> + </if> <if expr="use_titlecase"> <message name="IDS_PASSWORD_MANAGER_ACCOUNT_CHOOSER_SIGN_IN" desc="In Title Case: The title of the Sign in button in the account chooser when there is one account."> Sign In
diff --git a/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V2.png.sha1 b/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V2.png.sha1 new file mode 100644 index 0000000..2e2d4e4 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V2.png.sha1
@@ -0,0 +1 @@ +8287d85ba36e624ada15c29e4cd5a26258cc92cb \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGER_SAVE_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V1.png.sha1 b/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGER_SAVE_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V1.png.sha1 new file mode 100644 index 0000000..d2720d9 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGER_SAVE_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V1.png.sha1
@@ -0,0 +1 @@ +c098a770c6bdc1db8eb2af8bc30f6c8f74c99608 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGER_SAVE_UPDATE_PASSWORD_SIGNED_OUT_MESSAGE_DESCRIPTION_V1.png.sha1 b/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGER_SAVE_UPDATE_PASSWORD_SIGNED_OUT_MESSAGE_DESCRIPTION_V1.png.sha1 new file mode 100644 index 0000000..9cc2a8d --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGER_SAVE_UPDATE_PASSWORD_SIGNED_OUT_MESSAGE_DESCRIPTION_V1.png.sha1
@@ -0,0 +1 @@ +ac244af9a0214c43af43e0a475826e4d714b2b6d \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGER_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V2.png.sha1 b/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGER_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V2.png.sha1 new file mode 100644 index 0000000..c679fe1 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGER_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V2.png.sha1
@@ -0,0 +1 @@ +9f302d188c61200852a74ffbc2a2564299326dde \ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index d8fb9b8..7cd4b3f 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -6214,12 +6214,6 @@ flag_descriptions::kCCTResizable90MaximumHeightName, flag_descriptions::kCCTResizable90MaximumHeightDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kCCTResizable90MaximumHeight)}, - {"cct-resizable-allow-resize-by-user-gesture", - flag_descriptions::kCCTResizableAllowResizeByUserGestureName, - flag_descriptions::kCCTResizableAllowResizeByUserGestureDescription, - kOsAndroid, - FEATURE_VALUE_TYPE( - chrome::android::kCCTResizableAllowResizeByUserGesture)}, {"cct-resizable-for-third-parties", flag_descriptions::kCCTResizableForThirdPartiesName, flag_descriptions::kCCTResizableForThirdPartiesDescription, kOsAndroid, @@ -6635,11 +6629,6 @@ flag_descriptions::kFastPairSoftwareScanningDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kFastPairSoftwareScanning)}, - {"fast-pair-subsequent-pairing-ux", - flag_descriptions::kFastPairSubsequentPairingUXName, - flag_descriptions::kFastPairSubsequentPairingUXDescription, kOsCrOS, - FEATURE_VALUE_TYPE(ash::features::kFastPairSubsequentPairingUX)}, - {"pcie-billboard-notification", flag_descriptions::kPcieBillboardNotificationName, flag_descriptions::kPcieBillboardNotificationDescription, kOsCrOS, @@ -6668,11 +6657,6 @@ flag_descriptions::kEnableHostnameSettingDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kEnableHostnameSetting)}, - {"enable-networking-in-diagnostics-app", - flag_descriptions::kEnableNetworkingInDiagnosticsAppName, - flag_descriptions::kEnableNetworkingInDiagnosticsAppDescription, kOsCrOS, - FEATURE_VALUE_TYPE(ash::features::kEnableNetworkingInDiagnosticsApp)}, - {"enable-oauth-ipp", flag_descriptions::kEnableOAuthIppName, flag_descriptions::kEnableOAuthIppDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kEnableOAuthIpp)}, @@ -7448,9 +7432,9 @@ flag_descriptions::kMacAddressRandomizationDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kMacAddressRandomization)}, - {"oobe-material-next", flag_descriptions::kOobeMaterialNextName, - flag_descriptions::kOobeMaterialNextDescription, kOsCrOS, - FEATURE_VALUE_TYPE(ash::features::kOobeMaterialNext)}, + {"oobe-jelly", flag_descriptions::kOobeJellyName, + flag_descriptions::kOobeJellyDescription, kOsCrOS, + FEATURE_VALUE_TYPE(ash::features::kOobeJelly)}, {"search-result-inline-icon", flag_descriptions::kSearchResultInlineIconName,
diff --git a/chrome/browser/android/customtabs/branding/java/src/org/chromium/chrome/browser/customtabs/features/branding/BrandingController.java b/chrome/browser/android/customtabs/branding/java/src/org/chromium/chrome/browser/customtabs/features/branding/BrandingController.java index bacdcd1..fe7ff4b 100644 --- a/chrome/browser/android/customtabs/branding/java/src/org/chromium/chrome/browser/customtabs/features/branding/BrandingController.java +++ b/chrome/browser/android/customtabs/branding/java/src/org/chromium/chrome/browser/customtabs/features/branding/BrandingController.java
@@ -37,6 +37,8 @@ private static final String PARAM_BRANDING_CADENCE_NAME = "branding_cadence"; private static final String PARAM_MAX_BLANK_TOOLBAR_TIMEOUT_MS = "max_blank_toolbar_timeout"; private static final String PARAM_USE_TEMPORARY_STORAGE = "use_temporary_storage"; + private static final String PARAM_ANIMATE_TOOLBAR_ICON_TRANSITION = + "animate_toolbar_transition"; private static final int DEFAULT_BRANDING_CADENCE_MS = (int) TimeUnit.HOURS.toMillis(1); private static final int DEFAULT_MAX_BLANK_TOOLBAR_TIMEOUT_MS = 500; /** @@ -67,12 +69,21 @@ new BooleanCachedFieldTrialParameter( ChromeFeatureList.CCT_BRAND_TRANSPARENCY, PARAM_USE_TEMPORARY_STORAGE, false); + /** + * Whether animation transition will be used for the security icon during toolbar branding. + * If set to false, the icon transition will be disabled. + */ + public static final BooleanCachedFieldTrialParameter ANIMATE_TOOLBAR_ICON_TRANSITION = + new BooleanCachedFieldTrialParameter(ChromeFeatureList.CCT_BRAND_TRANSPARENCY, + PARAM_ANIMATE_TOOLBAR_ICON_TRANSITION, true); + private final CallbackController mCallbackController = new CallbackController(); private final @BrandingDecision OneshotSupplierImpl<Integer> mBrandingDecision = new OneshotSupplierImpl<>(); private final BrandingChecker mBrandingChecker; private final Context mContext; private final String mAppName; + private final boolean mEnableIconAnimation; private ToolbarBrandingDelegate mToolbarBrandingDelegate; private @Nullable Toast mToast; @@ -95,6 +106,7 @@ mContext = context; mAppName = appName; mExceptionReporter = exceptionReporter; + mEnableIconAnimation = ANIMATE_TOOLBAR_ICON_TRANSITION.getValue(); mBrandingDecision.onAvailable( mCallbackController.makeCancelable((decision) -> maybeMakeBrandingDecision())); @@ -117,6 +129,7 @@ mToolbarInitializedTime = SystemClock.elapsedRealtime(); mToolbarBrandingDelegate = delegate; + mToolbarBrandingDelegate.setIconTransitionEnabled(mEnableIconAnimation); // Start the task to timeout the branding check. If mBrandingChecker already finished, // canceling the task does nothing. Does not interrupt if the task is running, since the
diff --git a/chrome/browser/android/customtabs/branding/java/src/org/chromium/chrome/browser/customtabs/features/branding/ToolbarBrandingDelegate.java b/chrome/browser/android/customtabs/branding/java/src/org/chromium/chrome/browser/customtabs/features/branding/ToolbarBrandingDelegate.java index be66637..db7258ff 100644 --- a/chrome/browser/android/customtabs/branding/java/src/org/chromium/chrome/browser/customtabs/features/branding/ToolbarBrandingDelegate.java +++ b/chrome/browser/android/customtabs/branding/java/src/org/chromium/chrome/browser/customtabs/features/branding/ToolbarBrandingDelegate.java
@@ -19,4 +19,12 @@ /** Show the regular location with URL and Title, with start transition. */ void showRegularToolbar(); + + /** + * Whether the animation transition between state for toolbar icon should be disable. By + * default, the animation transition will be enabled if this is not set. + * @param enabled If true, the animation will be enabled; if false, the animation will be + * disabled. + */ + void setIconTransitionEnabled(boolean enabled); }
diff --git a/chrome/browser/ash/arc/arc_support_host.cc b/chrome/browser/ash/arc/arc_support_host.cc index 941407d..85f62c35 100644 --- a/chrome/browser/ash/arc/arc_support_host.cc +++ b/chrome/browser/ash/arc/arc_support_host.cc
@@ -8,7 +8,6 @@ #include <utility> #include <vector> -#include "ash/constants/ash_features.h" #include "base/bind.h" #include "base/hash/sha1.h" #include "base/i18n/timezone.h" @@ -418,9 +417,7 @@ message_args.Set(kErrorMessage, message); message_args.Set(kShouldShowSendFeedback, should_show_send_feedback); - message_args.Set(kShouldShowNetworkTests, - should_show_run_network_tests && - ash::features::IsArcNetworkDiagnosticsButtonEnabled()); + message_args.Set(kShouldShowNetworkTests, should_show_run_network_tests); message_host_->SendMessage(message_args); }
diff --git a/chrome/browser/ash/policy/core/device_local_account_browsertest.cc b/chrome/browser/ash/policy/core/device_local_account_browsertest.cc index ddb7aaf..e311f9e 100644 --- a/chrome/browser/ash/policy/core/device_local_account_browsertest.cc +++ b/chrome/browser/ash/policy/core/device_local_account_browsertest.cc
@@ -1315,7 +1315,7 @@ embedded_test_server()->StartAcceptingConnections(); // Specify an external data reference for the key::kUserAvatarImage policy. - std::unique_ptr<base::DictionaryValue> metadata = + std::unique_ptr<base::Value::Dict> metadata = test::ConstructExternalDataReference( embedded_test_server()->GetURL(kExternalDataPath).spec(), kExternalData);
diff --git a/chrome/browser/ash/policy/core/device_policy_decoder_unittest.cc b/chrome/browser/ash/policy/core/device_policy_decoder_unittest.cc index 3ecfd832..1f70eb3 100644 --- a/chrome/browser/ash/policy/core/device_policy_decoder_unittest.cc +++ b/chrome/browser/ash/policy/core/device_policy_decoder_unittest.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ash/policy/core/device_policy_decoder.h" +#include <memory> + #include "base/bind.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" @@ -77,21 +79,19 @@ }; std::unique_ptr<base::Value> DevicePolicyDecoderTest::GetWallpaperDict() const { - auto dict = std::make_unique<base::DictionaryValue>(); - dict->SetKey(kWallpaperUrlPropertyName, - base::Value(kWallpaperUrlPropertyValue)); - dict->SetKey(kWallpaperHashPropertyName, - base::Value(kWallpaperHashPropertyValue)); - return dict; + base::Value::Dict dict; + dict.Set(kWallpaperUrlPropertyName, kWallpaperUrlPropertyValue); + dict.Set(kWallpaperHashPropertyName, kWallpaperHashPropertyValue); + return std::make_unique<base::Value>(std::move(dict)); } std::unique_ptr<base::Value> DevicePolicyDecoderTest::GetBluetoothServiceAllowedList() const { - auto list = std::make_unique<base::ListValue>(); - list->Append(base::Value(kValidBluetoothServiceUUID4)); - list->Append(base::Value(kValidBluetoothServiceUUID8)); - list->Append(base::Value(kValidBluetoothServiceUUID32)); - return list; + base::Value::List list; + list.Append(kValidBluetoothServiceUUID4); + list.Append(kValidBluetoothServiceUUID8); + list.Append(kValidBluetoothServiceUUID32); + return std::make_unique<base::Value>(std::move(list)); } void DevicePolicyDecoderTest::DecodeDevicePolicyTestHelper(
diff --git a/chrome/browser/ash/policy/enrollment/enrollment_config_unittest.cc b/chrome/browser/ash/policy/enrollment/enrollment_config_unittest.cc index 1828fc5..a46e5da6 100644 --- a/chrome/browser/ash/policy/enrollment/enrollment_config_unittest.cc +++ b/chrome/browser/ash/policy/enrollment/enrollment_config_unittest.cc
@@ -94,11 +94,11 @@ EXPECT_EQ(GetParam().auth_mechanism, config.auth_mechanism); // Server-backed state: advertised enrollment. - base::DictionaryValue state_dict; - state_dict.SetStringKey(kDeviceStateMode, - kDeviceStateRestoreModeReEnrollmentRequested); - state_dict.SetStringKey(kDeviceStateManagementDomain, "example.com"); - local_state_.Set(prefs::kServerBackedDeviceState, state_dict); + base::Value::Dict state_dict; + state_dict.Set(kDeviceStateMode, + kDeviceStateRestoreModeReEnrollmentRequested); + state_dict.Set(kDeviceStateManagementDomain, "example.com"); + local_state_.SetDict(prefs::kServerBackedDeviceState, state_dict.Clone()); config = EnrollmentConfig::GetPrescribedEnrollmentConfig( local_state_, install_attributes_, &statistics_provider_); EXPECT_EQ(EnrollmentConfig::MODE_SERVER_ADVERTISED, config.mode); @@ -129,9 +129,8 @@ EXPECT_EQ(GetParam().auth_mechanism, config.auth_mechanism); // Server-backed state: forced enrollment. - state_dict.SetStringKey(kDeviceStateMode, - kDeviceStateRestoreModeReEnrollmentEnforced); - local_state_.Set(prefs::kServerBackedDeviceState, state_dict); + state_dict.Set(kDeviceStateMode, kDeviceStateRestoreModeReEnrollmentEnforced); + local_state_.SetDict(prefs::kServerBackedDeviceState, state_dict.Clone()); config = EnrollmentConfig::GetPrescribedEnrollmentConfig( local_state_, install_attributes_, &statistics_provider_); EXPECT_EQ(EnrollmentConfig::MODE_SERVER_FORCED, config.mode);
diff --git a/chrome/browser/ash/policy/external_data/cloud_external_data_manager_base_test_util.cc b/chrome/browser/ash/policy/external_data/cloud_external_data_manager_base_test_util.cc index 7541318..474dcbf 100644 --- a/chrome/browser/ash/policy/external_data/cloud_external_data_manager_base_test_util.cc +++ b/chrome/browser/ash/policy/external_data/cloud_external_data_manager_base_test_util.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ash/policy/external_data/cloud_external_data_manager_base_test_util.h" +#include <memory> #include <utility> #include "base/callback.h" @@ -30,7 +31,7 @@ namespace policy { namespace { -// Keys for 'DictionaryValue' objects +// Keys for the 'Value' objects const char kUrlKey[] = "url"; const char kHashKey[] = "hash"; } // namespace @@ -47,14 +48,13 @@ std::move(done_callback).Run(); } -std::unique_ptr<base::DictionaryValue> ConstructExternalDataReference( +std::unique_ptr<base::Value::Dict> ConstructExternalDataReference( const std::string& url, const std::string& data) { const std::string hash = crypto::SHA256HashString(data); - std::unique_ptr<base::DictionaryValue> metadata(new base::DictionaryValue); - metadata->SetKey(kUrlKey, base::Value(url)); - metadata->SetKey(kHashKey, - base::Value(base::HexEncode(hash.c_str(), hash.size()))); + auto metadata = std::make_unique<base::Value::Dict>(); + metadata->Set(kUrlKey, url); + metadata->Set(kHashKey, base::HexEncode(hash.c_str(), hash.size())); return metadata; }
diff --git a/chrome/browser/ash/policy/external_data/cloud_external_data_manager_base_test_util.h b/chrome/browser/ash/policy/external_data/cloud_external_data_manager_base_test_util.h index 1bf93f9..94377433 100644 --- a/chrome/browser/ash/policy/external_data/cloud_external_data_manager_base_test_util.h +++ b/chrome/browser/ash/policy/external_data/cloud_external_data_manager_base_test_util.h
@@ -10,10 +10,7 @@ #include "base/callback_forward.h" #include "base/files/file_path.h" - -namespace base { -class DictionaryValue; -} +#include "base/values.h" namespace net { namespace test_server { @@ -37,7 +34,7 @@ // Constructs a value that points a policy referencing external data at |url| // and sets the expected hash of the external data to that of |data|. -std::unique_ptr<base::DictionaryValue> ConstructExternalDataReference( +std::unique_ptr<base::Value::Dict> ConstructExternalDataReference( const std::string& url, const std::string& data); @@ -54,7 +51,7 @@ // removed. void SetExternalDataReference(CloudPolicyCore* core, const std::string& policy, - std::unique_ptr<base::DictionaryValue> metadata); + std::unique_ptr<base::Value::Dict> metadata); } // namespace test } // namespace policy
diff --git a/chrome/browser/ash/policy/external_data/user_cloud_external_data_manager_browsertest.cc b/chrome/browser/ash/policy/external_data/user_cloud_external_data_manager_browsertest.cc index 80e3895..746443c 100644 --- a/chrome/browser/ash/policy/external_data/user_cloud_external_data_manager_browsertest.cc +++ b/chrome/browser/ash/policy/external_data/user_cloud_external_data_manager_browsertest.cc
@@ -68,7 +68,7 @@ } std::string external_data_; - std::unique_ptr<base::DictionaryValue> metadata_; + std::unique_ptr<base::Value::Dict> metadata_; }; IN_PROC_BROWSER_TEST_F(UserCloudExternalDataManagerTest, FetchExternalData) {
diff --git a/chrome/browser/ash/policy/handlers/system_proxy_handler_unittest.cc b/chrome/browser/ash/policy/handlers/system_proxy_handler_unittest.cc index 23799e3..5438ef0 100644 --- a/chrome/browser/ash/policy/handlers/system_proxy_handler_unittest.cc +++ b/chrome/browser/ash/policy/handlers/system_proxy_handler_unittest.cc
@@ -77,14 +77,12 @@ void SetPolicy(bool system_proxy_enabled, const std::string& system_services_username, const std::string& system_services_password) { - base::DictionaryValue dict; - dict.SetKey("system_proxy_enabled", base::Value(system_proxy_enabled)); - dict.SetKey("system_services_username", - base::Value(system_services_username)); - dict.SetKey("system_services_password", - base::Value(system_services_password)); + base::Value::Dict dict; + dict.Set("system_proxy_enabled", system_proxy_enabled); + dict.Set("system_services_username", system_services_username); + dict.Set("system_services_password", system_services_password); scoped_testing_cros_settings_.device_settings()->Set( - ash::kSystemProxySettings, dict); + ash::kSystemProxySettings, base::Value(std::move(dict))); task_environment_.RunUntilIdle(); }
diff --git a/chrome/browser/ash/policy/handlers/tpm_auto_update_mode_policy_handler_unittest.cc b/chrome/browser/ash/policy/handlers/tpm_auto_update_mode_policy_handler_unittest.cc index 81dd6d1..a6b9083 100644 --- a/chrome/browser/ash/policy/handlers/tpm_auto_update_mode_policy_handler_unittest.cc +++ b/chrome/browser/ash/policy/handlers/tpm_auto_update_mode_policy_handler_unittest.cc
@@ -11,6 +11,7 @@ #include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "base/timer/mock_timer.h" +#include "base/values.h" #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/ash/settings/scoped_testing_cros_settings.h" #include "chrome/browser/ash/tpm_firmware_update.h" @@ -51,11 +52,11 @@ } void SetAutoUpdateMode(AutoUpdateMode auto_update_mode) { - base::DictionaryValue dict; - dict.SetKey(ash::tpm_firmware_update::kSettingsKeyAutoUpdateMode, - base::Value(static_cast<int>(auto_update_mode))); + base::Value::Dict dict; + dict.Set(ash::tpm_firmware_update::kSettingsKeyAutoUpdateMode, + base::Value(static_cast<int>(auto_update_mode))); scoped_testing_cros_settings_.device_settings()->Set( - ash::kTPMFirmwareUpdateSettings, dict); + ash::kTPMFirmwareUpdateSettings, base::Value(std::move(dict))); base::RunLoop().RunUntilIdle(); }
diff --git a/chrome/browser/ash/policy/reporting/arc_app_install_event_logger_unittest.cc b/chrome/browser/ash/policy/reporting/arc_app_install_event_logger_unittest.cc index 6599fb4..20c1d0f 100644 --- a/chrome/browser/ash/policy/reporting/arc_app_install_event_logger_unittest.cc +++ b/chrome/browser/ash/policy/reporting/arc_app_install_event_logger_unittest.cc
@@ -246,7 +246,7 @@ PolicyMap CreatePolicyWithForceInstalls(std::set<std::string> package_names) { PolicyMap policy_map; - base::DictionaryValue arc_policy; + base::Value::Dict arc_policy; base::Value::List list; for (std::string package_name : package_names) { @@ -256,7 +256,7 @@ list.Append(std::move(package)); } - arc_policy.GetDict().Set("applications", std::move(list)); + arc_policy.Set("applications", std::move(list)); std::string arc_policy_string; base::JSONWriter::Write(arc_policy, &arc_policy_string); SetPolicy(&policy_map, key::kArcEnabled, base::Value(true)); @@ -265,7 +265,7 @@ return policy_map; } - base::DictionaryValue CreateComplianceReport( + base::Value::Dict CreateComplianceReport( std::set<std::string> noncompliant_packages) { base::Value::List details; @@ -276,8 +276,8 @@ details.Append(std::move(package)); } - base::DictionaryValue compliance_report; - compliance_report.GetDict().Set("nonComplianceDetails", std::move(details)); + base::Value::Dict compliance_report; + compliance_report.Set("nonComplianceDetails", std::move(details)); return compliance_report; } @@ -464,7 +464,7 @@ PolicyMap new_policy_map; - base::DictionaryValue arc_policy; + base::Value::Dict arc_policy; base::Value::List list; // Test that REQUIRED, PREINSTALLED and FORCE_INSTALLED are markers to include @@ -489,7 +489,7 @@ package5.Set("installType", "AVAILABLE"); package5.Set("packageName", kPackageName5); list.Append(std::move(package5)); - arc_policy.GetDict().Set("applications", std::move(list)); + arc_policy.Set("applications", std::move(list)); std::string arc_policy_string; base::JSONWriter::Write(arc_policy, &arc_policy_string);
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler_unittest.cc index a0ddcc3..eebdd25 100644 --- a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler_unittest.cc +++ b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler_unittest.cc
@@ -134,14 +134,15 @@ base::Value(network_data.signal_strength)); service_client->SetServiceProperty(service_path, shill::kDeviceProperty, base::Value(device_path)); - base::DictionaryValue ip_config_properties; - ip_config_properties.SetKey(shill::kAddressProperty, - base::Value(network_data.ip_address)); - ip_config_properties.SetKey(shill::kGatewayProperty, - base::Value(network_data.gateway)); + base::Value::Dict ip_config_properties; + ip_config_properties.Set(shill::kAddressProperty, + base::Value(network_data.ip_address)); + ip_config_properties.Set(shill::kGatewayProperty, + base::Value(network_data.gateway)); const std::string kIPConfigPath = base::StrCat({"test_ip_config", network_data.guid}); - ip_config_client->AddIPConfig(kIPConfigPath, ip_config_properties); + ip_config_client->AddIPConfig( + kIPConfigPath, base::Value(std::move(ip_config_properties))); service_client->SetServiceProperty(service_path, shill::kIPConfigProperty, base::Value(kIPConfigPath)); if (network_data.type == shill::kTypeCellular) {
diff --git a/chrome/browser/ash/policy/status_collector/activity_storage.cc b/chrome/browser/ash/policy/status_collector/activity_storage.cc index fda3fac..2797539 100644 --- a/chrome/browser/ash/policy/status_collector/activity_storage.cc +++ b/chrome/browser/ash/policy/status_collector/activity_storage.cc
@@ -12,6 +12,7 @@ #include "base/bind.h" #include "base/check.h" #include "base/logging.h" +#include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" #include "chrome/common/pref_names.h" @@ -58,10 +59,10 @@ void ActivityStorage::TrimActivityPeriods(int64_t min_day_key, int64_t max_day_key) { - base::DictionaryValue copy; + base::Value::Dict copy; ForEachActivityPeriodFromPref(base::BindRepeating( - [](base::DictionaryValue* copy, int64_t min_day_key, int64_t max_day_key, + [](base::Value::Dict& copy, int64_t min_day_key, int64_t max_day_key, int64_t start, int64_t end, const std::string& activity_id) { int64_t day_key = start; // Remove data that is too old, or too far in the future. @@ -76,12 +77,12 @@ if (duration <= 0) return; const std::string key = MakeActivityPeriodPrefKey(day_key, activity_id); - copy->SetIntPath(key, duration); + copy.Set(key, base::saturated_cast<int>(duration)); }, - ©, min_day_key, max_day_key)); + std::ref(copy), min_day_key, max_day_key)); // Flush the activities into pref_service_ - pref_service_->Set(pref_name_, copy); + pref_service_->SetDict(pref_name_, std::move(copy)); } void ActivityStorage::RemoveOverlappingActivityPeriods() { @@ -185,19 +186,19 @@ void ActivityStorage::SetActivityPeriods( const std::map<std::string, Activities>& new_activity_periods) { - base::DictionaryValue copy; + base::Value::Dict copy; for (const auto& activity_pair : new_activity_periods) { const std::string& activity_id = activity_pair.first; const Activities& activities = activity_pair.second; for (const auto& activity : activities) { const std::string& key = MakeActivityPeriodPrefKey(activity.start_timestamp(), activity_id); - copy.SetIntKey(key, - activity.end_timestamp() - activity.start_timestamp()); + copy.Set(key, base::saturated_cast<int>(activity.end_timestamp() - + activity.start_timestamp())); } } - pref_service_->Set(pref_name_, copy); + pref_service_->SetDict(pref_name_, std::move(copy)); } int64_t ActivityStorage::LocalTimeToUtcDayStart(base::Time timestamp) const {
diff --git a/chrome/browser/ash/web_applications/diagnostics_app_integration_browsertest.cc b/chrome/browser/ash/web_applications/diagnostics_app_integration_browsertest.cc index ae88edb..602f437 100644 --- a/chrome/browser/ash/web_applications/diagnostics_app_integration_browsertest.cc +++ b/chrome/browser/ash/web_applications/diagnostics_app_integration_browsertest.cc
@@ -2,11 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/constants/ash_features.h" #include "ash/webui/diagnostics_ui/url_constants.h" #include "ash/webui/system_apps/public/system_web_app_type.h" #include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_feature_list.h" #include "chrome/browser/ash/system_web_apps/test_support/system_web_app_integration_test.h" #include "chrome/browser/lifetime/application_lifetime_desktop.h" #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h" @@ -37,10 +35,7 @@ class DiagnosticsAppIntegrationTest : public ash::SystemWebAppIntegrationTest { public: - DiagnosticsAppIntegrationTest() { - scoped_feature_list_.InitAndEnableFeature( - ash::features::kEnableNetworkingInDiagnosticsApp); - } + DiagnosticsAppIntegrationTest() = default; protected: base::HistogramTester histogram_tester_; @@ -64,9 +59,6 @@ return params; } - - private: - base::test::ScopedFeatureList scoped_feature_list_; }; // Test that the Diagnostics App installs and launches correctly by running some
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index b924f22..b8686da 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc
@@ -455,6 +455,12 @@ battery_metrics_.reset(); +#if BUILDFLAG(ENABLE_EXTENSIONS) + // The Extensions Browser Client needs to teardown some members while the + // profile manager is still alive. + extensions_browser_client_->StartTearDown(); +#endif + // Need to clear profiles (download managers) before the IO thread. { TRACE_EVENT0("shutdown", @@ -472,6 +478,8 @@ } #if BUILDFLAG(ENABLE_EXTENSIONS) + // The `media_file_system_registry_` cannot be reset until the + // `profile_manager_` has been. media_file_system_registry_.reset(); // Remove the global instance of the Storage Monitor now. Otherwise the // FILE thread would be gone when we try to release it in the dtor and
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h index ecae3d0e..0130685 100644 --- a/chrome/browser/browser_process_impl.h +++ b/chrome/browser/browser_process_impl.h
@@ -59,7 +59,7 @@ } // namespace breadcrumbs namespace extensions { -class ExtensionsBrowserClient; +class ChromeExtensionsBrowserClient; } namespace gcm { @@ -282,7 +282,7 @@ std::unique_ptr<GpuModeManager> gpu_mode_manager_; #if BUILDFLAG(ENABLE_EXTENSIONS) - std::unique_ptr<extensions::ExtensionsBrowserClient> + std::unique_ptr<extensions::ChromeExtensionsBrowserClient> extensions_browser_client_; scoped_refptr<extensions::EventRouterForwarder>
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index ddc5be9..d61bf8fd 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -1184,11 +1184,9 @@ ash::diagnostics::mojom::InputDataProvider, ash::DiagnosticsDialogUI>( map); - if (ash::features::IsNetworkingInDiagnosticsAppEnabled()) { - RegisterWebUIControllerInterfaceBinder< - ash::diagnostics::mojom::NetworkHealthProvider, - ash::DiagnosticsDialogUI>(map); - } + RegisterWebUIControllerInterfaceBinder< + ash::diagnostics::mojom::NetworkHealthProvider, ash::DiagnosticsDialogUI>( + map); RegisterWebUIControllerInterfaceBinder< ash::diagnostics::mojom::SystemDataProvider, ash::DiagnosticsDialogUI>(
diff --git a/chrome/browser/content_settings/generated_cookie_prefs.cc b/chrome/browser/content_settings/generated_cookie_prefs.cc index 63c6f702..74042a94 100644 --- a/chrome/browser/content_settings/generated_cookie_prefs.cc +++ b/chrome/browser/content_settings/generated_cookie_prefs.cc
@@ -359,10 +359,15 @@ extensions::settings_private::SetPrefResult GeneratedCookieDefaultContentSettingPref::SetPref(const base::Value* value) { - if (!value->is_int()) + if (!value->is_string()) { return extensions::settings_private::SetPrefResult::PREF_TYPE_MISMATCH; + } - int setting = value->GetInt(); + ContentSetting setting; + if (!content_settings::ContentSettingFromString(value->GetString(), + &setting)) { + return extensions::settings_private::SetPrefResult::PREF_TYPE_MISMATCH; + } if (setting != CONTENT_SETTING_ALLOW && setting != CONTENT_SETTING_SESSION_ONLY && setting != CONTENT_SETTING_BLOCK) { @@ -382,13 +387,14 @@ GeneratedCookieDefaultContentSettingPref::GetPrefObject() const { auto pref_object = std::make_unique<settings_api::PrefObject>(); pref_object->key = pref_name_; - pref_object->type = settings_api::PREF_TYPE_NUMBER; + pref_object->type = settings_api::PREF_TYPE_STRING; std::string content_setting_provider; auto content_setting = host_content_settings_map_->GetDefaultContentSetting( ContentSettingsType::COOKIES, &content_setting_provider); - pref_object->value = base::Value(content_setting); + pref_object->value = + base::Value(content_settings::ContentSettingToString(content_setting)); // Cookies content setting can be managed via policy, extension or // supervision, but cannot be recommended.
diff --git a/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc b/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc index 1623061..3f5986e 100644 --- a/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc +++ b/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc
@@ -549,37 +549,33 @@ map->SetDefaultContentSetting(ContentSettingsType::COOKIES, CONTENT_SETTING_ALLOW); auto pref_object = pref->GetPrefObject(); - EXPECT_EQ(pref_object->value->GetInt(), CONTENT_SETTING_ALLOW); + EXPECT_EQ(pref_object->value->GetString(), "allow"); // Ensure setting the preference correctly updates content settings and the // preference state. - EXPECT_EQ( - pref->SetPref( - std::make_unique<base::Value>(CONTENT_SETTING_SESSION_ONLY).get()), - extensions::settings_private::SetPrefResult::SUCCESS); + EXPECT_EQ(pref->SetPref(std::make_unique<base::Value>("session_only").get()), + extensions::settings_private::SetPrefResult::SUCCESS); EXPECT_EQ( map->GetDefaultContentSetting(ContentSettingsType::COOKIES, nullptr), CONTENT_SETTING_SESSION_ONLY); pref_object = pref->GetPrefObject(); - EXPECT_EQ(pref_object->value->GetInt(), CONTENT_SETTING_SESSION_ONLY); + EXPECT_EQ(pref_object->value->GetString(), "session_only"); - EXPECT_EQ( - pref->SetPref(std::make_unique<base::Value>(CONTENT_SETTING_ALLOW).get()), - extensions::settings_private::SetPrefResult::SUCCESS); + EXPECT_EQ(pref->SetPref(std::make_unique<base::Value>("allow").get()), + extensions::settings_private::SetPrefResult::SUCCESS); EXPECT_EQ( map->GetDefaultContentSetting(ContentSettingsType::COOKIES, nullptr), CONTENT_SETTING_ALLOW); pref_object = pref->GetPrefObject(); - EXPECT_EQ(pref_object->value->GetInt(), CONTENT_SETTING_ALLOW); + EXPECT_EQ(pref_object->value->GetString(), "allow"); - EXPECT_EQ( - pref->SetPref(std::make_unique<base::Value>(CONTENT_SETTING_BLOCK).get()), - extensions::settings_private::SetPrefResult::SUCCESS); + EXPECT_EQ(pref->SetPref(std::make_unique<base::Value>("block").get()), + extensions::settings_private::SetPrefResult::SUCCESS); EXPECT_EQ( map->GetDefaultContentSetting(ContentSettingsType::COOKIES, nullptr), CONTENT_SETTING_BLOCK); pref_object = pref->GetPrefObject(); - EXPECT_EQ(pref_object->value->GetInt(), CONTENT_SETTING_BLOCK); + EXPECT_EQ(pref_object->value->GetString(), "block"); } TEST_F(GeneratedCookiePrefsTest, DefaultContentSettingPref_TypeMismatch) { @@ -589,12 +585,14 @@ // Confirm that a type mismatch is reported as such. EXPECT_EQ(pref->SetPref(std::make_unique<base::Value>(false).get()), extensions::settings_private::SetPrefResult::PREF_TYPE_MISMATCH); - EXPECT_EQ( - pref->SetPref(std::make_unique<base::Value>(CONTENT_SETTING_ASK).get()), - extensions::settings_private::SetPrefResult::PREF_TYPE_MISMATCH); - EXPECT_EQ(pref->SetPref( - std::make_unique<base::Value>(CONTENT_SETTING_DEFAULT).get()), + EXPECT_EQ(pref->SetPref(std::make_unique<base::Value>("default").get()), extensions::settings_private::SetPrefResult::PREF_TYPE_MISMATCH); + EXPECT_EQ(pref->SetPref(std::make_unique<base::Value>("ask").get()), + extensions::settings_private::SetPrefResult::PREF_TYPE_MISMATCH); + EXPECT_EQ( + pref->SetPref( + std::make_unique<base::Value>("detect_important_content").get()), + extensions::settings_private::SetPrefResult::PREF_TYPE_MISMATCH); EXPECT_EQ(pref->SetPref(std::make_unique<base::Value>(100).get()), extensions::settings_private::SetPrefResult::PREF_TYPE_MISMATCH); } @@ -645,9 +643,8 @@ settings_api::Enforcement::ENFORCEMENT_ENFORCED); // Ensure the preference cannot be changed when it is enforced. - EXPECT_EQ( - pref->SetPref(std::make_unique<base::Value>(CONTENT_SETTING_BLOCK).get()), - extensions::settings_private::SetPrefResult::PREF_NOT_MODIFIABLE); + EXPECT_EQ(pref->SetPref(std::make_unique<base::Value>("block").get()), + extensions::settings_private::SetPrefResult::PREF_NOT_MODIFIABLE); EXPECT_EQ( map->GetDefaultContentSetting(ContentSettingsType::COOKIES, nullptr), CONTENT_SETTING_ALLOW);
diff --git a/chrome/browser/enterprise/connectors/connectors_service.cc b/chrome/browser/enterprise/connectors/connectors_service.cc index ec6ba37..65aeb49c 100644 --- a/chrome/browser/enterprise/connectors/connectors_service.cc +++ b/chrome/browser/enterprise/connectors/connectors_service.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/enterprise/connectors/reporting/extension_install_event_router.h" #include "chrome/browser/enterprise/connectors/service_provider_config.h" #include "chrome/browser/enterprise/util/affiliation.h" +#include "chrome/browser/extensions/chrome_content_browser_client_extensions_part.h" #include "chrome/browser/policy/chrome_browser_policy_connector.h" #include "chrome/browser/policy/dm_token_utils.h" #include "chrome/browser/profiles/profile.h" @@ -605,6 +606,13 @@ content::BrowserContext* ConnectorsServiceFactory::GetBrowserContextToUse( content::BrowserContext* context) const { + // Do not construct the connectors service if the extensions are disabled for + // the given context. + if (extensions::ChromeContentBrowserClientExtensionsPart:: + AreExtensionsDisabledForProfile(context)) { + return nullptr; + } + // On Chrome OS, settings from the primary/main profile apply to all // profiles, besides incognito. // However, the primary/main profile might not exist in tests - then the
diff --git a/chrome/browser/extensions/api/scripting/scripting_api.cc b/chrome/browser/extensions/api/scripting/scripting_api.cc index 089980b0..4a0bdc63 100644 --- a/chrome/browser/extensions/api/scripting/scripting_api.cc +++ b/chrome/browser/extensions/api/scripting/scripting_api.cc
@@ -20,7 +20,6 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" -#include "extensions/browser/api/extension_types_utils.h" #include "extensions/browser/api/scripting/scripting_constants.h" #include "extensions/browser/extension_api_frame_id_map.h" #include "extensions/browser/extension_file_task_runner.h" @@ -41,6 +40,7 @@ #include "extensions/common/permissions/api_permission.h" #include "extensions/common/permissions/permissions_data.h" #include "extensions/common/utils/content_script_utils.h" +#include "extensions/common/utils/extension_types_utils.h" namespace extensions { @@ -51,6 +51,9 @@ "Duplicate file specified: '*'."; constexpr char kExactlyOneOfCssAndFilesError[] = "Exactly one of 'css' and 'files' must be specified."; +constexpr char kFilesExceededSizeLimitError[] = + "Scripts could not be loaded because '*' exceeds the maximum script size " + "or the extension's maximum total script size."; // Note: CSS always injects as soon as possible, so we default to // document_start. Because of tab loading, there's no guarantee this will @@ -505,6 +508,15 @@ bool are_script_files_valid = script_parsing::ValidateFileSources( *scripts, symlink_policy, &error, &warnings); + // Script files over the per script/extension limit are recorded as warnings. + // However, for the scripting API we should treat "install warnings" as + // errors by turning this call into a no-op and returning an error. + if (!warnings.empty() && error.empty()) { + error = ErrorUtils::FormatErrorMessage(kFilesExceededSizeLimitError, + warnings[0].specific); + are_script_files_valid = false; + } + return std::make_pair(std::move(scripts), are_script_files_valid ? absl::nullopt : absl::make_optional(error));
diff --git a/chrome/browser/extensions/api/scripting/scripting_apitest.cc b/chrome/browser/extensions/api/scripting/scripting_apitest.cc index 6012620a..f7ba1aa7 100644 --- a/chrome/browser/extensions/api/scripting/scripting_apitest.cc +++ b/chrome/browser/extensions/api/scripting/scripting_apitest.cc
@@ -22,6 +22,7 @@ #include "extensions/browser/background_script_executor.h" #include "extensions/browser/disable_reason.h" #include "extensions/common/features/feature_channel.h" +#include "extensions/common/utils/content_script_utils.h" #include "extensions/test/extension_test_message_listener.h" #include "extensions/test/result_catcher.h" #include "extensions/test/test_extension_dir.h" @@ -190,6 +191,15 @@ embedded_test_server()->GetURL("google.com", "/simple.html")); } +IN_PROC_BROWSER_TEST_F(ScriptingAPITest, DynamicContentScriptsSizeLimits) { + auto single_scripts_limit_reset = + script_parsing::CreateScopedMaxScriptLengthForTesting(700u); + auto extension_scripts_limit_reset = + script_parsing::CreateScopedMaxScriptsLengthPerExtensionForTesting(1200u); + ASSERT_TRUE(RunExtensionTest("scripting/dynamic_scripts_size_limits")) + << message_; +} + // Tests that calling scripting.executeScript works on a newly created tab // before the initial commit has happened. Regression for crbug.com/1191971. IN_PROC_BROWSER_TEST_F(ScriptingAPITest, ExecuteScriptBeforeInitialCommit) {
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index 49fa6bc8..d616df56 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -327,7 +327,7 @@ (*s_allowlist)[::prefs::kCookieControlsMode] = settings_api::PrefType::PREF_TYPE_NUMBER; (*s_allowlist)[::content_settings::kCookieDefaultContentSetting] = - settings_api::PrefType::PREF_TYPE_NUMBER; + settings_api::PrefType::PREF_TYPE_STRING; (*s_allowlist)[::content_settings::kCookiePrimarySetting] = settings_api::PrefType::PREF_TYPE_NUMBER; (*s_allowlist)[::content_settings::kCookieSessionOnly] =
diff --git a/chrome/browser/extensions/chrome_app_sorting.cc b/chrome/browser/extensions/chrome_app_sorting.cc index 4086af58..f51ac242 100644 --- a/chrome/browser/extensions/chrome_app_sorting.cc +++ b/chrome/browser/extensions/chrome_app_sorting.cc
@@ -79,6 +79,7 @@ default_ordinals_created_(false) { ExtensionIdList extensions; ExtensionPrefs::Get(browser_context_)->GetExtensions(&extensions); + registry_observation_.Observe(ExtensionRegistry::Get(browser_context_)); InitializePageOrdinalMap(extensions); MigrateAppIndex(extensions); } @@ -745,4 +746,15 @@ return result; } +void ChromeAppSorting::OnExtensionLoaded( + content::BrowserContext* browser_context, + const Extension* extension) { + if (!extension->RequiresSortOrdinal()) { + return; + } + + SetExtensionVisible(extension->id(), extension->ShouldDisplayInNewTabPage()); + EnsureValidOrdinals(extension->id(), syncer::StringOrdinal()); +} + } // namespace extensions
diff --git a/chrome/browser/extensions/chrome_app_sorting.h b/chrome/browser/extensions/chrome_app_sorting.h index 4df5721..46096842 100644 --- a/chrome/browser/extensions/chrome_app_sorting.h +++ b/chrome/browser/extensions/chrome_app_sorting.h
@@ -24,6 +24,8 @@ #include "components/sync/model/string_ordinal.h" #include "extensions/browser/app_sorting.h" #include "extensions/browser/extension_prefs.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/browser/extension_registry_observer.h" #include "extensions/common/extension_id.h" namespace web_app { @@ -34,6 +36,7 @@ namespace extensions { class ChromeAppSorting : public AppSorting, + public ExtensionRegistryObserver, public web_app::AppRegistrarObserver, public web_app::WebAppInstallManagerObserver { public: @@ -175,6 +178,10 @@ // Returns the number of items in |m| visible on the new tab page. size_t CountItemsVisibleOnNtp(const AppLaunchOrdinalMap& m) const; + // ExtensionRegistryObserver: + void OnExtensionLoaded(content::BrowserContext* browser_context, + const Extension* extension) override; + const raw_ptr<content::BrowserContext, DanglingUntriaged> browser_context_ = nullptr; raw_ptr<const web_app::WebAppRegistrar, DanglingUntriaged> @@ -207,6 +214,12 @@ // The set of extensions that don't appear in the new tab page. std::set<std::string> ntp_hidden_extensions_; + // Observe the ExtensionRegistry. The registry is guaranteed to outlive this + // object, since this is owned by the ExtensionSystem, which depends on the + // ExtensionRegistry. + base::ScopedObservation<ExtensionRegistry, ExtensionRegistryObserver> + registry_observation_{this}; + base::WeakPtrFactory<ChromeAppSorting> weak_factory_{this}; };
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.cc b/chrome/browser/extensions/chrome_extensions_browser_client.cc index f016bcf..ff14f8f6 100644 --- a/chrome/browser/extensions/chrome_extensions_browser_client.cc +++ b/chrome/browser/extensions/chrome_extensions_browser_client.cc
@@ -142,6 +142,10 @@ ChromeExtensionsBrowserClient::~ChromeExtensionsBrowserClient() {} +void ChromeExtensionsBrowserClient::StartTearDown() { + user_script_listener_.StartTearDown(); +} + bool ChromeExtensionsBrowserClient::IsShuttingDown() { return g_browser_process->IsShuttingDown(); }
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.h b/chrome/browser/extensions/chrome_extensions_browser_client.h index 90cec7b..d33bb1c2 100644 --- a/chrome/browser/extensions/chrome_extensions_browser_client.h +++ b/chrome/browser/extensions/chrome_extensions_browser_client.h
@@ -52,6 +52,14 @@ ~ChromeExtensionsBrowserClient() override; + // Called by the BrowserProcess to indicate that we should perform any + // teardown necessary before being destroyed (e.g. unsubscribing observers, or + // any other pre-emptive freeing of resources. Note that we may still receive + // calls from other shutting down objects after this call, so this should + // primarily be used for things that may need to be cleaned up before other + // parts of the browser). + void StartTearDown(); + // ExtensionsBrowserClient overrides: bool IsShuttingDown() override; bool AreExtensionsDisabled(const base::CommandLine& command_line,
diff --git a/chrome/browser/extensions/content_script_apitest.cc b/chrome/browser/extensions/content_script_apitest.cc index 8960971..a2552b8f 100644 --- a/chrome/browser/extensions/content_script_apitest.cc +++ b/chrome/browser/extensions/content_script_apitest.cc
@@ -431,15 +431,22 @@ expected_warnings.emplace_back( l10n_util::GetStringFUTF8(IDS_EXTENSION_CONTENT_SCRIPT_FILE_TOO_LARGE, u"big.js"), - api::content_scripts::ManifestKeys::kContentScripts); + api::content_scripts::ManifestKeys::kContentScripts, "big.js"); expected_warnings.emplace_back( l10n_util::GetStringFUTF8(IDS_EXTENSION_CONTENT_SCRIPT_FILE_TOO_LARGE, u"inject_element_2.js"), - api::content_scripts::ManifestKeys::kContentScripts); + api::content_scripts::ManifestKeys::kContentScripts, + "inject_element_2.js"); EXPECT_EQ(extension->install_warnings(), expected_warnings); } +IN_PROC_BROWSER_TEST_F(ContentScriptApiTest, MainWorldInjections) { + ASSERT_TRUE(StartEmbeddedTestServer()); + ASSERT_TRUE(RunExtensionTest("content_scripts/main_world_injections")) + << message_; +} + class ContentScriptCssInjectionTest : public ExtensionApiTest { protected: // TODO(rdevlin.cronin): Make a testing switch that looks like FeatureSwitch,
diff --git a/chrome/browser/extensions/user_script_listener.cc b/chrome/browser/extensions/user_script_listener.cc index 98766f4..9e937da2 100644 --- a/chrome/browser/extensions/user_script_listener.cc +++ b/chrome/browser/extensions/user_script_listener.cc
@@ -10,13 +10,11 @@ #include "base/metrics/histogram_macros.h" #include "base/timer/elapsed_timer.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/chrome_content_browser_client_extensions_part.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_throttle.h" -#include "content/public/browser/notification_service.h" #include "extensions/browser/api/scripting/scripting_utils.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/user_script_manager.h" @@ -94,10 +92,9 @@ extension_registry_observations_.AddObservation( ExtensionRegistry::Get(profile)); } - } - registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED, - content::NotificationService::AllSources()); + profile_manager_observation_.Observe(g_browser_process->profile_manager()); + } } std::unique_ptr<NavigationThrottle> @@ -115,6 +112,10 @@ UserScriptsReady(context); } +void UserScriptListener::StartTearDown() { + profile_manager_observation_.Reset(); +} + void UserScriptListener::SetUserScriptsNotReadyForTesting( content::BrowserContext* context) { AppendNewURLPatterns(context, {URLPattern(URLPattern::SCHEME_ALL, @@ -218,25 +219,16 @@ dynamic_patterns.end()); } -void UserScriptListener::Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - switch (type) { - case chrome::NOTIFICATION_PROFILE_ADDED: { - Profile* profile = content::Source<Profile>(source).ptr(); - if (extensions::ChromeContentBrowserClientExtensionsPart:: - AreExtensionsDisabledForProfile(profile)) { - break; - } - auto* registry = ExtensionRegistry::Get(profile); - DCHECK(registry); - DCHECK(!extension_registry_observations_.IsObservingSource(registry)); - extension_registry_observations_.AddObservation(registry); - break; - } - default: - NOTREACHED(); +void UserScriptListener::OnProfileAdded(Profile* profile) { + if (extensions::ChromeContentBrowserClientExtensionsPart:: + AreExtensionsDisabledForProfile(profile)) { + return; } + + auto* registry = ExtensionRegistry::Get(profile); + DCHECK(registry); + DCHECK(!extension_registry_observations_.IsObservingSource(registry)); + extension_registry_observations_.AddObservation(registry); } void UserScriptListener::OnExtensionLoaded(
diff --git a/chrome/browser/extensions/user_script_listener.h b/chrome/browser/extensions/user_script_listener.h index 00e0001..5c9760d5 100644 --- a/chrome/browser/extensions/user_script_listener.h +++ b/chrome/browser/extensions/user_script_listener.h
@@ -11,13 +11,14 @@ #include "base/containers/circular_deque.h" #include "base/memory/weak_ptr.h" #include "base/scoped_multi_source_observation.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" +#include "base/scoped_observation.h" +#include "chrome/browser/profiles/profile_manager_observer.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_registry_observer.h" class GURL; class URLPattern; +class ProfileManager; namespace content { class BrowserContext; @@ -34,8 +35,8 @@ // script has not been loaded yet, then we delay the request. // // This class lives on the UI thread. -class UserScriptListener : public content::NotificationObserver, - public ExtensionRegistryObserver { +class UserScriptListener : public ExtensionRegistryObserver, + public ProfileManagerObserver { public: UserScriptListener(); @@ -53,6 +54,10 @@ // BrowserContext. void OnScriptsLoaded(content::BrowserContext* context); + // Called when the owning BrowserClient is notified that we should begin + // releasing our resources. + void StartTearDown(); + void SetUserScriptsNotReadyForTesting(content::BrowserContext* context); void TriggerUserScriptsReadyForTesting(content::BrowserContext* context); @@ -104,10 +109,8 @@ const Extension* extension, URLPatterns* patterns); - // content::NotificationObserver - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; + // ProfileManagerObserver + void OnProfileAdded(Profile* profile) override; // ExtensionRegistryObserver: void OnExtensionLoaded(content::BrowserContext* browser_context, @@ -121,7 +124,8 @@ extensions::ExtensionRegistryObserver> extension_registry_observations_{this}; - content::NotificationRegistrar registrar_; + base::ScopedObservation<ProfileManager, ProfileManagerObserver> + profile_manager_observation_{this}; }; } // namespace extensions
diff --git a/chrome/browser/extensions/user_script_listener_unittest.cc b/chrome/browser/extensions/user_script_listener_unittest.cc index 011c7e9..2ab843b7 100644 --- a/chrome/browser/extensions/user_script_listener_unittest.cc +++ b/chrome/browser/extensions/user_script_listener_unittest.cc
@@ -86,12 +86,20 @@ profile_manager_( new TestingProfileManager(TestingBrowserProcess::GetGlobal())) {} + ~UserScriptListenerTest() override {} + + UserScriptListenerTest(const UserScriptListenerTest&) = delete; + UserScriptListenerTest& operator=(const UserScriptListenerTest&) = delete; + void SetUp() override { #if BUILDFLAG(IS_CHROMEOS_ASH) user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>( std::make_unique<ash::FakeChromeUserManager>()); #endif ASSERT_TRUE(profile_manager_->SetUp()); + // The listener must be set up after the profile manager has been set up/ + // installed itself on the browser process. + listener_ = std::make_unique<UserScriptListener>(); profile_ = profile_manager_->CreateTestingProfile("test-profile"); ASSERT_TRUE(profile_); TestExtensionSystem* test_extension_system = @@ -105,6 +113,14 @@ profile_, std::move(instance)); } + void TearDown() override { + // The Listener unsubscribes itself from the profile in StartTearDown; + // failure to unsubscribe will result in the profile_manager's destructor + // throwing an error since there's still a subscription in the callback + // list. + listener_->StartTearDown(); + } + void MarkNavigationResumed() { was_navigation_resumed_ = true; } protected: @@ -133,7 +149,7 @@ std::unique_ptr<NavigationThrottle> CreateListenerNavigationThrottle( content::NavigationHandle* handle) { std::unique_ptr<NavigationThrottle> throttle = - listener_.CreateNavigationThrottle(handle); + listener_->CreateNavigationThrottle(handle); throttle->set_resume_callback_for_testing( base::BindRepeating(&UserScriptListenerTest::MarkNavigationResumed, base::Unretained(this))); @@ -151,7 +167,7 @@ content::BrowserTaskEnvironment task_environment_; content::RenderViewHostTestEnabler rvh_test_enabler_; std::unique_ptr<TestingProfileManager> profile_manager_; - UserScriptListener listener_; + std::unique_ptr<UserScriptListener> listener_; raw_ptr<TestingProfile> profile_ = nullptr; raw_ptr<ExtensionService> service_ = nullptr; bool was_navigation_resumed_ = false; @@ -172,7 +188,7 @@ CreateListenerNavigationThrottle(&handle); EXPECT_EQ(NavigationThrottle::DEFER, throttle->WillStartRequest()); - listener_.TriggerUserScriptsReadyForTesting(profile_); + listener_->TriggerUserScriptsReadyForTesting(profile_); EXPECT_TRUE(was_navigation_resumed_); } @@ -190,7 +206,7 @@ CreateListenerNavigationThrottle(&handle); EXPECT_EQ(NavigationThrottle::DEFER, throttle->WillStartRequest()); - listener_.TriggerUserScriptsReadyForTesting(profile_); + listener_->TriggerUserScriptsReadyForTesting(profile_); EXPECT_TRUE(was_navigation_resumed_); } @@ -210,7 +226,7 @@ // listener that the user scripts have been updated. EXPECT_FALSE(was_navigation_resumed_); - listener_.TriggerUserScriptsReadyForTesting(profile_); + listener_->TriggerUserScriptsReadyForTesting(profile_); EXPECT_TRUE(was_navigation_resumed_); } @@ -218,7 +234,7 @@ content::MockNavigationHandle handle(GURL(kMatchingUrl), web_contents_->GetPrimaryMainFrame()); std::unique_ptr<NavigationThrottle> throttle = - listener_.CreateNavigationThrottle(&handle); + listener_->CreateNavigationThrottle(&handle); EXPECT_EQ(nullptr, throttle); } @@ -229,7 +245,7 @@ content::MockNavigationHandle handle(GURL(kNotMatchingUrl), web_contents_->GetPrimaryMainFrame()); std::unique_ptr<NavigationThrottle> throttle = - listener_.CreateNavigationThrottle(&handle); + listener_->CreateNavigationThrottle(&handle); EXPECT_EQ(nullptr, throttle); } @@ -258,11 +274,11 @@ // When the first profile's user scripts are ready, the request should still // be blocked waiting for profile2. - listener_.TriggerUserScriptsReadyForTesting(profile_); + listener_->TriggerUserScriptsReadyForTesting(profile_); EXPECT_FALSE(was_navigation_resumed_); // After profile2 is ready, the request should proceed. - listener_.TriggerUserScriptsReadyForTesting(profile2); + listener_->TriggerUserScriptsReadyForTesting(profile2); EXPECT_TRUE(was_navigation_resumed_); } @@ -274,10 +290,10 @@ content::MockNavigationHandle handle(GURL(kMatchingUrl), web_contents_->GetPrimaryMainFrame()); std::unique_ptr<NavigationThrottle> throttle = - listener_.CreateNavigationThrottle(&handle); + listener_->CreateNavigationThrottle(&handle); ASSERT_TRUE(throttle); - listener_.TriggerUserScriptsReadyForTesting(profile_); + listener_->TriggerUserScriptsReadyForTesting(profile_); ASSERT_EQ(content::NavigationThrottle::PROCEED, throttle->WillStartRequest()); }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 699925cc..937095c 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2671,11 +2671,6 @@ "expiry_milestone": -1 }, { - "name": "enable-networking-in-diagnostics-app", - "owners": [ "//ash/webui/diagnostics_ui/OWNERS" ], - "expiry_milestone": 112 - }, - { "name": "enable-neural-palm-adaptive-hold", "owners": [ "robsc", "napper", "alanlxl" ], "expiry_milestone": 130 @@ -3202,7 +3197,7 @@ { "name": "enable-user-policy", "owners": [ "vincb" ], - "expiry_milestone": 110 + "expiry_milestone": 130 }, { "name": "enable-vaapi-av1-decode-acceleration", @@ -3600,11 +3595,6 @@ "expiry_milestone": 112 }, { - "name": "fast-pair-subsequent-pairing-ux", - "owners": [ "//ash/quick_pair/OWNERS", "dclasson@google.com" ], - "expiry_milestone": 106 - }, - { "name": "feature-notification-guide", "owners": [ "shaktisahu"], "expiry_milestone": 110 @@ -5257,7 +5247,7 @@ "expiry_milestone": 117 }, { - "name": "oobe-material-next", + "name": "oobe-jelly", "owners": [ "ziegltrum@google.com", "cros-oobe@google.com" ], "expiry_milestone": 118 }, @@ -6315,16 +6305,6 @@ "expiry_milestone": 114 }, { - "name": "smart-lock-sign-in-removed", - "owners": [ "bhartmire", "better-together-dev@google.com" ], - "expiry_milestone": 105 - }, - { - "name": "smart-lock-ui-revamp", - "owners": [ "cclem", "better-together-dev@google.com" ], - "expiry_milestone": 105 - }, - { "name": "smart-sorting-new-overflow-menu", "owners": [ "bwwilliams@google.com", "bling-flags@google.com" ], "expiry_milestone": 111
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 37dfe92..972f87fb 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -3474,10 +3474,6 @@ "of the screen height, otherwise the maximum height is 100% of the screen " "height. In both cases, Custom Tabs will yield to the top status bar when " "at full stop"; -const char kCCTResizableAllowResizeByUserGestureName[] = - "Bottom sheet Custom Tabs allow resize by user gesture"; -const char kCCTResizableAllowResizeByUserGestureDescription[] = - "Enable user gesture to resize bottom sheet Custom Tabs"; const char kCCTResizableForThirdPartiesName[] = "Bottom sheet Custom Tabs (third party)"; const char kCCTResizableForThirdPartiesDescription[] = @@ -4992,12 +4988,6 @@ "Allow using Fast Pair on devices which don't support hardware offloading " "of BLE scans. For development use."; -const char kFastPairSubsequentPairingUXName[] = - "Enable Fast Pair Subsequent Pairing UX"; -const char kFastPairSubsequentPairingUXDescription[] = - "Enables the \"Subsequent Pairing\" Fast Pair scenario in Bluetooth " - "Settings and Quick Settings."; - const char kFastPairSavedDevicesName[] = "Enable Fast Pair Saved Devices"; const char kFastPairSavedDevicesDescription[] = "Enables the Fast Pair \"Saved Devices\" page to display a list of the " @@ -5281,11 +5271,6 @@ "Allows CrOS to analyze Android network information to provide more " "context on connection errors"; -const char kEnableNetworkingInDiagnosticsAppName[] = - "Enable networking cards in the Diagnostics App"; -const char kEnableNetworkingInDiagnosticsAppDescription[] = - "Enable networking cards in the Diagnostics App"; - const char kEnableOAuthIppName[] = "Enable OAuth when printing via the IPP protocol"; const char kEnableOAuthIppDescription[] = @@ -5831,17 +5816,6 @@ "Ctrl-Alt-I shows a heads-up display view in the top-left corner. Helps " "debug hardware issues that generate spurious touch events."; -const char kSmartLockSignInRemovedName[] = "Remove Sign in with Smart Lock"; -const char kSmartLockSignInRemovedDescription[] = - "Deprecates Sign in with Smart Lock feature. Hides Smart Lock on the sign " - "in screen, removes the Smart Lock subpage in settings, and shows a " - "one-time notification for users who previously had this feature enabled."; - -const char kSmartLockUIRevampName[] = "Enable Smart Lock UI Revamp"; -const char kSmartLockUIRevampDescription[] = - "Replaces the existing Smart Lock UI on the lock screen with a new design " - "and adds Smart Lock to the 'Lock screen and sign-in' section of settings."; - const char kSpectreVariant2MitigationName[] = "Spectre variant 2 mitigation"; const char kSpectreVariant2MitigationDescription[] = "Controls whether Spectre variant 2 mitigation is enabled when " @@ -6012,9 +5986,9 @@ "Feature to allow MAC address randomization to be enabled for WiFi " "networks."; -const char kOobeMaterialNextName[] = "Material Next design for OOBE"; -const char kOobeMaterialNextDescription[] = - "Feature to enable the Material Next design in out of box experience."; +const char kOobeJellyName[] = "Jelly design for OOBE"; +const char kOobeJellyDescription[] = + "Feature to enable the Jelly design in out of box experience."; const char kLibAssistantV2MigrationName[] = "LibAssistant V2 migration"; const char kLibAssistantV2MigrationDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index c15183b..b5481b28 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1982,8 +1982,6 @@ extern const char kCCTResizable90MaximumHeightName[]; extern const char kCCTResizable90MaximumHeightDescription[]; -extern const char kCCTResizableAllowResizeByUserGestureName[]; -extern const char kCCTResizableAllowResizeByUserGestureDescription[]; extern const char kCCTResizableForThirdPartiesName[]; extern const char kCCTResizableForThirdPartiesDescription[]; extern const char kCCTResizableSideSheetName[]; @@ -2868,9 +2866,6 @@ extern const char kFastPairSoftwareScanningName[]; extern const char kFastPairSoftwareScanningDescription[]; -extern const char kFastPairSubsequentPairingUXName[]; -extern const char kFastPairSubsequentPairingUXDescription[]; - extern const char kFastPairSavedDevicesName[]; extern const char kFastPairSavedDevicesDescription[]; @@ -3023,9 +3018,6 @@ extern const char kEcheSWACheckAndroidNetworkInfoName[]; extern const char kEcheSWACheckAndroidNetworkInfoDescription[]; -extern const char kEnableNetworkingInDiagnosticsAppName[]; -extern const char kEnableNetworkingInDiagnosticsAppDescription[]; - extern const char kEnableOAuthIppName[]; extern const char kEnableOAuthIppDescription[]; @@ -3360,12 +3352,6 @@ extern const char kSimLockPolicyName[]; extern const char kSimLockPolicyDescription[]; -extern const char kSmartLockSignInRemovedName[]; -extern const char kSmartLockSignInRemovedDescription[]; - -extern const char kSmartLockUIRevampName[]; -extern const char kSmartLockUIRevampDescription[]; - extern const char kSnoopingProtectionName[]; extern const char kSnoopingProtectionDescription[]; @@ -3468,8 +3454,8 @@ extern const char kMacAddressRandomizationName[]; extern const char kMacAddressRandomizationDescription[]; -extern const char kOobeMaterialNextName[]; -extern const char kOobeMaterialNextDescription[]; +extern const char kOobeJellyName[]; +extern const char kOobeJellyDescription[]; extern const char kLibAssistantV2MigrationName[]; extern const char kLibAssistantV2MigrationDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 5d215b3..d12a248 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -192,7 +192,6 @@ &kCCTRemoveRemoteViewIds, &kCCTReportParallelRequestStatus, &kCCTResizable90MaximumHeight, - &kCCTResizableAllowResizeByUserGesture, &kCCTResizableForThirdParties, &kCCTResizableSideSheet, &kCCTRetainingStateInMemory, @@ -558,10 +557,6 @@ "CCTResizable90MaximumHeight", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kCCTResizableAllowResizeByUserGesture, - "CCTResizableAllowResizeByUserGesture", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kCCTResizableForThirdParties, "CCTResizableForThirdParties", 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 fec97553..e209833 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -49,7 +49,6 @@ BASE_DECLARE_FEATURE(kCCTRemoveRemoteViewIds); BASE_DECLARE_FEATURE(kCCTReportParallelRequestStatus); BASE_DECLARE_FEATURE(kCCTResizable90MaximumHeight); -BASE_DECLARE_FEATURE(kCCTResizableAllowResizeByUserGesture); BASE_DECLARE_FEATURE(kCCTResizableForThirdParties); BASE_DECLARE_FEATURE(kCCTResizableSideSheet); BASE_DECLARE_FEATURE(kCCTResourcePrefetch);
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 e6e0143..e158310 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
@@ -573,8 +573,6 @@ new CachedFlag(CCT_REMOVE_REMOTE_VIEW_IDS, true); public static final CachedFlag sCctResizable90MaximumHeight = new CachedFlag(CCT_RESIZABLE_90_MAXIMUM_HEIGHT, false); - public static final CachedFlag sCctResizableAllowResizeByUserGesture = - new CachedFlag(CCT_RESIZABLE_ALLOW_RESIZE_BY_USER_GESTURE, false); public static final CachedFlag sCctResizableForThirdParties = new CachedFlag(CCT_RESIZABLE_FOR_THIRD_PARTIES, false); public static final CachedFlag sCctResizableSideSheet =
diff --git a/chrome/browser/net/net_error_diagnostics_dialog_chromeos.cc b/chrome/browser/net/net_error_diagnostics_dialog_chromeos.cc index 9ca45d50..1e0758a 100644 --- a/chrome/browser/net/net_error_diagnostics_dialog_chromeos.cc +++ b/chrome/browser/net/net_error_diagnostics_dialog_chromeos.cc
@@ -4,16 +4,13 @@ #include "chrome/browser/net/net_error_diagnostics_dialog.h" -#include "ash/constants/ash_features.h" #include "ash/webui/connectivity_diagnostics/url_constants.h" -#include "base/check.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h" #include "chrome/browser/ui/chrome_pages.h" namespace { void LaunchDiagnosticsAppAtConnectivityScreen(Profile* profile) { - DCHECK(ash::features::IsNetworkingInDiagnosticsAppEnabled()); std::string diagnostics_connectivity_url = { "chrome://diagnostics/?connectivity"}; ash::SystemAppLaunchParams params; @@ -33,10 +30,5 @@ Profile* profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); - if (ash::features::IsNetworkingInDiagnosticsAppEnabled()) { - LaunchDiagnosticsAppAtConnectivityScreen(std::move(profile)); - } else { - ash::LaunchSystemWebAppAsync( - profile, ash::SystemWebAppType::CONNECTIVITY_DIAGNOSTICS); - } + LaunchDiagnosticsAppAtConnectivityScreen(std::move(profile)); }
diff --git a/chrome/browser/password_manager/android/BUILD.gn b/chrome/browser/password_manager/android/BUILD.gn index 8baeb82..03a8f87 100644 --- a/chrome/browser/password_manager/android/BUILD.gn +++ b/chrome/browser/password_manager/android/BUILD.gn
@@ -437,6 +437,7 @@ "password_store_android_backend_bridge_helper_impl_unittest.cc", "password_store_android_backend_unittest.cc", "password_sync_controller_delegate_android_unittest.cc", + "save_update_password_message_delegate_unittest.cc", ] deps = [
diff --git a/chrome/browser/password_manager/android/password_sync_controller_delegate_android.cc b/chrome/browser/password_manager/android/password_sync_controller_delegate_android.cc index 225b73c2..124908e 100644 --- a/chrome/browser/password_manager/android/password_sync_controller_delegate_android.cc +++ b/chrome/browser/password_manager/android/password_sync_controller_delegate_android.cc
@@ -55,7 +55,8 @@ syncer::SyncService* sync_service) { sync_service_ = sync_service; sync_observation_.Observe(sync_service); - is_sync_enabled_ = IsSyncEnabled(IsPasswordSyncEnabled(sync_service_)); + is_sync_enabled_ = IsSyncEnabled(IsPasswordSyncEnabled(sync_service)); + UpdateCredentialManagerSyncStatus(is_sync_enabled_.value()); } void PasswordSyncControllerDelegateAndroid::OnSyncStarting( @@ -130,20 +131,7 @@ void PasswordSyncControllerDelegateAndroid::OnStateChanged( syncer::SyncService* sync) { - // Notify credential manager about current account on startup or if - // password sync setting has changed. - if (sync_util::IsPasswordSyncEnabled(sync) && - (!credential_manager_sync_setting_.has_value() || - credential_manager_sync_setting_ == IsSyncEnabled(false))) { - bridge_->NotifyCredentialManagerWhenSyncing(); - credential_manager_sync_setting_ = IsSyncEnabled(true); - } - if (!sync_util::IsPasswordSyncEnabled(sync) && - (!credential_manager_sync_setting_.has_value() || - credential_manager_sync_setting_ == IsSyncEnabled(true))) { - bridge_->NotifyCredentialManagerWhenNotSyncing(); - credential_manager_sync_setting_ = IsSyncEnabled(false); - } + UpdateCredentialManagerSyncStatus(IsSyncEnabled(IsPasswordSyncEnabled(sync))); } void PasswordSyncControllerDelegateAndroid::OnSyncShutdown( @@ -173,6 +161,21 @@ } } +void PasswordSyncControllerDelegateAndroid::UpdateCredentialManagerSyncStatus( + IsSyncEnabled is_enabled) { + if (credential_manager_sync_setting_.has_value() && + credential_manager_sync_setting_ == is_enabled) { + return; + } + + credential_manager_sync_setting_ = is_enabled; + if (is_enabled) { + bridge_->NotifyCredentialManagerWhenSyncing(); + } else { + bridge_->NotifyCredentialManagerWhenNotSyncing(); + } +} + base::WeakPtr<syncer::ModelTypeControllerDelegate> PasswordSyncControllerDelegateAndroid::GetWeakPtrToBaseClass() { return weak_ptr_factory_.GetWeakPtr();
diff --git a/chrome/browser/password_manager/android/password_sync_controller_delegate_android.h b/chrome/browser/password_manager/android/password_sync_controller_delegate_android.h index cb345df..20322327 100644 --- a/chrome/browser/password_manager/android/password_sync_controller_delegate_android.h +++ b/chrome/browser/password_manager/android/password_sync_controller_delegate_android.h
@@ -72,6 +72,10 @@ private: using IsSyncEnabled = base::StrongAlias<struct IsSyncEnabledTag, bool>; + // Notify credential manager about current account on startup or if + // password sync setting has changed. + void UpdateCredentialManagerSyncStatus(IsSyncEnabled is_enabled); + base::WeakPtr<syncer::ModelTypeControllerDelegate> GetWeakPtrToBaseClass(); const std::unique_ptr<PasswordSyncControllerDelegateBridge> bridge_;
diff --git a/chrome/browser/password_manager/android/password_sync_controller_delegate_android_unittest.cc b/chrome/browser/password_manager/android/password_sync_controller_delegate_android_unittest.cc index f63fac52..b864cb7 100644 --- a/chrome/browser/password_manager/android/password_sync_controller_delegate_android_unittest.cc +++ b/chrome/browser/password_manager/android/password_sync_controller_delegate_android_unittest.cc
@@ -45,7 +45,7 @@ void RunUntilIdle() { task_environment_.RunUntilIdle(); } MockPasswordSyncControllerDelegateBridge* bridge() { return bridge_; } - syncer::SyncService* sync_service() { return &sync_service_; } + syncer::TestSyncService* sync_service() { return &sync_service_; } PasswordSyncControllerDelegateAndroid* sync_controller_delegate() { return sync_controller_delegate_.get(); } @@ -70,15 +70,54 @@ }; TEST_F(PasswordSyncControllerDelegateAndroidTest, + OnSyncStatusEnabledOnStartup) { + EXPECT_CALL(*bridge(), NotifyCredentialManagerWhenSyncing); + sync_controller_delegate()->OnSyncServiceInitialized(sync_service()); + testing::Mock::VerifyAndClearExpectations(bridge()); + + // Check that observing the same event again will not trigger another + // notification. + sync_controller_delegate()->OnStateChanged(sync_service()); +} + +TEST_F(PasswordSyncControllerDelegateAndroidTest, + OnSyncStatusEnabledWithoutPasswordsOnStartup) { + sync_service()->GetUserSettings()->SetSelectedTypes(/*sync_everything=*/false, + /*types=*/{}); + + EXPECT_CALL(*bridge(), NotifyCredentialManagerWhenNotSyncing); + sync_controller_delegate()->OnStateChanged(sync_service()); + testing::Mock::VerifyAndClearExpectations(bridge()); + + // Check that observing the same event again will not trigger another + // notification. + sync_controller_delegate()->OnStateChanged(sync_service()); +} + +TEST_F(PasswordSyncControllerDelegateAndroidTest, + OnSyncStatusDisabledOnStartup) { + sync_service()->SetDisableReasons( + syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN); + + EXPECT_CALL(*bridge(), NotifyCredentialManagerWhenNotSyncing); + sync_controller_delegate()->OnStateChanged(sync_service()); + testing::Mock::VerifyAndClearExpectations(bridge()); + + // Check that observing the same event again will not trigger another + // notification. + sync_controller_delegate()->OnStateChanged(sync_service()); +} + +TEST_F(PasswordSyncControllerDelegateAndroidTest, OnSyncStatusChangedToEnabledAfterStartup) { syncer::TestSyncService sync_service; EXPECT_CALL(*bridge(), NotifyCredentialManagerWhenSyncing); sync_controller_delegate()->OnStateChanged(&sync_service); + testing::Mock::VerifyAndClearExpectations(bridge()); // Check that observing the same event again will not trigger another // notification. - EXPECT_CALL(*bridge(), NotifyCredentialManagerWhenSyncing).Times(0); sync_controller_delegate()->OnStateChanged(&sync_service); } @@ -88,7 +127,6 @@ sync_service.GetUserSettings()->SetSelectedTypes(/*sync_everything=*/false, /*types=*/{}); - EXPECT_CALL(*bridge(), NotifyCredentialManagerWhenSyncing).Times(0); EXPECT_CALL(*bridge(), NotifyCredentialManagerWhenNotSyncing); sync_controller_delegate()->OnStateChanged(&sync_service); } @@ -117,10 +155,10 @@ EXPECT_CALL(*bridge(), NotifyCredentialManagerWhenNotSyncing); sync_controller_delegate()->OnStateChanged(&sync_service); + testing::Mock::VerifyAndClearExpectations(bridge()); // Check that observing the same event again will not trigger another // notification. - EXPECT_CALL(*bridge(), NotifyCredentialManagerWhenNotSyncing).Times(0); sync_controller_delegate()->OnStateChanged(&sync_service); } @@ -204,6 +242,7 @@ TEST_F(PasswordSyncControllerDelegateAndroidTest, AttachesObserverOnSyncServiceInitialized) { + EXPECT_CALL(*bridge(), NotifyCredentialManagerWhenSyncing); sync_controller_delegate()->OnSyncServiceInitialized(sync_service()); EXPECT_TRUE(sync_service()->HasObserver(sync_controller_delegate())); }
diff --git a/chrome/browser/password_manager/android/save_update_password_message_delegate.cc b/chrome/browser/password_manager/android/save_update_password_message_delegate.cc index 674f470a..ea4f225 100644 --- a/chrome/browser/password_manager/android/save_update_password_message_delegate.cc +++ b/chrome/browser/password_manager/android/save_update_password_message_delegate.cc
@@ -293,40 +293,74 @@ const password_manager::PasswordForm& pending_credentials, bool update_password, bool unified_password_manager) { - std::u16string description; + if (base::FeatureList::IsEnabled( + password_manager::features::kExploratorySaveUpdatePasswordStrings)) { + return GetExploratoryStringsMessageDescription(update_password); + } + if (unified_password_manager) { - if (!account_email_.empty()) { - description = l10n_util::GetStringFUTF16( - update_password - ? IDS_PASSWORD_MANAGER_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION - : IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION, - base::UTF8ToUTF16(account_email_)); - } else { - description = l10n_util::GetStringUTF16( - update_password - ? IDS_PASSWORD_MANAGER_UPDATE_PASSWORD_SIGNED_OUT_MESSAGE_DESCRIPTION - : IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SIGNED_OUT_MESSAGE_DESCRIPTION); - } - return description; + return GetUnifiedPasswordManagerMessageDescription(update_password); } if (!account_email_.empty()) { - description = l10n_util::GetStringFUTF16( + return l10n_util::GetStringFUTF16( update_password ? IDS_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_GOOGLE_ACCOUNT : IDS_SAVE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_GOOGLE_ACCOUNT, base::UTF8ToUTF16(account_email_)); - } else { + } + // TODO(crbug.com/1188971): There is no password when federation_origin is // set. Instead we should display federated provider in the description. // GetDisplayFederation() returns federation origin for a given form. const std::u16string masked_password = std::u16string(pending_credentials.password_value.size(), L'•'); + std::u16string description; description.append(pending_credentials.username_value) .append(u" ") .append(masked_password); - } - return description; + return description; +} + +std::u16string +SaveUpdatePasswordMessageDelegate::GetExploratoryStringsMessageDescription( + bool update_password) { + if (account_email_.empty()) { + return l10n_util::GetStringUTF16( + IDS_PASSWORD_MANAGER_SAVE_UPDATE_PASSWORD_SIGNED_OUT_MESSAGE_DESCRIPTION_V1); + } + + int string_version = + password_manager::features::kSaveUpdatePromptSyncingStringVersion.Get(); + DCHECK(string_version == 1 || string_version == 2); + if (string_version == 1) { + return l10n_util::GetStringFUTF16( + IDS_PASSWORD_MANAGER_SAVE_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V1, + base::UTF8ToUTF16(account_email_)); + } + + return l10n_util::GetStringFUTF16( + update_password + ? IDS_PASSWORD_MANAGER_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V2 + : IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V2, + base::UTF8ToUTF16(account_email_)); +} + +std::u16string +SaveUpdatePasswordMessageDelegate::GetUnifiedPasswordManagerMessageDescription( + bool update_password) { + if (!account_email_.empty()) { + return l10n_util::GetStringFUTF16( + update_password + ? IDS_PASSWORD_MANAGER_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION + : IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION, + base::UTF8ToUTF16(account_email_)); + } + + return l10n_util::GetStringUTF16( + update_password + ? IDS_PASSWORD_MANAGER_UPDATE_PASSWORD_SIGNED_OUT_MESSAGE_DESCRIPTION + : IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SIGNED_OUT_MESSAGE_DESCRIPTION); } int SaveUpdatePasswordMessageDelegate::GetPrimaryButtonTextId(
diff --git a/chrome/browser/password_manager/android/save_update_password_message_delegate.h b/chrome/browser/password_manager/android/save_update_password_message_delegate.h index f3078eb..6b2e3b3 100644 --- a/chrome/browser/password_manager/android/save_update_password_message_delegate.h +++ b/chrome/browser/password_manager/android/save_update_password_message_delegate.h
@@ -101,6 +101,10 @@ bool update_password, bool unified_password_manager); + std::u16string GetUnifiedPasswordManagerMessageDescription( + bool update_password); + std::u16string GetExploratoryStringsMessageDescription(bool update_password); + // Returns string id for the message primary button. Takes into account // whether this is save or update password scenario and whether the update // message will be followed by a username confirmation dialog.
diff --git a/chrome/browser/password_manager/android/save_update_password_message_delegate_unittest.cc b/chrome/browser/password_manager/android/save_update_password_message_delegate_unittest.cc index e70d50f8..6e14c5e 100644 --- a/chrome/browser/password_manager/android/save_update_password_message_delegate_unittest.cc +++ b/chrome/browser/password_manager/android/save_update_password_message_delegate_unittest.cc
@@ -9,6 +9,7 @@ #include "base/android/jni_android.h" #include "base/memory/ptr_util.h" #include "base/memory/scoped_refptr.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" @@ -33,6 +34,8 @@ #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" +using base::test::FeatureRef; +using base::test::FeatureRefAndParams; using password_manager::MockPasswordFormManagerForUI; using password_manager::PasswordForm; using password_manager::PasswordFormManagerForUI; @@ -62,6 +65,13 @@ constexpr char kConfirmUsernameMessageDismissalReason[] = "PasswordManager.SaveUpdateUIDismissalReasonAndroid." "UpdateWithUsernameConfirmation"; + +struct FeatureConfigTestParam { + bool with_unified_password_manager_android; + bool with_exploratory_save_update_password_strings; + int save_update_prompt_syncing_string_version; +}; + } // namespace class MockPasswordEditDialog : public PasswordEditDialog { @@ -83,7 +93,7 @@ }; class SaveUpdatePasswordMessageDelegateTest - : public base::test::WithFeatureOverride, + : public testing::WithParamInterface<FeatureConfigTestParam>, public ChromeRenderViewHostTestHarness { public: SaveUpdatePasswordMessageDelegateTest(); @@ -92,6 +102,8 @@ void SetUp() override; void TearDown() override; + void InitFeatureList(); + std::unique_ptr<MockPasswordFormManagerForUI> CreateFormManager( const GURL& password_form_url, const std::vector<const PasswordForm*>* best_matches); @@ -138,6 +150,17 @@ PasswordFormMetricsRecorder::BubbleDismissalReason expected_dismissal_reason); + std::u16string GetUnifiedPasswordManagerMessageDescription( + bool is_update, + bool is_signed_in, + const std::u16string& account_email); + + std::u16string GetExploratoryStringsMessageDescription( + bool is_update, + bool is_signed_in, + const std::u16string& account_email, + int new_string_version); + messages::MockMessageDispatcherBridge* message_dispatcher_bridge() { return &message_dispatcher_bridge_; } @@ -157,6 +180,7 @@ const std::vector<const PasswordForm*> kTwoFormsBestMatches = { &kPasswordForm1, &kPasswordForm2}; + base::test::ScopedFeatureList scoped_feature_list_; PasswordForm pending_credentials_; std::unique_ptr<SaveUpdatePasswordMessageDelegate> delegate_; GURL password_form_url_; @@ -171,14 +195,14 @@ }; SaveUpdatePasswordMessageDelegateTest::SaveUpdatePasswordMessageDelegateTest() - : base::test::WithFeatureOverride( - password_manager::features::kUnifiedPasswordManagerAndroid), - delegate_(base::WrapUnique( + : delegate_(base::WrapUnique( new SaveUpdatePasswordMessageDelegate(base::BindRepeating( &SaveUpdatePasswordMessageDelegateTest::CreatePasswordEditDialog, base::Unretained(this))))) {} void SaveUpdatePasswordMessageDelegateTest::SetUp() { + InitFeatureList(); + ChromeRenderViewHostTestHarness::SetUp(); ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient( web_contents(), nullptr); @@ -196,6 +220,35 @@ ChromeRenderViewHostTestHarness::TearDown(); } +void SaveUpdatePasswordMessageDelegateTest::InitFeatureList() { + std::vector<FeatureRefAndParams> enabled_features; + std::vector<FeatureRef> disabled_features; + + FeatureConfigTestParam feature_config = GetParam(); + if (feature_config.with_unified_password_manager_android) { + enabled_features.push_back( + {password_manager::features::kUnifiedPasswordManagerAndroid, {}}); + } else { + disabled_features.push_back( + password_manager::features::kUnifiedPasswordManagerAndroid); + } + + if (feature_config.with_exploratory_save_update_password_strings) { + enabled_features.push_back( + {password_manager::features::kExploratorySaveUpdatePasswordStrings, + {{password_manager::features::kSaveUpdatePromptSyncingStringVersion + .name, + base::NumberToString( + feature_config.save_update_prompt_syncing_string_version)}}}); + } else { + disabled_features.push_back( + password_manager::features::kExploratorySaveUpdatePasswordStrings); + } + + scoped_feature_list_.InitWithFeaturesAndParameters(enabled_features, + disabled_features); +} + std::unique_ptr<MockPasswordFormManagerForUI> SaveUpdatePasswordMessageDelegateTest::CreateFormManager( const GURL& password_form_url, @@ -366,6 +419,52 @@ } } +std::u16string SaveUpdatePasswordMessageDelegateTest:: + GetUnifiedPasswordManagerMessageDescription( + bool is_update, + bool is_signed_in, + const std::u16string& account_email) { + if (is_signed_in) { + return l10n_util::GetStringFUTF16( + is_update + ? IDS_PASSWORD_MANAGER_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION + : IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION, + account_email); + } + return l10n_util::GetStringUTF16( + is_update + ? IDS_PASSWORD_MANAGER_UPDATE_PASSWORD_SIGNED_OUT_MESSAGE_DESCRIPTION + : IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SIGNED_OUT_MESSAGE_DESCRIPTION); +} + +std::u16string +SaveUpdatePasswordMessageDelegateTest::GetExploratoryStringsMessageDescription( + bool is_update, + bool is_signed_in, + const std::u16string& account_email, + int new_string_version) { + if (!is_signed_in) { + return l10n_util::GetStringUTF16( + IDS_PASSWORD_MANAGER_SAVE_UPDATE_PASSWORD_SIGNED_OUT_MESSAGE_DESCRIPTION_V1); + } + + switch (new_string_version) { + case 1: + return l10n_util::GetStringFUTF16( + IDS_PASSWORD_MANAGER_SAVE_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V1, + account_email); + case 2: + return l10n_util::GetStringFUTF16( + is_update + ? IDS_PASSWORD_MANAGER_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V2 + : IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION_V2, + account_email); + default: + ADD_FAILURE() << "All string version param values should be handled"; + return u""; + } +} + // Tests that message properties (title, description, icon, button text) are // set correctly for save password message. TEST_P(SaveUpdatePasswordMessageDelegateTest, @@ -373,18 +472,40 @@ SetPendingCredentials(kUsername, kPassword); auto form_manager = CreateFormManager(GURL(kDefaultUrl), empty_best_matches()); - EnqueueMessage(std::move(form_manager), /*user_signed_in=*/false, - /*update_password=*/false); + const bool is_signed_in = false; + const bool is_update = false; + EnqueueMessage(std::move(form_manager), /*user_signed_in=*/is_signed_in, + /*update_password=*/is_update); EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SAVE_BUTTON), GetMessageWrapper()->GetPrimaryButtonText()); - if (IsParamFeatureEnabled()) { + // Validate message description that depends on + // kExploratorySaveUpdatePasswordStrings feature + if (GetParam().with_exploratory_save_update_password_strings) { + // password_manager::features::kExploratorySaveUpdatePasswordStrings is + // enabled + EXPECT_EQ(GetExploratoryStringsMessageDescription( + is_update, is_signed_in, kAccountEmail16, + GetParam().save_update_prompt_syncing_string_version), + GetMessageWrapper()->GetDescription()); + } else if (GetParam().with_unified_password_manager_android) { // password_manager::features::kUnifiedPasswordManagerAndroid is enabled - EXPECT_EQ( - l10n_util::GetStringUTF16( - IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SIGNED_OUT_MESSAGE_DESCRIPTION), - GetMessageWrapper()->GetDescription()); + EXPECT_EQ(GetUnifiedPasswordManagerMessageDescription( + is_update, is_signed_in, kAccountEmail16), + GetMessageWrapper()->GetDescription()); + } else { + EXPECT_NE(std::u16string::npos, + GetMessageWrapper()->GetDescription().find(kUsername)); + EXPECT_EQ(std::u16string::npos, + GetMessageWrapper()->GetDescription().find(kPassword)); + EXPECT_EQ(std::u16string::npos, + GetMessageWrapper()->GetDescription().find(kAccountEmail16)); + } + + // Validate remainig message fields + if (GetParam().with_unified_password_manager_android) { + // password_manager::features::kUnifiedPasswordManagerAndroid is enabled EXPECT_EQ(ResourceMapper::MapToJavaDrawableId( IDR_ANDROID_PASSWORD_MANAGER_LOGO_24DP), GetMessageWrapper()->GetIconResourceId()); @@ -394,12 +515,6 @@ } else { EXPECT_EQ(l10n_util::GetStringUTF16(IDS_SAVE_PASSWORD), GetMessageWrapper()->GetTitle()); - EXPECT_NE(std::u16string::npos, - GetMessageWrapper()->GetDescription().find(kUsername)); - EXPECT_EQ(std::u16string::npos, - GetMessageWrapper()->GetDescription().find(kPassword)); - EXPECT_EQ(std::u16string::npos, - GetMessageWrapper()->GetDescription().find(kAccountEmail16)); EXPECT_EQ( ResourceMapper::MapToJavaDrawableId(IDR_ANDROID_INFOBAR_SAVE_PASSWORD), GetMessageWrapper()->GetIconResourceId()); @@ -420,18 +535,26 @@ SetPendingCredentials(kUsername, kPassword); auto form_manager = CreateFormManager(GURL(kDefaultUrl), empty_best_matches()); - EnqueueMessage(std::move(form_manager), /*user_signed_in=*/false, - /*update_password=*/true); + const bool is_signed_in = false; + const bool is_update = true; + EnqueueMessage(std::move(form_manager), /*user_signed_in=*/is_signed_in, + /*update_password=*/is_update); EXPECT_EQ(l10n_util::GetStringUTF16(IDS_UPDATE_PASSWORD), GetMessageWrapper()->GetTitle()); - if (IsParamFeatureEnabled()) { + if (GetParam().with_exploratory_save_update_password_strings) { + // password_manager::features::kExploratorySaveUpdatePasswordStrings is + // enabled + EXPECT_EQ(GetExploratoryStringsMessageDescription( + is_update, is_signed_in, kAccountEmail16, + GetParam().save_update_prompt_syncing_string_version), + GetMessageWrapper()->GetDescription()); + } else if (GetParam().with_unified_password_manager_android) { // password_manager::features::kUnifiedPasswordManagerAndroid is enabled - EXPECT_EQ( - l10n_util::GetStringUTF16( - IDS_PASSWORD_MANAGER_UPDATE_PASSWORD_SIGNED_OUT_MESSAGE_DESCRIPTION), - GetMessageWrapper()->GetDescription()); + EXPECT_EQ(GetUnifiedPasswordManagerMessageDescription( + is_update, is_signed_in, kAccountEmail16), + GetMessageWrapper()->GetDescription()); } EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_UPDATE_BUTTON), @@ -513,16 +636,23 @@ SetPendingCredentials(kUsername, kPassword); auto form_manager = CreateFormManager(GURL(kDefaultUrl), empty_best_matches()); - EnqueueMessage(std::move(form_manager), /*user_signed_in=*/true, - /*update_password=*/false); + const bool is_signed_in = true; + const bool is_update = false; + EnqueueMessage(std::move(form_manager), /*user_signed_in=*/is_signed_in, + /*update_password=*/is_update); - if (IsParamFeatureEnabled()) { + if (GetParam().with_exploratory_save_update_password_strings) { + // password_manager::features::kExploratorySaveUpdatePasswordStrings is + // enabled + EXPECT_EQ(GetExploratoryStringsMessageDescription( + is_update, is_signed_in, kAccountEmail16, + GetParam().save_update_prompt_syncing_string_version), + GetMessageWrapper()->GetDescription()); + } else if (GetParam().with_unified_password_manager_android) { // password_manager::features::kUnifiedPasswordManagerAndroid is enabled - EXPECT_EQ( - l10n_util::GetStringFUTF16( - IDS_PASSWORD_MANAGER_SAVE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION, - kAccountEmail16), - GetMessageWrapper()->GetDescription()); + EXPECT_EQ(GetUnifiedPasswordManagerMessageDescription( + is_update, is_signed_in, kAccountEmail16), + GetMessageWrapper()->GetDescription()); } else { EXPECT_EQ(std::u16string::npos, GetMessageWrapper()->GetDescription().find(kUsername)); @@ -541,16 +671,23 @@ SetPendingCredentials(kUsername, kPassword); auto form_manager = CreateFormManager(GURL(kDefaultUrl), empty_best_matches()); - EnqueueMessage(std::move(form_manager), /*user_signed_in=*/true, - /*update_password=*/true); + const bool is_signed_in = true; + const bool is_update = true; + EnqueueMessage(std::move(form_manager), /*user_signed_in=*/is_signed_in, + /*update_password=*/is_update); - if (IsParamFeatureEnabled()) { + if (GetParam().with_exploratory_save_update_password_strings) { + // password_manager::features::kExploratorySaveUpdatePasswordStrings is + // enabled + EXPECT_EQ(GetExploratoryStringsMessageDescription( + is_update, is_signed_in, kAccountEmail16, + GetParam().save_update_prompt_syncing_string_version), + GetMessageWrapper()->GetDescription()); + } else if (GetParam().with_unified_password_manager_android) { // password_manager::features::kUnifiedPasswordManagerAndroid is enabled - EXPECT_EQ( - l10n_util::GetStringFUTF16( - IDS_PASSWORD_MANAGER_UPDATE_PASSWORD_SIGNED_IN_MESSAGE_DESCRIPTION, - kAccountEmail16), - GetMessageWrapper()->GetDescription()); + EXPECT_EQ(GetUnifiedPasswordManagerMessageDescription( + is_update, is_signed_in, kAccountEmail16), + GetMessageWrapper()->GetDescription()); } else { EXPECT_EQ(std::u16string::npos, GetMessageWrapper()->GetDescription().find(kUsername)); @@ -1034,4 +1171,32 @@ 1); } -INSTANTIATE_FEATURE_OVERRIDE_TEST_SUITE(SaveUpdatePasswordMessageDelegateTest); +INSTANTIATE_TEST_SUITE_P( + All, + SaveUpdatePasswordMessageDelegateTest, + testing::Values( + // Exploratory strings are disabled, no version specified + FeatureConfigTestParam{ + .with_unified_password_manager_android = false, + .with_exploratory_save_update_password_strings = false}, + FeatureConfigTestParam{ + .with_unified_password_manager_android = true, + .with_exploratory_save_update_password_strings = false}, + // Exploratory strings with UPM enabled + FeatureConfigTestParam{ + .with_unified_password_manager_android = true, + .with_exploratory_save_update_password_strings = true, + .save_update_prompt_syncing_string_version = 1}, + FeatureConfigTestParam{ + .with_unified_password_manager_android = true, + .with_exploratory_save_update_password_strings = true, + .save_update_prompt_syncing_string_version = 2}, + // Exploratory strings with UPM disabled + FeatureConfigTestParam{ + .with_unified_password_manager_android = false, + .with_exploratory_save_update_password_strings = true, + .save_update_prompt_syncing_string_version = 1}, + FeatureConfigTestParam{ + .with_unified_password_manager_android = false, + .with_exploratory_save_update_password_strings = true, + .save_update_prompt_syncing_string_version = 2}));
diff --git a/chrome/browser/resources/settings/site_settings/site_data.html b/chrome/browser/resources/settings/site_settings/site_data.html index dffb641..12c2a7d 100644 --- a/chrome/browser/resources/settings/site_settings/site_data.html +++ b/chrome/browser/resources/settings/site_settings/site_data.html
@@ -1,4 +1,26 @@ <style include="settings-shared"> + .content-settings-header, + .radio-group { + padding: 0 var(--cr-section-padding); + } + + .radio-group-sub-heading { + padding-bottom: 10px; + } + + settings-collapse-radio-button { + --settings-collapse-toggle-min-height: var(--settings-row-min-height); + } + + settings-collapse-radio-button.two-line { + --settings-collapse-toggle-min-height: + var(--settings-row-two-line-min-height); + } + + settings-collapse-radio-button:not(:first-of-type) { + --settings-collapse-separator-line: var(--cr-separator-line); + } + #exceptionHeader { padding: 0 var(--cr-section-padding); } @@ -7,6 +29,39 @@ padding-bottom: 10px; } </style> +<!-- TODO(crbug.com/1378703): Update all strings in this page. --> +<div class="content-settings-header secondary">$i18n{privacyPageTitle}</div> +<div id="notificationRadioGroup" class="radio-group"> + <h2>$i18n{privacyPageTitle}</h2> + <div class="secondary radio-group-sub-heading">$i18n{privacyPageTitle}</div> + <settings-radio-group id="defaultGroup" + pref="{{prefs.generated.cookie_default_content_setting}}" + selectable-elements="cr-radio-button, settings-collapse-radio-button"> + <settings-collapse-radio-button id="defaultAllow" no-collapse + name="[[contentSettingEnum_.ALLOW]]" + pref="[[prefs.generated.cookie_default_content_setting]]" + label="$i18n{privacyPageTitle}" + sub-label="$i18n{privacyPageTitle}" + icon="settings:notifications"> + </settings-collapse-radio-button> + <settings-collapse-radio-button id="defaultSessionOnly" no-collapse + class="two-line" + name="[[contentSettingEnum_.SESSION_ONLY]]" + pref="[[prefs.generated.cookie_default_content_setting]]" + label="$i18n{privacyPageTitle}" + sub-label="$i18n{privacyPageTitle}" + icon="settings:notifications"> + </settings-collapse-radio-button> + <settings-collapse-radio-button id="defaultBlock" no-collapse + class="two-line" + name="[[contentSettingEnum_.BLOCK]]" + pref="[[prefs.generated.cookie_default_content_setting]]" + label="$i18n{privacyPageTitle}" + sub-label="$i18n{privacyPageTitle}" + icon="settings:notifications-off"> + </settings-collapse-radio-button> + </settings-radio-group> +</div> <div id="exceptionHeader"> <!-- TODO(crbug.com/1378703): Update all strings in this page. --> <h2>$i18n{privacyPageTitle}</h2>
diff --git a/chrome/browser/resources/settings/site_settings/site_data.ts b/chrome/browser/resources/settings/site_settings/site_data.ts index 4144904c..5000046 100644 --- a/chrome/browser/resources/settings/site_settings/site_data.ts +++ b/chrome/browser/resources/settings/site_settings/site_data.ts
@@ -7,15 +7,29 @@ * 'settings-site-data' is the polymer element for showing the * settings for site data under Site Settings. */ +import '../controls/settings_radio_group.js'; +import '../prefs/prefs.js'; +import '../privacy_page/collapse_radio_button.js'; import './site_list.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {SettingsRadioGroupElement} from '../controls/settings_radio_group.js'; import {PrefsMixin} from '../prefs/prefs_mixin.js'; +import {SettingsCollapseRadioButtonElement} from '../privacy_page/collapse_radio_button.js'; import {ContentSetting, ContentSettingsTypes} from './constants.js'; import {getTemplate} from './site_data.html.js'; +export interface SettingsSiteDataElement { + $: { + defaultGroup: SettingsRadioGroupElement, + defaultAllow: SettingsCollapseRadioButtonElement, + defaultSessionOnly: SettingsCollapseRadioButtonElement, + defaultBlock: SettingsCollapseRadioButtonElement, + }; +} + const SettingsSiteDataElementBase = PrefsMixin(PolymerElement); export class SettingsSiteDataElement extends SettingsSiteDataElementBase { @@ -46,6 +60,7 @@ value: ContentSettingsTypes.COOKIES, }, + /** Expose ContentSetting enum to HTML bindings. */ contentSettingEnum_: { type: Object, value: ContentSetting,
diff --git a/chrome/browser/resources/side_panel/customize_chrome/app.html b/chrome/browser/resources/side_panel/customize_chrome/app.html index 2cd74b9..33124ab 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/app.html +++ b/chrome/browser/resources/side_panel/customize_chrome/app.html
@@ -32,7 +32,10 @@ } customize-chrome-appearance, - customize-chrome-shortcuts { + customize-chrome-shortcuts, + customize-chrome-cards, + customize-chrome-categories, + customize-chrome-themes { display: block; max-width: 320px; width: 100%;
diff --git a/chrome/browser/resources/side_panel/customize_chrome/cards.html b/chrome/browser/resources/side_panel/customize_chrome/cards.html index 77d7a3c..a11b7c98 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/cards.html +++ b/chrome/browser/resources/side_panel/customize_chrome/cards.html
@@ -1,21 +1,10 @@ <style> - .container { - width: 320px; - } - - #title { - font-weight: 500; - height: 20px; - margin-bottom: 16px; - } - #showToggleContainer { align-items: center; display: flex; - height: 20px; - margin-bottom: 16px; - margin-inline-end: 16px; - margin-inline-start: 16px; + font-size: 13px; + line-height: 20px; + margin: 0 16px 16px; } #showToggleTitle { @@ -24,27 +13,29 @@ #cards { display: flex; + margin: 0 16px; } .card { display: flex; - height: 20px; - margin-top: 16px; + justify-content: space-between; + margin-bottom: 16px; } .card-name { - flex-grow: 1; + font-size: 13px; + line-height: 20px; margin-inline-start: 24px; } .card-checkbox { - margin-inline-start: 16px; + margin-inline-end: 3px; width: 16px; } iron-collapse { --iron-collapse-transition-duration: 300ms; - margin-inline-start: 16px; + width: 100%; } hr { @@ -52,37 +43,34 @@ border: none; height: 1px; margin-bottom: 16px; - margin-top: 16px; - width: 288px; + width: 100%; } cr-toggle { margin-inline-start: 16px; } </style> -<div class="container"> - <div id="showToggleContainer"> - <div id="showToggleTitle">$i18n{showCardsToggleTitle}</div> - <cr-policy-indicator indicator-type="devicePolicy" - hidden="[[!managedByPolicy_]]"> - </cr-policy-indicator> - <cr-toggle title="$i18n{showCardsToggleTitle}" checked="[[show_]]" - disabled="[[managedByPolicy_]]" - on-change="onShowChange_"> - </cr-toggle> - </div> - <div id="cards"> - <iron-collapse opened="[[show_]]"> - <hr> - <template is="dom-repeat" items="[[modules_]]"> - <div class="card"> - <div class="card-name">[[item.name]]</div> - <cr-checkbox class="card-checkbox" checked="{{item.enabled}}" - disabled="[[managedByPolicy_]]" - title="[[item.name]]" on-change="onCardStatusChange_"> - </cr-checkbox> - </div> - </template> - </iron-collapse> - </div> +<div id="showToggleContainer"> + <div id="showToggleTitle">$i18n{showCardsToggleTitle}</div> + <cr-policy-indicator indicator-type="devicePolicy" + hidden="[[!managedByPolicy_]]"> + </cr-policy-indicator> + <cr-toggle title="$i18n{showCardsToggleTitle}" checked="[[show_]]" + disabled="[[managedByPolicy_]]" + on-change="onShowChange_"> + </cr-toggle> +</div> +<div id="cards"> + <iron-collapse opened="[[show_]]"> + <hr> + <template is="dom-repeat" items="[[modules_]]"> + <div class="card"> + <div class="card-name">[[item.name]]</div> + <cr-checkbox class="card-checkbox" checked="{{item.enabled}}" + disabled="[[managedByPolicy_]]" + title="[[item.name]]" on-change="onCardStatusChange_"> + </cr-checkbox> + </div> + </template> + </iron-collapse> </div>
diff --git a/chrome/browser/resources/side_panel/customize_chrome/categories.html b/chrome/browser/resources/side_panel/customize_chrome/categories.html index dfbe9ae..6db0e19 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/categories.html +++ b/chrome/browser/resources/side_panel/customize_chrome/categories.html
@@ -1,13 +1,8 @@ <style include="cr-hidden-style cr-icons"> - #container { - margin: 0 16px 32px 16px; - max-width: 284px; - } - #headerContainer { align-items: center; display: flex; - margin: 10px 0; + margin: 16px; } cr-icon-button { @@ -27,6 +22,8 @@ cr-grid { --cr-column-width: 1fr; --cr-grid-gap: 16px 11px; + display: block; + margin: 0 16px 32px; } .tile { @@ -151,56 +148,54 @@ width: 32px; } </style> -<div id="container"> - <div id="headerContainer"> - <cr-icon-button on-click="onBackClick_" id="backButton" - class="icon-arrow-back" title="$i18n{backButton}"> - </cr-icon-button> - <h1>$i18n{categoriesHeader}</h1> - </div> - <cr-grid columns="6"> - <div class="tile" tabindex="0" id="classicChromeTile" - role="button" on-click="onClassicChromeClick_"> - <div class="image-container"> - <img id="miniNewTabPage" src="icons/corner_new_tab_page.svg"></img> - </div> - <div class="label">$i18n{classicChrome}</div> - </div> - <div class="tile" tabindex="0" id="uploadImageTile" - role="button" on-click="onUploadImageClick_"> - <div class="image-container"> - <div id="uploadIcon" class="cr-icon"></div> - </div> - <div class="label">$i18n{uploadImage}</div> - </div> - <div class="tile" tabindex="0" role="button"> - <div class="image-container"> - <div class="chrome-color"></div> - <div class="chrome-color"></div> - </div> - <div class="label">$i18n{chromeColors}</div> - </div> - <template is="dom-repeat" id="collectionsRepeat" items="[[collections_]]"> - <div class="tile collection" tabindex="0" role="button" - on-click="onCollectionClick_"> - <div class="image-container"> - <img is="cr-auto-img" - auto-src="[[item.previewImageUrl.url]]" - draggable="false"> - </img> - </div> - <div class="label">[[item.label]]</div> - </div> - </template> - <div class="tile" tabindex="0" role="button" - on-click="onChromeWebStoreClick_" id="chromeWebStoreTile"> - <div class="image-container"> - <img id="chromeWebStore" src="icons/chrome_web_store.svg"></img> - </div> - <div class="label"> - <div class="cr-icon icon-external"></div> - $i18n{chromeWebStore} - </div> - </div> - </cr-grid> +<div id="headerContainer"> + <cr-icon-button on-click="onBackClick_" id="backButton" + class="icon-arrow-back" title="$i18n{backButton}"> + </cr-icon-button> + <h1>$i18n{categoriesHeader}</h1> </div> +<cr-grid columns="6"> + <div class="tile" tabindex="0" id="classicChromeTile" + role="button" on-click="onClassicChromeClick_"> + <div class="image-container"> + <img id="miniNewTabPage" src="icons/corner_new_tab_page.svg"></img> + </div> + <div class="label">$i18n{classicChrome}</div> + </div> + <div class="tile" tabindex="0" id="uploadImageTile" + role="button" on-click="onUploadImageClick_"> + <div class="image-container"> + <div id="uploadIcon" class="cr-icon"></div> + </div> + <div class="label">$i18n{uploadImage}</div> + </div> + <div class="tile" tabindex="0" role="button"> + <div class="image-container"> + <div class="chrome-color"></div> + <div class="chrome-color"></div> + </div> + <div class="label">$i18n{chromeColors}</div> + </div> + <template is="dom-repeat" id="collectionsRepeat" items="[[collections_]]"> + <div class="tile collection" tabindex="0" role="button" + on-click="onCollectionClick_"> + <div class="image-container"> + <img is="cr-auto-img" + auto-src="[[item.previewImageUrl.url]]" + draggable="false"> + </img> + </div> + <div class="label">[[item.label]]</div> + </div> + </template> + <div class="tile" tabindex="0" role="button" + on-click="onChromeWebStoreClick_" id="chromeWebStoreTile"> + <div class="image-container"> + <img id="chromeWebStore" src="icons/chrome_web_store.svg"></img> + </div> + <div class="label"> + <div class="cr-icon icon-external"></div> + $i18n{chromeWebStore} + </div> + </div> +</cr-grid>
diff --git a/chrome/browser/resources/side_panel/customize_chrome/shortcuts.html b/chrome/browser/resources/side_panel/customize_chrome/shortcuts.html index 44b5d9f..a4ddea78 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/shortcuts.html +++ b/chrome/browser/resources/side_panel/customize_chrome/shortcuts.html
@@ -26,7 +26,6 @@ cr-radio-group { --cr-radio-group-item-padding: 0px; - margin-top: 16px; width: 100%; } @@ -48,6 +47,14 @@ .option-description { color: var(--cr-secondary-text-color); } + + hr { + background-color: var(--horizontal-rule-color); + border: none; + height: 1px; + margin-bottom: 16px; + width: 100%; + } </style> <div id="showShortcutsToggleContainer"> <div id="showShortcutsToggleTitle">$i18n{showShortcutsToggle}</div> @@ -56,6 +63,7 @@ </div> <div id="options"> <iron-collapse opened="[[show_]]"> + <hr> <cr-radio-group id="shortcutsRadioSelection" disabled="[[!show_]]" selected="[[shortcutsRadioSelection_(customLinksEnabled_)]]" on-selected-changed="onShortcutsRadioSelectionChanged_">
diff --git a/chrome/browser/resources/side_panel/customize_chrome/themes.html b/chrome/browser/resources/side_panel/customize_chrome/themes.html index c6f0d3c..ff590c42 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/themes.html +++ b/chrome/browser/resources/side_panel/customize_chrome/themes.html
@@ -1,9 +1,4 @@ <style include="cr-hidden-style cr-icons"> - #container { - max-width: 320px; - width: 100%; - } - #headerContainer { align-items: center; display: flex; @@ -79,25 +74,23 @@ border-radius: 12px; } </style> -<div id="container"> - <div id="headerContainer"> - <cr-icon-button on-click="onBackClick_" id="backButton" - class="icon-arrow-back" title="$i18n{backButton}"> - </cr-icon-button> - <h1 id="header">[[header_]]</h1> - </div> - <cr-grid columns="3"> - <template is="dom-repeat" id="themesRepeat" items="[[themes_]]"> - <div class="tile theme" tabindex="0" role="button" - on-click="onSelectTheme_"> - <div class="image-container"> - <img is="cr-auto-img" - auto-src="[[item.previewImageUrl.url]]" - draggable="false"> - </img> - </div> - <div class="label">[[item.attribution1]]</div> - </div> - </template> - </cr-grid> +<div id="headerContainer"> + <cr-icon-button on-click="onBackClick_" id="backButton" + class="icon-arrow-back" title="$i18n{backButton}"> + </cr-icon-button> + <h1 id="header">[[header_]]</h1> </div> +<cr-grid columns="3"> + <template is="dom-repeat" id="themesRepeat" items="[[themes_]]"> + <div class="tile theme" tabindex="0" role="button" + on-click="onSelectTheme_"> + <div class="image-container"> + <img is="cr-auto-img" + auto-src="[[item.previewImageUrl.url]]" + draggable="false"> + </img> + </div> + <div class="label">[[item.attribution1]]</div> + </div> + </template> +</cr-grid>
diff --git a/chrome/browser/resources/side_panel/customize_chrome/themes.ts b/chrome/browser/resources/side_panel/customize_chrome/themes.ts index afa1645..6007368 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/themes.ts +++ b/chrome/browser/resources/side_panel/customize_chrome/themes.ts
@@ -8,7 +8,7 @@ import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; import {FocusOutlineManager} from 'chrome://resources/js/focus_outline_manager.js'; -import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {DomRepeatEvent, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {BackgroundCollection, CollectionImage, CustomizeChromePageHandlerInterface} from './customize_chrome.mojom-webui.js'; import {CustomizeChromeApiProxy} from './customize_chrome_api_proxy.js'; @@ -72,7 +72,16 @@ this.dispatchEvent(new Event('back-click')); } - private onSelectTheme_() { + private onSelectTheme_(e: DomRepeatEvent<CollectionImage>) { + const { + attribution1, + attribution2, + attributionUrl, + imageUrl, + previewImageUrl, + } = e.model.item; + this.pageHandler_.setBackgroundImage( + attribution1, attribution2, attributionUrl, imageUrl, previewImageUrl); this.dispatchEvent(new Event('theme-select')); } }
diff --git a/chrome/browser/search/background/ntp_custom_background_service.h b/chrome/browser/search/background/ntp_custom_background_service.h index 25c73bae..6253e98 100644 --- a/chrome/browser/search/background/ntp_custom_background_service.h +++ b/chrome/browser/search/background/ntp_custom_background_service.h
@@ -57,12 +57,13 @@ virtual void ResetCustomBackgroundInfo(); // Invoked when a custom background is configured on the NTP. - void SetCustomBackgroundInfo(const GURL& background_url, - const GURL& thumbnail_url, - const std::string& attribution_line_1, - const std::string& attribution_line_2, - const GURL& action_url, - const std::string& collection_id); + // Virtual for testing. + virtual void SetCustomBackgroundInfo(const GURL& background_url, + const GURL& thumbnail_url, + const std::string& attribution_line_1, + const std::string& attribution_line_2, + const GURL& action_url, + const std::string& collection_id); // Invoked when a user selected the "Upload an image" option on the NTP. // Virtual for testing.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index e115c4d..46aec62 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -5497,7 +5497,7 @@ } } - if (enable_lens_desktop_side_panel) { + if (enable_lens_desktop_google_branded_features) { sources += [ "lens/lens_side_panel_helper.h" ] }
diff --git a/chrome/browser/ui/tab_contents/core_tab_helper.cc b/chrome/browser/ui/tab_contents/core_tab_helper.cc index 09d229e..f97addb 100644 --- a/chrome/browser/ui/tab_contents/core_tab_helper.cc +++ b/chrome/browser/ui/tab_contents/core_tab_helper.cc
@@ -58,7 +58,7 @@ #include "components/guest_view/browser/guest_view_manager.h" #endif -#if BUILDFLAG(ENABLE_LENS_DESKTOP_SIDE_PANEL) +#if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES) #include "chrome/browser/ui/lens/lens_side_panel_helper.h" #endif @@ -502,12 +502,12 @@ content_type.c_str()); } if (use_side_panel) { -#if BUILDFLAG(ENABLE_LENS_DESKTOP_SIDE_PANEL) +#if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES) lens::OpenLensSidePanel(chrome::FindBrowserWithWebContents(web_contents()), open_url_params); #else web_contents()->OpenURL(open_url_params); -#endif // BUILDFLAG(ENABLE_LENS_DESKTOP_SIDE_PANEL) +#endif // BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES) } else { web_contents()->OpenURL(open_url_params); }
diff --git a/chrome/browser/ui/views/side_panel/side_panel.cc b/chrome/browser/ui/views/side_panel/side_panel.cc index e2898958..22d09142 100644 --- a/chrome/browser/ui/views/side_panel/side_panel.cc +++ b/chrome/browser/ui/views/side_panel/side_panel.cc
@@ -217,8 +217,9 @@ } gfx::Size SidePanel::GetMinimumSize() const { + const int min_side_panel_contents_width = 320; const int min_height = 0; - return gfx::Size(min_side_panel_contents_width_ + kBorderInsets.width(), + return gfx::Size(min_side_panel_contents_width + kBorderInsets.width(), min_height); } @@ -256,21 +257,8 @@ starting_width_on_resize_ = -1; } const int minimum_width = GetMinimumSize().width(); - // The side panel may be resized up to leaving the main contents at - // kMainBrowserContentsMinimumWidth. - DCHECK_EQ(browser_view_->GetMinimumSize().width(), - BrowserViewLayout::kMainBrowserContentsMinimumWidth); - const int maximum_width = width() + - browser_view_->contents_container()->width() - - BrowserViewLayout::kMainBrowserContentsMinimumWidth; - // Side panel must stay at minimum width if either: - // a) The proposed width is less than the minimum. - // b) There is not enough room for the side panel to be wider than the - // minimum. - if (proposed_width < minimum_width || maximum_width < minimum_width) { + if (proposed_width < minimum_width) { proposed_width = minimum_width; - } else if (proposed_width > maximum_width) { - proposed_width = maximum_width; } if (width() != proposed_width) { SetPanelWidth(proposed_width);
diff --git a/chrome/browser/ui/views/side_panel/side_panel.h b/chrome/browser/ui/views/side_panel/side_panel.h index 0a83a106..fc411e9b 100644 --- a/chrome/browser/ui/views/side_panel/side_panel.h +++ b/chrome/browser/ui/views/side_panel/side_panel.h
@@ -37,9 +37,6 @@ HorizontalAlignment GetHorizontalAlignment(); bool IsRightAligned(); gfx::Size GetMinimumSize() const override; - void SetMinimumSidePanelContentsWidthForTesting(int width) { - min_side_panel_contents_width_ = width; - } // views::ResizeAreaDelegate: void OnResize(int resize_amount, bool done_resizing) override; @@ -75,8 +72,6 @@ // Observes and listens to side panel alignment changes. PrefChangeRegistrar pref_change_registrar_; - - int min_side_panel_contents_width_ = 320; }; #endif // CHROME_BROWSER_UI_VIEWS_SIDE_PANEL_SIDE_PANEL_H_
diff --git a/chrome/browser/ui/views/side_panel/side_panel_coordinator_unittest.cc b/chrome/browser/ui/views/side_panel/side_panel_coordinator_unittest.cc index 4ed81c2b..c64df23 100644 --- a/chrome/browser/ui/views/side_panel/side_panel_coordinator_unittest.cc +++ b/chrome/browser/ui/views/side_panel/side_panel_coordinator_unittest.cc
@@ -115,19 +115,6 @@ return coordinator_->header_combobox_ != nullptr; } - void SetBrowserViewWidth(const int width) { - // If browser window is maximized then explicitly restore it, as otherwise - // the SetBounds call would be a no-op. - // TODO(crbug.com/1393153): Fix this on lacros builds and remove buildflag. -#if !BUILDFLAG(IS_CHROMEOS_LACROS) - if (browser_view()->IsMaximized()) - browser_view()->Restore(); -#endif - - browser_view()->SetBounds( - gfx::Rect(width, browser_view()->GetBounds().height())); - } - protected: raw_ptr<SidePanelCoordinator> coordinator_; raw_ptr<SidePanelRegistry> global_registry_; @@ -151,22 +138,8 @@ // Set side panel to right-aligned browser_view()->GetProfile()->GetPrefs()->SetBoolean( prefs::kSidePanelHorizontalAlignment, true); - - // The side panel can only be widened when the browser main web contents width - // is greater than |BrowserViewLayout::kMainBrowserContentsMinimumWidth|, - // which is 500. Therefore the side panel can only be widened when the total - // browser view width is greater than the minimum side panel contents width + - // 500. The browser view maximum width is constrained by the display maximum, - // which is 800 on win32 and ChromeOS. - // Therefore, we set the browser view width to be 800 and we reduce the side - // panel width to 100 so that it can be widened and shrunk. - SetBrowserViewWidth(800); - browser_view() - ->unified_side_panel() - ->SetMinimumSidePanelContentsWidthForTesting(100); - coordinator_->Toggle(); - const int starting_width = 200; + const int starting_width = 500; browser_view()->unified_side_panel()->SetPanelWidth(starting_width); views::test::RunScheduledLayout(browser_view()); EXPECT_EQ(browser_view()->unified_side_panel()->width(), starting_width); @@ -191,21 +164,8 @@ } TEST_F(SidePanelCoordinatorTest, ChangeSidePanelWidthMaxMin) { - // The side panel can only be widened when the browser main web contents width - // is greater than |BrowserViewLayout::kMainBrowserContentsMinimumWidth|, - // which is 500. Therefore the side panel can only be widened when the total - // browser view width is greater than the minimum side panel contents width + - // 500. The browser view maximum width is constrained by the display maximum, - // which is 800 on win32 and ChromeOS. - // Therefore, we set the browser view width to be 800 and we reduce the side - // panel width to 100 so that it can be widened and shrunk. - SetBrowserViewWidth(800); - browser_view() - ->unified_side_panel() - ->SetMinimumSidePanelContentsWidthForTesting(100); - coordinator_->Toggle(); - const int starting_width = 200; + const int starting_width = 500; browser_view()->unified_side_panel()->SetPanelWidth(starting_width); views::test::RunScheduledLayout(browser_view()); EXPECT_EQ(browser_view()->unified_side_panel()->width(), starting_width); @@ -220,32 +180,22 @@ browser_view()->unified_side_panel()->OnResize(-large_increment, true); views::test::RunScheduledLayout(browser_view()); - EXPECT_GT(browser_view()->unified_side_panel()->width(), starting_width); - EXPECT_EQ(browser_view()->contents_container()->width(), - BrowserViewLayout::kMainBrowserContentsMinimumWidth); + BrowserViewLayout* layout_manager = + static_cast<BrowserViewLayout*>(browser_view()->GetLayoutManager()); + const int min_web_contents_width = + layout_manager->GetMinWebContentsWidthForTesting(); + EXPECT_EQ(browser_view()->contents_web_view()->width(), + min_web_contents_width); } TEST_F(SidePanelCoordinatorTest, ChangeSidePanelWidthRTL) { - // The side panel can only be widened when the browser main web contents width - // is greater than |BrowserViewLayout::kMainBrowserContentsMinimumWidth|, - // which is 500. Therefore the side panel can only be widened when the total - // browser view width is greater than the minimum side panel contents width + - // 500. The browser view maximum width is constrained by the display maximum, - // which is 800 on win32 and ChromeOS. - // Therefore, we set the browser view width to be 800 and we reduce the side - // panel width to 100 so that it can be widened and shrunk. - SetBrowserViewWidth(800); - browser_view() - ->unified_side_panel() - ->SetMinimumSidePanelContentsWidthForTesting(100); - // Set side panel to right-aligned browser_view()->GetProfile()->GetPrefs()->SetBoolean( prefs::kSidePanelHorizontalAlignment, true); // Set UI direction to LTR base::i18n::SetRTLForTesting(false); coordinator_->Toggle(); - const int starting_width = 200; + const int starting_width = 500; browser_view()->unified_side_panel()->SetPanelWidth(starting_width); views::test::RunScheduledLayout(browser_view()); EXPECT_EQ(browser_view()->unified_side_panel()->width(), starting_width); @@ -269,79 +219,38 @@ } TEST_F(SidePanelCoordinatorTest, ChangeSidePanelWidthWindowResize) { - // The side panel can only be widened when the browser main web contents width - // is greater than |BrowserViewLayout::kMainBrowserContentsMinimumWidth|, - // which is 500. Therefore the side panel can only be widened when the total - // browser view width is greater than the minimum side panel contents width + - // 500. The browser view maximum width is constrained by the display maximum, - // which is 800 on win32 and ChromeOS. - // Therefore, we set the browser view width to be 800 and we reduce the side - // panel width to 100 so that it can be widened and shrunk. - SetBrowserViewWidth(800); - browser_view() - ->unified_side_panel() - ->SetMinimumSidePanelContentsWidthForTesting(100); - coordinator_->Toggle(); - const int starting_width = 200; + const int starting_width = 500; browser_view()->unified_side_panel()->SetPanelWidth(starting_width); views::test::RunScheduledLayout(browser_view()); EXPECT_EQ(browser_view()->unified_side_panel()->width(), starting_width); // Shrink browser window enough that side panel should also shrink in // observance of web contents minimum width. - const int original_width = browser_view()->GetBounds().width(); - SetBrowserViewWidth(starting_width); - EXPECT_EQ(browser_view()->unified_side_panel()->width(), - browser_view()->unified_side_panel()->GetMinimumSize().width()); - BrowserViewLayout* const layout_manager = + gfx::Rect original_bounds(browser_view()->GetBounds()); + gfx::Size new_size(starting_width, starting_width); + gfx::Rect new_bounds(original_bounds); + new_bounds.set_size(new_size); + // Explicitly restore the browser window on ChromeOS, as it would otherwise + // be maximized and the SetBounds call would be a no-op. +#if BUILDFLAG(IS_CHROMEOS_ASH) + browser_view()->Restore(); +#endif + browser_view()->SetBounds(new_bounds); + EXPECT_LT(browser_view()->unified_side_panel()->width(), starting_width); + BrowserViewLayout* layout_manager = static_cast<BrowserViewLayout*>(browser_view()->GetLayoutManager()); const int min_web_contents_width = layout_manager->GetMinWebContentsWidthForTesting(); - EXPECT_EQ(browser_view()->contents_container()->width(), + EXPECT_EQ(browser_view()->contents_web_view()->width(), min_web_contents_width); // Return browser window to original size, side panel should also return to // size prior to window resize. - SetBrowserViewWidth(original_width); + browser_view()->SetBounds(original_bounds); EXPECT_EQ(browser_view()->unified_side_panel()->width(), starting_width); } -TEST_F(SidePanelCoordinatorTest, ChangeSidePanelWidthSmallWindow) { - SetBrowserViewWidth(500); - browser_view() - ->unified_side_panel() - ->SetMinimumSidePanelContentsWidthForTesting(100); - coordinator_->Toggle(); - const int starting_width = 200; - const int min_side_panel_width = - browser_view()->unified_side_panel()->GetMinimumSize().width(); - browser_view()->unified_side_panel()->SetPanelWidth(starting_width); - views::test::RunScheduledLayout(browser_view()); - EXPECT_EQ(browser_view()->unified_side_panel()->width(), - min_side_panel_width); - - // Attempt to resize the side panel, side panel should not be able to resized. - const int increment = 50; - browser_view()->unified_side_panel()->OnResize(increment, true); - views::test::RunScheduledLayout(browser_view()); - EXPECT_EQ(browser_view()->unified_side_panel()->width(), - min_side_panel_width); - BrowserViewLayout* const layout_manager = - static_cast<BrowserViewLayout*>(browser_view()->GetLayoutManager()); - const int min_web_contents_width = - layout_manager->GetMinWebContentsWidthForTesting(); - EXPECT_EQ(browser_view()->contents_container()->width(), - min_web_contents_width); - - browser_view()->unified_side_panel()->OnResize(-increment, true); - views::test::RunScheduledLayout(browser_view()); - EXPECT_EQ(browser_view()->unified_side_panel()->width(), - min_side_panel_width); - EXPECT_EQ(browser_view()->contents_container()->width(), - min_web_contents_width); -} - TEST_F(SidePanelCoordinatorTest, ChangeSidePanelAlignment) { browser_view()->GetProfile()->GetPrefs()->SetBoolean( prefs::kSidePanelHorizontalAlignment, true);
diff --git a/chrome/browser/ui/webui/ash/login/oobe_ui.cc b/chrome/browser/ui/webui/ash/login/oobe_ui.cc index d967f845..e406f279 100644 --- a/chrome/browser/ui/webui/ash/login/oobe_ui.cc +++ b/chrome/browser/ui/webui/ash/login/oobe_ui.cc
@@ -287,7 +287,7 @@ const bool is_oobe_flow = display_type == OobeUI::kOobeDisplay; source->AddBoolean("isOsInstallAllowed", switches::IsOsInstallAllowed()); source->AddBoolean("isOobeFlow", is_oobe_flow); - source->AddBoolean("isMaterialNext", features::IsOobeMaterialNextEnabled()); + source->AddBoolean("isOobeJelly", features::IsOobeJellyEnabled()); source->AddBoolean("isChoobeEnabled", features::IsOobeChoobeEnabled()); // Configure shared resources
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom index d18898e6..29e011b 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom
@@ -126,6 +126,11 @@ // Choose custom background from local file system. ChooseLocalCustomBackground() => (bool success); + // Sets the background image and notifies all NTPs of the change. + SetBackgroundImage(string attribution_1, string attribution_2, + url.mojom.Url attribution_url, url.mojom.Url image_url, + url.mojom.Url thumbnail_url); + // Open Chrome Web Store in a new tab. OpenChromeWebStore();
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc index b33a408..66e4935 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc
@@ -247,6 +247,19 @@ nullptr); } +void CustomizeChromePageHandler::SetBackgroundImage( + const std::string& attribution_1, + const std::string& attribution_2, + const GURL& attribution_url, + const GURL& image_url, + const GURL& thumbnail_url) { + // Populating the |collection_id| turns on refresh daily which overrides the + // the selected image. + ntp_custom_background_service_->SetCustomBackgroundInfo( + image_url, thumbnail_url, attribution_1, attribution_2, attribution_url, + /* collection_id= */ ""); +} + void CustomizeChromePageHandler::OpenChromeWebStore() { NavigateParams navigate_params( profile_, GURL("https://chrome.google.com/webstore?category=theme"),
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h index 2c01b64e..483697e 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h
@@ -64,6 +64,11 @@ void SetClassicChromeDefaultTheme() override; void ChooseLocalCustomBackground( ChooseLocalCustomBackgroundCallback callback) override; + void SetBackgroundImage(const std::string& attribution_1, + const std::string& attribution_2, + const GURL& attribution_url, + const GURL& image_url, + const GURL& thumbnail_url) override; void OpenChromeWebStore() override; void SetModulesVisible(bool visible) override; void SetModuleDisabled(const std::string& module_id, bool disabled) override;
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc index 755b501d..95b960e 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc
@@ -157,6 +157,13 @@ MOCK_METHOD0(ResetCustomBackgroundInfo, void()); MOCK_METHOD1(SelectLocalBackgroundImage, void(const base::FilePath&)); MOCK_METHOD1(AddObserver, void(NtpCustomBackgroundServiceObserver*)); + MOCK_METHOD6(SetCustomBackgroundInfo, + void(const GURL&, + const GURL&, + const std::string&, + const std::string&, + const GURL&, + const std::string&)); }; class MockNtpBackgroundService : public NtpBackgroundService { @@ -590,6 +597,14 @@ browser().tab_strip_model()->GetWebContentsAt(0)->GetURL()); } +TEST_F(CustomizeChromePageHandlerTest, SetBackgroundImage) { + EXPECT_CALL(mock_ntp_custom_background_service_, SetCustomBackgroundInfo) + .Times(1); + handler().SetBackgroundImage( + "attribution1", "attribution2", GURL("https://attribution.com"), + GURL("https://image.jpg"), GURL("https://thumbnail.jpg")); +} + class CustomizeChromePageHandlerWithModulesTest : public CustomizeChromePageHandlerTest { public:
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index 8772e63..3b8d436 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -110,6 +110,8 @@ "os_integration/os_integration_sub_manager.h", "os_integration/protocol_handling_sub_manager.cc", "os_integration/protocol_handling_sub_manager.h", + "os_integration/run_on_os_login_sub_manager.cc", + "os_integration/run_on_os_login_sub_manager.h", "os_integration/shortcut_handling_sub_manager.cc", "os_integration/shortcut_handling_sub_manager.h", "os_integration/url_handler_manager.cc", @@ -585,6 +587,7 @@ "isolation_prefs_utils_unittest.cc", "os_integration/os_integration_manager_unittest.cc", "os_integration/protocol_handling_sub_manager_unittest.cc", + "os_integration/run_on_os_login_sub_manager_unittest.cc", "os_integration/web_app_file_handler_manager_unittest.cc", "os_integration/web_app_protocol_handler_manager_unittest.cc", "os_integration/web_app_shortcut_unittest.cc",
diff --git a/chrome/browser/web_applications/commands/run_on_os_login_command.cc b/chrome/browser/web_applications/commands/run_on_os_login_command.cc index c192884..cc556934 100644 --- a/chrome/browser/web_applications/commands/run_on_os_login_command.cc +++ b/chrome/browser/web_applications/commands/run_on_os_login_command.cc
@@ -145,8 +145,7 @@ if (login_mode_.value() == current_mode.value) { RecordCompletionState( RunOnOsLoginCommandCompletionState::kRunOnOsLoginModeAlreadyMatched); - SignalCompletionAndSelfDestruct(CommandResult::kSuccess, - std::move(callback_)); + OnOsHooksSet(OsHooksErrors()); return; } @@ -188,8 +187,7 @@ if (os_integration_state && login_mode_.value() == *os_integration_state) { RecordCompletionState( RunOnOsLoginCommandCompletionState::kRunOnOsLoginModeAlreadyMatched); - SignalCompletionAndSelfDestruct(CommandResult::kSuccess, - std::move(callback_)); + std::move(os_hooks_callback).Run(OsHooksErrors()); return; } @@ -197,13 +195,13 @@ // once OS integration // sub managers have been implemented. if (login_mode_.value() == RunOnOsLoginMode::kNotRun) { - web_app::OsHooksOptions os_hooks; - os_hooks[web_app::OsHookType::kRunOnOsLogin] = true; + OsHooksOptions os_hooks; + os_hooks[OsHookType::kRunOnOsLogin] = true; lock_->os_integration_manager().UninstallOsHooks( app_id_, os_hooks, std::move(os_hooks_callback)); } else { - web_app::InstallOsHooksOptions install_options; - install_options.os_hooks[web_app::OsHookType::kRunOnOsLogin] = true; + InstallOsHooksOptions install_options; + install_options.os_hooks[OsHookType::kRunOnOsLogin] = true; install_options.reason = SHORTCUT_CREATION_AUTOMATED; lock_->os_integration_manager().InstallOsHooks( app_id_, std::move(os_hooks_callback), nullptr, @@ -211,19 +209,24 @@ } } -void RunOnOsLoginCommand::OnOsHooksSet(web_app::OsHooksErrors errors) { - if (errors[web_app::OsHookType::kRunOnOsLogin] == true) { +void RunOnOsLoginCommand::OnOsHooksSet(OsHooksErrors errors) { + if (errors[OsHookType::kRunOnOsLogin] == true) { Abort(RunOnOsLoginCommandCompletionState::kOSHooksNotProperlySet); return; } - RecordCompletionState( - RunOnOsLoginCommandCompletionState::kSuccessfulCompletion); + + if (!completion_state_set_) { + RecordCompletionState( + RunOnOsLoginCommandCompletionState::kSuccessfulCompletion); + } + SignalCompletionAndSelfDestruct(CommandResult::kSuccess, std::move(callback_)); } void RunOnOsLoginCommand::RecordCompletionState( RunOnOsLoginCommandCompletionState completed_state) { + completion_state_set_ = true; base::UmaHistogramEnumeration("WebApp.RunOnOsLogin.CommandCompletionState", completed_state); }
diff --git a/chrome/browser/web_applications/commands/run_on_os_login_command.h b/chrome/browser/web_applications/commands/run_on_os_login_command.h index 1b27d498..9ce0ef7 100644 --- a/chrome/browser/web_applications/commands/run_on_os_login_command.h +++ b/chrome/browser/web_applications/commands/run_on_os_login_command.h
@@ -87,6 +87,7 @@ RunOnOsLoginAction set_or_sync_mode_; std::string stop_reason_; base::OnceClosure callback_ = base::DoNothing(); + bool completion_state_set_ = false; base::WeakPtrFactory<RunOnOsLoginCommand> weak_factory_{this}; };
diff --git a/chrome/browser/web_applications/os_integration/os_integration_manager.cc b/chrome/browser/web_applications/os_integration/os_integration_manager.cc index 751fcd82..14cd9f34 100644 --- a/chrome/browser/web_applications/os_integration/os_integration_manager.cc +++ b/chrome/browser/web_applications/os_integration/os_integration_manager.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/web_applications/os_integration/os_integration_sub_manager.h" #include "chrome/browser/web_applications/os_integration/protocol_handling_sub_manager.h" +#include "chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.h" #include "chrome/browser/web_applications/os_integration/shortcut_handling_sub_manager.h" #include "chrome/browser/web_applications/os_integration/web_app_shortcut.h" #include "chrome/browser/web_applications/os_integration/web_app_uninstallation_via_os_settings_registration.h" @@ -189,8 +190,12 @@ std::make_unique<ShortcutHandlingSubManager>(*icon_manager, *registrar); auto protocol_handling_sub_manager = std::make_unique<ProtocolHandlingSubManager>(*registrar); + + auto run_on_os_login_sub_manager = + std::make_unique<RunOnOsLoginSubManager>(*registrar); sub_managers_.push_back(std::move(shortcut_handling_sub_manager)); sub_managers_.push_back(std::move(protocol_handling_sub_manager)); + sub_managers_.push_back(std::move(run_on_os_login_sub_manager)); } void OsIntegrationManager::Start() {
diff --git a/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.cc b/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.cc new file mode 100644 index 0000000..701e4740 --- /dev/null +++ b/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.cc
@@ -0,0 +1,72 @@ + +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.h" + +#include <utility> + +#include "base/functional/callback.h" +#include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h" +#include "chrome/browser/web_applications/web_app_id.h" +#include "chrome/browser/web_applications/web_app_registrar.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace web_app { + +namespace { + +proto::RunOnOsLoginMode ConvertWebAppRunOnOsLoginModeToProto( + RunOnOsLoginMode mode) { + switch (mode) { + case RunOnOsLoginMode::kMinimized: + return proto::RunOnOsLoginMode::MINIMIZED; + case RunOnOsLoginMode::kWindowed: + return proto::RunOnOsLoginMode::WINDOWED; + case RunOnOsLoginMode::kNotRun: + return proto::RunOnOsLoginMode::NOT_RUN; + } +} + +} // namespace + +RunOnOsLoginSubManager::RunOnOsLoginSubManager(WebAppRegistrar& registrar) + : registrar_(registrar) {} + +RunOnOsLoginSubManager::~RunOnOsLoginSubManager() = default; + +void RunOnOsLoginSubManager::Configure( + const AppId& app_id, + proto::WebAppOsIntegrationState& desired_state, + base::OnceClosure configure_done) { + if (!registrar_->GetAppById(app_id)) { + std::move(configure_done).Run(); + return; + } + + DCHECK(!desired_state.has_run_on_os_login()); + + proto::RunOnOsLogin* run_on_os_login = + desired_state.mutable_run_on_os_login(); + + const auto login_mode = registrar_->GetAppRunOnOsLoginMode(app_id); + run_on_os_login->set_run_on_os_login_mode( + ConvertWebAppRunOnOsLoginModeToProto(login_mode.value)); + + std::move(configure_done).Run(); +} + +void RunOnOsLoginSubManager::Start() {} + +void RunOnOsLoginSubManager::Shutdown() {} + +void RunOnOsLoginSubManager::Execute( + const AppId& app_id, + const proto::WebAppOsIntegrationState& desired_state, + const absl::optional<proto::WebAppOsIntegrationState>& current_state, + base::OnceClosure callback) { + NOTREACHED() << "Not yet implemented"; +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.h b/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.h new file mode 100644 index 0000000..e1fb598 --- /dev/null +++ b/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager.h
@@ -0,0 +1,41 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_WEB_APPLICATIONS_OS_INTEGRATION_RUN_ON_OS_LOGIN_SUB_MANAGER_H_ +#define CHROME_BROWSER_WEB_APPLICATIONS_OS_INTEGRATION_RUN_ON_OS_LOGIN_SUB_MANAGER_H_ + +#include "base/functional/callback_forward.h" +#include "base/memory/raw_ref.h" +#include "chrome/browser/web_applications/os_integration/os_integration_sub_manager.h" +#include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h" +#include "chrome/browser/web_applications/web_app_id.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace web_app { + +class WebAppRegistrar; + +class RunOnOsLoginSubManager : public OsIntegrationSubManager { + public: + explicit RunOnOsLoginSubManager(WebAppRegistrar& registrar); + ~RunOnOsLoginSubManager() override; + void Start() override; + void Shutdown() override; + + void Configure(const AppId& app_id, + proto::WebAppOsIntegrationState& desired_state, + base::OnceClosure configure_done) override; + void Execute( + const AppId& app_id, + const proto::WebAppOsIntegrationState& desired_state, + const absl::optional<proto::WebAppOsIntegrationState>& current_state, + base::OnceClosure callback) override; + + private: + const raw_ref<WebAppRegistrar> registrar_; +}; + +} // namespace web_app + +#endif // CHROME_BROWSER_WEB_APPLICATIONS_OS_INTEGRATION_RUN_ON_OS_LOGIN_SUB_MANAGER_H_
diff --git a/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager_unittest.cc b/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager_unittest.cc new file mode 100644 index 0000000..dd2f22f --- /dev/null +++ b/chrome/browser/web_applications/os_integration/run_on_os_login_sub_manager_unittest.cc
@@ -0,0 +1,287 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> +#include <utility> + +#include "base/files/file_util.h" +#include "base/json/json_reader.h" +#include "base/strings/string_piece_forward.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/test_future.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/os_integration/os_integration_manager.h" +#include "chrome/browser/web_applications/policy/web_app_policy_manager.h" +#include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h" +#include "chrome/browser/web_applications/test/fake_web_app_provider.h" +#include "chrome/browser/web_applications/test/web_app_install_test_utils.h" +#include "chrome/browser/web_applications/test/web_app_test.h" +#include "chrome/browser/web_applications/test/web_app_test_utils.h" +#include "chrome/browser/web_applications/web_app_command_scheduler.h" +#include "chrome/browser/web_applications/web_app_install_info.h" +#include "chrome/browser/web_applications/web_app_install_params.h" +#include "chrome/browser/web_applications/web_app_provider.h" +#include "chrome/common/chrome_features.h" +#include "chrome/common/pref_names.h" +#include "components/prefs/pref_service.h" +#include "components/webapps/browser/install_result_code.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace web_app { + +namespace { + +class RunOnOsLoginSubManagerTest + : public WebAppTest, + public ::testing::WithParamInterface<OsIntegrationSubManagersState> { + public: + const GURL kWebAppUrl = GURL("https://example.com/path/index.html"); + + RunOnOsLoginSubManagerTest() = default; + ~RunOnOsLoginSubManagerTest() override = default; + + void SetUp() override { + WebAppTest::SetUp(); + { + base::ScopedAllowBlockingForTesting allow_blocking; + shortcut_override_ = + ShortcutOverrideForTesting::OverrideForTesting(base::GetHomeDir()); + } + if (EnableOsIntegrationSubManager()) { + scoped_feature_list_.InitAndEnableFeatureWithParameters( + features::kOsIntegrationSubManagers, {{"stage", "write_config"}}); + } else { + scoped_feature_list_.InitWithFeatures( + /*enabled_features=*/{}, + /*disabled_features=*/{features::kOsIntegrationSubManagers}); + } + + provider_ = FakeWebAppProvider::Get(profile()); + + auto file_handler_manager = + std::make_unique<WebAppFileHandlerManager>(profile()); + auto protocol_handler_manager = + std::make_unique<WebAppProtocolHandlerManager>(profile()); + auto shortcut_manager = std::make_unique<WebAppShortcutManager>( + profile(), /*icon_manager=*/nullptr, file_handler_manager.get(), + protocol_handler_manager.get()); + auto os_integration_manager = std::make_unique<OsIntegrationManager>( + profile(), std::move(shortcut_manager), std::move(file_handler_manager), + std::move(protocol_handler_manager), /*url_handler_manager=*/nullptr); + + provider_->SetOsIntegrationManager(std::move(os_integration_manager)); + test::AwaitStartWebAppProviderAndSubsystems(profile()); + } + + void TearDown() override { + test::UninstallAllWebApps(profile()); + { + // Blocking required due to file operations in the shortcut override + // destructor. + base::ScopedAllowBlockingForTesting allow_blocking; + shortcut_override_.reset(); + } + WebAppTest::TearDown(); + } + + bool EnableOsIntegrationSubManager() { + return GetParam() == OsIntegrationSubManagersState::kEnabled; + } + + AppId InstallWebApp() { + std::unique_ptr<WebAppInstallInfo> info = + std::make_unique<WebAppInstallInfo>(); + info->start_url = kWebAppUrl; + info->title = u"Test App"; + info->user_display_mode = web_app::UserDisplayMode::kStandalone; + base::test::TestFuture<const AppId&, webapps::InstallResultCode> result; + // InstallFromInfoWithParams is used instead of InstallFromInfo, because + // InstallFromInfo doesn't register OS integration. + provider().scheduler().InstallFromInfoWithParams( + std::move(info), /*overwrite_existing_manifest_fields=*/true, + webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, + result.GetCallback(), WebAppInstallParams()); + bool success = result.Wait(); + EXPECT_TRUE(success); + if (!success) { + return AppId(); + } + EXPECT_EQ(result.Get<webapps::InstallResultCode>(), + webapps::InstallResultCode::kSuccessNewInstall); + return result.Get<AppId>(); + } + + void SetWebAppSettingsListPref(const base::StringPiece pref) { + auto result = base::JSONReader::ReadAndReturnValueWithError( + pref, base::JSONParserOptions::JSON_ALLOW_TRAILING_COMMAS); + ASSERT_TRUE(result.has_value()) << result.error().message; + ASSERT_TRUE(result->is_list()); + profile()->GetPrefs()->Set(prefs::kWebAppSettings, std::move(*result)); + } + + protected: + WebAppProvider& provider() { return *provider_; } + WebAppRegistrar& registrar() { return provider().registrar_unsafe(); } + + private: + raw_ptr<FakeWebAppProvider> provider_; + base::test::ScopedFeatureList scoped_feature_list_; + std::unique_ptr<ShortcutOverrideForTesting::BlockingRegistration> + shortcut_override_; +}; + +TEST_P(RunOnOsLoginSubManagerTest, VerifyRunOnOsLoginSetProperlyOnInstall) { + const AppId& app_id = InstallWebApp(); + + auto state = registrar().GetAppCurrentOsIntegrationState(app_id); + if (EnableOsIntegrationSubManager()) { + // on installation, both values are set to NOT_RUN. + ASSERT_TRUE(state.has_value()); + const proto::WebAppOsIntegrationState& os_integration_state = state.value(); + ASSERT_TRUE(os_integration_state.has_run_on_os_login()); + const proto::RunOnOsLogin& run_on_os_login = + os_integration_state.run_on_os_login(); + ASSERT_THAT(run_on_os_login.run_on_os_login_mode(), + testing::Eq(proto::RunOnOsLoginMode::NOT_RUN)); + } else { + ASSERT_FALSE(state.has_value()); + } +} + +TEST_P(RunOnOsLoginSubManagerTest, VerifyRunOnOsLoginSetFromCommand) { + const AppId& app_id = InstallWebApp(); + + base::test::TestFuture<void> future; + provider().scheduler().SetRunOnOsLoginMode( + app_id, RunOnOsLoginMode::kWindowed, future.GetCallback()); + EXPECT_TRUE(future.Wait()); + auto state = registrar().GetAppCurrentOsIntegrationState(app_id); + + if (EnableOsIntegrationSubManager()) { + ASSERT_TRUE(state.has_value()); + const proto::WebAppOsIntegrationState& os_integration_state = state.value(); + ASSERT_TRUE(os_integration_state.has_run_on_os_login()); + const proto::RunOnOsLogin& run_on_os_login = + os_integration_state.run_on_os_login(); + ASSERT_THAT(run_on_os_login.run_on_os_login_mode(), + testing::Eq(proto::RunOnOsLoginMode::WINDOWED)); + } else { + ASSERT_FALSE(state.has_value()); + } +} + +TEST_P(RunOnOsLoginSubManagerTest, VerifyPolicySettingBlocked) { + const AppId& app_id = InstallWebApp(); + + const char kWebAppSettingPolicyBlockedConfig[] = R"([{ + "manifest_id" : "https://example.com/path/index.html", + "run_on_os_login": "blocked" + }])"; + + { + base::test::TestFuture<void> policy_future; + provider() + .policy_manager() + .SetRefreshPolicySettingsCompletedCallbackForTesting( + policy_future.GetCallback()); + SetWebAppSettingsListPref(kWebAppSettingPolicyBlockedConfig); + EXPECT_TRUE(policy_future.Wait()); + } + + auto state = registrar().GetAppCurrentOsIntegrationState(app_id); + if (EnableOsIntegrationSubManager()) { + ASSERT_TRUE(state.has_value()); + const proto::WebAppOsIntegrationState& os_integration_state = state.value(); + ASSERT_TRUE(os_integration_state.has_run_on_os_login()); + const proto::RunOnOsLogin& run_on_os_login = + os_integration_state.run_on_os_login(); + ASSERT_THAT(run_on_os_login.run_on_os_login_mode(), + testing::Eq(proto::RunOnOsLoginMode::NOT_RUN)); + } else { + ASSERT_FALSE(state.has_value()); + } +} + +TEST_P(RunOnOsLoginSubManagerTest, VerifyPolicySettingWindowedMode) { + const AppId& app_id = InstallWebApp(); + + const char kWebAppSettingPolicyWindowedConfig[] = R"([{ + "manifest_id" : "https://example.com/path/index.html", + "run_on_os_login": "run_windowed" + }])"; + + { + base::test::TestFuture<void> policy_future; + provider() + .policy_manager() + .SetRefreshPolicySettingsCompletedCallbackForTesting( + policy_future.GetCallback()); + SetWebAppSettingsListPref(kWebAppSettingPolicyWindowedConfig); + EXPECT_TRUE(policy_future.Wait()); + } + + auto state = registrar().GetAppCurrentOsIntegrationState(app_id); + if (EnableOsIntegrationSubManager()) { + ASSERT_TRUE(state.has_value()); + const proto::WebAppOsIntegrationState& os_integration_state = state.value(); + ASSERT_TRUE(os_integration_state.has_run_on_os_login()); + const proto::RunOnOsLogin& run_on_os_login = + os_integration_state.run_on_os_login(); + ASSERT_THAT(run_on_os_login.run_on_os_login_mode(), + testing::Eq(proto::RunOnOsLoginMode::WINDOWED)); + } else { + ASSERT_FALSE(state.has_value()); + } +} + +TEST_P(RunOnOsLoginSubManagerTest, VerifyPolicySettingAllowedMode) { + const AppId& app_id = InstallWebApp(); + + const char kWebAppSettingPolicyAllowedConfig[] = R"([{ + "manifest_id" : "https://example.com/path/index.html", + "run_on_os_login": "allowed" + }])"; + + { + base::test::TestFuture<void> policy_future; + provider() + .policy_manager() + .SetRefreshPolicySettingsCompletedCallbackForTesting( + policy_future.GetCallback()); + SetWebAppSettingsListPref(kWebAppSettingPolicyAllowedConfig); + EXPECT_TRUE(policy_future.Wait()); + } + + auto state = registrar().GetAppCurrentOsIntegrationState(app_id); + if (EnableOsIntegrationSubManager()) { + ASSERT_TRUE(state.has_value()); + const proto::WebAppOsIntegrationState& os_integration_state = state.value(); + ASSERT_TRUE(os_integration_state.has_run_on_os_login()); + const proto::RunOnOsLogin& run_on_os_login = + os_integration_state.run_on_os_login(); + ASSERT_THAT(run_on_os_login.run_on_os_login_mode(), + testing::Eq(proto::RunOnOsLoginMode::NOT_RUN)); + } else { + ASSERT_FALSE(state.has_value()); + } +} + +TEST_P(RunOnOsLoginSubManagerTest, StatesEmptyOnUninstall) { + const AppId& app_id = InstallWebApp(); + test::UninstallAllWebApps(profile()); + auto state = registrar().GetAppCurrentOsIntegrationState(app_id); + ASSERT_FALSE(state.has_value()); +} + +INSTANTIATE_TEST_SUITE_P( + All, + RunOnOsLoginSubManagerTest, + ::testing::Values(OsIntegrationSubManagersState::kEnabled, + OsIntegrationSubManagersState::kDisabled), + test::GetOsIntegrationSubManagersTestName); + +} // namespace + +} // namespace web_app
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager.cc b/chrome/browser/web_applications/policy/web_app_policy_manager.cc index 4ac2bff..8b9ab4c 100644 --- a/chrome/browser/web_applications/policy/web_app_policy_manager.cc +++ b/chrome/browser/web_applications/policy/web_app_policy_manager.cc
@@ -239,6 +239,10 @@ void WebAppPolicyManager::OnSyncCommandsComplete( std::vector<std::string> app_ids) { app_registrar_->NotifyWebAppSettingsPolicyChanged(); + + if (refresh_policy_settings_completed_) { + std::move(refresh_policy_settings_completed_).Run(); + } } #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -422,9 +426,6 @@ } ApplyPolicySettings(); - - if (refresh_policy_settings_completed_) - std::move(refresh_policy_settings_completed_).Run(); } void WebAppPolicyManager::ApplyPolicySettings() {
diff --git a/chrome/browser/web_applications/proto/web_app_os_integration_state.proto b/chrome/browser/web_applications/proto/web_app_os_integration_state.proto index b37db0a..fee5aa3 100644 --- a/chrome/browser/web_applications/proto/web_app_os_integration_state.proto +++ b/chrome/browser/web_applications/proto/web_app_os_integration_state.proto
@@ -28,12 +28,27 @@ repeated Protocol protocols = 1; } +// Run on OS Login modes for web app. +// See chrome/browser/web_applications/web_app_constants.h +// for web_app::RunOnOsLoginMode definition, which this enum should be in sync +// with. +enum RunOnOsLoginMode { + RUN_ON_OS_LOGIN_MODE_UNSPECIFIED = 0; + NOT_RUN = 1; + WINDOWED = 2; + MINIMIZED = 3; +} + +message RunOnOsLogin { + optional RunOnOsLoginMode run_on_os_login_mode = 1; +} + // Represents all the common OS Integration states to be stored in the web_app // DB that matches the values in the OS. message WebAppOsIntegrationState { reserved 2; optional ShortcutDescription shortcut = 1; optional ProtocolsHandled protocols_handled = 3; - + optional RunOnOsLogin run_on_os_login = 4; // Add data states for other OS integration hooks here. } \ No newline at end of file
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h index c7a4f8e..b25353f 100644 --- a/chrome/browser/web_applications/web_app.h +++ b/chrome/browser/web_applications/web_app.h
@@ -485,6 +485,8 @@ // Tracks if the app run on os login mode has been registered with the OS. // This might go out of sync with actual OS integration status, as Chrome does // not actively monitor OS registries. + // TODO(crbug.com/1401125): Remove after all OS Integration sub managers have + // been implemented and Synchronize() is running fine. absl::optional<RunOnOsLoginMode> run_on_os_login_os_integration_state_; SyncFallbackData sync_fallback_data_; blink::mojom::CaptureLinks capture_links_ =
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 513c3a6..0645941 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1671645419-579bdd82a8e15162e690e78e3e3a84ba10ca5d53.profdata +chrome-linux-main-1671709962-bf0d4c87ce7f67d80bfc0f8c21dff4fb7d49b87f.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 177b66e..024515f 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1671709962-db445d8b6e7b0fcb69b7fe803bc275df9c5d6ef5.profdata +chrome-mac-main-1671731872-e64a2792eafde6af466e698a236a817d2fcb14c8.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 69f4608..d1e38d61 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1671685452-ccde62eeadefd5bba36a6878de84f064cc8e801f.profdata +chrome-win32-main-1671721064-189024d4b81230d96d5ab1605f78c6009bc20cd6.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 291f4a9..106a9d9 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1671677985-53a355963172030f44c84218d4e693cb8b05f46a.profdata +chrome-win64-main-1671709962-86e5c2f479991b3710dd2b796a8a5ecc2dbf3c7c.profdata
diff --git a/chrome/common/extensions/manifest_handlers/content_scripts_manifest_unittest.cc b/chrome/common/extensions/manifest_handlers/content_scripts_manifest_unittest.cc index e556386d..35b06c4 100644 --- a/chrome/common/extensions/manifest_handlers/content_scripts_manifest_unittest.cc +++ b/chrome/common/extensions/manifest_handlers/content_scripts_manifest_unittest.cc
@@ -195,4 +195,37 @@ user_scripts[6]->match_origin_as_fallback()); } +TEST_F(ContentScriptsManifestTest, ExecutionWorld) { + scoped_refptr<const Extension> extension = + LoadAndExpectSuccess("content_script_execution_world.json"); + const UserScriptList& user_scripts = + ContentScriptsInfo::GetContentScripts(extension.get()); + ASSERT_EQ(3u, user_scripts.size()); + + // Content scripts which don't specify an execution world will default to the + // isolated world. + EXPECT_EQ(mojom::ExecutionWorld::kIsolated, + user_scripts[0]->execution_world()); + + // Content scripts which specify an execution world will run on the world that + // was specified. + EXPECT_EQ(mojom::ExecutionWorld::kMain, user_scripts[1]->execution_world()); + EXPECT_EQ(mojom::ExecutionWorld::kIsolated, + user_scripts[2]->execution_world()); +} + +TEST_F(ContentScriptsManifestTest, ExecutionWorld_InvalidForMV2) { + scoped_refptr<const Extension> extension = LoadAndExpectWarning( + "content_script_execution_world_warning_for_mv2.json", + errors::kExecutionWorldRestrictedToMV3); + const UserScriptList& user_scripts = + ContentScriptsInfo::GetContentScripts(extension.get()); + ASSERT_EQ(1u, user_scripts.size()); + + // The content script parsed from the manifest should be executing in the + // isolated world. + EXPECT_EQ(mojom::ExecutionWorld::kIsolated, + user_scripts[0]->execution_world()); +} + } // namespace extensions
diff --git a/chrome/test/data/extensions/api_test/content_scripts/main_world_injections/change_title.js b/chrome/test/data/extensions/api_test/content_scripts/main_world_injections/change_title.js new file mode 100644 index 0000000..51e33ebd --- /dev/null +++ b/chrome/test/data/extensions/api_test/content_scripts/main_world_injections/change_title.js
@@ -0,0 +1,8 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Changes the document's title based on the existence/value of +// window.mainWorldFlag, which is set by a script that's part of a web page. +document.title = window.mainWorldFlag === 'from main world' ? 'MAIN_WORLD' : + 'ISOLATED_WORLD';
diff --git a/chrome/test/data/extensions/api_test/content_scripts/main_world_injections/manifest.json b/chrome/test/data/extensions/api_test/content_scripts/main_world_injections/manifest.json new file mode 100644 index 0000000..0994de46 --- /dev/null +++ b/chrome/test/data/extensions/api_test/content_scripts/main_world_injections/manifest.json
@@ -0,0 +1,25 @@ +{ + "manifest_version": 3, + "name": "Main world content script test extension", + "version": "0.1", + "description": "Tests that scripts can be injected into the main world", + "background": { + "service_worker": "worker.js", + "type": "module" + }, + "permissions": ["scripting", "tabs"], + "host_permissions": ["*://main.example/*", "*://isolated.example/*"], + "content_scripts": [ + { + "matches": ["*://main.example/*"], + "js": ["change_title.js"], + "world": "MAIN", + "runAt": "document_end" + }, { + "matches": ["*://isolated.example/*"], + "js": ["change_title.js"], + "world": "ISOLATED", + "runAt": "document_end" + } + ] +}
diff --git a/chrome/test/data/extensions/api_test/content_scripts/main_world_injections/worker.js b/chrome/test/data/extensions/api_test/content_scripts/main_world_injections/worker.js new file mode 100644 index 0000000..0e6e8e1 --- /dev/null +++ b/chrome/test/data/extensions/api_test/content_scripts/main_world_injections/worker.js
@@ -0,0 +1,40 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {openTab} from '/_test_resources/test_util/tabs_util.js'; + +chrome.test.runTests([ + async function contentScriptsInMainWorld() { + const config = await chrome.test.getConfig(); + + // Opens a tab where a script may be injected that changes the title based + // on the execution world it's running in, then call executeScript which + // checks the title. + const exampleUrl = `http://main.example:${ + config.testServer.port}/extensions/main_world_script_flag.html`; + let tab = await openTab(exampleUrl); + let results = await chrome.scripting.executeScript({ + target: {tabId: tab.id}, + func: () => document.title, + }); + chrome.test.assertEq('MAIN_WORLD', results[0].result); + chrome.test.succeed(); + }, + + async function contentScriptsInIsolatedWorld() { + const config = await chrome.test.getConfig(); + + // Repeat the test above except the script should be running in the isolated + // world. + const hostPermsUrl = `http://isolated.example:${ + config.testServer.port}/extensions/main_world_script_flag.html`; + const tab = await openTab(hostPermsUrl); + const results = await chrome.scripting.executeScript({ + target: {tabId: tab.id}, + func: () => document.title, + }); + chrome.test.assertEq('ISOLATED_WORLD', results[0].result); + chrome.test.succeed(); + }, +]);
diff --git a/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/inject_dynamic_1.js b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/inject_dynamic_1.js new file mode 100644 index 0000000..be62d18 --- /dev/null +++ b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/inject_dynamic_1.js
@@ -0,0 +1,7 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var div = document.createElement('div'); +div.id = 'dynamic-1'; +document.body.appendChild(div);
diff --git a/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/inject_dynamic_2.js b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/inject_dynamic_2.js new file mode 100644 index 0000000..00cf7df3 --- /dev/null +++ b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/inject_dynamic_2.js
@@ -0,0 +1,7 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var div = document.createElement('div'); +div.id = 'dynamic-2'; +document.body.appendChild(div);
diff --git a/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/inject_dynamic_slightly_big.js b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/inject_dynamic_slightly_big.js new file mode 100644 index 0000000..392bd6cf --- /dev/null +++ b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/inject_dynamic_slightly_big.js
@@ -0,0 +1,19 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var div = document.createElement('div'); +div.id = 'dynamic-slightly-big'; +document.body.appendChild(div); +/* +PADDING OUT THE FILE TO BE OVER 650 BYTES +PADDING OUT THE FILE TO BE OVER 650 BYTES +PADDING OUT THE FILE TO BE OVER 650 BYTES +PADDING OUT THE FILE TO BE OVER 650 BYTES +PADDING OUT THE FILE TO BE OVER 650 BYTES +PADDING OUT THE FILE TO BE OVER 650 BYTES +PADDING OUT THE FILE TO BE OVER 650 BYTES +PADDING OUT THE FILE TO BE OVER 650 BYTES +PADDING OUT THE FILE TO BE OVER 650 BYTES +PADDING OUT THE FILE +*/
diff --git a/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/inject_dynamic_too_big.js b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/inject_dynamic_too_big.js new file mode 100644 index 0000000..eec3bfa --- /dev/null +++ b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/inject_dynamic_too_big.js
@@ -0,0 +1,20 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var div = document.createElement('div'); +div.id = 'dynamic-too-big'; +document.body.appendChild(div); +/* +PADDING OUT THE FILE TO BE OVER 700 BYTES +PADDING OUT THE FILE TO BE OVER 700 BYTES +PADDING OUT THE FILE TO BE OVER 700 BYTES +PADDING OUT THE FILE TO BE OVER 700 BYTES +PADDING OUT THE FILE TO BE OVER 700 BYTES +PADDING OUT THE FILE TO BE OVER 700 BYTES +PADDING OUT THE FILE TO BE OVER 700 BYTES +PADDING OUT THE FILE TO BE OVER 700 BYTES +PADDING OUT THE FILE TO BE OVER 700 BYTES +PADDING OUT THE FILE TO BE OVER 700 BYTES +PADDING OUT THE FILE TO BE OVER 700 BYTES +*/
diff --git a/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/inject_manifest.js b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/inject_manifest.js new file mode 100644 index 0000000..580020c --- /dev/null +++ b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/inject_manifest.js
@@ -0,0 +1,13 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var div = document.createElement('div'); +div.id = 'manifest'; +document.body.appendChild(div); +/* +PADDING OUT THE FILE TO BE OVER 400 BYTES +PADDING OUT THE FILE TO BE OVER 400 BYTES +PADDING OUT THE FILE TO BE OVER 400 BYTES +PADDING OUT THE FILE TO BE OVER 400 BYTES +*/
diff --git a/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/manifest.json b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/manifest.json new file mode 100644 index 0000000..7f54139 --- /dev/null +++ b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/manifest.json
@@ -0,0 +1,19 @@ +{ + "name": "Large dynamic content scripts", + "version": "1.0", + "manifest_version": 3, + "description": "Dynamic scripts that surpass the size limit are not loaded.", + "background": { + "service_worker": "worker.js", + "type": "module" + }, + "permissions": ["scripting", "tabs"], + "host_permissions": ["*://example.com/*"], + "content_scripts": [ + { + "matches": ["<all_urls>"], + "js": ["inject_manifest.js"], + "run_at": "document_end" + } + ] +}
diff --git a/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/worker.js b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/worker.js new file mode 100644 index 0000000..ffc2848 --- /dev/null +++ b/chrome/test/data/extensions/api_test/scripting/dynamic_scripts_size_limits/worker.js
@@ -0,0 +1,112 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {openTab} from '/_test_resources/test_util/tabs_util.js'; + +function getInjectedElementIds() { + let childIds = []; + for (const child of document.body.children) + childIds.push(child.id); + return childIds.sort(); +}; + +function getFileTooLargeError(fileName) { + return `Error: Scripts could not be loaded because '${fileName}' exceeds ` + + `the maximum script size or the extension's maximum total script size.`; +} + +chrome.test.runTests([ + async function exceedsPerScriptLimitSingleCall() { + await chrome.scripting.unregisterContentScripts(); + const scriptFile = 'inject_dynamic_too_big.js'; + const scripts = [{ + id: 'too_big', + matches: ['*://example.com/*'], + js: [scriptFile], + }]; + + await chrome.test.assertPromiseRejects( + chrome.scripting.registerContentScripts(scripts), + getFileTooLargeError(scriptFile)); + + const registeredScripts = + await chrome.scripting.getRegisteredContentScripts(); + chrome.test.assertEq([], registeredScripts); + + chrome.test.succeed(); + }, + + async function exceedsPerExtensionLimitSingleCall() { + await chrome.scripting.unregisterContentScripts(); + const bigScriptFile = 'inject_dynamic_slightly_big.js'; + const scripts = [ + { + id: 'too_big', + matches: ['http://example.com/*'], + js: [ + 'inject_dynamic_1.js', + 'inject_dynamic_2.js', + bigScriptFile, + ], + }, + { + id: 'too_big_part2', + matches: ['https://example.com/*'], + js: [bigScriptFile], + } + ]; + + await chrome.test.assertPromiseRejects( + chrome.scripting.registerContentScripts(scripts), + getFileTooLargeError(bigScriptFile)); + + const registeredScripts = + await chrome.scripting.getRegisteredContentScripts(); + chrome.test.assertEq([], registeredScripts); + + chrome.test.succeed(); + }, + + async function exceedsPerExtensionLimitOverall() { + await chrome.scripting.unregisterContentScripts(); + const bigScriptFile = 'inject_dynamic_slightly_big.js'; + const scripts = [{ + id: 'too_big', + matches: ['http://example.com/*'], + js: [ + 'inject_dynamic_1.js', + bigScriptFile, + 'inject_dynamic_2.js', + ], + }]; + + // Since the total length of files specified in the script above does not + // exceed the per-extension limit, the script is registered successfully. + await chrome.scripting.registerContentScripts(scripts); + + // However, the total length of all scripts for the extension: + // inject_manifest.js and `scripts` exceed the extension limit, as these + // scripts are being loaded (manifest first, then dynamic), any file that + // would exceed the per-extension limit at load-time will not have its + // contents loaded and will not do anything once injected. In this case, + // the files that have any actual effect are: inject_manifest.js, + // inject_dynamic_1.js and inject_dynamic_1.js. + // inject_dynamic_slightly_big.js will not have its contents loaded and thus + // will not affect the tab's contents. + const config = await chrome.test.getConfig(); + const url = `http://example.com:${config.testServer.port}/simple.html`; + let tab = await openTab(url); + let results = await chrome.scripting.executeScript( + {target: {tabId: tab.id}, func: getInjectedElementIds}); + + chrome.test.assertEq(1, results.length); + chrome.test.assertEq( + ['dynamic-1', 'dynamic-2', 'manifest'], results[0].result); + const registeredScripts = + await chrome.scripting.getRegisteredContentScripts(); + chrome.test.assertEq(1, registeredScripts.length); + + chrome.test.succeed(); + }, +]);
diff --git a/chrome/test/data/extensions/manifest_tests/content_script_execution_world.json b/chrome/test/data/extensions/manifest_tests/content_script_execution_world.json new file mode 100644 index 0000000..e8f9577f --- /dev/null +++ b/chrome/test/data/extensions/manifest_tests/content_script_execution_world.json
@@ -0,0 +1,17 @@ +{ + "name": "ContentScriptsManifestTest.ExecutionWorld", + "version": "0.1", + "manifest_version": 3, + "content_scripts": [{ + "matches": ["https://example.com/*"], + "js": ["file.js"] + }, { + "matches": ["https://google.com/*"], + "js": ["file.js"], + "world": "MAIN" + }, { + "matches": ["https://gmail.com/*"], + "js": ["file.js"], + "world": "ISOLATED" + }] +}
diff --git a/chrome/test/data/extensions/manifest_tests/content_script_execution_world_warning_for_mv2.json b/chrome/test/data/extensions/manifest_tests/content_script_execution_world_warning_for_mv2.json new file mode 100644 index 0000000..d637ce23 --- /dev/null +++ b/chrome/test/data/extensions/manifest_tests/content_script_execution_world_warning_for_mv2.json
@@ -0,0 +1,10 @@ +{ + "name": "ContentScriptsManifestTest.ExecutionWorld_InvalidForMV2", + "version": "0.1", + "manifest_version": 2, + "content_scripts": [{ + "matches": ["https://example.com/*"], + "js": ["file.js"], + "world": "MAIN" + }] +}
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index 125f596..e9578c0 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -21642,5 +21642,8 @@ } } ] + }, + "AppStoreRatingEnabled" : { + "reason_for_missing_test": "Maps into an iOS-specific pref" } }
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_test.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_test.js index ac91d125..a92f9a1 100644 --- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_test.js +++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_test.js
@@ -178,60 +178,40 @@ return flushTasks(); } - if (window.loadTimeData.getBoolean('isNetworkingEnabled') || - window.loadTimeData.getBoolean('isInputEnabled')) { - test('SystemPagePopulated', () => { - return initializeDiagnosticsApp( - fakeSystemInfo, fakeBatteryChargeStatus, fakeBatteryHealth, - fakeBatteryInfo, fakeCpuUsage, fakeMemoryUsage) - .then(() => { - const systemPage = - dx_utils.getNavigationViewPanelElement(page, 'system'); - assertTrue(!!systemPage); - assertTrue(isVisible(systemPage)); - assertFalse(isVisible(getCautionBanner())); - assertFalse(isVisible(getBottomNavContentDrawer())); - assertTrue(isVisible(getBottomNavContentPanel())); - assertTrue(isVisible(getSessionLogButton())); - }); - }); + test('SystemPagePopulated', () => { + return initializeDiagnosticsApp( + fakeSystemInfo, fakeBatteryChargeStatus, fakeBatteryHealth, + fakeBatteryInfo, fakeCpuUsage, fakeMemoryUsage) + .then(() => { + const systemPage = + dx_utils.getNavigationViewPanelElement(page, 'system'); + assertTrue(!!systemPage); + assertTrue(isVisible(systemPage)); + assertFalse(isVisible(getCautionBanner())); + assertFalse(isVisible(getBottomNavContentDrawer())); + assertTrue(isVisible(getBottomNavContentPanel())); + assertTrue(isVisible(getSessionLogButton())); + }); + }); - test('BannerVisibliblityTogglesWithEvents', () => { - const bannerMessage = 'Diagnostics Banner Message'; - return initializeDiagnosticsApp( - fakeSystemInfo, fakeBatteryChargeStatus, fakeBatteryHealth, - fakeBatteryInfo, fakeCpuUsage, fakeMemoryUsage) - .then(() => { - assertFalse(isVisible(getCautionBanner())); + test('BannerVisibliblityTogglesWithEvents', () => { + const bannerMessage = 'Diagnostics Banner Message'; + return initializeDiagnosticsApp( + fakeSystemInfo, fakeBatteryChargeStatus, fakeBatteryHealth, + fakeBatteryInfo, fakeCpuUsage, fakeMemoryUsage) + .then(() => { + assertFalse(isVisible(getCautionBanner())); - return triggerShowBannerEvent(bannerMessage); - }) - .then(() => { - assertTrue(isVisible(getCautionBanner())); - dx_utils.assertElementContainsText( - getCautionBannerMessage(), bannerMessage); + return triggerShowBannerEvent(bannerMessage); + }) + .then(() => { + assertTrue(isVisible(getCautionBanner())); + dx_utils.assertElementContainsText( + getCautionBannerMessage(), bannerMessage); - return triggerDismissBannerEvent(); - }) - .then(() => assertFalse(isVisible(getCautionBanner()))); - }); + return triggerDismissBannerEvent(); + }) + .then(() => assertFalse(isVisible(getCautionBanner()))); + }); - test('SaveSessionLogDisabledUntilResolved', () => { - return initializeDiagnosticsApp( - fakeSystemInfo, fakeBatteryChargeStatus, fakeBatteryHealth, - fakeBatteryInfo, fakeCpuUsage, fakeMemoryUsage) - .then(() => { - assertFalse(getSessionLogButton().disabled); - - DiagnosticsBrowserProxy.setSuccess(true); - getSessionLogButton().click(); - assertTrue(getSessionLogButton().disabled); - - return flushTasks(); - }) - .then(() => { - assertFalse(getSessionLogButton().disabled); - }); - }); - } });
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_utils_test.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_utils_test.js index ab89424..7c73287a 100644 --- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_utils_test.js +++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_utils_test.js
@@ -9,8 +9,6 @@ import {NetworkType} from 'chrome://diagnostics/network_health_provider.mojom-webui.js'; import {RoutineGroup} from 'chrome://diagnostics/routine_group.js'; import {RoutineType} from 'chrome://diagnostics/system_routine_controller.mojom-webui.js'; -import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; - import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; suite('diagnosticsUtilsTestSuite', function() { @@ -65,9 +63,7 @@ }); test('AllRoutineGroupsPresent', () => { - loadTimeData.overrideValues({enableArcNetworkDiagnostics: true}); - const isArcEnabled = loadTimeData.getBoolean('enableArcNetworkDiagnostics'); - const routineGroups = getRoutineGroups(NetworkType.kWiFi, isArcEnabled); + const routineGroups = getRoutineGroups(NetworkType.kWiFi); const [ localNetworkGroup, nameResolutionGroup, @@ -93,28 +89,13 @@ }); test('NetworkTypeIsNotWiFi', () => { - const isArcEnabled = loadTimeData.getBoolean('enableArcNetworkDiagnostics'); - const routineGroups = getRoutineGroups(NetworkType.kEthernet, isArcEnabled); + const routineGroups = getRoutineGroups(NetworkType.kEthernet); // WiFi group should be missing. assertEquals(routineGroups.length, 3); const groupNames = routineGroups.map(group => group.groupName); assertFalse(groupNames.includes('wifiGroupLabel')); }); - test('ArcRoutinesDisabled', () => { - loadTimeData.overrideValues({enableArcNetworkDiagnostics: false}); - const isArcEnabled = loadTimeData.getBoolean('enableArcNetworkDiagnostics'); - const routineGroups = getRoutineGroups(NetworkType.kEthernet, isArcEnabled); - const [localNetworkGroup, nameResolutionGroup, internetConnectivityGroup] = - routineGroups; - assertFalse( - nameResolutionGroup.routines.includes(RoutineType.kArcDnsResolution)); - - assertFalse(localNetworkGroup.routines.includes(RoutineType.kArcPing)); - assertFalse( - internetConnectivityGroup.routines.includes(RoutineType.kArcHttp)); - }); - test('GetNetworkCardTitle', () => { // Force connection state into title by setting displayStateInTitle to true. setDisplayStateInTitleForTesting(true);
diff --git a/chrome/test/data/webui/chromeos/diagnostics/system_page_test.js b/chrome/test/data/webui/chromeos/diagnostics/system_page_test.js index ae6d49e..e54a2fe 100644 --- a/chrome/test/data/webui/chromeos/diagnostics/system_page_test.js +++ b/chrome/test/data/webui/chromeos/diagnostics/system_page_test.js
@@ -137,7 +137,6 @@ document.createElement('system-page')); assertTrue(!!page); document.body.appendChild(page); - page.isNetworkingEnabled = false; return flushTasks(); } @@ -316,73 +315,6 @@ .then(() => assertTrue(isVisible(getSessionLogButton()))); }); - // System page is only responsible for banner display when in stand-alone - // view. - if (!window.loadTimeData.getBoolean('isNetworkingEnabled')) { - test('RunningCpuTestsShowsBanner', () => { - /** @type {?RoutineSectionElement} */ - let routineSection; - /** @type {!Array<!RoutineType>} */ - const routines = [ - RoutineType.kCpuCache, - ]; - routineController.setFakeStandardRoutineResult( - RoutineType.kCpuCache, StandardRoutineResult.kTestPassed); - return initializeSystemPage( - fakeSystemInfo, fakeBatteryChargeStatus, fakeBatteryHealth, - fakeBatteryInfo, fakeCpuUsage, fakeMemoryUsage) - .then(() => { - routineSection = dx_utils.getRoutineSection( - page.shadowRoot.querySelector('cpu-card')); - routineSection.routines = routines; - assertFalse(isVisible(getCautionBanner())); - return flushTasks(); - }) - .then(() => { - dx_utils.getRunTestsButtonFromSection(routineSection).click(); - return flushTasks(); - }) - .then(() => { - assertTrue(isVisible(getCautionBanner())); - return routineController.resolveRoutineForTesting(); - }) - .then(() => flushTasks()) - .then(() => assertFalse(isVisible(getCautionBanner()))); - }); - - test('RunningMemoryTestsShowsBanner', () => { - /** @type {?RoutineSectionElement} */ - let routineSection; - /** @type {!Array<!RoutineType>} */ - const routines = [RoutineType.kMemory]; - routineController.setFakeStandardRoutineResult( - RoutineType.kMemory, StandardRoutineResult.kTestPassed); - return initializeSystemPage( - fakeSystemInfo, fakeBatteryChargeStatus, fakeBatteryHealth, - fakeBatteryInfo, fakeCpuUsage, fakeMemoryUsage) - .then(() => { - routineSection = dx_utils.getRoutineSection( - page.shadowRoot.querySelector('memory-card')); - routineSection.routines = routines; - assertFalse(isVisible(getCautionBanner())); - return flushTasks(); - }) - .then(() => { - dx_utils.getRunTestsButtonFromSection(routineSection).click(); - return flushTasks(); - }) - .then(() => { - dx_utils.assertElementContainsText( - page.shadowRoot.querySelector('#banner > #bannerMsg'), - loadTimeData.getString('memoryBannerMessage')); - assertTrue(isVisible(getCautionBanner())); - return routineController.resolveRoutineForTesting(); - }) - .then(() => flushTasks()) - .then(() => assertFalse(isVisible(getCautionBanner()))); - }); - } - test('RecordNavigationCalled', () => { return initializeSystemPage( fakeSystemInfo, fakeBatteryChargeStatus, fakeBatteryHealth,
diff --git a/chrome/test/data/webui/chromeos/personalization_app/dynamic_color_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/dynamic_color_element_test.ts index db35891..09cc30b 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/dynamic_color_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/dynamic_color_element_test.ts
@@ -48,10 +48,7 @@ async function showStaticColorButtons() { const toggleButton = getToggleButton(); if (toggleButton.checked) { - personalizationStore.expectAction(ThemeActionName.SET_COLOR_SCHEME); - toggleButton.click(); - await personalizationStore.waitForAction( - ThemeActionName.SET_COLOR_SCHEME); + await clickToggleButton(); } assertFalse(getStaticColorSelector().hidden); } @@ -59,14 +56,19 @@ async function showColorSchemeButtons() { const toggleButton = getToggleButton(); if (!toggleButton.checked) { - personalizationStore.expectAction(ThemeActionName.SET_COLOR_SCHEME); - toggleButton.click(); - await personalizationStore.waitForAction( - ThemeActionName.SET_COLOR_SCHEME); + await clickToggleButton(); } assertFalse(getColorSchemeSelector().hidden); } + async function clickToggleButton() { + // Any time the toggle button is clicked, the color scheme is set (if + // dynamic colors are disabled, then it is set to ColorScheme.kStatic). + personalizationStore.expectAction(ThemeActionName.SET_COLOR_SCHEME); + getToggleButton().click(); + await personalizationStore.waitForAction(ThemeActionName.SET_COLOR_SCHEME); + } + setup(() => { const mocks = baseSetup(); themeProvider = mocks.themeProvider; @@ -183,9 +185,7 @@ const staticColorSelector = getStaticColorSelector(); await showColorSchemeButtons(); - personalizationStore.expectAction(ThemeActionName.SET_COLOR_SCHEME); - toggleButton.click(); - await personalizationStore.waitForAction(ThemeActionName.SET_COLOR_SCHEME); + await clickToggleButton(); assertFalse( toggleButton.checked, 'after clicking toggle, toggle should be off'); @@ -196,9 +196,7 @@ staticColorSelector.hidden, 'when the toggle is off, the static color buttons should be visible.'); - personalizationStore.expectAction(ThemeActionName.SET_COLOR_SCHEME); - toggleButton.click(); - await personalizationStore.waitForAction(ThemeActionName.SET_COLOR_SCHEME); + await clickToggleButton(); assertFalse( colorSchemeSelector.hidden, @@ -296,4 +294,35 @@ personalizationStore.data.theme.staticColorSelected); assertEquals(button.getAttribute('aria-checked'), 'true'); }); + + test('store previous color scheme selection locally', async () => { + const colorScheme = ColorScheme.kExpressive; + themeProvider.setColorScheme(colorScheme); + await initDynamicColorElement(); + + // Toggle to show static color buttons. + await clickToggleButton(); + // Toggle to show color scheme buttons again. + await clickToggleButton(); + + // The same color scheme button should be selected. + assertDeepEquals( + colorScheme, personalizationStore.data.theme.colorSchemeSelected); + }); + + test('store previous static color selection locally', async () => { + const staticColorHex = '#edd0e4'; + themeProvider.setStaticColor(hexColorToSkColor(staticColorHex)); + await initDynamicColorElement(); + + // Toggle to show color scheme buttons. + await clickToggleButton(); + // Toggle to show static color buttons again. + await clickToggleButton(); + + // The same static color button should be selected. + assertDeepEquals( + hexColorToSkColor(staticColorHex), + personalizationStore.data.theme.staticColorSelected); + }); });
diff --git a/chrome/test/data/webui/settings/site_data_test.ts b/chrome/test/data/webui/settings/site_data_test.ts index 55cf84f..3af8d4d 100644 --- a/chrome/test/data/webui/settings/site_data_test.ts +++ b/chrome/test/data/webui/settings/site_data_test.ts
@@ -14,6 +14,9 @@ // clang-format on +// Name of the cookie default content setting pref. +const PREF_NAME = 'generated.cookie_default_content_setting'; + suite('SiteDataTest', function() { let page: SettingsSiteDataElement; let settingsPrefs: SettingsPrefsElement; @@ -39,11 +42,44 @@ page.remove(); }); + test('DefaultSettingChangesUpdatePref', function() { + // Default is 'allow'. + assertEquals(page.getPref(PREF_NAME + '.value'), ContentSetting.ALLOW); + + page.$.defaultSessionOnly.click(); + assertEquals( + page.getPref(PREF_NAME + '.value'), ContentSetting.SESSION_ONLY); + + page.$.defaultBlock.click(); + assertEquals(page.getPref(PREF_NAME + '.value'), ContentSetting.BLOCK); + + page.$.defaultAllow.click(); + assertEquals(page.getPref(PREF_NAME + '.value'), ContentSetting.ALLOW); + }); + + test('PrefChangesUpdateDefaultSetting', function() { + // Default is 'allow'. + assertEquals(page.$.defaultGroup.selected, ContentSetting.ALLOW); + + page.set('prefs.' + PREF_NAME + '.value', ContentSetting.SESSION_ONLY); + flush(); + assertEquals(page.$.defaultGroup.selected, ContentSetting.SESSION_ONLY); + + page.set('prefs.' + PREF_NAME + '.value', ContentSetting.BLOCK); + flush(); + assertEquals(page.$.defaultGroup.selected, ContentSetting.BLOCK); + + page.set('prefs.' + PREF_NAME + '.value', ContentSetting.ALLOW); + flush(); + assertEquals(page.$.defaultGroup.selected, ContentSetting.ALLOW); + }); + test('ExceptionListsReadOnly', function() { // Check all exception lists are read only when the preference // reports as managed. - page.set('prefs.generated.cookie_default_content_setting', { + page.set('prefs.' + PREF_NAME, { value: ContentSetting.ALLOW, + type: chrome.settingsPrivate.PrefType.STRING, enforcement: chrome.settingsPrivate.Enforcement.ENFORCED, }); let exceptionLists = page.shadowRoot!.querySelectorAll('site-list'); @@ -54,8 +90,9 @@ // Return preference to unmanaged state and check all exception lists // are no longer read only. - page.set('prefs.generated.cookie_default_content_setting', { + page.set('prefs.' + PREF_NAME, { value: ContentSetting.ALLOW, + type: chrome.settingsPrivate.PrefType.STRING, }); exceptionLists = page.shadowRoot!.querySelectorAll('site-list'); assertEquals(exceptionLists.length, 3);
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts index 94129b47..7f8c2d5 100644 --- a/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts +++ b/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts
@@ -62,19 +62,25 @@ test('themes buttons create events', async () => { // Check that clicking the back button produces a back-click event. - let eventPromise = eventToPromise('back-click', themesElement); + const eventPromise = eventToPromise('back-click', themesElement); themesElement.$.backButton.click(); - let event = await eventPromise; + const event = await eventPromise; assertTrue(!!event); + }); + + test('set theme and send event on theme click', async () => { + await setCollection('test', 2); // Check that clicking a theme produces a theme-select event. - await setCollection('test', 2); - eventPromise = eventToPromise('theme-select', themesElement); + const eventPromise = eventToPromise('theme-select', themesElement); const theme = themesElement.shadowRoot!.querySelector('.theme')! as HTMLButtonElement; theme.click(); - event = await eventPromise; + const event = await eventPromise; assertTrue(!!event); + + // Check that setBackgroundImage was called on click. + assertEquals(1, handler.getCallCount('setBackgroundImage')); }); test('get collection images when collection changes', async () => {
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index ffc8dd7..7ba293a 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -15277.0.0 \ No newline at end of file +15288.0.0 \ No newline at end of file
diff --git a/chromeos/ash/components/network/metrics/cellular_network_metrics_logger.cc b/chromeos/ash/components/network/metrics/cellular_network_metrics_logger.cc index 81fef7a..50c7193 100644 --- a/chromeos/ash/components/network/metrics/cellular_network_metrics_logger.cc +++ b/chromeos/ash/components/network/metrics/cellular_network_metrics_logger.cc
@@ -101,6 +101,52 @@ apn_types_enum.value()); } +// static +void CellularNetworkMetricsLogger::LogModifyCustomApnResult( + bool success, + std::vector<chromeos::network_config::mojom::ApnType> old_apn_types, + absl::optional<chromeos::network_config::mojom::ApnState> apn_state, + absl::optional<chromeos::network_config::mojom::ApnState> old_apn_state) { + using ApnState = chromeos::network_config::mojom::ApnState; + base::UmaHistogramBoolean(kModifyCustomApnResultHistogram, success); + + bool has_apn_state = old_apn_state.has_value() && apn_state.has_value(); + bool was_apn_disabled = has_apn_state && + old_apn_state == ApnState::kEnabled && + apn_state == ApnState::kDisabled; + bool was_apn_enabled = has_apn_state && + old_apn_state == ApnState::kDisabled && + apn_state == ApnState::kEnabled; + + if (was_apn_enabled) { + base::UmaHistogramBoolean(kEnableCustomApnResultHistogram, success); + } else if (was_apn_disabled) { + base::UmaHistogramBoolean(kDisableCustomApnResultHistogram, success); + } + + // Only emit APN property metrics if the APN was successfully modified. + if (!success) { + return; + } + + absl::optional<CellularNetworkMetricsLogger::ApnTypes> apn_types_enum = + GetApnTypes(old_apn_types); + if (!apn_types_enum.has_value()) { + NET_LOG(DEBUG) << "ApnTypes not logged for APN because it " + << "doesn't have any APN types."; + return; + } + base::UmaHistogramEnumeration(kModifyCustomApnApnTypesHistogram, + apn_types_enum.value()); + if (was_apn_enabled) { + base::UmaHistogramEnumeration(kEnableCustomApnApnTypesHistogram, + apn_types_enum.value()); + } else if (was_apn_disabled) { + base::UmaHistogramEnumeration(kDisableCustomApnApnTypesHistogram, + apn_types_enum.value()); + } +} + void CellularNetworkMetricsLogger::OnConnectionResult( const std::string& guid, const absl::optional<std::string>& shill_error) {
diff --git a/chromeos/ash/components/network/metrics/cellular_network_metrics_logger.h b/chromeos/ash/components/network/metrics/cellular_network_metrics_logger.h index 0d6dc18..3235e91d 100644 --- a/chromeos/ash/components/network/metrics/cellular_network_metrics_logger.h +++ b/chromeos/ash/components/network/metrics/cellular_network_metrics_logger.h
@@ -41,6 +41,18 @@ "Network.Ash.Cellular.Apn.RemoveCustomApn.Result"; static constexpr char kRemoveCustomApnApnTypesHistogram[] = "Network.Ash.Cellular.Apn.RemoveCustomApn.ApnTypes"; + static constexpr char kModifyCustomApnResultHistogram[] = + "Network.Ash.Cellular.Apn.ModifyCustomApn.Result"; + static constexpr char kModifyCustomApnApnTypesHistogram[] = + "Network.Ash.Cellular.Apn.ModifyCustomApn.ApnTypes"; + static constexpr char kEnableCustomApnResultHistogram[] = + "Network.Ash.Cellular.Apn.EnableCustomApn.Result"; + static constexpr char kEnableCustomApnApnTypesHistogram[] = + "Network.Ash.Cellular.Apn.EnableCustomApn.ApnTypes"; + static constexpr char kDisableCustomApnResultHistogram[] = + "Network.Ash.Cellular.Apn.DisableCustomApn.Result"; + static constexpr char kDisableCustomApnApnTypesHistogram[] = + "Network.Ash.Cellular.Apn.DisableCustomApn.ApnTypes"; CellularNetworkMetricsLogger( NetworkStateHandler* network_state_handler, @@ -58,6 +70,11 @@ static void LogRemoveCustomApnResult( bool success, std::vector<chromeos::network_config::mojom::ApnType> apn_types); + static void LogModifyCustomApnResult( + bool success, + std::vector<chromeos::network_config::mojom::ApnType> old_apn_types, + absl::optional<chromeos::network_config::mojom::ApnState> apn_state, + absl::optional<chromeos::network_config::mojom::ApnState> old_apn_state); private: // ConnectionInfoMetricsLogger::Observer:
diff --git a/chromeos/services/network_config/cros_network_config.cc b/chromeos/services/network_config/cros_network_config.cc index d72ad94..1d10533 100644 --- a/chromeos/services/network_config/cros_network_config.cc +++ b/chromeos/services/network_config/cros_network_config.cc
@@ -3758,6 +3758,9 @@ if (!network || network->profile_path().empty()) { NET_LOG(ERROR) << "ModifyCustomApn: Called with unconfigured network: " << network_guid << "."; + ash::CellularNetworkMetricsLogger::LogModifyCustomApnResult( + /*success=*/false, /*old_apn_types=*/{}, /*apn_state=*/absl::nullopt, + /*old_apn_state=*/absl::nullopt); return; } @@ -3765,6 +3768,9 @@ NET_LOG(ERROR) << "ModifyCustomApn: Called with an APN without ID for network: " << network_guid << '.'; + ash::CellularNetworkMetricsLogger::LogModifyCustomApnResult( + /*success=*/false, /*old_apn_types=*/{}, /*apn_state=*/absl::nullopt, + /*old_apn_state=*/absl::nullopt); return; } @@ -3777,17 +3783,28 @@ if (!old_custom_apns || old_custom_apns->empty()) { NET_LOG(ERROR) << "ModifyCustomApn: Called for network: " << network_guid << " that does not have any user APNs."; + ash::CellularNetworkMetricsLogger::LogModifyCustomApnResult( + /*success=*/false, /*old_apn_types=*/{}, /*apn_state=*/absl::nullopt, + /*old_apn_state=*/absl::nullopt); return; } base::Value::List new_custom_apns; + std::vector<mojom::ApnType> modified_apn_old_apn_types; + mojom::ApnState modified_apn_old_apn_state; + bool was_value_replaced = false; for (const base::Value& old_apn : *old_custom_apns) { const std::string* old_apn_id = old_apn.GetDict().FindString(::onc::cellular_apn::kId); DCHECK(old_apn_id); + if (*apn->id == *old_apn_id) { new_custom_apns.Append(MojoApnToOnc(*apn)); + modified_apn_old_apn_types = OncApnTypesToMojo( + GetRequiredStringList(&old_apn, ::onc::cellular_apn::kApnTypes)); + modified_apn_old_apn_state = OncApnStateTypeToMojo( + old_apn.GetDict().FindString(::onc::cellular_apn::kState)); was_value_replaced = true; } else { new_custom_apns.Append(old_apn.Clone()); @@ -3798,6 +3815,9 @@ NET_LOG(ERROR) << "ModifyCustomApn: Called for network: " << network_guid << " that does have an user APNs with id: " << *apn->id << '.'; + ash::CellularNetworkMetricsLogger::LogModifyCustomApnResult( + /*success=*/false, /*old_apn_types=*/{}, /*apn_state=*/absl::nullopt, + /*old_apn_state=*/absl::nullopt); return; } NET_LOG(USER) << "ModifyCustomApn: Setting user APNs for: " << network_guid @@ -3808,7 +3828,9 @@ SetPropertiesInternal( network_guid, *network, UserApnListToOnc(network_guid, &new_custom_apns), base::BindOnce( - [](const std::string& guid, bool success, + [](const std::string& guid, std::vector<mojom::ApnType> old_apn_types, + const mojom::ApnState apn_state, + const mojom::ApnState old_apn_state, bool success, const std::string& message) { if (!success) { NET_LOG(ERROR) @@ -3816,8 +3838,13 @@ "list in Shill for network: " << guid << ": [" << message << ']'; } + // TODO(b/162365553) Add test coverage for the case when there is a + // failure from shill. + ash::CellularNetworkMetricsLogger::LogModifyCustomApnResult( + success, old_apn_types, apn_state, old_apn_state); }, - network_guid)); + network_guid, std::move(modified_apn_old_apn_types), apn->state, + modified_apn_old_apn_state)); } // static
diff --git a/chromeos/services/network_config/cros_network_config_unittest.cc b/chromeos/services/network_config/cros_network_config_unittest.cc index e220aed..51476ab 100644 --- a/chromeos/services/network_config/cros_network_config_unittest.cc +++ b/chromeos/services/network_config/cros_network_config_unittest.cc
@@ -966,6 +966,66 @@ apn_types, apn_types_count); } + void AssertModifyCustomApnResultBucketCount(size_t num_success, + size_t num_failure) { + histogram_tester_.ExpectBucketCount( + ash::CellularNetworkMetricsLogger::kModifyCustomApnResultHistogram, + true, num_success); + histogram_tester_.ExpectBucketCount( + ash::CellularNetworkMetricsLogger::kModifyCustomApnResultHistogram, + false, num_failure); + histogram_tester_.ExpectTotalCount( + ash::CellularNetworkMetricsLogger::kModifyCustomApnApnTypesHistogram, + num_success); + } + + void AssertModifyCustomApnPropertiesBucketCount(ApnTypes apn_types, + size_t apn_types_count) { + histogram_tester_.ExpectBucketCount( + ash::CellularNetworkMetricsLogger::kModifyCustomApnApnTypesHistogram, + apn_types, apn_types_count); + } + + void AssertEnableCustomApnResultBucketCount(size_t num_success, + size_t num_failure) { + histogram_tester_.ExpectBucketCount( + ash::CellularNetworkMetricsLogger::kEnableCustomApnResultHistogram, + true, num_success); + histogram_tester_.ExpectBucketCount( + ash::CellularNetworkMetricsLogger::kEnableCustomApnResultHistogram, + false, num_failure); + histogram_tester_.ExpectTotalCount( + ash::CellularNetworkMetricsLogger::kEnableCustomApnApnTypesHistogram, + num_success); + } + + void AssertEnableCustomApnPropertiesBucketCount(ApnTypes apn_types, + size_t apn_types_count) { + histogram_tester_.ExpectBucketCount( + ash::CellularNetworkMetricsLogger::kEnableCustomApnApnTypesHistogram, + apn_types, apn_types_count); + } + + void AssertDisableCustomApnResultBucketCount(size_t num_success, + size_t num_failure) { + histogram_tester_.ExpectBucketCount( + ash::CellularNetworkMetricsLogger::kDisableCustomApnResultHistogram, + true, num_success); + histogram_tester_.ExpectBucketCount( + ash::CellularNetworkMetricsLogger::kDisableCustomApnResultHistogram, + false, num_failure); + histogram_tester_.ExpectTotalCount( + ash::CellularNetworkMetricsLogger::kDisableCustomApnApnTypesHistogram, + num_success); + } + + void AssertDisableCustomApnPropertiesBucketCount(ApnTypes apn_types, + size_t apn_types_count) { + histogram_tester_.ExpectBucketCount( + ash::CellularNetworkMetricsLogger::kDisableCustomApnApnTypesHistogram, + apn_types, apn_types_count); + } + NetworkHandlerTestHelper* helper() { return helper_.get(); } CrosNetworkConfigTestObserver* observer() { return observer_.get(); } CrosNetworkConfig* cros_network_config() { @@ -2086,12 +2146,19 @@ mojom::ApnType::kAttach}; test_apn1.onc_apn_types = {::onc::cellular_apn::kApnTypeDefault, ::onc::cellular_apn::kApnTypeAttach}; + test_apn1.mojo_state = mojom::ApnState::kEnabled; + test_apn1.onc_state = ::onc::cellular_apn::kStateEnabled; + test_apn1.id = "apn_id_1"; ModifyCustomApn(kCellularGuid, test_apn1.AsMojoApn()); EXPECT_EQ(expected_network_config_calls, network_config_observer.GetOnConfigurationModifiedCallCount()); ASSERT_FALSE(network_metadata_store()->GetCustomApnList(kCellularGuid)); - + AssertModifyCustomApnResultBucketCount(/*num_success=*/0, /*num_failure=*/1); + AssertDisableCustomApnResultBucketCount(/*num_success=*/0, + /*num_failure=*/0); + AssertEnableCustomApnResultBucketCount(/*num_success=*/0, + /*num_failure=*/0); // Try to replace an APN when the custom APN list is empty, it should do // nothing network_metadata_store()->SetCustomApnList(kCellularGuid, @@ -2100,6 +2167,11 @@ EXPECT_EQ(expected_network_config_calls, network_config_observer.GetOnConfigurationModifiedCallCount()); EXPECT_TRUE(UserApnsInNetworkMetadataStoreMatch(kCellularGuid, {})); + AssertModifyCustomApnResultBucketCount(/*num_success=*/0, /*num_failure=*/2); + AssertDisableCustomApnResultBucketCount(/*num_success=*/0, + /*num_failure=*/0); + AssertEnableCustomApnResultBucketCount(/*num_success=*/0, + /*num_failure=*/0); TestApnData test_apn2; test_apn2.access_point_name = kCellularTestApn2; @@ -2111,6 +2183,8 @@ mojom::ApnType::kAttach}; test_apn2.onc_apn_types = {::onc::cellular_apn::kApnTypeDefault, ::onc::cellular_apn::kApnTypeAttach}; + test_apn2.mojo_state = mojom::ApnState::kEnabled; + test_apn2.onc_state = ::onc::cellular_apn::kStateEnabled; // Add two custom APNs using the official API { @@ -2127,9 +2201,8 @@ network_metadata_store()->GetCustomApnList(kCellularGuid); ASSERT_TRUE(custom_apns); ASSERT_EQ(2u, custom_apns->size()); - const std::string* first_apn_id = - custom_apns->front().GetDict().FindString(::onc::cellular_apn::kId); - ASSERT_TRUE(first_apn_id); + const std::string first_apn_id = + *custom_apns->front().GetDict().FindString(::onc::cellular_apn::kId); TestApnData test_apn3; test_apn3.access_point_name = kCellularTestApn3; @@ -2139,6 +2212,8 @@ test_apn3.attach = kCellularTestApnAttach3; test_apn3.mojo_apn_types = {mojom::ApnType::kAttach}; test_apn3.onc_apn_types = {::onc::cellular_apn::kApnTypeAttach}; + test_apn3.mojo_state = mojom::ApnState::kEnabled; + test_apn3.onc_state = ::onc::cellular_apn::kStateEnabled; // Verify that ModifyCustomApn does nothing if the input APN does not have an // ID. @@ -2153,8 +2228,14 @@ network_config_observer)); EXPECT_TRUE(UserApnsInManagedPropertiesMatch(kCellularGuid, expected_apns)); } - - test_apn3.id = *first_apn_id; + AssertModifyCustomApnResultBucketCount(/*num_success=*/0, + /*num_failure=*/3); + AssertDisableCustomApnResultBucketCount(/*num_success=*/0, + /*num_failure=*/0); + AssertEnableCustomApnResultBucketCount(/*num_success=*/0, + /*num_failure=*/0); + // Verify that ModifyCustomApn replaces the first custom APN + test_apn3.id = first_apn_id; ModifyCustomApn(kCellularGuid, test_apn3.AsMojoApn()); EXPECT_EQ(++expected_network_config_calls, network_config_observer.GetOnConfigurationModifiedCallCount()); @@ -2165,6 +2246,17 @@ EXPECT_TRUE(UserApnsInCellularConfigMatch(kCellularGuid, expected_apns, network_config_observer)); EXPECT_TRUE(UserApnsInManagedPropertiesMatch(kCellularGuid, expected_apns)); + + AssertModifyCustomApnResultBucketCount(/*num_success=*/1, + /*num_failure=*/3); + // Note: The old APN types should be logged + AssertModifyCustomApnPropertiesBucketCount(ApnTypes::kDefaultAndAttach, + /*apn_types_count=*/1); + // Enable/Disable metrics are not logged if the ApnState doesn't change. + AssertDisableCustomApnResultBucketCount(/*num_success=*/0, + /*num_failure=*/0); + AssertEnableCustomApnResultBucketCount(/*num_success=*/0, + /*num_failure=*/0); } // Try to update an ID not found in the list, API should do nothing @@ -2180,6 +2272,109 @@ network_config_observer)); EXPECT_TRUE(UserApnsInManagedPropertiesMatch(kCellularGuid, expected_apns)); } + AssertModifyCustomApnResultBucketCount(/*num_success=*/1, + /*num_failure=*/4); + AssertModifyCustomApnPropertiesBucketCount(ApnTypes::kDefaultAndAttach, + /*apn_types_count=*/1); + + // Verify that disabling a custom APN changes its ApnState to disabled and + // logs metrics + test_apn3.id = first_apn_id; + test_apn3.mojo_state = mojom::ApnState::kDisabled; + test_apn3.onc_state = ::onc::cellular_apn::kStateDisabled; + ModifyCustomApn(kCellularGuid, test_apn3.AsMojoApn()); + EXPECT_EQ(++expected_network_config_calls, + network_config_observer.GetOnConfigurationModifiedCallCount()); + { + std::vector<TestApnData*> expected_apns({&test_apn3, &test_apn1}); + EXPECT_TRUE( + UserApnsInNetworkMetadataStoreMatch(kCellularGuid, expected_apns)); + EXPECT_TRUE(UserApnsInCellularConfigMatch(kCellularGuid, expected_apns, + network_config_observer)); + EXPECT_TRUE(UserApnsInManagedPropertiesMatch(kCellularGuid, expected_apns)); + } + AssertModifyCustomApnResultBucketCount(/*num_success=*/2, + /*num_failure=*/4); + AssertModifyCustomApnPropertiesBucketCount(ApnTypes::kAttach, + /*apn_types_count=*/1); + AssertModifyCustomApnPropertiesBucketCount(ApnTypes::kDefaultAndAttach, + /*apn_types_count=*/1); + AssertDisableCustomApnResultBucketCount(/*num_success=*/1, + /*num_failure=*/0); + AssertDisableCustomApnPropertiesBucketCount(ApnTypes::kAttach, + /*apn_types_count=*/1); + AssertEnableCustomApnResultBucketCount(/*num_success=*/0, + /*num_failure=*/0); + AssertEnableCustomApnPropertiesBucketCount(ApnTypes::kAttach, + /*apn_types_count=*/0); + + // Verify that enabling a custom APN changes its ApnState to enabled and + // logs metrics + test_apn3.id = first_apn_id; + test_apn3.mojo_state = mojom::ApnState::kEnabled; + test_apn3.onc_state = ::onc::cellular_apn::kStateEnabled; + test_apn3.mojo_apn_types = {mojom::ApnType::kDefault}; + test_apn3.onc_apn_types = {::onc::cellular_apn::kApnTypeDefault}; + ModifyCustomApn(kCellularGuid, test_apn3.AsMojoApn()); + EXPECT_EQ(++expected_network_config_calls, + network_config_observer.GetOnConfigurationModifiedCallCount()); + { + std::vector<TestApnData*> expected_apns({&test_apn3, &test_apn1}); + EXPECT_TRUE( + UserApnsInNetworkMetadataStoreMatch(kCellularGuid, expected_apns)); + EXPECT_TRUE(UserApnsInCellularConfigMatch(kCellularGuid, expected_apns, + network_config_observer)); + EXPECT_TRUE(UserApnsInManagedPropertiesMatch(kCellularGuid, expected_apns)); + } + AssertModifyCustomApnResultBucketCount(/*num_success=*/3, + /*num_failure=*/4); + AssertModifyCustomApnPropertiesBucketCount(ApnTypes::kAttach, + /*apn_types_count=*/2); + AssertModifyCustomApnPropertiesBucketCount(ApnTypes::kDefaultAndAttach, + /*apn_types_count=*/1); + AssertModifyCustomApnPropertiesBucketCount(ApnTypes::kDefault, + /*apn_types_count=*/0); + AssertEnableCustomApnResultBucketCount(/*num_success=*/1, + /*num_failure=*/0); + AssertEnableCustomApnPropertiesBucketCount(ApnTypes::kAttach, + /*apn_types_count=*/1); + AssertDisableCustomApnResultBucketCount(/*num_success=*/1, + /*num_failure=*/0); + AssertDisableCustomApnPropertiesBucketCount(ApnTypes::kAttach, + /*apn_types_count=*/1); + + // Verify that changing the APN type logs an event when changing from default + // APN type to a different type + test_apn3.id = first_apn_id; + test_apn3.mojo_apn_types = {mojom::ApnType::kAttach}; + test_apn3.onc_apn_types = {::onc::cellular_apn::kApnTypeAttach}; + test_apn3.mojo_state = mojom::ApnState::kDisabled; + test_apn3.onc_state = ::onc::cellular_apn::kStateDisabled; + ModifyCustomApn(kCellularGuid, test_apn3.AsMojoApn()); + EXPECT_EQ(++expected_network_config_calls, + network_config_observer.GetOnConfigurationModifiedCallCount()); + { + std::vector<TestApnData*> expected_apns({&test_apn3, &test_apn1}); + EXPECT_TRUE( + UserApnsInNetworkMetadataStoreMatch(kCellularGuid, expected_apns)); + EXPECT_TRUE(UserApnsInCellularConfigMatch(kCellularGuid, expected_apns, + network_config_observer)); + EXPECT_TRUE(UserApnsInManagedPropertiesMatch(kCellularGuid, expected_apns)); + } + AssertModifyCustomApnResultBucketCount(/*num_success=*/4, + /*num_failure=*/4); + AssertModifyCustomApnPropertiesBucketCount(ApnTypes::kDefault, + /*apn_types_count=*/1); + AssertModifyCustomApnPropertiesBucketCount(ApnTypes::kAttach, + /*apn_types_count=*/2); + AssertModifyCustomApnPropertiesBucketCount(ApnTypes::kDefaultAndAttach, + /*apn_types_count=*/1); + AssertDisableCustomApnResultBucketCount(/*num_success=*/2, + /*num_failure=*/0); + AssertDisableCustomApnPropertiesBucketCount(ApnTypes::kAttach, + /*apn_types_count=*/1); + AssertDisableCustomApnPropertiesBucketCount(ApnTypes::kDefault, + /*apn_types_count=*/1); } TEST_F(CrosNetworkConfigTest, ConnectedAPN_ApnRevampEnabled) {
diff --git a/chromeos/services/network_config/test_apn_data.cc b/chromeos/services/network_config/test_apn_data.cc index 5245d38d..825ddfd 100644 --- a/chromeos/services/network_config/test_apn_data.cc +++ b/chromeos/services/network_config/test_apn_data.cc
@@ -7,6 +7,7 @@ #include "ash/constants/ash_features.h" #include "chromeos/ash/components/network/policy_util.h" #include "components/onc/onc_constants.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/cros_system_api/dbus/shill/dbus-constants.h" namespace chromeos::network_config { @@ -75,10 +76,11 @@ apn->password = password; apn->attach = attach; if (ash::features::IsApnRevampEnabled()) { - apn->id = id; + apn->id = id.empty() ? absl::nullopt : absl::optional<std::string>(id); apn->authentication_type = mojo_authentication_type; apn->ip_type = mojo_ip_type; apn->apn_types = mojo_apn_types; + apn->state = mojo_state; } return apn; }
diff --git a/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.cc b/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.cc index 465e184..30a2a366 100644 --- a/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.cc +++ b/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.cc
@@ -149,27 +149,6 @@ return frame_->widget_delegate()->ShouldShowCloseButton(); case views::CAPTION_BUTTON_ICON_CUSTOM: return true; - case views::CAPTION_BUTTON_ICON_FLOAT: { - if (!chromeos::wm::features::IsFloatWindowEnabled() || - !frame_->IsNativeWidgetInitialized()) { - return false; - } - // In tablet mode, only show the float/unfloat button if the window is - // floated. - if (chromeos::TabletState::Get()->InTabletMode()) { - return frame_->GetNativeWindow()->GetProperty(kWindowStateTypeKey) == - WindowStateType::kFloated; - } - // In clamshell mode, its harder to differentiate a non floated window - // with a floated window sometimes. Keep the pin button around for - // floatable windows if the developer flag is present. This is temporary - // until the float feature is launched, so instead of modifying build - // dependencies so lacros will depend on ash/constants, we use the - // string directly. - return base::CommandLine::ForCurrentProcess()->HasSwitch( - "ash-dev-shortcuts") && - chromeos::wm::CanFloatWindow(frame_->GetNativeWindow()); - } // No back or menu button by default. case views::CAPTION_BUTTON_ICON_BACK: case views::CAPTION_BUTTON_ICON_MENU: @@ -232,16 +211,6 @@ l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MINIMIZE)); AddChildView(minimize_button_.get()); - if (chromeos::wm::features::IsFloatWindowEnabled()) { - float_button_ = AddChildView(std::make_unique<views::FrameCaptionButton>( - base::BindRepeating( - &FrameCaptionButtonContainerView::FloatButtonPressed, - base::Unretained(this)), - views::CAPTION_BUTTON_ICON_FLOAT, HTMENU)); - float_button_->SetTooltipText( - l10n_util::GetStringUTF16(IDS_MULTITASK_MENU_FLOAT_BUTTON_NAME)); - } - size_button_ = new FrameSizeButton( base::BindRepeating(&FrameCaptionButtonContainerView::SizeButtonPressed, base::Unretained(this)), @@ -258,22 +227,13 @@ l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE)); AddChildView(close_button_.get()); - SetButtonImage(views::CAPTION_BUTTON_ICON_FLOAT, chromeos::kFloatButtonIcon); SetButtonImage(views::CAPTION_BUTTON_ICON_MENU, chromeos::kFloatWindowIcon); SetButtonImage(views::CAPTION_BUTTON_ICON_MINIMIZE, views::kWindowControlMinimizeIcon); SetButtonImage(views::CAPTION_BUTTON_ICON_CLOSE, views::kWindowControlCloseIcon); - // The float button relies on minimum size to know if it can be floated, which - // can only be checked after the widget has been initialized. - if (frame->IsNativeWidgetInitialized()) { - UpdateCaptionButtonState(/*animate=*/false); - } else { - frame->widget_delegate()->RegisterWidgetInitializedCallback(base::BindOnce( - &FrameCaptionButtonContainerView::UpdateCaptionButtonState, - base::Unretained(this), /*animate=*/false)); - } + UpdateCaptionButtonState(/*animate=*/false); } FrameCaptionButtonContainerView::~FrameCaptionButtonContainerView() = default; @@ -285,8 +245,6 @@ void FrameCaptionButtonContainerView::SetPaintAsActive(bool paint_as_active) { if (custom_button_) custom_button_->SetPaintAsActive(paint_as_active); - if (float_button_) - float_button_->SetPaintAsActive(paint_as_active); menu_button_->SetPaintAsActive(paint_as_active); minimize_button_->SetPaintAsActive(paint_as_active); size_button_->SetPaintAsActive(paint_as_active); @@ -298,13 +256,13 @@ views::CaptionButtonIcon icon, const gfx::VectorIcon& icon_definition) { button_icon_map_[icon] = &icon_definition; - views::FrameCaptionButton* buttons[] = {float_button_, menu_button_, - minimize_button_, size_button_, - close_button_}; - for (size_t i = 0; i < std::size(buttons); ++i) { - if (buttons[i] && buttons[i]->GetIcon() == icon) - buttons[i]->SetImage(icon, views::FrameCaptionButton::Animate::kNo, - icon_definition); + views::FrameCaptionButton* buttons[] = {menu_button_, minimize_button_, + size_button_, close_button_}; + for (views::FrameCaptionButton* button : buttons) { + if (button && button->GetIcon() == icon) { + button->SetImage(icon, views::FrameCaptionButton::Animate::kNo, + icon_definition); + } } } @@ -312,8 +270,6 @@ SkColor background_color) { if (custom_button_) custom_button_->SetBackgroundColor(background_color); - if (float_button_) - float_button_->SetBackgroundColor(background_color); menu_button_->SetBackgroundColor(background_color); minimize_button_->SetBackgroundColor(background_color); size_button_->SetBackgroundColor(background_color); @@ -381,12 +337,6 @@ custom_button_->SetVisible( model_->IsVisible(views::CAPTION_BUTTON_ICON_CUSTOM)); } - if (float_button_) { - float_button_->SetEnabled( - model_->IsEnabled(views::CAPTION_BUTTON_ICON_FLOAT)); - float_button_->SetVisible( - model_->IsVisible(views::CAPTION_BUTTON_ICON_FLOAT)); - } size_button_->SetEnabled( (model_->IsEnabled(views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE) || model_->InZoomMode())); @@ -403,14 +353,11 @@ void FrameCaptionButtonContainerView::UpdateButtonsImageAndTooltip() { UpdateSizeButton(); UpdateSnapButtons(); - UpdateFloatButton(); } void FrameCaptionButtonContainerView::SetButtonSize(const gfx::Size& size) { if (custom_button_) custom_button_->SetPreferredSize(size); - if (float_button_) - float_button_->SetPreferredSize(size); menu_button_->SetPreferredSize(size); minimize_button_->SetPreferredSize(size); size_button_->SetPreferredSize(size); @@ -583,26 +530,6 @@ : chromeos::kWindowControlBottomSnappedIcon); } -void FrameCaptionButtonContainerView::UpdateFloatButton() { - if (!float_button_) - return; - - const bool floated = frame_->GetNativeWindow()->GetProperty( - kWindowStateTypeKey) == WindowStateType::kFloated; - SetButtonImage( - views::CAPTION_BUTTON_ICON_FLOAT, - floated ? chromeos::kUnfloatButtonIcon : chromeos::kFloatButtonIcon); - float_button_->SetTooltipText(l10n_util::GetStringUTF16( - floated ? IDS_MULTITASK_MENU_EXIT_FLOAT_BUTTON_NAME - : IDS_MULTITASK_MENU_FLOAT_BUTTON_NAME)); - - // Float button also needs to update its visibility when float state changes. - float_button_->SetEnabled( - model_->IsEnabled(views::CAPTION_BUTTON_ICON_FLOAT)); - float_button_->SetVisible( - model_->IsVisible(views::CAPTION_BUTTON_ICON_FLOAT)); -} - void FrameCaptionButtonContainerView::MinimizeButtonPressed() { // Abort any animations of the button icons. SetButtonsToNormal(Animate::kNo); @@ -663,15 +590,6 @@ // TODO(oshima): Add metrics } -void FrameCaptionButtonContainerView::FloatButtonPressed() { - // Abort any animations of the button icons. - SetButtonsToNormal(Animate::kNo); - DCHECK(chromeos::wm::features::IsFloatWindowEnabled()); - - // Toggle float current window. - FloatControllerBase::Get()->ToggleFloat(GetWidget()->GetNativeWindow()); -} - bool FrameCaptionButtonContainerView::IsMinimizeButtonVisible() const { return minimize_button_->GetVisible(); } @@ -681,8 +599,6 @@ views::CAPTION_BUTTON_ICON_CLOSE, animate); if (custom_button_) custom_button_->SetState(views::Button::STATE_NORMAL); - if (float_button_) - float_button_->SetState(views::Button::STATE_NORMAL); menu_button_->SetState(views::Button::STATE_NORMAL); minimize_button_->SetState(views::Button::STATE_NORMAL); size_button_->SetState(views::Button::STATE_NORMAL); @@ -706,9 +622,9 @@ gfx::Point position(position_in_screen); views::View::ConvertPointFromScreen(this, &position); - views::FrameCaptionButton* buttons[] = {custom_button_, float_button_, - menu_button_, minimize_button_, - size_button_, close_button_}; + views::FrameCaptionButton* buttons[] = {custom_button_, menu_button_, + minimize_button_, size_button_, + close_button_}; int min_squared_distance = INT_MAX; views::FrameCaptionButton* closest_button = nullptr; for (size_t i = 0; i < std::size(buttons); ++i) { @@ -732,11 +648,10 @@ void FrameCaptionButtonContainerView::SetHoveredAndPressedButtons( const views::FrameCaptionButton* to_hover, const views::FrameCaptionButton* to_press) { - views::FrameCaptionButton* buttons[] = {custom_button_, float_button_, - menu_button_, minimize_button_, - size_button_, close_button_}; - for (size_t i = 0; i < std::size(buttons); ++i) { - views::FrameCaptionButton* button = buttons[i]; + views::FrameCaptionButton* buttons[] = {custom_button_, menu_button_, + minimize_button_, size_button_, + close_button_}; + for (views::FrameCaptionButton* button : buttons) { if (!button) continue; views::Button::ButtonState new_state = views::Button::STATE_NORMAL;
diff --git a/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h b/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h index b75ad43..686d48d0 100644 --- a/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h +++ b/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h
@@ -86,11 +86,6 @@ return container_view_->custom_button_; } - views::FrameCaptionButton* float_button() const { - DCHECK(chromeos::wm::features::IsFloatWindowEnabled()); - return container_view_->float_button_; - } - private: raw_ptr<FrameCaptionButtonContainerView> container_view_; }; @@ -128,8 +123,8 @@ // state. A parent view should relayout to reflect the change in states. void UpdateCaptionButtonState(bool animate); - // Updates the image and tooltips of the size, float and snap buttons. These - // can change on state change or display orientation change. + // Updates the image and tooltips of the size and snap buttons. These can + // change on state change or display orientation change. void UpdateButtonsImageAndTooltip(); // Sets the size of the buttons in this container. @@ -169,9 +164,7 @@ // well. void UpdateSizeButton(); void UpdateSnapButtons(); - void UpdateFloatButton(); - void FloatButtonPressed(); void MinimizeButtonPressed(); void SizeButtonPressed(); void CloseButtonPressed(); @@ -198,7 +191,6 @@ // The buttons. In the normal button style, at most one of |minimize_button_| // and |size_button_| is visible. raw_ptr<views::FrameCaptionButton> custom_button_ = nullptr; - raw_ptr<views::FrameCaptionButton> float_button_ = nullptr; raw_ptr<views::FrameCaptionButton> menu_button_ = nullptr; raw_ptr<views::FrameCaptionButton> minimize_button_ = nullptr; raw_ptr<views::FrameCaptionButton> size_button_ = nullptr;
diff --git a/chromeos/ui/frame/caption_buttons/frame_size_button.cc b/chromeos/ui/frame/caption_buttons/frame_size_button.cc index 3a7f3cc..1971c60 100644 --- a/chromeos/ui/frame/caption_buttons/frame_size_button.cc +++ b/chromeos/ui/frame/caption_buttons/frame_size_button.cc
@@ -71,7 +71,6 @@ return GetSnapDirectionForWindow(window, /*left_top=*/true); case views::CAPTION_BUTTON_ICON_RIGHT_BOTTOM_SNAPPED: return GetSnapDirectionForWindow(window, /*left_top=*/false); - case views::CAPTION_BUTTON_ICON_FLOAT: case views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE: case views::CAPTION_BUTTON_ICON_MINIMIZE: case views::CAPTION_BUTTON_ICON_CLOSE:
diff --git a/chromeos/ui/frame/multitask_menu/DIR_METADATA b/chromeos/ui/frame/multitask_menu/DIR_METADATA new file mode 100644 index 0000000..f57ce1e --- /dev/null +++ b/chromeos/ui/frame/multitask_menu/DIR_METADATA
@@ -0,0 +1 @@ +mixins: "//ash/wm/float/COMMON_METADATA" \ No newline at end of file
diff --git a/chromeos/ui/frame/multitask_menu/OWNERS b/chromeos/ui/frame/multitask_menu/OWNERS new file mode 100644 index 0000000..5639e5e --- /dev/null +++ b/chromeos/ui/frame/multitask_menu/OWNERS
@@ -0,0 +1 @@ +file://ash/wm/float/OWNERS
diff --git a/chromeos/ui/vector_icons/BUILD.gn b/chromeos/ui/vector_icons/BUILD.gn index 683ce729..eb62907 100644 --- a/chromeos/ui/vector_icons/BUILD.gn +++ b/chromeos/ui/vector_icons/BUILD.gn
@@ -40,7 +40,6 @@ "filetype_tini.icon", "filetype_video.icon", "filetype_word.icon", - "float_button.icon", "float_window.icon", "keyboard_shortcuts.icon", "notification_assistant.icon",
diff --git a/chromeos/ui/vector_icons/float_button.icon b/chromeos/ui/vector_icons/float_button.icon deleted file mode 100644 index 51d43e1..0000000 --- a/chromeos/ui/vector_icons/float_button.icon +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -CANVAS_DIMENSIONS, 20, -MOVE_TO, 14, 3, -V_LINE_TO, 5, -H_LINE_TO, 13, -V_LINE_TO, 9, -LINE_TO, 15, 11, -V_LINE_TO, 13, -H_LINE_TO, 11, -V_LINE_TO, 18, -LINE_TO, 10, 19, -LINE_TO, 9, 18, -V_LINE_TO, 13, -H_LINE_TO, 5, -V_LINE_TO, 11, -LINE_TO, 7, 9, -V_LINE_TO, 5, -H_LINE_TO, 6, -V_LINE_TO, 3, -H_LINE_TO, 14, -CLOSE, -MOVE_TO, 13, 11, -LINE_TO, 11, 9, -V_LINE_TO, 5, -H_LINE_TO, 9, -V_LINE_TO, 9, -LINE_TO, 7, 11, -H_LINE_TO, 13, -CLOSE
diff --git a/components/exo/client_controlled_shell_surface_unittest.cc b/components/exo/client_controlled_shell_surface_unittest.cc index aea8407..d7b96db 100644 --- a/components/exo/client_controlled_shell_surface_unittest.cc +++ b/components/exo/client_controlled_shell_surface_unittest.cc
@@ -1430,15 +1430,13 @@ views::CAPTION_BUTTON_ICON_CLOSE, views::CAPTION_BUTTON_ICON_BACK, views::CAPTION_BUTTON_ICON_MENU, - views::CAPTION_BUTTON_ICON_FLOAT, }; constexpr uint32_t kAllButtonMask = 1 << views::CAPTION_BUTTON_ICON_MINIMIZE | 1 << views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE | 1 << views::CAPTION_BUTTON_ICON_CLOSE | 1 << views::CAPTION_BUTTON_ICON_BACK | - 1 << views::CAPTION_BUTTON_ICON_MENU | - 1 << views::CAPTION_BUTTON_ICON_FLOAT; + 1 << views::CAPTION_BUTTON_ICON_MENU; ash::NonClientFrameViewAsh* frame_view = static_cast<ash::NonClientFrameViewAsh*>(
diff --git a/components/history_clusters/core/history_clusters_util.cc b/components/history_clusters/core/history_clusters_util.cc index b495c1b..09d02936 100644 --- a/components/history_clusters/core/history_clusters_util.cc +++ b/components/history_clusters/core/history_clusters_util.cc
@@ -7,6 +7,7 @@ #include <algorithm> #include "base/containers/contains.h" +#include "base/containers/cxx20_erase.h" #include "base/i18n/case_conversion.h" #include "base/ranges/algorithm.h" #include "base/strings/string_piece.h" @@ -255,29 +256,23 @@ // For the empty-query state, only show clusters with // `should_show_on_prominent_ui_surfaces` set to true. This restriction is // NOT applied when the user is searching for a specific keyword. - clusters.erase(base::ranges::remove_if( - clusters, - [](const history::Cluster& cluster) { - return !cluster.should_show_on_prominent_ui_surfaces; - }), - clusters.end()); + base::EraseIf(clusters, [](const history::Cluster& cluster) { + return !cluster.should_show_on_prominent_ui_surfaces; + }); } else { - clusters.erase(base::ranges::remove_if( - clusters, - [&](const history::Cluster& cluster) { - // Erase all duplicate single-visit non-prominent - // clusters. - if (!cluster.should_show_on_prominent_ui_surfaces && - cluster.visits.size() == 1) { - auto [unused_iterator, newly_inserted] = - seen_single_visit_cluster_urls->insert( - cluster.visits[0].url_for_deduping); - return !newly_inserted; - } + base::EraseIf(clusters, [&](const history::Cluster& cluster) { + // Erase all duplicate single-visit non-prominent + // clusters. + if (!cluster.should_show_on_prominent_ui_surfaces && + cluster.visits.size() == 1) { + auto [unused_iterator, newly_inserted] = + seen_single_visit_cluster_urls->insert( + cluster.visits[0].url_for_deduping); + return !newly_inserted; + } - return false; - }), - clusters.end()); + return false; + }); } } @@ -297,10 +292,8 @@ } if (GetConfig().drop_hidden_visits) { - cluster.visits.erase( - base::ranges::remove_if( - cluster.visits, [](const auto& visit) { return visit.hidden; }), - cluster.visits.end()); + base::EraseIf(cluster.visits, + [](const auto& visit) { return visit.hidden; }); } } }
diff --git a/components/js_injection/common/interfaces.mojom b/components/js_injection/common/interfaces.mojom index 533d9684..c451e6a 100644 --- a/components/js_injection/common/interfaces.mojom +++ b/components/js_injection/common/interfaces.mojom
@@ -29,11 +29,23 @@ js_injection.mojom.OriginMatcher origin_matcher; }; +// The ArrayBuffer arm of the JsWebMessage union below, which contains the +// ArrayBuffer payload sent between JavaScript and browser. +struct JsWebMessageArrayBufferValue { + mojo_base.mojom.BigBuffer array_buffer_value; + // If is_resizable_by_user_javascript is false, then max_byte_length is + // unused. + // + // TODO(crbug.com/657632): Use a wrapped uint64 or uint64? once supported. + bool is_resizable_by_user_javascript = false; + uint64 max_byte_length = 0; +}; + // JsWebMessage struct contains the message payload sent between // JavaScript and Browser. union JsWebMessage { mojo_base.mojom.String16 string_value; - mojo_base.mojom.BigBuffer array_buffer_value; + JsWebMessageArrayBufferValue array_buffer_value; }; // For JavaScript postMessage() API, implemented by browser.
diff --git a/components/js_injection/common/web_message_mojom_traits.cc b/components/js_injection/common/web_message_mojom_traits.cc index b5d17a1..70a83c8 100644 --- a/components/js_injection/common/web_message_mojom_traits.cc +++ b/components/js_injection/common/web_message_mojom_traits.cc
@@ -16,6 +16,25 @@ namespace mojo { // static +bool StructTraits<js_injection::mojom::JsWebMessageArrayBufferValueDataView, + std::unique_ptr<blink::WebMessageArrayBufferPayload>>:: + Read(js_injection::mojom::JsWebMessageArrayBufferValueDataView r, + std::unique_ptr<blink::WebMessageArrayBufferPayload>* out) { + mojo_base::BigBufferView big_buffer_view; + if (!r.ReadArrayBufferValue(&big_buffer_view)) { + return false; + } + absl::optional<size_t> max_byte_length; + if (r.is_resizable_by_user_javascript()) { + max_byte_length = base::checked_cast<size_t>(r.max_byte_length()); + } + *out = blink::WebMessageArrayBufferPayload::CreateFromBigBuffer( + mojo_base::BigBufferView::ToBigBuffer(std::move(big_buffer_view)), + max_byte_length); + return true; +} + +// static js_injection::mojom::JsWebMessageDataView::Tag UnionTraits< js_injection::mojom::JsWebMessageDataView, blink::WebMessagePayload>::GetTag(const blink::WebMessagePayload& payload) { @@ -42,12 +61,12 @@ return false; out->emplace<std::u16string>(std::move(string_value)); } else if (r.is_array_buffer_value()) { - mojo_base::BigBufferView big_buffer_view; - if (!r.ReadArrayBufferValue(&big_buffer_view)) + std::unique_ptr<blink::WebMessageArrayBufferPayload> array_buffer_value; + if (!r.ReadArrayBufferValue(&array_buffer_value)) { return false; + } out->emplace<std::unique_ptr<blink::WebMessageArrayBufferPayload>>( - blink::WebMessageArrayBufferPayload::CreateFromBigBuffer( - mojo_base::BigBufferView::ToBigBuffer(std::move(big_buffer_view)))); + std::move(array_buffer_value)); } else { return false; }
diff --git a/components/js_injection/common/web_message_mojom_traits.h b/components/js_injection/common/web_message_mojom_traits.h index f5a5a7a..c378a22 100644 --- a/components/js_injection/common/web_message_mojom_traits.h +++ b/components/js_injection/common/web_message_mojom_traits.h
@@ -16,6 +16,33 @@ namespace mojo { template <> +struct StructTraits<js_injection::mojom::JsWebMessageArrayBufferValueDataView, + std::unique_ptr<blink::WebMessageArrayBufferPayload>> { + static mojo_base::BigBuffer array_buffer_value( + const std::unique_ptr<blink::WebMessageArrayBufferPayload>& + array_buffer) { + auto big_buffer = mojo_base::BigBuffer(array_buffer->GetLength()); + array_buffer->CopyInto(big_buffer); + return big_buffer; + } + + static bool is_resizable_by_user_javascript( + const std::unique_ptr<blink::WebMessageArrayBufferPayload>& + array_buffer) { + return array_buffer->GetIsResizableByUserJavaScript(); + } + + static size_t max_byte_length( + const std::unique_ptr<blink::WebMessageArrayBufferPayload>& + array_buffer) { + return array_buffer->GetMaxByteLength(); + } + + static bool Read(js_injection::mojom::JsWebMessageArrayBufferValueDataView r, + std::unique_ptr<blink::WebMessageArrayBufferPayload>* out); +}; + +template <> struct UnionTraits<js_injection::mojom::JsWebMessageDataView, blink::WebMessagePayload> { static const std::u16string& string_value( @@ -23,14 +50,10 @@ return absl::get<std::u16string>(payload); } - static mojo_base::BigBuffer array_buffer_value( - const blink::WebMessagePayload& payload) { - auto& array_buffer = - absl::get<std::unique_ptr<blink::WebMessageArrayBufferPayload>>( - payload); - auto big_buffer = mojo_base::BigBuffer(array_buffer->GetLength()); - array_buffer->CopyInto(big_buffer); - return big_buffer; + static const std::unique_ptr<blink::WebMessageArrayBufferPayload>& + array_buffer_value(const blink::WebMessagePayload& payload) { + return absl::get<std::unique_ptr<blink::WebMessageArrayBufferPayload>>( + payload); } static js_injection::mojom::JsWebMessageDataView::Tag GetTag(
diff --git a/components/keyed_service/ios/browser_state_keyed_service_factory.cc b/components/keyed_service/ios/browser_state_keyed_service_factory.cc index 2ce7095..3b559667 100644 --- a/components/keyed_service/ios/browser_state_keyed_service_factory.cc +++ b/components/keyed_service/ios/browser_state_keyed_service_factory.cc
@@ -24,20 +24,6 @@ KeyedServiceFactory::SetTestingFactory(context, std::move(wrapped_factory)); } -KeyedService* BrowserStateKeyedServiceFactory::SetTestingFactoryAndUse( - web::BrowserState* context, - TestingFactory testing_factory) { - DCHECK(testing_factory); - return KeyedServiceFactory::SetTestingFactoryAndUse( - context, - base::BindRepeating( - [](const TestingFactory& testing_factory, void* context) { - return testing_factory.Run( - static_cast<web::BrowserState*>(context)); - }, - std::move(testing_factory))); -} - BrowserStateKeyedServiceFactory::BrowserStateKeyedServiceFactory( const char* name, BrowserStateDependencyManager* manager)
diff --git a/components/keyed_service/ios/browser_state_keyed_service_factory.h b/components/keyed_service/ios/browser_state_keyed_service_factory.h index baaf7cb..4a6f9ff 100644 --- a/components/keyed_service/ios/browser_state_keyed_service_factory.h +++ b/components/keyed_service/ios/browser_state_keyed_service_factory.h
@@ -46,12 +46,6 @@ void SetTestingFactory(web::BrowserState* context, TestingFactory testing_factory); - // Associates |testing_factory| with |context| and immediately returns the - // created KeyedService. Since the factory will be used immediately, it may - // not be empty. - KeyedService* SetTestingFactoryAndUse(web::BrowserState* context, - TestingFactory testing_factory); - protected: // BrowserStateKeyedServiceFactories must communicate with a // BrowserStateDependencyManager. For all non-test code, write your subclass
diff --git a/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.cc b/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.cc index afd1ccd..fe8123a 100644 --- a/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.cc +++ b/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.cc
@@ -25,21 +25,6 @@ std::move(wrapped_factory)); } -scoped_refptr<RefcountedKeyedService> -RefcountedBrowserStateKeyedServiceFactory::SetTestingFactoryAndUse( - web::BrowserState* context, - TestingFactory testing_factory) { - DCHECK(testing_factory); - return RefcountedKeyedServiceFactory::SetTestingFactoryAndUse( - context, - base::BindRepeating( - [](const TestingFactory& testing_factory, void* context) { - return testing_factory.Run( - static_cast<web::BrowserState*>(context)); - }, - std::move(testing_factory))); -} - RefcountedBrowserStateKeyedServiceFactory:: RefcountedBrowserStateKeyedServiceFactory( const char* name,
diff --git a/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.h b/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.h index dcc7792..3f3bd96 100644 --- a/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.h +++ b/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.h
@@ -48,13 +48,6 @@ void SetTestingFactory(web::BrowserState* context, TestingFactory testing_factory); - // Associates |testing_factory| with |context| and immediately returns the - // created KeyedService. Since the factory will be used immediately, it may - // not be empty. - scoped_refptr<RefcountedKeyedService> SetTestingFactoryAndUse( - web::BrowserState* context, - TestingFactory testing_factory); - protected: // RefcountedBrowserStateKeyedServiceFactories must communicate with a // BrowserStateDependencyManager. For all non-test code, write your subclass
diff --git a/components/lens/BUILD.gn b/components/lens/BUILD.gn index b2fccd7..1fd7aa7 100644 --- a/components/lens/BUILD.gn +++ b/components/lens/BUILD.gn
@@ -11,7 +11,7 @@ header = "buildflags.h" flags = [ "ENABLE_LENS_DESKTOP=$enable_lens_desktop", - "ENABLE_LENS_DESKTOP_SIDE_PANEL=$enable_lens_desktop_side_panel", + "ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES=$enable_lens_desktop_google_branded_features", ] }
diff --git a/components/lens/features.gni b/components/lens/features.gni index 4a9c6ec..7ac60ea9 100644 --- a/components/lens/features.gni +++ b/components/lens/features.gni
@@ -16,6 +16,11 @@ } declare_args() { - # Lens in the side panel is a Chrome specific feature - enable_lens_desktop_side_panel = enable_lens_desktop && is_chrome_branded + # Lens features that are specific to the Google Chrome branded browser. + # Features include: + # - Region Search + # - Side Panel + # - PDF Support + enable_lens_desktop_google_branded_features = + enable_lens_desktop && is_chrome_branded }
diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc index 9fac07da..9c0074c 100644 --- a/components/omnibox/browser/autocomplete_result.cc +++ b/components/omnibox/browser/autocomplete_result.cc
@@ -14,7 +14,6 @@ #include "base/containers/adapters.h" #include "base/containers/contains.h" #include "base/containers/cxx20_erase.h" -#include "base/containers/cxx20_erase_vector.h" #include "base/debug/stack_trace.h" #include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_macros.h" @@ -53,6 +52,20 @@ namespace { +constexpr bool is_android = +#if BUILDFLAG(IS_ANDROID) + true; +#else + false; +#endif + +constexpr bool is_ios = +#if BUILDFLAG(IS_IOS) + true; +#else + false; +#endif + // Rotates |it| to be in the front of |matches|. // |it| must be a valid iterator of |matches| or equal to |matches->end()|. void RotateMatchToFront(ACMatches::iterator it, ACMatches* matches) { @@ -63,17 +76,13 @@ std::rotate(matches->begin(), it, next); } -#if BUILDFLAG(IS_IOS) // Maximum number of pedals to show. // On iOS, the UI for pedals gets too visually cluttered with too many pedals. -constexpr size_t kMaxPedalCount = 1; +constexpr size_t kMaxPedalCount = + is_ios ? 1 : std::numeric_limits<size_t>::max(); // Maximum index of a match in a result for which the pedal should be displayed. -// On iOS, the UI for pedals gets too visually cluttered with too many pedals. -constexpr size_t kMaxPedalMatchIndex = 3; -#else -constexpr size_t kMaxPedalCount = std::numeric_limits<size_t>::max(); -constexpr size_t kMaxPedalMatchIndex = std::numeric_limits<size_t>::max(); -#endif +constexpr size_t kMaxPedalMatchIndex = + is_ios ? 3 : std::numeric_limits<size_t>::max(); enum class DontCopyDoneProviders { kFalse, kTrue, kUnknown }; @@ -84,25 +93,21 @@ // static size_t AutocompleteResult::GetMaxMatches(bool is_zero_suggest) { -#if BUILDFLAG(IS_ANDROID) - constexpr size_t kDefaultMaxAutocompleteMatches = 10; - constexpr size_t kDefaultMaxZeroSuggestMatches = 15; -#elif BUILDFLAG(IS_IOS) - constexpr size_t kDefaultMaxAutocompleteMatches = 6; + constexpr size_t kDefaultMaxAutocompleteMatches = + is_android ? 10 : (is_ios ? 6 : 8); + constexpr size_t kDefaultMaxZeroSuggestMatches = + is_android ? 15 : (is_ios ? 20 : 8); +#if BUILDFLAG(IS_IOS) // By default, iPad has the same max as iPhone. // `kDefaultMaxAutocompleteMatches` defines a hard limit on the number of // autocomplete suggestions on iPad, so if an experiment defines // MaxZeroSuggestMatches to 15, it would be 15 on iPhone and 10 on iPad. constexpr size_t kMaxAutocompleteMatchesOnIPad = 10; - constexpr size_t kDefaultMaxZeroSuggestMatches = 20; // By default, iPad has the same max as iPhone. `kMaxZeroSuggestMatchesOnIPad` // defines a hard limit on the number of ZPS suggestions on iPad, so if an // experiment defines MaxZeroSuggestMatches to 15, it would be 15 on iPhone // and 10 on iPad. constexpr size_t kMaxZeroSuggestMatchesOnIPad = 10; -#else - constexpr size_t kDefaultMaxAutocompleteMatches = 8; - constexpr size_t kDefaultMaxZeroSuggestMatches = 8; #endif static_assert(kMaxAutocompletePositionValue > kDefaultMaxAutocompleteMatches, "kMaxAutocompletePositionValue must be larger than the largest " @@ -150,11 +155,7 @@ // static size_t AutocompleteResult::GetDynamicMaxMatches() { -#if BUILDFLAG(IS_ANDROID) - constexpr const int kDynamicMaxMatchesLimit = 15; -#else - constexpr const int kDynamicMaxMatchesLimit = 10; -#endif + constexpr const int kDynamicMaxMatchesLimit = is_android ? 15 : 10; if (!base::FeatureList::IsEnabled(omnibox::kDynamicMaxAutocomplete)) return AutocompleteResult::GetMaxMatches(); return base::GetFieldTrialParamByFeatureAsInt( @@ -189,13 +190,9 @@ : DontCopyDoneProviders::kFalse; } if (g_dont_copy_done_providers == DontCopyDoneProviders::kTrue) { - old_matches->matches_.erase( - base::ranges::remove_if(*old_matches, - [](const auto& old_match) { - return old_match.provider && - old_match.provider->done(); - }), - old_matches->matches_.end()); + base::EraseIf(old_matches->matches_, [](const auto& old_match) { + return old_match.provider && old_match.provider->done(); + }); } if (old_matches->empty()) @@ -203,14 +200,10 @@ // Exclude specialized suggestion types from being transferred to prevent // user-visible artifacts. - old_matches->matches_.erase( - std::remove_if( - old_matches->begin(), old_matches->end(), - [](const auto& match) { - return match.type == AutocompleteMatchType::TILE_NAVSUGGEST || - match.type == AutocompleteMatchType::TILE_SUGGESTION; - }), - old_matches->matches_.end()); + base::EraseIf(old_matches->matches_, [](const auto& match) { + return match.type == AutocompleteMatchType::TILE_NAVSUGGEST || + match.type == AutocompleteMatchType::TILE_SUGGESTION; + }); if (empty()) { // If we've got no matches we can copy everything from the last result. @@ -300,19 +293,17 @@ for (auto& match : matches_) match.ComputeStrippedDestinationURL(input, template_url_service); -#if !BUILDFLAG(IS_IOS) - DemoteOnDeviceSearchSuggestions(); -#endif // !BUILDFLAG(IS_IOS) + if (!is_ios) + DemoteOnDeviceSearchSuggestions(); const auto& page_classification = input.current_page_classification(); CompareWithDemoteByType<AutocompleteMatch> comparing_object( page_classification); -#if !(BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)) // Because tail suggestions are a "last resort", we cull the tail suggestions // if there are any non-default, non-tail suggestions. - MaybeCullTailSuggestions(&matches_, comparing_object); -#endif + if (!is_android && !is_ios) + MaybeCullTailSuggestions(&matches_, comparing_object); DeduplicateMatches(&matches_); @@ -1254,15 +1245,11 @@ size_t url_count = 0; // Erase URL suggestions past the count of allowed ones, or anything past // maximum. - matches_.erase( - std::remove_if(matches_.begin(), matches_.end(), - [&url_count, max_url_count](const AutocompleteMatch& m) { - if (!AutocompleteMatch::IsSearchType(m.type) && - ++url_count > max_url_count) - return true; - return false; - }), - matches_.end()); + base::EraseIf(matches_, + [&url_count, max_url_count](const AutocompleteMatch& m) { + return !AutocompleteMatch::IsSearchType(m.type) && + ++url_count > max_url_count; + }); } // static
diff --git a/components/omnibox/browser/search_suggestion_parser_unittest.cc b/components/omnibox/browser/search_suggestion_parser_unittest.cc index 6e4d12a..5aae6c5fb 100644 --- a/components/omnibox/browser/search_suggestion_parser_unittest.cc +++ b/components/omnibox/browser/search_suggestion_parser_unittest.cc
@@ -8,6 +8,7 @@ #include "base/json/json_reader.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" +#include "build/build_config.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/test_scheme_classifier.h" #include "testing/gmock/include/gmock/gmock.h" @@ -1661,3 +1662,100 @@ /*is_keyword_result=*/false, &results)); } } + +TEST(SearchSuggestionParserTest, ParseCalculatorSuggestion) { + TestSchemeClassifier scheme_classifier; + AutocompleteInput input(u"1 + 1", metrics::OmniboxEventProto::NTP_REALBOX, + scheme_classifier); + + const std::string json_data = R"([ + "1 + 1", + [ + "1 + 1", + "= 2", + "1 + 1" + ], + ["", "Calculator", ""], + [], + { + "google:clientdata": { + "bpc": false, + "tlw": false + }, + "google:suggestdetail": [ + {}, + {}, + { + "a": "Song", + "dc": "#424242", + "i": "https://encrypted-tbn0.gstatic.com/images?q=song", + "q": "gs_ssp=eJzj4tFP1zcsNjAzMykwKDZg9GI1VNBWMAQAOlEEsA", + "t": "1+1", + "zae": "/g/1s0664p0s" + } + ], + "google:suggestrelevance": [1300, 1252, 1250], + "google:suggestsubtypes": [ + [512, 355], + [], + [512] + ], + "google:suggesttype": [ + "QUERY", + "CALCULATOR", + "ENTITY" + ], + "google:verbatimrelevance": 1300 + } + ])"; + + absl::optional<base::Value> root_val = base::JSONReader::Read(json_data); + ASSERT_TRUE(root_val); + + SearchSuggestionParser::Results results; + ASSERT_TRUE(SearchSuggestionParser::ParseSuggestResults( + *root_val, input, scheme_classifier, /*default_result_relevance=*/400, + /*is_keyword_result=*/false, &results)); + + ASSERT_EQ(3U, results.suggest_results.size()); + + // Most fields for a verbatim suggestion should be empty. + ASSERT_EQ(u"1 + 1", results.suggest_results[0].suggestion()); + ASSERT_EQ(u"", results.suggest_results[0].annotation()); + ASSERT_EQ("", results.suggest_results[0].image_dominant_color()); + ASSERT_EQ("", results.suggest_results[0].image_url().spec()); + ASSERT_EQ("", results.suggest_results[0].additional_query_params()); + ASSERT_EQ(u"1 + 1", results.suggest_results[0].match_contents()); + ASSERT_EQ("", results.suggest_results[0].entity_id()); + + // Calculator suggestions should have specific values for the |suggestion|, + // |match_contents|, and |annotation| fields. +#if !BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_ANDROID) + ASSERT_EQ(u"2", results.suggest_results[1].suggestion()); + ASSERT_EQ(u"2", results.suggest_results[1].annotation()); + ASSERT_EQ("", results.suggest_results[1].image_dominant_color()); + ASSERT_EQ("", results.suggest_results[1].image_url().spec()); + ASSERT_EQ("", results.suggest_results[1].additional_query_params()); + ASSERT_EQ(u"1 + 1", results.suggest_results[1].match_contents()); + ASSERT_EQ("", results.suggest_results[1].entity_id()); +#else + ASSERT_EQ(u"2", results.suggest_results[1].suggestion()); + ASSERT_EQ(u"", results.suggest_results[1].annotation()); + ASSERT_EQ("", results.suggest_results[1].image_dominant_color()); + ASSERT_EQ("", results.suggest_results[1].image_url().spec()); + ASSERT_EQ("", results.suggest_results[1].additional_query_params()); + ASSERT_EQ(u"= 2", results.suggest_results[1].match_contents()); + ASSERT_EQ("", results.suggest_results[1].entity_id()); +#endif + + // Entity data should be correctly sourced as usual. + ASSERT_EQ(u"1 + 1", results.suggest_results[2].suggestion()); + ASSERT_EQ(u"Song", results.suggest_results[2].annotation()); + ASSERT_EQ("#424242", results.suggest_results[2].image_dominant_color()); + ASSERT_EQ("https://encrypted-tbn0.gstatic.com/images?q=song", + results.suggest_results[2].image_url().spec()); + ASSERT_EQ("gs_ssp=eJzj4tFP1zcsNjAzMykwKDZg9GI1VNBWMAQAOlEEsA", + results.suggest_results[2].additional_query_params()); + ASSERT_EQ(u"1+1", results.suggest_results[2].match_contents()); + ASSERT_EQ("/g/1s0664p0s", results.suggest_results[2].entity_id()); +}
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc index 9065e8a..29291a6 100644 --- a/components/password_manager/core/common/password_manager_features.cc +++ b/components/password_manager/core/common/password_manager_features.cc
@@ -245,6 +245,11 @@ BASE_FEATURE(kUnifiedPasswordManagerAndroidBranding, "UnifiedPasswordManagerAndroidBranding", base::FEATURE_DISABLED_BY_DEFAULT); + +// Enables new exploratory strings for the save/update password prompts. +BASE_FEATURE(kExploratorySaveUpdatePasswordStrings, + "ExploratorySaveUpdatePasswordStrings", + base::FEATURE_DISABLED_BY_DEFAULT); #endif // Enables support of sending additional votes on username first flow. The votes @@ -287,6 +292,11 @@ extern const base::FeatureParam<int> kMaxShownUPMErrorsBeforeEviction = { &kUnifiedPasswordManagerErrorMessages, "max_shown_auth_errors_before_eviction", -1}; + +// The string version to use for the save/update password prompts when the user +// is syncing passwords. The only supported versions currently are 1 and 2. +extern const base::FeatureParam<int> kSaveUpdatePromptSyncingStringVersion = { + &kExploratorySaveUpdatePasswordStrings, "syncing_string_version", 1}; #endif // Field trial identifier for password generation requirements.
diff --git a/components/password_manager/core/common/password_manager_features.h b/components/password_manager/core/common/password_manager_features.h index f544e3d..1dd53bf6 100644 --- a/components/password_manager/core/common/password_manager_features.h +++ b/components/password_manager/core/common/password_manager_features.h
@@ -74,6 +74,7 @@ BASE_DECLARE_FEATURE(kUnifiedPasswordManagerSyncUsingAndroidBackendOnly); BASE_DECLARE_FEATURE(kUnifiedPasswordManagerReenrollment); BASE_DECLARE_FEATURE(kUnifiedPasswordManagerAndroidBranding); +BASE_DECLARE_FEATURE(kExploratorySaveUpdatePasswordStrings); #endif BASE_DECLARE_FEATURE(kUsernameFirstFlowFallbackCrowdsourcing); @@ -155,6 +156,8 @@ extern const base::FeatureParam<bool> kIgnoreAuthErrorMessageTimeouts; extern const base::FeatureParam<int> kMaxShownUPMErrorsBeforeEviction; + +extern const base::FeatureParam<int> kSaveUpdatePromptSyncingStringVersion; #endif // Field trial and corresponding parameters.
diff --git a/components/policy/resources/templates/policies.yaml b/components/policy/resources/templates/policies.yaml index ba754a0..9eb2f8c 100644 --- a/components/policy/resources/templates/policies.yaml +++ b/components/policy/resources/templates/policies.yaml
@@ -1050,6 +1050,7 @@ 1049: PrivacySandboxAdTopicsEnabled 1050: PrivacySandboxSiteEnabledAdsEnabled 1051: PrivacySandboxAdMeasurementEnabled + 1052: AppStoreRatingEnabled atomic_groups: 1: Homepage 2: RemoteAccess
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/AppStoreRatingEnabled.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/AppStoreRatingEnabled.yaml new file mode 100644 index 0000000..505aa27 --- /dev/null +++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/AppStoreRatingEnabled.yaml
@@ -0,0 +1,23 @@ +caption: Allows users to be shown the <ph name="IOS_NAME">iOS</ph> App Store Rating promo +desc: |- + When the policy is not set or set to Enabled, the App Store Rating promo may be shown to the user, at most once per year. + When the policy is set to Disabled, the App Store Rating promo will not be shown to the user. +future_on: +- ios +features: + dynamic_refresh: true + per_profile: true +type: main +schema: + type: boolean +items: +- caption: Allow the App Store Rating promo to be displayed + value: true +- caption: Do not allow the App Store Rating promo to be displayed + value: false +owners: +- hiramahmood@google.com +- file://components/policy/OWNERS +default: true +example_value: false +tags: []
diff --git a/components/sync/nigori/nigori_sync_bridge_impl.cc b/components/sync/nigori/nigori_sync_bridge_impl.cc index a0c734f..47c9d5b 100644 --- a/components/sync/nigori/nigori_sync_bridge_impl.cc +++ b/components/sync/nigori/nigori_sync_bridge_impl.cc
@@ -561,12 +561,9 @@ // Newly arrived keystore keys could resolve pending encryption state in // keystore mode. DCHECK_EQ(state_.passphrase_type, NigoriSpecifics::KEYSTORE_PASSPHRASE); - const absl::optional<sync_pb::NigoriKey> keystore_decryptor_key = - TryDecryptPendingKeystoreDecryptorToken( - sync_pb::EncryptedData(*state_.pending_keystore_decryptor_token)); - absl::optional<ModelError> error = TryDecryptPendingKeysWith( - BuildDecryptionKeyBagForRemoteKeybag(keystore_decryptor_key)); + absl::optional<ModelError> error = + TryDecryptPendingKeysWith(BuildDecryptionKeyBagForRemoteKeybag()); if (error.has_value()) { processor_->ReportError(*error); return false; @@ -686,21 +683,21 @@ state_.trusted_vault_debug_info = specifics.trusted_vault_debug_info(); + if (state_.passphrase_type == NigoriSpecifics::CUSTOM_PASSPHRASE) { + state_.custom_passphrase_key_derivation_params = + GetKeyDerivationParamsFromSpecifics(specifics); + } + absl::optional<sync_pb::NigoriKey> keystore_decryptor_key; if (state_.passphrase_type == NigoriSpecifics::KEYSTORE_PASSPHRASE) { - keystore_decryptor_key = TryDecryptPendingKeystoreDecryptorToken( - specifics.keystore_decryptor_token()); + state_.pending_keystore_decryptor_token = + specifics.keystore_decryptor_token(); } else { state_.pending_keystore_decryptor_token.reset(); } const NigoriKeyBag decryption_key_bag_for_remote_update = - BuildDecryptionKeyBagForRemoteKeybag(keystore_decryptor_key); - - if (state_.passphrase_type == NigoriSpecifics::CUSTOM_PASSPHRASE) { - state_.custom_passphrase_key_derivation_params = - GetKeyDerivationParamsFromSpecifics(specifics); - } + BuildDecryptionKeyBagForRemoteKeybag(); // Set incoming encrypted keys as pending, so they are processed in // TryDecryptPendingKeysWith(). If the keybag is not immediately decryptable, @@ -747,27 +744,20 @@ return absl::nullopt; } -absl::optional<sync_pb::NigoriKey> -NigoriSyncBridgeImpl::TryDecryptPendingKeystoreDecryptorToken( - const sync_pb::EncryptedData& keystore_decryptor_token) { - DCHECK(!keystore_decryptor_token.blob().empty()); - sync_pb::NigoriKey keystore_decryptor_key; - if (state_.keystore_keys_cryptographer->DecryptKeystoreDecryptorToken( - keystore_decryptor_token, &keystore_decryptor_key)) { - state_.pending_keystore_decryptor_token.reset(); - return keystore_decryptor_key; - } - state_.pending_keystore_decryptor_token = keystore_decryptor_token; - return absl::nullopt; -} - -NigoriKeyBag NigoriSyncBridgeImpl::BuildDecryptionKeyBagForRemoteKeybag( - const absl::optional<sync_pb::NigoriKey>& keystore_decryptor_key) const { +NigoriKeyBag NigoriSyncBridgeImpl::BuildDecryptionKeyBagForRemoteKeybag() + const { NigoriKeyBag decryption_key_bag = NigoriKeyBag::CreateEmpty(); - if (keystore_decryptor_key.has_value()) { + if (state_.pending_keystore_decryptor_token.has_value()) { DCHECK_EQ(state_.passphrase_type, NigoriSpecifics::KEYSTORE_PASSPHRASE); - decryption_key_bag.AddKeyFromProto(*keystore_decryptor_key); + sync_pb::NigoriKey keystore_decryptor_key; + if (state_.keystore_keys_cryptographer->DecryptKeystoreDecryptorToken( + *state_.pending_keystore_decryptor_token, + &keystore_decryptor_key)) { + // Note: |pending_keystore_decryptor_token| will be cleared upon + // successful decryption of |pending_keys|. + decryption_key_bag.AddKeyFromProto(keystore_decryptor_key); + } } if (state_.cryptographer->CanEncrypt()) {
diff --git a/components/sync/nigori/nigori_sync_bridge_impl.h b/components/sync/nigori/nigori_sync_bridge_impl.h index 3cdac89..1d303c9 100644 --- a/components/sync/nigori/nigori_sync_bridge_impl.h +++ b/components/sync/nigori/nigori_sync_bridge_impl.h
@@ -92,17 +92,12 @@ absl::optional<ModelError> UpdateLocalState( const sync_pb::NigoriSpecifics& specifics); - absl::optional<sync_pb::NigoriKey> TryDecryptPendingKeystoreDecryptorToken( - const sync_pb::EncryptedData& keystore_decryptor_token); - // Builds NigoriKeyBag, which contains keys acceptable for decryption of // |encryption_keybag| from remote NigoriSpecifics. Its content depends on - // current passphrase type and available keys: for KEYSTORE_PASSPHRASE it - // contains only |keystore_decryptor_key|, for all other passphrase types - // it contains deserialized |explicit_passphrase_key_| and current default - // encryption key. - NigoriKeyBag BuildDecryptionKeyBagForRemoteKeybag( - const absl::optional<sync_pb::NigoriKey>& keystore_decryptor_key) const; + // current passphrase type and available keys: it contains current default + // encryption key, for KEYSTORE_PASSPHRASE it additionally contains key + // obtained from |keystore_decryptor_token|. + NigoriKeyBag BuildDecryptionKeyBagForRemoteKeybag() const; // Uses |key_bag| to try to decrypt pending keys as represented in // |state_.pending_keys| (which must be set).
diff --git a/components/tracing/common/tracing_switches.cc b/components/tracing/common/tracing_switches.cc index 42fb6a67..ba1efdc 100644 --- a/components/tracing/common/tracing_switches.cc +++ b/components/tracing/common/tracing_switches.cc
@@ -107,4 +107,10 @@ // (currently 32kB on Desktop or 4kB on Android). const char kTraceSmbSize[] = "trace-smb-size"; +// This is only used when we did not set buffer size in trace config and will be +// used for all trace sessions. If not provided, we will use the default value +// provided in perfetto_config.cc +const char kDefaultTraceBufferSizeLimitInKb[] = + "default-trace-buffer-size-limit-in-kb"; + } // namespace switches
diff --git a/components/tracing/common/tracing_switches.h b/components/tracing/common/tracing_switches.h index e0baf33..7b951d9 100644 --- a/components/tracing/common/tracing_switches.h +++ b/components/tracing/common/tracing_switches.h
@@ -25,6 +25,7 @@ TRACING_EXPORT extern const char kTraceToConsole[]; TRACING_EXPORT extern const char kBackgroundTracingOutputFile[]; TRACING_EXPORT extern const char kTraceSmbSize[]; +TRACING_EXPORT extern const char kDefaultTraceBufferSizeLimitInKb[]; } // namespace switches
diff --git a/content/browser/android/message_payload.cc b/content/browser/android/message_payload.cc index e2fc8cfe..4067411 100644 --- a/content/browser/android/message_payload.cc +++ b/content/browser/android/message_payload.cc
@@ -33,6 +33,11 @@ size_t GetLength() const override { return length_; } + // Java ArrayBuffers are always fixed-length. + bool GetIsResizableByUserJavaScript() const override { return false; } + + size_t GetMaxByteLength() const override { return length_; } + // Due to JNI limitation, Java ByteArray cannot be converted into base::span // trivially. absl::optional<base::span<const uint8_t>> GetAsSpanIfPossible()
diff --git a/content/browser/attribution_reporting/attribution_storage_sql.cc b/content/browser/attribution_reporting/attribution_storage_sql.cc index 03aa4e65..3f24cc6 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql.cc +++ b/content/browser/attribution_reporting/attribution_storage_sql.cc
@@ -292,8 +292,9 @@ absl::optional<attribution_reporting::FilterData> DeserializeFilterData( const std::string& string) { proto::AttributionFilterData msg; - if (!msg.ParseFromString(string)) + if (!msg.ParseFromString(string)) { return absl::nullopt; + } attribution_reporting::FilterValues::container_type filter_values; filter_values.reserve(msg.filter_values().size()); @@ -339,15 +340,17 @@ absl::optional<attribution_reporting::AggregationKeys> DeserializeAggregationKeys(const std::string& str) { proto::AttributionAggregatableSource msg; - if (!msg.ParseFromString(str)) + if (!msg.ParseFromString(str)) { return absl::nullopt; + } attribution_reporting::AggregationKeys::Keys::container_type keys; keys.reserve(msg.keys().size()); for (const auto& [id, key] : msg.keys()) { - if (!key.has_high_bits() || !key.has_low_bits()) + if (!key.has_high_bits() || !key.has_low_bits()) { return absl::nullopt; + } keys.emplace_back(id, absl::MakeUint128(key.high_bits(), key.low_bits())); } @@ -358,14 +361,17 @@ absl::optional<StoredSource::ActiveState> GetSourceActiveState( bool event_level_active, bool aggregatable_active) { - if (event_level_active && aggregatable_active) + if (event_level_active && aggregatable_active) { return StoredSource::ActiveState::kActive; + } - if (!event_level_active && !aggregatable_active) + if (!event_level_active && !aggregatable_active) { return StoredSource::ActiveState::kInactive; + } - if (!event_level_active) + if (!event_level_active) { return StoredSource::ActiveState::kReachedEventLevelAttributionLimit; + } // We haven't enforced aggregatable attribution limit yet. return absl::nullopt; @@ -438,15 +444,17 @@ absl::optional<attribution_reporting::FilterData> filter_data = DeserializeFilterData(statement.ColumnString(col++)); - if (!filter_data) + if (!filter_data) { return absl::nullopt; + } bool event_level_active = statement.ColumnBool(col++); bool aggregatable_active = statement.ColumnBool(col++); absl::optional<StoredSource::ActiveState> active_state = GetSourceActiveState(event_level_active, aggregatable_active); - if (!active_state.has_value()) + if (!active_state.has_value()) { return absl::nullopt; + } return StoredSourceData{ .source = StoredSource( @@ -475,8 +483,9 @@ sql::Statement statement( db->GetCachedStatement(SQL_FROM_HERE, kReadSourceToAttributeSql)); statement.BindInt64(0, *source_id); - if (!statement.Step()) + if (!statement.Step()) { return absl::nullopt; + } return ReadSourceFromStatement(statement); } @@ -511,8 +520,9 @@ bool AttributionStorageSql::DeactivateSources( const std::vector<StoredSource::Id>& sources) { sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) + if (!transaction.Begin()) { return false; + } static constexpr char kDeactivateSourcesSql[] = "UPDATE sources " @@ -524,8 +534,9 @@ for (StoredSource::Id id : sources) { statement.Reset(/*clear_bound_vars=*/true); statement.BindInt64(0, *id); - if (!statement.Run()) + if (!statement.Run()) { return false; + } } return transaction.Commit(); @@ -536,8 +547,9 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Force the creation of the database if it doesn't exist, as we need to // persist the source. - if (!LazyInit(DbCreationPolicy::kCreateIfAbsent)) + if (!LazyInit(DbCreationPolicy::kCreateIfAbsent)) { return StoreSourceResult(StorableSource::Result::kInternalError); + } // Only delete expired impressions periodically to avoid excessive DB // operations. @@ -546,8 +558,9 @@ DCHECK_GE(delete_frequency, base::TimeDelta()); const base::Time now = base::Time::Now(); if (now - last_deleted_expired_sources_ >= delete_frequency) { - if (!DeleteExpiredSources()) + if (!DeleteExpiredSources()) { return StoreSourceResult(StorableSource::Result::kInternalError); + } last_deleted_expired_sources_ = now; } @@ -588,8 +601,9 @@ } sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) + if (!transaction.Begin()) { return StoreSourceResult(StorableSource::Result::kInternalError); + } AttributionStorageDelegate::RandomizedResponse randomized_response = delegate_->GetRandomizedResponse(common_info); @@ -646,16 +660,18 @@ SerializeAggregationKeys(common_info.aggregation_keys())); statement.BindBlob(18, SerializeFilterData(common_info.filter_data())); - if (!statement.Run()) + if (!statement.Run()) { return StoreSourceResult(StorableSource::Result::kInternalError); + } const StoredSource::Id source_id(db_->GetLastInsertRowId()); const StoredSource stored_source(source.common_info(), attribution_logic, *active_state, source_id, /*aggregatable_budget_consumed=*/0); - if (!rate_limit_table_.AddRateLimitForSource(db_.get(), stored_source)) + if (!rate_limit_table_.AddRateLimitForSource(db_.get(), stored_source)) { return StoreSourceResult(StorableSource::Result::kInternalError); + } absl::optional<base::Time> min_fake_report_time; @@ -681,8 +697,9 @@ } } - if (!transaction.Commit()) + if (!transaction.Commit()) { return StoreSourceResult(StorableSource::Result::kInternalError); + } return StoreSourceResult( attribution_logic == StoredSource::AttributionLogic::kTruthfully @@ -733,8 +750,9 @@ min_priority_statement.BindTime(1, report.report_time()); const bool has_matching_report = min_priority_statement.Step(); - if (!min_priority_statement.Succeeded()) + if (!min_priority_statement.Succeeded()) { return MaybeReplaceLowerPriorityEventLevelReportResult::kError; + } // Deactivate the source at event-level as a new report will never be // generated in the future. @@ -759,17 +777,20 @@ // it. We could explicitly check the trigger time here, but it would only // be relevant in the case of an ill-behaved clock, in which case the rest of // the attribution functionality would probably also break. - if (conversion_priority <= min_priority) + if (conversion_priority <= min_priority) { return MaybeReplaceLowerPriorityEventLevelReportResult::kDropNewReport; + } absl::optional<AttributionReport> replaced = GetReport(conversion_id_with_min_priority); - if (!replaced.has_value()) + if (!replaced.has_value()) { return MaybeReplaceLowerPriorityEventLevelReportResult::kError; + } // Otherwise, delete the existing report with the lowest priority. - if (!DeleteReportInternal(conversion_id_with_min_priority)) + if (!DeleteReportInternal(conversion_id_with_min_priority)) { return MaybeReplaceLowerPriorityEventLevelReportResult::kError; + } replaced_report = std::move(replaced); return MaybeReplaceLowerPriorityEventLevelReportResult::kReplaceOldReport; @@ -828,8 +849,9 @@ : new_aggregatable_status; DCHECK(aggregatable_status.has_value()); - if (!IsSuccessResult(*aggregatable_status)) + if (!IsSuccessResult(*aggregatable_status)) { new_aggregatable_report = absl::nullopt; + } return CreateReportResult( trigger_time, *event_level_status, *aggregatable_status, @@ -1069,8 +1091,9 @@ statement.BindTime(2, base::Time::Now()); // If there are no matching sources, return early. - if (!statement.Step()) + if (!statement.Step()) { return statement.Succeeded(); + } // The first one returned will be attributed; it has the highest priority. source_id_to_attribute = StoredSource::Id(statement.ColumnInt64(0)); @@ -1104,13 +1127,15 @@ return EventLevelResult::kFalselyAttributedSource; } - if (!top_level_filters_match) + if (!top_level_filters_match) { return EventLevelResult::kNoMatchingSourceFilterData; + } const CommonSourceInfo& common_info = attribution_info.source.common_info(); - if (attribution_info.time > common_info.event_report_window_time()) + if (attribution_info.time > common_info.event_report_window_time()) { return EventLevelResult::kReportWindowPassed; + } const AttributionSourceType source_type = common_info.source_type(); @@ -1122,8 +1147,9 @@ event_trigger.not_filters); }); - if (event_trigger == trigger.registration().event_triggers.vec().end()) + if (event_trigger == trigger.registration().event_triggers.vec().end()) { return EventLevelResult::kNoMatchingConfigurations; + } switch (ReportAlreadyStored(attribution_info.source.source_id(), event_trigger->dedup_key, @@ -1193,8 +1219,9 @@ } sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) + if (!transaction.Begin()) { return EventLevelResult::kInternalError; + } auto* event_level_data = absl::get_if<AttributionReport::EventLevelData>(&report.data()); @@ -1212,8 +1239,9 @@ maybe_replace_lower_priority_report_result == MaybeReplaceLowerPriorityEventLevelReportResult:: kDropNewReportSourceDeactivated) { - if (!transaction.Commit()) + if (!transaction.Commit()) { return EventLevelResult::kInternalError; + } dropped_report = std::move(report); @@ -1239,8 +1267,9 @@ attribution_info.time, report.report_time(), event_level_data->priority, report.external_report_id(), attribution_info.debug_key); - if (!id) + if (!id) { return EventLevelResult::kInternalError; + } event_level_data->id = *id; } @@ -1267,15 +1296,18 @@ // Update the attributed source. impression_update_statement.BindInt64(0, *attribution_info.source.source_id()); - if (!impression_update_statement.Run()) + if (!impression_update_statement.Run()) { return EventLevelResult::kInternalError; + } } - if (!transaction.Commit()) + if (!transaction.Commit()) { return EventLevelResult::kInternalError; + } - if (!create_report) + if (!create_report) { return EventLevelResult::kDroppedForNoise; + } return maybe_replace_lower_priority_report_result == MaybeReplaceLowerPriorityEventLevelReportResult:: @@ -1309,8 +1341,9 @@ store_report_statement.BindInt64(4, priority); store_report_statement.BindString(5, external_report_id.AsLowercaseString()); BindUint64OrNull(store_report_statement, 6, trigger_debug_key); - if (!store_report_statement.Run()) + if (!store_report_statement.Run()) { return absl::nullopt; + } return AttributionReport::EventLevelData::Id(db_->GetLastInsertRowId()); } @@ -1362,8 +1395,9 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!report_types.Empty()); - if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) + if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) { return {}; + } std::vector<AttributionReport> reports; @@ -1417,12 +1451,14 @@ while (statement.Step()) { absl::optional<AttributionReport> report = ReadReportFromStatement(statement); - if (report.has_value()) + if (report.has_value()) { reports.push_back(std::move(*report)); + } } - if (!statement.Succeeded()) + if (!statement.Succeeded()) { return {}; + } return reports; } @@ -1430,8 +1466,9 @@ absl::optional<base::Time> AttributionStorageSql::GetNextReportTime( base::Time time) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) + if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) { return absl::nullopt; + } absl::optional<base::Time> next_event_level_report_time = GetNextEventLevelReportTime(time); @@ -1467,8 +1504,9 @@ std::vector<AttributionReport> AttributionStorageSql::GetReports( const std::vector<AttributionReport::Id>& ids) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) + if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) { return {}; + } std::vector<AttributionReport> reports; for (AttributionReport::Id id : ids) { @@ -1479,8 +1517,9 @@ }, id); - if (report.has_value()) + if (report.has_value()) { reports.push_back(std::move(*report)); + } } return reports; } @@ -1494,8 +1533,9 @@ db_->GetCachedStatement(SQL_FROM_HERE, kGetReportSql)); statement.BindInt64(0, *conversion_id); - if (!statement.Step()) + if (!statement.Step()) { return absl::nullopt; + } return ReadReportFromStatement(statement); } @@ -1514,12 +1554,15 @@ StoredSource::Id source_id(statement.ColumnInt64(0)); source_ids.push_back(source_id); } - if (!statement.Succeeded()) + if (!statement.Succeeded()) { return false; - if (source_ids.empty()) + } + if (source_ids.empty()) { return true; - if (!DeleteSources(source_ids)) + } + if (!DeleteSources(source_ids)) { return false; + } // Deliberately retain the existing bound vars so that the limit, etc are // the same. statement.Reset(/*clear_bound_vars=*/false); @@ -1543,8 +1586,9 @@ db_->GetCachedStatement(SQL_FROM_HERE, kSelectExpiredSourcesSql)); select_expired_statement.BindTime(0, base::Time::Now()); select_expired_statement.BindInt(1, kMaxDeletesPerBatch); - if (!delete_sources_from_paged_select(select_expired_statement)) + if (!delete_sources_from_paged_select(select_expired_statement)) { return false; + } // Delete all sources that have no associated reports and are // inactive. This is done in a separate statement from @@ -1569,8 +1613,9 @@ bool AttributionStorageSql::DeleteReport(AttributionReport::Id report_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) + if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) { return true; + } return absl::visit( [&](auto id) { @@ -1594,8 +1639,9 @@ AttributionReport::Id report_id, base::Time new_report_time) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) + if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) { return false; + } auto [statement_id, sql_query, report_id_int] = absl::visit( base::Overloaded{ @@ -1628,15 +1674,17 @@ // If no delay is being applied (i.e. debug mode is active), return the // earliest report time nonetheless so that it is scheduled properly. - if (!delay.has_value()) + if (!delay.has_value()) { return GetNextReportTime(base::Time::Min()); + } DCHECK_GE(delay->min, base::TimeDelta()); DCHECK_GE(delay->max, base::TimeDelta()); DCHECK_LE(delay->min, delay->max); - if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) + if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) { return absl::nullopt; + } base::Time now = base::Time::Now(); @@ -1682,8 +1730,9 @@ StoragePartition::StorageKeyMatcherFunction filter, bool delete_rate_limit_data) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) + if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) { return; + } SCOPED_UMA_HISTOGRAM_TIMER("Conversions.ClearDataTime"); if (filter.is_null() && (delete_begin.is_null() || delete_begin.is_min()) && @@ -1741,15 +1790,17 @@ // TODO(csharrison, johnidel): Should we consider poisoning the DB if some of // the delete operations fail? - if (!statement.Succeeded()) + if (!statement.Succeeded()) { return; + } // Delete the data in a transaction to avoid cases where the source part // of a report is deleted without deleting the associated report, or // vice versa. sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) + if (!transaction.Begin()) { return; + } int aggregatable_maybe_deleted = ClearAggregatableAttributionsForOriginsInRange( @@ -1767,8 +1818,9 @@ base::flat_set<StoredSource::Id>(std::move(source_ids_to_delete)) .extract(); - if (!DeleteSources(source_ids_to_delete)) + if (!DeleteSources(source_ids_to_delete)) { return; + } // Careful! At this point we can still have some vestigial entries in the DB. // For example, if a source has two reports, and one report is @@ -1783,8 +1835,9 @@ for (StoredSource::Id source_id : source_ids_to_delete) { delete_vestigial_statement.Reset(/*clear_bound_vars=*/true); delete_vestigial_statement.BindInt64(0, *source_id); - if (!delete_vestigial_statement.Run()) + if (!delete_vestigial_statement.Run()) { return; + } num_event_reports_deleted += db_->GetLastChangeCount(); } @@ -1794,8 +1847,9 @@ aggregatable_maybe_deleted = ClearAggregatableAttributionsForSourceIds(source_ids_to_delete); - if (aggregatable_maybe_deleted < 0) + if (aggregatable_maybe_deleted < 0) { return; + } num_aggregatable_reports_deleted += aggregatable_maybe_deleted; if (delete_rate_limit_data && !rate_limit_table_.ClearDataForSourceIds( @@ -1809,8 +1863,9 @@ return; } - if (!transaction.Commit()) + if (!transaction.Commit()) { return; + } RecordSourcesDeleted(static_cast<int>(source_ids_to_delete.size())); RecordReportsDeleted(num_event_reports_deleted, @@ -1819,51 +1874,59 @@ void AttributionStorageSql::ClearAllDataAllTime(bool delete_rate_limit_data) { sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) + if (!transaction.Begin()) { return; + } static constexpr char kDeleteAllReportsSql[] = "DELETE FROM event_level_reports"; sql::Statement delete_all_reports_statement( db_->GetCachedStatement(SQL_FROM_HERE, kDeleteAllReportsSql)); - if (!delete_all_reports_statement.Run()) + if (!delete_all_reports_statement.Run()) { return; + } int num_event_reports_deleted = db_->GetLastChangeCount(); static constexpr char kDeleteAllSourcesSql[] = "DELETE FROM sources"; sql::Statement delete_all_sources_statement( db_->GetCachedStatement(SQL_FROM_HERE, kDeleteAllSourcesSql)); - if (!delete_all_sources_statement.Run()) + if (!delete_all_sources_statement.Run()) { return; + } int num_sources_deleted = db_->GetLastChangeCount(); static constexpr char kDeleteAllDedupKeysSql[] = "DELETE FROM dedup_keys"; sql::Statement delete_all_dedup_keys_statement( db_->GetCachedStatement(SQL_FROM_HERE, kDeleteAllDedupKeysSql)); - if (!delete_all_dedup_keys_statement.Run()) + if (!delete_all_dedup_keys_statement.Run()) { return; + } static constexpr char kDeleteAllAggregationsSql[] = "DELETE FROM aggregatable_report_metadata"; sql::Statement delete_all_aggregations_statement( db_->GetCachedStatement(SQL_FROM_HERE, kDeleteAllAggregationsSql)); - if (!delete_all_aggregations_statement.Run()) + if (!delete_all_aggregations_statement.Run()) { return; + } static constexpr char kDeleteAllContributionsSql[] = "DELETE FROM aggregatable_contributions"; sql::Statement delete_all_contributions_statement( db_->GetCachedStatement(SQL_FROM_HERE, kDeleteAllContributionsSql)); - if (!delete_all_contributions_statement.Run()) + if (!delete_all_contributions_statement.Run()) { return; + } int num_aggregatable_reports_deleted = db_->GetLastChangeCount(); if (delete_rate_limit_data && - !rate_limit_table_.ClearAllDataAllTime(db_.get())) + !rate_limit_table_.ClearAllDataAllTime(db_.get())) { return; + } - if (!transaction.Commit()) + if (!transaction.Commit()) { return; + } RecordSourcesDeleted(num_sources_deleted); RecordReportsDeleted(num_event_reports_deleted, @@ -1882,8 +1945,9 @@ sql::Statement statement( db_->GetCachedStatement(SQL_FROM_HERE, kCountSourcesSql)); statement.BindString(0, serialized_origin); - if (!statement.Step()) + if (!statement.Step()) { return false; + } int64_t count = statement.ColumnInt64(0); return count < delegate_->GetMaxSourcesPerOrigin(); } @@ -1893,8 +1957,9 @@ StoredSource::Id source_id, absl::optional<uint64_t> dedup_key, AttributionReport::Type report_type) { - if (!dedup_key.has_value()) + if (!dedup_key.has_value()) { return ReportAlreadyStoredStatus::kNotStored; + } static constexpr char kCountReportsSql[] = "SELECT COUNT(*)FROM dedup_keys " @@ -1907,8 +1972,9 @@ // If there's an error, return true so `MaybeCreateAndStoreReport()` // returns early. - if (!statement.Step()) + if (!statement.Step()) { return ReportAlreadyStoredStatus::kError; + } int64_t count = statement.ColumnInt64(0); return count > 0 ? ReportAlreadyStoredStatus::kStored @@ -1935,8 +2001,9 @@ statement.BindString( 0, net::SchemefulSite(trigger.destination_origin()).Serialize()); - if (!statement.Step()) + if (!statement.Step()) { return ConversionCapacityStatus::kError; + } int64_t count = statement.ColumnInt64(0); int max = delegate_->GetMaxReportsPerDestination(report_type); DCHECK_GT(max, 0); @@ -1946,8 +2013,9 @@ std::vector<StoredSource> AttributionStorageSql::GetActiveSources(int limit) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) + if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) { return {}; + } // Negatives are treated as no limit // (https://sqlite.org/lang_select.html#limitoffset). @@ -1967,24 +2035,28 @@ while (statement.Step()) { absl::optional<StoredSourceData> source_data = ReadSourceFromStatement(statement); - if (source_data.has_value()) + if (source_data.has_value()) { sources.push_back(std::move(source_data->source)); + } } - if (!statement.Succeeded()) + if (!statement.Succeeded()) { return {}; + } for (auto& source : sources) { absl::optional<std::vector<uint64_t>> dedup_keys = ReadDedupKeys(source.source_id(), AttributionReport::Type::kEventLevel); - if (!dedup_keys.has_value()) + if (!dedup_keys.has_value()) { return {}; + } source.SetDedupKeys(std::move(*dedup_keys)); absl::optional<std::vector<uint64_t>> aggregatable_dedup_keys = ReadDedupKeys(source.source_id(), AttributionReport::Type::kAggregatableAttribution); - if (!aggregatable_dedup_keys.has_value()) + if (!aggregatable_dedup_keys.has_value()) { return {}; + } source.SetAggregatableDedupKeys(std::move(*aggregatable_dedup_keys)); } @@ -2005,8 +2077,9 @@ while (statement.Step()) { dedup_keys.push_back(DeserializeUint64(statement.ColumnInt64(0))); } - if (!statement.Succeeded()) + if (!statement.Succeeded()) { return absl ::nullopt; + } return dedup_keys; } @@ -2047,8 +2120,9 @@ // storage needs to be used for an operation which needs to operate even on // an empty database. case DbStatus::kDeferringCreation: - if (creation_policy == DbCreationPolicy::kIgnoreIfAbsent) + if (creation_policy == DbCreationPolicy::kIgnoreIfAbsent) { return false; + } break; case DbStatus::kDeferringOpen: break; @@ -2099,19 +2173,22 @@ } bool AttributionStorageSql::InitializeSchema(bool db_empty) { - if (db_empty) + if (db_empty) { return CreateSchema(); + } sql::MetaTable meta_table; // Create the meta table if it doesn't already exist. The only version for // which this is the case is version 1. - if (!meta_table.Init(db_.get(), /*version=*/1, kCompatibleVersionNumber)) + if (!meta_table.Init(db_.get(), /*version=*/1, kCompatibleVersionNumber)) { return false; + } int version = meta_table.GetVersionNumber(); - if (version == kCurrentVersionNumber) + if (version == kCurrentVersionNumber) { return true; + } // Recreate the DB if the version is deprecated or too new. In the latter // case, the DB will never work until Chrome is re-upgraded. Assume the user @@ -2130,12 +2207,14 @@ bool AttributionStorageSql::CreateSchema() { base::ThreadTicks start_timestamp; - if (base::ThreadTicks::IsSupported()) + if (base::ThreadTicks::IsSupported()) { start_timestamp = base::ThreadTicks::Now(); + } sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) + if (!transaction.Begin()) { return false; + } // TODO(johnidel, csharrison): Many sources will share a target origin and // a reporting origin, so it makes sense to make a "shared string" table for @@ -2194,8 +2273,9 @@ "aggregatable_budget_consumed INTEGER NOT NULL," "aggregatable_source BLOB NOT NULL," "filter_data BLOB NOT NULL)"; - if (!db_->Execute(kImpressionTableSql)) + if (!db_->Execute(kImpressionTableSql)) { return false; + } // Optimizes source lookup by conversion destination/reporting origin // during calls to `MaybeCreateAndStoreReport()`, @@ -2207,8 +2287,9 @@ "CREATE INDEX sources_by_active_destination_site_reporting_origin " "ON sources(event_level_active,aggregatable_active," "destination_site,reporting_origin)"; - if (!db_->Execute(kConversionDestinationIndexSql)) + if (!db_->Execute(kConversionDestinationIndexSql)) { return false; + } // Optimizes calls to `DeleteExpiredSources()` and // `MaybeCreateAndStoreReport()` by indexing sources by expiry @@ -2217,16 +2298,18 @@ static constexpr char kImpressionExpiryIndexSql[] = "CREATE INDEX sources_by_expiry_time " "ON sources(expiry_time)"; - if (!db_->Execute(kImpressionExpiryIndexSql)) + if (!db_->Execute(kImpressionExpiryIndexSql)) { return false; + } // Optimizes counting active sources by source origin. static constexpr char kImpressionOriginIndexSql[] = "CREATE INDEX active_sources_by_source_origin " "ON sources(source_origin)" "WHERE event_level_active=1 OR aggregatable_active=1"; - if (!db_->Execute(kImpressionOriginIndexSql)) + if (!db_->Execute(kImpressionOriginIndexSql)) { return false; + } // TODO: Remove this during the next DB migration. static constexpr char kImpressionSiteReportingOriginIndexSql[] = @@ -2234,8 +2317,9 @@ "ON sources(source_site,reporting_origin)" "WHERE event_level_active=1 AND num_attributions=0 AND " "aggregatable_active=1 AND aggregatable_budget_consumed=0"; - if (!db_->Execute(kImpressionSiteReportingOriginIndexSql)) + if (!db_->Execute(kImpressionSiteReportingOriginIndexSql)) { return false; + } // All columns in this table are const except |report_time| and // |failed_send_attempts|, @@ -2259,8 +2343,9 @@ "failed_send_attempts INTEGER NOT NULL," "external_report_id TEXT NOT NULL," "debug_key INTEGER)"; - if (!db_->Execute(kConversionTableSql)) + if (!db_->Execute(kConversionTableSql)) { return false; + } // Optimize sorting reports by report time for calls to // `GetAttributionReports()`. The reports with the earliest report times are @@ -2268,8 +2353,9 @@ static constexpr char kConversionReportTimeIndexSql[] = "CREATE INDEX event_level_reports_by_report_time " "ON event_level_reports(report_time)"; - if (!db_->Execute(kConversionReportTimeIndexSql)) + if (!db_->Execute(kConversionReportTimeIndexSql)) { return false; + } // Want to optimize report look up by source id. This allows us to // quickly know if an expired source can be deleted safely if it has no @@ -2278,11 +2364,13 @@ static constexpr char kConversionImpressionIdIndexSql[] = "CREATE INDEX event_level_reports_by_source_id " "ON event_level_reports(source_id)"; - if (!db_->Execute(kConversionImpressionIdIndexSql)) + if (!db_->Execute(kConversionImpressionIdIndexSql)) { return false; + } - if (!rate_limit_table_.CreateTable(db_.get())) + if (!rate_limit_table_.CreateTable(db_.get())) { return false; + } static constexpr char kDedupKeyTableSql[] = "CREATE TABLE dedup_keys(" @@ -2290,8 +2378,9 @@ "report_type INTEGER NOT NULL," "dedup_key INTEGER NOT NULL," "PRIMARY KEY(source_id,report_type,dedup_key))WITHOUT ROWID"; - if (!db_->Execute(kDedupKeyTableSql)) + if (!db_->Execute(kDedupKeyTableSql)) { return false; + } // ============================ // AGGREGATE ATTRIBUTION SCHEMA @@ -2324,16 +2413,18 @@ "failed_send_attempts INTEGER NOT NULL," "initial_report_time INTEGER NOT NULL," "aggregation_coordinator INTEGER NOT NULL)"; - if (!db_->Execute(kAggregatableReportMetadataTableSql)) + if (!db_->Execute(kAggregatableReportMetadataTableSql)) { return false; + } // Optimizes aggregatable report look up by source id during calls to // `DeleteExpiredSources()`, `ClearAggregatableAttributionsForSourceIds()`. static constexpr char kAggregateSourceIdIndexSql[] = "CREATE INDEX aggregate_source_id_idx " "ON aggregatable_report_metadata(source_id)"; - if (!db_->Execute(kAggregateSourceIdIndexSql)) + if (!db_->Execute(kAggregateSourceIdIndexSql)) { return false; + } // Optimizes aggregatable report look up by trigger time for clearing site // data during calls to @@ -2341,8 +2432,9 @@ static constexpr char kAggregateTriggerTimeIndexSql[] = "CREATE INDEX aggregate_trigger_time_idx " "ON aggregatable_report_metadata(trigger_time)"; - if (!db_->Execute(kAggregateTriggerTimeIndexSql)) + if (!db_->Execute(kAggregateTriggerTimeIndexSql)) { return false; + } // Optimizes aggregatable report look up by report time to get reports in a // time range during calls to @@ -2350,8 +2442,9 @@ static constexpr char kAggregateReportTimeIndexSql[] = "CREATE INDEX aggregate_report_time_idx " "ON aggregatable_report_metadata(report_time)"; - if (!db_->Execute(kAggregateReportTimeIndexSql)) + if (!db_->Execute(kAggregateReportTimeIndexSql)) { return false; + } // All columns in this table are const. // `aggregation_id` is the primary key of a row in the @@ -2366,24 +2459,27 @@ "key_high_bits INTEGER NOT NULL," "key_low_bits INTEGER NOT NULL," "value INTEGER NOT NULL)"; - if (!db_->Execute(kAggregatableContributionsTableSql)) + if (!db_->Execute(kAggregatableContributionsTableSql)) { return false; + } // Optimizes contribution look up by aggregation id during calls to // `DeleteAggregatableContributions()`. static constexpr char kContributionAggregationIdIndexSql[] = "CREATE INDEX contribution_aggregation_id_idx " "ON aggregatable_contributions(aggregation_id)"; - if (!db_->Execute(kContributionAggregationIdIndexSql)) + if (!db_->Execute(kContributionAggregationIdIndexSql)) { return false; + } if (sql::MetaTable meta_table; !meta_table.Init( db_.get(), kCurrentVersionNumber, kCompatibleVersionNumber)) { return false; } - if (!transaction.Commit()) + if (!transaction.Commit()) { return false; + } if (base::ThreadTicks::IsSupported()) { base::UmaHistogramMediumTimes("Conversions.Storage.CreationTime", @@ -2429,8 +2525,9 @@ bool AttributionStorageSql::DeleteSources( const std::vector<StoredSource::Id>& source_ids) { sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) + if (!transaction.Begin()) { return false; + } static constexpr char kDeleteSourcesSql[] = "DELETE FROM sources WHERE source_id=?"; @@ -2440,8 +2537,9 @@ for (StoredSource::Id source_id : source_ids) { delete_impression_statement.Reset(/*clear_bound_vars=*/true); delete_impression_statement.BindInt64(0, *source_id); - if (!delete_impression_statement.Run()) + if (!delete_impression_statement.Run()) { return false; + } } static constexpr char kDeleteDedupKeySql[] = @@ -2452,8 +2550,9 @@ for (StoredSource::Id source_id : source_ids) { delete_dedup_key_statement.Reset(/*clear_bound_vars=*/true); delete_dedup_key_statement.BindInt64(0, *source_id); - if (!delete_dedup_key_statement.Run()) + if (!delete_dedup_key_statement.Run()) { return false; + } } return transaction.Commit(); @@ -2467,8 +2566,9 @@ DCHECK_LE(delete_begin, delete_end); sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) + if (!transaction.Begin()) { return -1; + } // TODO(linnan): Considering optimizing SQL query by moving some logic to C++. // See the comment in crrev.com/c/3379484 for more information. @@ -2506,8 +2606,9 @@ } } - if (!statement.Succeeded() || !transaction.Commit()) + if (!statement.Succeeded() || !transaction.Commit()) { return -1; + } return num_aggregate_reports_deleted; } @@ -2515,19 +2616,22 @@ bool AttributionStorageSql::DeleteReportInternal( AttributionReport::AggregatableAttributionData::Id aggregation_id) { sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) + if (!transaction.Begin()) { return false; + } static constexpr char kDeleteAggregationSql[] = "DELETE FROM aggregatable_report_metadata WHERE aggregation_id=?"; sql::Statement statement( db_->GetCachedStatement(SQL_FROM_HERE, kDeleteAggregationSql)); statement.BindInt64(0, *aggregation_id); - if (!statement.Run()) + if (!statement.Run()) { return false; + } - if (!DeleteAggregatableContributions(aggregation_id)) + if (!DeleteAggregatableContributions(aggregation_id)) { return false; + } return transaction.Commit(); } @@ -2548,8 +2652,9 @@ int AttributionStorageSql::ClearAggregatableAttributionsForSourceIds( const std::vector<StoredSource::Id>& source_ids) { sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) + if (!transaction.Begin()) { return -1; + } static constexpr char kDeleteAggregationsSql[] = "DELETE FROM aggregatable_report_metadata " @@ -2573,14 +2678,16 @@ } } - if (!statement.Succeeded()) + if (!statement.Succeeded()) { return -1; + } num_aggregatable_reports_deleted += db_->GetLastChangeCount(); } - if (!transaction.Commit()) + if (!transaction.Commit()) { return -1; + } return num_aggregatable_reports_deleted; } @@ -2601,12 +2708,14 @@ while (statement.Step()) { absl::optional<AttributionReport> report = ReadAggregatableAttributionReportFromStatement(statement); - if (report.has_value()) + if (report.has_value()) { reports.push_back(std::move(*report)); + } } - if (!statement.Succeeded()) + if (!statement.Succeeded()) { return {}; + } return reports; } @@ -2651,13 +2760,15 @@ ? budget - aggregatable_budget_consumed : 0; - if (capacity == 0) + if (capacity == 0) { return RateLimitResult::kNotAllowed; + } const base::CheckedNumeric<int64_t> budget_required = aggregatable_attribution.BudgetRequired(); - if (!budget_required.IsValid() || budget_required.ValueOrDie() > capacity) + if (!budget_required.IsValid() || budget_required.ValueOrDie() > capacity) { return RateLimitResult::kNotAllowed; + } return RateLimitResult::kAllowed; } @@ -2708,16 +2819,18 @@ bool top_level_filters_match, absl::optional<AttributionReport>& report, absl::optional<int>& max_aggregatable_reports_per_destination) { - if (!top_level_filters_match) + if (!top_level_filters_match) { return AggregatableResult::kNoMatchingSourceFilterData; + } const attribution_reporting::TriggerRegistration& trigger_registration = trigger.registration(); const CommonSourceInfo& common_info = attribution_info.source.common_info(); - if (attribution_info.time > common_info.aggregatable_report_window_time()) + if (attribution_info.time > common_info.aggregatable_report_window_time()) { return AggregatableResult::kReportWindowPassed; + } std::vector<AggregatableHistogramContribution> contributions = CreateAggregatableHistogram( @@ -2725,8 +2838,9 @@ common_info.aggregation_keys(), trigger_registration.aggregatable_trigger_data, trigger_registration.aggregatable_values); - if (contributions.empty()) + if (contributions.empty()) { return AggregatableResult::kNoHistograms; + } switch ( ReportAlreadyStored(attribution_info.source.source_id(), @@ -2775,8 +2889,9 @@ DCHECK(aggregatable_attribution); sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) + if (!transaction.Begin()) { return false; + } const AttributionInfo& attribution_info = report.attribution_info(); @@ -2798,8 +2913,9 @@ insert_metadata_statement.BindInt( 6, SerializeAggregationCoordinator( aggregatable_attribution->aggregation_coordinator)); - if (!insert_metadata_statement.Run()) + if (!insert_metadata_statement.Run()) { return false; + } aggregatable_attribution->id = AttributionReport::AggregatableAttributionData::Id( @@ -2821,8 +2937,9 @@ 2, SerializeUint64(absl::Uint128Low64(contribution.key()))); insert_contributions_statement.BindInt64( 3, static_cast<int64_t>(contribution.value())); - if (!insert_contributions_statement.Run()) + if (!insert_contributions_statement.Run()) { return false; + } } return transaction.Commit(); @@ -2852,11 +2969,13 @@ } sql::Transaction transaction(db_.get()); - if (!transaction.Begin()) + if (!transaction.Begin()) { return AggregatableResult::kInternalError; + } - if (!StoreAggregatableAttributionReport(report)) + if (!StoreAggregatableAttributionReport(report)) { return AggregatableResult::kInternalError; + } StoredSource::Id source_id = report.attribution_info().source.source_id(); @@ -2875,8 +2994,9 @@ return AggregatableResult::kInternalError; } - if (!transaction.Commit()) + if (!transaction.Commit()) { return AggregatableResult::kInternalError; + } return AggregatableResult::kSuccess; } @@ -2890,8 +3010,9 @@ absl::optional<StoredSourceData> source_data = ReadSourceFromStatement(statement); - if (!source_data.has_value()) + if (!source_data.has_value()) { return absl::nullopt; + } int col = kSourceColumnCount; AttributionReport::AggregatableAttributionData::Id report_id( @@ -2917,8 +3038,9 @@ std::vector<AggregatableHistogramContribution> contributions = GetAggregatableContributions(report_id); - if (contributions.empty()) + if (contributions.empty()) { return absl::nullopt; + } return AttributionReport(AttributionInfo(std::move(source_data->source), trigger_time, trigger_debug_key), @@ -2938,8 +3060,9 @@ db_->GetCachedStatement(SQL_FROM_HERE, kGetReportSql)); statement.BindInt64(0, *report_id); - if (!statement.Step()) + if (!statement.Step()) { return absl::nullopt; + } return ReadAggregatableAttributionReportFromStatement(statement); }
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc index a63fe17..f0b21694 100644 --- a/content/browser/webauth/authenticator_impl_unittest.cc +++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -4619,6 +4619,27 @@ } } +TEST_F(AuthenticatorImplTest, PRFWithoutSupport) { + // This tests that the PRF extension doesn't trigger any DCHECKs or crashes + // when used with an authenticator doesn't doesn't support hmac-secret. + NavigateAndCommit(GURL(kTestOrigin1)); + + auto prf_value = blink::mojom::PRFValues::New(); + const std::vector<uint8_t> salt1(32, 1); + prf_value->first = salt1; + std::vector<blink::mojom::PRFValuesPtr> prf_inputs; + prf_inputs.emplace_back(std::move(prf_value)); + + PublicKeyCredentialRequestOptionsPtr options = + GetTestPublicKeyCredentialRequestOptions(); + options->prf = true; + options->prf_inputs = std::move(prf_inputs); + + GetAssertionResult result = AuthenticatorGetAssertion(std::move(options)); + + EXPECT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR); +} + class AuthenticatorDevicePublicKeyTest : public AuthenticatorImplTest { void SetUp() override { AuthenticatorImplTest::SetUp();
diff --git a/content/browser/webid/idp_network_request_manager.cc b/content/browser/webid/idp_network_request_manager.cc index ec152c3..16a8f13 100644 --- a/content/browser/webid/idp_network_request_manager.cc +++ b/content/browser/webid/idp_network_request_manager.cc
@@ -133,14 +133,14 @@ } absl::optional<content::IdentityRequestAccount> ParseAccount( - const base::Value& account, + const base::Value::Dict& account, const std::string& client_id) { - auto* id = account.FindStringKey(kAccountIdKey); - auto* email = account.FindStringKey(kAccountEmailKey); - auto* name = account.FindStringKey(kAccountNameKey); - auto* given_name = account.FindStringKey(kAccountGivenNameKey); - auto* picture = account.FindStringKey(kAccountPictureKey); - auto* approved_clients = account.FindListKey(kAccountApprovedClientsKey); + auto* id = account.FindString(kAccountIdKey); + auto* email = account.FindString(kAccountEmailKey); + auto* name = account.FindString(kAccountNameKey); + auto* given_name = account.FindString(kAccountGivenNameKey); + auto* picture = account.FindString(kAccountPictureKey); + auto* approved_clients = account.FindList(kAccountApprovedClientsKey); // required fields if (!(id && email && name)) @@ -150,7 +150,7 @@ absl::optional<LoginState> approved_value; if (approved_clients) { - for (const base::Value& entry : approved_clients->GetList()) { + for (const base::Value& entry : *approved_clients) { if (entry.is_string() && entry.GetString() == client_id) { approved_value = LoginState::kSignIn; break; @@ -162,7 +162,7 @@ // kSignUp instead of leaving as nullopt. approved_value = LoginState::kSignUp; } - RecordApprovedClientsSize(approved_clients->GetList().size()); + RecordApprovedClientsSize(approved_clients->size()); } return content::IdentityRequestAccount( @@ -172,19 +172,19 @@ // Parses accounts from given Value. Returns true if parse is successful and // adds parsed accounts to the |account_list|. -bool ParseAccounts(const base::Value* accounts, +bool ParseAccounts(const base::Value::List& accounts, AccountList& account_list, const std::string& client_id) { DCHECK(account_list.empty()); - if (!accounts->is_list()) - return false; base::flat_set<std::string> account_ids; - for (auto& account : accounts->GetList()) { - if (!account.is_dict()) + for (auto& account : accounts) { + const base::Value::Dict* account_dict = account.GetIfDict(); + if (!account_dict) { return false; + } - auto parsed_account = ParseAccount(account, client_id); + auto parsed_account = ParseAccount(*account_dict, client_id); if (parsed_account) { if (account_ids.count(parsed_account->id)) return false; @@ -208,18 +208,15 @@ // Parse IdentityProviderMetadata from given value. Overwrites |idp_metadata| // with the parsed value. -void ParseIdentityProviderMetadata(const base::Value& idp_metadata_value, +void ParseIdentityProviderMetadata(const base::Value::Dict& idp_metadata_value, int brand_icon_ideal_size, int brand_icon_minimum_size, IdentityProviderMetadata& idp_metadata) { - if (!idp_metadata_value.is_dict()) - return; - - idp_metadata.brand_background_color = ParseCssColor( - idp_metadata_value.FindStringKey(kIdpBrandingBackgroundColor)); + idp_metadata.brand_background_color = + ParseCssColor(idp_metadata_value.FindString(kIdpBrandingBackgroundColor)); if (idp_metadata.brand_background_color) { idp_metadata.brand_text_color = ParseCssColor( - idp_metadata_value.FindStringKey(kIdpBrandingForegroundColor)); + idp_metadata_value.FindString(kIdpBrandingForegroundColor)); if (idp_metadata.brand_text_color) { float text_contrast_ratio = color_utils::GetContrastRatio( *idp_metadata.brand_background_color, *idp_metadata.brand_text_color); @@ -228,39 +225,45 @@ } } - const base::Value* icons_value = - idp_metadata_value.FindKey(kIdpBrandingIcons); - if (icons_value != nullptr && icons_value->is_list()) { - std::vector<blink::Manifest::ImageResource> icons; - for (const base::Value& icon_value : icons_value->GetList()) { - if (!icon_value.is_dict()) - continue; + const base::Value::List* icons_value = + idp_metadata_value.FindList(kIdpBrandingIcons); + if (!icons_value) { + return; + } - const std::string* icon_src = - icon_value.FindStringKey(kIdpBrandingIconUrl); - if (icon_src == nullptr) - continue; - - blink::Manifest::ImageResource icon; - icon.src = GURL(*icon_src); - if (!icon.src.is_valid()) - continue; - - icon.purpose = {blink::mojom::ManifestImageResource_Purpose::MASKABLE}; - - absl::optional<int> icon_size = - icon_value.FindIntKey(kIdpBrandingIconSize); - int icon_size_int = icon_size ? icon_size.value() : 0; - icon.sizes.emplace_back(icon_size_int, icon_size_int); - - icons.push_back(icon); + std::vector<blink::Manifest::ImageResource> icons; + for (const base::Value& icon_value : *icons_value) { + const base::Value::Dict* icon_value_dict = icon_value.GetIfDict(); + if (!icon_value_dict) { + continue; } - idp_metadata.brand_icon_url = - blink::ManifestIconSelector::FindBestMatchingSquareIcon( - icons, brand_icon_ideal_size, brand_icon_minimum_size, - blink::mojom::ManifestImageResource_Purpose::MASKABLE); + const std::string* icon_src = + icon_value_dict->FindString(kIdpBrandingIconUrl); + if (!icon_src) { + continue; + } + + blink::Manifest::ImageResource icon; + icon.src = GURL(*icon_src); + if (!icon.src.is_valid()) { + continue; + } + + icon.purpose = {blink::mojom::ManifestImageResource_Purpose::MASKABLE}; + + absl::optional<int> icon_size = + icon_value_dict->FindInt(kIdpBrandingIconSize); + int icon_size_int = icon_size.value_or(0); + icon.sizes.emplace_back(icon_size_int, icon_size_int); + + icons.push_back(icon); } + + idp_metadata.brand_icon_url = + blink::ManifestIconSelector::FindBestMatchingSquareIcon( + icons, brand_icon_ideal_size, brand_icon_minimum_size, + blink::mojom::ManifestImageResource_Purpose::MASKABLE); } ParseStatus GetResponseError(std::string* response_body, int response_code) { @@ -278,9 +281,10 @@ if (!result.has_value()) return ParseStatus::kInvalidResponseError; - auto& response = *result; - if (!response.is_dict()) + const base::Value::Dict* response = result->GetIfDict(); + if (!response) { return ParseStatus::kInvalidResponseError; + } return ParseStatus::kSuccess; } @@ -374,13 +378,13 @@ return; } - auto& response = *result; + const base::Value::Dict& response = result->GetDict(); auto ExtractEndpoint = [&](const char* key) { - const base::Value* endpoint = response.FindKey(key); - if (!endpoint || !endpoint->is_string()) { + const std::string* endpoint = response.FindString(key); + if (!endpoint) { return GURL(); } - return ResolveConfigUrl(provider, endpoint->GetString()); + return ResolveConfigUrl(provider, *endpoint); }; Endpoints endpoints; @@ -389,7 +393,8 @@ endpoints.client_metadata = ExtractEndpoint(kClientMetadataEndpointKey); endpoints.metrics = ExtractEndpoint(kMetricsEndpoint); - const base::Value* idp_metadata_value = response.FindKey(kIdpBrandingKey); + const base::Value::Dict* idp_metadata_value = + response.FindDict(kIdpBrandingKey); IdentityProviderMetadata idp_metadata; idp_metadata.config_url = provider; if (idp_metadata_value) { @@ -412,13 +417,13 @@ return; } - auto& response = *result; + const base::Value::Dict& response = result->GetDict(); auto ExtractUrl = [&](const char* key) { - const base::Value* endpoint = response.FindKey(key); - if (!endpoint || !endpoint->is_string()) { + const std::string* endpoint = response.FindString(key); + if (!endpoint) { return std::string(); } - return endpoint->GetString(); + return *endpoint; }; IdpNetworkRequestManager::ClientMetadata data; @@ -440,10 +445,10 @@ } AccountList account_list; - auto& response = *result; - const base::Value* accounts = response.FindKey(kAccountsKey); + const base::Value::Dict& response = result->GetDict(); + const base::Value::List* accounts = response.FindList(kAccountsKey); bool accounts_present = - accounts && ParseAccounts(accounts, account_list, client_id); + accounts && ParseAccounts(*accounts, account_list, client_id); if (!accounts_present) { std::move(callback).Run( @@ -465,18 +470,17 @@ return; } - auto& response = *result; - const base::Value* token = response.FindKey(kTokenKey); - bool token_present = token && token->is_string(); + const base::Value::Dict& response = result->GetDict(); + const std::string* token = response.FindString(kTokenKey); - if (!token_present) { + if (!token) { std::move(callback).Run( {ParseStatus::kInvalidResponseError, fetch_status.response_code}, std::string()); return; } std::move(callback).Run({ParseStatus::kSuccess, fetch_status.response_code}, - token->GetString()); + *token); } void OnLogoutCompleted(IdpNetworkRequestManager::LogoutCallback callback,
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 35a3c7e5..af6dbda3 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -3188,15 +3188,20 @@ ResumeIfPaused(); } -void TestNavigationManager::WaitForFirstYieldAfterDidStartNavigation() { +bool TestNavigationManager::WaitForFirstYieldAfterDidStartNavigation() { TRACE_EVENT( "test", "TestNavigationManager::WaitForFirstYieldAfterDidStartNavigation"); if (current_state_ >= NavigationState::WILL_START) - return; + return true; DCHECK_EQ(desired_state_, NavigationState::WILL_START); - WaitForDesiredState(); + // Ignore the result because DidStartNavigation will update |desired_state_| + // we check below. + (void)WaitForDesiredState(); + // This returns false if the runloop was terminated by a timeout rather than + // reaching the |WILL_START|. + return current_state_ >= NavigationState::WILL_START; } bool TestNavigationManager::WaitForRequestStart() { @@ -3224,10 +3229,10 @@ return WaitForDesiredState(); } -void TestNavigationManager::WaitForNavigationFinished() { +bool TestNavigationManager::WaitForNavigationFinished() { TRACE_EVENT("test", "TestNavigationManager::WaitForNavigationFinished"); desired_state_ = NavigationState::FINISHED; - WaitForDesiredState(); + return WaitForDesiredState(); } void TestNavigationManager::DidStartNavigation(NavigationHandle* handle) {
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h index a85ab69..022f135 100644 --- a/content/public/test/browser_test_utils.h +++ b/content/public/test/browser_test_utils.h
@@ -1699,8 +1699,9 @@ // where throttles run and none defer, this will break at the same time as // WaitForRequestStart. Note: since we won't know which throttle deferred, // don't use ResumeNavigation() after this call since it assumes we paused - // from the TestNavigationManagerThrottle. - void WaitForFirstYieldAfterDidStartNavigation(); + // from the TestNavigationManagerThrottle. Returns false if the waiting was + // terminated before reaching DidStartNavigation (e.g. timeout). + bool WaitForFirstYieldAfterDidStartNavigation(); // Waits until the navigation request is ready to be sent to the network // stack. This will wait until all NavigationThrottles have proceeded through @@ -1714,8 +1715,9 @@ [[nodiscard]] bool WaitForResponse(); // Waits until the navigation has been finished. Will automatically resume - // navigations paused before this point. - void WaitForNavigationFinished(); + // navigations paused before this point. Returns false if the waiting was + // terminated before reaching DidStartNavigation (e.g. timeout). + bool WaitForNavigationFinished(); // Resume the navigation. // * Called after |WaitForRequestStart|, it causes the request to be sent. @@ -1767,7 +1769,7 @@ // Waits for the desired state. Returns false if the desired state cannot be // reached (eg the navigation finishes before reaching this state). - bool WaitForDesiredState(); + [[nodiscard]] bool WaitForDesiredState(); // Called when the state of the navigation has changed. This will either stop // the message loop if the state specified by the user has been reached, or
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 2a2410d..a1f691c 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -72,6 +72,10 @@ "media/audio_decoder.h", "media/batching_media_log.cc", "media/batching_media_log.h", + "media/codec_factory.cc", + "media/codec_factory.h", + "media/codec_factory_mojo.cc", + "media/codec_factory_mojo.h", "media/gpu/gpu_video_accelerator_factories_impl.cc", "media/gpu/gpu_video_accelerator_factories_impl.h", "media/inspector_media_event_handler.cc", @@ -340,7 +344,11 @@ } if (is_fuchsia) { - sources += [ "renderer_main_platform_delegate_fuchsia.cc" ] + sources += [ + "media/codec_factory_fuchsia.cc", + "media/codec_factory_fuchsia.h", + "renderer_main_platform_delegate_fuchsia.cc", + ] public_deps += [ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.mediacodec" ] deps += [
diff --git a/content/renderer/media/codec_factory.cc b/content/renderer/media/codec_factory.cc new file mode 100644 index 0000000..65939e76 --- /dev/null +++ b/content/renderer/media/codec_factory.cc
@@ -0,0 +1,224 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/media/codec_factory.h" + +#include <memory> +#include <optional> + +#include "base/functional/callback_forward.h" +#include "base/memory/ptr_util.h" +#include "base/notreached.h" +#include "media/base/bind_to_current_loop.h" +#include "media/base/decoder.h" +#include "media/base/media_log.h" +#include "media/base/overlay_info.h" +#include "media/base/supported_video_decoder_config.h" +#include "media/mojo/clients/mojo_video_encode_accelerator.h" +#include "media/video/gpu_video_accelerator_factories.h" + +namespace content { + +CodecFactory::CodecFactory( + scoped_refptr<base::SequencedTaskRunner> media_task_runner, + scoped_refptr<viz::ContextProviderCommandBuffer> context_provider, + bool video_decode_accelerator_enabled, + bool video_encode_accelerator_enabled, + mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> + pending_vea_provider_remote) + : media_task_runner_(std::move(media_task_runner)), + context_provider_(std::move(context_provider)), + video_decode_accelerator_enabled_(video_decode_accelerator_enabled), + video_encode_accelerator_enabled_(video_encode_accelerator_enabled) { + media_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&CodecFactory::BindOnTaskRunner, base::Unretained(this), + std::move(pending_vea_provider_remote))); +} +CodecFactory::~CodecFactory() = default; + +std::unique_ptr<media::VideoEncodeAccelerator> +CodecFactory::CreateVideoEncodeAccelerator() { + DCHECK(video_encode_accelerator_enabled_); + DCHECK(media_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(vea_provider_.is_bound()); + + base::AutoLock lock(supported_profiles_lock_); + // When |supported_vea_profiles_| is empty, no hw encoder is available or + // we have not yet gotten the supported profiles. + if (!supported_vea_profiles_) { + DVLOG(2) << "VEA's profiles have not yet been gotten"; + } else if (supported_vea_profiles_->empty()) { + // There is no profile supported by VEA. + return nullptr; + } + + mojo::PendingRemote<media::mojom::VideoEncodeAccelerator> vea; + vea_provider_->CreateVideoEncodeAccelerator( + vea.InitWithNewPipeAndPassReceiver()); + + if (!vea) { + return nullptr; + } + + return base::WrapUnique<media::VideoEncodeAccelerator>( + new media::MojoVideoEncodeAccelerator(std::move(vea))); +} + +media::VideoDecoderType CodecFactory::GetVideoDecoderType() { + base::AutoLock lock(supported_profiles_lock_); + return video_decoder_type_; +} + +absl::optional<media::SupportedVideoDecoderConfigs> +CodecFactory::GetSupportedVideoDecoderConfigs() { + base::AutoLock lock(supported_profiles_lock_); + return supported_decoder_configs_; +} + +absl::optional<media::VideoEncodeAccelerator::SupportedProfiles> +CodecFactory::GetVideoEncodeAcceleratorSupportedProfiles() { + base::AutoLock lock(supported_profiles_lock_); + return supported_vea_profiles_; +} + +bool CodecFactory::IsDecoderSupportKnown() { + base::AutoLock lock(supported_profiles_lock_); + return decoder_support_notifier_.is_notified(); +} + +bool CodecFactory::IsEncoderSupportKnown() { + base::AutoLock lock(supported_profiles_lock_); + return encoder_support_notifier_.is_notified(); +} + +void CodecFactory::NotifyDecoderSupportKnown(base::OnceClosure callback) { + base::AutoLock lock(supported_profiles_lock_); + decoder_support_notifier_.Register( + media::BindToCurrentLoop(std::move(callback))); +} + +void CodecFactory::NotifyEncoderSupportKnown(base::OnceClosure callback) { + base::AutoLock lock(supported_profiles_lock_); + encoder_support_notifier_.Register( + media::BindToCurrentLoop(std::move(callback))); +} + +CodecFactory::Notifier::Notifier() = default; +CodecFactory::Notifier::~Notifier() = default; + +void CodecFactory::Notifier::Register(base::OnceClosure callback) { + if (is_notified_) { + std::move(callback).Run(); + return; + } + callbacks_.push_back(std::move(callback)); +} + +void CodecFactory::Notifier::Notify() { + DCHECK(!is_notified_); + is_notified_ = true; + while (!callbacks_.empty()) { + std::move(callbacks_.back()).Run(); + callbacks_.pop_back(); + } +} + +void CodecFactory::OnDecoderSupportFailed() { + base::AutoLock lock(supported_profiles_lock_); + if (decoder_support_notifier_.is_notified()) { + return; + } + supported_decoder_configs_ = media::SupportedVideoDecoderConfigs(); + decoder_support_notifier_.Notify(); +} + +void CodecFactory::OnGetSupportedDecoderConfigs() { + base::AutoLock lock(supported_profiles_lock_); + decoder_support_notifier_.Notify(); +} + +void CodecFactory::OnEncoderSupportFailed() { + base::AutoLock lock(supported_profiles_lock_); + if (encoder_support_notifier_.is_notified()) { + return; + } + supported_vea_profiles_ = media::VideoEncodeAccelerator::SupportedProfiles(); + encoder_support_notifier_.Notify(); +} + +void CodecFactory::OnGetVideoEncodeAcceleratorSupportedProfiles( + const media::VideoEncodeAccelerator::SupportedProfiles& + supported_profiles) { + base::AutoLock lock(supported_profiles_lock_); + supported_vea_profiles_ = supported_profiles; + encoder_support_notifier_.Notify(); +} + +void CodecFactory::BindOnTaskRunner( + mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> + pending_vea_provider_remote) { + DCHECK(media_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(context_provider_); + + vea_provider_.Bind(std::move(pending_vea_provider_remote)); + + if (context_provider_->BindToCurrentSequence() != + gpu::ContextResult::kSuccess) { + OnDecoderSupportFailed(); + OnEncoderSupportFailed(); + return; + } + + if (video_encode_accelerator_enabled_) { + // The remote might be disconnected if the encoding process crashes, for + // example a GPU driver failure. Set a disconnect handler to watch these + // types of failures and treat them as if there are no supported encoder + // profiles. + // Unretained is safe since CodecFactory is never destroyed. + // It lives until the process shuts down. + vea_provider_.set_disconnect_handler(base::BindOnce( + &CodecFactory::OnEncoderSupportFailed, base::Unretained(this))); + vea_provider_->GetVideoEncodeAcceleratorSupportedProfiles(base::BindOnce( + &CodecFactory::OnGetVideoEncodeAcceleratorSupportedProfiles, + base::Unretained(this))); + } else { + OnEncoderSupportFailed(); + } + + if (!video_decode_accelerator_enabled_) { + OnDecoderSupportFailed(); + } +} + +CodecFactoryDefault::CodecFactoryDefault( + scoped_refptr<base::SequencedTaskRunner> task_runner, + scoped_refptr<viz::ContextProviderCommandBuffer> context_provider, + bool video_decode_accelerator_enabled, + bool video_encode_accelerator_enabled, + mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> + pending_vea_provider_remote) + : CodecFactory(std::move(task_runner), + std::move(context_provider), + video_decode_accelerator_enabled, + video_encode_accelerator_enabled, + std::move(pending_vea_provider_remote)) { + // There is no decoder provider. + OnDecoderSupportFailed(); +} + +CodecFactoryDefault::~CodecFactoryDefault() = default; + +std::unique_ptr<media::VideoDecoder> CodecFactoryDefault::CreateVideoDecoder( + media::GpuVideoAcceleratorFactories* gpu_factories, + media::MediaLog* media_log, + media::RequestOverlayInfoCB request_overlay_info_cb, + const gfx::ColorSpace& rendering_color_space) { + NOTIMPLEMENTED() + << "CodecFactoryDefault does not have a provider to create a " + "hardware video decoder."; + return nullptr; +} + +} // namespace content
diff --git a/content/renderer/media/codec_factory.h b/content/renderer/media/codec_factory.h new file mode 100644 index 0000000..55e1374 --- /dev/null +++ b/content/renderer/media/codec_factory.h
@@ -0,0 +1,196 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_MEDIA_CODEC_FACTORY_H_ +#define CONTENT_RENDERER_MEDIA_CODEC_FACTORY_H_ + +#include <memory> + +#include "base/functional/callback_forward.h" +#include "content/common/content_export.h" +#include "media/base/decoder.h" +#include "media/base/media_log.h" +#include "media/base/overlay_info.h" +#include "media/base/supported_video_decoder_config.h" +#include "media/base/video_decoder.h" +#include "media/mojo/mojom/video_encode_accelerator.mojom.h" +#include "media/video/gpu_video_accelerator_factories.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h" + +namespace content { + +// Assists to GpuVideoAcceleratorFactoriesImpl on hardware decoder and encoder +// functionalities. +// +// It is a base class that handles the encoder resources +// via media::mojom::VideoEncodeAcceleratorProvider. Its derived classes need +// to implement how to connect to hardware decoder resources. +class CONTENT_EXPORT CodecFactory { + public: + // `media_task_runner` - task runner for running multi-media operations. + // `context_provider` - context provider for creating a video decoder. + // `video_decode_accelerator_enabled` - whether the video decode accelerator + // is enabled. + // `video_encode_accelerator_enabled` - whether the video encode accelerator + // is enabled. + // `pending_vea_provider_remote` - bound pending + // media::mojom::VideoEncodeAcceleratorProvider remote. + CodecFactory( + scoped_refptr<base::SequencedTaskRunner> media_task_runner, + scoped_refptr<viz::ContextProviderCommandBuffer> context_provider, + bool video_decode_accelerator_enabled, + bool video_encode_accelerator_enabled, + mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> + pending_vea_provider_remote); + + CodecFactory(const CodecFactory&) = delete; + CodecFactory& operator=(const CodecFactory&) = delete; + virtual ~CodecFactory(); + + // `gpu_factories` - pointer to the GpuVideoAcceleratorFactories that + // owns |this|. + // `media_log` - process-wide pointer to log to chrome://media-internals log. + // `request_overlay_info_cb` - callback that gets the overlay information. + // `rendering_color_space` - color space for the purpose of color conversion. + // + // Derived class should construct its own type of video decoder. + virtual std::unique_ptr<media::VideoDecoder> CreateVideoDecoder( + media::GpuVideoAcceleratorFactories* gpu_factories, + media::MediaLog* media_log, + media::RequestOverlayInfoCB request_overlay_info_cb, + const gfx::ColorSpace& rendering_color_space) = 0; + + std::unique_ptr<media::VideoEncodeAccelerator> CreateVideoEncodeAccelerator(); + + // Returns VideoDecoderType::kUnknown in cases where IsDecoderSupportKnown() + // is false. + // Otherwise, it returns the type of decoder that provided the + // configs for the config support check. + media::VideoDecoderType GetVideoDecoderType(); + + // Returns a nullopt if we have not yet gotten the configs. + // Returns an optional that contains an empty vector if we have gotten the + // result and there are no supported configs. + absl::optional<media::SupportedVideoDecoderConfigs> + GetSupportedVideoDecoderConfigs(); + + // Returns a nullopt if we have not yet gotten the profiles. + // Returns an optional that contains an empty vector if we have gotten the + // result and there are no supported profiles. + absl::optional<media::VideoEncodeAccelerator::SupportedProfiles> + GetVideoEncodeAcceleratorSupportedProfiles(); + + // Returns true if media::SupportedVideoDecoderConfigs are populated. + bool IsDecoderSupportKnown(); + + // Returns true if media::VideoEncodeAccelerator::SupportedProfiles are + // populated. + bool IsEncoderSupportKnown(); + + // If the current decoder support is not yet known, use this to register a + // callback that is notified once the support is known. At that point, calling + // GetSupportedVideoDecoderConfigs will give the set of supported decoder + // configs. + // + // There is no way to unsubscribe a callback, it is recommended to use a + // WeakPtr if you need this feature. + void NotifyDecoderSupportKnown(base::OnceClosure callback); + + // If the current encoder support is not yet known, use this to register a + // callback that is notified once the support is known. At that point, calling + // GetVideoEncodeAcceleratorSupportedProfiles will give the set of supported + // encoder profiles. + // + // There is no way to unsubscribe a callback, it is recommended to use a + // WeakPtr if you need this feature. + void NotifyEncoderSupportKnown(base::OnceClosure callback); + + protected: + class Notifier { + public: + Notifier(); + ~Notifier(); + + void Register(base::OnceClosure callback); + void Notify(); + + bool is_notified() { return is_notified_; } + + private: + bool is_notified_ = false; + std::vector<base::OnceClosure> callbacks_; + }; + + void OnDecoderSupportFailed(); + void OnGetSupportedDecoderConfigs(); + + void OnEncoderSupportFailed(); + void OnGetVideoEncodeAcceleratorSupportedProfiles( + const media::VideoEncodeAccelerator::SupportedProfiles& + supported_profiles); + + // Task runner on the Media thread for running multi-media operations + // (e.g., creating a video decoder). + // In Fuchsia, it needs to be started with the IO message pump for FIDL calls. + scoped_refptr<base::SequencedTaskRunner> media_task_runner_; + + // Shared pointer to a shared context provider. All access should happen only + // on the media thread. + const scoped_refptr<viz::ContextProviderCommandBuffer> context_provider_; + + // Whether video acceleration encoding/decoding should be enabled. + const bool video_decode_accelerator_enabled_; + const bool video_encode_accelerator_enabled_; + + base::Lock supported_profiles_lock_; + + // If the Optional is empty, then we have not yet gotten the configs. + // If the Optional contains an empty vector, then we have gotten the result + // and there are no supported configs. + absl::optional<media::SupportedVideoDecoderConfigs> supported_decoder_configs_ + GUARDED_BY(supported_profiles_lock_); + absl::optional<media::VideoEncodeAccelerator::SupportedProfiles> + supported_vea_profiles_ GUARDED_BY(supported_profiles_lock_); + + media::VideoDecoderType video_decoder_type_ + GUARDED_BY(supported_profiles_lock_) = media::VideoDecoderType::kUnknown; + + Notifier decoder_support_notifier_ GUARDED_BY(supported_profiles_lock_); + Notifier encoder_support_notifier_ GUARDED_BY(supported_profiles_lock_); + + private: + void BindOnTaskRunner( + mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> + pending_vea_provider_remote); + + mojo::Remote<media::mojom::VideoEncodeAcceleratorProvider> vea_provider_; +}; + +// CodecFactoryDefault is the default derived class, which has no +// decoder provider. It does not have any supported video decoder configs and +// returns a null pointer when creating a hardware video decoder. +class CodecFactoryDefault final : public CodecFactory { + public: + CodecFactoryDefault( + scoped_refptr<base::SequencedTaskRunner> task_runner, + scoped_refptr<viz::ContextProviderCommandBuffer> context_provider, + bool video_decode_accelerator_enabled, + bool video_encode_accelerator_enabled, + mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> + pending_vea_provider_remote); + ~CodecFactoryDefault() override; + + // Returns nullptr since there is no decoder provider. + std::unique_ptr<media::VideoDecoder> CreateVideoDecoder( + media::GpuVideoAcceleratorFactories* gpu_factories, + media::MediaLog* media_log, + media::RequestOverlayInfoCB request_overlay_info_cb, + const gfx::ColorSpace& rendering_color_space) override; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_CODEC_FACTORY_H_
diff --git a/content/renderer/media/codec_factory_fuchsia.cc b/content/renderer/media/codec_factory_fuchsia.cc new file mode 100644 index 0000000..c8e6d2b --- /dev/null +++ b/content/renderer/media/codec_factory_fuchsia.cc
@@ -0,0 +1,92 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/media/codec_factory_fuchsia.h" + +#include "base/functional/bind.h" +#include "base/location.h" +#include "base/synchronization/lock.h" +#include "content/renderer/media/codec_factory.h" +#include "media/base/decoder.h" +#include "media/base/overlay_info.h" +#include "media/base/supported_video_decoder_config.h" +#include "media/base/video_decoder.h" +#include "media/fuchsia/mojom/fuchsia_media.mojom.h" +#include "media/fuchsia/video/fuchsia_video_decoder.h" +#include "media/video/gpu_video_accelerator_factories.h" + +namespace content { + +CodecFactoryFuchsia::CodecFactoryFuchsia( + scoped_refptr<base::SequencedTaskRunner> media_task_runner, + scoped_refptr<viz::ContextProviderCommandBuffer> context_provider, + bool video_decode_accelerator_enabled, + bool video_encode_accelerator_enabled, + mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> + pending_vea_provider_remote, + mojo::PendingRemote<media::mojom::FuchsiaMediaCodecProvider> + pending_media_codec_provider_remote) + : CodecFactory(std::move(media_task_runner), + std::move(context_provider), + video_decode_accelerator_enabled, + video_encode_accelerator_enabled, + std::move(pending_vea_provider_remote)) { + media_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&CodecFactoryFuchsia::BindOnTaskRunner, + base::Unretained(this), + std::move(pending_media_codec_provider_remote))); +} +CodecFactoryFuchsia::~CodecFactoryFuchsia() = default; + +std::unique_ptr<media::VideoDecoder> CodecFactoryFuchsia::CreateVideoDecoder( + media::GpuVideoAcceleratorFactories* gpu_factories, + media::MediaLog* media_log, + media::RequestOverlayInfoCB request_overlay_info_cb, + const gfx::ColorSpace& rendering_color_space) { + DCHECK(video_decode_accelerator_enabled_); + + return std::make_unique<media::FuchsiaVideoDecoder>(context_provider_, + media_codec_provider_, + /*allow_overlays=*/true); +} + +void CodecFactoryFuchsia::BindOnTaskRunner( + mojo::PendingRemote<media::mojom::FuchsiaMediaCodecProvider> + media_codec_provider_remote) { + DCHECK(media_task_runner_->RunsTasksInCurrentSequence()); + + if (!video_decode_accelerator_enabled_) { + OnDecoderSupportFailed(); + return; + } + + media_codec_provider_.Bind(std::move(media_codec_provider_remote), + media_task_runner_); + // The remote might be disconnected if the decoding process crashes, for + // example a decoder driver failure. Set a disconnect handler to watch these + // types of failures and treat them as if there are no supported decoder + // configs. + // Unretained is safe since CodecFactory is never destroyed. + // It lives until the process shuts down. + media_codec_provider_.set_disconnect_handler( + base::BindOnce(&CodecFactoryFuchsia::OnDecoderSupportFailed, + base::Unretained(this)), + media_task_runner_); + media_codec_provider_->GetSupportedVideoDecoderConfigs( + base::BindOnce(&CodecFactoryFuchsia::OnGetSupportedDecoderConfigs, + base::Unretained(this))); +} + +void CodecFactoryFuchsia::OnGetSupportedDecoderConfigs( + const media::SupportedVideoDecoderConfigs& supported_configs) { + { + base::AutoLock lock(supported_profiles_lock_); + supported_decoder_configs_.emplace(supported_configs); + video_decoder_type_ = media::VideoDecoderType::kFuchsia; + } + CodecFactory::OnGetSupportedDecoderConfigs(); +} + +} // namespace content
diff --git a/content/renderer/media/codec_factory_fuchsia.h b/content/renderer/media/codec_factory_fuchsia.h new file mode 100644 index 0000000..743c203 --- /dev/null +++ b/content/renderer/media/codec_factory_fuchsia.h
@@ -0,0 +1,57 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_MEDIA_CODEC_FACTORY_FUCHSIA_H_ +#define CONTENT_RENDERER_MEDIA_CODEC_FACTORY_FUCHSIA_H_ + +#include "content/common/content_export.h" +#include "content/renderer/media/codec_factory.h" +#include "media/base/overlay_info.h" +#include "media/base/video_decoder.h" +#include "media/fuchsia/mojom/fuchsia_media.mojom.h" +#include "media/video/gpu_video_accelerator_factories.h" +#include "mojo/public/cpp/bindings/shared_remote.h" + +namespace content { + +// CodecFactoryFuchsia gets hardware decoder resources +// via media::mojom::FuchsiaMediaCodecProvider. +// +// Codec-related services on Fuchsia are used directly from the renderer process +// after the browser process provides a connection to the FIDL protocol via +// media::mojom::FuchsiaMediaCodecProvider. This can improve performance by +// avoiding the need to hop through the browser process. +class CONTENT_EXPORT CodecFactoryFuchsia final : public CodecFactory { + public: + CodecFactoryFuchsia( + scoped_refptr<base::SequencedTaskRunner> media_task_runner, + scoped_refptr<viz::ContextProviderCommandBuffer> context_provider, + bool video_decode_accelerator_enabled, + bool video_encode_accelerator_enabled, + mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> + pending_vea_provider_remote, + mojo::PendingRemote<media::mojom::FuchsiaMediaCodecProvider> + pending_media_codec_provider_remote); + ~CodecFactoryFuchsia() override; + + std::unique_ptr<media::VideoDecoder> CreateVideoDecoder( + media::GpuVideoAcceleratorFactories* gpu_factories, + media::MediaLog* media_log, + media::RequestOverlayInfoCB request_overlay_info_cb, + const gfx::ColorSpace& rendering_color_space) override; + + private: + void BindOnTaskRunner( + mojo::PendingRemote<media::mojom::FuchsiaMediaCodecProvider> + media_codec_provider_remote); + void OnGetSupportedDecoderConfigs( + const media::SupportedVideoDecoderConfigs& supported_configs); + + mojo::SharedRemote<media::mojom::FuchsiaMediaCodecProvider> + media_codec_provider_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_CODEC_FACTORY_FUCHSIA_H_
diff --git a/content/renderer/media/codec_factory_mojo.cc b/content/renderer/media/codec_factory_mojo.cc new file mode 100644 index 0000000..411d3ab --- /dev/null +++ b/content/renderer/media/codec_factory_mojo.cc
@@ -0,0 +1,98 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/media/codec_factory_mojo.h" + +#include "base/functional/bind.h" +#include "base/location.h" +#include "base/synchronization/lock.h" +#include "content/renderer/media/codec_factory.h" +#include "media/base/overlay_info.h" +#include "media/mojo/clients/mojo_video_decoder.h" +#include "media/mojo/mojom/interface_factory.mojom.h" +#include "media/video/gpu_video_accelerator_factories.h" +#include "mojo/public/cpp/bindings/pending_remote.h" + +namespace content { + +CodecFactoryMojo::CodecFactoryMojo( + scoped_refptr<base::SequencedTaskRunner> media_task_runner, + scoped_refptr<viz::ContextProviderCommandBuffer> context_provider, + bool video_decode_accelerator_enabled, + bool video_encode_accelerator_enabled, + mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> + pending_vea_provider_remote, + mojo::PendingRemote<media::mojom::InterfaceFactory> + pending_interface_factory_remote) + : CodecFactory(std::move(media_task_runner), + std::move(context_provider), + video_decode_accelerator_enabled, + video_encode_accelerator_enabled, + std::move(pending_vea_provider_remote)) { + media_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&CodecFactoryMojo::BindOnTaskRunner, + base::Unretained(this), + std::move(pending_interface_factory_remote))); +} +CodecFactoryMojo::~CodecFactoryMojo() = default; + +std::unique_ptr<media::VideoDecoder> CodecFactoryMojo::CreateVideoDecoder( + media::GpuVideoAcceleratorFactories* gpu_factories, + media::MediaLog* media_log, + media::RequestOverlayInfoCB request_overlay_info_cb, + const gfx::ColorSpace& rendering_color_space) { + DCHECK(video_decode_accelerator_enabled_); + DCHECK(interface_factory_.is_bound()); + + mojo::PendingRemote<media::mojom::VideoDecoder> video_decoder; + interface_factory_->CreateVideoDecoder( + video_decoder.InitWithNewPipeAndPassReceiver(), /*dst_video_decoder=*/{}); + return std::make_unique<media::MojoVideoDecoder>( + media_task_runner_, gpu_factories, media_log, std::move(video_decoder), + std::move(request_overlay_info_cb), rendering_color_space); +} + +void CodecFactoryMojo::BindOnTaskRunner( + mojo::PendingRemote<media::mojom::InterfaceFactory> + interface_factory_remote) { + DCHECK(media_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(context_provider_); + + interface_factory_.Bind(std::move(interface_factory_remote)); + + if (!video_decode_accelerator_enabled_) { + OnDecoderSupportFailed(); + return; + } + + // Note: This is a bit of a hack, since we don't specify the implementation + // before asking for the map of supported configs. We do this because it + // (a) saves an ipc call, and (b) makes the return of those configs atomic. + interface_factory_->CreateVideoDecoder( + video_decoder_.BindNewPipeAndPassReceiver(), /*dst_video_decoder=*/{}); + // The remote might be disconnected if the decoding process crashes, for + // example a GPU driver failure. Set a disconnect handler to watch these + // types of failures and treat them as if there are no supported decoder + // configs. + // Unretained is safe since CodecFactory is never destroyed. + // It lives until the process shuts down. + video_decoder_.set_disconnect_handler(base::BindOnce( + &CodecFactoryMojo::OnDecoderSupportFailed, base::Unretained(this))); + video_decoder_->GetSupportedConfigs(base::BindOnce( + &CodecFactoryMojo::OnGetSupportedDecoderConfigs, base::Unretained(this))); +} + +void CodecFactoryMojo::OnGetSupportedDecoderConfigs( + const media::SupportedVideoDecoderConfigs& supported_configs, + media::VideoDecoderType decoder_type) { + { + base::AutoLock lock(supported_profiles_lock_); + video_decoder_.reset(); + supported_decoder_configs_.emplace(supported_configs); + video_decoder_type_ = decoder_type; + } + CodecFactory::OnGetSupportedDecoderConfigs(); +} + +} // namespace content
diff --git a/content/renderer/media/codec_factory_mojo.h b/content/renderer/media/codec_factory_mojo.h new file mode 100644 index 0000000..ff371a6 --- /dev/null +++ b/content/renderer/media/codec_factory_mojo.h
@@ -0,0 +1,56 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_MEDIA_CODEC_FACTORY_MOJO_H_ +#define CONTENT_RENDERER_MEDIA_CODEC_FACTORY_MOJO_H_ + +#include <memory> + +#include "content/common/content_export.h" +#include "content/renderer/media/codec_factory.h" +#include "media/base/decoder.h" +#include "media/base/overlay_info.h" +#include "media/base/video_decoder.h" +#include "media/mojo/mojom/interface_factory.mojom.h" +#include "media/video/gpu_video_accelerator_factories.h" +#include "mojo/public/cpp/bindings/remote.h" + +namespace content { + +// CodecFactoryMojo gets hardware decoder resources +// via media::mojom::InterfaceFactory. Use it when mojo-based video decoder is +// enabled. +class CONTENT_EXPORT CodecFactoryMojo final : public CodecFactory { + public: + CodecFactoryMojo( + scoped_refptr<base::SequencedTaskRunner> media_task_runner, + scoped_refptr<viz::ContextProviderCommandBuffer> context_provider, + bool video_decode_accelerator_enabled, + bool video_encode_accelerator_enabled, + mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> + pending_vea_provider_remote, + mojo::PendingRemote<media::mojom::InterfaceFactory> + pending_interface_factory_remote); + ~CodecFactoryMojo() override; + + std::unique_ptr<media::VideoDecoder> CreateVideoDecoder( + media::GpuVideoAcceleratorFactories* gpu_factories, + media::MediaLog* media_log, + media::RequestOverlayInfoCB request_overlay_info_cb, + const gfx::ColorSpace& rendering_color_space) override; + + private: + void BindOnTaskRunner( + mojo::PendingRemote<media::mojom::InterfaceFactory> interface_factory); + void OnGetSupportedDecoderConfigs( + const media::SupportedVideoDecoderConfigs& supported_configs, + media::VideoDecoderType decoder_type); + + mojo::Remote<media::mojom::InterfaceFactory> interface_factory_; + mojo::Remote<media::mojom::VideoDecoder> video_decoder_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_CODEC_FACTORY_MOJO_H_
diff --git a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc index d2bfea3..c6022f1 100644 --- a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc +++ b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
@@ -6,8 +6,10 @@ #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> +#include <memory> +#include <optional> -#include "base/bind.h" +#include "base/functional/bind.h" #include "base/memory/ptr_util.h" #include "base/memory/unsafe_shared_memory_region.h" #include "base/metrics/histogram_macros.h" @@ -15,22 +17,15 @@ #include "base/unguessable_token.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" -#include "components/viz/common/gpu/context_provider.h" -#include "content/child/child_thread_impl.h" -#include "content/public/common/content_features.h" +#include "content/renderer/media/codec_factory.h" #include "content/renderer/render_thread_impl.h" -#include "gpu/command_buffer/client/context_support.h" -#include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" #include "gpu/ipc/client/command_buffer_proxy_impl.h" #include "gpu/ipc/client/gpu_channel_host.h" -#include "gpu/ipc/common/gpu_memory_buffer_support.h" -#include "media/base/bind_to_current_loop.h" -#include "media/gpu/gpu_video_accelerator_util.h" +#include "media/base/decoder.h" +#include "media/base/supported_video_decoder_config.h" #include "media/mojo/buildflags.h" -#include "media/mojo/clients/mojo_video_decoder.h" -#include "media/mojo/clients/mojo_video_encode_accelerator.h" #include "media/video/video_encode_accelerator.h" #include "services/viz/public/cpp/gpu/context_provider_command_buffer.h" #include "third_party/skia/include/core/SkTypes.h" @@ -53,26 +48,6 @@ } // namespace -GpuVideoAcceleratorFactoriesImpl::Notifier::Notifier() = default; -GpuVideoAcceleratorFactoriesImpl::Notifier::~Notifier() = default; - -void GpuVideoAcceleratorFactoriesImpl::Notifier::Register( - base::OnceClosure callback) { - if (is_notified_) { - std::move(callback).Run(); - return; - } - callbacks_.push_back(std::move(callback)); -} - -void GpuVideoAcceleratorFactoriesImpl::Notifier::Notify() { - DCHECK(!is_notified_); - is_notified_ = true; - for (auto& callback : callbacks_) - std::move(callback).Run(); - callbacks_.clear(); -} - // static std::unique_ptr<GpuVideoAcceleratorFactoriesImpl> GpuVideoAcceleratorFactoriesImpl::Create( @@ -80,22 +55,40 @@ const scoped_refptr<base::SequencedTaskRunner>& main_thread_task_runner, const scoped_refptr<base::SequencedTaskRunner>& task_runner, const scoped_refptr<viz::ContextProviderCommandBuffer>& context_provider, + std::unique_ptr<CodecFactory> codec_factory, bool enable_video_gpu_memory_buffers, bool enable_media_stream_gpu_memory_buffers, bool enable_video_decode_accelerator, - bool enable_video_encode_accelerator, - mojo::PendingRemote<media::mojom::InterfaceFactory> - interface_factory_remote, - mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> - vea_provider_remote) { + bool enable_video_encode_accelerator) { RecordContextProviderPhaseUmaEnum( ContextProviderPhase::CONTEXT_PROVIDER_ACQUIRED); return base::WrapUnique(new GpuVideoAcceleratorFactoriesImpl( std::move(gpu_channel_host), main_thread_task_runner, task_runner, - context_provider, enable_video_gpu_memory_buffers, + std::move(context_provider), std::move(codec_factory), + RenderThreadImpl::current()->GetGpuMemoryBufferManager(), + enable_video_gpu_memory_buffers, enable_media_stream_gpu_memory_buffers, + enable_video_decode_accelerator, enable_video_encode_accelerator)); +} + +// static +std::unique_ptr<GpuVideoAcceleratorFactoriesImpl> +GpuVideoAcceleratorFactoriesImpl::CreateForTesting( + scoped_refptr<gpu::GpuChannelHost> gpu_channel_host, + const scoped_refptr<base::SequencedTaskRunner>& main_thread_task_runner, + const scoped_refptr<base::SequencedTaskRunner>& task_runner, + const scoped_refptr<viz::ContextProviderCommandBuffer>& context_provider, + std::unique_ptr<CodecFactory> codec_factory, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, + bool enable_video_gpu_memory_buffers, + bool enable_media_stream_gpu_memory_buffers, + bool enable_video_decode_accelerator, + bool enable_video_encode_accelerator) { + return base::WrapUnique(new GpuVideoAcceleratorFactoriesImpl( + std::move(gpu_channel_host), main_thread_task_runner, task_runner, + std::move(context_provider), std::move(codec_factory), + std::move(gpu_memory_buffer_manager), enable_video_gpu_memory_buffers, enable_media_stream_gpu_memory_buffers, enable_video_decode_accelerator, - enable_video_encode_accelerator, std::move(interface_factory_remote), - std::move(vea_provider_remote))); + enable_video_encode_accelerator)); } GpuVideoAcceleratorFactoriesImpl::GpuVideoAcceleratorFactoriesImpl( @@ -103,53 +96,40 @@ const scoped_refptr<base::SequencedTaskRunner>& main_thread_task_runner, const scoped_refptr<base::SequencedTaskRunner>& task_runner, const scoped_refptr<viz::ContextProviderCommandBuffer>& context_provider, + std::unique_ptr<CodecFactory> codec_factory, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, bool enable_video_gpu_memory_buffers, bool enable_media_stream_gpu_memory_buffers, bool enable_video_decode_accelerator, - bool enable_video_encode_accelerator, - mojo::PendingRemote<media::mojom::InterfaceFactory> - interface_factory_remote, - mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> - vea_provider_remote) + bool enable_video_encode_accelerator) : main_thread_task_runner_(main_thread_task_runner), task_runner_(task_runner), gpu_channel_host_(std::move(gpu_channel_host)), + codec_factory_(std::move(codec_factory)), context_provider_(context_provider), enable_video_gpu_memory_buffers_(enable_video_gpu_memory_buffers), enable_media_stream_gpu_memory_buffers_( enable_media_stream_gpu_memory_buffers), video_decode_accelerator_enabled_(enable_video_decode_accelerator), video_encode_accelerator_enabled_(enable_video_encode_accelerator), - gpu_memory_buffer_manager_( - RenderThreadImpl::current()->GetGpuMemoryBufferManager()) { + gpu_memory_buffer_manager_(gpu_memory_buffer_manager) { DCHECK(main_thread_task_runner_); DCHECK(gpu_channel_host_); task_runner_->PostTask( FROM_HERE, base::BindOnce(&GpuVideoAcceleratorFactoriesImpl::BindOnTaskRunner, - base::Unretained(this), - std::move(interface_factory_remote), - std::move(vea_provider_remote))); + base::Unretained(this))); } GpuVideoAcceleratorFactoriesImpl::~GpuVideoAcceleratorFactoriesImpl() {} -void GpuVideoAcceleratorFactoriesImpl::BindOnTaskRunner( - mojo::PendingRemote<media::mojom::InterfaceFactory> - interface_factory_remote, - mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> - vea_provider_remote) { +void GpuVideoAcceleratorFactoriesImpl::BindOnTaskRunner() { DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(context_provider_); - interface_factory_.Bind(std::move(interface_factory_remote)); - vea_provider_.Bind(std::move(vea_provider_remote)); - if (context_provider_->BindToCurrentSequence() != gpu::ContextResult::kSuccess) { - OnDecoderSupportFailed(); - OnEncoderSupportFailed(); OnContextLost(); return; } @@ -160,98 +140,24 @@ context_provider_->GetCommandBufferProxy()->GetGpuChannel().GetChannelToken( base::BindOnce(&GpuVideoAcceleratorFactoriesImpl::OnChannelTokenReady, base::Unretained(this))); - - if (video_encode_accelerator_enabled_) { - vea_provider_.set_disconnect_handler(base::BindOnce( - &GpuVideoAcceleratorFactoriesImpl::OnEncoderSupportFailed, - base::Unretained(this))); - vea_provider_->GetVideoEncodeAcceleratorSupportedProfiles( - base::BindOnce(&GpuVideoAcceleratorFactoriesImpl:: - OnGetVideoEncodeAcceleratorSupportedProfiles, - base::Unretained(this))); - } else { - OnEncoderSupportFailed(); - } - -#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) - if (video_decode_accelerator_enabled_) { - // Note: This is a bit of a hack, since we don't specify the implementation - // before asking for the map of supported configs. We do this because it - // (a) saves an ipc call, and (b) makes the return of those configs atomic. - interface_factory_->CreateVideoDecoder( - video_decoder_.BindNewPipeAndPassReceiver(), /*dst_video_decoder=*/{}); - video_decoder_.set_disconnect_handler(base::BindOnce( - &GpuVideoAcceleratorFactoriesImpl::OnDecoderSupportFailed, - base::Unretained(this))); - video_decoder_->GetSupportedConfigs(base::BindOnce( - &GpuVideoAcceleratorFactoriesImpl::OnSupportedDecoderConfigs, - base::Unretained(this))); - } else { - OnDecoderSupportFailed(); - } -#else - OnDecoderSupportFailed(); -#endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) } bool GpuVideoAcceleratorFactoriesImpl::IsDecoderSupportKnown() { - base::AutoLock lock(supported_profiles_lock_); - return decoder_support_notifier_.is_notified(); + return codec_factory_->IsDecoderSupportKnown(); } void GpuVideoAcceleratorFactoriesImpl::NotifyDecoderSupportKnown( base::OnceClosure callback) { - base::AutoLock lock(supported_profiles_lock_); - decoder_support_notifier_.Register( - media::BindToCurrentLoop(std::move(callback))); -} - -void GpuVideoAcceleratorFactoriesImpl::OnSupportedDecoderConfigs( - const media::SupportedVideoDecoderConfigs& supported_configs, - media::VideoDecoderType decoder_type) { - base::AutoLock lock(supported_profiles_lock_); - video_decoder_.reset(); - supported_decoder_configs_ = supported_configs; - video_decoder_type_ = decoder_type; - decoder_support_notifier_.Notify(); -} - -void GpuVideoAcceleratorFactoriesImpl::OnDecoderSupportFailed() { - base::AutoLock lock(supported_profiles_lock_); - video_decoder_.reset(); - if (decoder_support_notifier_.is_notified()) - return; - supported_decoder_configs_ = media::SupportedVideoDecoderConfigs(); - decoder_support_notifier_.Notify(); + codec_factory_->NotifyDecoderSupportKnown(std::move(callback)); } bool GpuVideoAcceleratorFactoriesImpl::IsEncoderSupportKnown() { - base::AutoLock lock(supported_profiles_lock_); - return encoder_support_notifier_.is_notified(); + return codec_factory_->IsEncoderSupportKnown(); } void GpuVideoAcceleratorFactoriesImpl::NotifyEncoderSupportKnown( base::OnceClosure callback) { - base::AutoLock lock(supported_profiles_lock_); - encoder_support_notifier_.Register( - media::BindToCurrentLoop(std::move(callback))); -} - -void GpuVideoAcceleratorFactoriesImpl:: - OnGetVideoEncodeAcceleratorSupportedProfiles( - const media::VideoEncodeAccelerator::SupportedProfiles& - supported_profiles) { - base::AutoLock lock(supported_profiles_lock_); - supported_vea_profiles_ = supported_profiles; - encoder_support_notifier_.Notify(); -} - -void GpuVideoAcceleratorFactoriesImpl::OnEncoderSupportFailed() { - base::AutoLock lock(supported_profiles_lock_); - if (encoder_support_notifier_.is_notified()) - return; - supported_vea_profiles_ = media::VideoEncodeAccelerator::SupportedProfiles(); - encoder_support_notifier_.Notify(); + codec_factory_->NotifyEncoderSupportKnown(std::move(callback)); } bool GpuVideoAcceleratorFactoriesImpl::CheckContextLost() { @@ -330,16 +236,14 @@ return Supported::kFalse; } - base::AutoLock lock(supported_profiles_lock_); - - // If GetSupportedConfigs() has not completed (or was never started), report - // that all configs are supported. Clients will find out that configs are not - // supported when VideoDecoder::Initialize() fails. - if (!supported_decoder_configs_) + auto supported_decoder_configs = + codec_factory_->GetSupportedVideoDecoderConfigs(); + if (!supported_decoder_configs) { return Supported::kUnknown; + } // Iterate over the supported configs. - for (const auto& supported : *supported_decoder_configs_) { + for (const auto& supported : *supported_decoder_configs) { if (supported.Matches(config)) return Supported::kTrue; } @@ -347,8 +251,7 @@ } media::VideoDecoderType GpuVideoAcceleratorFactoriesImpl::GetDecoderType() { - base::AutoLock lock(supported_profiles_lock_); - return video_decoder_type_; + return codec_factory_->GetVideoDecoderType(); } std::unique_ptr<media::VideoDecoder> @@ -357,50 +260,21 @@ media::RequestOverlayInfoCB request_overlay_info_cb) { DCHECK(video_decode_accelerator_enabled_); DCHECK(task_runner_->RunsTasksInCurrentSequence()); - DCHECK(interface_factory_.is_bound()); - -#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) if (CheckContextLost()) return nullptr; - mojo::PendingRemote<media::mojom::VideoDecoder> video_decoder; - interface_factory_->CreateVideoDecoder( - video_decoder.InitWithNewPipeAndPassReceiver(), /*dst_video_decoder=*/{}); - return std::make_unique<media::MojoVideoDecoder>( - task_runner_, this, media_log, std::move(video_decoder), - std::move(request_overlay_info_cb), rendering_color_space_); -#else - return nullptr; -#endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) + return codec_factory_->CreateVideoDecoder( + this, media_log, request_overlay_info_cb, rendering_color_space_); } std::unique_ptr<media::VideoEncodeAccelerator> GpuVideoAcceleratorFactoriesImpl::CreateVideoEncodeAccelerator() { DCHECK(video_encode_accelerator_enabled_); DCHECK(task_runner_->RunsTasksInCurrentSequence()); - DCHECK(vea_provider_.is_bound()); if (CheckContextLost()) return nullptr; - base::AutoLock lock(supported_profiles_lock_); - // When |supported_vea_profiles_| is empty, no hw encoder is available or - // we have not yet gotten the supported profiles. - if (!supported_vea_profiles_) { - DVLOG(2) << "VEA's profiles have not yet been gotten"; - } else if (supported_vea_profiles_->empty()) { - // There is no profile supported by VEA. - return nullptr; - } - - mojo::PendingRemote<media::mojom::VideoEncodeAccelerator> vea; - vea_provider_->CreateVideoEncodeAccelerator( - vea.InitWithNewPipeAndPassReceiver()); - - if (!vea) - return nullptr; - - return std::unique_ptr<media::VideoEncodeAccelerator>( - new media::MojoVideoEncodeAccelerator(std::move(vea))); + return codec_factory_->CreateVideoEncodeAccelerator(); } std::unique_ptr<gfx::GpuMemoryBuffer> @@ -522,8 +396,7 @@ absl::optional<media::VideoEncodeAccelerator::SupportedProfiles> GpuVideoAcceleratorFactoriesImpl::GetVideoEncodeAcceleratorSupportedProfiles() { - base::AutoLock lock(supported_profiles_lock_); - return supported_vea_profiles_; + return codec_factory_->GetVideoEncodeAcceleratorSupportedProfiles(); } viz::RasterContextProvider*
diff --git a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h index 99bd984..bf8aa6e 100644 --- a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h +++ b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h
@@ -12,20 +12,19 @@ #include <vector> #include "base/callback_list.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "base/synchronization/waitable_event.h" +#include "base/memory/scoped_refptr.h" #include "base/unguessable_token.h" +#include "build/build_config.h" #include "components/viz/common/gpu/context_lost_observer.h" -#include "media/base/supported_video_decoder_config.h" -#include "media/mojo/mojom/interface_factory.mojom.h" -#include "media/mojo/mojom/video_decoder.mojom.h" -#include "media/mojo/mojom/video_encode_accelerator.mojom.h" +#include "content/common/content_export.h" +#include "content/renderer/media/codec_factory.h" +#include "media/mojo/buildflags.h" #include "media/video/gpu_video_accelerator_factories.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "mojo/public/cpp/bindings/remote.h" #include "third_party/abseil-cpp/absl/types/optional.h" -#include "ui/gfx/geometry/size.h" + +#if BUILDFLAG(IS_FUCHSIA) +#include <fuchsia/mediacodec/cpp/fidl.h> +#endif namespace base { class SequencedTaskRunner; @@ -52,7 +51,7 @@ // the |task_runner_|, as provided during construction. // |context_provider| should not support locking and will be bound to // |task_runner_| where all the operations on the context should also happen. -class GpuVideoAcceleratorFactoriesImpl +class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl : public media::GpuVideoAcceleratorFactories, public viz::ContextLostObserver { public: @@ -63,14 +62,22 @@ const scoped_refptr<base::SequencedTaskRunner>& main_thread_task_runner, const scoped_refptr<base::SequencedTaskRunner>& task_runner, const scoped_refptr<viz::ContextProviderCommandBuffer>& context_provider, + std::unique_ptr<CodecFactory> codec_factory, bool enable_video_gpu_memory_buffers, bool enable_media_stream_gpu_memory_buffers, bool enable_video_decode_accelerator, - bool enable_video_encode_accelerator, - mojo::PendingRemote<media::mojom::InterfaceFactory> - interface_factory_remote, - mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> - vea_provider_remote); + bool enable_video_encode_accelerator); + static std::unique_ptr<GpuVideoAcceleratorFactoriesImpl> CreateForTesting( + scoped_refptr<gpu::GpuChannelHost> gpu_channel_host, + const scoped_refptr<base::SequencedTaskRunner>& main_thread_task_runner, + const scoped_refptr<base::SequencedTaskRunner>& task_runner, + const scoped_refptr<viz::ContextProviderCommandBuffer>& context_provider, + std::unique_ptr<CodecFactory> codec_factory, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, + bool enable_video_gpu_memory_buffers, + bool enable_media_stream_gpu_memory_buffers, + bool enable_video_decode_accelerator, + bool enable_video_encode_accelerator); // media::GpuVideoAcceleratorFactories implementation. bool IsGpuVideoDecodeAcceleratorEnabled() override; @@ -140,60 +147,32 @@ ~GpuVideoAcceleratorFactoriesImpl() override; private: - class Notifier { - public: - Notifier(); - ~Notifier(); - - void Register(base::OnceClosure callback); - void Notify(); - - bool is_notified() { return is_notified_; } - - private: - bool is_notified_ = false; - std::vector<base::OnceClosure> callbacks_; - }; - GpuVideoAcceleratorFactoriesImpl( scoped_refptr<gpu::GpuChannelHost> gpu_channel_host, const scoped_refptr<base::SequencedTaskRunner>& main_thread_task_runner, const scoped_refptr<base::SequencedTaskRunner>& task_runner, const scoped_refptr<viz::ContextProviderCommandBuffer>& context_provider, + std::unique_ptr<CodecFactory> codec_factory, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, bool enable_gpu_memory_buffer_video_frames_for_video, bool enable_gpu_memory_buffer_video_frames_for_media_stream, bool enable_video_decode_accelerator, - bool enable_video_encode_accelerator, - mojo::PendingRemote<media::mojom::InterfaceFactory> - interface_factory_remote, - mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> - vea_provider_remote); + bool enable_video_encode_accelerator); - void BindOnTaskRunner( - mojo::PendingRemote<media::mojom::InterfaceFactory> - interface_factory_remote, - mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> - vea_provider_remote); + void BindOnTaskRunner(); // viz::ContextLostObserver implementation. void OnContextLost() override; void SetContextProviderLostOnMainThread(); - void OnSupportedDecoderConfigs( - const media::SupportedVideoDecoderConfigs& supported_configs, - media::VideoDecoderType decoder_type); - void OnDecoderSupportFailed(); - - void OnGetVideoEncodeAcceleratorSupportedProfiles( - const media::VideoEncodeAccelerator::SupportedProfiles& - supported_profiles); - void OnEncoderSupportFailed(); void OnChannelTokenReady(const base::UnguessableToken& token); const scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner_; const scoped_refptr<base::SequencedTaskRunner> task_runner_; const scoped_refptr<gpu::GpuChannelHost> gpu_channel_host_; + const std::unique_ptr<CodecFactory> codec_factory_; + // Shared pointer to a shared context provider. It is initially set on main // thread, but all subsequent access and destruction should happen only on the // media thread. @@ -218,27 +197,6 @@ gfx::ColorSpace rendering_color_space_; gpu::GpuMemoryBufferManager* const gpu_memory_buffer_manager_; - - mojo::Remote<media::mojom::InterfaceFactory> interface_factory_; - mojo::Remote<media::mojom::VideoEncodeAcceleratorProvider> vea_provider_; - - // SupportedDecoderConfigs state. - mojo::Remote<media::mojom::VideoDecoder> video_decoder_; - - base::Lock supported_profiles_lock_; - - // If the Optional is empty, then we have not yet gotten the configs. If the - // Optional contains an empty vector, then we have gotten the result and there - // are no supported configs. - absl::optional<media::SupportedVideoDecoderConfigs> supported_decoder_configs_ - GUARDED_BY(supported_profiles_lock_); - media::VideoDecoderType video_decoder_type_ - GUARDED_BY(supported_profiles_lock_) = media::VideoDecoderType::kUnknown; - Notifier decoder_support_notifier_ GUARDED_BY(supported_profiles_lock_); - - absl::optional<media::VideoEncodeAccelerator::SupportedProfiles> - supported_vea_profiles_ GUARDED_BY(supported_profiles_lock_); - Notifier encoder_support_notifier_ GUARDED_BY(supported_profiles_lock_); }; } // namespace content
diff --git a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl_unittest.cc b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl_unittest.cc new file mode 100644 index 0000000..5b70f84 --- /dev/null +++ b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl_unittest.cc
@@ -0,0 +1,685 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h" + +#include <GLES2/gl2.h> +#include <cstddef> +#include <memory> + +#include "base/memory/scoped_refptr.h" +#include "base/test/gtest_util.h" +#include "base/test/task_environment.h" +#include "base/test/test_future.h" +#include "build/build_config.h" +#include "components/viz/common/gpu/context_cache_controller.h" +#include "components/viz/common/gpu/context_lost_observer.h" +#include "components/viz/test/test_gpu_memory_buffer_manager.h" +#include "content/public/common/gpu_stream_constants.h" +#include "content/renderer/media/codec_factory.h" +#include "gpu/command_buffer/client/gles2_interface_stub.h" +#include "gpu/command_buffer/common/capabilities.h" +#include "gpu/command_buffer/common/context_creation_attribs.h" +#include "gpu/command_buffer/common/context_result.h" +#include "gpu/config/gpu_feature_info.h" +#include "gpu/ipc/client/command_buffer_proxy_impl.h" +#include "gpu/ipc/client/gpu_channel_host.h" +#include "gpu/ipc/common/gpu_channel.mojom.h" +#include "gpu/ipc/common/mock_gpu_channel.h" +#include "media/base/decoder.h" +#include "media/base/media_util.h" +#include "media/base/supported_video_decoder_config.h" +#include "media/base/video_codecs.h" +#include "media/base/video_decoder_config.h" +#include "media/mojo/buildflags.h" +#include "media/mojo/mojom/video_encode_accelerator.mojom.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest-death-test.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkImage.h" + +#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) +#include "content/renderer/media/codec_factory_mojo.h" +#include "media/filters/fake_video_decoder.h" +#include "media/mojo/mojom/interface_factory.mojom.h" +#include "media/mojo/services/mojo_cdm_service_context.h" +#include "media/mojo/services/mojo_media_client.h" +#include "media/mojo/services/mojo_video_decoder_service.h" +#include "mojo/public/cpp/bindings/unique_receiver_set.h" +#endif + +#if BUILDFLAG(IS_FUCHSIA) +#include "content/renderer/media/codec_factory_fuchsia.h" +#include "media/fuchsia/mojom/fuchsia_media.mojom.h" +#endif + +using ::testing::_; +using ::testing::Invoke; +using ::testing::NiceMock; +using ::testing::Return; + +namespace content { + +namespace { + +constexpr gfx::Size kCodedSize(320, 240); +constexpr gfx::Rect kVisibleRect(320, 240); +constexpr gfx::Size kNaturalSize(320, 240); + +const media::SupportedVideoDecoderConfig kH264MaxSupportedVideoDecoderConfig = + media::SupportedVideoDecoderConfig( + media::VideoCodecProfile::H264PROFILE_MIN, + media::VideoCodecProfile::H264PROFILE_MAX, + media::kDefaultSwDecodeSizeMin, + media::kDefaultSwDecodeSizeMax, + true, + false); + +const media::VideoDecoderConfig kH264BaseConfig( + media::VideoCodec::kH264, + media::H264PROFILE_MIN, + media::VideoDecoderConfig::AlphaMode::kIsOpaque, + media::VideoColorSpace(), + media::kNoTransformation, + kCodedSize, + kVisibleRect, + kNaturalSize, + media::EmptyExtraData(), + media::EncryptionScheme::kUnencrypted); + +const media::VideoDecoderConfig kVP9BaseConfig( + media::VideoCodec::kVP9, + media::VP9PROFILE_MIN, + media::VideoDecoderConfig::AlphaMode::kIsOpaque, + media::VideoColorSpace(), + media::kNoTransformation, + kCodedSize, + kVisibleRect, + kNaturalSize, + media::EmptyExtraData(), + media::EncryptionScheme::kUnencrypted); + +} // namespace + +class TestGpuChannelHost : public gpu::GpuChannelHost { + public: + explicit TestGpuChannelHost(gpu::mojom::GpuChannel& gpu_channel) + : GpuChannelHost(0 /* channel_id */, + gpu::GPUInfo(), + gpu::GpuFeatureInfo(), + mojo::ScopedMessagePipeHandle( + mojo::MessagePipeHandle(mojo::kInvalidHandleValue))), + gpu_channel_(gpu_channel) {} + + gpu::mojom::GpuChannel& GetGpuChannel() override { return *gpu_channel_; } + + protected: + ~TestGpuChannelHost() override = default; + const raw_ref<gpu::mojom::GpuChannel> gpu_channel_; +}; + +class MockOverlayInfoCbHandler { + public: + MOCK_METHOD2(Call, void(bool, media::ProvideOverlayInfoCB)); +}; + +class MockContextProviderCommandBuffer + : public viz::ContextProviderCommandBuffer { + public: + MockContextProviderCommandBuffer( + scoped_refptr<gpu::GpuChannelHost> channel, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) + : viz::ContextProviderCommandBuffer( + std::move(channel), + gpu_memory_buffer_manager, + content::kGpuStreamIdDefault, + content::kGpuStreamPriorityDefault, + gpu::kNullSurfaceHandle, + GURL(), + false, + false, + true, + gpu::SharedMemoryLimits(), + gpu::ContextCreationAttribs(), + viz::command_buffer_metrics::ContextType::FOR_TESTING) {} + + MOCK_METHOD(gpu::CommandBufferProxyImpl*, + GetCommandBufferProxy, + (), + (override)); + + // ContextProvider / RasterContextProvider implementation. + MOCK_METHOD(gpu::ContextResult, BindToCurrentSequence, (), (override)); + MOCK_METHOD(gpu::gles2::GLES2Interface*, ContextGL, (), (override)); + MOCK_METHOD(gpu::raster::RasterInterface*, RasterInterface, (), (override)); + MOCK_METHOD(gpu::ContextSupport*, ContextSupport, (), (override)); + MOCK_METHOD(class GrDirectContext*, GrContext, (), (override)); + MOCK_METHOD(gpu::SharedImageInterface*, SharedImageInterface, (), (override)); + MOCK_METHOD(viz::ContextCacheController*, CacheController, (), (override)); + MOCK_METHOD(base::Lock*, GetLock, (), (override)); + MOCK_METHOD(gpu::Capabilities&, ContextCapabilities, (), (const, override)); + MOCK_METHOD(gpu::GpuFeatureInfo&, GetGpuFeatureInfo, (), (const, override)); + MOCK_METHOD(void, AddObserver, (viz::ContextLostObserver*), (override)); + MOCK_METHOD(void, RemoveObserver, (viz::ContextLostObserver*), (override)); + + // base::trace_event::MemoryDumpProvider implementation. + MOCK_METHOD(bool, + OnMemoryDump, + (const base::trace_event::MemoryDumpArgs&, + base::trace_event::ProcessMemoryDump*), + (override)); + + protected: + ~MockContextProviderCommandBuffer() override = default; +}; + +class MockGLESInterface : public gpu::gles2::GLES2InterfaceStub { + public: + MOCK_METHOD(GLenum, GetGraphicsResetStatusKHR, ()); +}; + +class FakeVEAProviderImpl + : public media::mojom::VideoEncodeAcceleratorProvider { + public: + ~FakeVEAProviderImpl() override = default; + + void Bind(mojo::PendingReceiver<media::mojom::VideoEncodeAcceleratorProvider> + receiver) { + receiver_.Bind(std::move(receiver)); + } + + void SetVideoEncodeAcceleratorSupportedProfiles( + std::vector<media::VideoEncodeAccelerator::SupportedProfile> + supported_profile) { + supported_profile_ = supported_profile; + } + // media::mojom::VideoEncodeAcceleratorProvider impl. + void CreateVideoEncodeAccelerator( + mojo::PendingReceiver<media::mojom::VideoEncodeAccelerator> receiver) + override {} + void GetVideoEncodeAcceleratorSupportedProfiles( + GetVideoEncodeAcceleratorSupportedProfilesCallback callback) override { + std::move(callback).Run(supported_profile_); + } + + private: + mojo::Receiver<media::mojom::VideoEncodeAcceleratorProvider> receiver_{this}; + std::vector<media::VideoEncodeAccelerator::SupportedProfile> + supported_profile_; +}; + +#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) +// Client to MojoVideoDecoderService vended by FakeInterfaceFactory. Creates a +// FakeGpuVideoDecoder when requested. +class FakeMojoMediaClient : public media::MojoMediaClient { + public: + void SetSupportedVideoDecoderConfigs( + media::SupportedVideoDecoderConfigs configs) { + supported_video_decoder_configs_ = configs; + } + + // MojoMediaClient implementation. + std::unique_ptr<media::VideoDecoder> CreateVideoDecoder( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + media::MediaLog* media_log, + media::mojom::CommandBufferIdPtr command_buffer_id, + media::RequestOverlayInfoCB request_overlay_info_cb, + const gfx::ColorSpace& target_color_space, + mojo::PendingRemote<media::stable::mojom::StableVideoDecoder> + oop_video_decoder) override { + return std::make_unique<media::FakeVideoDecoder>( + 0 /* decoder_id */, 0 /* decoding_delay */, + 13 /* max_parallel_decoding_requests */, media::BytesDecodedCB()); + } + media::SupportedVideoDecoderConfigs GetSupportedVideoDecoderConfigs() + override { + return supported_video_decoder_configs_; + } + media::VideoDecoderType GetDecoderImplementationType() override { + return media::VideoDecoderType::kTesting; + } + + private: + media::SupportedVideoDecoderConfigs supported_video_decoder_configs_; +}; + +// Other end of remote InterfaceFactory requested by VideoDecoderBroker. Used +// to create our (fake) media::mojom::VideoDecoder. +class FakeInterfaceFactory : public media::mojom::InterfaceFactory { + public: + FakeInterfaceFactory() = default; + ~FakeInterfaceFactory() override = default; + + void Bind(mojo::PendingReceiver<media::mojom::InterfaceFactory> receiver) { + receiver_.Bind(std::move(receiver)); + receiver_.set_disconnect_handler(base::BindOnce( + &FakeInterfaceFactory::OnConnectionError, base::Unretained(this))); + } + + void SetSupportedVideoDecoderConfigs( + media::SupportedVideoDecoderConfigs configs) { + mojo_media_client_.SetSupportedVideoDecoderConfigs(configs); + } + + // Implement this one interface from mojom::InterfaceFactory. Using the real + // MojoVideoDecoderService allows us to reuse buffer conversion code. The + // FakeMojoMediaClient will create a FakeGpuVideoDecoder. + void CreateVideoDecoder( + mojo::PendingReceiver<media::mojom::VideoDecoder> receiver, + mojo::PendingRemote<media::stable::mojom::StableVideoDecoder> + dst_video_decoder) override { + video_decoder_receivers_.Add( + std::make_unique<media::MojoVideoDecoderService>( + &mojo_media_client_, &cdm_service_context_, + mojo::PendingRemote<media::stable::mojom::StableVideoDecoder>()), + std::move(receiver)); + } + + // Stub out other mojom::InterfaceFactory interfaces. + void CreateAudioDecoder( + mojo::PendingReceiver<media::mojom::AudioDecoder> receiver) override {} + void CreateAudioEncoder( + mojo::PendingReceiver<media::mojom::AudioEncoder> receiver) override {} + void CreateDefaultRenderer( + const std::string& audio_device_id, + mojo::PendingReceiver<media::mojom::Renderer> receiver) override {} +#if BUILDFLAG(ENABLE_CAST_RENDERER) + void CreateCastRenderer( + const base::UnguessableToken& overlay_plane_id, + mojo::PendingReceiver<media::mojom::Renderer> receiver) override {} +#endif +#if BUILDFLAG(IS_ANDROID) + void CreateFlingingRenderer( + const std::string& presentation_id, + mojo::PendingRemote<media::mojom::FlingingRendererClientExtension> + client_extension, + mojo::PendingReceiver<media::mojom::Renderer> receiver) override {} + void CreateMediaPlayerRenderer( + mojo::PendingRemote<media::mojom::MediaPlayerRendererClientExtension> + client_extension_remote, + mojo::PendingReceiver<media::mojom::Renderer> receiver, + mojo::PendingReceiver<media::mojom::MediaPlayerRendererExtension> + renderer_extension_receiver) override {} +#endif // BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_WIN) + void CreateMediaFoundationRenderer( + mojo::PendingRemote<media::mojom::MediaLog> media_log_remote, + mojo::PendingReceiver<media::mojom::Renderer> receiver, + mojo::PendingReceiver<media::mojom::MediaFoundationRendererExtension> + renderer_extension_receiver, + mojo::PendingRemote<media::mojom::MediaFoundationRendererClientExtension> + client_extension_remote) override {} +#endif // BUILDFLAG(IS_WIN) + void CreateCdm(const media::CdmConfig& cdm_config, + CreateCdmCallback callback) override {} + + private: + void OnConnectionError() { receiver_.reset(); } + + media::MojoCdmServiceContext cdm_service_context_; + FakeMojoMediaClient mojo_media_client_; + mojo::Receiver<media::mojom::InterfaceFactory> receiver_{this}; + mojo::UniqueReceiverSet<media::mojom::VideoDecoder> video_decoder_receivers_; +}; +#endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) + +#if BUILDFLAG(IS_FUCHSIA) +class FakeFuchsiaMediaCodecProvide + : public media::mojom::FuchsiaMediaCodecProvider { + public: + ~FakeFuchsiaMediaCodecProvide() override = default; + + void Bind( + mojo::PendingReceiver<media::mojom::FuchsiaMediaCodecProvider> receiver) { + receiver_.Bind(std::move(receiver)); + } + + void SetSupportedVideoDecoderConfigs( + media::SupportedVideoDecoderConfigs configs) { + supported_video_decoder_configs_ = configs; + } + + // media::mojom::FuchsiaMediaCodecProvider implementation. + void CreateVideoDecoder( + media::VideoCodec codec, + media::mojom::VideoDecoderSecureMemoryMode secure_mode, + fidl::InterfaceRequest<fuchsia::media::StreamProcessor> + stream_processor_request) final { + ADD_FAILURE() << "Not implemented."; + } + + void GetSupportedVideoDecoderConfigs( + GetSupportedVideoDecoderConfigsCallback callback) final { + std::move(callback).Run(supported_video_decoder_configs_); + } + + private: + media::SupportedVideoDecoderConfigs supported_video_decoder_configs_; + mojo::Receiver<media::mojom::FuchsiaMediaCodecProvider> receiver_{this}; +}; +#endif // BUILDFLAG(IS_FUCHSIA) + +class GpuVideoAcceleratorFactoriesImplTest : public testing::Test { + public: + GpuVideoAcceleratorFactoriesImplTest() + : gpu_channel_host_( + base::MakeRefCounted<TestGpuChannelHost>(mock_gpu_channel_)), + mock_context_provider_( + base::MakeRefCounted<NiceMock<MockContextProviderCommandBuffer>>( + gpu_channel_host_, + &gpu_memory_buffer_manager_)) {} + ~GpuVideoAcceleratorFactoriesImplTest() override = default; + + void SetUp() override { + MockGpuChannel(); + MockContextProvider(); + } + + void TearDown() override { + task_environment_.RunUntilIdle(); + ASSERT_TRUE(testing::Mock::VerifyAndClear(&mock_context_provider_)); + ASSERT_TRUE(testing::Mock::VerifyAndClear(&mock_context_gl_)); + ASSERT_TRUE(testing::Mock::VerifyAndClear(&mock_gpu_channel_)); + delete gpu_command_buffer_proxy_; + mock_context_provider_.reset(); + gpu_channel_host_.reset(); + } + + void MockGpuChannel() { + // Simulate success, since we're not actually talking to the service + // in this test suite. + ON_CALL(mock_gpu_channel_, CreateCommandBuffer(_, _, _, _, _, _, _)) + .WillByDefault(Invoke( + [&](gpu::mojom::CreateCommandBufferParamsPtr params, + int32_t routing_id, base::UnsafeSharedMemoryRegion shared_state, + mojo::PendingAssociatedReceiver<gpu::mojom::CommandBuffer> + receiver, + mojo::PendingAssociatedRemote<gpu::mojom::CommandBufferClient> + client, + gpu::ContextResult* result, + gpu::Capabilities* capabilities) -> bool { + // There's no real GpuChannel pipe for this endpoint to use, so + // associate it with a dedicated pipe for these tests. This + // allows the CommandBufferProxyImpl to make calls on its + // CommandBuffer endpoint. + receiver.EnableUnassociatedUsage(); + *result = gpu::ContextResult::kSuccess; + return true; + })); + } + + void MockContextProvider() { + ON_CALL(*mock_context_provider_, BindToCurrentSequence()) + .WillByDefault(Return(gpu::ContextResult::kSuccess)); + ON_CALL(mock_context_gl_, GetGraphicsResetStatusKHR()) + .WillByDefault(Return(GL_NO_ERROR)); + ON_CALL(*mock_context_provider_, ContextGL()) + .WillByDefault(Return(&mock_context_gl_)); + + gpu_command_buffer_proxy_ = new gpu::CommandBufferProxyImpl( + gpu_channel_host_, &gpu_memory_buffer_manager_, + content::kGpuStreamIdDefault, + task_environment_.GetMainThreadTaskRunner()); + gpu_command_buffer_proxy_->Initialize( + gpu::kNullSurfaceHandle, nullptr, content::kGpuStreamPriorityDefault, + gpu::ContextCreationAttribs(), GURL()); + ON_CALL(*mock_context_provider_, GetCommandBufferProxy()) + .WillByDefault(Return(gpu_command_buffer_proxy_)); + } + + std::unique_ptr<CodecFactory> CreateCodecFactory( + scoped_refptr<viz::ContextProviderCommandBuffer> context_provider, + bool enable_video_decode_accelerator, + bool enable_video_encode_accelerator) { + mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> + vea_provider; + fake_vea_provider_.Bind(vea_provider.InitWithNewPipeAndPassReceiver()); + +#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) + mojo::PendingRemote<media::mojom::InterfaceFactory> interface_factory; + fake_media_codec_provider_.Bind( + interface_factory.InitWithNewPipeAndPassReceiver()); + return std::make_unique<CodecFactoryMojo>( + task_environment_.GetMainThreadTaskRunner(), + std::move(context_provider), enable_video_decode_accelerator, + enable_video_encode_accelerator, std::move(vea_provider), + std::move(interface_factory)); +#elif BUILDFLAG(IS_FUCHSIA) + mojo::PendingRemote<media::mojom::FuchsiaMediaCodecProvider> + media_codec_provider; + fake_media_codec_provider_.Bind( + media_codec_provider.InitWithNewPipeAndPassReceiver()); + return std::make_unique<CodecFactoryFuchsia>( + task_environment_.GetMainThreadTaskRunner(), + std::move(context_provider), enable_video_decode_accelerator, + enable_video_encode_accelerator, std::move(vea_provider), + std::move(media_codec_provider)); +#else + return std::make_unique<CodecFactoryDefault>( + task_environment_.GetMainThreadTaskRunner(), + std::move(context_provider), enable_video_decode_accelerator, + enable_video_encode_accelerator, std::move(vea_provider)); +#endif + } + + std::unique_ptr<GpuVideoAcceleratorFactoriesImpl> + CreateGpuVideoAcceleratorFactories(bool enable_video_decode_accelerator, + bool enable_video_encode_accelerator) { + std::unique_ptr<CodecFactory> codec_factory = CreateCodecFactory( + mock_context_provider_, enable_video_decode_accelerator, + enable_video_encode_accelerator); + auto gpu_factories = GpuVideoAcceleratorFactoriesImpl::CreateForTesting( + gpu_channel_host_, task_environment_.GetMainThreadTaskRunner(), + task_environment_.GetMainThreadTaskRunner(), mock_context_provider_, + std::move(codec_factory), &gpu_memory_buffer_manager_, + true, /* enable_video_gpu_memory_buffers */ + true, /* enable_media_stream_gpu_memory_buffers */ + enable_video_decode_accelerator, enable_video_encode_accelerator); + + // Wait until all async IO messages (e.g. Mojo and FIDL) to be delieved + // and handled. + task_environment_.RunUntilIdle(); + + return gpu_factories; + } + + protected: + base::test::SingleThreadTaskEnvironment task_environment_{ + base::test::SingleThreadTaskEnvironment::MainThreadType::IO}; + + NiceMock<gpu::MockGpuChannel> mock_gpu_channel_; + NiceMock<MockGLESInterface> mock_context_gl_; + viz::TestGpuMemoryBufferManager gpu_memory_buffer_manager_; + scoped_refptr<TestGpuChannelHost> gpu_channel_host_; + scoped_refptr<MockContextProviderCommandBuffer> mock_context_provider_; + gpu::CommandBufferProxyImpl* gpu_command_buffer_proxy_; + + FakeVEAProviderImpl fake_vea_provider_; + +#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) + FakeInterfaceFactory fake_media_codec_provider_; +#elif BUILDFLAG(IS_FUCHSIA) + FakeFuchsiaMediaCodecProvide fake_media_codec_provider_; +#endif +}; + +TEST_F(GpuVideoAcceleratorFactoriesImplTest, VideoDecoderAcceleratorDisabled) { + auto gpu_video_accelerator_factories = + CreateGpuVideoAcceleratorFactories(false, false); + + EXPECT_FALSE( + gpu_video_accelerator_factories->IsGpuVideoDecodeAcceleratorEnabled()); + EXPECT_TRUE(gpu_video_accelerator_factories->IsDecoderSupportKnown()); + EXPECT_EQ(gpu_video_accelerator_factories->IsDecoderConfigSupported( + kH264BaseConfig), + media::GpuVideoAcceleratorFactories::Supported::kFalse); + EXPECT_EQ(gpu_video_accelerator_factories->GetDecoderType(), + media::VideoDecoderType::kUnknown); + + ASSERT_TRUE( + testing::Mock::VerifyAndClearExpectations(&mock_context_provider_)); +} + +TEST_F(GpuVideoAcceleratorFactoriesImplTest, VideoEncoderAcceleratorDisabled) { + auto gpu_video_accelerator_factories = + CreateGpuVideoAcceleratorFactories(false, false); + + EXPECT_FALSE( + gpu_video_accelerator_factories->IsGpuVideoEncodeAcceleratorEnabled()); + EXPECT_TRUE(gpu_video_accelerator_factories->IsEncoderSupportKnown()); +} + +TEST_F(GpuVideoAcceleratorFactoriesImplTest, EncoderConfigsIsSupported) { + fake_vea_provider_.SetVideoEncodeAcceleratorSupportedProfiles( + {media::VideoEncodeAccelerator::SupportedProfile( + media::VideoCodecProfile::VP9PROFILE_MAX, kCodedSize)}); + auto gpu_video_accelerator_factories = + CreateGpuVideoAcceleratorFactories(false, true); + + EXPECT_TRUE( + gpu_video_accelerator_factories->IsGpuVideoEncodeAcceleratorEnabled()); + EXPECT_TRUE(gpu_video_accelerator_factories->IsEncoderSupportKnown()); + base::test::TestFuture<void> future; + gpu_video_accelerator_factories->NotifyEncoderSupportKnown( + future.GetCallback()); + EXPECT_TRUE(future.Wait()); + auto supported_profiles = gpu_video_accelerator_factories + ->GetVideoEncodeAcceleratorSupportedProfiles(); + EXPECT_TRUE(supported_profiles.has_value()); + EXPECT_EQ(supported_profiles->size(), static_cast<size_t>(1)); +} + +TEST_F(GpuVideoAcceleratorFactoriesImplTest, EncoderConfigsIsNotSupported) { + fake_vea_provider_.SetVideoEncodeAcceleratorSupportedProfiles({}); + auto gpu_video_accelerator_factories = + CreateGpuVideoAcceleratorFactories(false, true); + + EXPECT_TRUE( + gpu_video_accelerator_factories->IsGpuVideoEncodeAcceleratorEnabled()); + EXPECT_TRUE(gpu_video_accelerator_factories->IsEncoderSupportKnown()); + base::test::TestFuture<void> future; + gpu_video_accelerator_factories->NotifyEncoderSupportKnown( + future.GetCallback()); + EXPECT_TRUE(future.Wait()); + auto supported_profiles = gpu_video_accelerator_factories + ->GetVideoEncodeAcceleratorSupportedProfiles(); + EXPECT_TRUE(supported_profiles.has_value()); + EXPECT_TRUE(supported_profiles->empty()); +} + +TEST_F(GpuVideoAcceleratorFactoriesImplTest, CreateVideoEncodeAccelerator) { + fake_vea_provider_.SetVideoEncodeAcceleratorSupportedProfiles( + {media::VideoEncodeAccelerator::SupportedProfile( + media::VideoCodecProfile::VP9PROFILE_MAX, kCodedSize)}); + auto gpu_video_accelerator_factories = + CreateGpuVideoAcceleratorFactories(false, true); + + EXPECT_NE(gpu_video_accelerator_factories->CreateVideoEncodeAccelerator(), + nullptr); +} + +#ifdef GTEST_HAS_DEATH_TEST +using GpuVideoAcceleratorFactoriesImplDeathTest = + GpuVideoAcceleratorFactoriesImplTest; + +TEST_F(GpuVideoAcceleratorFactoriesImplDeathTest, + CreateVideoEncodeAcceleratorFailed) { + auto gpu_video_accelerator_factories = + CreateGpuVideoAcceleratorFactories(false, false); + + EXPECT_DCHECK_DEATH({ + EXPECT_EQ(gpu_video_accelerator_factories->CreateVideoEncodeAccelerator(), + nullptr); + }); +} + +TEST_F(GpuVideoAcceleratorFactoriesImplDeathTest, CreateVideoDecoderFailed) { + testing::StrictMock<MockOverlayInfoCbHandler> cb_handler; + media::RequestOverlayInfoCB mock_cb = base::BindRepeating( + &MockOverlayInfoCbHandler::Call, base::Unretained(&cb_handler)); + auto gpu_video_accelerator_factories = + CreateGpuVideoAcceleratorFactories(false, false); + + EXPECT_DCHECK_DEATH({ + EXPECT_EQ(gpu_video_accelerator_factories->CreateVideoDecoder( + nullptr, std::move(mock_cb)), + nullptr); + }); +} +#endif // GTEST_HAS_DEATH_TEST + +#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) || BUILDFLAG(IS_FUCHSIA) +TEST_F(GpuVideoAcceleratorFactoriesImplTest, DecoderConfigIsSupported) { + fake_media_codec_provider_.SetSupportedVideoDecoderConfigs( + {kH264MaxSupportedVideoDecoderConfig}); + + auto gpu_video_accelerator_factories = + CreateGpuVideoAcceleratorFactories(true, false); + + EXPECT_TRUE( + gpu_video_accelerator_factories->IsGpuVideoDecodeAcceleratorEnabled()); + EXPECT_TRUE(gpu_video_accelerator_factories->IsDecoderSupportKnown()); + base::test::TestFuture<void> future; + gpu_video_accelerator_factories->NotifyDecoderSupportKnown( + future.GetCallback()); + EXPECT_TRUE(future.Wait()); + EXPECT_EQ(gpu_video_accelerator_factories->IsDecoderConfigSupported( + kH264BaseConfig), + media::GpuVideoAcceleratorFactories::Supported::kTrue); + EXPECT_NE(gpu_video_accelerator_factories->GetDecoderType(), + media::VideoDecoderType::kUnknown); +} + +TEST_F(GpuVideoAcceleratorFactoriesImplTest, DecoderConfigIsNotSupported) { + fake_media_codec_provider_.SetSupportedVideoDecoderConfigs( + {kH264MaxSupportedVideoDecoderConfig}); + + auto gpu_video_accelerator_factories = + CreateGpuVideoAcceleratorFactories(true, false); + + EXPECT_TRUE( + gpu_video_accelerator_factories->IsGpuVideoDecodeAcceleratorEnabled()); + EXPECT_TRUE(gpu_video_accelerator_factories->IsDecoderSupportKnown()); + base::test::TestFuture<void> future; + gpu_video_accelerator_factories->NotifyDecoderSupportKnown( + future.GetCallback()); + EXPECT_TRUE(future.Wait()); + EXPECT_EQ( + gpu_video_accelerator_factories->IsDecoderConfigSupported(kVP9BaseConfig), + media::GpuVideoAcceleratorFactories::Supported::kFalse); +} + +TEST_F(GpuVideoAcceleratorFactoriesImplTest, CreateVideoDecoder) { + testing::StrictMock<MockOverlayInfoCbHandler> cb_handler; + media::RequestOverlayInfoCB mock_cb = base::BindRepeating( + &MockOverlayInfoCbHandler::Call, base::Unretained(&cb_handler)); + auto gpu_video_accelerator_factories = + CreateGpuVideoAcceleratorFactories(true, false); + + EXPECT_NE(gpu_video_accelerator_factories->CreateVideoDecoder( + nullptr, std::move(mock_cb)), + nullptr); +} +#else +TEST_F(GpuVideoAcceleratorFactoriesImplTest, DefaultCodecFactory) { + auto gpu_video_accelerator_factories = + CreateGpuVideoAcceleratorFactories(false, false); + + EXPECT_FALSE( + gpu_video_accelerator_factories->IsGpuVideoDecodeAcceleratorEnabled()); + EXPECT_TRUE(gpu_video_accelerator_factories->IsDecoderSupportKnown()); + base::test::TestFuture<void> future; + gpu_video_accelerator_factories->NotifyDecoderSupportKnown( + future.GetCallback()); + EXPECT_TRUE(future.Wait()); + EXPECT_EQ(gpu_video_accelerator_factories->IsDecoderConfigSupported( + kH264BaseConfig), + media::GpuVideoAcceleratorFactories::Supported::kFalse); +} +#endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) || BUILDFLAG(IS_FUCHSIA) + +} // namespace content
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 1ab2dbae..8820b82 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -75,6 +75,7 @@ #include "content/common/main_frame_counter.h" #include "content/common/process_visibility_tracker.h" #include "content/common/pseudonymization_salt.h" +#include "content/public/common/content_client.h" #include "content/public/common/content_constants.h" #include "content/public/common/content_features.h" #include "content/public/common/content_paths.h" @@ -87,6 +88,7 @@ #include "content/renderer/agent_scheduling_group.h" #include "content/renderer/browser_exposed_renderer_interfaces.h" #include "content/renderer/effective_connection_type_helper.h" +#include "content/renderer/media/codec_factory.h" #include "content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h" #include "content/renderer/media/media_factory.h" #include "content/renderer/media/render_media_client.h" @@ -120,6 +122,7 @@ #include "media/video/gpu_video_accelerator_factories.h" #include "mojo/public/cpp/bindings/binder_map.h" #include "mojo/public/cpp/bindings/callback_helpers.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "mojo/public/cpp/system/message_pipe.h" #include "net/base/net_errors.h" @@ -201,6 +204,16 @@ #include <malloc.h> #endif +#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) +#include "content/renderer/media/codec_factory_mojo.h" +#include "media/mojo/mojom/interface_factory.mojom.h" +#endif + +#if BUILDFLAG(IS_FUCHSIA) +#include "content/renderer/media/codec_factory_fuchsia.h" +#include "media/fuchsia/mojom/fuchsia_media.mojom.h" +#endif + #if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX) #include "base/test/clang_profiling.h" #endif @@ -1047,7 +1060,6 @@ gpu::kGpuFeatureStatusEnabled); const bool enable_video_encode_accelerator = - #if BUILDFLAG(IS_LINUX) base::FeatureList::IsEnabled(media::kVaapiVideoEncodeLinux) && #else @@ -1076,31 +1088,17 @@ gpu_channel_host->gpu_info().overlay_info.supports_overlays); #endif // BUILDFLAG(IS_WIN) - mojo::PendingRemote<media::mojom::InterfaceFactory> interface_factory; - BindHostReceiver(interface_factory.InitWithNewPipeAndPassReceiver()); - - mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> - vea_provider; - -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) - if (base::FeatureList::IsEnabled(media::kUseOutOfProcessVideoEncoding)) { - BindHostReceiver(vea_provider.InitWithNewPipeAndPassReceiver()); - } else { - gpu_->CreateVideoEncodeAcceleratorProvider( - vea_provider.InitWithNewPipeAndPassReceiver()); - } -#else - gpu_->CreateVideoEncodeAcceleratorProvider( - vea_provider.InitWithNewPipeAndPassReceiver()); -#endif - + auto codec_factory = CreateMediaCodecFactory(media_context_provider, + enable_video_decode_accelerator, + enable_video_encode_accelerator); gpu_factories_.push_back(GpuVideoAcceleratorFactoriesImpl::Create( std::move(gpu_channel_host), base::SingleThreadTaskRunner::GetCurrentDefault(), GetMediaSequencedTaskRunner(), std::move(media_context_provider), - enable_video_gpu_memory_buffers, enable_media_stream_gpu_memory_buffers, - enable_video_decode_accelerator, enable_video_encode_accelerator, - std::move(interface_factory), std::move(vea_provider))); + std::move(codec_factory), enable_video_gpu_memory_buffers, + enable_media_stream_gpu_memory_buffers, enable_video_decode_accelerator, + enable_video_encode_accelerator)); + gpu_factories_.back()->SetRenderingColorSpace(rendering_color_space_); return gpu_factories_.back().get(); } @@ -1839,4 +1837,45 @@ attribution_os_support_ = attribution_os_support; } +std::unique_ptr<CodecFactory> RenderThreadImpl::CreateMediaCodecFactory( + scoped_refptr<viz::ContextProviderCommandBuffer> context_provider, + bool enable_video_decode_accelerator, + bool enable_video_encode_accelerator) { + mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> + vea_provider; +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + if (base::FeatureList::IsEnabled(media::kUseOutOfProcessVideoEncoding)) { + BindHostReceiver(vea_provider.InitWithNewPipeAndPassReceiver()); + } else { + gpu_->CreateVideoEncodeAcceleratorProvider( + vea_provider.InitWithNewPipeAndPassReceiver()); + } +#else + gpu_->CreateVideoEncodeAcceleratorProvider( + vea_provider.InitWithNewPipeAndPassReceiver()); +#endif + +#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) + mojo::PendingRemote<media::mojom::InterfaceFactory> interface_factory; + BindHostReceiver(interface_factory.InitWithNewPipeAndPassReceiver()); + return std::make_unique<CodecFactoryMojo>( + GetMediaSequencedTaskRunner(), context_provider, + enable_video_decode_accelerator, enable_video_encode_accelerator, + std::move(vea_provider), std::move(interface_factory)); +#elif BUILDFLAG(IS_FUCHSIA) + mojo::PendingRemote<media::mojom::FuchsiaMediaCodecProvider> + media_codec_provider; + BindHostReceiver(media_codec_provider.InitWithNewPipeAndPassReceiver()); + return std::make_unique<CodecFactoryFuchsia>( + GetMediaSequencedTaskRunner(), context_provider, + enable_video_decode_accelerator, enable_video_encode_accelerator, + std::move(vea_provider), std::move(media_codec_provider)); +#else + return std::make_unique<CodecFactoryDefault>( + GetMediaSequencedTaskRunner(), context_provider, + enable_video_decode_accelerator, enable_video_encode_accelerator, + std::move(vea_provider)); +#endif +} + } // namespace content
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index d3dc1320..d4cbe57 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -40,6 +40,7 @@ #include "content/common/shared_storage_worklet_service.mojom.h" #include "content/public/renderer/render_thread.h" #include "content/renderer/discardable_memory_utils.h" +#include "content/renderer/media/codec_factory.h" #include "gpu/ipc/client/gpu_channel_host.h" #include "ipc/ipc_sync_channel.h" #include "media/media_buildflags.h" @@ -467,6 +468,11 @@ void OnRendererInterfaceReceiver( mojo::PendingAssociatedReceiver<mojom::Renderer> receiver); + std::unique_ptr<CodecFactory> CreateMediaCodecFactory( + scoped_refptr<viz::ContextProviderCommandBuffer> context_provider, + bool enable_video_decode_accelerator, + bool enable_video_encode_accelerator); + scoped_refptr<discardable_memory::ClientDiscardableSharedMemoryManager> discardable_memory_allocator_;
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 02e3f16..928f2a63 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -2585,6 +2585,7 @@ "../renderer/accessibility/ax_image_stopwords_unittest.cc", "../renderer/content_security_policy_util_unittest.cc", "../renderer/media/batching_media_log_unittest.cc", + "../renderer/media/gpu/gpu_video_accelerator_factories_impl_unittest.cc", "../renderer/media/inspector_media_event_handler_unittest.cc", "../renderer/media/renderer_webaudiodevice_impl_unittest.cc", "../renderer/render_thread_impl_unittest.cc", @@ -2754,6 +2755,7 @@ "//gin", "//gpu", "//gpu:test_support", + "//gpu/ipc/common:test_support", "//gpu/ipc/host", "//gpu/ipc/service", "//ipc:test_support", @@ -2785,6 +2787,7 @@ "//services/video_capture/public/cpp:mocks", "//services/video_capture/public/mojom", "//services/video_capture/public/mojom:constants", + "//services/viz/public/cpp/gpu", "//skia", "//sql", "//sql:test_support",
diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc index 7780b113..b61d6454 100644 --- a/device/fido/get_assertion_request_handler.cc +++ b/device/fido/get_assertion_request_handler.cc
@@ -300,6 +300,19 @@ return specialized_request; } +CtapGetAssertionOptions SpecializeOptionsForAuthenticator( + const CtapGetAssertionOptions& options, + const FidoAuthenticator& authenticator) { + CtapGetAssertionOptions specialized_options(options); + + if (!options.prf_inputs.empty() && + !authenticator.SupportsHMACSecretExtension()) { + specialized_options.prf_inputs.clear(); + } + + return specialized_options; +} + } // namespace GetAssertionRequestHandler::GetAssertionRequestHandler( @@ -408,6 +421,8 @@ CtapGetAssertionRequest request = SpecializeRequestForAuthenticator(request_, *authenticator); + CtapGetAssertionOptions options = + SpecializeOptionsForAuthenticator(options_, *authenticator); PINUVDisposition uv_disposition = authenticator->PINUVDispositionForGetAssertion(request, observer()); switch (uv_disposition) { @@ -443,7 +458,7 @@ CtapGetAssertionRequest request_copy(request); authenticator->GetAssertion( - std::move(request_copy), options_, + std::move(request_copy), std::move(options), base::BindOnce(&GetAssertionRequestHandler::HandleResponse, weak_factory_.GetWeakPtr(), authenticator, std::move(request), base::ElapsedTimer()));
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn index 59ccae6..f8fb263 100644 --- a/extensions/browser/BUILD.gn +++ b/extensions/browser/BUILD.gn
@@ -164,8 +164,6 @@ "api/device_permissions_prompt.h", "api/execute_code_function.cc", "api/execute_code_function.h", - "api/extension_types_utils.cc", - "api/extension_types_utils.h", "api/extensions_api_client.cc", "api/extensions_api_client.h", "api/guest_view/app_view/app_view_guest_internal_api.cc",
diff --git a/extensions/browser/api/execute_code_function.cc b/extensions/browser/api/execute_code_function.cc index 373c2a1..30a4eb4 100644 --- a/extensions/browser/api/execute_code_function.cc +++ b/extensions/browser/api/execute_code_function.cc
@@ -11,7 +11,6 @@ #include "base/bind.h" #include "base/ranges/algorithm.h" -#include "extensions/browser/api/extension_types_utils.h" #include "extensions/browser/extension_api_frame_id_map.h" #include "extensions/browser/extensions_browser_client.h" #include "extensions/browser/load_and_localize_file.h" @@ -20,6 +19,7 @@ #include "extensions/common/extension_resource.h" #include "extensions/common/mojom/css_origin.mojom-shared.h" #include "extensions/common/mojom/run_location.mojom-shared.h" +#include "extensions/common/utils/extension_types_utils.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace {
diff --git a/extensions/browser/extension_registrar.cc b/extensions/browser/extension_registrar.cc index 65975c67..f6b8330 100644 --- a/extensions/browser/extension_registrar.cc +++ b/extensions/browser/extension_registrar.cc
@@ -15,7 +15,6 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/storage_partition.h" -#include "extensions/browser/app_sorting.h" #include "extensions/browser/blocklist_extension_prefs.h" #include "extensions/browser/extension_host.h" #include "extensions/browser/extension_prefs.h" @@ -129,15 +128,6 @@ } else if (extension_prefs_->IsExtensionDisabled(extension->id())) { registry_->AddDisabled(extension); } else { // Extension should be enabled. - // All apps that are displayed in the launcher are ordered by their ordinals - // so we must ensure they have valid ordinals. - if (extension->RequiresSortOrdinal()) { - AppSorting* app_sorting = extension_system_->app_sorting(); - app_sorting->SetExtensionVisible(extension->id(), - extension->ShouldDisplayInNewTabPage()); - app_sorting->EnsureValidOrdinals(extension->id(), - syncer::StringOrdinal()); - } registry_->AddEnabled(extension); ActivateExtension(extension.get(), true); }
diff --git a/extensions/browser/extension_user_script_loader.cc b/extensions/browser/extension_user_script_loader.cc index a50fb50..e3ab1ca 100644 --- a/extensions/browser/extension_user_script_loader.cc +++ b/extensions/browser/extension_user_script_loader.cc
@@ -33,7 +33,6 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/render_process_host.h" -#include "extensions/browser/api/extension_types_utils.h" #include "extensions/browser/api/scripting/scripting_constants.h" #include "extensions/browser/api/scripting/scripting_utils.h" #include "extensions/browser/component_extension_resource_manager.h" @@ -53,6 +52,7 @@ #include "extensions/common/permissions/permissions_data.h" #include "extensions/common/url_pattern_set.h" #include "extensions/common/utils/content_script_utils.h" +#include "extensions/common/utils/extension_types_utils.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/base/resource/resource_bundle.h"
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn index 0317404d..d8084c1 100644 --- a/extensions/common/BUILD.gn +++ b/extensions/common/BUILD.gn
@@ -443,6 +443,8 @@ "utils/base_string.h", "utils/content_script_utils.cc", "utils/content_script_utils.h", + "utils/extension_types_utils.cc", + "utils/extension_types_utils.h", "value_builder.cc", "value_builder.h", "value_counter.cc",
diff --git a/extensions/common/api/content_scripts.idl b/extensions/common/api/content_scripts.idl index 6860728..85636f2 100644 --- a/extensions/common/api/content_scripts.idl +++ b/extensions/common/api/content_scripts.idl
@@ -75,10 +75,8 @@ // Specifies when JavaScript files are injected into the web page. The // preferred and default value is <code>document_idle</code>. RunAt? run_at; - // Describes the JavaScript world that this script will execute in. - // Currently manifest scripts will always run in the isolated world and this - // field should not be specified. Eventually, main world support may be - // added. + // The JavaScript "world" to run the script in. Defaults to + // <code>ISOLATED</code>. Only available in Manifest V3 extensions. [nodoc] extensionTypes.ExecutionWorld? world; };
diff --git a/extensions/common/csp_validator.cc b/extensions/common/csp_validator.cc index 1b472bb8..bc5ccb9 100644 --- a/extensions/common/csp_validator.cc +++ b/extensions/common/csp_validator.cc
@@ -114,8 +114,8 @@ public: // Subframe related directives can have multiple directive names: "child-src" // or "frame-src". - DirectiveStatus(std::initializer_list<const char*> directives) - : directive_names_(directives.begin(), directives.end()) {} + explicit DirectiveStatus(std::vector<std::string> directives) + : directive_names_(std::move(directives)) {} DirectiveStatus(const DirectiveStatus&) = delete; DirectiveStatus(DirectiveStatus&&) = default; @@ -401,9 +401,7 @@ virtual std::string GetDefaultCSPValue(const DirectiveStatus& status) = 0; // List of directives we care about. - // TODO(karandeepb): There is no reason for these to be on the heap. Stack - // allocate. - std::vector<std::unique_ptr<DirectiveStatus>> secure_directives_; + std::vector<DirectiveStatus> secure_directives_; private: const std::string manifest_key_; @@ -424,9 +422,9 @@ for (const auto& directive : directives) { CSPDirectiveToken csp_directive_token(directive); bool matches_enforcing_directive = false; - for (const std::unique_ptr<DirectiveStatus>& status : secure_directives_) { - if (csp_directive_token.MatchAndUpdateStatus( - status.get(), secure_function_, manifest_key_, warnings)) { + for (DirectiveStatus& status : secure_directives_) { + if (csp_directive_token.MatchAndUpdateStatus(&status, secure_function_, + manifest_key_, warnings)) { matches_enforcing_directive = true; break; } @@ -441,8 +439,8 @@ } if (default_src_status.seen_in_policy()) { - for (const std::unique_ptr<DirectiveStatus>& status : secure_directives_) { - if (!status->seen_in_policy()) { + for (const DirectiveStatus& status : secure_directives_) { + if (!status.seen_in_policy()) { // This |status| falls back to "default-src". So warnings from // "default-src" will apply. if (warnings) { @@ -457,16 +455,17 @@ } else { // Did not see "default-src". // Make sure we cover all sources from |secure_directives_|. - for (const std::unique_ptr<DirectiveStatus>& status : secure_directives_) { - if (status->seen_in_policy()) // Already covered. + for (const DirectiveStatus& status : secure_directives_) { + if (status.seen_in_policy()) { // Already covered. continue; - enforced_csp_parts.push_back(GetDefaultCSPValue(*status)); + } + enforced_csp_parts.push_back(GetDefaultCSPValue(status)); if (warnings && show_missing_csp_warnings_) { warnings->push_back( InstallWarning(ErrorUtils::FormatErrorMessage( manifest_errors::kInvalidCSPMissingSecureSrc, - manifest_key_, status->name()), + manifest_key_, status.name()), manifest_key_)); } } @@ -483,9 +482,9 @@ : CSPEnforcer(std::move(manifest_key), true, base::BindRepeating(&GetSecureDirectiveValues, options)) { - secure_directives_.emplace_back(new DirectiveStatus({kScriptSrc})); + secure_directives_.emplace_back(std::vector<std::string>({kScriptSrc})); if (!allow_insecure_object_src) - secure_directives_.emplace_back(new DirectiveStatus({kObjectSrc})); + secure_directives_.emplace_back(std::vector<std::string>({kObjectSrc})); } ExtensionCSPEnforcer(const ExtensionCSPEnforcer&) = delete; @@ -507,8 +506,8 @@ false, base::BindRepeating(&GetAppSandboxSecureDirectiveValues)) { secure_directives_.emplace_back( - new DirectiveStatus({kChildSrc, kFrameSrc})); - secure_directives_.emplace_back(new DirectiveStatus({kScriptSrc})); + std::vector<std::string>({kChildSrc, kFrameSrc})); + secure_directives_.emplace_back(std::vector<std::string>({kScriptSrc})); } AppSandboxPageCSPEnforcer(const AppSandboxPageCSPEnforcer&) = delete;
diff --git a/extensions/common/manifest.cc b/extensions/common/manifest.cc index 8a92ed3..268b293 100644 --- a/extensions/common/manifest.cc +++ b/extensions/common/manifest.cc
@@ -349,15 +349,6 @@ return nullptr; } -bool Manifest::GetDictionary(const std::string& path, - const base::Value** out_value) const { - const base::Value* value = available_values_.FindByDottedPath(path); - if (!value || !value->is_dict()) - return false; - *out_value = value; - return true; -} - bool Manifest::GetList(const std::string& path, const base::Value** out_value) const { const base::Value* value = available_values_.FindByDottedPath(path);
diff --git a/extensions/common/manifest.h b/extensions/common/manifest.h index e2f1655..1ad2b75 100644 --- a/extensions/common/manifest.h +++ b/extensions/common/manifest.h
@@ -176,8 +176,6 @@ const base::Value* FindDictPathAsValue(base::StringPiece path) const; // Deprecated: Use the FindDictPath(asValue) functions instead. - bool GetDictionary(const std::string& path, - const base::Value** out_value) const; bool GetList(const std::string& path, const base::Value** out_value) const; // Returns true if this equals the |other| manifest.
diff --git a/extensions/common/manifest_constants.cc b/extensions/common/manifest_constants.cc index d471313..37ec3c35 100644 --- a/extensions/common/manifest_constants.cc +++ b/extensions/common/manifest_constants.cc
@@ -274,6 +274,9 @@ const char16_t kDefaultStateShouldNotBeSet[] = u"The default_state key cannot be set for browser_action or page_action " "keys."; +const char kExecutionWorldRestrictedToMV3[] = + "The 'world' property is restricted to extensions with 'manifest_version' " + "set to 3 or higher."; const char kExpectString[] = "Expect string value."; const char kFileNotFound[] = "File not found: *."; const char kHasDifferentialFingerprint[] =
diff --git a/extensions/common/manifest_constants.h b/extensions/common/manifest_constants.h index 1115352..3d7cf336 100644 --- a/extensions/common/manifest_constants.h +++ b/extensions/common/manifest_constants.h
@@ -241,6 +241,7 @@ extern const char kDeclarativeNetRequestPermissionNeeded[]; extern const char16_t kDefaultStateShouldNotBeSet[]; extern const char kDevToolsExperimental[]; +extern const char kExecutionWorldRestrictedToMV3[]; extern const char kExpectString[]; extern const char kFileNotFound[]; extern const char kHasDifferentialFingerprint[];
diff --git a/extensions/common/manifest_handlers/content_scripts_handler.cc b/extensions/common/manifest_handlers/content_scripts_handler.cc index fe0b1702..0d6d915 100644 --- a/extensions/common/manifest_handlers/content_scripts_handler.cc +++ b/extensions/common/manifest_handlers/content_scripts_handler.cc
@@ -17,6 +17,7 @@ #include "base/values.h" #include "content/public/common/url_constants.h" #include "extensions/common/api/content_scripts.h" +#include "extensions/common/api/extension_types.h" #include "extensions/common/error_utils.h" #include "extensions/common/extension.h" #include "extensions/common/extension_features.h" @@ -30,6 +31,7 @@ #include "extensions/common/url_pattern.h" #include "extensions/common/url_pattern_set.h" #include "extensions/common/utils/content_script_utils.h" +#include "extensions/common/utils/extension_types_utils.h" #include "extensions/strings/grit/extensions_strings.h" #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" @@ -142,6 +144,17 @@ ParseGlobs(base::OptionalToPtr(content_script.include_globs), base::OptionalToPtr(content_script.exclude_globs), result.get()); + // Parse execution world. This should only be possible for MV3. + if (content_script.world != api::extension_types::EXECUTION_WORLD_NONE) { + if (extension->manifest_version() >= 3) { + result->set_execution_world(ConvertExecutionWorld(content_script.world)); + } else { + extension->AddInstallWarning( + InstallWarning(errors::kExecutionWorldRestrictedToMV3, + ContentScriptsKeys::kContentScripts)); + } + } + if (!script_parsing::ParseFileSources( extension, base::OptionalToPtr(content_script.js), base::OptionalToPtr(content_script.css), definition_index,
diff --git a/extensions/common/manifest_url_handlers.cc b/extensions/common/manifest_url_handlers.cc index 8d2a698b..404c2a9c 100644 --- a/extensions/common/manifest_url_handlers.cc +++ b/extensions/common/manifest_url_handlers.cc
@@ -73,14 +73,6 @@ } // static -bool ManifestURL::UpdatesFromGallery(const base::DictionaryValue* manifest) { - if (const std::string* url = manifest->FindStringKey(keys::kUpdateURL)) { - return extension_urls::IsWebstoreUpdateUrl(GURL(*url)); - } - return false; -} - -// static const GURL& ManifestURL::GetAboutPage(const Extension* extension) { return Get(extension, keys::kAboutPage); }
diff --git a/extensions/common/manifest_url_handlers.h b/extensions/common/manifest_url_handlers.h index b8c6cf0..b3c6ade 100644 --- a/extensions/common/manifest_url_handlers.h +++ b/extensions/common/manifest_url_handlers.h
@@ -11,10 +11,6 @@ #include "extensions/common/extension.h" #include "extensions/common/manifest_handler.h" -namespace base { -class DictionaryValue; -} - namespace extensions { // A structure to hold various URLs like devtools_page, homepage_url, etc @@ -51,7 +47,6 @@ // Returns true if this extension's update URL is the extension gallery. static bool UpdatesFromGallery(const Extension* extension); - static bool UpdatesFromGallery(const base::DictionaryValue* manifest); // Returns the About Page for this extension. static const GURL& GetAboutPage(const Extension* extension);
diff --git a/extensions/common/utils/content_script_utils.cc b/extensions/common/utils/content_script_utils.cc index 558d828fa..c34dce7b 100644 --- a/extensions/common/utils/content_script_utils.cc +++ b/extensions/common/utils/content_script_utils.cc
@@ -56,7 +56,8 @@ InstallWarning script_file_too_large_warning( l10n_util::GetStringFUTF8(IDS_EXTENSION_CONTENT_SCRIPT_FILE_TOO_LARGE, relative_path.LossyDisplayName()), - api::content_scripts::ManifestKeys::kContentScripts); + api::content_scripts::ManifestKeys::kContentScripts, + base::UTF16ToUTF8(relative_path.LossyDisplayName())); if (remaining_length == 0u) { warnings->push_back(std::move(script_file_too_large_warning)); return true;
diff --git a/extensions/browser/api/extension_types_utils.cc b/extensions/common/utils/extension_types_utils.cc similarity index 97% rename from extensions/browser/api/extension_types_utils.cc rename to extensions/common/utils/extension_types_utils.cc index 7efa1e6..42c6b8a7 100644 --- a/extensions/browser/api/extension_types_utils.cc +++ b/extensions/common/utils/extension_types_utils.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "extensions/browser/api/extension_types_utils.h" +#include "extensions/common/utils/extension_types_utils.h" namespace extensions {
diff --git a/extensions/browser/api/extension_types_utils.h b/extensions/common/utils/extension_types_utils.h similarity index 83% rename from extensions/browser/api/extension_types_utils.h rename to extensions/common/utils/extension_types_utils.h index 0263abd..76e0317 100644 --- a/extensions/browser/api/extension_types_utils.h +++ b/extensions/common/utils/extension_types_utils.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef EXTENSIONS_BROWSER_API_EXTENSION_TYPES_UTILS_H_ -#define EXTENSIONS_BROWSER_API_EXTENSION_TYPES_UTILS_H_ +#ifndef EXTENSIONS_COMMON_UTILS_EXTENSION_TYPES_UTILS_H_ +#define EXTENSIONS_COMMON_UTILS_EXTENSION_TYPES_UTILS_H_ #include "extensions/common/api/extension_types.h" #include "extensions/common/mojom/execution_world.mojom-shared.h" @@ -27,4 +27,4 @@ } // namespace extensions -#endif // EXTENSIONS_BROWSER_API_EXTENSION_TYPES_UTILS_H_ +#endif // EXTENSIONS_COMMON_UTILS_EXTENSION_TYPES_UTILS_H_
diff --git a/gpu/GRAPHICS_TEAM_OWNERS b/gpu/GRAPHICS_TEAM_OWNERS index e7987031..8080ca3 100644 --- a/gpu/GRAPHICS_TEAM_OWNERS +++ b/gpu/GRAPHICS_TEAM_OWNERS
@@ -11,11 +11,9 @@ zmo@chromium.org # ANGLE team -capn@chromium.org jmadill@chromium.org jonahr@chromium.org srisser@chromium.org -sugoi@chromium.org syoussefi@chromium.org ynovikov@chromium.org
diff --git a/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm b/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm index 4674acf5..878f5e2 100644 --- a/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm +++ b/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm
@@ -90,9 +90,14 @@ // Test fixture for AppLauncherTabHelper class. class AppLauncherTabHelperTest : public PlatformTest { protected: - AppLauncherTabHelperTest() - : browser_state_(TestChromeBrowserState::Builder().Build()), - abuse_detector_([[FakeAppLauncherAbuseDetector alloc] init]) { + AppLauncherTabHelperTest() { + TestChromeBrowserState::Builder builder; + builder.AddTestingFactory( + ReadingListModelFactory::GetInstance(), + base::BindRepeating(&BuildReadingListModelWithFakeStorage, + std::vector<ReadingListEntry>())); + browser_state_ = builder.Build(); + abuse_detector_ = [[FakeAppLauncherAbuseDetector alloc] init]; AppLauncherTabHelper::CreateForWebState(&web_state_, abuse_detector_); // Allow is the default policy for this test. abuse_detector_.policy = ExternalAppLaunchPolicyAllow; @@ -131,27 +136,11 @@ return policy_decision.ShouldAllowNavigation(); } - // Initialize reading list model and its required tab helpers. - void InitializeReadingListModel() { - TestChromeBrowserState::Builder test_cbs_builder; - chrome_browser_state_ = test_cbs_builder.Build(); - web_state_.SetBrowserState(chrome_browser_state_.get()); - ReadingListModelFactory::GetInstance()->SetTestingFactoryAndUse( - chrome_browser_state_.get(), - base::BindRepeating(&BuildReadingListModelWithFakeStorage, - std::vector<ReadingListEntry>())); - is_reading_list_initialized_ = true; - } - // Returns true if the `expected_read_status` matches the read status for any // non empty source URL based on the transition type and the app policy. bool TestReadingListUpdate(bool is_app_blocked, bool is_link_transition, bool expected_read_status) { - // Make sure reading list model is initialized. - if (!is_reading_list_initialized_) - InitializeReadingListModel(); - web_state_.SetCurrentURL(GURL("https://chromium.org")); GURL pending_url("http://google.com"); navigation_manager_->AddItem(pending_url, ui::PAGE_TRANSITION_LINK); @@ -159,8 +148,8 @@ navigation_manager_->SetPendingItem(item); item->SetOriginalRequestURL(pending_url); - ReadingListModel* model = ReadingListModelFactory::GetForBrowserState( - chrome_browser_state_.get()); + ReadingListModel* model = + ReadingListModelFactory::GetForBrowserState(browser_state_.get()); EXPECT_TRUE(model->DeleteAllEntries()); model->AddOrReplaceEntry(pending_url, "unread", reading_list::ADDED_VIA_CURRENT_APP, @@ -199,11 +188,8 @@ std::unique_ptr<TestChromeBrowserState> browser_state_; web::FakeWebState web_state_; FakeNavigationManager* navigation_manager_ = nullptr; - - std::unique_ptr<TestChromeBrowserState> chrome_browser_state_ = nil; FakeAppLauncherAbuseDetector* abuse_detector_ = nil; FakeAppLauncherTabHelperDelegate delegate_; - bool is_reading_list_initialized_ = false; AppLauncherTabHelper* tab_helper_ = nullptr; };
diff --git a/ios/chrome/browser/autofill/manual_fill/passwords_fetcher_unittest.mm b/ios/chrome/browser/autofill/manual_fill/passwords_fetcher_unittest.mm index 52407db..72c3454e 100644 --- a/ios/chrome/browser/autofill/manual_fill/passwords_fetcher_unittest.mm +++ b/ios/chrome/browser/autofill/manual_fill/passwords_fetcher_unittest.mm
@@ -62,12 +62,12 @@ void SetUp() override { PlatformTest::SetUp(); TestChromeBrowserState::Builder test_cbs_builder; - chrome_browser_state_ = test_cbs_builder.Build(); - IOSChromePasswordStoreFactory::GetInstance()->SetTestingFactory( - chrome_browser_state_.get(), + test_cbs_builder.AddTestingFactory( + IOSChromePasswordStoreFactory::GetInstance(), base::BindRepeating( &password_manager::BuildPasswordStore< web::BrowserState, password_manager::TestPasswordStore>)); + chrome_browser_state_ = test_cbs_builder.Build(); } password_manager::PasswordStoreInterface* GetPasswordStore() {
diff --git a/ios/chrome/browser/download/background_service/background_download_service_test.cc b/ios/chrome/browser/download/background_service/background_download_service_test.cc index 3a41701d..d7f5758 100644 --- a/ios/chrome/browser/download/background_service/background_download_service_test.cc +++ b/ios/chrome/browser/download/background_service/background_download_service_test.cc
@@ -96,6 +96,11 @@ void SetUp() override { download::test::BackgroundDownloadTestBase::SetUp(); TestChromeBrowserState::Builder builder; + builder.AddTestingFactory( + BackgroundDownloadServiceFactory::GetInstance(), + base::BindRepeating( + &BackgroundDownloadServiceTest::MakeBackgroundDowloadService, + base::Unretained(this))); browser_state_ = builder.Build(); // Create a random file in root dir and an unknown file in downoad dir. @@ -108,22 +113,9 @@ ASSERT_TRUE(base::CreateTemporaryFileInDir(download_dir, &temp_file_path_to_delete_)); - // Inject a fake client through SetTestingFactory. - BackgroundDownloadServiceFactory* factory = - BackgroundDownloadServiceFactory::GetInstance(); - factory->SetTestingFactory( - browser_state_.get(), - base::BindLambdaForTesting([&](web::BrowserState* browser_state) { - auto fake_client = std::make_unique<NiceMock<FakeClient>>(); - fake_client_ = fake_client.get(); - auto clients = std::make_unique<download::DownloadClientMap>(); - clients->emplace(download::DownloadClient::TEST, - std::move(fake_client)); - return factory->BuildServiceWithClients(browser_state, - std::move(clients)); - })); service_ = BackgroundDownloadServiceFactory::GetForBrowserState( browser_state_.get()); + ASSERT_TRUE(fake_client_); } // Download a file from embedded test server. Use different `relative_url` for @@ -137,16 +129,34 @@ service_->StartDownload(std::move(params)); } - FakeClient* client() { return fake_client_; } + FakeClient* client() { + DCHECK(fake_client_); + return fake_client_; + } + const base::FilePath& temp_file_path() const { return temp_file_path_; } const base::FilePath& temp_file_path_to_delete() const { return temp_file_path_to_delete_; } + // Factory for BackgroundDownloadService injecting a FakeClient into the + // service. A pointer to the FakeClient object is kept in the test fixture + // instance to allow test cases to manipulate it. + std::unique_ptr<KeyedService> MakeBackgroundDowloadService( + web::BrowserState* browser_state) { + DCHECK(!fake_client_); + auto fake_client = std::make_unique<NiceMock<FakeClient>>(); + fake_client_ = fake_client.get(); + auto clients = std::make_unique<download::DownloadClientMap>(); + clients->emplace(download::DownloadClient::TEST, std::move(fake_client)); + return BackgroundDownloadServiceFactory::GetInstance() + ->BuildServiceWithClients(browser_state, std::move(clients)); + } + private: std::unique_ptr<ChromeBrowserState> browser_state_; download::BackgroundDownloadService* service_; - FakeClient* fake_client_; + FakeClient* fake_client_ = nullptr; base::FilePath temp_file_path_; base::FilePath temp_file_path_to_delete_; };
diff --git a/ios/chrome/browser/infobars/overlays/BUILD.gn b/ios/chrome/browser/infobars/overlays/BUILD.gn index af70a41..3c3a6ac 100644 --- a/ios/chrome/browser/infobars/overlays/BUILD.gn +++ b/ios/chrome/browser/infobars/overlays/BUILD.gn
@@ -20,8 +20,6 @@ "infobar_overlay_request_inserter.mm", "infobar_overlay_tab_helper.h", "infobar_overlay_tab_helper.mm", - "permissions_overlay_tab_helper.h", - "permissions_overlay_tab_helper.mm", "translate_infobar_placeholder_overlay_request_cancel_handler.h", "translate_infobar_placeholder_overlay_request_cancel_handler.mm", "translate_overlay_tab_helper.h", @@ -29,7 +27,6 @@ ] public_deps = [ ":overlay_type" ] deps = [ - ":infobar_delegates", ":util", "//base", "//components/infobars/core", @@ -53,15 +50,6 @@ sources = [ "infobar_overlay_type.h" ] } -source_set("infobar_delegates") { - configs += [ "//build/config/compiler:enable_arc" ] - sources = [ - "permissions_overlay_infobar_delegate.h", - "permissions_overlay_infobar_delegate.mm", - ] - deps = [ "//components/infobars/core" ] -} - source_set("util") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ @@ -108,7 +96,6 @@ "infobar_overlay_request_inserter_unittest.mm", "infobar_overlay_tab_helper_unittest.mm", "infobar_overlay_util_unittest.mm", - "permissions_overlay_tab_helper_unittest.mm", "translate_infobar_placeholder_overlay_request_cancel_handler_unittest.mm", "translate_overlay_tab_helper_unittest.mm", ] @@ -116,7 +103,6 @@ ":overlays", ":test_support", ":util", - "//base", "//base/test:test_support", "//components/password_manager/core/browser:test_support", "//components/sync_preferences:test_support", @@ -125,7 +111,6 @@ "//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/infobars", "//ios/chrome/browser/infobars:public", - "//ios/chrome/browser/infobars/overlays:infobar_delegates", "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test", "//ios/chrome/browser/infobars/test", "//ios/chrome/browser/main:test_support", @@ -142,8 +127,6 @@ "//ios/chrome/browser/ui/infobars/test", "//ios/chrome/browser/web_state_list", "//ios/chrome/test:test_support", - "//ios/web/common", - "//ios/web/public/permissions", "//ios/web/public/test", "//ios/web/public/test/fakes", "//testing/gtest",
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/BUILD.gn b/ios/chrome/browser/overlays/public/infobar_banner/BUILD.gn index a3201b1..b399b21c 100644 --- a/ios/chrome/browser/overlays/public/infobar_banner/BUILD.gn +++ b/ios/chrome/browser/overlays/public/infobar_banner/BUILD.gn
@@ -37,12 +37,12 @@ "//components/translate/core/browser", "//ios/chrome/app/strings", "//ios/chrome/browser/infobars", - "//ios/chrome/browser/infobars/overlays:infobar_delegates", "//ios/chrome/browser/infobars/overlays:overlay_type", "//ios/chrome/browser/overlays", "//ios/chrome/browser/overlays/public/common", "//ios/chrome/browser/overlays/public/common/infobars", "//ios/chrome/browser/passwords:infobar_delegates", + "//ios/chrome/browser/permissions:infobar_delegate", "//ios/chrome/browser/safe_browsing/tailored_security:infobar_delegates", "//ios/chrome/browser/ui/authentication", "//ios/chrome/browser/ui/resources:legacy_password_key",
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/permissions_infobar_banner_overlay_request_config.mm b/ios/chrome/browser/overlays/public/infobar_banner/permissions_infobar_banner_overlay_request_config.mm index 32f6c5c0..ce4f4cb7 100644 --- a/ios/chrome/browser/overlays/public/infobar_banner/permissions_infobar_banner_overlay_request_config.mm +++ b/ios/chrome/browser/overlays/public/infobar_banner/permissions_infobar_banner_overlay_request_config.mm
@@ -8,8 +8,8 @@ #import "components/infobars/core/infobar.h" #import "ios/chrome/browser/infobars/infobar_ios.h" #import "ios/chrome/browser/infobars/overlays/infobar_overlay_type.h" -#import "ios/chrome/browser/infobars/overlays/permissions_overlay_infobar_delegate.h" #import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h" +#import "ios/chrome/browser/permissions/permissions_infobar_delegate.h" #import "ios/chrome/grit/ios_strings.h" #import "ios/web/public/permissions/permissions.h" #import "ui/base/l10n/l10n_util.h" @@ -26,8 +26,8 @@ PermissionsBannerRequestConfig::PermissionsBannerRequestConfig(InfoBar* infobar) : infobar_(infobar) { DCHECK(infobar_); - PermissionsOverlayInfobarDelegate* delegate = - static_cast<PermissionsOverlayInfobarDelegate*>(infobar_->delegate()); + PermissionsInfobarDelegate* delegate = + static_cast<PermissionsInfobarDelegate*>(infobar_->delegate()); NSArray<NSNumber*>* accessible_permissions = delegate->GetMostRecentlyAccessiblePermissions(); if ([accessible_permissions containsObject:@(web::PermissionCamera)]) {
diff --git a/ios/chrome/browser/overlays/public/infobar_modal/permissions/BUILD.gn b/ios/chrome/browser/overlays/public/infobar_modal/permissions/BUILD.gn index 0b17686..4c8e098 100644 --- a/ios/chrome/browser/overlays/public/infobar_modal/permissions/BUILD.gn +++ b/ios/chrome/browser/overlays/public/infobar_modal/permissions/BUILD.gn
@@ -14,9 +14,9 @@ "//base", "//ios/chrome/app/strings", "//ios/chrome/browser/infobars", - "//ios/chrome/browser/infobars/overlays:infobar_delegates", "//ios/chrome/browser/overlays", "//ios/chrome/browser/overlays/public/common/infobars", + "//ios/chrome/browser/permissions:infobar_delegate", "//ios/chrome/browser/web", "//ios/web/public", "//ui/base",
diff --git a/ios/chrome/browser/overlays/public/infobar_modal/permissions/permissions_modal_overlay_request_config.mm b/ios/chrome/browser/overlays/public/infobar_modal/permissions/permissions_modal_overlay_request_config.mm index 7a9aad7..b3eddf79 100644 --- a/ios/chrome/browser/overlays/public/infobar_modal/permissions/permissions_modal_overlay_request_config.mm +++ b/ios/chrome/browser/overlays/public/infobar_modal/permissions/permissions_modal_overlay_request_config.mm
@@ -7,8 +7,8 @@ #import "base/strings/sys_string_conversions.h" #import "base/strings/utf_string_conversions.h" #import "ios/chrome/browser/infobars/infobar_ios.h" -#import "ios/chrome/browser/infobars/overlays/permissions_overlay_infobar_delegate.h" #import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h" +#import "ios/chrome/browser/permissions/permissions_infobar_delegate.h" #import "ios/chrome/grit/ios_strings.h" #import "ios/web/public/navigation/navigation_item.h" #import "ios/web/public/navigation/navigation_manager.h" @@ -25,8 +25,8 @@ PermissionsInfobarModalOverlayRequestConfig(InfoBarIOS* infobar) : infobar_(infobar) { DCHECK(infobar_); - PermissionsOverlayInfobarDelegate* delegate = - static_cast<PermissionsOverlayInfobarDelegate*>(infobar_->delegate()); + PermissionsInfobarDelegate* delegate = + static_cast<PermissionsInfobarDelegate*>(infobar_->delegate()); web_state_ = delegate->GetWebState(); web::NavigationItem* visible_item =
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm b/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm index e8b6253..139e11af 100644 --- a/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm +++ b/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm
@@ -18,6 +18,7 @@ #import "base/test/bind.h" #import "base/test/scoped_feature_list.h" #import "base/time/time.h" +#import "components/keyed_service/core/service_access_type.h" #import "components/password_manager/core/browser/bulk_leak_check_service.h" #import "components/password_manager/core/browser/mock_bulk_leak_check_service.h" #import "components/password_manager/core/browser/password_form.h" @@ -74,26 +75,9 @@ (override)); }; -scoped_refptr<TestPasswordStore> CreateAndUseTestPasswordStore( - ChromeBrowserState* _browserState) { - return base::WrapRefCounted(static_cast<password_manager::TestPasswordStore*>( - IOSChromePasswordStoreFactory::GetInstance() - ->SetTestingFactoryAndUse( - _browserState, - base::BindRepeating(&password_manager::BuildPasswordStore< - web::BrowserState, TestPasswordStore>)) - .get())); -} - -MockBulkLeakCheckService* CreateAndUseBulkLeakCheckService( - ChromeBrowserState* _browserState) { - return static_cast<MockBulkLeakCheckService*>( - IOSChromeBulkLeakCheckServiceFactory::GetInstance() - ->SetTestingFactoryAndUse( - _browserState, base::BindLambdaForTesting([](web::BrowserState*) { - return std::unique_ptr<KeyedService>( - std::make_unique<MockBulkLeakCheckService>()); - }))); +std::unique_ptr<KeyedService> MakeMockPasswordCheckManagerObserver( + web::BrowserState*) { + return std::make_unique<MockBulkLeakCheckService>(); } PasswordForm MakeSavedPassword( @@ -127,11 +111,25 @@ class IOSChromePasswordCheckManagerTest : public PlatformTest { public: - IOSChromePasswordCheckManagerTest() - : browser_state_(TestChromeBrowserState::Builder().Build()), - bulk_leak_check_service_( - CreateAndUseBulkLeakCheckService(browser_state_.get())), - store_(CreateAndUseTestPasswordStore(browser_state_.get())) { + IOSChromePasswordCheckManagerTest() { + TestChromeBrowserState::Builder builder; + builder.AddTestingFactory( + IOSChromeBulkLeakCheckServiceFactory::GetInstance(), + base::BindRepeating(&MakeMockPasswordCheckManagerObserver)); + builder.AddTestingFactory( + IOSChromePasswordStoreFactory::GetInstance(), + base::BindRepeating( + &password_manager::BuildPasswordStore<web::BrowserState, + TestPasswordStore>)); + browser_state_ = builder.Build(); + bulk_leak_check_service_ = static_cast<MockBulkLeakCheckService*>( + IOSChromeBulkLeakCheckServiceFactory::GetForBrowserState( + browser_state_.get())); + store_ = + base::WrapRefCounted(static_cast<password_manager::TestPasswordStore*>( + IOSChromePasswordStoreFactory::GetForBrowserState( + browser_state_.get(), ServiceAccessType::EXPLICIT_ACCESS) + .get())); manager_ = IOSChromePasswordCheckManagerFactory::GetForBrowserState( browser_state_.get()); }
diff --git a/ios/chrome/browser/passwords/well_known_change_password_tab_helper_unittest.mm b/ios/chrome/browser/passwords/well_known_change_password_tab_helper_unittest.mm index 5157e046..438b5ba 100644 --- a/ios/chrome/browser/passwords/well_known_change_password_tab_helper_unittest.mm +++ b/ios/chrome/browser/passwords/well_known_change_password_tab_helper_unittest.mm
@@ -70,6 +70,10 @@ navigation_manager->LoadURLWithParams(params); } +std::unique_ptr<KeyedService> MakeMockAffiliationService(web::BrowserState*) { + return std::make_unique<NiceMock<password_manager::MockAffiliationService>>(); +} + } // namespace // This test uses a mockserver to simulate different response. To handle the @@ -85,7 +89,10 @@ &WellKnownChangePasswordTabHelperTest::HandleRequest, base::Unretained(this))); - browser_state_ = TestChromeBrowserState::Builder().Build(); + TestChromeBrowserState::Builder builder; + builder.AddTestingFactory(IOSChromeAffiliationServiceFactory::GetInstance(), + base::BindRepeating(&MakeMockAffiliationService)); + browser_state_ = builder.Build(); web::WebState::CreateParams params(browser_state_.get()); web_state_ = web::WebState::Create(params); @@ -100,14 +107,8 @@ affiliation_service_ = static_cast<password_manager::MockAffiliationService*>( - IOSChromeAffiliationServiceFactory::GetInstance() - ->SetTestingFactoryAndUse( - web_state()->GetBrowserState(), - base::BindRepeating([](web::BrowserState* browser_state) { - return std::unique_ptr<KeyedService>( - std::make_unique<NiceMock< - password_manager::MockAffiliationService>>()); - }))); + IOSChromeAffiliationServiceFactory::GetForBrowserState( + browser_state_.get())); web_state()->SetDelegate(&delegate_); password_manager::WellKnownChangePasswordTabHelper::CreateForWebState(
diff --git a/ios/chrome/browser/permissions/BUILD.gn b/ios/chrome/browser/permissions/BUILD.gn new file mode 100644 index 0000000..cb5b671f --- /dev/null +++ b/ios/chrome/browser/permissions/BUILD.gn
@@ -0,0 +1,57 @@ +# Copyright 2022 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("infobar_delegate") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "permissions_infobar_delegate.h", + "permissions_infobar_delegate.mm", + ] + deps = [ "//components/infobars/core" ] +} + +source_set("tab_helper") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "permissions_tab_helper.h", + "permissions_tab_helper.mm", + ] + deps = [ + ":infobar_delegate", + "//components/infobars/core", + "//ios/chrome/browser/infobars", + "//ios/chrome/browser/infobars/overlays", + "//ios/chrome/browser/infobars/overlays:util", + "//ios/chrome/browser/overlays", + "//ios/chrome/browser/overlays/public/common/infobars", + "//ios/chrome/browser/overlays/public/infobar_banner", + "//ios/chrome/browser/overlays/public/infobar_modal/permissions", + "//ios/web/common", + "//ios/web/public", + "//ios/web/public/permissions", + ] +} + +source_set("unit_tests") { + configs += [ "//build/config/compiler:enable_arc" ] + testonly = true + sources = [ "permissions_tab_helper_unittest.mm" ] + deps = [ + ":infobar_delegate", + ":tab_helper", + "//base", + "//base/test:test_support", + "//ios/chrome/browser/infobars", + "//ios/chrome/browser/infobars/overlays", + "//ios/chrome/browser/permissions:infobar_delegate", + "//ios/chrome/test:test_support", + "//ios/web/common", + "//ios/web/common", + "//ios/web/public/permissions", + "//ios/web/public/permissions", + "//ios/web/public/test", + "//ios/web/public/test/fakes", + "//testing/gtest", + ] +}
diff --git a/ios/chrome/browser/infobars/overlays/permissions_overlay_infobar_delegate.h b/ios/chrome/browser/permissions/permissions_infobar_delegate.h similarity index 70% rename from ios/chrome/browser/infobars/overlays/permissions_overlay_infobar_delegate.h rename to ios/chrome/browser/permissions/permissions_infobar_delegate.h index 049e4e4..5e9fe6a20 100644 --- a/ios/chrome/browser/infobars/overlays/permissions_overlay_infobar_delegate.h +++ b/ios/chrome/browser/permissions/permissions_infobar_delegate.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_PERMISSIONS_OVERLAY_INFOBAR_DELEGATE_H_ -#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_PERMISSIONS_OVERLAY_INFOBAR_DELEGATE_H_ +#ifndef IOS_CHROME_BROWSER_PERMISSIONS_PERMISSIONS_INFOBAR_DELEGATE_H_ +#define IOS_CHROME_BROWSER_PERMISSIONS_PERMISSIONS_INFOBAR_DELEGATE_H_ #import <Foundation/Foundation.h> #include "components/infobars/core/confirm_infobar_delegate.h" @@ -14,13 +14,13 @@ // An interface derived from ConfirmInfoBarDelegate implemented by objects // wishing to a PermissionsInfoBar. -class PermissionsOverlayInfobarDelegate : public ConfirmInfoBarDelegate { +class PermissionsInfobarDelegate : public ConfirmInfoBarDelegate { public: - PermissionsOverlayInfobarDelegate( + PermissionsInfobarDelegate( NSArray<NSNumber*>* recently_accessible_permissions, web::WebState* web_state); - ~PermissionsOverlayInfobarDelegate() override; + ~PermissionsInfobarDelegate() override; // ConfirmInfoBarDelegate implementation. std::u16string GetMessageText() const override; @@ -39,4 +39,4 @@ web::WebState* web_state_; }; -#endif // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_PERMISSIONS_OVERLAY_INFOBAR_DELEGATE_H_ +#endif // IOS_CHROME_BROWSER_PERMISSIONS_PERMISSIONS_INFOBAR_DELEGATE_H_
diff --git a/ios/chrome/browser/infobars/overlays/permissions_overlay_infobar_delegate.mm b/ios/chrome/browser/permissions/permissions_infobar_delegate.mm similarity index 61% rename from ios/chrome/browser/infobars/overlays/permissions_overlay_infobar_delegate.mm rename to ios/chrome/browser/permissions/permissions_infobar_delegate.mm index ab73175..d5b6f102 100644 --- a/ios/chrome/browser/infobars/overlays/permissions_overlay_infobar_delegate.mm +++ b/ios/chrome/browser/permissions/permissions_infobar_delegate.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/infobars/overlays/permissions_overlay_infobar_delegate.h" +#import "ios/chrome/browser/permissions/permissions_infobar_delegate.h" #import "components/infobars/core/infobar_delegate.h" @@ -10,31 +10,30 @@ #error "This file requires ARC support." #endif -PermissionsOverlayInfobarDelegate::PermissionsOverlayInfobarDelegate( +PermissionsInfobarDelegate::PermissionsInfobarDelegate( NSArray<NSNumber*>* recently_accessible_permissions, web::WebState* web_state) : recently_accessible_permissions_(recently_accessible_permissions), web_state_(web_state) {} -PermissionsOverlayInfobarDelegate::~PermissionsOverlayInfobarDelegate() = - default; +PermissionsInfobarDelegate::~PermissionsInfobarDelegate() = default; NSArray<NSNumber*>* -PermissionsOverlayInfobarDelegate::GetMostRecentlyAccessiblePermissions() { +PermissionsInfobarDelegate::GetMostRecentlyAccessiblePermissions() { return recently_accessible_permissions_; } // As we don't need message in the infobar, we return empty message to satisfy // implementation requirement for ConfirmInfoBarDelegate. -std::u16string PermissionsOverlayInfobarDelegate::GetMessageText() const { +std::u16string PermissionsInfobarDelegate::GetMessageText() const { return std::u16string(); } -web::WebState* PermissionsOverlayInfobarDelegate::GetWebState() const { +web::WebState* PermissionsInfobarDelegate::GetWebState() const { return web_state_; } infobars::InfoBarDelegate::InfoBarIdentifier -PermissionsOverlayInfobarDelegate::GetIdentifier() const { +PermissionsInfobarDelegate::GetIdentifier() const { return IOS_PERMISSIONS_INFOBAR_DELEGATE; }
diff --git a/ios/chrome/browser/infobars/overlays/permissions_overlay_tab_helper.h b/ios/chrome/browser/permissions/permissions_tab_helper.h similarity index 78% rename from ios/chrome/browser/infobars/overlays/permissions_overlay_tab_helper.h rename to ios/chrome/browser/permissions/permissions_tab_helper.h index 359a9410..53104da7 100644 --- a/ios/chrome/browser/infobars/overlays/permissions_overlay_tab_helper.h +++ b/ios/chrome/browser/permissions/permissions_tab_helper.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_PERMISSIONS_OVERLAY_TAB_HELPER_H_ -#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_PERMISSIONS_OVERLAY_TAB_HELPER_H_ +#ifndef IOS_CHROME_BROWSER_PERMISSIONS_PERMISSIONS_TAB_HELPER_H_ +#define IOS_CHROME_BROWSER_PERMISSIONS_PERMISSIONS_TAB_HELPER_H_ #import <Foundation/Foundation.h> @@ -24,17 +24,16 @@ // Tab helper that observes changes to web permissions and creates/replaces the // respective infobar accordingly. -class PermissionsOverlayTabHelper +class PermissionsTabHelper : public infobars::InfoBarManager::Observer, public web::WebStateObserver, - public web::WebStateUserData<PermissionsOverlayTabHelper> { + public web::WebStateUserData<PermissionsTabHelper> { public: - explicit PermissionsOverlayTabHelper(web::WebState* web_state); + explicit PermissionsTabHelper(web::WebState* web_state); - PermissionsOverlayTabHelper(const PermissionsOverlayTabHelper&) = delete; - PermissionsOverlayTabHelper& operator=(const PermissionsOverlayTabHelper&) = - delete; - ~PermissionsOverlayTabHelper() override; + PermissionsTabHelper(const PermissionsTabHelper&) = delete; + PermissionsTabHelper& operator=(const PermissionsTabHelper&) = delete; + ~PermissionsTabHelper() override; // web::WebStateObserver implementation. void PermissionStateChanged(web::WebState* web_state, @@ -47,7 +46,7 @@ void OnManagerShuttingDown(infobars::InfoBarManager* manager) override; private: - friend class web::WebStateUserData<PermissionsOverlayTabHelper>; + friend class web::WebStateUserData<PermissionsTabHelper>; // Adds/replaces the infobar and show the banner. void ShowInfoBar(); @@ -86,4 +85,4 @@ WEB_STATE_USER_DATA_KEY_DECL(); }; -#endif // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_PERMISSIONS_OVERLAY_TAB_HELPER_H_ +#endif // IOS_CHROME_BROWSER_PERMISSIONS_PERMISSIONS_TAB_HELPER_H_
diff --git a/ios/chrome/browser/infobars/overlays/permissions_overlay_tab_helper.mm b/ios/chrome/browser/permissions/permissions_tab_helper.mm similarity index 81% rename from ios/chrome/browser/infobars/overlays/permissions_overlay_tab_helper.mm rename to ios/chrome/browser/permissions/permissions_tab_helper.mm index 3ebc996..d57cab9 100644 --- a/ios/chrome/browser/infobars/overlays/permissions_overlay_tab_helper.mm +++ b/ios/chrome/browser/permissions/permissions_tab_helper.mm
@@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/infobars/overlays/permissions_overlay_tab_helper.h" +#import "ios/chrome/browser/permissions/permissions_tab_helper.h" #import "base/timer/timer.h" #import "ios/chrome/browser/infobars/infobar_ios.h" #import "ios/chrome/browser/infobars/infobar_manager_impl.h" #import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h" #import "ios/chrome/browser/infobars/overlays/infobar_overlay_util.h" -#import "ios/chrome/browser/infobars/overlays/permissions_overlay_infobar_delegate.h" #import "ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_placeholder_request_config.h" #import "ios/chrome/browser/overlays/public/overlay_request_queue.h" #import "ios/chrome/browser/overlays/public/overlay_request_queue_util.h" +#import "ios/chrome/browser/permissions/permissions_infobar_delegate.h" #import "ios/web/common/features.h" #import "ios/web/public/permissions/permissions.h" @@ -24,8 +24,7 @@ const float kTimeoutInMillisecond = 250; } // namespace -PermissionsOverlayTabHelper::PermissionsOverlayTabHelper( - web::WebState* web_state) +PermissionsTabHelper::PermissionsTabHelper(web::WebState* web_state) : web_state_(web_state) { if (@available(iOS 15.0, *)) { if (web::features::IsMediaPermissionsControlEnabled()) { @@ -40,11 +39,10 @@ } } -PermissionsOverlayTabHelper::~PermissionsOverlayTabHelper() {} +PermissionsTabHelper::~PermissionsTabHelper() {} -void PermissionsOverlayTabHelper::PermissionStateChanged( - web::WebState* web_state, - web::Permission permission) { +void PermissionsTabHelper::PermissionStateChanged(web::WebState* web_state, + web::Permission permission) { DCHECK_EQ(web_state_, web_state); web::PermissionState new_state = web_state_->GetStateForPermission(permission); @@ -79,7 +77,7 @@ if (!timer_.IsRunning()) { recently_accessible_permissions_ = [NSMutableArray array]; timer_.Start(FROM_HERE, base::Milliseconds(kTimeoutInMillisecond), this, - &PermissionsOverlayTabHelper::ShowInfoBar); + &PermissionsTabHelper::ShowInfoBar); } [recently_accessible_permissions_ addObject:@(permission)]; } @@ -89,7 +87,7 @@ } } -void PermissionsOverlayTabHelper::WebStateDestroyed(web::WebState* web_state) { +void PermissionsTabHelper::WebStateDestroyed(web::WebState* web_state) { DCHECK_EQ(web_state_, web_state); DCHECK(banner_queue_); if (web::features::IsMediaPermissionsControlEnabled()) { @@ -100,29 +98,29 @@ inserter_ = nullptr; } -void PermissionsOverlayTabHelper::OnInfoBarRemoved(infobars::InfoBar* infobar, - bool animate) { +void PermissionsTabHelper::OnInfoBarRemoved(infobars::InfoBar* infobar, + bool animate) { if (infobar == infobar_) { infobar_manager_scoped_observation_.Reset(); infobar_ = nullptr; } } -void PermissionsOverlayTabHelper::OnManagerShuttingDown( +void PermissionsTabHelper::OnManagerShuttingDown( infobars::InfoBarManager* manager) { DCHECK(infobar_manager_scoped_observation_.IsObservingSource(manager)); infobar_manager_scoped_observation_.Reset(); } -void PermissionsOverlayTabHelper::ShowInfoBar() { +void PermissionsTabHelper::ShowInfoBar() { infobars::InfoBarManager* infobar_manager = InfoBarManagerImpl::FromWebState(web_state_); if (!infobar_manager_scoped_observation_.IsObservingSource(infobar_manager)) { infobar_manager_scoped_observation_.Observe(infobar_manager); } - std::unique_ptr<PermissionsOverlayInfobarDelegate> delegate( - std::make_unique<PermissionsOverlayInfobarDelegate>( + std::unique_ptr<PermissionsInfobarDelegate> delegate( + std::make_unique<PermissionsInfobarDelegate>( recently_accessible_permissions_, web_state_)); BOOL first_activation = infobar_ == nullptr; @@ -137,8 +135,9 @@ size_t index = 0; bool request_found = GetInfobarOverlayRequestIndex( banner_queue_, static_cast<InfoBarIOS*>(infobar_), &index); - if (request_found) // The new banner is already shown. + if (request_found) { // The new banner is already shown. return; + } InsertParams params(static_cast<InfoBarIOS*>(infobar_)); params.overlay_type = InfobarOverlayType::kBanner; params.insertion_index = banner_queue_->size(); @@ -147,7 +146,7 @@ } } -void PermissionsOverlayTabHelper::UpdateIsInfoBarAccepted() { +void PermissionsTabHelper::UpdateIsInfoBarAccepted() { if (infobar_ == nullptr) { return; } @@ -163,4 +162,4 @@ static_cast<InfoBarIOS*>(infobar_)->set_accepted(accepted); } -WEB_STATE_USER_DATA_KEY_IMPL(PermissionsOverlayTabHelper) +WEB_STATE_USER_DATA_KEY_IMPL(PermissionsTabHelper)
diff --git a/ios/chrome/browser/infobars/overlays/permissions_overlay_tab_helper_unittest.mm b/ios/chrome/browser/permissions/permissions_tab_helper_unittest.mm similarity index 92% rename from ios/chrome/browser/infobars/overlays/permissions_overlay_tab_helper_unittest.mm rename to ios/chrome/browser/permissions/permissions_tab_helper_unittest.mm index 4fcb7a9..691f386 100644 --- a/ios/chrome/browser/infobars/overlays/permissions_overlay_tab_helper_unittest.mm +++ b/ios/chrome/browser/permissions/permissions_tab_helper_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/infobars/overlays/permissions_overlay_tab_helper.h" +#import "ios/chrome/browser/permissions/permissions_tab_helper.h" #import "base/test/scoped_feature_list.h" #import "base/test/task_environment.h" @@ -13,7 +13,7 @@ #import "ios/chrome/browser/infobars/infobar_manager_impl.h" #import "ios/chrome/browser/infobars/overlays/default_infobar_overlay_request_factory.h" #import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h" -#import "ios/chrome/browser/infobars/overlays/permissions_overlay_infobar_delegate.h" +#import "ios/chrome/browser/permissions/permissions_infobar_delegate.h" #import "ios/web/common/features.h" #import "ios/web/public/permissions/permissions.h" #import "ios/web/public/test/fakes/fake_navigation_manager.h" @@ -29,10 +29,10 @@ constexpr base::TimeDelta kTimeoutDelay = base::Milliseconds(251); } // namespace -// Test fixture for PermissionsOverlayTabHelper. -class PermissionsOverlayTabHelperTest : public PlatformTest { +// Test fixture for PermissionsTabHelper. +class PermissionsTabHelperTest : public PlatformTest { public: - PermissionsOverlayTabHelperTest() + PermissionsTabHelperTest() : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) { scoped_feature_list_.InitWithFeatures( {web::features::kMediaPermissionsControl}, {}); @@ -42,14 +42,13 @@ InfoBarManagerImpl::CreateForWebState(&web_state_); InfobarOverlayRequestInserter::CreateForWebState( &web_state_, &DefaultInfobarOverlayRequestFactory); - PermissionsOverlayTabHelper::CreateForWebState(&web_state_); + PermissionsTabHelper::CreateForWebState(&web_state_); } - ~PermissionsOverlayTabHelperTest() override { + ~PermissionsTabHelperTest() override { InfoBarManagerImpl::FromWebState(&web_state_)->ShutDown(); // Observer should be removed before `scoped_feature_list_` is reset. - web_state_.RemoveObserver( - PermissionsOverlayTabHelper::FromWebState(&web_state_)); + web_state_.RemoveObserver(PermissionsTabHelper::FromWebState(&web_state_)); } protected: @@ -68,10 +67,11 @@ // Returns recently_accessible_permissions determined by the tab helper. NSArray<NSNumber*>* recently_accessible_permissions() { - if (infobar() == nullptr) + if (infobar() == nullptr) { return [NSArray array]; - PermissionsOverlayInfobarDelegate* delegate = - static_cast<PermissionsOverlayInfobarDelegate*>(infobar()->delegate()); + } + PermissionsInfobarDelegate* delegate = + static_cast<PermissionsInfobarDelegate*>(infobar()->delegate()); return delegate->GetMostRecentlyAccessiblePermissions(); } @@ -82,7 +82,7 @@ // Tests that an infobar is setup with the correct acceptance state when the // status of a single permission changes. -TEST_F(PermissionsOverlayTabHelperTest, CheckInfobarCountForSinglePermission) { +TEST_F(PermissionsTabHelperTest, CheckInfobarCountForSinglePermission) { if (@available(iOS 15, *)) { // Allowed permission. web_state_.SetStateForPermission(web::PermissionStateAllowed, @@ -109,7 +109,7 @@ // Tests that blocking a permission and allowing it again correctly resets // infobar and acceptance state. -TEST_F(PermissionsOverlayTabHelperTest, BlockingAndAllowingSinglePermission) { +TEST_F(PermissionsTabHelperTest, BlockingAndAllowingSinglePermission) { if (@available(iOS 15, *)) { // Allowed permission. web_state_.SetStateForPermission(web::PermissionStateAllowed, @@ -143,7 +143,7 @@ // Tests that making a permission inaccessible and allowing it again correctly // resets infobar and acceptance state. -TEST_F(PermissionsOverlayTabHelperTest, +TEST_F(PermissionsTabHelperTest, MakingPermissionNotAccessibleAndAllowingItAgain) { if (@available(iOS 15, *)) { // Allowed permission. @@ -176,7 +176,7 @@ // Tests that an infobar is setup with the correct acceptance state when the // status of both permission are allowed simultaneously. -TEST_F(PermissionsOverlayTabHelperTest, +TEST_F(PermissionsTabHelperTest, CheckInfobarCountForSimultaneouslyAllowedPermissions) { if (@available(iOS 15, *)) { // Allow both permissions. @@ -217,7 +217,7 @@ // Tests that an infobar is setup and replaced with the correct acceptance // state when the status of both permission are allowed one by one. -TEST_F(PermissionsOverlayTabHelperTest, +TEST_F(PermissionsTabHelperTest, CheckInfobarCountForSeparatelyAllowedPermissions) { if (@available(iOS 15, *)) { // Allow one permission. @@ -264,7 +264,7 @@ // Tests that infobar and acceptance state would be handled correctly when one // permission is blocked while the other permission changes states. -TEST_F(PermissionsOverlayTabHelperTest, +TEST_F(PermissionsTabHelperTest, CheckInfobarAndAcceptanceStateWhenOnePermissionIsBlocked) { if (@available(iOS 15, *)) { // Allow one permission.
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 b308bf8..b41ac132 100644 --- a/ios/chrome/browser/policy/configuration_policy_handler_list_factory.mm +++ b/ios/chrome/browser/policy/configuration_policy_handler_list_factory.mm
@@ -56,6 +56,9 @@ { policy::key::kAllowChromeDataInBackups, prefs::kAllowChromeDataInBackups, base::Value::Type::BOOLEAN }, + { policy::key::kAppStoreRatingEnabled, + prefs::kAppStoreRatingPolicyEnabled, + base::Value::Type::BOOLEAN }, { policy::key::kComponentUpdatesEnabled, prefs::kComponentUpdatesEnabled, base::Value::Type::BOOLEAN },
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm index aecbe8f..8003075 100644 --- a/ios/chrome/browser/prefs/browser_prefs.mm +++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -191,6 +191,7 @@ registry->RegisterListPref(prefs::kRestrictAccountsToPatterns); registry->RegisterIntegerPref(prefs::kBrowserSigninPolicy, static_cast<int>(BrowserSigninMode::kEnabled)); + registry->RegisterBooleanPref(prefs::kAppStoreRatingPolicyEnabled, true); registry->RegisterIntegerPref(kTrialGroupPrefName, 0);
diff --git a/ios/chrome/browser/prefs/pref_names.cc b/ios/chrome/browser/prefs/pref_names.cc index dcbb50e7..f9ad265 100644 --- a/ios/chrome/browser/prefs/pref_names.cc +++ b/ios/chrome/browser/prefs/pref_names.cc
@@ -9,6 +9,9 @@ // The application locale. const char kApplicationLocale[] = "intl.app_locale"; +// Boolean that is true when the AppStoreRatingEnabled policy is enabled. +const char kAppStoreRatingPolicyEnabled[] = "ios.app_store_rating_enabled"; + // Boolean that is true when Suggest support is enabled. const char kArticlesForYouEnabled[] = "suggestions.articles_enabled";
diff --git a/ios/chrome/browser/prefs/pref_names.h b/ios/chrome/browser/prefs/pref_names.h index 82ee729..f611833f 100644 --- a/ios/chrome/browser/prefs/pref_names.h +++ b/ios/chrome/browser/prefs/pref_names.h
@@ -8,6 +8,7 @@ namespace prefs { extern const char kApplicationLocale[]; +extern const char kAppStoreRatingPolicyEnabled[]; extern const char kArticlesForYouEnabled[]; extern const char kBrowserStateInfoCache[]; extern const char kBrowserStateLastUsed[];
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn index 613b6a4..a826bae6 100644 --- a/ios/chrome/browser/tabs/BUILD.gn +++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -87,6 +87,7 @@ "//ios/chrome/browser/optimization_guide", "//ios/chrome/browser/overscroll_actions", "//ios/chrome/browser/passwords", + "//ios/chrome/browser/permissions:tab_helper", "//ios/chrome/browser/policy_url_blocking", "//ios/chrome/browser/prerender", "//ios/chrome/browser/reading_list",
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm index 5076803..97c96c8 100644 --- a/ios/chrome/browser/tabs/tab_helper_util.mm +++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -53,7 +53,6 @@ #import "ios/chrome/browser/infobars/overlays/default_infobar_overlay_request_factory.h" #import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h" #import "ios/chrome/browser/infobars/overlays/infobar_overlay_tab_helper.h" -#import "ios/chrome/browser/infobars/overlays/permissions_overlay_tab_helper.h" #import "ios/chrome/browser/infobars/overlays/translate_overlay_tab_helper.h" #import "ios/chrome/browser/itunes_urls/itunes_urls_handler_tab_helper.h" #import "ios/chrome/browser/link_to_text/link_to_text_tab_helper.h" @@ -66,6 +65,7 @@ #import "ios/chrome/browser/overscroll_actions/overscroll_actions_tab_helper.h" #import "ios/chrome/browser/passwords/password_tab_helper.h" #import "ios/chrome/browser/passwords/well_known_change_password_tab_helper.h" +#import "ios/chrome/browser/permissions/permissions_tab_helper.h" #import "ios/chrome/browser/policy_url_blocking/policy_url_blocking_tab_helper.h" #import "ios/chrome/browser/prerender/prerender_service_factory.h" #import "ios/chrome/browser/reading_list/offline_page_tab_helper.h" @@ -250,7 +250,7 @@ OfflinePageTabHelper::CreateForWebState( web_state, ReadingListModelFactory::GetForBrowserState(browser_state)); - PermissionsOverlayTabHelper::CreateForWebState(web_state); + PermissionsTabHelper::CreateForWebState(web_state); RepostFormTabHelper::CreateForWebState(web_state); NetExportTabHelper::CreateForWebState(web_state);
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm index 97358177..62f0302 100644 --- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm +++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -1518,15 +1518,8 @@ self.findBarCoordinator = nil; } - findBarCoordinator = - [[FindBarCoordinator alloc] initWithBaseViewController:self.viewController - browser:self.browser]; - self.findBarCoordinator = findBarCoordinator; - - findBarCoordinator.presenter = _toolbarAccessoryPresenter; - findBarCoordinator.delegate = self; - findBarCoordinator.presentationDelegate = self.viewController; - [findBarCoordinator start]; + self.findBarCoordinator = [self newFindBarCoordinator]; + [self.findBarCoordinator start]; } - (void)closeFindInPage { @@ -1539,6 +1532,7 @@ findTabHelper->StopFinding(); } else { [self.findBarCoordinator stop]; + self.findBarCoordinator = nil; } } } @@ -1548,13 +1542,16 @@ self.browser->GetWebStateList()->GetActiveWebState(); auto* findHelper = FindTabHelper::FromWebState(currentWebState); if (findHelper && findHelper->IsFindUIActive() && - !self.findBarCoordinator.presenter.isPresenting) { + !_toolbarAccessoryPresenter.isPresenting) { + DCHECK(!self.findBarCoordinator); + self.findBarCoordinator = [self newFindBarCoordinator]; [self.findBarCoordinator start]; } } - (void)hideFindUI { [self.findBarCoordinator stop]; + self.findBarCoordinator = nil; } - (void)defocusFindInPage { @@ -1604,6 +1601,18 @@ !helper->IsFindUIActive()); } +- (FindBarCoordinator*)newFindBarCoordinator { + FindBarCoordinator* findBarCoordinator = + [[FindBarCoordinator alloc] initWithBaseViewController:self.viewController + browser:self.browser]; + + findBarCoordinator.presenter = _toolbarAccessoryPresenter; + findBarCoordinator.delegate = self; + findBarCoordinator.presentationDelegate = self.viewController; + + return findBarCoordinator; +} + #pragma mark - PromosManagerCommands - (void)maybeDisplayPromo { @@ -1759,14 +1768,8 @@ self.textZoomCoordinator = nil; } - textZoomCoordinator = [[TextZoomCoordinator alloc] - initWithBaseViewController:self.viewController - browser:self.browser]; - self.textZoomCoordinator = textZoomCoordinator; - - textZoomCoordinator.presenter = _toolbarAccessoryPresenter; - textZoomCoordinator.delegate = self; - [textZoomCoordinator start]; + self.textZoomCoordinator = [self newTextZoomCoordinator]; + [self.textZoomCoordinator start]; } - (void)closeTextZoom { @@ -1780,6 +1783,7 @@ } } [self.textZoomCoordinator stop]; + self.textZoomCoordinator = nil; } - (void)showTextZoomUIIfActive { @@ -1792,13 +1796,26 @@ FontSizeTabHelper* fontSizeTabHelper = FontSizeTabHelper::FromWebState(currentWebState); if (fontSizeTabHelper && fontSizeTabHelper->IsTextZoomUIActive() && - !self.textZoomCoordinator.presenter.isPresenting) { + !_toolbarAccessoryPresenter.isPresenting) { + DCHECK(!self.textZoomCoordinator); + self.textZoomCoordinator = [self newTextZoomCoordinator]; [self.textZoomCoordinator start]; } } - (void)hideTextZoomUI { [self.textZoomCoordinator stop]; + self.textZoomCoordinator = nil; +} + +- (TextZoomCoordinator*)newTextZoomCoordinator { + TextZoomCoordinator* textZoomCoordinator = [[TextZoomCoordinator alloc] + initWithBaseViewController:self.viewController + browser:self.browser]; + textZoomCoordinator.presenter = _toolbarAccessoryPresenter; + textZoomCoordinator.delegate = self; + + return textZoomCoordinator; } #pragma mark - URLLoadingServiceDelegate
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator_unittest.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator_unittest.mm index 0325da48..c8ee5c8 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator_unittest.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator_unittest.mm
@@ -62,6 +62,10 @@ test_cbs_builder.AddTestingFactory( ios::TemplateURLServiceFactory::GetInstance(), ios::TemplateURLServiceFactory::GetDefaultFactory()); + test_cbs_builder.AddTestingFactory( + ReadingListModelFactory::GetInstance(), + base::BindRepeating(&BuildReadingListModelWithFakeStorage, + std::vector<ReadingListEntry>())); chrome_browser_state_ = test_cbs_builder.Build(); large_icon_service_.reset(new favicon::LargeIconServiceImpl( &mock_favicon_service_, nullptr, 32, favicon_base::IconType::kTouchIcon, @@ -69,7 +73,7 @@ browser_ = std::make_unique<TestBrowser>(chrome_browser_state_.get()); web_state_list_ = browser_->GetWebStateList(); fake_web_state_ = std::make_unique<web::FakeWebState>(); - InitializeReadingListModel(); + fake_web_state_->SetBrowserState(chrome_browser_state_.get()); dispatcher_ = OCMProtocolMock(@protocol(ContentSuggestionsMediatorDispatcher)); consumer_ = OCMProtocolMock(@protocol(ContentSuggestionsConsumer)); @@ -119,15 +123,6 @@ return test_web_state; } - // Initialize reading list model and its required tab helpers. - void InitializeReadingListModel() { - fake_web_state_->SetBrowserState(chrome_browser_state_.get()); - ReadingListModelFactory::GetInstance()->SetTestingFactoryAndUse( - chrome_browser_state_.get(), - base::BindRepeating(&BuildReadingListModelWithFakeStorage, - std::vector<ReadingListEntry>())); - } - web::WebTaskEnvironment task_environment_; sync_preferences::TestingPrefServiceSyncable pref_service_; IOSChromeScopedTestingLocalState local_state_;
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm index 14bf3a82..acf55219 100644 --- a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm +++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
@@ -1192,6 +1192,8 @@ AppLaunchConfiguration config = [self appConfigurationForTestCase]; config.relaunch_policy = ForceRelaunchByCleanShutdown; config.features_disabled.push_back(kTrendingQueriesModule); + // TODO(crbug.com/1403077): Reenable the discover feed sync promo feature + config.features_disabled.push_back(kEnableDiscoverFeedTopSyncPromo); [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config]; [self
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm index 7b87f53..dfe8373 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm
@@ -932,8 +932,8 @@ [self cleanUpCollectionViewConstraints]; [NSLayoutConstraint activateConstraints:@[ - [self.feedHeaderViewController.view.leadingAnchor - constraintEqualToAnchor:self.collectionView.leadingAnchor], + [self.feedHeaderViewController.view.leftAnchor + constraintEqualToAnchor:self.collectionView.leftAnchor], [self.feedHeaderViewController.view.widthAnchor constraintEqualToAnchor:self.collectionView.widthAnchor], [self.collectionView.centerXAnchor @@ -945,8 +945,8 @@ if (IsDiscoverFeedTopSyncPromoEnabled() && self.feedTopSectionViewController) { [NSLayoutConstraint activateConstraints:@[ - [self.feedTopSectionViewController.view.leadingAnchor - constraintEqualToAnchor:self.collectionView.leadingAnchor], + [self.feedTopSectionViewController.view.leftAnchor + constraintEqualToAnchor:self.collectionView.leftAnchor], [self.feedTopSectionViewController.view.widthAnchor constraintEqualToAnchor:self.collectionView.widthAnchor], [self.feedTopSectionViewController.view.topAnchor
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm index 68fa295..cf4ae1f 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
@@ -95,7 +95,7 @@ return nil; } -// Returns visit Copied Link button matcher from UIMenuController. +// Returns Visit Copied Link button matcher from UIMenuController. id<GREYMatcher> VisitCopiedLinkButton() { NSString* a11yLabelCopiedLink = l10n_util::GetNSString(IDS_IOS_VISIT_COPIED_LINK); @@ -160,6 +160,20 @@ return grey_accessibilityHint(a11yHintPasteButton); } +// Returns Copy button from the context menu. +id<GREYMatcher> CopyContextMenuButton() { + return grey_allOf( + grey_accessibilityLabel(l10n_util::GetNSString(IDS_IOS_SHARE_MENU_COPY)), + grey_accessibilityTrait(UIAccessibilityTraitButton), nil); +} + +// Returns Visit Copied Link button from the context menu. +id<GREYMatcher> VisitCopiedLinkContextMenuButton() { + return grey_allOf(grey_accessibilityLabel( + l10n_util::GetNSString(IDS_IOS_VISIT_COPIED_LINK)), + grey_accessibilityTrait(UIAccessibilityTraitButton), nil); +} + // Taps the fake omnibox and waits for the real omnibox to be visible. void FocusFakebox() { [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()] @@ -170,7 +184,10 @@ } // namespace -@interface OmniboxTestCase : ChromeTestCase +@interface OmniboxTestCase : ChromeTestCase { + GURL _URL1; +} + @end @implementation OmniboxTestCase @@ -182,6 +199,9 @@ self.testServer->RegisterRequestHandler( base::BindRepeating(&StandardResponse)); GREYAssertTrue(self.testServer->Start(), @"Test server failed to start."); + + _URL1 = self.testServer->GetURL(kPage1URL); + [ChromeEarlGrey clearPasteboard]; [ChromeEarlGrey clearBrowsingHistory]; } @@ -293,9 +313,7 @@ - (void)testOmniboxMenuPasteURLToSearch { FocusFakebox(); // Copy URL into clipboard. - NSString* URL = - base::SysUTF8ToNSString(self.testServer->GetURL(kPage1URL).spec()); - [ChromeEarlGrey copyTextToPasteboard:URL]; + [ChromeEarlGrey copyTextToPasteboard:base::SysUTF8ToNSString(_URL1.spec())]; // Tap Visit Copied Link menu button. [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()] performAction:grey_longPress()]; @@ -307,8 +325,7 @@ // Tests that Search Copied Image menu button is shown with an image in the // clipboard and is starting an image search. -// Flaky. crbug.com/1361857 -- (void)DISABLED_testOmniboxMenuPasteImageToSearch { +- (void)testOmniboxMenuPasteImageToSearch { [self copyImageIntoClipboard]; // Wait for the context menu to dismiss, so the omnibox can be tapped. @@ -322,6 +339,7 @@ performAction:grey_longPress()]; [[EarlGrey selectElementWithMatcher:SearchCopiedImageButton()] performAction:grey_tap()]; + // Check that the omnibox started a google search. [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()] assertWithMatcher:chrome_test_util::OmniboxContainingText("google")]; @@ -359,9 +377,7 @@ disabled:{} relaunchPolicy:ForceRelaunchByCleanShutdown]; FocusFakebox(); - NSString* URL = - base::SysUTF8ToNSString(self.testServer->GetURL(kPage1URL).spec()); - [ChromeEarlGrey copyTextToPasteboard:URL]; + [ChromeEarlGrey copyTextToPasteboard:base::SysUTF8ToNSString(_URL1.spec())]; [[EarlGrey selectElementWithMatcher:PasteToSearchButton()] performAction:grey_tap()]; @@ -399,8 +415,11 @@ #pragma mark - Steady state tests -@interface LocationBarSteadyStateTestCase : ChromeTestCase -- (void)testFocusingOmniboxDismissesEditMenu; +@interface LocationBarSteadyStateTestCase : ChromeTestCase { + GURL _URL1; + GURL _URL2; +} + @end @implementation LocationBarSteadyStateTestCase @@ -413,6 +432,9 @@ base::BindRepeating(&StandardResponse)); GREYAssertTrue(self.testServer->Start(), @"Test server failed to start."); + _URL1 = self.testServer->GetURL(kPage1URL); + _URL2 = self.testServer->GetURL(kPage2URL); + [ChromeEarlGrey clearBrowsingHistory]; // Clear the pasteboard in case there is a URL copied. @@ -420,16 +442,6 @@ [pasteboard setValue:@"" forPasteboardType:UIPasteboardNameGeneral]; } -- (AppLaunchConfiguration)appConfigurationForTestCase { - AppLaunchConfiguration config; - - if ([self isRunningTest:@selector(testFocusingOmniboxDismissesEditMenu)]) { - config.features_disabled.push_back(kIOSLocationBarUseNativeContextMenu); - } - - return config; -} - // Tapping on steady view starts editing. - (void)testTapSwitchesToEditing { [self openPage1]; @@ -441,9 +453,7 @@ // Tests that in compact, a share button is visible. // Voice search is not enabled on the bots, so the voice search button is // not tested here. -// TODO(crbug.com/996541) Starting in Xcode 11 beta 6, the share button does -// not appear (even with a delay) flakily. -- (void)DISABLED_testTrailingButton { +- (void)testTrailingButton { [self openPage1]; if ([ChromeEarlGrey isCompactWidth]) { @@ -452,22 +462,20 @@ } } -// TODO(crbug.com/1056700): Test is flaky -- (void)DISABLED_testCopyPaste { +- (void)testCopyPaste { [self openPage1]; // Long pressing should allow copying. [[EarlGrey selectElementWithMatcher:chrome_test_util::DefocusedLocationView()] performAction:grey_longPress()]; - // Verify that system text selection callout is displayed. - [[EarlGrey selectElementWithMatcher:chrome_test_util:: - SystemSelectionCalloutCopyButton()] + // Verify that the Copy button is displayed. + [[EarlGrey selectElementWithMatcher:CopyContextMenuButton()] assertWithMatcher:grey_notNil()]; // Pressing should not allow pasting when pasteboard is empty. // Verify that system text selection callout is not displayed. - [[EarlGrey selectElementWithMatcher:VisitCopiedLinkButton()] + [[EarlGrey selectElementWithMatcher:VisitCopiedLinkContextMenuButton()] assertWithMatcher:grey_nil()]; [[EarlGrey selectElementWithMatcher:SearchCopiedTextButton()] assertWithMatcher:grey_nil()]; @@ -477,21 +485,9 @@ [self checkLocationBarSteadyState]; // Tapping it should copy the URL. - [[EarlGrey selectElementWithMatcher:chrome_test_util:: - SystemSelectionCalloutCopyButton()] + [[EarlGrey selectElementWithMatcher:CopyContextMenuButton()] performAction:grey_tap()]; - - // Edit menu takes a while to copy, and not waiting here will cause Page 2 to - // load before the copy happens, so Page 2 URL may be copied. - GREYCondition* copyCondition = [GREYCondition - conditionWithName:@"page1 URL copied condition" - block:^BOOL { - return [UIPasteboard.generalPasteboard.string - hasSuffix:base::SysUTF8ToNSString(kPage1URL)]; - }]; - // Wait for copy to happen or timeout after 5 seconds. - GREYAssertTrue([copyCondition waitWithTimeout:5], - @"Copying page 1 URL failed"); + [ChromeEarlGrey verifyStringCopied:base::SysUTF8ToNSString(_URL1.spec())]; // Go to another web page. [self openPage2]; @@ -499,37 +495,47 @@ // Visit copied link should now be available. [[EarlGrey selectElementWithMatcher:chrome_test_util::DefocusedLocationView()] performAction:grey_longPress()]; - [[EarlGrey selectElementWithMatcher:VisitCopiedLinkButton()] + [[EarlGrey selectElementWithMatcher:VisitCopiedLinkContextMenuButton()] assertWithMatcher:grey_notNil()]; [self checkLocationBarSteadyState]; // Tapping it should navigate to Page 1. - [[EarlGrey selectElementWithMatcher:VisitCopiedLinkButton()] + [[EarlGrey selectElementWithMatcher:VisitCopiedLinkContextMenuButton()] performAction:grey_tap()]; [ChromeEarlGrey waitForPageToFinishLoading]; [ChromeEarlGrey waitForWebStateContainingText:kPage1]; } -- (void)testFocusingOmniboxDismissesEditMenu { +- (void)testDismissesEditMenu { [self openPage1]; // Long pressing should open edit menu. [[EarlGrey selectElementWithMatcher:chrome_test_util::DefocusedLocationView()] performAction:grey_longPress()]; - [[EarlGrey selectElementWithMatcher:chrome_test_util:: - SystemSelectionCalloutCopyButton()] + [[EarlGrey selectElementWithMatcher:CopyContextMenuButton()] assertWithMatcher:grey_notNil()]; - // Focus omnibox. - [ChromeEarlGreyUI focusOmnibox]; - [self checkLocationBarEditState]; + // Dismiss context menu. + GREYAssertTrue([ChromeEarlGreyUI dismissContextMenuIfPresent], + @"Failed to dismiss context menu."); - // Verify that the edit menu disappeared. - [[EarlGrey selectElementWithMatcher:chrome_test_util:: - SystemSelectionCalloutCopyButton()] - assertWithMatcher:grey_nil()]; + GREYCondition* contextMenuDismissed = [GREYCondition + conditionWithName:@"Wait for context menu to be dismissed" + block:^BOOL { + NSError* error; + [[EarlGrey selectElementWithMatcher:CopyContextMenuButton()] + assertWithMatcher:grey_nil() + error:&error]; + return error == nil; + }]; + + // Verify that the context menu disappeared. + GREYAssertTrue([contextMenuDismissed + waitWithTimeout:base::test::ios::kWaitForUIElementTimeout + .InSecondsF()], + @"Context menu is still visible."); } // Copies and pastes a URL, then performs an undo of the paste, and attempts to @@ -606,17 +612,7 @@ [ChromeEarlGrey simulatePhysicalKeyboardEvent:@"X" flags:UIKeyModifierCommand]; - - // It takes a while to copy, and not waiting here will cause the test to fail. - GREYCondition* copyCondition = [GREYCondition - conditionWithName:@"page1 URL copied condition" - block:^BOOL { - return [UIPasteboard.generalPasteboard.string - hasSuffix:base::SysUTF8ToNSString(kPage1URL)]; - }]; - // Wait for copy to happen or timeout after 5 seconds. - GREYAssertTrue([copyCondition waitWithTimeout:5], - @"Copying page 1 URL failed"); + [ChromeEarlGrey verifyStringCopied:base::SysUTF8ToNSString(_URL1.spec())]; // Verify that the omnibox is empty. [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()] @@ -693,14 +689,14 @@ // Navigates to Page 1 in a tab and waits for it to load. - (void)openPage1 { // Go to a web page to have a normal location bar. - [ChromeEarlGrey loadURL:self.testServer->GetURL(kPage1URL)]; + [ChromeEarlGrey loadURL:_URL1]; [ChromeEarlGrey waitForWebStateContainingText:kPage1]; } // Navigates to Page 2 in a tab and waits for it to load. - (void)openPage2 { // Go to a web page to have a normal location bar. - [ChromeEarlGrey loadURL:self.testServer->GetURL(kPage2URL)]; + [ChromeEarlGrey loadURL:_URL2]; [ChromeEarlGrey waitForWebStateContainingText:kPage2]; } @@ -739,8 +735,13 @@ // displayed. Paste button should be hidden when pasteboard is empty otherwise // it should be displayed. Select & SelectAll buttons should be hidden when the // omnibox is empty. -// TODO(crbug.com/1209342): test failing on device -- (void)DISABLED_testEmptyOmnibox { +- (void)testEmptyOmnibox { + // TODO(crbug.com/1209342): this test fails on iOS 15 devices. + if (base::ios::IsRunningOnIOS15OrLater() && + !base::ios::IsRunningOnIOS16OrLater()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 15."); + } + // Focus omnibox. [self focusFakebox]; [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()] @@ -836,12 +837,6 @@ // If the selected text is the entire omnibox field, select & SelectAll button // should be hidden. - (void)testSelection { -// TODO(crbug.com/1209342): test failing on ipad device -#if !TARGET_IPHONE_SIMULATOR - if ([ChromeEarlGrey isIPadIdiom]) { - EARL_GREY_TEST_SKIPPED(@"This test doesn't pass on iPad device."); - } -#endif // Focus omnibox. [self focusFakebox]; [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()] @@ -892,12 +887,12 @@ } - (void)testNoDefaultMatch { - // TODO(crbug.com/1253345) Re-enable this test for iOS 15 and earlier. There - // is currently a problem with the test on iOS 15 devices where copying to the - // pasteboard fails. - if (!base::ios::IsRunningOnIOS16OrLater()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 15 and earlier."); + // TODO(crbug.com/1253345) This test fails on iOS 15 devices. + if (base::ios::IsRunningOnIOS15OrLater() && + !base::ios::IsRunningOnIOS16OrLater()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 15."); } + NSString* copiedText = @"test no default match1"; // Put some text in pasteboard.
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/permissions/BUILD.gn b/ios/chrome/browser/ui/overlays/infobar_banner/permissions/BUILD.gn index 97fdcf55..3527b00 100644 --- a/ios/chrome/browser/ui/overlays/infobar_banner/permissions/BUILD.gn +++ b/ios/chrome/browser/ui/overlays/infobar_banner/permissions/BUILD.gn
@@ -34,9 +34,9 @@ "//components/infobars/core", "//ios/chrome/app/strings", "//ios/chrome/browser/infobars:infobars", - "//ios/chrome/browser/infobars/overlays:infobar_delegates", "//ios/chrome/browser/overlays/public/infobar_banner", "//ios/chrome/browser/overlays/test", + "//ios/chrome/browser/permissions:infobar_delegate", "//ios/chrome/browser/ui/infobars/banners", "//ios/chrome/browser/ui/infobars/banners/test", "//ios/web/public/permissions",
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/permissions/permissions_infobar_banner_overlay_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/infobar_banner/permissions/permissions_infobar_banner_overlay_mediator_unittest.mm index 66c870a..514e011 100644 --- a/ios/chrome/browser/ui/overlays/infobar_banner/permissions/permissions_infobar_banner_overlay_mediator_unittest.mm +++ b/ios/chrome/browser/ui/overlays/infobar_banner/permissions/permissions_infobar_banner_overlay_mediator_unittest.mm
@@ -5,10 +5,10 @@ #import "ios/chrome/browser/ui/overlays/infobar_banner/permissions/permissions_infobar_banner_overlay_mediator.h" #import "ios/chrome/browser/infobars/infobar_ios.h" -#import "ios/chrome/browser/infobars/overlays/permissions_overlay_infobar_delegate.h" #import "ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.h" #import "ios/chrome/browser/overlays/public/infobar_banner/permissions_infobar_banner_overlay_request_config.h" #import "ios/chrome/browser/overlays/test/fake_overlay_request_callback_installer.h" +#import "ios/chrome/browser/permissions/permissions_infobar_delegate.h" #import "ios/chrome/browser/ui/infobars/banners/test/fake_infobar_banner_consumer.h" #import "ios/chrome/grit/ios_strings.h" #import "ios/web/public/permissions/permissions.h" @@ -40,8 +40,8 @@ NSArray<NSNumber*>* recently_accessible_permissions = @[ @(web::PermissionCamera), @(web::PermissionMicrophone) ]; // Second parameter is used for modal; not needed for this test. - std::unique_ptr<PermissionsOverlayInfobarDelegate> delegate = - std::make_unique<PermissionsOverlayInfobarDelegate>( + std::unique_ptr<PermissionsInfobarDelegate> delegate = + std::make_unique<PermissionsInfobarDelegate>( recently_accessible_permissions, nullptr); InfoBarIOS infobar(InfobarType::kInfobarTypePermissions, std::move(delegate)); @@ -68,8 +68,8 @@ NSArray<NSNumber*>* recently_accessible_permissions = @[ @(web::PermissionCamera) ]; // Second parameter is used for modal; not needed for this test. - std::unique_ptr<PermissionsOverlayInfobarDelegate> delegate = - std::make_unique<PermissionsOverlayInfobarDelegate>( + std::unique_ptr<PermissionsInfobarDelegate> delegate = + std::make_unique<PermissionsInfobarDelegate>( recently_accessible_permissions, nullptr); InfoBarIOS infobar(InfobarType::kInfobarTypePermissions, std::move(delegate));
diff --git a/ios/chrome/browser/ui/overlays/infobar_modal/permissions/BUILD.gn b/ios/chrome/browser/ui/overlays/infobar_modal/permissions/BUILD.gn index e2b3710..d16c7051 100644 --- a/ios/chrome/browser/ui/overlays/infobar_modal/permissions/BUILD.gn +++ b/ios/chrome/browser/ui/overlays/infobar_modal/permissions/BUILD.gn
@@ -44,10 +44,10 @@ "//components/infobars/core", "//ios/chrome/app/strings", "//ios/chrome/browser/infobars:infobars", - "//ios/chrome/browser/infobars/overlays:infobar_delegates", "//ios/chrome/browser/overlays:overlays", "//ios/chrome/browser/overlays/public/infobar_modal/permissions", "//ios/chrome/browser/overlays/test", + "//ios/chrome/browser/permissions:infobar_delegate", "//ios/chrome/browser/ui/permissions", "//ios/chrome/browser/ui/permissions:permission_info", "//ios/web/public/navigation",
diff --git a/ios/chrome/browser/ui/overlays/infobar_modal/permissions/permissions_infobar_modal_overlay_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/infobar_modal/permissions/permissions_infobar_modal_overlay_mediator_unittest.mm index efe33da..89c7725 100644 --- a/ios/chrome/browser/ui/overlays/infobar_modal/permissions/permissions_infobar_modal_overlay_mediator_unittest.mm +++ b/ios/chrome/browser/ui/overlays/infobar_modal/permissions/permissions_infobar_modal_overlay_mediator_unittest.mm
@@ -5,9 +5,9 @@ #import "ios/chrome/browser/ui/overlays/infobar_modal/permissions/permissions_infobar_modal_overlay_mediator.h" #import "ios/chrome/browser/infobars/infobar_ios.h" -#import "ios/chrome/browser/infobars/overlays/permissions_overlay_infobar_delegate.h" #import "ios/chrome/browser/overlays/public/infobar_modal/permissions/permissions_modal_overlay_request_config.h" #import "ios/chrome/browser/overlays/public/overlay_request.h" +#import "ios/chrome/browser/permissions/permissions_infobar_delegate.h" #import "ios/chrome/browser/ui/permissions/permission_info.h" #import "ios/chrome/browser/ui/permissions/permissions_consumer.h" #import "ios/chrome/grit/ios_strings.h" @@ -68,9 +68,9 @@ navigation_manager->SetVisibleItem(item.get()); web_state_.SetNavigationManager(std::move(navigation_manager)); // First parameter is used for banner; not needed for this test. - std::unique_ptr<PermissionsOverlayInfobarDelegate> delegate = - std::make_unique<PermissionsOverlayInfobarDelegate>([NSArray array], - &web_state_); + std::unique_ptr<PermissionsInfobarDelegate> delegate = + std::make_unique<PermissionsInfobarDelegate>([NSArray array], + &web_state_); InfoBarIOS infobar(InfobarType::kInfobarTypePermissions, std::move(delegate)); request_ = OverlayRequest::CreateWithConfig<
diff --git a/ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.h b/ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.h index ccd52f8..662a67ad 100644 --- a/ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.h +++ b/ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.h
@@ -11,6 +11,7 @@ #include "components/keyed_service/core/keyed_service.h" #include "components/sync/engine/cycle/sync_cycle_snapshot.h" #include "google_apis/gaia/google_service_auth_error.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h" #include "ios/web/public/test/web_task_environment.h" #include "testing/platform_test.h" @@ -19,10 +20,6 @@ class MockSyncService; } // namespace syncer -namespace web { -class BrowserState; -} // namespace web - @class AppState; class Browser; @class SceneState; @@ -35,9 +32,6 @@ // supporting structure they require. class PassphraseTableViewControllerTest : public ChromeTableViewControllerTest { public: - static std::unique_ptr<KeyedService> CreateNiceMockSyncService( - web::BrowserState* context); - PassphraseTableViewControllerTest(); ~PassphraseTableViewControllerTest() override; @@ -45,6 +39,11 @@ void SetUp() override; void TearDown() override; + // Allow sub-classes to register testing factories in the builder for the + // new TestChromeBrowserState. + virtual void RegisterTestingFactories( + TestChromeBrowserState::Builder& builder); + void SetUpNavigationController(UIViewController* test_controller); web::WebTaskEnvironment task_environment_;
diff --git a/ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.mm b/ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.mm index 4c88fee47..aa708f95 100644 --- a/ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.mm +++ b/ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.mm
@@ -44,6 +44,8 @@ using testing::NiceMock; using testing::Return; +namespace { + std::unique_ptr<sync_preferences::PrefServiceSyncable> CreatePrefService() { sync_preferences::PrefServiceMockFactory factory; scoped_refptr<user_prefs::PrefRegistrySyncable> registry( @@ -54,12 +56,13 @@ return prefs; } -std::unique_ptr<KeyedService> -PassphraseTableViewControllerTest::CreateNiceMockSyncService( +std::unique_ptr<KeyedService> CreateNiceMockSyncService( web::BrowserState* context) { return std::make_unique<NiceMock<syncer::MockSyncService>>(); } +} // anonymous namespace + PassphraseTableViewControllerTest::PassphraseTableViewControllerTest() : ChromeTableViewControllerTest(), fake_sync_service_(NULL), @@ -79,11 +82,12 @@ AuthenticationServiceFactory::GetInstance(), AuthenticationServiceFactory::GetDefaultFactory()); test_cbs_builder.AddTestingFactory( - SyncServiceFactory::GetInstance(), - base::BindRepeating(&CreateMockSyncService)); - test_cbs_builder.AddTestingFactory( SyncSetupServiceFactory::GetInstance(), base::BindRepeating(&SyncSetupServiceMock::CreateKeyedService)); + test_cbs_builder.AddTestingFactory( + SyncServiceFactory::GetInstance(), + base::BindRepeating(&CreateNiceMockSyncService)); + RegisterTestingFactories(test_cbs_builder); test_cbs_builder.SetPrefService(CreatePrefService()); chrome_browser_state_ = test_cbs_builder.Build(); AuthenticationServiceFactory::CreateAndInitializeForBrowserState( @@ -97,9 +101,7 @@ SceneStateBrowserAgent::CreateForBrowser(browser_.get(), scene_state_); fake_sync_service_ = static_cast<syncer::MockSyncService*>( - SyncServiceFactory::GetInstance()->SetTestingFactoryAndUse( - chrome_browser_state_.get(), - base::BindRepeating(&CreateNiceMockSyncService))); + SyncServiceFactory::GetForBrowserState(chrome_browser_state_.get())); // Set up non-default return values for our sync service mock. ON_CALL(*fake_sync_service_->GetMockUserSettings(), IsPassphraseRequired()) @@ -128,6 +130,11 @@ ChromeTableViewControllerTest::TearDown(); } +void PassphraseTableViewControllerTest::RegisterTestingFactories( + TestChromeBrowserState::Builder& builder) { + // nothing to do, this is for sub-classes to override +} + void PassphraseTableViewControllerTest::SetUpNavigationController( UIViewController* test_controller) { dummy_controller_ = [[UIViewController alloc] init];
diff --git a/ios/chrome/browser/ui/settings/password/legacy_password_settings_egtest.mm b/ios/chrome/browser/ui/settings/password/legacy_password_settings_egtest.mm index 2f700d8a..12b9d110 100644 --- a/ios/chrome/browser/ui/settings/password/legacy_password_settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/password/legacy_password_settings_egtest.mm
@@ -411,9 +411,15 @@ AppLaunchConfiguration config; config.relaunch_policy = NoForceRelaunchAndResetState; + // Versions of these tests running against UI Split are found in + // password_manager_egtest.mm config.features_disabled.push_back( password_manager::features::kIOSPasswordUISplit); + // Grouping is intended to work with UI Split on. + config.features_disabled.push_back( + password_manager::features::kPasswordsGrouping); + if ([self isRunningTest:@selector (testNoOndeviceEncryptionSetupWhenSignedOut)]) { config.features_enabled.push_back(syncer::kSyncTrustedVaultPassphrasePromo); @@ -1382,12 +1388,12 @@ // Test that when user types text in search field, passwords and blocked // items are filtered out and "save passwords" switch is removed. - (void)testSearchPasswords { -// TODO(crbug.com/1067818): Test doesn't pass on iPad device. -#if !TARGET_IPHONE_SIMULATOR + // TODO(crbug.com/1067818): Test doesn't pass on iPad device or simulator. if ([ChromeEarlGrey isIPadIdiom]) { - EARL_GREY_TEST_SKIPPED(@"This test doesn't pass on iPad device."); + EARL_GREY_TEST_SKIPPED( + @"This test doesn't pass on iPad device or simulator."); } -#endif + SaveExamplePasswordForms(); SaveExampleBlockedForms();
diff --git a/ios/chrome/browser/ui/settings/password/password_issues_mediator_unittest.mm b/ios/chrome/browser/ui/settings/password/password_issues_mediator_unittest.mm index 4f3e846..b132831 100644 --- a/ios/chrome/browser/ui/settings/password/password_issues_mediator_unittest.mm +++ b/ios/chrome/browser/ui/settings/password/password_issues_mediator_unittest.mm
@@ -7,6 +7,7 @@ #import "base/strings/string_piece.h" #import "base/strings/string_util.h" #import "base/strings/utf_string_conversions.h" +#import "components/keyed_service/core/service_access_type.h" #import "components/password_manager/core/browser/password_manager_test_utils.h" #import "components/password_manager/core/browser/test_password_store.h" #import "components/password_manager/core/browser/ui/credential_ui_entry.h" @@ -45,18 +46,6 @@ using password_manager::InsecureCredential; using password_manager::TestPasswordStore; -// Sets test password store and returns pointer to it. -scoped_refptr<TestPasswordStore> CreateAndUseTestPasswordStore( - ChromeBrowserState* _browserState) { - return base::WrapRefCounted(static_cast<password_manager::TestPasswordStore*>( - IOSChromePasswordStoreFactory::GetInstance() - ->SetTestingFactoryAndUse( - _browserState, - base::BindRepeating(&password_manager::BuildPasswordStore< - web::BrowserState, TestPasswordStore>)) - .get())); -} - } // namespace // Test class that conforms to PasswordIssuesConsumer in order to test the @@ -88,9 +77,18 @@ test_cbs_builder.AddTestingFactory( SyncSetupServiceFactory::GetInstance(), base::BindRepeating(&SyncSetupServiceMock::CreateKeyedService)); + test_cbs_builder.AddTestingFactory( + IOSChromePasswordStoreFactory::GetInstance(), + base::BindRepeating( + &password_manager::BuildPasswordStore<web::BrowserState, + TestPasswordStore>)); chrome_browser_state_ = test_cbs_builder.Build(); - store_ = CreateAndUseTestPasswordStore(chrome_browser_state_.get()); + store_ = + base::WrapRefCounted(static_cast<password_manager::TestPasswordStore*>( + IOSChromePasswordStoreFactory::GetForBrowserState( + chrome_browser_state_.get(), ServiceAccessType::EXPLICIT_ACCESS) + .get())); password_check_ = IOSChromePasswordCheckManagerFactory::GetForBrowserState( chrome_browser_state_.get());
diff --git a/ios/chrome/browser/ui/settings/password/password_manager_egtest.mm b/ios/chrome/browser/ui/settings/password/password_manager_egtest.mm index e209c52..2c442ce 100644 --- a/ios/chrome/browser/ui/settings/password/password_manager_egtest.mm +++ b/ios/chrome/browser/ui/settings/password/password_manager_egtest.mm
@@ -398,6 +398,13 @@ // Various tests for the main Password Manager UI. @interface PasswordManagerTestCase : ChromeTestCase + +- (BOOL)groupingEnabled; + +- (GREYElementInteraction*) + interactionForSinglePasswordEntryWithDomain:(NSString*)domain + username:(NSString*)username; + @end @implementation PasswordManagerTestCase { @@ -405,6 +412,19 @@ std::unique_ptr<EarlGreyScopedBlockSwizzler> _passwordAutoFillStatusSwizzler; } +- (BOOL)groupingEnabled { + return YES; +} + +- (GREYElementInteraction*) + interactionForSinglePasswordEntryWithDomain:(NSString*)domain + username:(NSString*)username { + // With grouping enabled, discard the username; it's only shown on the details + // page. + return GetInteractionForListItem(ButtonWithAccessibilityLabel(domain), + kGREYDirectionDown); +} + - (void)setUp { [super setUp]; GREYAssertNil([MetricsAppInterface setupHistogramTester], @@ -440,6 +460,14 @@ config.features_enabled.push_back( password_manager::features::kIOSPasswordUISplit); + if ([self groupingEnabled]) { + config.features_enabled.push_back( + password_manager::features::kPasswordsGrouping); + } else { + config.features_disabled.push_back( + password_manager::features::kPasswordsGrouping); + } + if ([self isRunningTest:@selector (testNoOndeviceEncryptionSetupWhenSignedOut)]) { config.features_enabled.push_back(syncer::kSyncTrustedVaultPassphrasePromo); @@ -482,6 +510,10 @@ // Verifies the UI elements are accessible on the Passwords page. - (void)testAccessibilityOnPasswords { + if ([self groupingEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"This test isn't implemented with grouped passwords yet."); + } // Saving a form is needed for using the "password details" view. SaveExamplePasswordForm(); @@ -494,7 +526,8 @@ performAction:grey_tap()]; // Inspect "password details" view. - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; [ChromeEarlGrey verifyAccessibilityForCurrentScreen]; [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] @@ -514,7 +547,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; // Check the snackbar in case of successful reauthentication. @@ -558,7 +592,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; [PasswordSettingsAppInterface setUpMockReauthenticationModule]; @@ -588,7 +623,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; [PasswordSettingsAppInterface setUpMockReauthenticationModule]; @@ -622,7 +658,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; CopyPasswordDetailWithID(IDS_IOS_SHOW_PASSWORD_VIEW_USERNAME); @@ -647,7 +684,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; CopyPasswordDetailWithID(IDS_IOS_SHOW_PASSWORD_VIEW_SITE); @@ -674,7 +712,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; [PasswordSettingsAppInterface setUpMockReauthenticationModule]; @@ -703,7 +742,8 @@ @"Stored password was not removed from PasswordStore."); // Also verify that the removed password is no longer in the list. - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] assertWithMatcher:grey_not(grey_sufficientlyVisible())]; // Finally, verify that the Add button is visible and enabled, because there @@ -729,7 +769,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; [PasswordSettingsAppInterface setUpMockReauthenticationModule]; @@ -758,7 +799,8 @@ @"Stored password was not removed from PasswordStore."); // Also verify that the removed password is no longer in the list. - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] assertWithMatcher:grey_not(grey_sufficientlyVisible())]; // Verify blocked sites are still there. @@ -777,6 +819,11 @@ // goes back to the list-of-passwords view which doesn't display that form // anymore. - (void)testDuplicatedSavedFormDeletionInDetailView { + if ([self groupingEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"This test isn't implemented with grouped passwords yet."); + } + // Save form to be deleted later. SaveExamplePasswordForm(); // Save duplicate of the previously saved form to be deleted at the same time. @@ -790,7 +837,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; [PasswordSettingsAppInterface setUpMockReauthenticationModule]; @@ -819,7 +867,8 @@ @"Stored password was not removed from PasswordStore."); // Also verify that the removed password is no longer in the list. - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] assertWithMatcher:grey_not(grey_sufficientlyVisible())]; // Finally, verify that the Add button is visible and enabled, because there @@ -837,6 +886,10 @@ // Checks that deleting a blocked form from password details view goes // back to the list-of-passwords view which doesn't display that form anymore. - (void)testBlockedFormDeletionInDetailView { + if ([self groupingEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"This test isn't implemented with grouped passwords yet."); + } // Save blocked form to be deleted later. GREYAssert([PasswordSettingsAppInterface saveExampleBlockedOrigin:@"https://blocked.com"], @@ -887,6 +940,10 @@ // back to the list-of-passwords view which only displays a previously saved // password. - (void)testBlockedFormDeletionInDetailViewWithSavedForm { + if ([self groupingEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"This test isn't implemented with grouped passwords yet."); + } // Save blocked form to be deleted later. GREYAssert([PasswordSettingsAppInterface saveExampleBlockedOrigin:@"https://blocked.com"], @@ -924,7 +981,8 @@ assertWithMatcher:grey_not(grey_sufficientlyVisible())]; // Verify existing saved password is still in the list. - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] assertWithMatcher:grey_sufficientlyVisible()]; [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] @@ -940,7 +998,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; [PasswordSettingsAppInterface setUpMockReauthenticationModule]; @@ -972,7 +1031,8 @@ performAction:grey_tap()]; [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] performAction:grey_tap()]; - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] assertWithMatcher:grey_sufficientlyVisible()]; [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] @@ -991,7 +1051,8 @@ TapEdit(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; // Check that the current view is not the detail view, by failing to locate @@ -1013,7 +1074,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; // Tap the password cell to display the context menu. @@ -1050,6 +1112,10 @@ // Checks that federated credentials have no password but show the federation. - (void)testFederated { + if ([self groupingEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"This test isn't implemented with grouped passwords yet."); + } GREYAssert([PasswordSettingsAppInterface saveExampleFederatedOrigin:@"https://famous.provider.net" userName:@"federated username" @@ -1058,7 +1124,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, federated username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"federated username"] performAction:grey_tap()]; // Check that the Site and Username are present and correct. @@ -1100,7 +1167,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; [[EarlGrey selectElementWithMatcher:PasswordDetailWebsite()] @@ -1166,7 +1234,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, federated username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"federated username"] performAction:grey_tap()]; [[EarlGrey selectElementWithMatcher:PasswordDetailWebsite()] @@ -1230,7 +1299,8 @@ performAction:grey_tap()]; // Check the stored items. Scroll down if needed. - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] assertWithMatcher:grey_notNil()]; } @@ -1283,7 +1353,8 @@ TapEdit(); // Select password entry to be removed. - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; [[EarlGrey selectElementWithMatcher:DeleteButtonAtBottom()] @@ -1310,7 +1381,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; [PasswordSettingsAppInterface setUpMockReauthenticationModule]; @@ -1340,7 +1412,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; [PasswordSettingsAppInterface setUpMockReauthenticationModule]; @@ -1383,6 +1456,10 @@ // any device. To limit the effect of (2), custom large scrolling steps are // added to the usual scrolling actions. - (void)testManyPasswords { + if ([self groupingEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"This test isn't implemented with grouped passwords yet."); + } if ([ChromeEarlGrey isIPadIdiom]) { // TODO(crbug.com/906551): Enable the test on iPad once the bug is fixed. EARL_GREY_TEST_DISABLED(@"Disabled for iPad."); @@ -1446,7 +1523,8 @@ TapEdit(); // Select password entry to be removed. - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; [[EarlGrey selectElementWithMatcher:DeleteButtonAtBottom()] @@ -1541,12 +1619,16 @@ // Test that when user types text in search field, passwords and blocked // items are filtered out and "save passwords" switch is removed. - (void)testSearchPasswords { -// TODO(crbug.com/1067818): Test doesn't pass on iPad device. -#if !TARGET_IPHONE_SIMULATOR - if ([ChromeEarlGrey isIPadIdiom]) { - EARL_GREY_TEST_SKIPPED(@"This test doesn't pass on iPad device."); + if ([self groupingEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"This test isn't implemented with grouped passwords yet."); } -#endif + // TODO(crbug.com/1067818): Test doesn't pass on iPad device or simulator. + if ([ChromeEarlGrey isIPadIdiom]) { + EARL_GREY_TEST_SKIPPED( + @"This test doesn't pass on iPad device or simulator."); + } + SaveExamplePasswordForms(); SaveExampleBlockedForms(); @@ -1588,6 +1670,10 @@ // Test search and delete all passwords and blocked items. - (void)testSearchAndDeleteAllPasswords { + if ([self groupingEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"This test isn't implemented with grouped passwords yet."); + } SaveExamplePasswordForms(); SaveExampleBlockedForms(); @@ -1649,6 +1735,10 @@ // Test that the user can edit a password that is part of search results. - (void)testCanEditPasswordsFromASearch { + if ([self groupingEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"This test isn't implemented with grouped passwords yet."); + } SaveExamplePasswordForms(); OpenPasswordManager(); @@ -1700,7 +1790,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; // Check the snackbar in case of successful reauthentication. @@ -1751,7 +1842,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; // Check the snackbar in case of successful reauthentication. @@ -1794,7 +1886,8 @@ [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] performAction:grey_tap()]; - [GetInteractionForPasswordEntry(@"example.com, new username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"new username"] assertWithMatcher:grey_notNil()]; [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] @@ -1806,6 +1899,11 @@ // Checks that attempts to edit a username to a value which is already used for // the same domain fails. - (void)testEditUsernameFails { + if ([self groupingEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"This test isn't implemented with grouped passwords yet."); + } + GREYAssert( [PasswordSettingsAppInterface saveExamplePassword:@"concrete password" userName:@"concrete username1" @@ -1820,7 +1918,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username1") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username1"] performAction:grey_tap()]; // Check the snackbar in case of successful reauthentication. @@ -1861,7 +1960,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; // Check the snackbar in case of successful reauthentication. @@ -1894,6 +1994,10 @@ // Tests that removing multiple passwords works fine. - (void)testRemovingMultiplePasswords { + if ([self groupingEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"This test isn't implemented with grouped passwords yet."); + } constexpr int kPasswordsCount = 4; // Send the passwords to the queue to be added to the PasswordStore. @@ -1985,7 +2089,8 @@ [[EarlGrey selectElementWithMatcher:AddPasswordSaveButton()] performAction:grey_tap()]; - [GetInteractionForPasswordEntry(@"example.com, new username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"new username"] performAction:grey_tap()]; [PasswordSettingsAppInterface setUpMockReauthenticationModule]; @@ -2094,7 +2199,8 @@ [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] performAction:grey_tap()]; - [GetInteractionForPasswordEntry(@"example.com, new username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"new username"] assertWithMatcher:grey_notNil()]; [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] @@ -2107,6 +2213,10 @@ // a credential that has the same website as that of an existing credential // (does not contain username). - (void)testDuplicatedCredentialWithNoUsername { + if ([self groupingEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"This test isn't implemented with grouped passwords yet."); + } OpenPasswordManager(); [[EarlGrey selectElementWithMatcher:AddPasswordToolbarButton()] @@ -2149,7 +2259,8 @@ [[EarlGrey selectElementWithMatcher:AddPasswordSaveButton()] performAction:grey_tap()]; - [GetInteractionForPasswordEntry(@"example.com, new username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"new username"] performAction:grey_tap()]; [PasswordSettingsAppInterface setUpMockReauthenticationModule]; @@ -2194,6 +2305,11 @@ // Checks that deleting a compromised password from password issues goes back // to the list-of-issues which doesn't display that password anymore. - (void)testDeletePasswordIssue { + if ([self groupingEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"This test isn't implemented with grouped passwords yet."); + } + GREYAssert([PasswordSettingsAppInterface saveInsecurePassword:@"concrete password" userName:@"concrete username" @@ -2210,7 +2326,8 @@ [GetInteractionForPasswordEntry([NSString stringWithFormat:@"%@, %@", text, detailText]) performAction:grey_tap()]; - [GetInteractionForPasswordIssueEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; [PasswordSettingsAppInterface setUpMockReauthenticationModule]; @@ -2246,7 +2363,8 @@ OpenPasswordManager(); - [GetInteractionForPasswordEntry(@"example.com, concrete username") + [[self interactionForSinglePasswordEntryWithDomain:@"example.com" + username:@"concrete username"] performAction:grey_tap()]; // Check the snackbar in case of successful reauthentication. @@ -2272,6 +2390,10 @@ // properly when there are passwords with a favicon. // TODO(crbug.com/1348585): Fix to re-enable. - (void)testLogFaviconsForPasswordsMetrics { + if ([self groupingEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"This test isn't implemented with grouped passwords yet."); + } // Sign-in and synced user. FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; @@ -2437,3 +2559,31 @@ } @end + +// Rerun all the tests in this file but with kPasswordsGrouping disabled. This +// will be removed once that feature launches fully, but ensures regressions +// aren't introduced in the meantime. +@interface PasswordManagerGroupingDisabledTestCase : PasswordManagerTestCase + +@end + +@implementation PasswordManagerGroupingDisabledTestCase + +- (BOOL)groupingEnabled { + return NO; +} + +- (GREYElementInteraction*) + interactionForSinglePasswordEntryWithDomain:(NSString*)domain + username:(NSString*)username { + NSString* label = [NSString stringWithFormat:@"%@, %@", domain, username]; + return GetInteractionForListItem(ButtonWithAccessibilityLabel(label), + kGREYDirectionDown); +} + +// This causes the test case to actually be detected as a test case. The actual +// tests are all inherited from the parent class. +- (void)testEmpty { +} + +@end
diff --git a/ios/chrome/browser/ui/settings/password/password_settings/password_settings_mediator_unittest.mm b/ios/chrome/browser/ui/settings/password/password_settings/password_settings_mediator_unittest.mm index 3a28987..985948d 100644 --- a/ios/chrome/browser/ui/settings/password/password_settings/password_settings_mediator_unittest.mm +++ b/ios/chrome/browser/ui/settings/password/password_settings/password_settings_mediator_unittest.mm
@@ -6,6 +6,7 @@ #import "base/test/scoped_feature_list.h" #import "base/test/task_environment.h" +#import "components/keyed_service/core/service_access_type.h" #import "components/password_manager/core/browser/affiliation/mock_affiliation_service.h" #import "components/password_manager/core/browser/password_manager_test_utils.h" #import "components/password_manager/core/browser/test_password_store.h" @@ -55,26 +56,23 @@ .WillByDefault(testing::Return(passphrase_type)); } -// Sets up a password store factory for testing, and returns the test store. -scoped_refptr<TestPasswordStore> CreateAndUseTestPasswordStore( - ChromeBrowserState* browser_state) { - return base::WrapRefCounted(static_cast<password_manager::TestPasswordStore*>( - IOSChromePasswordStoreFactory::GetInstance() - ->SetTestingFactoryAndUse( - browser_state, - base::BindRepeating(&password_manager::BuildPasswordStore< - web::BrowserState, TestPasswordStore>)) - .get())); -} - class PasswordSettingsMediatorTest : public PlatformTest { protected: void SetUp() override { TestChromeBrowserState::Builder builder; + builder.AddTestingFactory( + IOSChromePasswordStoreFactory::GetInstance(), + base::BindRepeating( + &password_manager::BuildPasswordStore<web::BrowserState, + TestPasswordStore>)); browser_state_ = builder.Build(); password_manager::MockAffiliationService affiliation_service_; - store_ = CreateAndUseTestPasswordStore(browser_state_.get()); + store_ = + base::WrapRefCounted(static_cast<password_manager::TestPasswordStore*>( + IOSChromePasswordStoreFactory::GetForBrowserState( + browser_state_.get(), ServiceAccessType::EXPLICIT_ACCESS) + .get())); presenter_ = std::make_unique<SavedPasswordsPresenter>( &affiliation_service_, store_, /*accont_store=*/nullptr);
diff --git a/ios/chrome/browser/ui/settings/password/passwords_mediator_unittest.mm b/ios/chrome/browser/ui/settings/password/passwords_mediator_unittest.mm index 73ae4239..be880e1c 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_mediator_unittest.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_mediator_unittest.mm
@@ -9,6 +9,7 @@ #import "base/strings/string_util.h" #import "base/strings/utf_string_conversions.h" #import "base/test/scoped_feature_list.h" +#import "components/keyed_service/core/service_access_type.h" #import "components/password_manager/core/browser/password_manager_test_utils.h" #import "components/password_manager/core/browser/test_password_store.h" #import "components/password_manager/core/browser/ui/credential_ui_entry.h" @@ -46,18 +47,6 @@ using password_manager::InsecureType; using password_manager::TestPasswordStore; -// Sets test password store and returns pointer to it. -scoped_refptr<TestPasswordStore> BuildTestPasswordStore( - ChromeBrowserState* _browserState) { - return base::WrapRefCounted(static_cast<password_manager::TestPasswordStore*>( - IOSChromePasswordStoreFactory::GetInstance() - ->SetTestingFactoryAndUse( - _browserState, - base::BindRepeating(&password_manager::BuildPasswordStore< - web::BrowserState, TestPasswordStore>)) - .get())); -} - // Creates a saved password form. PasswordForm CreatePasswordForm() { PasswordForm form; @@ -132,10 +121,18 @@ builder.AddTestingFactory( SyncSetupServiceFactory::GetInstance(), base::BindRepeating(&SyncSetupServiceMock::CreateKeyedService)); + builder.AddTestingFactory( + IOSChromePasswordStoreFactory::GetInstance(), + base::BindRepeating( + &password_manager::BuildPasswordStore<web::BrowserState, + TestPasswordStore>)); browser_state_ = builder.Build(); - store_ = BuildTestPasswordStore(browser_state_.get()); - + store_ = + base::WrapRefCounted(static_cast<password_manager::TestPasswordStore*>( + IOSChromePasswordStoreFactory::GetForBrowserState( + browser_state_.get(), ServiceAccessType::EXPLICIT_ACCESS) + .get())); password_check_ = IOSChromePasswordCheckManagerFactory::GetForBrowserState( browser_state_.get());
diff --git a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm index a403a18..88f10d5 100644 --- a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm +++ b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm
@@ -111,18 +111,6 @@ using password_manager::TestPasswordStore; using l10n_util::GetNSString; -// Sets test password store and returns pointer to it. -scoped_refptr<TestPasswordStore> BuildTestPasswordStore( - ChromeBrowserState* _browserState) { - return base::WrapRefCounted(static_cast<password_manager::TestPasswordStore*>( - IOSChromePasswordStoreFactory::GetInstance() - ->SetTestingFactoryAndUse( - _browserState, - base::BindRepeating(&password_manager::BuildPasswordStore< - web::BrowserState, TestPasswordStore>)) - .get())); -} - // Registers account preference that will be used for Safe Browsing. PrefService* SetPrefService() { TestingPrefServiceSimple* prefs = new TestingPrefServiceSimple(); @@ -162,6 +150,11 @@ test_cbs_builder.AddTestingFactory( SyncSetupServiceFactory::GetInstance(), base::BindRepeating(&SyncSetupServiceMock::CreateKeyedService)); + test_cbs_builder.AddTestingFactory( + IOSChromePasswordStoreFactory::GetInstance(), + base::BindRepeating( + &password_manager::BuildPasswordStore<web::BrowserState, + TestPasswordStore>)); browser_state_ = test_cbs_builder.Build(); AuthenticationServiceFactory::CreateAndInitializeForBrowserState( browser_state_.get(), @@ -170,7 +163,11 @@ AuthenticationServiceFactory::GetInstance()->GetForBrowserState( browser_state_.get())); - store_ = BuildTestPasswordStore(browser_state_.get()); + store_ = + base::WrapRefCounted(static_cast<password_manager::TestPasswordStore*>( + IOSChromePasswordStoreFactory::GetForBrowserState( + browser_state_.get(), ServiceAccessType::EXPLICIT_ACCESS) + .get())); password_check_ = IOSChromePasswordCheckManagerFactory::GetForBrowserState( browser_state_.get());
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller_unittest.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller_unittest.mm index f5129cf..fc1d587 100644 --- a/ios/chrome/browser/ui/settings/settings_navigation_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/settings_navigation_controller_unittest.mm
@@ -56,6 +56,11 @@ test_cbs_builder.AddTestingFactory( ios::TemplateURLServiceFactory::GetInstance(), ios::TemplateURLServiceFactory::GetDefaultFactory()); + test_cbs_builder.AddTestingFactory( + IOSChromePasswordStoreFactory::GetInstance(), + base::BindRepeating( + &password_manager::BuildPasswordStore< + web::BrowserState, password_manager::TestPasswordStore>)); chrome_browser_state_ = test_cbs_builder.Build(); AuthenticationServiceFactory::CreateAndInitializeForBrowserState( chrome_browser_state_.get(), @@ -69,12 +74,6 @@ mockDelegate_ = [OCMockObject niceMockForProtocol:@protocol(SettingsNavigationControllerDelegate)]; - IOSChromePasswordStoreFactory::GetInstance()->SetTestingFactory( - browser_->GetBrowserState(), - base::BindRepeating( - &password_manager::BuildPasswordStore< - web::BrowserState, password_manager::TestPasswordStore>)); - TemplateURLService* template_url_service = ios::TemplateURLServiceFactory::GetForBrowserState( chrome_browser_state_.get());
diff --git a/ios/chrome/browser/ui/settings/settings_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/settings_table_view_controller_unittest.mm index c4a2772..c06ac0f 100644 --- a/ios/chrome/browser/ui/settings/settings_table_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/settings_table_view_controller_unittest.mm
@@ -6,6 +6,7 @@ #import "base/strings/sys_string_conversions.h" #import "base/test/task_environment.h" +#import "components/keyed_service/core/service_access_type.h" #import "components/password_manager/core/browser/password_manager_test_utils.h" #import "components/password_manager/core/browser/test_password_store.h" #import "components/policy/core/common/policy_loader_ios_constants.h" @@ -74,6 +75,11 @@ builder.AddTestingFactory( AuthenticationServiceFactory::GetInstance(), AuthenticationServiceFactory::GetDefaultFactory()); + builder.AddTestingFactory( + IOSChromePasswordStoreFactory::GetInstance(), + base::BindRepeating( + &password_manager::BuildPasswordStore< + web::BrowserState, password_manager::TestPasswordStore>)); chrome_browser_state_ = builder.Build(); browser_ = std::make_unique<TestBrowser>(chrome_browser_state_.get()); @@ -97,12 +103,8 @@ password_store_mock_ = base::WrapRefCounted(static_cast<password_manager::TestPasswordStore*>( - IOSChromePasswordStoreFactory::GetInstance() - ->SetTestingFactoryAndUse( - chrome_browser_state_.get(), - base::BindRepeating(&password_manager::BuildPasswordStore< - web::BrowserState, - password_manager::TestPasswordStore>)) + IOSChromePasswordStoreFactory::GetForBrowserState( + chrome_browser_state_.get(), ServiceAccessType::EXPLICIT_ACCESS) .get())); fake_identity_ = [FakeSystemIdentity fakeIdentity1];
diff --git a/ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller_unittest.mm index 951730d..570afb2 100644 --- a/ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller_unittest.mm
@@ -71,9 +71,8 @@ void SetUp() override { PassphraseTableViewControllerTest::SetUp(); mock_sync_setup_service_ = static_cast<NiceMock<SyncSetupServiceMock>*>( - SyncSetupServiceFactory::GetInstance()->SetTestingFactoryAndUse( - chrome_browser_state_.get(), - base::BindRepeating(&SyncSetupServiceMock::CreateKeyedService))); + SyncSetupServiceFactory::GetForBrowserState( + chrome_browser_state_.get())); ON_CALL(*fake_sync_service_, GetTransportState) .WillByDefault(Return(syncer::SyncService::TransportState::ACTIVE)); ON_CALL(*fake_sync_service_->GetMockUserSettings(), @@ -87,6 +86,13 @@ PassphraseTableViewControllerTest::TearDown(); } + void RegisterTestingFactories( + TestChromeBrowserState::Builder& builder) override { + builder.AddTestingFactory( + SyncSetupServiceFactory::GetInstance(), + base::BindRepeating(&SyncSetupServiceMock::CreateKeyedService)); + } + ChromeTableViewController* InstantiateController() override { return [[SyncEncryptionPassphraseTableViewController alloc] initWithBrowser:browser_.get()];
diff --git a/ios/chrome/browser/web_state_list/web_state_list.h b/ios/chrome/browser/web_state_list/web_state_list.h index bd1f513..71b85fd 100644 --- a/ios/chrome/browser/web_state_list/web_state_list.h +++ b/ios/chrome/browser/web_state_list/web_state_list.h
@@ -182,6 +182,10 @@ // is a bitwise combination of ClosingFlags values. void CloseWebStateAt(int index, int close_flags); + // Closes and destroys all non-pinned WebStates. The `close_flags` is a + // bitwise combination of ClosingFlags values. + void CloseAllNonPinnedWebStates(int close_flags); + // Closes and destroys all WebStates. The `close_flags` is a bitwise // combination of ClosingFlags values. void CloseAllWebStates(int close_flags); @@ -249,11 +253,11 @@ // Assumes that the WebStateList is locked. void CloseWebStateAtImpl(int index, int close_flags); - // Closes and destroys all WebStates. The `close_flags` is a bitwise - // combination of ClosingFlags values. + // Closes and destroys all WebStates after `start_index`. The `close_flags` + // is a bitwise combination of ClosingFlags values. // // Assumes that the WebStateList is locked. - void CloseAllWebStatesImpl(int close_flags); + void CloseAllWebStatesAfterIndexImpl(int start_index, int close_flags); // Makes the WebState at the specified index the active WebState. //
diff --git a/ios/chrome/browser/web_state_list/web_state_list.mm b/ios/chrome/browser/web_state_list/web_state_list.mm index dc0f8139..b417f80 100644 --- a/ios/chrome/browser/web_state_list/web_state_list.mm +++ b/ios/chrome/browser/web_state_list/web_state_list.mm
@@ -285,7 +285,23 @@ void WebStateList::CloseAllWebStates(int close_flags) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto lock = LockForMutation(); - return CloseAllWebStatesImpl(close_flags); + PerformBatchOperation(base::BindOnce( + [](int start_index, int close_flags, WebStateList* web_state_list) { + web_state_list->CloseAllWebStatesAfterIndexImpl(start_index, + close_flags); + }, + 0, close_flags)); +} + +void WebStateList::CloseAllNonPinnedWebStates(int close_flags) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + auto lock = LockForMutation(); + PerformBatchOperation(base::BindOnce( + [](int start_index, int close_flags, WebStateList* web_state_list) { + web_state_list->CloseAllWebStatesAfterIndexImpl(start_index, + close_flags); + }, + GetIndexOfFirstNonPinnedWebState(), close_flags)); } void WebStateList::ActivateWebStateAt(int index) { @@ -462,25 +478,33 @@ // Dropping detached_web_state will destroy it. } -void WebStateList::CloseAllWebStatesImpl(int close_flags) { +void WebStateList::CloseAllWebStatesAfterIndexImpl(int start_index, + int close_flags) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(locked_); - PerformBatchOperation(base::BindOnce( - [](int close_flags, WebStateList* web_state_list) { - // Since all the WebStates will be closed, notify that the active - // WebState is de-activated before closing them. This avoid sending - // one notification per WebState in the worst case (when the active - // WebState is the last one and no opener is set to any WebState). - web_state_list->ActivateWebStateAtImpl( - kInvalidIndex, ActiveWebStateChangeReason::Closed); + // Immediately determine the new active index to avoid + // sending multiple notification about changing active + // WebState. + int new_active_index = kInvalidIndex; + if (start_index != 0) { + std::vector<int> removing_indexes; + removing_indexes.reserve(count() - start_index); + for (int i = start_index; i < count(); ++i) { + removing_indexes.push_back(i); + } - // Close the WebStates from last to first. - while (!web_state_list->empty()) - web_state_list->CloseWebStateAtImpl(web_state_list->count() - 1, - close_flags); - }, - close_flags)); + WebStateListOrderController order_controller(*this); + new_active_index = order_controller.DetermineNewActiveIndex( + active_index_, + WebStateListRemovingIndexes(std::move(removing_indexes))); + } + + ActivateWebStateAtImpl(new_active_index, ActiveWebStateChangeReason::Closed); + + while (count() > start_index) { + CloseWebStateAtImpl(count() - 1, close_flags); + } } void WebStateList::ActivateWebStateAtImpl(int index,
diff --git a/ios/chrome/browser/web_state_list/web_state_list_unittest.mm b/ios/chrome/browser/web_state_list/web_state_list_unittest.mm index c0524ac..4211407e 100644 --- a/ios/chrome/browser/web_state_list/web_state_list_unittest.mm +++ b/ios/chrome/browser/web_state_list/web_state_list_unittest.mm
@@ -686,8 +686,104 @@ opener, start_index, false)); } -// Tests closing all webstates. -TEST_F(WebStateListTest, CloseAllWebStates) { +// Tests closing all non-pinned webstates (pinned WebStates present). +TEST_F(WebStateListTest, CloseAllNonPinnedWebStates_PinnedWebStatesPresent) { + AppendNewWebState(kURL0); + AppendNewWebState(kURL1); + AppendNewWebState(kURL2); + + web_state_list_.SetWebStatePinnedAt(0, true); + + // Sanity checks before closing WebStates. + EXPECT_EQ(3, web_state_list_.count()); + EXPECT_TRUE(web_state_list_.IsWebStatePinnedAt(0)); + + observer_.ResetStatistics(); + web_state_list_.CloseAllNonPinnedWebStates(WebStateList::CLOSE_USER_ACTION); + + EXPECT_EQ(1, web_state_list_.count()); + EXPECT_TRUE(web_state_list_.IsWebStatePinnedAt(0)); + + EXPECT_TRUE(observer_.web_state_detached_called()); + EXPECT_TRUE(observer_.batch_operation_started()); + EXPECT_TRUE(observer_.batch_operation_ended()); +} + +// Tests closing all non-pinned webstates (non-pinned WebStates not present). +TEST_F(WebStateListTest, + CloseAllNonPinnedWebStates_NonPinnedWebStatesNotPresent) { + AppendNewWebState(kURL0); + AppendNewWebState(kURL1); + AppendNewWebState(kURL2); + + web_state_list_.SetWebStatePinnedAt(0, true); + web_state_list_.SetWebStatePinnedAt(1, true); + web_state_list_.SetWebStatePinnedAt(2, true); + + // Sanity checks before closing WebStates. + EXPECT_EQ(3, web_state_list_.count()); + EXPECT_TRUE(web_state_list_.IsWebStatePinnedAt(0)); + EXPECT_TRUE(web_state_list_.IsWebStatePinnedAt(1)); + EXPECT_TRUE(web_state_list_.IsWebStatePinnedAt(2)); + + observer_.ResetStatistics(); + web_state_list_.CloseAllNonPinnedWebStates(WebStateList::CLOSE_USER_ACTION); + + EXPECT_EQ(3, web_state_list_.count()); + EXPECT_TRUE(web_state_list_.IsWebStatePinnedAt(0)); + EXPECT_TRUE(web_state_list_.IsWebStatePinnedAt(1)); + EXPECT_TRUE(web_state_list_.IsWebStatePinnedAt(2)); + + EXPECT_FALSE(observer_.web_state_detached_called()); + EXPECT_TRUE(observer_.batch_operation_started()); + EXPECT_TRUE(observer_.batch_operation_ended()); +} + +// Tests closing all non-pinned webstates (pinned WebStates not present). +TEST_F(WebStateListTest, CloseAllNonPinnedWebStates_PinnedWebStatesNotPresent) { + AppendNewWebState(kURL0); + AppendNewWebState(kURL1); + AppendNewWebState(kURL2); + + // Sanity checks before closing WebStates. + EXPECT_EQ(3, web_state_list_.count()); + + observer_.ResetStatistics(); + web_state_list_.CloseAllNonPinnedWebStates(WebStateList::CLOSE_USER_ACTION); + + EXPECT_EQ(0, web_state_list_.count()); + + EXPECT_TRUE(observer_.web_state_detached_called()); + EXPECT_TRUE(observer_.batch_operation_started()); + EXPECT_TRUE(observer_.batch_operation_ended()); +} + +// Tests closing all webstates (non-pinned). +TEST_F(WebStateListTest, CloseAllWebStates_NonPinned) { + AppendNewWebState(kURL0); + AppendNewWebState(kURL1); + AppendNewWebState(kURL2); + + web_state_list_.SetWebStatePinnedAt(0, true); + web_state_list_.SetWebStatePinnedAt(1, true); + + // Sanity check before closing WebStates. + EXPECT_EQ(3, web_state_list_.count()); + EXPECT_TRUE(web_state_list_.IsWebStatePinnedAt(0)); + EXPECT_TRUE(web_state_list_.IsWebStatePinnedAt(1)); + + observer_.ResetStatistics(); + web_state_list_.CloseAllWebStates(WebStateList::CLOSE_USER_ACTION); + + EXPECT_EQ(0, web_state_list_.count()); + + EXPECT_TRUE(observer_.web_state_detached_called()); + EXPECT_TRUE(observer_.batch_operation_started()); + EXPECT_TRUE(observer_.batch_operation_ended()); +} + +// Tests closing all webstates (pinned and non-pinned). +TEST_F(WebStateListTest, CloseAllWebStates_PinnedNonPinned) { AppendNewWebState(kURL0); AppendNewWebState(kURL1); AppendNewWebState(kURL2);
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn index c30903c..e6c0416 100644 --- a/ios/chrome/test/BUILD.gn +++ b/ios/chrome/test/BUILD.gn
@@ -236,6 +236,7 @@ "//ios/chrome/browser/overlays/public/web_content_area:unit_tests", "//ios/chrome/browser/overscroll_actions:unit_tests", "//ios/chrome/browser/passwords:unit_tests", + "//ios/chrome/browser/permissions:unit_tests", "//ios/chrome/browser/policy:unit_tests", "//ios/chrome/browser/prerender:unit_tests", "//ios/chrome/browser/promos_manager:unit_tests",
diff --git a/ios/chrome/test/data/policy/policy_test_cases.json b/ios/chrome/test/data/policy/policy_test_cases.json index b7f08bc..3fee4fa 100644 --- a/ios/chrome/test/data/policy/policy_test_cases.json +++ b/ios/chrome/test/data/policy/policy_test_cases.json
@@ -1,5 +1,43 @@ { "-- Instructions --": "See https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/enterprise/policy_pref_mapping_test.md (This file is interpreted by //ios/chrome/browser/policy/policy_unittest.mm)", + "AppStoreRatingEnabled": { + "os": [ + "ios" + ], + "policy_pref_mapping_tests": [ + { + "note": "Default value (no policies set).", + "prefs": { + "ios.app_store_rating_enabled": { + "location": "local_state", + "default_value": true + } + } + }, + { + "policies": { + "AppStoreRatingEnabled": false + }, + "prefs": { + "ios.app_store_rating_enabled": { + "location": "local_state", + "value": false + } + } + }, + { + "policies": { + "AppStoreRatingEnabled": true + }, + "prefs": { + "ios.app_store_rating_enabled": { + "location": "local_state", + "value": true + } + } + } + ] + }, "AutofillAddressEnabled": { "os": [ "ios"
diff --git a/media/base/byte_queue.cc b/media/base/byte_queue.cc index 53ed077..e6b2f0b 100644 --- a/media/base/byte_queue.cc +++ b/media/base/byte_queue.cc
@@ -9,10 +9,26 @@ #include "base/check_op.h" #include "base/numerics/checked_math.h" +#include "base/process/memory.h" namespace media { -ByteQueue::ByteQueue() : buffer_(new uint8_t[size_]) {} +ByteQueue::ByteQueue() { + uint8_t* new_buffer = nullptr; + + // Though ::Push() is allowed to fail memory allocation for `buffer_`, do not + // allow memory allocation failure here during ByteQueue construction. + // TODO(crbug.com/1266639): Consider refactoring to an Initialize() method + // that does this allocation and that can indicate failure, so callers can + // more gracefully handle the former OOM case that now fails this CHECK. For + // example, some StreamParsers create additional ByteQueues during Parse, so + // such handling could be a parse error in that case. Other handling + // customization could be done where ByteQueues are created as part of + // StreamParser creation. + CHECK(base::UncheckedMalloc(size_, reinterpret_cast<void**>(&new_buffer)) && + new_buffer); + buffer_.reset(new_buffer); +} ByteQueue::~ByteQueue() = default; @@ -21,7 +37,7 @@ used_ = 0; } -void ByteQueue::Push(const uint8_t* data, int size) { +bool ByteQueue::Push(const uint8_t* data, int size) { DCHECK(data); DCHECK_GT(size, 0); @@ -35,24 +51,28 @@ (base::CheckedNumeric<size_t>(size_) + size_ / 4).ValueOrDie(); const size_t new_size = std::max(size_needed, safe_size); - // Copy the data from the old buffer to the start of the new one. - if (used_ > 0) { - // Note: We could use realloc() here, but would need an additional move to - // pack data at offset_ = 0 after a potential internal new allocation + - // copy by realloc(). - // - // In local tests on a few top video sites that ends up being the common - // case, so just prefer to copy and pack ourselves. - auto new_buffer = std::make_unique<uint8_t[]>(new_size); - memcpy(new_buffer.get(), Front(), used_); - buffer_ = std::move(new_buffer); - } else { - // Free the existing |data| first so that the memory can be reused, if - // possible. Note that the new array is purposely not initialized. - buffer_.reset(); - buffer_ = std::make_unique<uint8_t[]>(new_size); + // Try to obtain a new backing buffer of `new_size` capacity. Note: If + // `used_` is positive, we could use realloc() here, but would need an + // additional move to pack data at offset_ = 0 after a potential internal + // new allocation + copy by realloc(). In local tests on a few top video + // sites that ends up being the common case, so just prefer to copy and pack + // ourselves. Further, we need to handle potential allocation failure, since + // callers may have fallback paths for that scenario, and the allocation + // path allowing this must not be used with realloc. + uint8_t* new_buffer = nullptr; + if (!base::UncheckedMalloc(new_size, + reinterpret_cast<void**>(&new_buffer)) || + !new_buffer) { + return false; } + // Note that the new array is purposely not initialized. Copy the data, if + // any, from the old buffer to the start of the new one. + if (used_ > 0) { + memcpy(new_buffer, Front(), used_); + } + + buffer_.reset(new_buffer); // This also frees the previous `buffer_`. size_ = new_size; offset_ = 0; } else if ((offset_ + used_ + size) > size_) { @@ -63,6 +83,8 @@ memcpy(Front() + used_, data, size); used_ += size; + + return true; } void ByteQueue::Peek(const uint8_t** data, int* size) const {
diff --git a/media/base/byte_queue.h b/media/base/byte_queue.h index 18b425f41..d564897 100644 --- a/media/base/byte_queue.h +++ b/media/base/byte_queue.h
@@ -10,6 +10,7 @@ #include <memory> +#include "base/process/memory.h" #include "media/base/media_export.h" namespace media { @@ -32,8 +33,10 @@ // Reset the queue to the empty state. void Reset(); - // Appends new bytes onto the end of the queue. - void Push(const uint8_t* data, int size); + // Appends new bytes onto the end of the queue. If allocation failure occurs, + // then the append of `data` is not done and returns false. Otherwise, returns + // true. + [[nodiscard]] bool Push(const uint8_t* data, int size); // Get a pointer to the front of the queue and the queue size. These values // are only valid until the next Push() or Pop() call. @@ -58,7 +61,7 @@ // Number of bytes stored in |buffer_|. int used_ = 0; - std::unique_ptr<uint8_t[]> buffer_; + std::unique_ptr<uint8_t, base::UncheckedFreeDeleter> buffer_; }; } // namespace media
diff --git a/media/base/stream_parser.h b/media/base/stream_parser.h index 2f27fd53..e582b9a4 100644 --- a/media/base/stream_parser.h +++ b/media/base/stream_parser.h
@@ -173,9 +173,6 @@ // `QuotaExceededErr` exception per the MSE specification. App could use a // back-off and retry strategy or otherwise alter their behavior to attempt to // buffer media for further playback. - // TODO(crbug.com/1286810): Update resource allocation paths in the - // StreamParser implementations of this method to recognize and report - // allocation failure. [[nodiscard]] virtual bool AppendToParseBuffer(const uint8_t* buf, size_t size) = 0;
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc index e997e30..68cd8d4 100644 --- a/media/filters/chunk_demuxer.cc +++ b/media/filters/chunk_demuxer.cc
@@ -939,7 +939,10 @@ case INITIALIZED: DCHECK(IsValidId_Locked(id)); if (!source_state_map_[id]->AppendToParseBuffer(data, length)) { - ReportError_Locked(CHUNK_DEMUXER_ERROR_APPEND_FAILED); + // Just indicate that the append failed. Let the caller give app an + // error so that it may adapt. This is different from + // RunSegmentParserLoop(), where fatal MediaSource failure should + // occur if the underlying parse fails. return false; } break;
diff --git a/media/filters/chunk_demuxer.h b/media/filters/chunk_demuxer.h index 6aac01d..9cb07af 100644 --- a/media/filters/chunk_demuxer.h +++ b/media/filters/chunk_demuxer.h
@@ -305,9 +305,6 @@ // per the MSE specification. App could use a back-off and retry strategy or // otherwise alter their behavior to attempt to buffer media for further // playback. - // TODO(crbug.com/1286810): Update resource allocation paths in the - // StreamParser implementations eventually executed within this method to - // recognize and report allocation failure. [[nodiscard]] bool AppendToParseBuffer(const std::string& id, const uint8_t* data, size_t length);
diff --git a/media/filters/source_buffer_state.h b/media/filters/source_buffer_state.h index a49d7a6..31deb83 100644 --- a/media/filters/source_buffer_state.h +++ b/media/filters/source_buffer_state.h
@@ -66,9 +66,6 @@ // append failure using a `QuotaExceededErr` exception per the MSE // specification. App could use a back-off and retry strategy or otherwise // alter their behavior to attempt to buffer media for further playback. - // TODO(crbug.com/1286810): Update resource allocation paths in the - // StreamParser implementations called by this method to recognize and report - // allocation failure. [[nodiscard]] bool AppendToParseBuffer(const uint8_t* data, size_t length); // Tells the stream parser to parse more of the data previously sent to it
diff --git a/media/formats/common/offset_byte_queue.cc b/media/formats/common/offset_byte_queue.cc index 47efd0cd..782e3c6 100644 --- a/media/formats/common/offset_byte_queue.cc +++ b/media/formats/common/offset_byte_queue.cc
@@ -19,10 +19,15 @@ head_ = 0; } -void OffsetByteQueue::Push(const uint8_t* buf, int size) { - queue_.Push(buf, size); +bool OffsetByteQueue::Push(const uint8_t* buf, int size) { + if (!queue_.Push(buf, size)) { + DVLOG(4) << "Failed to push buf of size " << size; + Sync(); + return false; + } Sync(); DVLOG(4) << "Buffer pushed. head=" << head() << " tail=" << tail(); + return true; } void OffsetByteQueue::Peek(const uint8_t** buf, int* size) {
diff --git a/media/formats/common/offset_byte_queue.h b/media/formats/common/offset_byte_queue.h index 41ab1007..6e9468db 100644 --- a/media/formats/common/offset_byte_queue.h +++ b/media/formats/common/offset_byte_queue.h
@@ -27,7 +27,7 @@ // These work like their underlying ByteQueue counterparts. void Reset(); - void Push(const uint8_t* buf, int size); + [[nodiscard]] bool Push(const uint8_t* buf, int size); void Peek(const uint8_t** buf, int* size); void Pop(int count);
diff --git a/media/formats/common/offset_byte_queue_unittest.cc b/media/formats/common/offset_byte_queue_unittest.cc index 1361055..02b538e 100644 --- a/media/formats/common/offset_byte_queue_unittest.cc +++ b/media/formats/common/offset_byte_queue_unittest.cc
@@ -21,8 +21,8 @@ buf[i] = i; } queue_ = std::make_unique<OffsetByteQueue>(); - queue_->Push(buf, sizeof(buf)); - queue_->Push(buf, sizeof(buf)); + ASSERT_TRUE(queue_->Push(buf, sizeof(buf))) << "Test should not hit OOM"; + ASSERT_TRUE(queue_->Push(buf, sizeof(buf))) << "Test should not hit OOM"; queue_->Pop(384); // Queue will start with 128 bytes of data and an offset of 384 bytes.
diff --git a/media/formats/mp2t/es_parser.cc b/media/formats/mp2t/es_parser.cc index 2c17bc7..a7d9342 100644 --- a/media/formats/mp2t/es_parser.cc +++ b/media/formats/mp2t/es_parser.cc
@@ -4,6 +4,8 @@ #include "media/formats/mp2t/es_parser.h" +#include "base/logging.h" +#include "media/base/byte_queue.h" #include "media/base/stream_parser_buffer.h" #include "media/base/timestamp_constants.h" #include "media/formats/common/offset_byte_queue.h" @@ -45,7 +47,11 @@ } // Add the incoming bytes to the ES queue. - es_queue_->Push(buf, size); + if (!es_queue_->Push(buf, size)) { + DVLOG(2) << "Failed to push buf of size " << size; + return false; + } + return ParseFromEsQueue(); }
diff --git a/media/formats/mp2t/es_parser_h264.cc b/media/formats/mp2t/es_parser_h264.cc index 0cc43f5..daa7723 100644 --- a/media/formats/mp2t/es_parser_h264.cc +++ b/media/formats/mp2t/es_parser_h264.cc
@@ -216,9 +216,16 @@ // Simulate an additional AUD to force emitting the last access unit // which is assumed to be complete at this point. uint8_t aud[] = {0x00, 0x00, 0x01, 0x09}; - es_queue_->Push(aud, sizeof(aud)); - ParseFromEsQueue(); + // Fail if this AUD's push fails allocation, since otherwise the behavior of + // the subsequent parse would vary based on whether or not the system is + // near-OOM. + // TODO(crbug.com/1266639): Consider plumbing parse failure for this push + // failure case, instead of what used to OOM but now instead would fail this + // CHECK. + CHECK(es_queue_->Push(aud, sizeof(aud))); + + ParseFromEsQueue(); es_adapter_.Flush(); }
diff --git a/media/formats/mp2t/mp2t_stream_parser.cc b/media/formats/mp2t/mp2t_stream_parser.cc index ec6213f..0e7fc3d 100644 --- a/media/formats/mp2t/mp2t_stream_parser.cc +++ b/media/formats/mp2t/mp2t_stream_parser.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/numerics/checked_math.h" +#include "media/base/byte_queue.h" #include "media/base/media_tracks.h" #include "media/base/stream_parser.h" #include "media/base/stream_parser_buffer.h" @@ -334,7 +335,10 @@ // Add the data to the parser state. uninspected_pending_bytes_ = base::checked_cast<int>(size); - ts_byte_queue_.Push(buf, uninspected_pending_bytes_); + if (!ts_byte_queue_.Push(buf, uninspected_pending_bytes_)) { + DVLOG(2) << "AppendToParseBuffer(): Failed to push buf of size " << size; + return false; + } return true; }
diff --git a/media/formats/mp2t/ts_section_pes.cc b/media/formats/mp2t/ts_section_pes.cc index c6bf662..2f4588d 100644 --- a/media/formats/mp2t/ts_section_pes.cc +++ b/media/formats/mp2t/ts_section_pes.cc
@@ -9,6 +9,7 @@ #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "media/base/bit_reader.h" +#include "media/base/byte_queue.h" #include "media/base/stream_parser_buffer.h" #include "media/base/timestamp_constants.h" #include "media/formats/mp2t/es_parser.h" @@ -76,8 +77,9 @@ } // Add the data to the parser state. - if (size > 0) - pes_byte_queue_.Push(buf, size); + if (size > 0) { + RCHECK(pes_byte_queue_.Push(buf, size)); // Can fail if allocation fails. + } // Try emitting the current PES packet. return (parse_result && Emit(false));
diff --git a/media/formats/mp2t/ts_section_psi.cc b/media/formats/mp2t/ts_section_psi.cc index ca7a88b..65e5a43 100644 --- a/media/formats/mp2t/ts_section_psi.cc +++ b/media/formats/mp2t/ts_section_psi.cc
@@ -8,6 +8,7 @@ #include "base/logging.h" #include "media/base/bit_reader.h" +#include "media/base/byte_queue.h" #include "media/formats/mp2t/mp2t_common.h" static bool IsCrcValid(const uint8_t* buf, int size) { @@ -77,7 +78,7 @@ return true; // Add the data to the parser state. - psi_byte_queue_.Push(buf, size); + RCHECK(psi_byte_queue_.Push(buf, size)); // Can fail if allocation fails. int raw_psi_size; const uint8_t* raw_psi; psi_byte_queue_.Peek(&raw_psi, &raw_psi_size);
diff --git a/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc index 2f70c7c4..27e2b9d 100644 --- a/media/formats/mp4/mp4_stream_parser.cc +++ b/media/formats/mp4/mp4_stream_parser.cc
@@ -149,7 +149,11 @@ // could lead to memory corruption, preferring CHECK. CHECK_EQ(queue_.tail(), max_parse_offset_); - queue_.Push(buf, base::checked_cast<int>(size)); + if (!queue_.Push(buf, base::checked_cast<int>(size))) { + DVLOG(2) << "AppendToParseBuffer(): Failed to push buf of size " << size; + return false; + } + return true; }
diff --git a/media/formats/mpeg/mpeg_audio_stream_parser_base.cc b/media/formats/mpeg/mpeg_audio_stream_parser_base.cc index b2fd133..5e77078 100644 --- a/media/formats/mpeg/mpeg_audio_stream_parser_base.cc +++ b/media/formats/mpeg/mpeg_audio_stream_parser_base.cc
@@ -10,6 +10,7 @@ #include "base/callback_helpers.h" #include "base/numerics/checked_math.h" #include "base/time/time.h" +#include "media/base/byte_queue.h" #include "media/base/media_log.h" #include "media/base/media_tracks.h" #include "media/base/media_util.h" @@ -132,7 +133,10 @@ CHECK_EQ(uninspected_pending_bytes_, 0); uninspected_pending_bytes_ = base::checked_cast<int>(size); - queue_.Push(buf, uninspected_pending_bytes_); + if (!queue_.Push(buf, uninspected_pending_bytes_)) { + DVLOG(2) << "AppendToParseBuffer(): Failed to push buf of size " << size; + return false; + } return true; }
diff --git a/media/formats/webm/webm_stream_parser.cc b/media/formats/webm/webm_stream_parser.cc index 36a000a..f3640d9 100644 --- a/media/formats/webm/webm_stream_parser.cc +++ b/media/formats/webm/webm_stream_parser.cc
@@ -12,6 +12,7 @@ #include "base/logging.h" #include "base/numerics/checked_math.h" #include "base/strings/string_number_conversions.h" +#include "media/base/byte_queue.h" #include "media/base/media_track.h" #include "media/base/media_tracks.h" #include "media/base/stream_parser.h" @@ -102,7 +103,10 @@ CHECK_EQ(uninspected_pending_bytes_, 0); uninspected_pending_bytes_ = base::checked_cast<int>(size); - byte_queue_.Push(buf, uninspected_pending_bytes_); + if (!byte_queue_.Push(buf, uninspected_pending_bytes_)) { + DVLOG(2) << "AppendToParseBuffer(): Failed to push buf of size " << size; + return false; + } return true; }
diff --git a/media/gpu/chromeos/image_processor_factory.cc b/media/gpu/chromeos/image_processor_factory.cc index 96b9eb5e..afd526b 100644 --- a/media/gpu/chromeos/image_processor_factory.cc +++ b/media/gpu/chromeos/image_processor_factory.cc
@@ -284,18 +284,18 @@ if (processor) return processor; } - if (base::FeatureList::IsEnabled(media::kPreferLibYuvImageProcessor)) { + auto processor = CreateLibYUVImageProcessorWithInputCandidates( input_candidates, input_visible_rect, output_size, client_task_runner, out_format_picker, error_cb); if (processor) return processor; - } - auto processor = CreateV4L2ImageProcessorWithInputCandidates( - input_candidates, input_visible_rect, num_buffers, client_task_runner, - out_format_picker, error_cb); - if (processor) - return processor; + + processor = CreateV4L2ImageProcessorWithInputCandidates( + input_candidates, input_visible_rect, num_buffers, client_task_runner, + out_format_picker, error_cb); + if (processor) + return processor; #endif
diff --git a/media/video/gpu_video_accelerator_factories.h b/media/video/gpu_video_accelerator_factories.h index eb08a3bd..beb43bd2 100644 --- a/media/video/gpu_video_accelerator_factories.h +++ b/media/video/gpu_video_accelerator_factories.h
@@ -160,9 +160,6 @@ // May be called on any thread. virtual void NotifyEncoderSupportKnown(base::OnceClosure callback) = 0; - // Caller owns returned pointer, but should call Destroy() on it (instead of - // directly deleting) for proper destruction, as per the - // VideoEncodeAccelerator interface. virtual std::unique_ptr<VideoEncodeAccelerator> CreateVideoEncodeAccelerator() = 0;
diff --git a/media/video/video_encode_accelerator.h b/media/video/video_encode_accelerator.h index 61a515a0..f37a1d50 100644 --- a/media/video/video_encode_accelerator.h +++ b/media/video/video_encode_accelerator.h
@@ -456,7 +456,7 @@ virtual bool IsGpuFrameResizeSupported(); protected: - // Do not delete directly; use Destroy() or own it with a scoped_ptr, which + // Do not delete directly; use Destroy() or own it with a unique_ptr, which // will Destroy() it properly by default. virtual ~VideoEncodeAccelerator(); };
diff --git a/net/BUILD.gn b/net/BUILD.gn index 2b8bda07..f87eb48 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -3510,6 +3510,9 @@ "data/verify_certificate_chain_unittest/root-lacks-basic-constraints/chain.pem", "data/verify_certificate_chain_unittest/root-lacks-basic-constraints/main.test", "data/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-constraints.test", + "data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/chain.pem", + "data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/main.test", + "data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/ta-with-constraints.test", "data/verify_certificate_chain_unittest/target-and-intermediate/chain.pem", "data/verify_certificate_chain_unittest/target-and-intermediate/distrusted-root-expired.test", "data/verify_certificate_chain_unittest/target-and-intermediate/distrusted-root.test",
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc index f1066db..3b9ccb9d 100644 --- a/net/cert/cert_verify_proc_unittest.cc +++ b/net/cert/cert_verify_proc_unittest.cc
@@ -4798,7 +4798,7 @@ if (VerifyProcTypeIsBuiltin()) { EXPECT_THAT(Verify(), IsOk()); - EXPECT_THAT(VerifyWithExpiryAndConstraints(), IsOk()); + EXPECT_THAT(VerifyWithExpiryAndConstraints(), IsError(ERR_CERT_INVALID)); } else if (VerifyProcTypeIsMacAtMostOS10_14() || verify_proc_type() == CERT_VERIFY_PROC_ANDROID) { EXPECT_THAT(Verify(), IsOk());
diff --git a/net/cert/pki/verify_certificate_chain.cc b/net/cert/pki/verify_certificate_chain.cc index ec4081b..d84ed652 100644 --- a/net/cert/pki/verify_certificate_chain.cc +++ b/net/cert/pki/verify_certificate_chain.cc
@@ -1199,6 +1199,14 @@ void PathVerifier::ApplyTrustAnchorConstraints(const ParsedCertificate& cert, KeyPurpose required_key_purpose, CertErrors* errors) { + // If keyUsage is present, verify that |cert| has correct keyUsage bits for a + // CA. This matches the handling for intermediates from RFC 5280 section + // 6.1.4 step n. + if (cert.has_key_usage() && + !cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)) { + errors->AddError(cert_errors::kKeyCertSignBitNotSet); + } + // This is not part of RFC 5937 nor RFC 5280, but matches the EKU handling // done for intermediates (described in Web PKI's Baseline Requirements). VerifyExtendedKeyUsage(cert, required_key_purpose, errors,
diff --git a/net/cert/pki/verify_certificate_chain.h b/net/cert/pki/verify_certificate_chain.h index 0e87f7a..5bfe8a54 100644 --- a/net/cert/pki/verify_certificate_chain.h +++ b/net/cert/pki/verify_certificate_chain.h
@@ -222,7 +222,7 @@ // // * Signature: No // * Validity (expiration): No -// * Key usage: No +// * Key usage: Yes // * Extended key usage: Yes (required if required_key_purpose is STRICT) // * Basic constraints: Yes // * Name constraints: Yes
diff --git a/net/cert/pki/verify_certificate_chain_typed_unittest.h b/net/cert/pki/verify_certificate_chain_typed_unittest.h index 183f6fb..fc913a8 100644 --- a/net/cert/pki/verify_certificate_chain_typed_unittest.h +++ b/net/cert/pki/verify_certificate_chain_typed_unittest.h
@@ -136,6 +136,9 @@ this->RunTest("target-serverauth-various-keyusages/ec-digitalSignature.test"); this->RunTest("target-serverauth-various-keyusages/ec-keyAgreement.test"); this->RunTest("target-serverauth-various-keyusages/ec-keyEncipherment.test"); + + this->RunTest("root-lacks-keycertsign-key-usage/main.test"); + this->RunTest("root-lacks-keycertsign-key-usage/ta-with-constraints.test"); } TYPED_TEST_P(VerifyCertificateChainSingleRootTest, ExtendedKeyUsage) {
diff --git a/net/data/gencerts/__init__.py b/net/data/gencerts/__init__.py index 7d2e4590..d1c77d9 100755 --- a/net/data/gencerts/__init__.py +++ b/net/data/gencerts/__init__.py
@@ -123,7 +123,7 @@ # If the file doesn't already exist, generate a new key using the generation # parameters. if not os.path.isfile(path): - key_contents = subprocess.check_output(generation_arguments) + key_contents = subprocess.check_output(generation_arguments, text=True) # Prepend the generation parameters to the key file. write_string_to_file(generation_arguments_str + '\n' + key_contents,
diff --git a/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/chain.pem b/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/chain.pem new file mode 100644 index 0000000..fb858e4d --- /dev/null +++ b/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/chain.pem
@@ -0,0 +1,266 @@ +[Created by: ./generate-chains.py] + +Certificate chain where the root keyUsage extension is present but does not +contain keyCertSign. + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 4d:9c:b5:b6:68:93:5e:c6:e1:a7:65:67:49:b3:e4:0e:bd:5e:63:b4 + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Intermediate + Validity + Not Before: Oct 5 12:00:00 2021 GMT + Not After : Oct 5 12:00:00 2022 GMT + Subject: CN=Target + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b1:1c:a4:b9:20:81:72:4b:f5:2c:50:7e:3f:1a: + 85:27:5b:2d:50:7c:e5:36:fd:9c:ac:26:a0:7d:b7: + 94:d5:6b:fd:c3:46:1a:dc:4d:10:45:98:cc:87:8d: + af:fc:0e:bc:c9:b2:61:4b:8c:c2:9b:c8:da:7b:05: + b3:3b:e0:21:95:a5:9c:01:72:34:48:3d:e4:44:f2: + e7:b6:6b:58:f4:8d:60:92:c8:91:29:41:23:29:23: + fd:da:62:d0:c3:78:92:5f:01:09:55:2e:3a:a2:b3: + 2c:2d:c5:cd:79:26:7a:66:bc:e3:a5:17:51:ae:b7: + 29:50:75:10:6f:2c:55:a9:79:04:21:05:3b:14:32: + 65:7c:3a:2c:33:ea:6b:72:20:f1:87:31:f2:8f:27: + 69:4f:50:1d:c2:18:36:8e:b8:6d:c4:b8:0b:7a:23: + 87:e1:48:84:ec:44:98:77:df:a7:7a:06:37:4d:42: + 33:40:e2:b2:c9:67:2f:94:20:69:5c:6d:30:1a:b8: + c5:60:9e:32:6e:4d:b2:85:de:94:b9:86:50:f9:0c: + 72:06:34:bb:f0:4a:fc:cd:c8:89:7b:eb:69:e5:64: + e8:55:4c:12:79:cc:81:88:26:f6:59:22:d5:60:8c: + 36:4f:96:30:e2:ea:f4:10:dc:82:08:d2:3b:e2:05: + 13:77 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + A9:6C:19:42:95:E3:95:C7:FF:D2:0F:BD:2C:E9:43:1F:2E:09:A2:C7 + X509v3 Authority Key Identifier: + 5E:60:7B:07:9D:3D:65:C3:D3:DE:FB:C8:28:BE:34:22:10:C9:C4:A2 + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Intermediate.cer + X509v3 CRL Distribution Points: + Full Name: + URI:http://url-for-crl/Intermediate.crl + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 14:bf:fa:03:43:bd:68:2c:77:55:2b:4a:49:ed:1b:71:4d:50: + 0c:91:f8:c0:2c:db:66:d8:a9:45:86:25:f6:cf:3a:db:94:e9: + c2:c9:76:3f:c1:b3:1f:58:08:e8:05:d2:2f:de:82:35:ad:87: + 56:c7:a8:d9:2c:e4:1a:a9:3f:91:52:cc:82:1b:2d:6d:83:99: + 7e:2a:0f:90:93:a7:d3:09:a6:53:49:bc:d2:73:08:73:77:9c: + 5d:d8:7b:3e:ae:42:e3:2d:d5:89:1c:45:de:06:3d:99:a9:e8: + 63:f9:27:f7:01:1c:aa:85:00:1e:37:11:8d:4b:c0:a0:b4:fe: + 16:30:6f:da:88:8e:a9:34:33:9b:9d:6c:d7:f2:c8:e6:86:9d: + f4:07:60:7e:86:fc:fb:4a:22:a4:cf:84:95:dc:da:cd:35:46: + 71:d3:d3:71:e2:50:0b:a9:8c:25:1e:dc:13:9d:f6:e2:90:fa: + dd:64:a2:d4:d8:04:fd:64:eb:77:c7:87:88:b5:1a:90:0b:d1: + e3:5f:5c:94:3a:8d:3b:6b:ad:f7:9c:27:8f:dd:a2:b7:de:64: + fb:2f:c1:8e:b0:49:88:30:e8:2e:c9:49:26:a2:ad:3f:f8:b5: + 4c:7a:d0:42:33:18:ae:fc:c1:29:66:8a:3d:7b:88:83:48:f6: + 77:c0:02:d1 +-----BEGIN CERTIFICATE----- +MIIDoDCCAoigAwIBAgIUTZy1tmiTXsbhp2VnSbPkDr1eY7QwDQYJKoZIhvcNAQEL +BQAwFzEVMBMGA1UEAwwMSW50ZXJtZWRpYXRlMB4XDTIxMTAwNTEyMDAwMFoXDTIy +MTAwNTEyMDAwMFowETEPMA0GA1UEAwwGVGFyZ2V0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAsRykuSCBckv1LFB+PxqFJ1stUHzlNv2crCagfbeU1Wv9 +w0Ya3E0QRZjMh42v/A68ybJhS4zCm8jaewWzO+AhlaWcAXI0SD3kRPLntmtY9I1g +ksiRKUEjKSP92mLQw3iSXwEJVS46orMsLcXNeSZ6ZrzjpRdRrrcpUHUQbyxVqXkE +IQU7FDJlfDosM+prciDxhzHyjydpT1Adwhg2jrhtxLgLeiOH4UiE7ESYd9+negY3 +TUIzQOKyyWcvlCBpXG0wGrjFYJ4ybk2yhd6UuYZQ+QxyBjS78Er8zciJe+tp5WTo +VUwSecyBiCb2WSLVYIw2T5Yw4ur0ENyCCNI74gUTdwIDAQABo4HpMIHmMB0GA1Ud +DgQWBBSpbBlCleOVx//SD70s6UMfLgmixzAfBgNVHSMEGDAWgBReYHsHnT1lw9Pe ++8govjQiEMnEojA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUHMAKGI2h0dHA6Ly91 +cmwtZm9yLWFpYS9JbnRlcm1lZGlhdGUuY2VyMDQGA1UdHwQtMCswKaAnoCWGI2h0 +dHA6Ly91cmwtZm9yLWNybC9JbnRlcm1lZGlhdGUuY3JsMA4GA1UdDwEB/wQEAwIF +oDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQAD +ggEBABS/+gNDvWgsd1UrSkntG3FNUAyR+MAs22bYqUWGJfbPOtuU6cLJdj/Bsx9Y +COgF0i/egjWth1bHqNks5BqpP5FSzIIbLW2DmX4qD5CTp9MJplNJvNJzCHN3nF3Y +ez6uQuMt1YkcRd4GPZmp6GP5J/cBHKqFAB43EY1LwKC0/hYwb9qIjqk0M5udbNfy +yOaGnfQHYH6G/PtKIqTPhJXc2s01RnHT03HiUAupjCUe3BOd9uKQ+t1kotTYBP1k +63fHh4i1GpAL0eNfXJQ6jTtrrfecJ4/dorfeZPsvwY6wSYgw6C7JSSairT/4tUx6 +0EIzGK78wSlmij17iINI9nfAAtE= +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 54:e3:4d:7d:5e:fd:13:7b:9f:32:55:f3:77:55:e6:39:52:6f:ef:40 + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root + Validity + Not Before: Oct 5 12:00:00 2021 GMT + Not After : Oct 5 12:00:00 2022 GMT + Subject: CN=Intermediate + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:9c:38:da:61:b8:ad:0d:aa:de:44:df:52:78:01: + 82:89:fb:5f:bd:fc:a9:79:d0:8d:10:5c:3c:4e:b7: + b5:43:36:bc:05:3a:0c:4e:54:88:00:45:fb:33:25: + ca:cf:3a:aa:ad:a4:de:d2:2e:c1:53:44:b8:f5:58: + e7:27:19:5a:70:34:71:c7:4d:77:1f:53:f2:66:b9: + 79:e8:c2:10:8c:2f:5d:19:17:7e:e3:26:7e:0c:5d: + 8e:ae:85:01:f7:05:ac:ce:18:5d:7c:a4:fa:fc:38: + e6:18:63:a5:4c:d0:a3:cb:a3:e6:47:ad:5f:ec:32: + fc:11:02:87:cb:fa:87:c9:38:aa:b8:b2:7e:98:99: + 1b:4e:f3:01:fc:48:6a:60:a5:29:80:3c:0c:50:23: + 3a:ae:0a:a6:d4:29:69:1e:15:34:ed:93:31:fb:30: + d4:d6:23:59:94:89:fa:99:b4:16:d8:04:63:d0:c3: + a9:2d:be:ff:6a:84:c7:54:bb:e8:eb:bd:16:5b:88: + 33:10:1b:6e:20:4f:60:49:56:09:86:dc:95:fc:c5: + d9:2c:de:03:32:88:fc:3a:84:06:48:92:10:7c:2d: + b9:6a:25:fd:93:c0:51:75:bd:54:e7:ba:0b:bb:d8: + b3:f5:60:55:9e:c7:06:70:fd:f3:f0:13:8e:a8:33: + 17:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 5E:60:7B:07:9D:3D:65:C3:D3:DE:FB:C8:28:BE:34:22:10:C9:C4:A2 + X509v3 Authority Key Identifier: + 20:1D:40:05:AB:57:09:3B:3A:83:BE:19:65:15:EB:74:EF:0C:0D:D7 + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Root.cer + X509v3 CRL Distribution Points: + Full Name: + URI:http://url-for-crl/Root.crl + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 12:3c:5d:46:a3:a4:11:4c:f6:d7:cc:92:61:b0:fd:ec:b6:12: + 37:3f:52:43:39:5e:8b:ff:5f:a9:09:3e:3b:3a:e4:c9:ec:59: + 00:8d:08:12:f9:b5:bd:8b:f4:41:dd:ff:d4:5c:5f:58:e7:e7: + 8c:a9:96:60:f0:78:27:7c:ca:da:24:67:93:ff:72:58:50:6b: + 8c:f2:11:da:8b:27:1b:68:9a:e0:9d:59:78:64:0d:d1:c4:c2: + 72:5f:9f:ef:32:d6:65:10:38:62:54:97:d5:03:cf:c4:a5:34: + f6:d2:d0:dd:b4:fc:08:49:2d:43:55:7c:2d:43:a1:1c:30:65: + b2:30:f8:5a:0a:ce:e8:1e:ad:c0:41:2d:d3:a2:64:76:3b:e8: + 82:3a:5b:93:f3:e8:84:de:7e:20:8d:05:06:2b:82:fd:6d:7c: + 35:6a:04:05:c0:6c:1b:91:6d:db:b3:a7:a5:35:42:9f:af:69: + 22:81:a9:f7:58:1c:fc:f1:31:54:26:f6:c5:b9:67:d0:da:eb: + 01:bd:69:10:de:ea:d3:95:29:ab:f2:59:8d:62:b9:01:b2:32: + 75:b7:47:3c:39:51:5d:be:46:48:da:19:f2:a8:61:8c:5f:cf: + 9c:a9:c9:92:a8:4e:ef:5c:8a:3f:73:fd:38:91:c2:90:33:c6: + 60:8e:67:22 +-----BEGIN CERTIFICATE----- +MIIDgDCCAmigAwIBAgIUVONNfV79E3ufMlXzd1XmOVJv70AwDQYJKoZIhvcNAQEL +BQAwDzENMAsGA1UEAwwEUm9vdDAeFw0yMTEwMDUxMjAwMDBaFw0yMjEwMDUxMjAw +MDBaMBcxFTATBgNVBAMMDEludGVybWVkaWF0ZTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAJw42mG4rQ2q3kTfUngBgon7X738qXnQjRBcPE63tUM2vAU6 +DE5UiABF+zMlys86qq2k3tIuwVNEuPVY5ycZWnA0ccdNdx9T8ma5eejCEIwvXRkX +fuMmfgxdjq6FAfcFrM4YXXyk+vw45hhjpUzQo8uj5ketX+wy/BECh8v6h8k4qriy +fpiZG07zAfxIamClKYA8DFAjOq4KptQpaR4VNO2TMfsw1NYjWZSJ+pm0FtgEY9DD +qS2+/2qEx1S76Ou9FluIMxAbbiBPYElWCYbclfzF2SzeAzKI/DqEBkiSEHwtuWol +/ZPAUXW9VOe6C7vYs/VgVZ7HBnD98/ATjqgzF/8CAwEAAaOByzCByDAdBgNVHQ4E +FgQUXmB7B509ZcPT3vvIKL40IhDJxKIwHwYDVR0jBBgwFoAUIB1ABatXCTs6g74Z +ZRXrdO8MDdcwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzAChhtodHRwOi8vdXJs +LWZvci1haWEvUm9vdC5jZXIwLAYDVR0fBCUwIzAhoB+gHYYbaHR0cDovL3VybC1m +b3ItY3JsL1Jvb3QuY3JsMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ +MA0GCSqGSIb3DQEBCwUAA4IBAQASPF1Go6QRTPbXzJJhsP3sthI3P1JDOV6L/1+p +CT47OuTJ7FkAjQgS+bW9i/RB3f/UXF9Y5+eMqZZg8HgnfMraJGeT/3JYUGuM8hHa +iycbaJrgnVl4ZA3RxMJyX5/vMtZlEDhiVJfVA8/EpTT20tDdtPwISS1DVXwtQ6Ec +MGWyMPhaCs7oHq3AQS3TomR2O+iCOluT8+iE3n4gjQUGK4L9bXw1agQFwGwbkW3b +s6elNUKfr2kigan3WBz88TFUJvbFuWfQ2usBvWkQ3urTlSmr8lmNYrkBsjJ1t0c8 +OVFdvkZI2hnyqGGMX8+cqcmSqE7vXIo/c/04kcKQM8Zgjmci +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 54:e3:4d:7d:5e:fd:13:7b:9f:32:55:f3:77:55:e6:39:52:6f:ef:3f + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root + Validity + Not Before: Oct 5 12:00:00 2021 GMT + Not After : Oct 5 12:00:00 2022 GMT + Subject: CN=Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:9d:78:55:f3:0c:19:87:95:61:61:db:6c:07:71: + bb:94:fd:a5:8d:cc:a7:b2:d6:0a:36:85:0a:07:1c: + 6b:e2:06:63:06:2b:ca:c6:ac:a8:fe:9b:02:f4:c0: + bc:cf:12:cd:49:18:2c:90:35:55:16:a1:2b:49:77: + 0a:a3:e2:04:22:e8:2c:58:21:7c:f4:b6:bd:19:61: + c6:50:4f:a8:0f:b1:e9:96:e7:fc:f6:1d:bb:ad:58: + 69:25:e9:db:6d:91:cc:61:2b:e5:93:9d:a9:37:c3: + f3:29:74:58:cd:b9:85:48:b8:ca:49:14:7b:18:54: + ee:c5:c7:18:98:48:91:f8:c2:c2:ec:15:67:27:bf: + a6:1b:29:25:97:67:ce:07:25:13:56:1a:b0:42:c8: + 1d:1b:33:49:83:f4:da:67:52:79:22:3c:0d:9f:0c: + e5:91:87:5f:fe:f6:43:70:bc:2f:68:c8:d6:37:8f: + cf:97:7b:c9:d6:3f:9e:06:c6:b0:ea:20:b6:7f:b0: + 33:a0:0f:5b:05:2a:1a:02:b9:22:80:d8:1a:bb:dc: + 81:db:68:cb:d7:c1:99:6e:34:f7:f5:b2:72:94:94: + c4:0e:04:8c:6d:b7:5f:6b:bb:c5:3f:6b:50:08:42: + 9a:cc:5f:41:96:ff:a2:fd:67:37:38:77:6f:d3:f4: + 2c:93 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 20:1D:40:05:AB:57:09:3B:3A:83:BE:19:65:15:EB:74:EF:0C:0D:D7 + X509v3 Authority Key Identifier: + 20:1D:40:05:AB:57:09:3B:3A:83:BE:19:65:15:EB:74:EF:0C:0D:D7 + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Root.cer + X509v3 CRL Distribution Points: + Full Name: + URI:http://url-for-crl/Root.crl + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 24:3d:9b:fe:64:91:03:db:33:58:d3:74:2a:57:a5:82:48:28: + 80:2e:57:82:09:ff:3d:6e:1a:f4:2d:c3:ee:90:9b:07:88:1d: + 25:97:65:5b:ef:90:54:b4:61:86:4c:15:5e:1a:a5:ee:d4:41: + af:6f:0a:2b:4e:b0:75:bd:d8:2c:8e:20:e9:6f:7a:d1:1b:4a: + b6:2d:c6:60:be:cb:56:7d:f1:c3:06:03:cd:c4:23:25:1f:09: + f5:44:d1:7c:9e:48:29:b4:a6:a7:55:40:f7:11:05:dc:45:5c: + 45:3f:2d:a6:23:54:e7:74:a8:d8:a3:81:23:00:77:64:9c:d3: + 1e:f1:f1:33:b6:a5:21:8e:af:a9:14:f5:37:6a:e3:6f:82:9f: + 65:6d:ab:de:0a:a5:29:62:d9:01:57:bf:69:48:c9:93:be:c2: + 2d:4b:e6:ed:0e:1e:e5:d8:fe:9c:8b:fc:36:09:08:45:f8:31: + 45:21:22:0b:62:c3:61:82:8f:65:bb:01:14:37:c2:b0:31:2f: + a2:40:b9:91:21:54:50:b6:24:39:6b:c1:a5:90:3f:b4:77:9c: + 13:d7:0a:dc:3d:85:ef:77:fa:53:6b:fc:cf:8a:3e:45:db:5c: + 8b:4b:6b:a5:d8:ee:0b:19:f2:c1:a3:02:e0:ba:36:43:c8:e8: + 8b:c8:9a:2f +-----BEGIN CERTIFICATE----- +MIIDeDCCAmCgAwIBAgIUVONNfV79E3ufMlXzd1XmOVJv7z8wDQYJKoZIhvcNAQEL +BQAwDzENMAsGA1UEAwwEUm9vdDAeFw0yMTEwMDUxMjAwMDBaFw0yMjEwMDUxMjAw +MDBaMA8xDTALBgNVBAMMBFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCdeFXzDBmHlWFh22wHcbuU/aWNzKey1go2hQoHHGviBmMGK8rGrKj+mwL0 +wLzPEs1JGCyQNVUWoStJdwqj4gQi6CxYIXz0tr0ZYcZQT6gPsemW5/z2HbutWGkl +6dttkcxhK+WTnak3w/MpdFjNuYVIuMpJFHsYVO7FxxiYSJH4wsLsFWcnv6YbKSWX +Z84HJRNWGrBCyB0bM0mD9NpnUnkiPA2fDOWRh1/+9kNwvC9oyNY3j8+Xe8nWP54G +xrDqILZ/sDOgD1sFKhoCuSKA2Bq73IHbaMvXwZluNPf1snKUlMQOBIxtt19ru8U/ +a1AIQprMX0GW/6L9Zzc4d2/T9CyTAgMBAAGjgcswgcgwHQYDVR0OBBYEFCAdQAWr +Vwk7OoO+GWUV63TvDA3XMB8GA1UdIwQYMBaAFCAdQAWrVwk7OoO+GWUV63TvDA3X +MDcGCCsGAQUFBwEBBCswKTAnBggrBgEFBQcwAoYbaHR0cDovL3VybC1mb3ItYWlh +L1Jvb3QuY2VyMCwGA1UdHwQlMCMwIaAfoB2GG2h0dHA6Ly91cmwtZm9yLWNybC9S +b290LmNybDAOBgNVHQ8BAf8EBAMCBaAwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG +9w0BAQsFAAOCAQEAJD2b/mSRA9szWNN0KlelgkgogC5Xggn/PW4a9C3D7pCbB4gd +JZdlW++QVLRhhkwVXhql7tRBr28KK06wdb3YLI4g6W960RtKti3GYL7LVn3xwwYD +zcQjJR8J9UTRfJ5IKbSmp1VA9xEF3EVcRT8tpiNU53So2KOBIwB3ZJzTHvHxM7al +IY6vqRT1N2rjb4KfZW2r3gqlKWLZAVe/aUjJk77CLUvm7Q4e5dj+nIv8NgkIRfgx +RSEiC2LDYYKPZbsBFDfCsDEvokC5kSFUULYkOWvBpZA/tHecE9cK3D2F73f6U2v8 +z4o+Rdtci0trpdjuCxnywaMC4Lo2Q8joi8iaLw== +-----END CERTIFICATE-----
diff --git a/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/generate-chains.py b/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/generate-chains.py new file mode 100755 index 0000000..693a2e12 --- /dev/null +++ b/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/generate-chains.py
@@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# Copyright 2022 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Certificate chain where the root keyUsage extension is present but does not +contain keyCertSign.""" + +import sys +sys.path += ['../..'] + +import gencerts + +# Self-signed root certificate without keyCertSign. +root = gencerts.create_self_signed_root_certificate('Root') +root.get_extensions().set_property('keyUsage', + 'critical,digitalSignature,keyEncipherment') + +# Intermediate certificate. +intermediate = gencerts.create_intermediate_certificate('Intermediate', root) + +# Target certificate. +target = gencerts.create_end_entity_certificate('Target', intermediate) + +chain = [target, intermediate, root] +gencerts.write_chain(__doc__, chain, 'chain.pem')
diff --git a/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/keys/Intermediate.key b/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/keys/Intermediate.key new file mode 100644 index 0000000..c59282d5 --- /dev/null +++ b/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/keys/Intermediate.key
@@ -0,0 +1,29 @@ +openssl genrsa 2048 +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCcONphuK0Nqt5E +31J4AYKJ+1+9/Kl50I0QXDxOt7VDNrwFOgxOVIgARfszJcrPOqqtpN7SLsFTRLj1 +WOcnGVpwNHHHTXcfU/JmuXnowhCML10ZF37jJn4MXY6uhQH3BazOGF18pPr8OOYY +Y6VM0KPLo+ZHrV/sMvwRAofL+ofJOKq4sn6YmRtO8wH8SGpgpSmAPAxQIzquCqbU +KWkeFTTtkzH7MNTWI1mUifqZtBbYBGPQw6ktvv9qhMdUu+jrvRZbiDMQG24gT2BJ +VgmG3JX8xdks3gMyiPw6hAZIkhB8LblqJf2TwFF1vVTnugu72LP1YFWexwZw/fPw +E46oMxf/AgMBAAECggEAB0L0EU3HXkn4E4utgCsfZiPunKl1atZt8C0K/crq3IlB +rraDiVKP92WvwJfI0d6GveD0UIdgcIS4889iZnFc84RxWeCSbgmo/1H7+WNBgXQ9 +wUntZntmdlNIK6y+dvAaSuj1oExLTe6kV2bhiwZs6EbU9rXEeyyyUph9BApZrHM1 +jwTbVsDRqq26gJq889SvvfIN2kwUaptFe9sAu7VNRlTU5XUVSEVwjaGs5ddDUKVT +TYHSPMBCRQMbgXxp3pBJAlBmSxRd+T2zsEOIPuUE/an3kyNSGXl7H+SBizNnqqsw +vkmq/e8yWnQW6niDJkdxm4Y8PetzdEl3zSZ43v5duQKBgQDAfN327WDp4Qyq0E3H +VnRzKJA/21eau9tHqO20lKccAH1E8YQAdNsA2pannU0z10vcKifT9Z32VqtjBNxQ +iOBah1q0EeKZL9oemmlc7MMpA8Ps3ddJuYgkt7wb/2PjnfHWXL+zfl0CC/nhAq8c +qMd9PLp22RkfaTvFBEcCFRYJdwKBgQDPxK6f678E9Rs1mtpt6iTZP5yfMJ9T/Jkh +4P8h/CDcaKKoyMz+0nx0mokIUXmn38RKeDf3/u8oe/9VL55etsSZy02BQWD4tFlP +3xv18DBpLPZbPqO5/FZDz43RWgiyoYm+4GOElMEhI3R+pXM0WtOS/vL8HPF6cZeR +xYOneBwHuQKBgB7+vFs7pCRk+b4zpqKXmE7G1FuD/VpML6YdXJF8cmA+7+z/Gutb +5bwAdsvst3bGj0+XdixaW6JEGHrsWHGbaM0LCJ8AVkWmf+/3m0m8Ujyzf4QPwM/9 +UR/geijj+fi4AS4sZy4HBgEDXqxN21a5Es5mzfu/P51gO6Cg7LI4JQFHAoGAcOiC +uXekzC3jRoNL1tWahtFR7RTAUSUBlu6t16srtHvMgYr2FDkQ11EvzOxx/2/UPWAN +kmDhWQ/hl0qUdwY92xInoWmFKELiEky95i5MMKv1iWqGEUl3G8zMVgvmlCTDNY69 +pkwslDSvVy/UZoxBVC3moGmeNRtL8jTzMexM10kCgYANE5y/x9O+dNCDaUd6lcR3 +eV54CEGgWliifpKNVmeZfUy0zjx3pOiUaDjvLwtKtYnNvvpNlxq0weMRRqqb3isx +R/HgGuqX5rdz9bz6pP7n2sqQ67Y/bN7HD8F+B3gn2UmjekscEW7p31sgPNtfa0+u +zONbHBAlP5YbWROTvuw6Wg== +-----END PRIVATE KEY-----
diff --git a/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/keys/Root.key b/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/keys/Root.key new file mode 100644 index 0000000..f92bfb3 --- /dev/null +++ b/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/keys/Root.key
@@ -0,0 +1,29 @@ +openssl genrsa 2048 +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCdeFXzDBmHlWFh +22wHcbuU/aWNzKey1go2hQoHHGviBmMGK8rGrKj+mwL0wLzPEs1JGCyQNVUWoStJ +dwqj4gQi6CxYIXz0tr0ZYcZQT6gPsemW5/z2HbutWGkl6dttkcxhK+WTnak3w/Mp +dFjNuYVIuMpJFHsYVO7FxxiYSJH4wsLsFWcnv6YbKSWXZ84HJRNWGrBCyB0bM0mD +9NpnUnkiPA2fDOWRh1/+9kNwvC9oyNY3j8+Xe8nWP54GxrDqILZ/sDOgD1sFKhoC +uSKA2Bq73IHbaMvXwZluNPf1snKUlMQOBIxtt19ru8U/a1AIQprMX0GW/6L9Zzc4 +d2/T9CyTAgMBAAECggEAOd1W5B2dogOECfQaEfA6qIi+lclPFHnvvdIMecl5YVDM +gZ+E/5XB8fFfWDYdC5DSq9n8wi8+6bZm1DOwzsEGmRcs+GOx6bDe8x1JRQjIbqAH +gMMV4xDQ/uV+mgaB8hUB//EkBycH4CyaxbBx04MpVaxF9S3X//xx026SfJ8qOLkx +VLGP2sIeOexuv7luEnRFCXLFLaEocZ0O6F55E3q4scl2iVs4QumE6PVHoz+TNkIv +jT5JFnxYAdpkmJZAne2T9cIJjBz4pUHlwhK5eIXzUEirJIT3Dfx5xkSjY+4rOiAU +Q0KtadzjTTCqMQpbp3lS9hFLd2xoLtW+C90kDzVoOQKBgQDNDAN1CoN2xcT4Wcwl +QfPrjzE8uh2Xb2kF9jjeoVx4Z+F40AebkrwVmsSP3DM3j3sI8ijHfDsu1/HsF421 +7WHDnRqsojTAY2hFLYFOJZikK4288wwE5RPLbXz6FqYxsyqDlPOYMgt0GDuMZrFU +Aw0Y5WjYAu0yz+DsyjQ0pMXFeQKBgQDEmbys+k9jbRF3mh7Ai7jP04rlHijH200p +u91xQKwFSGnErvEINvSUc6NAYDzk4u+WzDs8woi4ZOrK/Ayn6+vxJLxCn1NI/BjJ +H8XMuKvt6pAeX8ZYGPfjendq1E+RKVMYZifnEpPd6P4gY8oOHVbx91SJWB6U/MUy +HlUs99X7awKBgQC6Ux1dIMWfi01WpDrW7FybhE4osbMsJggYa8r3u0eM/lCr+NXA +8BDLzQyq8Vz1MwOJeIvH4kLhaUej0y9pzyEUoVFY6DjpTiu1GQm0GoPfQtiUh4M3 +e3aGV6LGmwhAh1+tnA/TED7KKy8JgVPIVNF0+xpPmDE1CCOK6J+R6tzweQKBgDk6 +Wy6rClLx28TJ6yu3QEvW0zaQieRrVNHSKsqdvbUn+AnVtrnibV2NL7c8jF1AJefq +eU/dfLjYP3Ro3DJBPYQLYnWuNSsonvpksko+c2WlAuCklnLsibQA4SQKu0KRGewf +SHw97ycIfHjnM1jad4Wlrkjwiq5pyekl5TtaxUITAoGAclnWjbVoNGwd+MKtKlHA +gYyVqTEDoMeaHOg+SkNE00BHpUG8XcdYBlUR56XWRHBWxRn3AotBeVUjJYe385y2 +2wBXEYZ6tBkWK9YYy3w5CylUNXIAz03itb+xGZ/r1ZpEdYGta9yDUfRoLJ2Y6Eej +xy1t92XPwm6o9yqrpa8KqwM= +-----END PRIVATE KEY-----
diff --git a/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/keys/Target.key b/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/keys/Target.key new file mode 100644 index 0000000..908f58c --- /dev/null +++ b/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/keys/Target.key
@@ -0,0 +1,29 @@ +openssl genrsa 2048 +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCxHKS5IIFyS/Us +UH4/GoUnWy1QfOU2/ZysJqB9t5TVa/3DRhrcTRBFmMyHja/8DrzJsmFLjMKbyNp7 +BbM74CGVpZwBcjRIPeRE8ue2a1j0jWCSyJEpQSMpI/3aYtDDeJJfAQlVLjqisywt +xc15JnpmvOOlF1GutylQdRBvLFWpeQQhBTsUMmV8Oiwz6mtyIPGHMfKPJ2lPUB3C +GDaOuG3EuAt6I4fhSITsRJh336d6BjdNQjNA4rLJZy+UIGlcbTAauMVgnjJuTbKF +3pS5hlD5DHIGNLvwSvzNyIl762nlZOhVTBJ5zIGIJvZZItVgjDZPljDi6vQQ3III +0jviBRN3AgMBAAECggEAHvw1X0PuEZpzUqTkaVLQ78E2TMoE6dl1svJxCn13Ft11 +QFf/9AGxcpOYWLCzlKPZaGoCNo7yLwH1IyesozGDfqRCBki+F9NoH53lZtch8WrY +deWL680/AwAOdcnq3v+1j9RlFxdm37b76CgeWe8e4+Fw7B2Hx0q4+h/415JIjETa +OWUkhe77FaA1DUOjrgfv9jhLag/3OLzO9Ae/sFJIoYACVB5lbOPjBGy6bpXfDgOC +ppgn4NsUnkG/ouTm1c1SfgCxpYdpGZ9tQ08IqjuFwupd2dfBUb8mKnYf2gs5nnmt +IWxi+656pnaGhmUjJLFaQ4y8f31tSpudWddukzQWBQKBgQC+dDV4hvY0aL52eL+P +JKpYkAAWjXikg6KGYFQEl1MDIMhUQtWgxgfLU5uLD4ljST5qos6cWfO/ZWrriAAE +Na5ooT4l5wVwgaRLeqwU4+06fpGsuXFvutkDdULdR8evJfwsSQyDUHlu3fWwLcaB +irvbc/CVYIvIzg7orD/1GGAzkwKBgQDuEPGcXo8EN5HYD5LXtd2eT0LhouowHv5p +9aDKG1g4zFubkkB13UZgQXE5ivA5ll7pJIWv0dh9UDeSK1noE8vpniMd4+uxAqdw +sf2pPES43su24e7SfQpJEJ63sAYhWdJrzJ/qyxzroxO+65D8ozgUdeBlR/ECHCUA +m0i1RibXDQKBgQCbDKyDZQyHekak2ITLGkR8OS95LM9sz6W+1ClSW4e/Yi71OjwE +2XN6+qQEwC9PX0+rLMQb0bd4uC4ldeDdjH5iu/KGlN9+ymxg7outrilxl50tCwPo +vCr0f8BhuZA9bSUxQH8pYJibw6PDPGEBEVsCvA6+7Yyfe/HzRlgDR0b6dQKBgG9+ +Zflq26YI9HfxCz+VQB6VVmhgKTeyPEqZq90bo1yucLTScPgCUqRf4cwmQs1lnDuq +TCYErFQ8DlqZjPjA1L4rvpyQEuEKsip4YakxvamrRlL3SycvQnLnor26ZZSXAZJU ++gw3ZesBrAy9PGDlfC0w64/jen8XeUjocMvc9/G9AoGAUd3EFeCC1bCHDrzzYtEY +54WY1dV7zT3ePOFpVEZ0KHe4kgszdGHC/olRmmyxnsv+gyOuJ38uEH85WQ93Uxvu +gPp4xRUGmRMc40qKW8DKQhQru1p7I92D2Nplf65Uh7XR8AKc8fvzoowB3q95UzjC +lkPYeGUpv6L/Tt1IEy87iP8= +-----END PRIVATE KEY-----
diff --git a/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/main.test b/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/main.test new file mode 100644 index 0000000..c898fa45 --- /dev/null +++ b/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/main.test
@@ -0,0 +1,5 @@ +chain: chain.pem +last_cert_trust: TRUSTED_ANCHOR +utc_time: DEFAULT +key_purpose: SERVER_AUTH +expected_errors:
diff --git a/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/ta-with-constraints.test b/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/ta-with-constraints.test new file mode 100644 index 0000000..4ddcdb7 --- /dev/null +++ b/net/data/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/ta-with-constraints.test
@@ -0,0 +1,8 @@ +chain: chain.pem +last_cert_trust: TRUSTED_ANCHOR_WITH_CONSTRAINTS +utc_time: DEFAULT +key_purpose: SERVER_AUTH +expected_errors: +----- Certificate i=2 (CN=Root) ----- +ERROR: keyCertSign bit is not set +
diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc index 059cce8d..e9c9e03 100644 --- a/net/http/transport_security_state.cc +++ b/net/http/transport_security_state.cc
@@ -464,8 +464,7 @@ const X509Certificate* served_certificate_chain, const SignedCertificateTimestampAndStatusList& signed_certificate_timestamps, - ct::CTPolicyCompliance policy_compliance, - const NetworkAnonymizationKey& network_anonymization_key) { + ct::CTPolicyCompliance policy_compliance) { using CTRequirementLevel = RequireCTDelegate::CTRequirementLevel; std::string hostname = host_port_pair.host();
diff --git a/net/http/transport_security_state.h b/net/http/transport_security_state.h index 8ef76b9d..f34123b 100644 --- a/net/http/transport_security_state.h +++ b/net/http/transport_security_state.h
@@ -358,8 +358,7 @@ const X509Certificate* served_certificate_chain, const SignedCertificateTimestampAndStatusList& signed_certificate_timestamps, - ct::CTPolicyCompliance policy_compliance, - const NetworkAnonymizationKey& network_anonymization_key); + ct::CTPolicyCompliance policy_compliance); // Assign a |Delegate| for persisting the transport security state. If // |NULL|, state will not be persisted. The caller retains
diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc index ce7bdc7..e418213 100644 --- a/net/http/transport_security_state_unittest.cc +++ b/net/http/transport_security_state_unittest.cc
@@ -1123,8 +1123,7 @@ state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey()); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS); MockRequireCTDelegate always_require_delegate; EXPECT_CALL(always_require_delegate, IsCTRequiredForHost(_, _, _)) @@ -1135,29 +1134,25 @@ state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); EXPECT_EQ( TransportSecurityState::CT_REQUIREMENTS_NOT_MET, state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS)); EXPECT_EQ( TransportSecurityState::CT_REQUIREMENTS_MET, state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS)); EXPECT_EQ( TransportSecurityState::CT_REQUIREMENTS_MET, state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY)); state.SetRequireCTDelegate(nullptr); EXPECT_EQ( @@ -1165,8 +1160,7 @@ state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); } // If CT is not required, then regardless of the CT state for the host, @@ -1177,8 +1171,7 @@ state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey()); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS); MockRequireCTDelegate never_require_delegate; EXPECT_CALL(never_require_delegate, IsCTRequiredForHost(_, _, _)) @@ -1189,15 +1182,13 @@ state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); EXPECT_EQ( TransportSecurityState::CT_NOT_REQUIRED, state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS)); state.SetRequireCTDelegate(nullptr); EXPECT_EQ( @@ -1205,8 +1196,7 @@ state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); } // If the Delegate is in the default state, then it should return the same @@ -1217,8 +1207,7 @@ state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey()); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS); MockRequireCTDelegate default_require_ct_delegate; EXPECT_CALL(default_require_ct_delegate, IsCTRequiredForHost(_, _, _)) @@ -1229,8 +1218,7 @@ state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); state.SetRequireCTDelegate(nullptr); EXPECT_EQ( @@ -1238,8 +1226,7 @@ state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); } } @@ -1300,39 +1287,29 @@ state_.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED, state_.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS)); EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED, state_.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS)); EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED, state_.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY)); state_.SetRequireCTDelegate(nullptr); EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED, state_.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, cert.get(), cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); } INSTANTIATE_TEST_SUITE_P( @@ -1374,9 +1351,7 @@ state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, before_cert.get(), before_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); // ... but certificates issued after 1 June 2016 are required to be... EXPECT_EQ( @@ -1384,33 +1359,25 @@ state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, after_cert.get(), after_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); EXPECT_EQ( TransportSecurityState::CT_REQUIREMENTS_NOT_MET, state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, after_cert.get(), after_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS)); EXPECT_EQ( TransportSecurityState::CT_REQUIREMENTS_MET, state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, after_cert.get(), after_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY)); EXPECT_EQ( TransportSecurityState::CT_REQUIREMENTS_MET, state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, after_cert.get(), after_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS)); // ... unless they were issued by an excluded intermediate. hashes.push_back(HashValue(google_hash_value)); @@ -1419,17 +1386,13 @@ state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, before_cert.get(), before_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); EXPECT_EQ( TransportSecurityState::CT_NOT_REQUIRED, state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, after_cert.get(), after_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); // And other certificates should remain unaffected. SHA256HashValue unrelated_hash_value = {{0x01, 0x02}}; @@ -1441,17 +1404,13 @@ HostPortPair("www.example.com", 443), true, unrelated_hashes, before_cert.get(), before_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED, state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, unrelated_hashes, after_cert.get(), after_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); } // Tests that Certificate Transparency is required for all of the Symantec @@ -1483,33 +1442,25 @@ state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, before_cert.get(), before_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); EXPECT_EQ( TransportSecurityState::CT_REQUIREMENTS_NOT_MET, state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, before_cert.get(), before_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS)); EXPECT_EQ( TransportSecurityState::CT_REQUIREMENTS_MET, state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, before_cert.get(), before_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY)); EXPECT_EQ( TransportSecurityState::CT_REQUIREMENTS_MET, state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, before_cert.get(), before_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS)); scoped_refptr<X509Certificate> after_cert = ImportCertFromFile(GetTestCertsDirectory(), "post_june_2016.pem"); @@ -1520,33 +1471,25 @@ state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, after_cert.get(), after_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS)); EXPECT_EQ( TransportSecurityState::CT_REQUIREMENTS_NOT_MET, state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, after_cert.get(), after_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS)); EXPECT_EQ( TransportSecurityState::CT_REQUIREMENTS_MET, state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, after_cert.get(), after_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY)); EXPECT_EQ( TransportSecurityState::CT_REQUIREMENTS_MET, state.CheckCTRequirements( HostPortPair("www.example.com", 443), true, hashes, after_cert.get(), after_cert.get(), SignedCertificateTimestampAndStatusList(), - - ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS, - NetworkAnonymizationKey())); + ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS)); } #if BUILDFLAG(INCLUDE_TRANSPORT_SECURITY_STATE_PRELOAD_LIST)
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc index 8da0467..9f3e9af1 100644 --- a/net/quic/crypto/proof_verifier_chromium.cc +++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -534,8 +534,7 @@ cert_verify_result.is_issued_by_known_root, cert_verify_result.public_key_hashes, cert_verify_result.verified_cert.get(), cert_.get(), - cert_verify_result.scts, cert_verify_result.policy_compliance, - proof_verifier_->network_anonymization_key_); + cert_verify_result.scts, cert_verify_result.policy_compliance); if (sct_auditing_delegate_) { sct_auditing_delegate_->MaybeEnqueueReport(
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc index 391247f..56904f01 100644 --- a/net/socket/ssl_client_socket_impl.cc +++ b/net/socket/ssl_client_socket_impl.cc
@@ -1340,8 +1340,7 @@ server_cert_verify_result_.public_key_hashes, server_cert_verify_result_.verified_cert.get(), server_cert_.get(), server_cert_verify_result_.scts, - server_cert_verify_result_.policy_compliance, - ssl_config_.network_anonymization_key); + server_cert_verify_result_.policy_compliance); if (context_->sct_auditing_delegate()) { context_->sct_auditing_delegate()->MaybeEnqueueReport(
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index b85173a..c6e4e71b 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc
@@ -882,7 +882,7 @@ HostPortPair(new_hostname, 0), ssl_info.is_issued_by_known_root, ssl_info.public_key_hashes, ssl_info.cert.get(), ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps, - ssl_info.ct_policy_compliance, network_anonymization_key)) { + ssl_info.ct_policy_compliance)) { case TransportSecurityState::CT_REQUIREMENTS_NOT_MET: return false; case TransportSecurityState::CT_REQUIREMENTS_MET:
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index 8ad7cb3..6bae8bc 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -1342,8 +1342,7 @@ int NetworkContext::CheckCTComplianceForSignedExchange( net::CertVerifyResult& cert_verify_result, const net::X509Certificate& certificate, - const net::HostPortPair& host_port_pair, - const net::NetworkAnonymizationKey& network_anonymization_key) { + const net::HostPortPair& host_port_pair) { net::X509Certificate* verified_cert = cert_verify_result.verified_cert.get(); net::ct::SCTList verified_scts; @@ -1373,8 +1372,7 @@ url_request_context_->transport_security_state()->CheckCTRequirements( host_port_pair, cert_verify_result.is_issued_by_known_root, cert_verify_result.public_key_hashes, verified_cert, &certificate, - cert_verify_result.scts, cert_verify_result.policy_compliance, - network_anonymization_key); + cert_verify_result.scts, cert_verify_result.policy_compliance); if (url_request_context_->sct_auditing_delegate()) { url_request_context_->sct_auditing_delegate()->MaybeEnqueueReport( @@ -2696,8 +2694,7 @@ #if BUILDFLAG(IS_CT_SUPPORTED) int ct_result = CheckCTComplianceForSignedExchange( *pending_cert_verify->result, *pending_cert_verify->certificate, - net::HostPortPair::FromURL(pending_cert_verify->url), - pending_cert_verify->network_anonymization_key); + net::HostPortPair::FromURL(pending_cert_verify->url)); #endif // BUILDFLAG(IS_CT_SUPPORTED) net::TransportSecurityState::PKPStatus pin_validity = url_request_context_->transport_security_state()->CheckPublicKeyPins(
diff --git a/services/network/network_context.h b/services/network/network_context.h index 5853a395..cca5788e 100644 --- a/services/network/network_context.h +++ b/services/network/network_context.h
@@ -677,8 +677,7 @@ int CheckCTComplianceForSignedExchange( net::CertVerifyResult& cert_verify_result, const net::X509Certificate& certificate, - const net::HostPortPair& host_port_pair, - const net::NetworkAnonymizationKey& network_anonymization_key); + const net::HostPortPair& host_port_pair); #endif // BUILDFLAG(IS_CT_SUPPORTED) #if BUILDFLAG(IS_DIRECTORY_TRANSFER_REQUIRED)
diff --git a/services/tracing/public/cpp/perfetto/perfetto_config.cc b/services/tracing/public/cpp/perfetto/perfetto_config.cc index ee543eee..e18b233b 100644 --- a/services/tracing/public/cpp/perfetto/perfetto_config.cc +++ b/services/tracing/public/cpp/perfetto/perfetto_config.cc
@@ -7,6 +7,7 @@ #include <cstdint> #include <string> +#include "base/command_line.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/trace_event/memory_dump_manager.h" @@ -16,6 +17,7 @@ #include "build/build_config.h" #include "build/chromecast_buildflags.h" #include "build/chromeos_buildflags.h" +#include "components/tracing/common/tracing_switches.h" #include "services/tracing/public/mojom/perfetto_service.mojom.h" namespace tracing { @@ -168,6 +170,22 @@ } } +size_t GetDefaultTraceBufferSize() { + auto* command_line = base::CommandLine::ForCurrentProcess(); + std::string switch_value = command_line->GetSwitchValueASCII( + switches::kDefaultTraceBufferSizeLimitInKb); + size_t switch_kilobytes; + if (!switch_value.empty() && + base::StringToSizeT(switch_value, &switch_kilobytes)) { + return switch_kilobytes; + } else { + // TODO(eseckler): Reduce the default buffer size after benchmarks set + // what they require. Should also invest some time to reduce the overhead + // of begin/end pairs further. + return 200 * 1024; + } +} + } // namespace perfetto::TraceConfig GetDefaultPerfettoConfig( @@ -193,10 +211,8 @@ size_t size_limit = chrome_config.GetTraceBufferSizeInKb(); if (size_limit == 0) { - // TODO(eseckler): Reduce the default buffer size after benchmarks set what - // they require. Should also invest some time to reduce the overhead of - // begin/end pairs further. - size_limit = 200 * 1024; + // If trace config did not provide trace buffer size, we will use default + size_limit = GetDefaultTraceBufferSize(); } auto* buffer_config = perfetto_config.add_buffers(); buffer_config->set_size_kb(size_limit);
diff --git a/services/viz/public/cpp/gpu/context_provider_command_buffer.h b/services/viz/public/cpp/gpu/context_provider_command_buffer.h index 04de90c5..e434c1b 100644 --- a/services/viz/public/cpp/gpu/context_provider_command_buffer.h +++ b/services/viz/public/cpp/gpu/context_provider_command_buffer.h
@@ -84,7 +84,8 @@ command_buffer_metrics::ContextType type, base::SharedMemoryMapper* buffer_mapper = nullptr); - gpu::CommandBufferProxyImpl* GetCommandBufferProxy(); + // Virtual for testing. + virtual gpu::CommandBufferProxyImpl* GetCommandBufferProxy(); // Gives the GL internal format that should be used for calling CopyTexImage2D // on the default framebuffer. uint32_t GetCopyTextureInternalFormat();
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index f8a163a..4d4e419 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -27252,7 +27252,8 @@ { "args": [ "--gs-results-bucket=chromium-result-details", - "--recover-devices" + "--recover-devices", + "--test-launcher-filter-file=../../testing/buildbot/filters/android.pie_arm64.content_browsertests_coverage.filter" ], "isolate_profile_data": true, "merge": { @@ -27705,7 +27706,8 @@ "args": [ "--use-cmd-decoder=validating", "--gs-results-bucket=chromium-result-details", - "--recover-devices" + "--recover-devices", + "--test-launcher-filter-file=../../testing/buildbot/filters/android.pie_arm64_rel.gl_tests.filter" ], "isolate_profile_data": true, "merge": {
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn index 94e28e4..7b00151 100644 --- a/testing/buildbot/filters/BUILD.gn +++ b/testing/buildbot/filters/BUILD.gn
@@ -130,6 +130,7 @@ "//testing/buildbot/filters/android.emulator_12.oop_network_service_content_browsertests.filter", "//testing/buildbot/filters/android.emulator_n.content_browsertests.filter", "//testing/buildbot/filters/android.emulator_p.content_browsertests.filter", + "//testing/buildbot/filters/android.pie_arm64.content_browsertests_coverage.filter", "//testing/buildbot/filters/cast-linux.content_browsertests.filter", "//testing/buildbot/filters/chromium.webrtc.fyi.android.tests.dbg.content_browsertests.filter", "//testing/buildbot/filters/linux-lacros.content_browsertests.filter",
diff --git a/testing/buildbot/filters/android.pie_arm64.content_browsertests_coverage.filter b/testing/buildbot/filters/android.pie_arm64.content_browsertests_coverage.filter new file mode 100644 index 0000000..da3dbfd --- /dev/null +++ b/testing/buildbot/filters/android.pie_arm64.content_browsertests_coverage.filter
@@ -0,0 +1,21 @@ +# crbug.com/1403109 +-DomSerializerTests.SerializeHTMLDOMWithAddingMOTW +-DomSerializerTests.SerializeHTMLDOMWithBaseTag +-DomSerializerTests.SerializeHTMLDOMWithEmptyHead +-DomSerializerTests.SerializeHTMLDOMWithEntitiesInAttributeValue +-DomSerializerTests.SerializeHTMLDOMWithEntitiesInText +-DomSerializerTests.SerializeHTMLDOMWithNonStandardEntities +-DomSerializerTests.SerializeHTMLDOMWithoutDocType +-DomSerializerTests.SerializeOffTheRecordHTMLDOMWithAddingMOTW +-DomSerializerTests.SerializeXMLDocWithBuiltInEntities +-DomSerializerTests.SubResourceForElementsInNonHTMLNamespace +-RenderThreadImplDiscardableMemoryBrowserTest.CheckReleaseMemory +-RenderThreadImplDiscardableMemoryBrowserTest.LockDiscardableMemory +-RenderThreadImplDiscardableMemoryBrowserTest.ReleaseFreeDiscardableMemory +-RenderViewBrowserTest.ConfirmCacheInformationPlumbed +-SavableResourcesTest.GetSavableResourceLinksWithPageHasInvalidLinks +-SavableResourcesTest.GetSavableResourceLinksWithPageHasValidLinks +-SavableResourcesTest.GetSavableResourceLinksWithPageHasValidStyleLink +-SingleProcessMemoryTracingTest.BrowserInitiatedSingleDump +-SingleProcessMemoryTracingTest.ManyInterleavedDumps +-SingleProcessMemoryTracingTest.RendererInitiatedSingleDump
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index aadda2d..8904a2a9 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1735,10 +1735,15 @@ ], }, }, + 'android-pie-arm64-coverage-experimental-rel': { + 'args': [ + '--test-launcher-filter-file=../../testing/buildbot/filters/android.pie_arm64.content_browsertests_coverage.filter', + ], + }, 'android-pie-arm64-rel': { 'swarming': { 'quickrun_shards': 40 - } + }, }, 'android-pie-x86-rel': { 'args': [ @@ -2234,6 +2239,11 @@ '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_n.gl_tests.filter', ], }, + 'android-pie-arm64-coverage-experimental-rel': { + 'args': [ + '--test-launcher-filter-file=../../testing/buildbot/filters/android.pie_arm64_rel.gl_tests.filter', # https://crbug.com/1034007 + ], + }, 'android-pie-arm64-rel': { 'args': [ '--test-launcher-filter-file=../../testing/buildbot/filters/android.pie_arm64_rel.gl_tests.filter', # https://crbug.com/1034007
diff --git a/third_party/blink/common/messaging/string_message_codec.cc b/third_party/blink/common/messaging/string_message_codec.cc index 249b797..726124e 100644 --- a/third_party/blink/common/messaging/string_message_codec.cc +++ b/third_party/blink/common/messaging/string_message_codec.cc
@@ -32,6 +32,15 @@ size_t GetLength() const override { return length_; } + bool GetIsResizableByUserJavaScript() const override { + // VectorArrayBuffers are not used for ArrayBuffer transfers and are + // currently always fixed-length. Structured cloning resizables ArrayBuffers + // is not yet supported in SMC. + return false; + } + + size_t GetMaxByteLength() const override { return length_; } + absl::optional<base::span<const uint8_t>> GetAsSpanIfPossible() const override { return base::make_span(data_).subspan(position_, length_); @@ -51,11 +60,22 @@ // An ArrayBufferPayload impl based on mojo::BigBuffer. class BigBufferArrayBuffer : public WebMessageArrayBufferPayload { public: - explicit BigBufferArrayBuffer(mojo_base::BigBuffer data) - : data_(std::move(data)) {} + explicit BigBufferArrayBuffer(mojo_base::BigBuffer data, + absl::optional<size_t> max_byte_length) + : data_(std::move(data)), max_byte_length_(max_byte_length) { + DCHECK(!max_byte_length || *max_byte_length >= GetLength()); + } size_t GetLength() const override { return data_.size(); } + bool GetIsResizableByUserJavaScript() const override { + return max_byte_length_.has_value(); + } + + size_t GetMaxByteLength() const override { + return max_byte_length_.value_or(GetLength()); + } + absl::optional<base::span<const uint8_t>> GetAsSpanIfPossible() const override { return base::make_span(data_); @@ -68,6 +88,7 @@ private: mojo_base::BigBuffer data_; + absl::optional<size_t> max_byte_length_; }; const uint32_t kVarIntShift = 7; @@ -147,8 +168,11 @@ // static std::unique_ptr<WebMessageArrayBufferPayload> -WebMessageArrayBufferPayload::CreateFromBigBuffer(mojo_base::BigBuffer buffer) { - return std::make_unique<BigBufferArrayBuffer>(std::move(buffer)); +WebMessageArrayBufferPayload::CreateFromBigBuffer( + mojo_base::BigBuffer buffer, + absl::optional<size_t> max_byte_length) { + return std::make_unique<BigBufferArrayBuffer>(std::move(buffer), + max_byte_length); } // static @@ -191,7 +215,9 @@ array_buffer->CopyInto(base::make_span(big_buffer)); message.array_buffer_contents_array.push_back( mojom::SerializedArrayBufferContents::New( - std::move(big_buffer))); + std::move(big_buffer), + array_buffer->GetIsResizableByUserJavaScript(), + array_buffer->GetMaxByteLength())); }}, payload); @@ -279,9 +305,14 @@ return absl::nullopt; if (message.array_buffer_contents_array.size() != 1) return absl::nullopt; + auto& array_buffer_contents = message.array_buffer_contents_array[0]; + absl::optional<size_t> max_byte_length; + if (array_buffer_contents->is_resizable_by_user_javascript) { + max_byte_length.emplace(array_buffer_contents->max_byte_length); + } return absl::make_optional( WebMessagePayload(std::make_unique<BigBufferArrayBuffer>( - std::move(message.array_buffer_contents_array[0]->contents)))); + std::move(array_buffer_contents->contents), max_byte_length))); } }
diff --git a/third_party/blink/common/messaging/string_message_codec_unittest.cc b/third_party/blink/common/messaging/string_message_codec_unittest.cc index 901e7f19..f56d757 100644 --- a/third_party/blink/common/messaging/string_message_codec_unittest.cc +++ b/third_party/blink/common/messaging/string_message_codec_unittest.cc
@@ -118,9 +118,12 @@ // Copy data into a new array_buffer_contents_array slot. mojo_base::BigBuffer big_buffer(array_buffer->GetLength()); array_buffer->CopyInto(big_buffer); + constexpr bool is_resizable_by_user_js = false; + constexpr size_t max_byte_length = 0; transferable_message.array_buffer_contents_array.push_back( mojom::SerializedArrayBufferContents::New( - std::move(big_buffer))); + std::move(big_buffer), is_resizable_by_user_js, + max_byte_length)); } EXPECT_TRUE( serializer.WriteValue(context, message_as_array_buffer)
diff --git a/third_party/blink/public/common/messaging/string_message_codec.h b/third_party/blink/public/common/messaging/string_message_codec.h index 07abce9..4155ac5 100644 --- a/third_party/blink/public/common/messaging/string_message_codec.h +++ b/third_party/blink/public/common/messaging/string_message_codec.h
@@ -28,6 +28,14 @@ // Returns the length of the payload. virtual size_t GetLength() const = 0; + // Represents an ArrayBuffer resizable by user JavaScript. + virtual bool GetIsResizableByUserJavaScript() const = 0; + + // Returns the maximum length of the payload. If representing a resizable + // ArrayBuffer, this is >= GetLength(). Otherwise, if representing a + // fixed-length ArrayBuffer, this is == GetLength(). + virtual size_t GetMaxByteLength() const = 0; + // Convert the underlying buffer to a span if possible. Or return empty if // can't (like Java ByteArray). JNI API does not provide a way to get a // pointer to the underlying array memory, so another API |CopyInto| should be @@ -41,8 +49,12 @@ virtual void CopyInto(base::span<uint8_t> dest) const = 0; // Create a new WebMessageArrayBufferPayload from BigBuffer. + // + // If max_byte_length is not nullopt, then it must be >= buffer's length. The + // created BigBuffer represents a resizable ArrayBuffer. static std::unique_ptr<WebMessageArrayBufferPayload> CreateFromBigBuffer( - mojo_base::BigBuffer buffer); + mojo_base::BigBuffer buffer, + absl::optional<size_t> max_byte_length); // Create a new WebMessageArrayBufferPayload from vector for testing. static std::unique_ptr<WebMessageArrayBufferPayload> CreateForTesting(
diff --git a/third_party/blink/public/mojom/array_buffer/array_buffer_contents.mojom b/third_party/blink/public/mojom/array_buffer/array_buffer_contents.mojom index fdd7da2..4d613f774 100644 --- a/third_party/blink/public/mojom/array_buffer/array_buffer_contents.mojom +++ b/third_party/blink/public/mojom/array_buffer/array_buffer_contents.mojom
@@ -10,4 +10,10 @@ // ArrayBufferContents. struct SerializedArrayBufferContents { mojo_base.mojom.BigBuffer contents; + // If is_resizable_by_user_javascript is false, then max_byte_length is + // unused. + // + // TODO(crbug.com/657632): Use a wrapped uint64 or uint64? once supported. + bool is_resizable_by_user_javascript = false; + uint64 max_byte_length = 0; };
diff --git a/third_party/blink/renderer/bindings/core/v8/idl_types.h b/third_party/blink/renderer/bindings/core/v8/idl_types.h index 859728c..86b5eb9 100644 --- a/third_party/blink/renderer/bindings/core/v8/idl_types.h +++ b/third_party/blink/renderer/bindings/core/v8/idl_types.h
@@ -240,6 +240,10 @@ template <typename T> struct IDLBufferSourceTypeNoSizeLimit {}; +// [AllowResizable] +template <typename T> +struct IDLAllowResizable {}; + // IDL optional types // // IDLOptional represents an optional argument and supports a conversion from
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 d22f6f23..8da4921 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
@@ -51,34 +51,20 @@ kDoNotCheck, }; +enum class ResizableAllowance { kDisallowResizable, kAllowResizable }; + // The basic recipe of NativeValueTraits<T>::NativeValue function // implementation for buffer source types. template <typename RecipeTrait, - auto(*ToBlinkValue)(v8::Isolate*, v8::Local<v8::Value>), + auto (*ToBlinkValue)(v8::Isolate*, v8::Local<v8::Value>), Nullablity nullablity, BufferSizeCheck buffer_size_check, + ResizableAllowance allow_resizable, typename ScriptWrappableOrBufferSourceTypeName, bool (*IsSharedBuffer)(v8::Local<v8::Value>) = nullptr> auto NativeValueImpl(v8::Isolate* isolate, v8::Local<v8::Value> value, ExceptionState& exception_state) { - auto blink_value = ToBlinkValue(isolate, value); - if (LIKELY(RecipeTrait::IsNonNull(blink_value))) { - if constexpr (buffer_size_check == BufferSizeCheck::kCheck) { - if (DoesExceedSizeLimit(isolate, RecipeTrait::ByteLength(blink_value), - exception_state)) { - return RecipeTrait::NullValue(); - } - } - return RecipeTrait::ToReturnType(blink_value); - } - - if constexpr (nullablity == Nullablity::kIsNullable) { - if (LIKELY(value->IsNullOrUndefined())) { - return RecipeTrait::NullValue(); - } - } - const char* buffer_source_type_name = nullptr; if constexpr (std::is_base_of_v<ScriptWrappable, ScriptWrappableOrBufferSourceTypeName>) { @@ -89,6 +75,33 @@ buffer_source_type_name = ScriptWrappableOrBufferSourceTypeName::GetName(); } + auto blink_value = ToBlinkValue(isolate, value); + if (LIKELY(RecipeTrait::IsNonNull(blink_value))) { + if constexpr (allow_resizable == ResizableAllowance::kDisallowResizable) { + if (RecipeTrait::IsResizable(blink_value)) { + exception_state.ThrowTypeError( + ExceptionMessages::ResizableArrayBufferNotAllowed( + buffer_source_type_name)); + return RecipeTrait::NullValue(); + } + } + + if constexpr (buffer_size_check == BufferSizeCheck::kCheck) { + if (DoesExceedSizeLimit(isolate, RecipeTrait::ByteLength(blink_value), + exception_state)) { + return RecipeTrait::NullValue(); + } + } + + return RecipeTrait::ToReturnType(blink_value); + } + + if constexpr (nullablity == Nullablity::kIsNullable) { + if (LIKELY(value->IsNullOrUndefined())) { + return RecipeTrait::NullValue(); + } + } + if constexpr (IsSharedBuffer != nullptr) { if (IsSharedBuffer(value)) { exception_state.ThrowTypeError( @@ -106,32 +119,16 @@ // The basic recipe of NativeValueTraits<T>::ArgumentValue function // implementation for buffer source types. template <typename RecipeTrait, - auto(*ToBlinkValue)(v8::Isolate*, v8::Local<v8::Value>), + auto (*ToBlinkValue)(v8::Isolate*, v8::Local<v8::Value>), Nullablity nullablity, BufferSizeCheck buffer_size_check, + ResizableAllowance allow_resizable, typename ScriptWrappableOrBufferSourceTypeName, bool (*IsSharedBuffer)(v8::Local<v8::Value>) = nullptr> auto ArgumentValueImpl(v8::Isolate* isolate, int argument_index, v8::Local<v8::Value> value, ExceptionState& exception_state) { - auto blink_value = ToBlinkValue(isolate, value); - if (LIKELY(RecipeTrait::IsNonNull(blink_value))) { - if constexpr (buffer_size_check == BufferSizeCheck::kCheck) { - if (DoesExceedSizeLimit(isolate, RecipeTrait::ByteLength(blink_value), - exception_state)) { - return RecipeTrait::NullValue(); - } - } - return RecipeTrait::ToReturnType(blink_value); - } - - if constexpr (nullablity == Nullablity::kIsNullable) { - if (LIKELY(value->IsNullOrUndefined())) { - return RecipeTrait::NullValue(); - } - } - const char* buffer_source_type_name = nullptr; if constexpr (std::is_base_of_v<ScriptWrappable, ScriptWrappableOrBufferSourceTypeName>) { @@ -142,6 +139,33 @@ buffer_source_type_name = ScriptWrappableOrBufferSourceTypeName::GetName(); } + auto blink_value = ToBlinkValue(isolate, value); + if (LIKELY(RecipeTrait::IsNonNull(blink_value))) { + if constexpr (allow_resizable == ResizableAllowance::kDisallowResizable) { + if (RecipeTrait::IsResizable(blink_value)) { + exception_state.ThrowTypeError( + ExceptionMessages::ResizableArrayBufferNotAllowed( + buffer_source_type_name)); + return RecipeTrait::NullValue(); + } + } + + if constexpr (buffer_size_check == BufferSizeCheck::kCheck) { + if (DoesExceedSizeLimit(isolate, RecipeTrait::ByteLength(blink_value), + exception_state)) { + return RecipeTrait::NullValue(); + } + } + + return RecipeTrait::ToReturnType(blink_value); + } + + if constexpr (nullablity == Nullablity::kIsNullable) { + if (LIKELY(value->IsNullOrUndefined())) { + return RecipeTrait::NullValue(); + } + } + if constexpr (IsSharedBuffer != nullptr) { if (IsSharedBuffer(value)) { exception_state.ThrowTypeError( @@ -217,10 +241,15 @@ template <typename T, typename unused = void> struct RecipeTrait { - static bool IsNonNull(const T* buffer) { return buffer; } + static bool IsNonNull(const T* buffer_view) { return buffer_view; } static T* NullValue() { return nullptr; } - static T* ToReturnType(T* buffer) { return buffer; } - static size_t ByteLength(const T* buffer) { return buffer->byteLength(); } + static T* ToReturnType(T* buffer_view) { return buffer_view; } + static size_t ByteLength(const T* buffer_view) { + return buffer_view->byteLength(); + } + static bool IsResizable(const T* buffer_view) { + return buffer_view->BufferBase()->IsResizableByUserJavaScript(); + } }; template <typename T> @@ -230,6 +259,9 @@ static T* NullValue() { return nullptr; } static T* ToReturnType(T* buffer) { return buffer; } static size_t ByteLength(const T* buffer) { return buffer->ByteLength(); } + static bool IsResizable(const T* buffer) { + return buffer->IsResizableByUserJavaScript(); + } }; template <typename T> @@ -260,6 +292,12 @@ static size_t ByteLength(v8::Local<v8::Value> buffer) { return buffer.As<typename ABVTrait<T>::V8ViewType>()->ByteLength(); } + static bool IsResizable(v8::Local<v8::Value> buffer) { + return buffer.As<typename ABVTrait<T>::V8ViewType>() + ->Buffer() + ->GetBackingStore() + ->IsResizableByUserJavaScript(); + } }; // ToBlinkValue implementation for the recipe functions @@ -432,6 +470,7 @@ ExceptionState& exception_state) { return NativeValueImpl<RecipeTrait<DOMArrayBuffer>, ToDOMArrayBuffer, Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, DOMArrayBuffer>(isolate, value, exception_state); } @@ -442,6 +481,7 @@ ExceptionState& exception_state) { return ArgumentValueImpl<RecipeTrait<DOMArrayBuffer>, ToDOMArrayBuffer, Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, DOMArrayBuffer>(isolate, argument_index, value, exception_state); } @@ -454,6 +494,7 @@ ExceptionState& exception_state) { return NativeValueImpl<RecipeTrait<DOMArrayBuffer>, ToDOMArrayBuffer, Nullablity::kIsNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, DOMArrayBuffer>(isolate, value, exception_state); } @@ -464,19 +505,46 @@ ExceptionState& exception_state) { return ArgumentValueImpl<RecipeTrait<DOMArrayBuffer>, ToDOMArrayBuffer, Nullablity::kIsNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, DOMArrayBuffer>(isolate, argument_index, value, exception_state); } +// [AllowResizable] ArrayBuffer + +DOMArrayBuffer* +NativeValueTraits<IDLAllowResizable<DOMArrayBuffer>>::NativeValue( + v8::Isolate* isolate, + v8::Local<v8::Value> value, + ExceptionState& exception_state) { + return NativeValueImpl<RecipeTrait<DOMArrayBuffer>, ToDOMArrayBuffer, + Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kAllowResizable, DOMArrayBuffer>( + isolate, value, exception_state); +} + +DOMArrayBuffer* +NativeValueTraits<IDLAllowResizable<DOMArrayBuffer>>::ArgumentValue( + v8::Isolate* isolate, + int argument_index, + v8::Local<v8::Value> value, + ExceptionState& exception_state) { + return ArgumentValueImpl<RecipeTrait<DOMArrayBuffer>, ToDOMArrayBuffer, + Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kAllowResizable, DOMArrayBuffer>( + isolate, argument_index, value, exception_state); +} + // SharedArrayBuffer DOMSharedArrayBuffer* NativeValueTraits<DOMSharedArrayBuffer>::NativeValue( v8::Isolate* isolate, v8::Local<v8::Value> value, ExceptionState& exception_state) { - return NativeValueImpl<RecipeTrait<DOMSharedArrayBuffer>, - ToDOMSharedArrayBuffer, Nullablity::kIsNotNullable, - BufferSizeCheck::kCheck, DOMSharedArrayBuffer>( + return NativeValueImpl< + RecipeTrait<DOMSharedArrayBuffer>, ToDOMSharedArrayBuffer, + Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, DOMSharedArrayBuffer>( isolate, value, exception_state); } @@ -485,9 +553,10 @@ int argument_index, v8::Local<v8::Value> value, ExceptionState& exception_state) { - return ArgumentValueImpl<RecipeTrait<DOMSharedArrayBuffer>, - ToDOMSharedArrayBuffer, Nullablity::kIsNotNullable, - BufferSizeCheck::kCheck, DOMSharedArrayBuffer>( + return ArgumentValueImpl< + RecipeTrait<DOMSharedArrayBuffer>, ToDOMSharedArrayBuffer, + Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, DOMSharedArrayBuffer>( isolate, argument_index, value, exception_state); } @@ -498,9 +567,10 @@ v8::Isolate* isolate, v8::Local<v8::Value> value, ExceptionState& exception_state) { - return NativeValueImpl<RecipeTrait<DOMSharedArrayBuffer>, - ToDOMSharedArrayBuffer, Nullablity::kIsNullable, - BufferSizeCheck::kCheck, DOMSharedArrayBuffer>( + return NativeValueImpl< + RecipeTrait<DOMSharedArrayBuffer>, ToDOMSharedArrayBuffer, + Nullablity::kIsNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, DOMSharedArrayBuffer>( isolate, value, exception_state); } @@ -510,9 +580,37 @@ int argument_index, v8::Local<v8::Value> value, ExceptionState& exception_state) { - return ArgumentValueImpl<RecipeTrait<DOMSharedArrayBuffer>, - ToDOMSharedArrayBuffer, Nullablity::kIsNullable, - BufferSizeCheck::kCheck, DOMSharedArrayBuffer>( + return ArgumentValueImpl< + RecipeTrait<DOMSharedArrayBuffer>, ToDOMSharedArrayBuffer, + Nullablity::kIsNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, DOMSharedArrayBuffer>( + isolate, argument_index, value, exception_state); +} + +// [AllowResizable] SharedArrayBuffer + +DOMSharedArrayBuffer* +NativeValueTraits<IDLAllowResizable<DOMSharedArrayBuffer>>::NativeValue( + v8::Isolate* isolate, + v8::Local<v8::Value> value, + ExceptionState& exception_state) { + return NativeValueImpl< + RecipeTrait<DOMSharedArrayBuffer>, ToDOMSharedArrayBuffer, + Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kAllowResizable, DOMSharedArrayBuffer>( + isolate, value, exception_state); +} + +DOMSharedArrayBuffer* +NativeValueTraits<IDLAllowResizable<DOMSharedArrayBuffer>>::ArgumentValue( + v8::Isolate* isolate, + int argument_index, + v8::Local<v8::Value> value, + ExceptionState& exception_state) { + return ArgumentValueImpl< + RecipeTrait<DOMSharedArrayBuffer>, ToDOMSharedArrayBuffer, + Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kAllowResizable, DOMSharedArrayBuffer>( isolate, argument_index, value, exception_state); } @@ -524,6 +622,7 @@ ExceptionState& exception_state) { return NativeValueImpl<RecipeTrait<DOMArrayBufferBase>, ToDOMArrayBufferBase, Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, BufferSourceTypeNameAllowSharedArrayBuffer>( isolate, value, exception_state); } @@ -536,6 +635,7 @@ return ArgumentValueImpl<RecipeTrait<DOMArrayBufferBase>, ToDOMArrayBufferBase, Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, BufferSourceTypeNameAllowSharedArrayBuffer>( isolate, argument_index, value, exception_state); } @@ -550,6 +650,7 @@ return ArgumentValueImpl<RecipeTrait<DOMArrayBufferBase>, ToDOMArrayBufferBase, Nullablity::kIsNotNullable, BufferSizeCheck::kDoNotCheck, + ResizableAllowance::kDisallowResizable, BufferSourceTypeNameAllowSharedArrayBuffer>( isolate, argument_index, value, exception_state); } @@ -563,6 +664,7 @@ ExceptionState& exception_state) { return NativeValueImpl<RecipeTrait<DOMArrayBufferBase>, ToDOMArrayBufferBase, Nullablity::kIsNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, BufferSourceTypeNameAllowSharedArrayBuffer>( isolate, value, exception_state); } @@ -576,6 +678,7 @@ return ArgumentValueImpl<RecipeTrait<DOMArrayBufferBase>, ToDOMArrayBufferBase, Nullablity::kIsNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, BufferSourceTypeNameAllowSharedArrayBuffer>( isolate, argument_index, value, exception_state); } @@ -591,6 +694,7 @@ return ArgumentValueImpl<RecipeTrait<DOMArrayBufferBase>, ToDOMArrayBufferBase, Nullablity::kIsNullable, BufferSizeCheck::kDoNotCheck, + ResizableAllowance::kDisallowResizable, BufferSourceTypeNameAllowSharedArrayBuffer>( isolate, argument_index, value, exception_state); } @@ -604,11 +708,11 @@ NativeValue(v8::Isolate* isolate, v8::Local<v8::Value> value, ExceptionState& exception_state) { - return NativeValueImpl<RecipeTrait<NotShared<T>>, - ToDOMViewType<T, kNotShared>, - Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, T, - ABVTrait<T>::IsShared>(isolate, value, - exception_state); + return NativeValueImpl< + RecipeTrait<NotShared<T>>, ToDOMViewType<T, kNotShared>, + Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, T, ABVTrait<T>::IsShared>( + isolate, value, exception_state); } template <typename T> @@ -619,11 +723,11 @@ int argument_index, v8::Local<v8::Value> value, ExceptionState& exception_state) { - return ArgumentValueImpl<RecipeTrait<NotShared<T>>, - ToDOMViewType<T, kNotShared>, - Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, - T, ABVTrait<T>::IsShared>(isolate, argument_index, - value, exception_state); + return ArgumentValueImpl< + RecipeTrait<NotShared<T>>, ToDOMViewType<T, kNotShared>, + Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, T, ABVTrait<T>::IsShared>( + isolate, argument_index, value, exception_state); } // [AllowShared] ArrayBufferView @@ -635,10 +739,11 @@ NativeValue(v8::Isolate* isolate, v8::Local<v8::Value> value, ExceptionState& exception_state) { - return NativeValueImpl< - RecipeTrait<MaybeShared<T>>, ToDOMViewType<T, kMaybeShared>, - Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, T>(isolate, value, - exception_state); + return NativeValueImpl<RecipeTrait<MaybeShared<T>>, + ToDOMViewType<T, kMaybeShared>, + Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, T>( + isolate, value, exception_state); } template <typename T> @@ -649,9 +754,10 @@ int argument_index, v8::Local<v8::Value> value, ExceptionState& exception_state) { - return ArgumentValueImpl< - RecipeTrait<MaybeShared<T>>, ToDOMViewType<T, kMaybeShared>, - Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, T>( + return ArgumentValueImpl<RecipeTrait<MaybeShared<T>>, + ToDOMViewType<T, kMaybeShared>, + Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, T>( isolate, argument_index, value, exception_state); } @@ -666,8 +772,9 @@ ExceptionState& exception_state) { return NativeValueImpl< RecipeTrait<MaybeShared<T>>, ToDOMViewType<T, kMaybeShared>, - Nullablity::kIsNotNullable, BufferSizeCheck::kDoNotCheck, T>( - isolate, value, exception_state); + Nullablity::kIsNotNullable, BufferSizeCheck::kDoNotCheck, + ResizableAllowance::kDisallowResizable, T>(isolate, value, + exception_state); } template <typename T> @@ -680,8 +787,9 @@ ExceptionState& exception_state) { return ArgumentValueImpl< RecipeTrait<MaybeShared<T>>, ToDOMViewType<T, kMaybeShared>, - Nullablity::kIsNotNullable, BufferSizeCheck::kDoNotCheck, T>( - isolate, argument_index, value, exception_state); + Nullablity::kIsNotNullable, BufferSizeCheck::kDoNotCheck, + ResizableAllowance::kDisallowResizable, T>(isolate, argument_index, value, + exception_state); } // Nullable ArrayBufferView @@ -693,9 +801,10 @@ NativeValue(v8::Isolate* isolate, v8::Local<v8::Value> value, ExceptionState& exception_state) { - return NativeValueImpl<RecipeTrait<NotShared<T>>, - ToDOMViewType<T, kNotShared>, Nullablity::kIsNullable, - BufferSizeCheck::kCheck, T, ABVTrait<T>::IsShared>( + return NativeValueImpl< + RecipeTrait<NotShared<T>>, ToDOMViewType<T, kNotShared>, + Nullablity::kIsNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, T, ABVTrait<T>::IsShared>( isolate, value, exception_state); } @@ -707,11 +816,11 @@ int argument_index, v8::Local<v8::Value> value, ExceptionState& exception_state) { - return ArgumentValueImpl<RecipeTrait<NotShared<T>>, - ToDOMViewType<T, kNotShared>, - Nullablity::kIsNullable, BufferSizeCheck::kCheck, T, - ABVTrait<T>::IsShared>(isolate, argument_index, - value, exception_state); + return ArgumentValueImpl< + RecipeTrait<NotShared<T>>, ToDOMViewType<T, kNotShared>, + Nullablity::kIsNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, T, ABVTrait<T>::IsShared>( + isolate, argument_index, value, exception_state); } // Nullable [AllowShared] ArrayBufferView @@ -725,7 +834,8 @@ ExceptionState& exception_state) { return NativeValueImpl<RecipeTrait<MaybeShared<T>>, ToDOMViewType<T, kMaybeShared>, - Nullablity::kIsNullable, BufferSizeCheck::kCheck, T>( + Nullablity::kIsNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, T>( isolate, value, exception_state); } @@ -739,7 +849,8 @@ ExceptionState& exception_state) { return ArgumentValueImpl<RecipeTrait<MaybeShared<T>>, ToDOMViewType<T, kMaybeShared>, - Nullablity::kIsNullable, BufferSizeCheck::kCheck, T>( + Nullablity::kIsNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, T>( isolate, argument_index, value, exception_state); } @@ -755,8 +866,9 @@ ExceptionState& exception_state) { return ArgumentValueImpl< RecipeTrait<MaybeShared<T>>, ToDOMViewType<T, kMaybeShared>, - Nullablity::kIsNullable, BufferSizeCheck::kDoNotCheck, T>( - isolate, argument_index, value, exception_state); + Nullablity::kIsNullable, BufferSizeCheck::kDoNotCheck, + ResizableAllowance::kDisallowResizable, T>(isolate, argument_index, value, + exception_state); } // [AllowShared, FlexibleArrayBufferView] ArrayBufferView @@ -771,6 +883,7 @@ ExceptionState& exception_state) { return ArgumentValueImpl<RecipeTrait<T>, ToFlexibleArrayBufferView, Nullablity::kIsNotNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, typename ABVTrait<T>::DOMViewType>( isolate, argument_index, value, exception_state); } @@ -788,8 +901,9 @@ ExceptionState& exception_state) { return ArgumentValueImpl< RecipeTrait<T>, ToFlexibleArrayBufferView, Nullablity::kIsNotNullable, - BufferSizeCheck::kDoNotCheck, typename ABVTrait<T>::DOMViewType>( - isolate, argument_index, value, exception_state); + BufferSizeCheck::kDoNotCheck, ResizableAllowance::kDisallowResizable, + typename ABVTrait<T>::DOMViewType>(isolate, argument_index, value, + exception_state); } // Nullable [AllowShared, FlexibleArrayBufferView] ArrayBufferView @@ -804,6 +918,7 @@ ExceptionState& exception_state) { return ArgumentValueImpl<RecipeTrait<T>, ToFlexibleArrayBufferView, Nullablity::kIsNullable, BufferSizeCheck::kCheck, + ResizableAllowance::kDisallowResizable, typename ABVTrait<T>::DOMViewType>( isolate, argument_index, value, exception_state); }
diff --git a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h index b054098..849062a 100644 --- a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h +++ b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
@@ -577,6 +577,19 @@ }; template <> +struct CORE_EXPORT NativeValueTraits<IDLAllowResizable<DOMArrayBuffer>> + : public NativeValueTraitsBase<DOMArrayBuffer*> { + static DOMArrayBuffer* NativeValue(v8::Isolate* isolate, + v8::Local<v8::Value> value, + ExceptionState& exception_state); + + static DOMArrayBuffer* ArgumentValue(v8::Isolate* isolate, + int argument_index, + v8::Local<v8::Value> value, + ExceptionState& exception_state); +}; + +template <> struct CORE_EXPORT NativeValueTraits<DOMSharedArrayBuffer> : public NativeValueTraitsBase<DOMSharedArrayBuffer*> { static DOMSharedArrayBuffer* NativeValue(v8::Isolate* isolate, @@ -602,6 +615,19 @@ ExceptionState& exception_state); }; +template <> +struct CORE_EXPORT NativeValueTraits<IDLAllowResizable<DOMSharedArrayBuffer>> + : public NativeValueTraitsBase<DOMSharedArrayBuffer*> { + static DOMSharedArrayBuffer* NativeValue(v8::Isolate* isolate, + v8::Local<v8::Value> value, + ExceptionState& exception_state); + + static DOMSharedArrayBuffer* ArgumentValue(v8::Isolate* isolate, + int argument_index, + v8::Local<v8::Value> value, + ExceptionState& exception_state); +}; + // DOMArrayBufferBase is the common base class of DOMArrayBuffer and // DOMSharedArrayBuffer, so it behaves as "[AllowShared] ArrayBuffer" in // Web IDL.
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc index 480d532..62de65f 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc
@@ -121,8 +121,8 @@ } if (object->IsArrayBuffer()) { DOMArrayBuffer* array_buffer = - NativeValueTraits<DOMArrayBuffer>::NativeValue(isolate, object, - exception_state); + NativeValueTraits<IDLAllowResizable<DOMArrayBuffer>>::NativeValue( + isolate, object, exception_state); if (exception_state.HadException()) return false; if (transferables.array_buffers.Contains(array_buffer)) { @@ -137,8 +137,8 @@ } if (object->IsSharedArrayBuffer()) { DOMSharedArrayBuffer* shared_array_buffer = - NativeValueTraits<DOMSharedArrayBuffer>::NativeValue(isolate, object, - exception_state); + NativeValueTraits<IDLAllowResizable<DOMSharedArrayBuffer>>::NativeValue( + isolate, object, exception_state); if (exception_state.HadException()) return false; if (transferables.array_buffers.Contains(shared_array_buffer)) {
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc index 59d6e4ba..3d91f59 100644 --- a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc +++ b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
@@ -163,7 +163,6 @@ ScriptPromiseResolver* resolver) : fail_encoder_initialization_for_test_(false), enforce_idle_encoding_for_test_(false), - image_(image), context_(context), encode_options_(options), function_type_(function_type), @@ -172,7 +171,6 @@ input_digest_(input_digest), callback_(callback), script_promise_resolver_(resolver) { - DCHECK(image); DCHECK(context); mime_type_ = ImageEncoderUtils::ToEncodingMimeType( @@ -181,9 +179,9 @@ // We use pixmap to access the image pixels. Make the image unaccelerated if // necessary. - image_ = image_->MakeUnaccelerated(); + DCHECK(image); + image_ = image->MakeUnaccelerated(); - DCHECK(image_); sk_sp<SkImage> skia_image = image_->PaintImageForCurrentFrame().GetSwSkImage(); DCHECK(skia_image);
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc index 115d5d09..c5ca9c8 100644 --- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc +++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -1153,11 +1153,10 @@ CanvasAsyncBlobCreator* async_creator = nullptr; scoped_refptr<StaticBitmapImage> image_bitmap = Snapshot(kBackBuffer); if (image_bitmap) { - auto image_unaccelerated = image_bitmap->MakeUnaccelerated(); auto* options = ImageEncodeOptions::Create(); options->setType(ImageEncodingMimeTypeName(encoding_mime_type)); async_creator = MakeGarbageCollected<CanvasAsyncBlobCreator>( - std::move(image_unaccelerated), options, + image_bitmap, options, CanvasAsyncBlobCreator::kHTMLCanvasToBlobCallback, callback, start_time, GetExecutionContext(), IdentifiabilityStudySettings::Get()->ShouldSampleType(
diff --git a/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc index 36f25d2..5937e50 100644 --- a/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc
@@ -208,8 +208,10 @@ // 2.3. Let result[i].x = CSS_positions[i].x + shift.x and // result[i].y = CSS_positions[i].y + shift.y. const float scaling_factor = ScalingFactorAt(items, i); - result_[i].x = css_positions_[i].x() + shift.x() * scaling_factor; - result_[i].y = css_positions_[i].y() + shift.y() * scaling_factor; + result_[i].x = + ClampTo<float>(css_positions_[i].x() + shift.x() * scaling_factor); + result_[i].y = + ClampTo<float>(css_positions_[i].y() + shift.y() * scaling_factor); } } @@ -241,9 +243,9 @@ const unsigned i = range.start_index; const unsigned j_plus_1 = range.end_index + 1; auto* element = To<SVGTextContentElement>(range.layout_object->GetNode()); - const float text_length = + const float text_length = ClampTo<float>( element->textLength()->CurrentValue()->Value(SVGLengthContext(element)) * - ScalingFactorAt(items, i); + ScalingFactorAt(items, i)); const SVGLengthAdjustType length_adjust = element->lengthAdjust()->CurrentEnumValue(); @@ -413,6 +415,7 @@ // Take into account of baseline-shift. if (!horizontal_) shift.set_x(shift.x() + css_positions_[i].x()); + shift.set_x(ClampTo<float>(shift.x())); } // 3.2. If resolved_y[index] is set, then let // shift.y = resolved_y[index] − result.y[index]. @@ -423,6 +426,7 @@ // Take into account of baseline-shift. if (horizontal_) shift.set_y(shift.y() + css_positions_[i].y()); + shift.set_y(ClampTo<float>(shift.y())); } // If this character is the first one in a <textPath>, reset the @@ -665,6 +669,8 @@ info.x = point_tangent.point.x() * scaling_factor; info.y = point_tangent.point.y() * scaling_factor; } + info.x = ClampTo<float>(*info.x); + info.y = ClampTo<float>(*info.y); } } } else { @@ -698,8 +704,10 @@ PointAndTangent point_tangent; path_mapper->PointAndNormalAtLength(path_mapper->length(), point_tangent); - path_end_x = point_tangent.point.x() * scaling_factor - *info.x; - path_end_y = point_tangent.point.y() * scaling_factor - *info.y; + path_end_x = ClampTo<float>(point_tangent.point.x() * scaling_factor - + *info.x); + path_end_y = ClampTo<float>(point_tangent.point.y() * scaling_factor - + *info.y); } else { // The 'current text position' should be at the next to the last // drawn character.
diff --git a/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm_test.cc index 2ed2aa0af..6a8396b 100644 --- a/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm_test.cc +++ b/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm_test.cc
@@ -50,4 +50,18 @@ // Pass if no crashes. } +TEST_F(NGSVGTextLayoutAlgorithmTest, HugeScaleCrash) { + SetBodyInnerHTML(R"HTML( + <svg xmlns="http://www.w3.org/2000/svg" width="450" height="450"> + <style> + #test-body-content { + scale: 16420065941240262705269076410170673060945878020586681613052798923953430637521913631296811416; + } + </style> + <text id="test-body-content" x="-10" y="14">A</text> + </svg>)HTML"); + UpdateAllLifecyclePhasesForTest(); + // Pass if no crashes. +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message.cc b/third_party/blink/renderer/core/messaging/blink_transferable_message.cc index a301728..04c8c61 100644 --- a/third_party/blink/renderer/core/messaging/blink_transferable_message.cc +++ b/third_party/blink/renderer/core/messaging/blink_transferable_message.cc
@@ -62,7 +62,11 @@ for (auto& item : message.array_buffer_contents_array) { mojo_base::BigBuffer& big_buffer = item->contents; - ArrayBufferContents contents(big_buffer.size(), 1, + absl::optional<size_t> max_byte_length; + if (item->is_resizable_by_user_javascript) { + max_byte_length = base::checked_cast<size_t>(item->max_byte_length); + } + ArrayBufferContents contents(big_buffer.size(), max_byte_length, 1, ArrayBufferContents::kNotShared, ArrayBufferContents::kDontInitialize); // Check if we allocated the backing store of the ArrayBufferContents
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc b/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc index 262e827..fd3750bb 100644 --- a/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc +++ b/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc
@@ -113,8 +113,13 @@ return false; auto contents_data = contents_view.data(); + absl::optional<size_t> max_data_size; + if (data.is_resizable_by_user_javascript()) { + max_data_size = base::checked_cast<size_t>(data.max_byte_length()); + } blink::ArrayBufferContents array_buffer_contents( - contents_data.size(), 1, blink::ArrayBufferContents::kNotShared, + contents_data.size(), max_data_size, 1, + blink::ArrayBufferContents::kNotShared, blink::ArrayBufferContents::kDontInitialize); if (contents_data.size() != array_buffer_contents.DataLength()) { return false;
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h b/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h index 643ad5e..2d43c2fb 100644 --- a/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h +++ b/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h
@@ -90,6 +90,15 @@ return mojo_base::BigBuffer( base::make_span(allocation_start, array_buffer_contents.DataLength())); } + static bool is_resizable_by_user_javascript( + const blink::ArrayBufferContents& array_buffer_contents) { + return array_buffer_contents.IsResizableByUserJavaScript(); + } + static size_t max_byte_length( + const blink::ArrayBufferContents& array_buffer_contents) { + return array_buffer_contents.MaxDataLength(); + } + static bool Read(blink::mojom::SerializedArrayBufferContentsDataView, blink::ArrayBufferContents* out); };
diff --git a/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc b/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc index ae25b305..b3e7c1c4 100644 --- a/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc +++ b/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc
@@ -75,6 +75,8 @@ std::unique_ptr<Canvas2DLayerBridge> bridge = MakeCanvas2DLayerBridge(size); element->SetResourceProviderForTesting(nullptr, std::move(bridge), size); ASSERT_EQ(context, element->RenderingContext()); + ASSERT_TRUE(context->IsComposited()); + ASSERT_TRUE(element->IsAccelerated()); // Force the page to paint. element->PreFinalizeFrame(); @@ -82,9 +84,6 @@ element->PostFinalizeFrame(); UpdateAllLifecyclePhasesForTest(); - ASSERT_TRUE(context->IsComposited()); - ASSERT_TRUE(element->IsAccelerated()); - // Fetch the layer associated with the <canvas>, and check that it was // correctly configured in the layer tree. const cc::Layer* layer = context->CcLayer();
diff --git a/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.cc b/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.cc index 72257f8..202fcb5 100644 --- a/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.cc +++ b/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.cc
@@ -68,6 +68,7 @@ ArrayBufferContents::ArrayBufferContents( size_t num_elements, + absl::optional<size_t> max_num_elements, size_t element_byte_size, SharingType is_shared, ArrayBufferContents::InitializationPolicy policy) { @@ -79,17 +80,36 @@ return; } size_t length = checked_length.ValueOrDie(); - void* data = AllocateMemoryOrNull(length, policy); - if (!data) { - return; - } - auto deleter = [](void* data, size_t, void*) { FreeMemory(data); }; - if (is_shared == kNotShared) { - backing_store_ = - v8::ArrayBuffer::NewBackingStore(data, length, deleter, nullptr); + + if (!max_num_elements) { + // Create a fixed-length ArrayBuffer. + void* data = AllocateMemoryOrNull(length, policy); + if (!data) { + return; + } + auto deleter = [](void* data, size_t, void*) { FreeMemory(data); }; + if (is_shared == kNotShared) { + backing_store_ = + v8::ArrayBuffer::NewBackingStore(data, length, deleter, nullptr); + } else { + backing_store_ = v8::SharedArrayBuffer::NewBackingStore(data, length, + deleter, nullptr); + } } else { + // The resizable form of the constructor is currently only used for IPC + // transfers of ArrayBuffers, and SharedArrayBuffers cannot be transferred + // across agent clusters. + DCHECK_EQ(kNotShared, is_shared); + // Currently V8 does not support embedder-allocated resizable backing + // stores. It does not zero resizable allocations, which use a + // reserve-and-partially-commit pattern. Check that the caller is not + // expecting zeroed memory. + CHECK_EQ(kDontInitialize, policy); + auto max_checked_length = + base::CheckedNumeric<size_t>(*max_num_elements) * element_byte_size; + size_t max_length = max_checked_length.ValueOrDie(); backing_store_ = - v8::SharedArrayBuffer::NewBackingStore(data, length, deleter, nullptr); + v8::ArrayBuffer::NewResizableBackingStore(length, max_length); } }
diff --git a/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h b/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h index 6728537..eed68f28 100644 --- a/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h +++ b/third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h
@@ -61,6 +61,19 @@ ArrayBufferContents(size_t num_elements, size_t element_byte_size, SharingType is_shared, + InitializationPolicy policy) + : ArrayBufferContents(num_elements, + absl::nullopt, + element_byte_size, + is_shared, + policy) {} + // If max_num_elements has a value, a backing store for a resizable + // ArrayBuffer is created. Otherwise a backing store for a fixed-length + // ArrayBuffer is created. + ArrayBufferContents(size_t num_elements, + absl::optional<size_t> max_num_elements, + size_t element_byte_size, + SharingType is_shared, InitializationPolicy); ArrayBufferContents( @@ -99,9 +112,16 @@ size_t DataLength() const { return backing_store_ ? backing_store_->ByteLength() : 0; } + size_t MaxDataLength() const { + return backing_store_ ? backing_store_->MaxByteLength() : 0; + } bool IsShared() const { return backing_store_ ? backing_store_->IsShared() : false; } + bool IsResizableByUserJavaScript() const { + return backing_store_ ? backing_store_->IsResizableByUserJavaScript() + : false; + } bool IsValid() const { return backing_store_ && backing_store_->Data(); } std::shared_ptr<v8::BackingStore> BackingStore() const {
diff --git a/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_base.h b/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_base.h index e31773e..9551143 100644 --- a/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_base.h +++ b/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_base.h
@@ -33,6 +33,10 @@ bool IsShared() const { return contents_.IsShared(); } + bool IsResizableByUserJavaScript() const { + return contents_.IsResizableByUserJavaScript(); + } + // ScriptWrappable overrides: v8::MaybeLocal<v8::Value> Wrap(ScriptState*) override { NOTREACHED();
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc index 1261f1d..f9f4621 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
@@ -189,10 +189,7 @@ } bool CanvasRenderingContext2D::IsComposited() const { - if (Canvas2DLayerBridge* layer_bridge = canvas()->GetCanvas2DLayerBridge()) { - return layer_bridge->IsComposited(); - } - return false; + return IsAccelerated(); } void CanvasRenderingContext2D::Stop() {
diff --git a/third_party/blink/renderer/platform/bindings/exception_messages.cc b/third_party/blink/renderer/platform/bindings/exception_messages.cc index 444f7b6..3e3403a9 100644 --- a/third_party/blink/renderer/platform/bindings/exception_messages.cc +++ b/third_party/blink/renderer/platform/bindings/exception_messages.cc
@@ -271,6 +271,12 @@ expected_type); } +String ExceptionMessages::ResizableArrayBufferNotAllowed( + const char* expected_type) { + return String::Format("The provided %s value must not be resizable.", + expected_type); +} + String ExceptionMessages::ValueNotOfType(const char* expected_type) { return String::Format("The provided value is not of type '%s'.", expected_type);
diff --git a/third_party/blink/renderer/platform/bindings/exception_messages.h b/third_party/blink/renderer/platform/bindings/exception_messages.h index 83d7dcd8..7e092f3c 100644 --- a/third_party/blink/renderer/platform/bindings/exception_messages.h +++ b/third_party/blink/renderer/platform/bindings/exception_messages.h
@@ -129,6 +129,8 @@ static String SharedArrayBufferNotAllowed(const char* expected_type); + static String ResizableArrayBufferNotAllowed(const char* expected_type); + static String ValueNotOfType(const char* expected_type); static String InputArrayTooLong(unsigned expected_size, unsigned actual_size);
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc index 2e6b5d1..7d6f4379 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
@@ -151,25 +151,6 @@ return ShouldAccelerate(); } -bool Canvas2DLayerBridge::IsComposited() const { - if (IsHibernating()) { - return false; - } - - if (UNLIKELY(!resource_host_)) { - return false; - } - - CanvasResourceProvider* resource_provider = - resource_host_->ResourceProvider(); - if (UNLIKELY(!resource_provider)) { - return false; - } - - return resource_provider->SupportsDirectCompositing() && - !resource_host_->LowLatencyEnabled(); -} - static void HibernateWrapper(base::WeakPtr<Canvas2DLayerBridge> bridge, base::TimeTicks /*idleDeadline*/) { if (bridge) { @@ -286,13 +267,14 @@ if (resource_provider && resource_provider->IsValid()) { #if DCHECK_IS_ON() - // If resource provider is composited, a layer should already exist. + // If resource provider is accelerated, a layer should already exist. // unless this is a canvas in low latency mode. // If this DCHECK fails, it probably means that // CanvasRenderingContextHost::GetOrCreateCanvasResourceProvider() was // called on a 2D context before this function. - if (IsComposited()) { - DCHECK(!!layer_); + if (IsAccelerated()) { + DCHECK(!!layer_ || + (resource_host_ && resource_host_->LowLatencyEnabled())); } #endif return resource_provider; @@ -327,7 +309,7 @@ // TODO crbug/1090081: Check possibility to move DidDraw inside Clear. DidDraw(); - if (IsComposited() && !layer_) { + if (IsAccelerated() && !layer_) { layer_ = cc::TextureLayer::CreateForMailbox(this); layer_->SetIsDrawable(true); layer_->SetHitTestable(true); @@ -337,7 +319,6 @@ cc::PaintFlags::FilterQuality::kNone); layer_->SetHDRConfiguration(resource_host_->GetHDRMode(), resource_host_->GetHDRMetadata()); - layer_->SetFlipped(!resource_provider->IsOriginTopLeft()); } // After the page becomes visible and successfully restored the canvas // resource provider, set |lose_context_in_background_| to false. @@ -771,7 +752,7 @@ constexpr unsigned kMaxCanvasAnimationBacklog = 2; if (frames_since_last_commit_ >= static_cast<int>(kMaxCanvasAnimationBacklog)) { - if (IsComposited() && !rate_limiter_) { + if (IsAccelerated() && !rate_limiter_) { rate_limiter_ = std::make_unique<SharedContextRateLimiter>( kMaxCanvasAnimationBacklog); } @@ -783,7 +764,7 @@ } void Canvas2DLayerBridge::DoPaintInvalidation(const gfx::Rect& dirty_rect) { - if (layer_ && IsComposited()) { + if (layer_ && raster_mode_ == RasterMode::kGPU) { layer_->SetNeedsDisplayRect(dirty_rect); } }
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h index ec1b2136..ed344ceb 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h +++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
@@ -96,8 +96,6 @@ virtual void DidRestoreCanvasMatrixClipStack(cc::PaintCanvas*) {} virtual bool IsAccelerated() const; - bool IsComposited() const; - // This may recreate CanvasResourceProvider cc::PaintCanvas* GetPaintCanvas(); bool IsValid();
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc index a1f5fde..0fcb0f5 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
@@ -1016,29 +1016,4 @@ EXPECT_FALSE(bridge->HasRateLimiterForTesting()); } -TEST_F(Canvas2DLayerBridgeTest, SoftwareCanvasIsCompositedIfImageChromium) { - ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform; - ScopedCanvas2dImageChromiumForTest canvas_2d_image_chromium(true); - const_cast<gpu::Capabilities&>(SharedGpuContext::ContextProviderWrapper() - ->ContextProvider() - ->GetCapabilities()) - .gpu_memory_buffer_formats.Put(gfx::BufferFormat::BGRA_8888); - std::unique_ptr<Canvas2DLayerBridge> bridge = - MakeBridge(gfx::Size(300, 150), RasterMode::kCPU, kNonOpaque); - EXPECT_TRUE(bridge->IsValid()); - DrawSomething(bridge.get()); - EXPECT_FALSE(bridge->IsAccelerated()); - EXPECT_TRUE(bridge->IsComposited()); -} - -TEST_F(Canvas2DLayerBridgeTest, SoftwareCanvasNotCompositedIfNotImageChromium) { - ScopedCanvas2dImageChromiumForTest canvas_2d_image_chromium(false); - std::unique_ptr<Canvas2DLayerBridge> bridge = - MakeBridge(gfx::Size(300, 150), RasterMode::kCPU, kNonOpaque); - EXPECT_TRUE(bridge->IsValid()); - DrawSomething(bridge.get()); - EXPECT_FALSE(bridge->IsAccelerated()); - EXPECT_FALSE(bridge->IsComposited()); -} - } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc index f0b976c3..d2f2e89 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -705,10 +705,7 @@ auto surface = SkSurface::MakeRasterDirect(CreateSkImageInfo(), gpu_memory_buffer_->memory(0), gpu_memory_buffer_->stride(0)); - - SkPixmap pixmap; - image->peekPixels(&pixmap); - surface->writePixels(pixmap, 0, 0); + surface->getCanvas()->drawImage(image, 0, 0); auto* sii = ContextProviderWrapper()->ContextProvider()->SharedImageInterface(); gpu_memory_buffer_->Unmap();
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 7d4502a6..36e06c76 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -910,6 +910,7 @@ crbug.com/1044742 external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-border-image.html [ Failure ] crbug.com/1044742 external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-filter.html [ Failure ] crbug.com/1044742 external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-stacking-context-001.html [ Failure ] +crbug.com/1044742 external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-video.html [ Failure ] crbug.com/1271275 external/wpt/css/compositing/background-blending/background-blend-mode-plus-lighter.html [ Failure ] @@ -2991,8 +2992,6 @@ crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ] # ====== New tests from wpt-importer added here ====== -crbug.com/626703 [ Mac12 ] external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-video.html [ Failure ] -crbug.com/626703 [ Win ] external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-video.html [ Failure ] crbug.com/626703 [ Win10.20h2 ] external/wpt/web-animations/idlharness.window.html [ Crash Failure ] crbug.com/626703 external/wpt/html/rendering/widgets/the-select-element/option-add-label-quirks.html [ Failure ] crbug.com/626703 [ Mac11-arm64 ] external/wpt/html/semantics/popovers/light-dismiss-event-ordering.tentative.html [ Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 9463d08..fe15e91e 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -1680,5 +1680,17 @@ ], "args": ["--enable-features=SplitUserMediaQueues"], "expires": "Jul 1, 2023" + }, + { + "prefix": "js-resizable-arraybuffer", + "platforms": ["Linux", "Mac", "Win"], + "bases": [ + "external/wpt/html/infrastructure/safe-passing-of-structured-data/cross-origin-transfer-resizable-arraybuffer.html" + ], + "exclusive_tests": [ + "external/wpt/html/infrastructure/safe-passing-of-structured-data/cross-origin-transfer-resizable-arraybuffer.html" + ], + "args": ["--js-flags=--harmony-rab-gsab"], + "expires": "Jul 1, 2023" } ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-001c.html b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-001c.html index 0f8195157..4fb7f113 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-001c.html +++ b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-001c.html
@@ -12,7 +12,6 @@ <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit"> <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position"> <link rel="match" href="object-fit-contain-png-001-ref.html"> - <meta name=fuzzy content="maxDifference=0-20;totalPixels=0-2000"> <style type="text/css"> canvas { border: 1px dashed gray;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-002c.html b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-002c.html index 14834316..738c015a 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-002c.html +++ b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-contain-png-002c.html
@@ -12,7 +12,6 @@ <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit"> <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position"> <link rel="match" href="object-fit-contain-png-002-ref.html"> - <meta name=fuzzy content="maxDifference=0-20;totalPixels=0-2000"> <style type="text/css"> canvas { border: 1px dashed gray;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-001c.html b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-001c.html index 0e2a388..36031175 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-001c.html +++ b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-001c.html
@@ -12,7 +12,6 @@ <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit"> <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position"> <link rel="match" href="object-fit-fill-png-001-ref.html"> - <meta name=fuzzy content="maxDifference=0-20;totalPixels=0-3200"> <style type="text/css"> canvas { border: 1px dashed gray;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-002c.html b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-002c.html index 43bcced..a332c37 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-002c.html +++ b/third_party/blink/web_tests/external/wpt/css/css-images/object-fit-fill-png-002c.html
@@ -12,7 +12,6 @@ <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-fit"> <link rel="help" href="http://www.w3.org/TR/css3-images/#the-object-position"> <link rel="match" href="object-fit-fill-png-002-ref.html"> - <meta name=fuzzy content="maxDifference=0-20;totalPixels=0-3200"> <style type="text/css"> canvas { border: 1px dashed gray;
diff --git a/third_party/blink/web_tests/external/wpt/html/infrastructure/safe-passing-of-structured-data/cross-origin-transfer-resizable-arraybuffer.html b/third_party/blink/web_tests/external/wpt/html/infrastructure/safe-passing-of-structured-data/cross-origin-transfer-resizable-arraybuffer.html new file mode 100644 index 0000000..2b21a145 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/infrastructure/safe-passing-of-structured-data/cross-origin-transfer-resizable-arraybuffer.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>postMessage transfer ArrayBuffer cross origin iframe</title> +<script src='/resources/testharness.js'></script> +<script src='/resources/testharnessreport.js'></script> +<script src='/common/get-host-info.sub.js'></script> + +<script> + +async_test(t => { + const oopif = document.createElement('iframe'); + + window.addEventListener('message', t.step_func((e) => { + if (e.data === 'started') { + const rab = new ArrayBuffer(32, { maxByteLength: 1024 }); + oopif.contentWindow.postMessage(rab, '*', [rab]); + } else { + assert_equals(e.data, 'byteLength=32,maxByteLength=1024,resizable=true'); + t.done(); + } + })); + + window.addEventListener('load', () => { + oopif.src = `${get_host_info().HTTP_REMOTE_ORIGIN}/html/infrastructure/safe-passing-of-structured-data/resources/iframe-resizable-arraybuffer-helper.html`; + document.body.appendChild(oopif); + }); +}, 'postMessaging resizable ArrayBuffer to OOPIF'); + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/infrastructure/safe-passing-of-structured-data/resources/iframe-resizable-arraybuffer-helper.html b/third_party/blink/web_tests/external/wpt/html/infrastructure/safe-passing-of-structured-data/resources/iframe-resizable-arraybuffer-helper.html new file mode 100644 index 0000000..378c953 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/infrastructure/safe-passing-of-structured-data/resources/iframe-resizable-arraybuffer-helper.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<script> + +window.addEventListener('message', (e) => { + const buffer = e.data; + e.source.postMessage(`byteLength=${buffer.byteLength},maxByteLength=${buffer.maxByteLength},resizable=${buffer.resizable}`, '*'); +}); + +window.parent.postMessage('started', '*'); + +</script>
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/canvas/canvas-incremental-repaint-expected.png index e2c967a..5f61902 100644 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/canvas/canvas-incremental-repaint-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/canvas/canvas-incremental-repaint-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color-scheme/color/color-picker-appearance-expected.png new file mode 100644 index 0000000..5d03ab2a --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-click-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-click-expected.png new file mode 100644 index 0000000..9597811 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-click-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png new file mode 100644 index 0000000..2d91917 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png new file mode 100644 index 0000000..ef045b8 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-drag-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-drag-expected.png new file mode 100644 index 0000000..9597811 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-drag-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png new file mode 100644 index 0000000..68e5798 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png new file mode 100644 index 0000000..c8b2b51 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png new file mode 100644 index 0000000..7a299d1 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png new file mode 100644 index 0000000..9176a3a1 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png new file mode 100644 index 0000000..220dc263 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png new file mode 100644 index 0000000..4090cebd --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png new file mode 100644 index 0000000..66da85c --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png new file mode 100644 index 0000000..cb7b5b4 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hex-format-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hex-format-expected.png new file mode 100644 index 0000000..c8acdf4d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hex-format-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hsl-format-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hsl-format-expected.png new file mode 100644 index 0000000..86aa0df --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hsl-format-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png new file mode 100644 index 0000000..6892e25b --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png new file mode 100644 index 0000000..450d929c --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-imperfect-match-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-imperfect-match-expected.png new file mode 100644 index 0000000..ea6faa4 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-imperfect-match-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-manual-color-change-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-manual-color-change-expected.png new file mode 100644 index 0000000..3d6f2cb --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-manual-color-change-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-set-value-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-set-value-expected.png new file mode 100644 index 0000000..6027fc7 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-set-value-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png new file mode 100644 index 0000000..36fe0c2 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-value-attribute-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-value-attribute-expected.png new file mode 100644 index 0000000..92335fbd --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-appearance-value-attribute-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png new file mode 100644 index 0000000..54909a8 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/color-spin/canvas-primary-squares-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/media/alpha-video-playback-expected.png similarity index 61% rename from third_party/blink/web_tests/platform/mac/virtual/color-spin/canvas-primary-squares-expected.png rename to third_party/blink/web_tests/platform/mac-mac11-arm64/media/alpha-video-playback-expected.png index 6530304..e4d0a9d 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/color-spin/canvas-primary-squares-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/media/alpha-video-playback-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/paint/invalidation/canvas-resize-no-full-invalidation-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/paint/invalidation/canvas-resize-no-full-invalidation-expected.png new file mode 100644 index 0000000..2bfe7f7 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/paint/invalidation/canvas-resize-no-full-invalidation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png new file mode 100644 index 0000000..3d15b57 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png new file mode 100644 index 0000000..8d0f8d8 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png new file mode 100644 index 0000000..c231417 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png deleted file mode 100644 index 5f61902..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/media-foundation-for-clear-dcomp/media/alpha-video-playback-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/media-foundation-for-clear-dcomp/media/alpha-video-playback-expected.png new file mode 100644 index 0000000..7fc316c --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/media-foundation-for-clear-dcomp/media/alpha-video-playback-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/media-foundation-for-clear-frameserver/media/alpha-video-playback-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/media-foundation-for-clear-frameserver/media/alpha-video-playback-expected.png new file mode 100644 index 0000000..7fc316c --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/media-foundation-for-clear-frameserver/media/alpha-video-playback-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png new file mode 100644 index 0000000..1344ecc --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png index 87ec10d..4cb0a2d 100644 --- a/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png b/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png index ae0a6ac..8204b2c2 100644 --- a/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac11/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/canvas/canvas-incremental-repaint-expected.png index e2c967a..5f61902 100644 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/canvas/canvas-incremental-repaint-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/canvas/canvas-incremental-repaint-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color-scheme/color/color-picker-appearance-expected.png new file mode 100644 index 0000000..5d03ab2a --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-click-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-click-expected.png new file mode 100644 index 0000000..9597811 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-click-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png new file mode 100644 index 0000000..2d91917 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png new file mode 100644 index 0000000..ef045b8 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-drag-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-drag-expected.png new file mode 100644 index 0000000..9597811 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-drag-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png new file mode 100644 index 0000000..68e5798 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png new file mode 100644 index 0000000..c8b2b51 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png new file mode 100644 index 0000000..7a299d1 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png new file mode 100644 index 0000000..9176a3a1 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png new file mode 100644 index 0000000..220dc263 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png new file mode 100644 index 0000000..4090cebd --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png new file mode 100644 index 0000000..66da85c --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png new file mode 100644 index 0000000..cb7b5b4 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hex-format-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hex-format-expected.png new file mode 100644 index 0000000..c8acdf4d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hex-format-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hsl-format-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hsl-format-expected.png new file mode 100644 index 0000000..86aa0df --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hsl-format-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png new file mode 100644 index 0000000..6892e25b --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png new file mode 100644 index 0000000..450d929c --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-imperfect-match-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-imperfect-match-expected.png new file mode 100644 index 0000000..ea6faa4 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-imperfect-match-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-manual-color-change-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-manual-color-change-expected.png new file mode 100644 index 0000000..3d6f2cb --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-manual-color-change-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-set-value-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-set-value-expected.png new file mode 100644 index 0000000..6027fc7 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-set-value-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png new file mode 100644 index 0000000..36fe0c2 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-value-attribute-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-value-attribute-expected.png new file mode 100644 index 0000000..92335fbd --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-appearance-value-attribute-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png new file mode 100644 index 0000000..54909a8 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/color-spin/canvas-primary-squares-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/media/alpha-video-playback-expected.png similarity index 61% copy from third_party/blink/web_tests/platform/mac/virtual/color-spin/canvas-primary-squares-expected.png copy to third_party/blink/web_tests/platform/mac-mac12-arm64/media/alpha-video-playback-expected.png index 6530304..e4d0a9d 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/color-spin/canvas-primary-squares-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/media/alpha-video-playback-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/paint/invalidation/canvas-resize-no-full-invalidation-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/paint/invalidation/canvas-resize-no-full-invalidation-expected.png new file mode 100644 index 0000000..2bfe7f7 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/paint/invalidation/canvas-resize-no-full-invalidation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png new file mode 100644 index 0000000..3d15b57 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png new file mode 100644 index 0000000..8d0f8d8 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png new file mode 100644 index 0000000..c231417 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png new file mode 100644 index 0000000..77ae8468 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png deleted file mode 100644 index 5f61902..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/gpu/fast/canvas/canvas-incremental-repaint-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/media-foundation-for-clear-dcomp/media/alpha-video-playback-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/media-foundation-for-clear-dcomp/media/alpha-video-playback-expected.png new file mode 100644 index 0000000..7fc316c --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/media-foundation-for-clear-dcomp/media/alpha-video-playback-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/media-foundation-for-clear-frameserver/media/alpha-video-playback-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/media-foundation-for-clear-frameserver/media/alpha-video-playback-expected.png new file mode 100644 index 0000000..7fc316c --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/media-foundation-for-clear-frameserver/media/alpha-video-playback-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png new file mode 100644 index 0000000..1344ecc --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12-arm64/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-hidpi-blurry-expected.png b/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-hidpi-blurry-expected.png index 92e03005..6a9b251 100644 --- a/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-hidpi-blurry-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-hidpi-blurry-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-incremental-repaint-expected.png index abf0b0d..aef4be0 100644 --- a/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-incremental-repaint-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-incremental-repaint-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png b/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png index 761864c..ad7239b 100644 --- a/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-toDataURL-webp-expected.png b/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-toDataURL-webp-expected.png deleted file mode 100644 index 904c452..0000000 --- a/third_party/blink/web_tests/platform/mac/fast/canvas/canvas-toDataURL-webp-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/canvas/pixelated-expected.png b/third_party/blink/web_tests/platform/mac/fast/canvas/pixelated-expected.png deleted file mode 100644 index b75d52bc..0000000 --- a/third_party/blink/web_tests/platform/mac/fast/canvas/pixelated-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/color/color-picker-appearance-expected.png index 9e2444f..577c247 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-click-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-click-expected.png index 5210665..6770f89 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-click-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-click-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png index 73668a6..9af4d8d 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png index 13b9281..0d159ed 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-down-keyboard-navigation-from-top-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-drag-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-drag-expected.png index 5210665..6770f89 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-drag-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-drag-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png index ee3fa6f0..c824cba 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-keyboard-navigation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png index c1d9b25b..bf48c62d 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-bottom-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png index 5bc891c..6744078 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-left-keyboard-navigation-from-top-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png index 867acb27..ba54ccd 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-bottom-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png index 4e5b644..16af243d 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-right-keyboard-navigation-from-top-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png index 6e61b30..02ae9d4 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-touch-drag-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png index 23fe32a..f863fcd 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-left-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png index f1e886ee..db826b4 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-color-well-up-keyboard-navigation-from-bottom-right-corner-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hex-format-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hex-format-expected.png index 0368d30d..2f59f7f 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hex-format-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hex-format-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hsl-format-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hsl-format-expected.png index c621520..574a796 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hsl-format-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hsl-format-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-accelerated-keyboard-navigation-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-accelerated-keyboard-navigation-expected.png index dd4d416..4de189f 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-accelerated-keyboard-navigation-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-accelerated-keyboard-navigation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-click-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-click-expected.png index aa13f9c..42f81d5a 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-click-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-click-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-drag-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-drag-expected.png index aa13f9c..42f81d5a 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-drag-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-drag-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-keyboard-navigation-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-keyboard-navigation-expected.png index 4dd743b..3189d77 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-keyboard-navigation-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-keyboard-navigation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png index 0476678..f75fe963 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-left-edge-zero-hue-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png index 2a1980a..a2bc636 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-right-edge-zero-hue-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-touch-drag-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-touch-drag-expected.png index a5c05a8..8d82275 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-touch-drag-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-hue-slider-touch-drag-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-imperfect-match-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-imperfect-match-expected.png index a095fc9..f65ba0d 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-imperfect-match-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-imperfect-match-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-manual-color-change-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-manual-color-change-expected.png index 63d3411..dec5aeb 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-manual-color-change-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-manual-color-change-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-set-value-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-set-value-expected.png index 0c84723..9e27acf 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-set-value-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-set-value-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png index 114e9dc..777f415b 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-tap-hex-format-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-value-attribute-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-value-attribute-expected.png index ecf3bcc5..f400434 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-value-attribute-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-value-attribute-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom125-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom125-expected.png index 14efaf2..5bb2acd0 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom125-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom125-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom200-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom200-expected.png index 46cf7c2..900f5a7 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom200-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-appearance-zoom200-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png index 0ad74dc..a434e66 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/color/color-picker-top-left-selection-position-after-reopen-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/replaced/border-radius-clip-content-edge-expected.png b/third_party/blink/web_tests/platform/mac/fast/replaced/border-radius-clip-content-edge-expected.png index ef8cc96..50044ee 100644 --- a/third_party/blink/web_tests/platform/mac/fast/replaced/border-radius-clip-content-edge-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/replaced/border-radius-clip-content-edge-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/inspector-protocol/overlay/overlay-with-emulation-scale-expected.txt b/third_party/blink/web_tests/platform/mac/inspector-protocol/overlay/overlay-with-emulation-scale-expected.txt deleted file mode 100644 index f546a917..0000000 --- a/third_party/blink/web_tests/platform/mac/inspector-protocol/overlay/overlay-with-emulation-scale-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -Verifies that overlay is correctly rendered with emulation scale > 1. -The test passes if the image URL below is 300x600 image containing a 270x420 brown rectangle, without any green or red. -data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAJYCAYAAADYJts/AAAAAXNSR0IArs4c6QAAB9JJREFUeJzt20EKhEAMAMGdxf9/OT5BBUVaqu6BnJpcsmZmfgAB/7cXADhLsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjK2yxNrPbAG8Gk3vSy7sIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8jYLk/MPLAGwDEXFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARk7HLgMrk9KayMAAAAASUVORK5CYII= -
diff --git a/third_party/blink/web_tests/platform/mac/media/alpha-video-playback-expected.png b/third_party/blink/web_tests/platform/mac/media/alpha-video-playback-expected.png index e4d0a9d..5f0004e 100644 --- a/third_party/blink/web_tests/platform/mac/media/alpha-video-playback-expected.png +++ b/third_party/blink/web_tests/platform/mac/media/alpha-video-playback-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-putImageData-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-putImageData-expected.txt deleted file mode 100644 index 9051839..0000000 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-putImageData-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -{ - "layers": [ - { - "name": "Scrolling background of LayoutNGView #document", - "bounds": [800, 600], - "contentsOpaque": true, - "backgroundColor": "#FFFFFF" - }, - { - "name": "LayoutHTMLCanvas CANVAS id='canvas'", - "position": [8, 8], - "bounds": [100, 100] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-expected.txt deleted file mode 100644 index dce35520..0000000 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -{ - "layers": [ - { - "name": "Scrolling background of LayoutNGView #document", - "bounds": [800, 600], - "contentsOpaque": true, - "backgroundColor": "#FFFFFF" - }, - { - "name": "LayoutHTMLCanvas (positioned) CANVAS id='canvas'", - "position": [50, 50], - "bounds": [500, 500] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-no-full-invalidation-expected.png b/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-no-full-invalidation-expected.png index 2bfe7f7..4359ac3 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-no-full-invalidation-expected.png +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-no-full-invalidation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-no-full-invalidation-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-no-full-invalidation-expected.txt deleted file mode 100644 index dbfdd46..0000000 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/canvas-resize-no-full-invalidation-expected.txt +++ /dev/null
@@ -1,20 +0,0 @@ -{ - "layers": [ - { - "name": "Scrolling background of LayoutNGView #document", - "bounds": [800, 600], - "contentsOpaque": true, - "backgroundColor": "#FFFFFF", - "invalidations": [ - [50, 50, 600, 500] - ] - }, - { - "name": "LayoutHTMLCanvas (positioned) CANVAS id='canvas'", - "position": [50, 50], - "bounds": [500, 500], - "backgroundColor": "#003300" - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt index f5ec0f3..5598dfc 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt
@@ -1,235 +1,56 @@ { "layers": [ { - "name": "Scrolling background of LayoutNGView #document", + "name": "Scrolling background of LayoutView #document", "bounds": [785, 928], "contentsOpaque": true, - "backgroundColor": "#FFFFFF" - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-oversolid color'", - "position": [145, 63], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-overimage'", - "position": [287, 63], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-overcanvas'", - "position": [429, 63], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-overvideo'", - "position": [571, 63], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-insolid color'", - "position": [145, 113], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-inimage'", - "position": [287, 113], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-incanvas'", - "position": [429, 113], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-invideo'", - "position": [571, 113], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-outsolid color'", - "position": [145, 163], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-outimage'", - "position": [287, 163], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-outcanvas'", - "position": [429, 163], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-outvideo'", - "position": [571, 163], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-atopsolid color'", - "position": [145, 213], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-atopimage'", - "position": [287, 213], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-atopcanvas'", - "position": [429, 213], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-atopvideo'", - "position": [571, 213], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-oversolid color'", - "position": [145, 263], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-overimage'", - "position": [287, 263], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-overcanvas'", - "position": [429, 263], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-overvideo'", - "position": [571, 263], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-insolid color'", - "position": [145, 313], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-inimage'", - "position": [287, 313], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-incanvas'", - "position": [429, 313], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-invideo'", - "position": [571, 313], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-outsolid color'", - "position": [145, 363], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-outimage'", - "position": [287, 363], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-outcanvas'", - "position": [429, 363], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-outvideo'", - "position": [571, 363], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-atopsolid color'", - "position": [145, 413], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-atopimage'", - "position": [287, 413], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-atopcanvas'", - "position": [429, 413], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='destination-atopvideo'", - "position": [571, 413], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='lightersolid color'", - "position": [145, 463], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='lighterimage'", - "position": [287, 463], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='lightercanvas'", - "position": [429, 463], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='lightervideo'", - "position": [571, 463], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='copysolid color'", - "position": [145, 513], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='copyimage'", - "position": [287, 513], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='copycanvas'", - "position": [429, 513], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='copyvideo'", - "position": [571, 513], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='xorsolid color'", - "position": [145, 563], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='xorimage'", - "position": [287, 563], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='xorcanvas'", - "position": [429, 563], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='xorvideo'", - "position": [571, 563], - "bounds": [130, 40] - }, - { - "name": "LayoutHTMLCanvas CANVAS id='source-canvas'", - "position": [16, 751], - "bounds": [150, 60] + "backgroundColor": "#FFFFFF", + "invalidations": [ + [569, 562, 133, 42], + [569, 512, 133, 42], + [569, 462, 133, 42], + [569, 412, 133, 42], + [569, 362, 133, 42], + [569, 312, 133, 42], + [569, 262, 133, 42], + [569, 212, 133, 42], + [569, 162, 133, 42], + [569, 112, 133, 42], + [569, 62, 133, 42], + [427, 562, 133, 42], + [427, 512, 133, 42], + [427, 462, 133, 42], + [427, 412, 133, 42], + [427, 362, 133, 42], + [427, 312, 133, 42], + [427, 262, 133, 42], + [427, 212, 133, 42], + [427, 162, 133, 42], + [427, 112, 133, 42], + [427, 62, 133, 42], + [285, 562, 133, 42], + [285, 512, 133, 42], + [285, 462, 133, 42], + [285, 412, 133, 42], + [285, 362, 133, 42], + [285, 312, 133, 42], + [285, 262, 133, 42], + [285, 212, 133, 42], + [285, 162, 133, 42], + [285, 112, 133, 42], + [285, 62, 133, 42], + [143, 562, 133, 42], + [143, 512, 133, 42], + [143, 462, 133, 42], + [143, 412, 133, 42], + [143, 362, 133, 42], + [143, 312, 133, 42], + [143, 262, 133, 42], + [143, 212, 133, 42], + [143, 162, 133, 42], + [143, 112, 133, 42], + [143, 62, 133, 42] + ] }, { "name": "LayoutVideo VIDEO id='video'",
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png index 9b27031..e53a7e8 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-hc/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png index da2f7b8c..4eb24ef 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/dark-color-scheme/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png index 91c1688..fb5bce8 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png index e0d5c881..932e2c9 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png index 3126f45..8615a13 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png index 9bad6262..10c466a 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/paint-subrect-grid-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/paint-subrect-grid-expected.png deleted file mode 100644 index f55c833..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/paint-subrect-grid-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/pixelated-canvas-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/pixelated-canvas-expected.png deleted file mode 100644 index 1021936..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/pixelated-canvas-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/media-foundation-for-clear-dcomp/media/alpha-video-playback-expected.png b/third_party/blink/web_tests/platform/mac/virtual/media-foundation-for-clear-dcomp/media/alpha-video-playback-expected.png deleted file mode 100644 index e2872f31..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/media-foundation-for-clear-dcomp/media/alpha-video-playback-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/media-foundation-for-clear-frameserver/media/alpha-video-playback-expected.png b/third_party/blink/web_tests/platform/mac/virtual/media-foundation-for-clear-frameserver/media/alpha-video-playback-expected.png deleted file mode 100644 index e2872f31..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/media-foundation-for-clear-frameserver/media/alpha-video-playback-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/no-alloc-direct-call/fast/canvas/canvas-hidpi-blurry-expected.png b/third_party/blink/web_tests/platform/mac/virtual/no-alloc-direct-call/fast/canvas/canvas-hidpi-blurry-expected.png deleted file mode 100644 index 6a9b251..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/no-alloc-direct-call/fast/canvas/canvas-hidpi-blurry-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/no-alloc-direct-call/fast/canvas/canvas-incremental-repaint-expected.png b/third_party/blink/web_tests/platform/mac/virtual/no-alloc-direct-call/fast/canvas/canvas-incremental-repaint-expected.png deleted file mode 100644 index f0252fb..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/no-alloc-direct-call/fast/canvas/canvas-incremental-repaint-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/no-alloc-direct-call/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png b/third_party/blink/web_tests/platform/mac/virtual/no-alloc-direct-call/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png deleted file mode 100644 index ad7239b..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/no-alloc-direct-call/fast/canvas/canvas-toDataURL-jpeg-maximum-quality-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png index c0ced16..fa3bcbc 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png b/third_party/blink/web_tests/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png similarity index 100% rename from third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png rename to third_party/blink/web_tests/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/optimize-contrast-canvas-expected.png b/third_party/blink/web_tests/virtual/exotic-color-space/images/optimize-contrast-canvas-expected.png similarity index 100% rename from third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/optimize-contrast-canvas-expected.png rename to third_party/blink/web_tests/virtual/exotic-color-space/images/optimize-contrast-canvas-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/paint-subrect-expected.png b/third_party/blink/web_tests/virtual/exotic-color-space/images/paint-subrect-expected.png similarity index 100% rename from third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/paint-subrect-expected.png rename to third_party/blink/web_tests/virtual/exotic-color-space/images/paint-subrect-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/js-resizable-arraybuffer/README.md b/third_party/blink/web_tests/virtual/js-resizable-arraybuffer/README.md new file mode 100644 index 0000000..3eaae58 --- /dev/null +++ b/third_party/blink/web_tests/virtual/js-resizable-arraybuffer/README.md
@@ -0,0 +1 @@ +This virtual test suite will be removed once resizable ArrayBuffers ship in V8.
diff --git a/third_party/libaddressinput/README.chromium b/third_party/libaddressinput/README.chromium index 4afd47c..d130f28b 100644 --- a/third_party/libaddressinput/README.chromium +++ b/third_party/libaddressinput/README.chromium
@@ -1,8 +1,7 @@ Name: libaddressinput URL: https://github.com/google/libaddressinput -Version: 0 -Date: 16 May 2022 -Revision: 64bff363610097d3a44d0fe19912b53460e2ab78 +Version: e8712e415627f22d0b00ebee8db99547077f39bd +Date: 2022-12-22 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index b80e239e..477ec05 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -32319,6 +32319,7 @@ <int value="1049" label="PrivacySandboxAdTopicsEnabled"/> <int value="1050" label="PrivacySandboxSiteEnabledAdsEnabled"/> <int value="1051" label="PrivacySandboxAdMeasurementEnabled"/> + <int value="1052" label="AppStoreRatingEnabled"/> </enum> <enum name="EnterprisePoliciesSources"> @@ -36829,6 +36830,26 @@ <int value="68" label="SRSXB33_1"/> <int value="69" label="SRSXB33_2"/> <int value="70" label="SRSXB33_3"/> + <int value="71" label="BoatRockerz255Pro"/> + <int value="72" label="BoseQuietComfort35II"/> + <int value="73" label="BoseQuietComfort35II_1"/> + <int value="74" label="JBLTUNE230NCTWS"/> + <int value="75" label="JBLTUNE230NCTWS_1"/> + <int value="76" label="JBLTUNE230NCTWS_2"/> + <int value="77" label="JBLTUNE230NCTWS_3"/> + <int value="78" label="OnePlusBuds"/> + <int value="79" label="OnePlusBuds_1"/> + <int value="80" label="OnePlusBuds_2"/> + <int value="81" label="RealMeBudsQ2TWS"/> + <int value="82" label="RealMeTechLifeBudsT100"/> + <int value="83" label="RealMeTechLifeBudsT100_1"/> + <int value="84" label="RealMeTechLifeBudsT100_2"/> + <int value="85" label="SRSXB13"/> + <int value="86" label="SRSXB13_1"/> + <int value="87" label="SRSXB13_2"/> + <int value="88" label="SRSXB13_3"/> + <int value="89" label="SRSXB13_4"/> + <int value="90" label="SRSXB13_5"/> </enum> <enum name="FastPairVersion"> @@ -57465,6 +57486,7 @@ label="WalletRequiresFirstSyncSetupComplete:disabled"/> <int value="-1921593903" label="ImeInputLogicHmm:disabled"/> <int value="-1920912991" label="PermissionChip:disabled"/> + <int value="-1920869766" label="OobeJelly:disabled"/> <int value="-1920349954" label="FontManagerEarlyInit:disabled"/> <int value="-1920177029" label="FeedVideoInlinePlayback:enabled"/> <int value="-1920004248" label="FeedBackToTop:disabled"/> @@ -61508,6 +61530,7 @@ label="AutofillSendExperimentIdsInPaymentsRPCs:disabled"/> <int value="418769094" label="MixedContentSiteSetting:enabled"/> <int value="420160748" label="CornerShortcuts:enabled"/> + <int value="420356964" label="OobeJelly:enabled"/> <int value="420682005" label="AdaptiveButtonInTopToolbar:enabled"/> <int value="421986951" label="UseRealColorSpaceForAndroidVideo:disabled"/> <int value="422307097" label="PhysicalWeb:disabled"/> @@ -61550,7 +61573,6 @@ <int value="453017472" label="IntentBlockExternalFormRedirectsNoGesture:disabled"/> <int value="453102772" label="OfflinePagesLoadSignalCollecting:disabled"/> - <int value="453308897" label="OobeMaterialNext:enabled"/> <int value="453427119" label="EcheSWADisableStunServer:enabled"/> <int value="453601558" label="SupportToolScreenshot:enabled"/> <int value="454106312" label="UsernameFirstFlowFilling:enabled"/> @@ -61559,7 +61581,6 @@ label="disable-gesture-requirement-for-media-playback"/> <int value="455754036" label="MirroringService:disabled"/> <int value="457301531" label="SiteIsolationForGuests:disabled"/> - <int value="457686085" label="OobeMaterialNext:disabled"/> <int value="457881889" label="enable-autoplay-muted-videos"/> <int value="458410433" label="disable-views-rect-based-targeting"/> <int value="460136092" label="MidiManagerAndroid:disabled"/>
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml index 8437818..c440415 100644 --- a/tools/metrics/histograms/metadata/android/histograms.xml +++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -4769,7 +4769,7 @@ <histogram name="Android.WebView.Startup.NonblockingServiceConnectionDelay.{ServiceName}" - units="ms" expires_after="2023-02-01"> + units="ms" expires_after="2023-09-01"> <owner>hazems@chromium.org</owner> <owner>src/android_webview/OWNERS</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/bluetooth/histograms.xml b/tools/metrics/histograms/metadata/bluetooth/histograms.xml index 422567cd8..24cd244 100644 --- a/tools/metrics/histograms/metadata/bluetooth/histograms.xml +++ b/tools/metrics/histograms/metadata/bluetooth/histograms.xml
@@ -203,6 +203,9 @@ summary="subsequent pairing protocol"/> </token> <token key="FastPairTrackedModelID"> + <variant name="BoatRockerz255Pro"/> + <variant name="BoseQuietComfort35II"/> + <variant name="BoseQuietComfort35II_1"/> <variant name="JBLLIVE300TWS"/> <variant name="JBLLIVE300TWS_1"/> <variant name="JBLLIVE300TWS_2"/> @@ -234,8 +237,15 @@ <variant name="JBLTUNE225TWS_3"/> <variant name="JBLTUNE225TWS_4"/> <variant name="JBLTUNE225TWS_5"/> + <variant name="JBLTUNE230NCTWS_1"/> + <variant name="JBLTUNE230NCTWS_2"/> + <variant name="JBLTUNE230NCTWS_3"/> + <variant name="JBLTUNE230NCTWS_4"/> <variant name="NothingEar1"/> <variant name="NothingEar1_2"/> + <variant name="OnePlusBuds"/> + <variant name="OnePlusBuds_1"/> + <variant name="OnePlusBuds_2"/> <variant name="OnePlusBudsZ"/> <variant name="OnePlusBudsZ_1"/> <variant name="OnePlusBudsZ_2"/> @@ -255,6 +265,10 @@ <variant name="RealMeBudsAirPro"/> <variant name="RealMeBudsAirPro_1"/> <variant name="RealMeBudsAirPro_2"/> + <variant name="RealMeBudsQ2TWS"/> + <variant name="RealMeTechLifeBudsT100"/> + <variant name="RealMeTechLifeBudsT100_1"/> + <variant name="RealMeTechLifeBudsT100_2"/> <variant name="SonyWF1000XM3"/> <variant name="SonyWF1000XM3_1"/> <variant name="SonyWF1000XM3_2"/> @@ -265,6 +279,12 @@ <variant name="SonyWF1000XM3_7"/> <variant name="SonyWH1000XM3"/> <variant name="SonyWH1000XM3_1"/> + <variant name="SRSXB13"/> + <variant name="SRSXB13_1"/> + <variant name="SRSXB13_2"/> + <variant name="SRSXB13_3"/> + <variant name="SRSXB13_4"/> + <variant name="SRSXB13_5"/> <variant name="SRSXB23"/> <variant name="SRSXB23_1"/> <variant name="SRSXB23_2"/> @@ -452,6 +472,9 @@ summary="subsequent pairing protocol"/> </token> <token key="FastPairTrackedModelID"> + <variant name="BoatRockerz255Pro"/> + <variant name="BoseQuietComfort35II"/> + <variant name="BoseQuietComfort35II_1"/> <variant name="JBLLIVE300TWS"/> <variant name="JBLLIVE300TWS_1"/> <variant name="JBLLIVE300TWS_2"/> @@ -483,8 +506,15 @@ <variant name="JBLTUNE225TWS_3"/> <variant name="JBLTUNE225TWS_4"/> <variant name="JBLTUNE225TWS_5"/> + <variant name="JBLTUNE230NCTWS_1"/> + <variant name="JBLTUNE230NCTWS_2"/> + <variant name="JBLTUNE230NCTWS_3"/> + <variant name="JBLTUNE230NCTWS_4"/> <variant name="NothingEar1"/> <variant name="NothingEar1_2"/> + <variant name="OnePlusBuds"/> + <variant name="OnePlusBuds_1"/> + <variant name="OnePlusBuds_2"/> <variant name="OnePlusBudsZ"/> <variant name="OnePlusBudsZ_1"/> <variant name="OnePlusBudsZ_2"/> @@ -504,6 +534,10 @@ <variant name="RealMeBudsAirPro"/> <variant name="RealMeBudsAirPro_1"/> <variant name="RealMeBudsAirPro_2"/> + <variant name="RealMeBudsQ2TWS"/> + <variant name="RealMeTechLifeBudsT100"/> + <variant name="RealMeTechLifeBudsT100_1"/> + <variant name="RealMeTechLifeBudsT100_2"/> <variant name="SonyWF1000XM3"/> <variant name="SonyWF1000XM3_1"/> <variant name="SonyWF1000XM3_2"/> @@ -514,6 +548,12 @@ <variant name="SonyWF1000XM3_7"/> <variant name="SonyWH1000XM3"/> <variant name="SonyWH1000XM3_1"/> + <variant name="SRSXB13"/> + <variant name="SRSXB13_1"/> + <variant name="SRSXB13_2"/> + <variant name="SRSXB13_3"/> + <variant name="SRSXB13_4"/> + <variant name="SRSXB13_5"/> <variant name="SRSXB23"/> <variant name="SRSXB23_1"/> <variant name="SRSXB23_2"/> @@ -1162,6 +1202,9 @@ UI, and when the learn more button is pressed on the associate account UI. </summary> <token key="FastPairTrackedModelID"> + <variant name="BoatRockerz255Pro"/> + <variant name="BoseQuietComfort35II"/> + <variant name="BoseQuietComfort35II_1"/> <variant name="JBLLIVE300TWS"/> <variant name="JBLLIVE300TWS_1"/> <variant name="JBLLIVE300TWS_2"/> @@ -1193,8 +1236,15 @@ <variant name="JBLTUNE225TWS_3"/> <variant name="JBLTUNE225TWS_4"/> <variant name="JBLTUNE225TWS_5"/> + <variant name="JBLTUNE230NCTWS_1"/> + <variant name="JBLTUNE230NCTWS_2"/> + <variant name="JBLTUNE230NCTWS_3"/> + <variant name="JBLTUNE230NCTWS_4"/> <variant name="NothingEar1"/> <variant name="NothingEar1_2"/> + <variant name="OnePlusBuds"/> + <variant name="OnePlusBuds_1"/> + <variant name="OnePlusBuds_2"/> <variant name="OnePlusBudsZ"/> <variant name="OnePlusBudsZ_1"/> <variant name="OnePlusBudsZ_2"/> @@ -1214,6 +1264,10 @@ <variant name="RealMeBudsAirPro"/> <variant name="RealMeBudsAirPro_1"/> <variant name="RealMeBudsAirPro_2"/> + <variant name="RealMeBudsQ2TWS"/> + <variant name="RealMeTechLifeBudsT100"/> + <variant name="RealMeTechLifeBudsT100_1"/> + <variant name="RealMeTechLifeBudsT100_2"/> <variant name="SonyWF1000XM3"/> <variant name="SonyWF1000XM3_1"/> <variant name="SonyWF1000XM3_2"/> @@ -1224,6 +1278,12 @@ <variant name="SonyWF1000XM3_7"/> <variant name="SonyWH1000XM3"/> <variant name="SonyWH1000XM3_1"/> + <variant name="SRSXB13"/> + <variant name="SRSXB13_1"/> + <variant name="SRSXB13_2"/> + <variant name="SRSXB13_3"/> + <variant name="SRSXB13_4"/> + <variant name="SRSXB13_5"/> <variant name="SRSXB23"/> <variant name="SRSXB23_1"/> <variant name="SRSXB23_2"/>
diff --git a/tools/metrics/histograms/metadata/extensions/histograms.xml b/tools/metrics/histograms/metadata/extensions/histograms.xml index f0f864b..fa5dfb3 100644 --- a/tools/metrics/histograms/metadata/extensions/histograms.xml +++ b/tools/metrics/histograms/metadata/extensions/histograms.xml
@@ -2931,7 +2931,7 @@ <histogram name="Extensions.SettingsOverridden.BackToGoogleNtpOverriddenDialogResult" - enum="SettingsOverriddenDialogResult" expires_after="2022-10-04"> + enum="SettingsOverriddenDialogResult" expires_after="2023-12-15"> <owner>rdevlin.cronin@chromium.org</owner> <owner>extensions-core@chromium.org</owner> <summary> @@ -2945,7 +2945,7 @@ <histogram name="Extensions.SettingsOverridden.BackToGoogleSearchOverriddenDialogResult" - enum="SettingsOverriddenDialogResult" expires_after="2022-12-04"> + enum="SettingsOverriddenDialogResult" expires_after="2023-12-15"> <owner>rdevlin.cronin@chromium.org</owner> <owner>extensions-core@chromium.org</owner> <summary> @@ -2959,7 +2959,7 @@ <histogram name="Extensions.SettingsOverridden.BackToOtherSearchOverriddenDialogResult" - enum="SettingsOverriddenDialogResult" expires_after="2023-01-01"> + enum="SettingsOverriddenDialogResult" expires_after="2023-12-15"> <owner>rdevlin.cronin@chromium.org</owner> <owner>extensions-core@chromium.org</owner> <summary> @@ -2973,7 +2973,7 @@ <histogram name="Extensions.SettingsOverridden.GenericNtpOverriddenDialogResult" - enum="SettingsOverriddenDialogResult" expires_after="2022-10-04"> + enum="SettingsOverriddenDialogResult" expires_after="2023-12-15"> <owner>rdevlin.cronin@chromium.org</owner> <owner>extensions-core@chromium.org</owner> <summary> @@ -2986,7 +2986,7 @@ <histogram name="Extensions.SettingsOverridden.GenericSearchOverriddenDialogResult" - enum="SettingsOverriddenDialogResult" expires_after="2022-12-11"> + enum="SettingsOverriddenDialogResult" expires_after="2023-12-15"> <owner>rdevlin.cronin@chromium.org</owner> <owner>extensions-core@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/network/histograms.xml b/tools/metrics/histograms/metadata/network/histograms.xml index 84b989d..b5679d1 100644 --- a/tools/metrics/histograms/metadata/network/histograms.xml +++ b/tools/metrics/histograms/metadata/network/histograms.xml
@@ -96,6 +96,57 @@ </summary> </histogram> +<histogram name="Network.Ash.Cellular.Apn.DisableCustomApn.ApnTypes" + enum="ApnTypes" expires_after="2023-10-18"> + <owner>gordonseto@google.com</owner> + <owner>cros-connectivity@google.com</owner> + <summary> + Records the APN types of an APN before modification. This is emitted each + time a user disables a custom APN. + </summary> +</histogram> + +<histogram name="Network.Ash.Cellular.Apn.DisableCustomApn.Result" + enum="BooleanSuccess" expires_after="2023-10-18"> + <owner>gordonseto@google.com</owner> + <owner>cros-connectivity@google.com</owner> + <summary>Records the result of an attempt to disable a custom APN.</summary> +</histogram> + +<histogram name="Network.Ash.Cellular.Apn.EnableCustomApn.ApnTypes" + enum="ApnTypes" expires_after="2023-10-18"> + <owner>gordonseto@google.com</owner> + <owner>cros-connectivity@google.com</owner> + <summary> + Records the APN types of an APN before modification. This is emitted each + time a user enable a custom APN. + </summary> +</histogram> + +<histogram name="Network.Ash.Cellular.Apn.EnableCustomApn.Result" + enum="BooleanSuccess" expires_after="2023-10-18"> + <owner>gordonseto@google.com</owner> + <owner>cros-connectivity@google.com</owner> + <summary>Records the result of an attempt to enable a custom APN.</summary> +</histogram> + +<histogram name="Network.Ash.Cellular.Apn.ModifyCustomApn.ApnTypes" + enum="ApnTypes" expires_after="2023-10-18"> + <owner>gordonseto@google.com</owner> + <owner>cros-connectivity@google.com</owner> + <summary> + Records the APN types of an APN before modification. This is emitted each + time a user modifies a custom APN. + </summary> +</histogram> + +<histogram name="Network.Ash.Cellular.Apn.ModifyCustomApn.Result" + enum="BooleanSuccess" expires_after="2023-10-18"> + <owner>gordonseto@google.com</owner> + <owner>cros-connectivity@google.com</owner> + <summary>Records the result of an attempt to modify a custom APN.</summary> +</histogram> + <histogram name="Network.Ash.Cellular.Apn.RemoveCustomApn.ApnTypes" enum="ApnTypes" expires_after="2023-10-18"> <owner>gordonseto@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/startup/histograms.xml b/tools/metrics/histograms/metadata/startup/histograms.xml index 5955d0a..9e61695 100644 --- a/tools/metrics/histograms/metadata/startup/histograms.xml +++ b/tools/metrics/histograms/metadata/startup/histograms.xml
@@ -117,6 +117,21 @@ </summary> </histogram> +<histogram name="Startup.Android.Cold.TimeToFirstNavigationCommit2.Tabbed" + units="ms" expires_after="2023-06-04"> + <owner>pasko@chromium.org</owner> + <owner>agrieve@chromium.org</owner> + <summary> + Experimental. Same as + Startup.Android.Cold.TimeToFirstNavigationCommit.Tabbed with two + modifications. + + The first difference is to record navigation commits happening before + post-native initialization. The second modifications is not to record + samples when FRE is shown. + </summary> +</histogram> + <histogram name="Startup.Android.Cold.TimeToFirstVisibleContent" units="ms" expires_after="never"> <!-- expires-never: guiding metric (internal: go/chrome-browser-guiding-metrics) -->
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index f86fa4a..396de62 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@ "full_remote_path": "perfetto-luci-artifacts/v31.0/linux-arm64/trace_processor_shell" }, "win": { - "hash": "1afc434b55f61464bb6572c6debaf5097c10c819", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/1cb29c1d2443c26ce562ad4fac05ed6c365b97dc/trace_processor_shell.exe" + "hash": "0befcfb83f92421c85513c0d86328dd1fbffd5ba", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/b177a9b77d364faf675687204c9e48b8fd4d813c/trace_processor_shell.exe" }, "linux_arm": { "hash": "6373f26144aad58f230d11d6a91efda5a09c9873", "full_remote_path": "perfetto-luci-artifacts/v31.0/linux-arm/trace_processor_shell" }, "mac": { - "hash": "d9e9df1c54ec0b0fa8946662398887877977d57e", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/1cb29c1d2443c26ce562ad4fac05ed6c365b97dc/trace_processor_shell" + "hash": "642e3e46788e22f52302b04aea6422f7810718e1", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/b177a9b77d364faf675687204c9e48b8fd4d813c/trace_processor_shell" }, "mac_arm64": { "hash": "5f47ee79e59d00bf3889d30ca52315522c158040", "full_remote_path": "perfetto-luci-artifacts/v31.0/mac-arm64/trace_processor_shell" }, "linux": { - "hash": "6ed855f2f81b0d2f715f4350aa44fc55c87380f7", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/1cb29c1d2443c26ce562ad4fac05ed6c365b97dc/trace_processor_shell" + "hash": "e84516277d57cf556b47707d89511acc85bd8aeb", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/b177a9b77d364faf675687204c9e48b8fd4d813c/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/ozone/common/gl_ozone_egl.cc b/ui/ozone/common/gl_ozone_egl.cc index 9b1d37e..e745dd7 100644 --- a/ui/ozone/common/gl_ozone_egl.cc +++ b/ui/ozone/common/gl_ozone_egl.cc
@@ -13,6 +13,7 @@ #include "ui/gl/gl_share_group.h" #include "ui/gl/gl_surface.h" #include "ui/gl/gl_utils.h" +#include "ui/gl/presenter.h" namespace ui {
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn index 1efbcbf..0d26515 100644 --- a/ui/ozone/platform/wayland/BUILD.gn +++ b/ui/ozone/platform/wayland/BUILD.gn
@@ -405,6 +405,8 @@ "test/mock_surface.h", "test/mock_wayland_platform_window_delegate.cc", "test/mock_wayland_platform_window_delegate.h", + "test/mock_wayland_zcr_color_manager.cc", + "test/mock_wayland_zcr_color_manager.h", "test/mock_wp_presentation.cc", "test/mock_wp_presentation.h", "test/mock_xdg_shell.cc", @@ -475,6 +477,14 @@ "test/test_viewporter.h", "test/test_wayland_server_thread.cc", "test/test_wayland_server_thread.h", + "test/test_wayland_zcr_color_management_output.cc", + "test/test_wayland_zcr_color_management_output.h", + "test/test_wayland_zcr_color_management_surface.cc", + "test/test_wayland_zcr_color_management_surface.h", + "test/test_wayland_zcr_color_space.cc", + "test/test_wayland_zcr_color_space.h", + "test/test_wayland_zcr_color_space_creator.cc", + "test/test_wayland_zcr_color_space_creator.h", "test/test_wp_pointer_gestures.cc", "test/test_wp_pointer_gestures.h", "test/test_xdg_popup.cc", @@ -514,6 +524,7 @@ deps = [ ":wayland", "//base:base", + "//ui/base/wayland:color_manager_util", "//ui/base/wayland:wayland_display_util", "//ui/ozone:platform", "//ui/ozone:test_support", @@ -569,6 +580,7 @@ "host/wayland_window_unittest.cc", "host/wayland_zaura_output_unittest.cc", "host/wayland_zaura_shell_unittest.cc", + "host/wayland_zcr_color_manager_unittest.cc", "host/wayland_zwp_pointer_gestures_unittest.cc", "host/zwp_text_input_wrapper_v1_unittest.cc", "test/wayland_drag_drop_test.cc",
diff --git a/ui/ozone/platform/wayland/host/wayland_zcr_color_manager_unittest.cc b/ui/ozone/platform/wayland/host/wayland_zcr_color_manager_unittest.cc new file mode 100644 index 0000000..1c9f810 --- /dev/null +++ b/ui/ozone/platform/wayland/host/wayland_zcr_color_manager_unittest.cc
@@ -0,0 +1,199 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <chrome-color-management-client-protocol.h> + +#include "base/check.h" +#include "base/files/file_util.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/display/test/test_screen.h" +#include "ui/gfx/color_space.h" +#include "ui/ozone/platform/wayland/common/wayland_object.h" +#include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h" +#include "ui/ozone/platform/wayland/host/wayland_connection.h" +#include "ui/ozone/platform/wayland/host/wayland_output.h" +#include "ui/ozone/platform/wayland/host/wayland_output_manager.h" +#include "ui/ozone/platform/wayland/host/wayland_zcr_color_management_output.h" +#include "ui/ozone/platform/wayland/host/wayland_zcr_color_manager.h" +#include "ui/ozone/platform/wayland/host/wayland_zcr_color_space.h" +#include "ui/ozone/platform/wayland/test/mock_surface.h" +#include "ui/ozone/platform/wayland/test/mock_wayland_zcr_color_manager.h" +#include "ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_output.h" +#include "ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_surface.h" +#include "ui/ozone/platform/wayland/test/test_wayland_zcr_color_space.h" +#include "ui/ozone/platform/wayland/test/wayland_test.h" + +using ::testing::Values; + +namespace ui { +namespace { + +base::ScopedFD MakeFD() { + base::FilePath temp_path; + EXPECT_TRUE(base::CreateTemporaryFile(&temp_path)); + auto file = + base::File(temp_path, base::File::FLAG_READ | base::File::FLAG_WRITE | + base::File::FLAG_CREATE_ALWAYS); + return base::ScopedFD(file.TakePlatformFile()); +} + +class WaylandZcrColorManagerTest : public WaylandTest { + public: + WaylandZcrColorManagerTest() = default; + WaylandZcrColorManagerTest(const WaylandZcrColorManagerTest&) = delete; + WaylandZcrColorManagerTest& operator=(const WaylandZcrColorManagerTest&) = + delete; + ~WaylandZcrColorManagerTest() override = default; + + void SetUp() override { + WaylandTest::SetUp(); + ASSERT_TRUE(connection_->zcr_color_manager()); + } + + WaylandWindow* window() { return window_.get(); } +}; + +} // namespace + +TEST_P(WaylandZcrColorManagerTest, CreateColorManagementOutput) { + // Set default values for the output. + PostToServerAndWait([](wl::TestWaylandServerThread* server) { + wl::TestOutput* output = server->output(); + output->SetRect({800, 600}); + output->SetScale(1); + output->Flush(); + }); + + auto* output_manager = connection_->wayland_output_manager(); + WaylandOutput* wayland_output = output_manager->GetPrimaryOutput(); + ASSERT_TRUE(wayland_output); + EXPECT_TRUE(wayland_output->IsReady()); + + auto* color_management_output = wayland_output->color_management_output(); + ASSERT_TRUE(color_management_output); + // Set HDR10 on server output, notify color management output with event. + PostToServerAndWait([&](wl::TestWaylandServerThread* server) { + auto params_vector = + server->zcr_color_manager_v1()->color_management_outputs(); + for (auto* mock_params : params_vector) { + mock_params->SetGfxColorSpace(gfx::ColorSpace::CreateHDR10()); + zcr_color_management_output_v1_send_color_space_changed( + mock_params->resource()); + } + }); + // Allow output to respond to server event, then send color space events. + PostToServerAndWait([&](wl::TestWaylandServerThread* server) { + auto params_vector = + server->zcr_color_manager_v1()->color_management_outputs(); + for (auto* mock_params : params_vector) { + auto* zcr_color_space = mock_params->GetZcrColorSpace(); + // assert that the color space is the same as the one in output. + EXPECT_EQ(zcr_color_space->GetGfxColorSpace(), + gfx::ColorSpace::CreateHDR10()); + // send HDR10 over wayland. + zcr_color_space_v1_send_names(zcr_color_space->resource(), 5, 5, 3); + zcr_color_space_v1_send_done(zcr_color_space->resource()); + } + }); + + // Check that the received color space is equal to the one on server output. + auto* gfx_color_space = color_management_output->gfx_color_space(); + gfx_color_space->ToString(); + EXPECT_EQ(*gfx_color_space, gfx::ColorSpace::CreateHDR10()); +} + +TEST_P(WaylandZcrColorManagerTest, CreateColorManagementSurface) { + auto* surface = window_.get()->root_surface(); + PostToServerAndWait([&](wl::TestWaylandServerThread* server) { + auto params_vector = + server->zcr_color_manager_v1()->color_management_surfaces(); + for (auto* mock_params : params_vector) { + EXPECT_EQ(gfx::ColorSpace::CreateSRGB(), mock_params->GetGfxColorSpace()); + } + }); + + // Updated buffer handle needed for ApplyPendingState() to set color_space + EXPECT_TRUE(connection_->buffer_manager_host()); + auto interface_ptr = connection_->buffer_manager_host()->BindInterface(); + buffer_manager_gpu_->Initialize(std::move(interface_ptr), {}, false, true, + false, 0); + + // Setup wl_buffers. + constexpr uint32_t buffer_id = 1; + gfx::Size buffer_size(1024, 768); + auto length = 1024 * 768 * 4; + buffer_manager_gpu_->CreateShmBasedBuffer(MakeFD(), length, buffer_size, + buffer_id); + base::RunLoop().RunUntilIdle(); + + // preload color_space in color manager cache, since first call with a + // new color_space always returns null. + connection_->zcr_color_manager()->GetColorSpace( + gfx::ColorSpace::CreateHDR10()); + connection_->RoundTripQueue(); + surface->set_color_space(gfx::ColorSpace::CreateHDR10()); + surface->AttachBuffer(connection_->buffer_manager_host()->EnsureBufferHandle( + surface, buffer_id)); + surface->ApplyPendingState(); + // Assert that surface on server has correct color_space. + PostToServerAndWait([&](wl::TestWaylandServerThread* server) { + auto params_vector = + server->zcr_color_manager_v1()->color_management_surfaces(); + EXPECT_EQ(gfx::ColorSpace::CreateHDR10(), + params_vector.front()->GetGfxColorSpace()); + }); +} + +TEST_P(WaylandZcrColorManagerTest, DoNotSetInvaliColorSpace) { + auto* surface = window_.get()->root_surface(); + PostToServerAndWait([&](wl::TestWaylandServerThread* server) { + auto params_vector = + server->zcr_color_manager_v1()->color_management_surfaces(); + for (auto* mock_params : params_vector) { + EXPECT_EQ(gfx::ColorSpace::CreateSRGB(), mock_params->GetGfxColorSpace()); + } + }); + + // Updated buffer handle needed for ApplyPendingState() to set color_space + EXPECT_TRUE(connection_->buffer_manager_host()); + auto interface_ptr = connection_->buffer_manager_host()->BindInterface(); + buffer_manager_gpu_->Initialize(std::move(interface_ptr), {}, false, true, + false, 0); + + // Setup wl_buffers. + constexpr uint32_t buffer_id = 1; + gfx::Size buffer_size(1024, 768); + auto length = 1024 * 768 * 4; + buffer_manager_gpu_->CreateShmBasedBuffer(MakeFD(), length, buffer_size, + buffer_id); + base::RunLoop().RunUntilIdle(); + + gfx::ColorSpace invalid_space = + gfx::ColorSpace(gfx::ColorSpace::PrimaryID::INVALID, + gfx::ColorSpace::TransferID::INVALID); + // Attempt to set an invalid color space on the surface and expect that the + // original default color space remains unchanged on the surface. + connection_->zcr_color_manager()->GetColorSpace(invalid_space); + connection_->RoundTripQueue(); + surface->set_color_space(invalid_space); + surface->AttachBuffer(connection_->buffer_manager_host()->EnsureBufferHandle( + surface, buffer_id)); + surface->ApplyPendingState(); + // Assert that surface on server has correct color_space. + PostToServerAndWait([&](wl::TestWaylandServerThread* server) { + auto params_vector = + server->zcr_color_manager_v1()->color_management_surfaces(); + EXPECT_EQ(gfx::ColorSpace::CreateSRGB(), + params_vector.front()->GetGfxColorSpace()); + }); +} + +INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, + WaylandZcrColorManagerTest, + Values(wl::ServerConfig{})); + +} // namespace ui
diff --git a/ui/ozone/platform/wayland/test/mock_wayland_zcr_color_manager.cc b/ui/ozone/platform/wayland/test/mock_wayland_zcr_color_manager.cc new file mode 100644 index 0000000..40ad018b --- /dev/null +++ b/ui/ozone/platform/wayland/test/mock_wayland_zcr_color_manager.cc
@@ -0,0 +1,203 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/ozone/platform/wayland/test/mock_wayland_zcr_color_manager.h" + +#include <chrome-color-management-server-protocol.h> +#include <cstdint> +#include <iterator> + +#include "base/ranges/algorithm.h" +#include "ui/base/wayland/color_manager_util.h" +#include "ui/gfx/color_space.h" +#include "ui/ozone/platform/wayland/test/global_object.h" +#include "ui/ozone/platform/wayland/test/server_object.h" +#include "ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_output.h" +#include "ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_surface.h" +#include "ui/ozone/platform/wayland/test/test_wayland_zcr_color_space.h" +#include "ui/ozone/platform/wayland/test/test_wayland_zcr_color_space_creator.h" + +namespace wl { + +namespace { + +constexpr uint32_t kZcrColorManagerVersion = 1; + +void CreateColorSpaceFromIcc(wl_client* client, + wl_resource* resource, + uint32_t id, + int32_t fd) { + auto* zcr_color_manager = GetUserDataAs<MockZcrColorManagerV1>(resource); + zcr_color_manager->CreateColorSpaceFromIcc(client, resource, id, fd); +} + +void CreateColorSpaceFromNames(wl_client* client, + wl_resource* resource, + uint32_t id, + uint32_t eotf, + uint32_t chromaticity, + uint32_t whitepoint) { + wl_resource* color_space_resource = + CreateResourceWithImpl<TestZcrColorSpaceV1>( + client, &zcr_color_space_v1_interface, 1, &kTestZcrColorSpaceV1Impl, + 0); + DCHECK(color_space_resource); + auto* zcr_color_manager = GetUserDataAs<MockZcrColorManagerV1>(resource); + auto* zcr_color_space = + GetUserDataAs<TestZcrColorSpaceV1>(color_space_resource); + + auto chromaticity_id = gfx::ColorSpace::PrimaryID::INVALID; + const auto* maybe_primary = ui::wayland::kChromaticityMap.find(chromaticity); + if (maybe_primary != ui::wayland::kChromaticityMap.end()) { + chromaticity_id = maybe_primary->second; + } + auto eotf_id = gfx::ColorSpace::TransferID::INVALID; + const auto* maybe_eotf = ui::wayland::kEotfMap.find(eotf); + if (maybe_eotf != ui::wayland::kEotfMap.end()) { + eotf_id = maybe_eotf->second; + } + + zcr_color_space->SetGfxColorSpace(gfx::ColorSpace(chromaticity_id, eotf_id)); + zcr_color_space->SetZcrColorManager(zcr_color_manager); + wl_resource* creator_resource = + CreateResourceWithImpl<TestZcrColorSpaceCreatorV1>( + client, &zcr_color_space_creator_v1_interface, 1, nullptr, id); + DCHECK(creator_resource); + zcr_color_space_creator_v1_send_created(creator_resource, + color_space_resource); + + zcr_color_manager->StoreZcrColorSpace(zcr_color_space); + zcr_color_manager->CreateColorSpaceFromNames(client, resource, id, eotf, + chromaticity, whitepoint); +} + +void CreateColorSpaceFromParams(wl_client* client, + wl_resource* resource, + uint32_t id, + uint32_t eotf, + uint32_t primary_r_x, + uint32_t primary_r_y, + uint32_t primary_g_x, + uint32_t primary_g_y, + uint32_t primary_b_x, + uint32_t primary_b_y, + uint32_t whitepoint_x, + uint32_t whitepoint_y) { + wl_resource* color_space_resource = + CreateResourceWithImpl<TestZcrColorSpaceV1>( + client, &zcr_color_space_v1_interface, 1, &kTestZcrColorSpaceV1Impl, + 0); + DCHECK(color_space_resource); + auto* zcr_color_manager = GetUserDataAs<MockZcrColorManagerV1>(resource); + auto* zcr_color_space = + GetUserDataAs<TestZcrColorSpaceV1>(color_space_resource); + + zcr_color_space->SetGfxColorSpace(gfx::ColorSpace::CreateSRGB()); + zcr_color_space->SetZcrColorManager(zcr_color_manager); + wl_resource* creator_resource = + CreateResourceWithImpl<TestZcrColorSpaceCreatorV1>( + client, &zcr_color_space_creator_v1_interface, 1, nullptr, id); + DCHECK(creator_resource); + zcr_color_space_creator_v1_send_created(creator_resource, + color_space_resource); + + zcr_color_manager->StoreZcrColorSpace(zcr_color_space); + zcr_color_manager->CreateColorSpaceFromParams( + client, resource, id, eotf, primary_r_x, primary_r_y, primary_g_x, + primary_g_y, primary_b_x, primary_b_y, whitepoint_x, whitepoint_y); +} + +void GetColorManagementOutput(wl_client* client, + wl_resource* resource, + uint32_t id, + wl_resource* output) { + wl_resource* output_resource = + CreateResourceWithImpl<TestZcrColorManagementOutputV1>( + client, &zcr_color_management_output_v1_interface, 1, + &kTestZcrColorManagementOutputV1Impl, id); + DCHECK(output_resource); + auto* zcr_color_manager = GetUserDataAs<MockZcrColorManagerV1>(resource); + auto* color_manager_output = + GetUserDataAs<TestZcrColorManagementOutputV1>(output_resource); + + gfx::ColorSpace color_space; + color_manager_output->SetGfxColorSpace(color_space); + color_manager_output->StoreZcrColorManager(zcr_color_manager); + zcr_color_manager->StoreZcrColorManagementOutput(color_manager_output); + zcr_color_manager->GetColorManagementOutput(client, resource, id, output); +} + +void GetColorManagementSurface(wl_client* client, + wl_resource* resource, + uint32_t id, + wl_resource* output) { + wl_resource* surface_resource = + CreateResourceWithImpl<TestZcrColorManagementSurfaceV1>( + client, &zcr_color_management_surface_v1_interface, 1, + &kTestZcrColorManagementSurfaceV1Impl, id); + DCHECK(surface_resource); + auto* zcr_color_manager = GetUserDataAs<MockZcrColorManagerV1>(resource); + auto* color_manager_surface = + GetUserDataAs<TestZcrColorManagementSurfaceV1>(surface_resource); + + gfx::ColorSpace color_space; + color_manager_surface->SetGfxColorSpace(color_space); + color_manager_surface->StoreZcrColorManager(zcr_color_manager); + zcr_color_manager->StoreZcrColorManagementSurface(color_manager_surface); + zcr_color_manager->GetColorManagementSurface(client, resource, id, output); +} + +} // namespace + +const struct zcr_color_manager_v1_interface kMockZcrColorManagerV1Impl = { + &CreateColorSpaceFromIcc, &CreateColorSpaceFromNames, + &CreateColorSpaceFromParams, &GetColorManagementOutput, + &GetColorManagementSurface, &DestroyResource}; + +MockZcrColorManagerV1::MockZcrColorManagerV1() + : GlobalObject(&zcr_color_manager_v1_interface, + &kMockZcrColorManagerV1Impl, + kZcrColorManagerVersion) {} + +MockZcrColorManagerV1::~MockZcrColorManagerV1() { + DCHECK(color_manager_outputs_.empty()); + DCHECK(color_manager_surfaces_.empty()); +} + +void MockZcrColorManagerV1::StoreZcrColorManagementOutput( + TestZcrColorManagementOutputV1* params) { + color_manager_outputs_.push_back(params); +} + +void MockZcrColorManagerV1::StoreZcrColorManagementSurface( + TestZcrColorManagementSurfaceV1* params) { + color_manager_surfaces_.push_back(params); +} + +void MockZcrColorManagerV1::StoreZcrColorSpace(TestZcrColorSpaceV1* params) { + color_manager_color_spaces_.push_back(params); +} + +void MockZcrColorManagerV1::OnZcrColorManagementOutputDestroyed( + TestZcrColorManagementOutputV1* params) { + auto it = base::ranges::find(color_manager_outputs_, params); + DCHECK(it != color_manager_outputs_.end()); + color_manager_outputs_.erase(it); +} + +void MockZcrColorManagerV1::OnZcrColorManagementSurfaceDestroyed( + TestZcrColorManagementSurfaceV1* params) { + auto it = base::ranges::find(color_manager_surfaces_, params); + DCHECK(it != color_manager_surfaces_.end()); + color_manager_surfaces_.erase(it); +} + +void MockZcrColorManagerV1::OnZcrColorSpaceDestroyed( + TestZcrColorSpaceV1* params) { + auto it = base::ranges::find(color_manager_color_spaces_, params); + DCHECK(it != color_manager_color_spaces_.end()); + color_manager_color_spaces_.erase(it); +} + +} // namespace wl
diff --git a/ui/ozone/platform/wayland/test/mock_wayland_zcr_color_manager.h b/ui/ozone/platform/wayland/test/mock_wayland_zcr_color_manager.h new file mode 100644 index 0000000..85c9d2c --- /dev/null +++ b/ui/ozone/platform/wayland/test/mock_wayland_zcr_color_manager.h
@@ -0,0 +1,98 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_MOCK_WAYLAND_ZCR_COLOR_MANAGER_H_ +#define UI_OZONE_PLATFORM_WAYLAND_TEST_MOCK_WAYLAND_ZCR_COLOR_MANAGER_H_ + +#include <chrome-color-management-server-protocol.h> +#include <vector> + +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/ozone/platform/wayland/test/global_object.h" + +struct wl_client; +struct wl_resource; + +namespace wl { + +extern const struct zcr_color_manager_v1_interface kMockZcrColorManagerV1Impl; + +class TestZcrColorManagementOutputV1; +class TestZcrColorManagementSurfaceV1; +class TestZcrColorSpaceV1; + +// Manage zwp_linux_buffer_params_v1 +class MockZcrColorManagerV1 : public GlobalObject { + public: + MockZcrColorManagerV1(); + + MockZcrColorManagerV1(const MockZcrColorManagerV1&) = delete; + MockZcrColorManagerV1& operator=(const MockZcrColorManagerV1&) = delete; + + ~MockZcrColorManagerV1() override; + + MOCK_METHOD4( + CreateColorSpaceFromIcc, + void(wl_client* client, wl_resource* resource, uint32_t id, int32_t fd)); + MOCK_METHOD6(CreateColorSpaceFromNames, + void(wl_client* client, + wl_resource* resource, + uint32_t id, + uint32_t eotf, + uint32_t chromaticity, + uint32_t whitepoint)); + MOCK_METHOD(void, + CreateColorSpaceFromParams, + (wl_client * client, + wl_resource* resource, + uint32_t id, + uint32_t eotf, + uint32_t primary_r_x, + uint32_t primary_r_y, + uint32_t primary_g_x, + uint32_t primary_g_y, + uint32_t primary_b_x, + uint32_t primary_b_y, + uint32_t whitepoint_x, + uint32_t whitepoint_y)); + MOCK_METHOD4(GetColorManagementOutput, + void(wl_client* client, + wl_resource* resource, + uint32_t id, + wl_resource* output)); + MOCK_METHOD4(GetColorManagementSurface, + void(wl_client* client, + wl_resource* resource, + uint32_t id, + wl_resource* surface)); + MOCK_METHOD2(Destroy, void(wl_client* client, wl_resource* resource)); + + const std::vector<TestZcrColorManagementOutputV1*> color_management_outputs() + const { + return color_manager_outputs_; + } + + const std::vector<TestZcrColorManagementSurfaceV1*> + color_management_surfaces() const { + return color_manager_surfaces_; + } + void StoreZcrColorManagementOutput(TestZcrColorManagementOutputV1* params); + void StoreZcrColorManagementSurface(TestZcrColorManagementSurfaceV1* params); + void StoreZcrColorSpace(TestZcrColorSpaceV1* params); + + void OnZcrColorManagementOutputDestroyed( + TestZcrColorManagementOutputV1* params); + void OnZcrColorManagementSurfaceDestroyed( + TestZcrColorManagementSurfaceV1* params); + void OnZcrColorSpaceDestroyed(TestZcrColorSpaceV1* params); + + private: + std::vector<TestZcrColorManagementOutputV1*> color_manager_outputs_; + std::vector<TestZcrColorManagementSurfaceV1*> color_manager_surfaces_; + std::vector<TestZcrColorSpaceV1*> color_manager_color_spaces_; +}; + +} // namespace wl + +#endif // UI_OZONE_PLATFORM_WAYLAND_TEST_MOCK_WAYLAND_ZCR_COLOR_MANAGER_H_
diff --git a/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc b/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc index 100f51f..cf432c48 100644 --- a/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc +++ b/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc
@@ -144,6 +144,9 @@ return false; if (!wp_pointer_gestures_.Initialize(display_.get())) return false; + if (!zcr_color_manager_v1_.Initialize(display_.get())) { + return false; + } client_ = wl_client_create(display_.get(), server_fd.release()); if (!client_)
diff --git a/ui/ozone/platform/wayland/test/test_wayland_server_thread.h b/ui/ozone/platform/wayland/test/test_wayland_server_thread.h index 4151878..b463345 100644 --- a/ui/ozone/platform/wayland/test/test_wayland_server_thread.h +++ b/ui/ozone/platform/wayland/test/test_wayland_server_thread.h
@@ -17,6 +17,7 @@ #include "base/threading/thread_checker.h" #include "ui/display/types/display_constants.h" #include "ui/ozone/platform/wayland/test/global_object.h" +#include "ui/ozone/platform/wayland/test/mock_wayland_zcr_color_manager.h" #include "ui/ozone/platform/wayland/test/mock_wp_presentation.h" #include "ui/ozone/platform/wayland/test/mock_xdg_shell.h" #include "ui/ozone/platform/wayland/test/mock_zwp_linux_dmabuf.h" @@ -154,6 +155,10 @@ TestWpPointerGestures& wp_pointer_gestures() { return wp_pointer_gestures_; } + MockZcrColorManagerV1* zcr_color_manager_v1() { + return &zcr_color_manager_v1_; + } + void set_output_delegate(OutputDelegate* delegate) { output_delegate_ = delegate; } @@ -217,6 +222,7 @@ TestZXdgOutputManager zxdg_output_manager_; MockXdgShell xdg_shell_; TestZAuraShell zaura_shell_; + MockZcrColorManagerV1 zcr_color_manager_v1_; TestZcrStylus zcr_stylus_; TestZcrTextInputExtensionV1 zcr_text_input_extension_v1_; TestZwpTextInputManagerV1 zwp_text_input_manager_v1_;
diff --git a/ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_output.cc b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_output.cc new file mode 100644 index 0000000..8dd6ab23 --- /dev/null +++ b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_output.cc
@@ -0,0 +1,59 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_output.h" + +#include "base/notreached.h" +#include "ui/gfx/color_space.h" +#include "ui/ozone/platform/wayland/test/mock_wayland_zcr_color_manager.h" +#include "ui/ozone/platform/wayland/test/server_object.h" +#include "ui/ozone/platform/wayland/test/test_wayland_zcr_color_space.h" + +namespace wl { + +namespace { + +void GetColorSpace(wl_client* client, wl_resource* resource, uint32_t id) { + wl_resource* color_space_resource = + CreateResourceWithImpl<TestZcrColorSpaceV1>( + client, &zcr_color_space_v1_interface, 1, &kTestZcrColorSpaceV1Impl, + id); + auto* color_management_output = + GetUserDataAs<TestZcrColorManagementOutputV1>(resource); + auto* zcr_color_space = + GetUserDataAs<TestZcrColorSpaceV1>(color_space_resource); + zcr_color_space->SetGfxColorSpace( + color_management_output->GetGfxColorSpace()); + color_management_output->StoreZcrColorSpace(zcr_color_space); +} + +} // namespace + +const struct zcr_color_management_output_v1_interface + kTestZcrColorManagementOutputV1Impl = {&GetColorSpace, &DestroyResource}; + +TestZcrColorManagementOutputV1::TestZcrColorManagementOutputV1( + wl_resource* resource) + : ServerObject(resource) {} + +TestZcrColorManagementOutputV1::~TestZcrColorManagementOutputV1() { + DCHECK(zcr_color_manager_); + zcr_color_manager_->OnZcrColorManagementOutputDestroyed(this); +} + +void TestZcrColorManagementOutputV1::SetGfxColorSpace( + gfx::ColorSpace gfx_color_space) { + gfx_color_space_ = gfx_color_space; +} + +void TestZcrColorManagementOutputV1::StoreZcrColorManager( + MockZcrColorManagerV1* zcr_color_manager) { + zcr_color_manager_ = zcr_color_manager; +} + +void TestZcrColorManagementOutputV1::StoreZcrColorSpace( + TestZcrColorSpaceV1* zcr_color_space) { + zcr_color_space_ = zcr_color_space; +} +} // namespace wl \ No newline at end of file
diff --git a/ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_output.h b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_output.h new file mode 100644 index 0000000..4f92cde --- /dev/null +++ b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_output.h
@@ -0,0 +1,55 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_WAYLAND_ZCR_COLOR_MANAGEMENT_OUTPUT_H_ +#define UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_WAYLAND_ZCR_COLOR_MANAGEMENT_OUTPUT_H_ + +#include <chrome-color-management-server-protocol.h> + +#include "base/files/scoped_file.h" +#include "base/memory/raw_ptr.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/gfx/color_space.h" +#include "ui/ozone/platform/wayland/test/server_object.h" + +struct wl_client; +struct wl_resource; + +namespace wl { + +extern const struct zcr_color_management_output_v1_interface + kTestZcrColorManagementOutputV1Impl; + +class MockZcrColorManagerV1; +class TestZcrColorSpaceV1; + +class TestZcrColorManagementOutputV1 : public ServerObject { + public: + explicit TestZcrColorManagementOutputV1(wl_resource* resource); + + TestZcrColorManagementOutputV1(const TestZcrColorManagementOutputV1&) = + delete; + TestZcrColorManagementOutputV1& operator=( + const TestZcrColorManagementOutputV1&) = delete; + + ~TestZcrColorManagementOutputV1() override; + + void GetColorSpace(wl_client* client, wl_resource* resource, uint32_t id); + void Destroy(wl_client* client, wl_resource* resource); + + gfx::ColorSpace GetGfxColorSpace() const { return gfx_color_space_; } + void SetGfxColorSpace(gfx::ColorSpace gfx_color_space); + void StoreZcrColorManager(MockZcrColorManagerV1* zcr_color_manager); + TestZcrColorSpaceV1* GetZcrColorSpace() const { return zcr_color_space_; } + void StoreZcrColorSpace(TestZcrColorSpaceV1* zcr_color_space); + + private: + gfx::ColorSpace gfx_color_space_; + raw_ptr<MockZcrColorManagerV1> zcr_color_manager_ = nullptr; + raw_ptr<TestZcrColorSpaceV1> zcr_color_space_ = nullptr; +}; + +} // namespace wl + +#endif // UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_WAYLAND_ZCR_COLOR_MANAGEMENT_OUTPUT_H_
diff --git a/ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_surface.cc b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_surface.cc new file mode 100644 index 0000000..5f3baf57 --- /dev/null +++ b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_surface.cc
@@ -0,0 +1,82 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_surface.h" + +#include "base/notreached.h" +#include "ui/gfx/color_space.h" +#include "ui/ozone/platform/wayland/test/mock_wayland_zcr_color_manager.h" +#include "ui/ozone/platform/wayland/test/server_object.h" +#include "ui/ozone/platform/wayland/test/test_wayland_zcr_color_space.h" + +namespace wl { + +namespace { + +void SetAlphaMode(wl_client* client, + wl_resource* resource, + uint32_t alpha_mode) { + auto* color_management_surface = + GetUserDataAs<TestZcrColorManagementSurfaceV1>(resource); + DCHECK(color_management_surface); +} + +void SetExtendedDynamicRange(wl_client* client, + wl_resource* resource, + uint32_t value) { + auto* color_management_surface = + GetUserDataAs<TestZcrColorManagementSurfaceV1>(resource); + DCHECK(color_management_surface); +} + +void SetColorSpace(wl_client* client, + wl_resource* resource, + wl_resource* color_space_resource, + uint32_t render_intent) { + auto* color_management_surface = + GetUserDataAs<TestZcrColorManagementSurfaceV1>(resource); + DCHECK(color_space_resource); + auto* zcr_color_space = + GetUserDataAs<TestZcrColorSpaceV1>(color_space_resource); + color_management_surface->SetGfxColorSpace( + zcr_color_space->GetGfxColorSpace()); +} + +void SetDefaultColorSpace(wl_client* client, wl_resource* resource) { + auto* color_management_surface = + GetUserDataAs<TestZcrColorManagementSurfaceV1>(resource); + color_management_surface->SetGfxColorSpace(gfx::ColorSpace::CreateSRGB()); +} + +} // namespace + +const struct zcr_color_management_surface_v1_interface + kTestZcrColorManagementSurfaceV1Impl = { + &SetAlphaMode, &SetExtendedDynamicRange, &SetColorSpace, + &SetDefaultColorSpace, &DestroyResource}; + +TestZcrColorManagementSurfaceV1::TestZcrColorManagementSurfaceV1( + wl_resource* resource) + : ServerObject(resource) {} + +TestZcrColorManagementSurfaceV1::~TestZcrColorManagementSurfaceV1() { + DCHECK(zcr_color_manager_); + zcr_color_manager_->OnZcrColorManagementSurfaceDestroyed(this); +} + +gfx::ColorSpace TestZcrColorManagementSurfaceV1::GetGfxColorSpace() { + return gfx_color_space_; +} + +void TestZcrColorManagementSurfaceV1::SetGfxColorSpace( + gfx::ColorSpace gfx_color_space) { + gfx_color_space_ = gfx_color_space; +} + +void TestZcrColorManagementSurfaceV1::StoreZcrColorManager( + MockZcrColorManagerV1* zcr_color_manager) { + zcr_color_manager_ = zcr_color_manager; +} + +} // namespace wl \ No newline at end of file
diff --git a/ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_surface.h b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_surface.h new file mode 100644 index 0000000..7ce1e9c --- /dev/null +++ b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_management_surface.h
@@ -0,0 +1,61 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_WAYLAND_ZCR_COLOR_MANAGEMENT_SURFACE_H_ +#define UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_WAYLAND_ZCR_COLOR_MANAGEMENT_SURFACE_H_ + +#include <chrome-color-management-server-protocol.h> + +#include "base/files/scoped_file.h" +#include "base/memory/raw_ptr.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/gfx/color_space.h" +#include "ui/ozone/platform/wayland/test/server_object.h" + +struct wl_client; +struct wl_resource; + +namespace wl { + +extern const struct zcr_color_management_surface_v1_interface + kTestZcrColorManagementSurfaceV1Impl; + +class MockZcrColorManagerV1; + +class TestZcrColorManagementSurfaceV1 : public ServerObject { + public: + explicit TestZcrColorManagementSurfaceV1(wl_resource* resource); + + TestZcrColorManagementSurfaceV1(const TestZcrColorManagementSurfaceV1&) = + delete; + TestZcrColorManagementSurfaceV1& operator=( + const TestZcrColorManagementSurfaceV1&) = delete; + + ~TestZcrColorManagementSurfaceV1() override; + + void SetAlphaMode(wl_client* client, + wl_resource* resource, + uint32_t alpha_mode); + void SetExtendedDynamicRange(wl_client* client, + wl_resource* resource, + uint32_t value); + void SetColorSpace(wl_client* client, + wl_resource* resource, + wl_resource* color_space_resource, + uint32_t render_intent); + void SetDefaultColorSpace(wl_client* client, wl_resource* resource); + void Destroy(wl_client* client, wl_resource* resource); + + gfx::ColorSpace GetGfxColorSpace(); + void SetGfxColorSpace(gfx::ColorSpace gfx_color_space); + void StoreZcrColorManager(MockZcrColorManagerV1* zcr_color_manager); + + private: + gfx::ColorSpace gfx_color_space_; + raw_ptr<MockZcrColorManagerV1> zcr_color_manager_ = nullptr; +}; + +} // namespace wl + +#endif // UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_WAYLAND_ZCR_COLOR_MANAGEMENT_SURFACE_H_
diff --git a/ui/ozone/platform/wayland/test/test_wayland_zcr_color_space.cc b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_space.cc new file mode 100644 index 0000000..0fe157d --- /dev/null +++ b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_space.cc
@@ -0,0 +1,42 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/ozone/platform/wayland/test/test_wayland_zcr_color_space.h" + +#include "ui/ozone/platform/wayland/test/mock_wayland_zcr_color_manager.h" +#include "ui/ozone/platform/wayland/test/server_object.h" + +namespace wl { + +namespace { + +void GetInformation(wl_client* client, wl_resource* resource) { + auto* zcr_color_space = GetUserDataAs<TestZcrColorSpaceV1>(resource); + DCHECK(zcr_color_space); +} + +} // namespace + +const struct zcr_color_space_v1_interface kTestZcrColorSpaceV1Impl = { + &GetInformation, &DestroyResource}; + +TestZcrColorSpaceV1::TestZcrColorSpaceV1(wl_resource* resource) + : ServerObject(resource) {} + +TestZcrColorSpaceV1::~TestZcrColorSpaceV1() { + if (zcr_color_manager_) { + zcr_color_manager_->OnZcrColorSpaceDestroyed(this); + } +} + +void TestZcrColorSpaceV1::SetGfxColorSpace(gfx::ColorSpace gfx_color_space) { + gfx_color_space_ = gfx_color_space; +} + +void TestZcrColorSpaceV1::SetZcrColorManager( + MockZcrColorManagerV1* zcr_color_manager) { + zcr_color_manager_ = zcr_color_manager; +} + +} // namespace wl \ No newline at end of file
diff --git a/ui/ozone/platform/wayland/test/test_wayland_zcr_color_space.h b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_space.h new file mode 100644 index 0000000..30e9291 --- /dev/null +++ b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_space.h
@@ -0,0 +1,50 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_WAYLAND_ZCR_COLOR_SPACE_H_ +#define UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_WAYLAND_ZCR_COLOR_SPACE_H_ + +#include <chrome-color-management-server-protocol.h> + +#include "base/files/scoped_file.h" +#include "base/memory/raw_ptr.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/gfx/color_space.h" +#include "ui/ozone/platform/wayland/test/server_object.h" + +struct wl_client; +struct wl_resource; + +namespace wl { + +extern const struct zcr_color_space_v1_interface kTestZcrColorSpaceV1Impl; + +class MockZcrColorManagerV1; + +// Manage zcr_color_space_v1_interface +class TestZcrColorSpaceV1 : public ServerObject { + public: + explicit TestZcrColorSpaceV1(wl_resource* resource); + + TestZcrColorSpaceV1(const TestZcrColorSpaceV1&) = delete; + TestZcrColorSpaceV1& operator=(const TestZcrColorSpaceV1&) = delete; + + ~TestZcrColorSpaceV1() override; + + void GetInformation(wl_client* client, wl_resource* resource); + void Destroy(wl_client* client, wl_resource* resource); + + gfx::ColorSpace GetGfxColorSpace() const { return gfx_color_space_; } + void SetGfxColorSpace(gfx::ColorSpace gfx_color_space); + + void SetZcrColorManager(MockZcrColorManagerV1* zcr_color_manager); + + private: + gfx::ColorSpace gfx_color_space_; + raw_ptr<MockZcrColorManagerV1> zcr_color_manager_ = nullptr; +}; + +} // namespace wl + +#endif // UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_WAYLANDS_ZCR_COLOR_SPACE_H_ \ No newline at end of file
diff --git a/ui/ozone/platform/wayland/test/test_wayland_zcr_color_space_creator.cc b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_space_creator.cc new file mode 100644 index 0000000..d58cf22 --- /dev/null +++ b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_space_creator.cc
@@ -0,0 +1,14 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/ozone/platform/wayland/test/test_wayland_zcr_color_space_creator.h" + +namespace wl { + +TestZcrColorSpaceCreatorV1::TestZcrColorSpaceCreatorV1(wl_resource* resource) + : ServerObject(resource) {} + +TestZcrColorSpaceCreatorV1::~TestZcrColorSpaceCreatorV1() = default; + +} // namespace wl \ No newline at end of file
diff --git a/ui/ozone/platform/wayland/test/test_wayland_zcr_color_space_creator.h b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_space_creator.h new file mode 100644 index 0000000..7d1ef0ba --- /dev/null +++ b/ui/ozone/platform/wayland/test/test_wayland_zcr_color_space_creator.h
@@ -0,0 +1,30 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_WAYLAND_ZCR_COLOR_SPACE_CREATOR_H_ +#define UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_WAYLAND_ZCR_COLOR_SPACE_CREATOR_H_ + +#include <chrome-color-management-server-protocol.h> + +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/ozone/platform/wayland/test/server_object.h" + +struct wl_resource; + +namespace wl { + +class TestZcrColorSpaceCreatorV1 : public ServerObject { + public: + explicit TestZcrColorSpaceCreatorV1(wl_resource* resource); + + TestZcrColorSpaceCreatorV1(const TestZcrColorSpaceCreatorV1&) = delete; + TestZcrColorSpaceCreatorV1& operator=(const TestZcrColorSpaceCreatorV1&) = + delete; + + ~TestZcrColorSpaceCreatorV1() override; +}; + +} // namespace wl + +#endif // UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_WAYLAND_ZCR_COLOR_SPACE_CREATOR_H_
diff --git a/ui/ozone/platform/wayland/test/wayland_test.h b/ui/ozone/platform/wayland/test/wayland_test.h index ad27dd8..94389be 100644 --- a/ui/ozone/platform/wayland/test/wayland_test.h +++ b/ui/ozone/platform/wayland/test/wayland_test.h
@@ -14,6 +14,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/buildflags.h" +#include "ui/base/ui_base_features.h" #include "ui/events/ozone/layout/keyboard_layout_engine.h" #include "ui/ozone/common/features.h" #include "ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h" @@ -116,7 +117,7 @@ std::unique_ptr<WaylandWindow> window_; gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget; std::vector<base::test::FeatureRef> enabled_features_{ - ui::kWaylandOverlayDelegation}; + features::kLacrosColorManagement, ui::kWaylandOverlayDelegation}; std::vector<base::test::FeatureRef> disabled_features_; private:
diff --git a/ui/views/corewm/tooltip_lacros.cc b/ui/views/corewm/tooltip_lacros.cc index c050d04..35fe9cb 100644 --- a/ui/views/corewm/tooltip_lacros.cc +++ b/ui/views/corewm/tooltip_lacros.cc
@@ -78,11 +78,8 @@ // Add the distance between `parent_window` and its toplevel window to // `position_` since Ash-side server will use this position as relative to // wayland toplevel window. - // TODO(elkurin): Use WaylandWindow instead of ToplevelWindow/Popup when it's - // supported on ozone. - // TODO(elkurin): The position is wrong for some popup such as dictionary - // popup shown on right-clicking a word. Should use the nearest toplevel - // window or popup window instead of always referring to GetToplevelWindow(). + // TODO(crbug.com/1385219): Use WaylandWindow instead of ToplevelWindow/Popup + // when it's supported on ozone. aura::Window::ConvertPointToTarget( parent_window_, parent_window_->GetToplevelWindow(), &position_); trigger_ = trigger;
diff --git a/ui/views/window/caption_button_types.h b/ui/views/window/caption_button_types.h index 5a825b8..536f5534 100644 --- a/ui/views/window/caption_button_types.h +++ b/ui/views/window/caption_button_types.h
@@ -24,7 +24,6 @@ // specific to their use case (e.g. tab search caption button in the browser // window frame). CAPTION_BUTTON_ICON_CUSTOM, - CAPTION_BUTTON_ICON_FLOAT, CAPTION_BUTTON_ICON_COUNT, };
diff --git a/ui/views/window/frame_caption_button.cc b/ui/views/window/frame_caption_button.cc index 25a6410..94e78b0a 100644 --- a/ui/views/window/frame_caption_button.cc +++ b/ui/views/window/frame_caption_button.cc
@@ -387,8 +387,6 @@ u"CAPTION_BUTTON_ICON_LOCATION"}, {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_MENU, u"CAPTION_BUTTON_ICON_MENU"}, - {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_FLOAT, - u"CAPTION_BUTTON_ICON_FLOAT"}, {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_ZOOM, u"CAPTION_BUTTON_ICON_ZOOM"}, {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_CENTER,
diff --git a/weblayer/browser/file_select_helper.cc b/weblayer/browser/file_select_helper.cc index 4763f34..c7fd8dc0 100644 --- a/weblayer/browser/file_select_helper.cc +++ b/weblayer/browser/file_select_helper.cc
@@ -118,6 +118,8 @@ void FileSelectHelper::RunFileChooserEnd() { if (listener_) listener_->FileSelectionCanceled(); + + select_file_dialog_->ListenerDestroyed(); select_file_dialog_.reset(); Release(); }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java index f948b858..d6dec550 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
@@ -362,11 +362,13 @@ public void shutdown() { StrictModeWorkaround.apply(); mInDestroy = true; + + BrowserImplJni.get().prepareForShutdown(mNativeBrowser); + for (Object tab : getTabs()) { destroyTabImpl((TabImpl) tab); } mBrowserFragmentImpl.shutdown(); - BrowserImplJni.get().deleteBrowser(mNativeBrowser); mVisibleSecurityStateObservers.clear();