diff --git a/BUILD.gn b/BUILD.gn index b0456ba..dca156f 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -1585,12 +1585,9 @@ script_test("blink_python_tests") { script = "//testing/scripts/run_isolated_script_test.py" - args = [ - "@WrappedPath(" + - rebase_path("//third_party/blink/tools/run_blinkpy_tests.py", - root_build_dir) + ")", - "--coverage", - ] + args = [ "@WrappedPath(" + + rebase_path("//third_party/blink/tools/run_blinkpy_tests.py", + root_build_dir) + ")" ] data = [ # These tests use //build/android/devil_chromium.py even when !is_android,
diff --git a/DEPS b/DEPS index de18e02..2435834 100644 --- a/DEPS +++ b/DEPS
@@ -279,7 +279,7 @@ 'dawn_standalone': False, # reclient CIPD package version - 'reclient_version': 're_client_version:0.72.0.b874055-gomaip', + 'reclient_version': 're_client_version:0.76.0.f4c4bc4-gomaip', # Enable fetching Rust-related packages. 'use_rust': False, @@ -297,15 +297,15 @@ # 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': '7acdbfc5ae97776c6f2502cfd4949bef67feae42', + 'skia_revision': 'f2ac3b9728f770efb53c34aeca7da6527d36f311', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'babfba7408534bbc5b214b0898aa5c19634d50e7', + 'v8_revision': '13f3751b987e0fd310cd189123dd86a51212f4bf', # 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': '87ed2c9d1eaf918d38ceb6c4f210ce27f8efa9cb', + 'angle_revision': 'c9360ccbd34aecc458cd13091e28243cf74f9c50', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -368,7 +368,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': '268569634e0497164b911738502a4438bf1e669b', + 'catapult_revision': 'b2cd6477b94b91a0b94b3430a50ba3bce650c5b6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -440,7 +440,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nearby # and whatever else without interference from each other. - 'nearby_revision': '30a82350cdda38c01fd6794d9addee89ced7d10f', + 'nearby_revision': '76d45f20db7260c315b52396c740ae3e3f7bfd9f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling securemessage # and whatever else without interference from each other. @@ -483,7 +483,7 @@ 'libcxx_revision': '55e0c49d148aecc33568a1a61b916323004a2d18', # GN CIPD package version. - 'gn_version': 'git_revision:c8c63300ac8ecb66d8126af5407257209ae59044', + 'gn_version': 'git_revision:0bcd37bd2b83f1a9ee17088037ebdfe6eab6d31a', } # Only these hosts are allowed for dependencies in this DEPS file. @@ -873,7 +873,7 @@ 'packages': [ { 'package': 'chromium/rts/model/mac-amd64', - 'version': 'nv2m5tQGuaQEvcuOnvOK8U8qcOB1z6Atuu1nEF9oGV4C', + 'version': 'WBTAImq5mN_jfX-oLpNn_P3VJ_MbJjXvN-VRik9nnMoC', }, ], 'dep_type': 'cipd', @@ -1693,7 +1693,7 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@d53c356ad7d9a77f43cff070b7af4212fb3f739f', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@476824373c1963ca293213cddd13f6a839390491', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907', @@ -1762,7 +1762,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/linux-amd64', - 'version': '9fyLI7UE2vwgyQweLyqyh193CzDMxbUr0xRuqtcCLAgC', + 'version': 'ebDbf3X2jdAICDlXMXUr7yp4muhSvYoREDLdZZoJzuAC', }, ], 'dep_type': 'cipd', @@ -1805,7 +1805,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8057e5e76dec5b64f99c4c19f748d20c892822c7', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@cce874eebdb4e4f669f662c3f448102c6075ab87', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/browser/aw_permission_manager.cc b/android_webview/browser/aw_permission_manager.cc index d0ddf34..fe625ae 100644 --- a/android_webview/browser/aw_permission_manager.cc +++ b/android_webview/browser/aw_permission_manager.cc
@@ -16,6 +16,7 @@ #include "components/permissions/permission_util.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" @@ -468,6 +469,17 @@ return PermissionStatus::DENIED; } +content::PermissionResult +AwPermissionManager::GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) { + blink::mojom::PermissionStatus status = + GetPermissionStatus(permission, origin.GetURL(), origin.GetURL()); + + return content::PermissionResult( + status, content::PermissionStatusSource::UNSPECIFIED); +} + PermissionStatus AwPermissionManager::GetPermissionStatusForCurrentDocument( PermissionType permission, content::RenderFrameHost* render_frame_host) {
diff --git a/android_webview/browser/aw_permission_manager.h b/android_webview/browser/aw_permission_manager.h index 9713d7a..9276409 100644 --- a/android_webview/browser/aw_permission_manager.h +++ b/android_webview/browser/aw_permission_manager.h
@@ -11,6 +11,7 @@ #include "base/containers/id_map.h" #include "base/memory/weak_ptr.h" #include "content/public/browser/permission_controller_delegate.h" +#include "content/public/browser/permission_result.h" namespace blink { enum class PermissionType; @@ -60,6 +61,9 @@ blink::PermissionType permission, const GURL& requesting_origin, const GURL& embedding_origin) override; + content::PermissionResult GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) override; blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument( blink::PermissionType permission, content::RenderFrameHost* render_frame_host) override;
diff --git a/android_webview/browser/icon_helper.cc b/android_webview/browser/icon_helper.cc index 8247e795..7e3b3b1 100644 --- a/android_webview/browser/icon_helper.cc +++ b/android_webview/browser/icon_helper.cc
@@ -4,8 +4,6 @@ #include "android_webview/browser/icon_helper.h" -#include <vector> - #include "base/bind.h" #include "base/callback.h" #include "base/check_op.h" @@ -18,7 +16,6 @@ #include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/geometry/size.h" -#include "ui/gfx/image/image_util.h" using content::BrowserThread; using content::WebContents; @@ -55,13 +52,7 @@ return; } - std::vector<SkBitmap> filtered_images; - std::vector<gfx::Size> filtered_bitmap_sizes; - gfx::FilterAndResizeImagesForMaximalSize( - bitmaps, kLargestIconSize, filtered_images, filtered_bitmap_sizes); - DCHECK_EQ(filtered_images.size(), filtered_bitmap_sizes.size()); - - if (filtered_images.size() == 0) { + if (bitmaps.size() == 0) { return; } @@ -71,13 +62,13 @@ if (listener_) { std::vector<size_t> best_indices; - SelectFaviconFrameIndices(filtered_bitmap_sizes, + SelectFaviconFrameIndices(original_bitmap_sizes, std::vector<int>(1U, kLargestIconSize), &best_indices, nullptr); listener_->OnReceivedIcon( image_url, - filtered_images[best_indices.size() == 0 ? 0 : best_indices.front()]); + bitmaps[best_indices.size() == 0 ? 0 : best_indices.front()]); } } @@ -98,10 +89,10 @@ } web_contents()->DownloadImage( candidate->icon_url, - true, // Is a favicon - gfx::Size(), // No preferred size - 0, // Max bitmap size - 0 means unlimited - false, // Normal cache policy + true, // Is a favicon + gfx::Size(), // No preferred size + kLargestIconSize, // Max bitmap size + false, // Normal cache policy base::BindOnce(&IconHelper::DownloadFaviconCallback, base::Unretained(this))); break;
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java index a3d7065..fc06e59 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java +++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -345,7 +345,11 @@ "Enable rendering starvation-prevention during threaded scrolling." + " See https://crbug.com/1315279."), Flag.baseFeature(BaseFeatures.NO_WAKE_UPS_FOR_CANCELED_TASKS, + "Controls whether wake ups are possible for canceled tasks."), + Flag.baseFeature(BaseFeatures.REMOVE_CANCELED_TASKS_IN_TASK_QUEUE, "Controls whether or not canceled delayed tasks are removed from task queues."), + Flag.baseFeature(BlinkFeatures.THROTTLE_INTERSECTION_OBSERVER_UMA, + "Reduces fine-grained UMA metrics for IntersectionObserver."), // Add new commandline switches and features above. The final entry should have a // trailing comma for cleaner diffs. };
diff --git a/android_webview/tools/generate_flag_labels.py b/android_webview/tools/generate_flag_labels.py index da9d3f12..917270a 100755 --- a/android_webview/tools/generate_flag_labels.py +++ b/android_webview/tools/generate_flag_labels.py
@@ -59,6 +59,8 @@ 'AutofillShadowDom': 'AutofillShadowDOM', 'HtmlParamElementUrlSupport': 'HTMLParamElementUrlSupport', 'webview-mp-arch-fenced-frames': 'webview-mparch-fenced-frames', + 'ThrottleIntersectionObserverUma': 'ThrottleIntersectionObserverUMA', + 'RemoveCanceledTasksInTaskQueue': 'RemoveCanceledTasksInTaskQueue2', # The final entry should have a trailing comma for cleaner diffs. You may # remove the entry from this dictionary when it's time to delete the # corresponding base::Feature or commandline switch.
diff --git a/ash/app_list/views/apps_container_view_unittest.cc b/ash/app_list/views/apps_container_view_unittest.cc index 1a40b461ae..27ffe61f 100644 --- a/ash/app_list/views/apps_container_view_unittest.cc +++ b/ash/app_list/views/apps_container_view_unittest.cc
@@ -7,6 +7,7 @@ #include "ash/app_list/app_list_controller_impl.h" #include "ash/app_list/model/app_list_test_model.h" #include "ash/app_list/test/app_list_test_helper.h" +#include "ash/app_list/views/apps_grid_view_test_api.h" #include "ash/app_list/views/continue_section_view.h" #include "ash/app_list/views/recent_apps_view.h" #include "ash/app_list/views/search_box_view.h" @@ -25,6 +26,34 @@ namespace ash { +namespace { + +class TransitionWaiter : public PaginationModelObserver { + public: + explicit TransitionWaiter(PaginationModel* model) : model_(model) { + model_->AddObserver(this); + } + + TransitionWaiter(const TransitionWaiter&) = delete; + TransitionWaiter& operator=(const TransitionWaiter&) = delete; + + ~TransitionWaiter() override { model_->RemoveObserver(this); } + + void Wait() { + ui_run_loop_ = std::make_unique<base::RunLoop>(); + ui_run_loop_->Run(); + } + + private: + // PaginationModelObserver: + void TransitionEnded() override { ui_run_loop_->QuitWhenIdle(); } + + std::unique_ptr<base::RunLoop> ui_run_loop_; + PaginationModel* model_ = nullptr; +}; + +} // namespace + class AppsContainerViewTest : public AshTestBase { public: AppsContainerViewTest() { @@ -66,6 +95,21 @@ ->selected_page(); } + int GetTotalPages() { + return GetAppListTestHelper() + ->GetRootPagedAppsGridView() + ->pagination_model() + ->total_pages(); + } + + bool HasGradientMask() { + return GetAppListTestHelper() + ->GetAppsContainerView() + ->scrollable_container_for_test() + ->layer() + ->layer_mask_layer(); + } + private: base::test::ScopedFeatureList features_; std::unique_ptr<test::AppListTestModel> app_list_test_model_; @@ -327,4 +371,45 @@ EXPECT_EQ(GetSelectedPage(), 0); } +// Test that the gradient mask is created when the page drag begins, and +// destroyed once the page drag has been released and completes. +TEST_F(AppsContainerViewTest, StartPageDragThenRelease) { + GetAppListTestHelper()->AddAppItems(23); + TabletMode::Get()->SetEnabledForTest(true); + auto* apps_grid_view = GetAppListTestHelper()->GetRootPagedAppsGridView(); + test::AppsGridViewTestApi test_api(apps_grid_view); + + EXPECT_FALSE(HasGradientMask()); + EXPECT_EQ(0, GetSelectedPage()); + EXPECT_EQ(2, GetTotalPages()); + + TransitionWaiter transition_waiter(apps_grid_view->pagination_model()); + gfx::Point start_page_drag = test_api.GetViewAtIndex(GridIndex(0, 0)) + ->GetIconBoundsInScreen() + .bottom_right(); + start_page_drag.Offset(10, 0); + + // Begin a touch and drag the page upward. + auto* generator = GetEventGenerator(); + generator->set_current_screen_location(start_page_drag); + generator->PressTouch(); + generator->MoveTouchBy(0, -20); + + // Move the touch down a bit so it does not register as a fling to the next + // page. + generator->MoveTouchBy(0, 1); + + // Gradient mask should exist during the page drag. + EXPECT_TRUE(HasGradientMask()); + + // End the page drag and wait for the page to animate back to the correct + // position. + generator->ReleaseTouch(); + transition_waiter.Wait(); + + // The gradient mask should be removed after the end of the page animation. + EXPECT_FALSE(HasGradientMask()); + EXPECT_EQ(0, GetSelectedPage()); +} + } // namespace ash
diff --git a/ash/components/arc/ime/arc_ime_service.cc b/ash/components/arc/ime/arc_ime_service.cc index 6a477f5..c2a1cad 100644 --- a/ash/components/arc/ime/arc_ime_service.cc +++ b/ash/components/arc/ime/arc_ime_service.cc
@@ -548,7 +548,7 @@ return true; } -bool ArcImeService::GetCompositionCharacterBounds(uint32_t index, +bool ArcImeService::GetCompositionCharacterBounds(size_t index, gfx::Rect* rect) const { return false; }
diff --git a/ash/components/arc/ime/arc_ime_service.h b/ash/components/arc/ime/arc_ime_service.h index 03c0cf3..8106b5b 100644 --- a/ash/components/arc/ime/arc_ime_service.h +++ b/ash/components/arc/ime/arc_ime_service.h
@@ -132,7 +132,7 @@ base::i18n::TextDirection GetTextDirection() const override; int GetTextInputFlags() const override; bool CanComposeInline() const override; - bool GetCompositionCharacterBounds(uint32_t index, + bool GetCompositionCharacterBounds(size_t index, gfx::Rect* rect) const override; bool HasCompositionText() const override; FocusReason GetFocusReason() const override;
diff --git a/ash/public/cpp/pagination/pagination_model.cc b/ash/public/cpp/pagination/pagination_model.cc index d5628ba..0975b61a 100644 --- a/ash/public/cpp/pagination/pagination_model.cc +++ b/ash/public/cpp/pagination/pagination_model.cc
@@ -271,6 +271,7 @@ if (!duration.is_zero()) transition_animation_->SetSlideDuration(duration); + is_transition_started_ = true; NotifyTransitionStarted(); transition_animation_->Show(); } @@ -288,9 +289,11 @@ } void PaginationModel::AnimationEnded(const gfx::Animation* animation) { - // Do not notify transition end for the reverting animation. - if (!IsRevertingCurrentTransition()) + // Ensure that each TransitionStarted() has only one TransitionEnded(). + if (is_transition_started_) { + is_transition_started_ = false; NotifyTransitionEnded(); + } // Save |pending_selected_page_| because SelectPage resets it. int next_target = pending_selected_page_;
diff --git a/ash/public/cpp/pagination/pagination_model.h b/ash/public/cpp/pagination/pagination_model.h index 86533993..226b4d22 100644 --- a/ash/public/cpp/pagination/pagination_model.h +++ b/ash/public/cpp/pagination/pagination_model.h
@@ -34,6 +34,12 @@ return target_page == rhs.target_page && progress == rhs.progress; } + std::string ToString() const { + std::stringstream ss; + ss << "Target Page: " << target_page << ", Progess: " << progress; + return ss.str(); + } + // Target page for the transition or -1 if there is no target page. For // page switcher, this is the target selected page. For touch scroll, // this is usually the previous or next page (or -1 when there is no @@ -139,6 +145,9 @@ Transition transition_; + // Whether a transition has started, but not yet ended. + bool is_transition_started_ = false; + // Pending selected page when SelectedPage is called during a transition. If // multiple SelectPage is called while a transition is in progress, only the // last target page is remembered here.
diff --git a/ash/public/cpp/pagination/pagination_model_unittest.cc b/ash/public/cpp/pagination/pagination_model_unittest.cc index 3eed56c..48e6a41 100644 --- a/ash/public/cpp/pagination/pagination_model_unittest.cc +++ b/ash/public/cpp/pagination/pagination_model_unittest.cc
@@ -519,5 +519,23 @@ EXPECT_EQ(1, observer_.transition_end_call_count()); } +// Tests that a canceled scroll will call both TransitionStart and +// TransitionEnd. +TEST_F(PaginationModelTest, CancelAnimationHasOneTransitionEnd) { + const int kStartPage = 2; + + // Scroll to the next page (negative delta) and cancel it. + SetStartPageAndExpects(kStartPage, 0, 1, 0); + pagination()->StartScroll(); + pagination()->UpdateScroll(-0.1); + EXPECT_EQ(kStartPage + 1, pagination()->transition().target_page); + pagination()->EndScroll(true); // Cancel transition + WaitForPagingAnimation(); + EXPECT_EQ(0, observer_.selection_count()); + + EXPECT_EQ(1, observer_.transition_start_call_count()); + EXPECT_EQ(1, observer_.transition_end_call_count()); +} + } // namespace test } // namespace ash
diff --git a/ash/rgb_keyboard/rgb_keyboard_manager.cc b/ash/rgb_keyboard/rgb_keyboard_manager.cc index 14c23aa9..a8f9245 100644 --- a/ash/rgb_keyboard/rgb_keyboard_manager.cc +++ b/ash/rgb_keyboard/rgb_keyboard_manager.cc
@@ -146,11 +146,6 @@ ime_controller_ptr_->AddObserver(this); } - - // Set keyboard to the default color on startup - RgbkbdClient::Get()->SetStaticBackgroundColor(SkColorGetR(kDefaultColor), - SkColorGetG(kDefaultColor), - SkColorGetB(kDefaultColor)); } bool RgbKeyboardManager::IsPerKeyKeyboard() const {
diff --git a/ash/rgb_keyboard/rgb_keyboard_manager_unittest.cc b/ash/rgb_keyboard/rgb_keyboard_manager_unittest.cc index f1db670..f1d8cf4 100644 --- a/ash/rgb_keyboard/rgb_keyboard_manager_unittest.cc +++ b/ash/rgb_keyboard/rgb_keyboard_manager_unittest.cc
@@ -235,16 +235,6 @@ EXPECT_TRUE(client_->get_caps_lock_state()); } -TEST_F(RgbKeyboardManagerTest, DefaultState) { - const RgbColor& default_rgb_values = client_->recently_sent_rgb(); - - EXPECT_FALSE(client_->is_rainbow_mode_set()); - - EXPECT_EQ(SkColorGetR(kDefaultColor), std::get<0>(default_rgb_values)); - EXPECT_EQ(SkColorGetG(kDefaultColor), std::get<1>(default_rgb_values)); - EXPECT_EQ(SkColorGetB(kDefaultColor), std::get<2>(default_rgb_values)); -} - // TODO(jimmyxgong): This is just a stub test, there is only one enum available // so just check num times the function has been called. TEST_F(RgbKeyboardManagerTest, SetAnimationMode) {
diff --git a/ash/system/accessibility/dictation_button_tray.cc b/ash/system/accessibility/dictation_button_tray.cc index 9aafb1fb4..c8af5cc 100644 --- a/ash/system/accessibility/dictation_button_tray.cc +++ b/ash/system/accessibility/dictation_button_tray.cc
@@ -19,6 +19,7 @@ #include "ash/system/tray/tray_utils.h" #include "components/prefs/pref_service.h" #include "ui/accessibility/accessibility_features.h" +#include "ui/base/ime/text_input_client.h" #include "ui/base/l10n/l10n_util.h" #include "ui/compositor/layer.h" #include "ui/gfx/geometry/transform_util.h" @@ -40,11 +41,18 @@ constexpr float kInProgressAnimationScaleFactor = 0.875f; // Helper function that creates an image for the dictation icon. -gfx::ImageSkia GetIconImage(bool enabled) { +// |active| means Dictation is actively listening for speech. The icon +// changes to an "on" icon from "off" when Dictation is listening. +// |enabled| indicates whether the tray button is enabled, i.e. clickable. +// A secondary color is used to indicate the icon is not enabled. +gfx::ImageSkia GetIconImage(bool active, bool enabled) { const SkColor color = - TrayIconColor(Shell::Get()->session_controller()->GetSessionState()); - return enabled ? gfx::CreateVectorIcon(kDictationOnNewuiIcon, color) - : gfx::CreateVectorIcon(kDictationOffNewuiIcon, color); + enabled + ? TrayIconColor(Shell::Get()->session_controller()->GetSessionState()) + : AshColorProvider::Get()->GetContentLayerColor( + AshColorProvider::ContentLayerType::kIconColorSecondary); + return active ? gfx::CreateVectorIcon(kDictationOnNewuiIcon, color) + : gfx::CreateVectorIcon(kDictationOffNewuiIcon, color); } } // namespace @@ -53,7 +61,13 @@ : TrayBackgroundView(shelf), icon_(new views::ImageView()), download_progress_(0) { - const gfx::ImageSkia icon_image = GetIconImage(/*enabled=*/false); + Shell* shell = Shell::Get(); + ui::TextInputClient* client = + shell->window_tree_host_manager()->input_method()->GetTextInputClient(); + in_text_input_ = + (client && client->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE); + const gfx::ImageSkia icon_image = + GetIconImage(/*active=*/false, /*enabled=*/in_text_input_); const int vertical_padding = (kTrayItemSize - icon_image.height()) / 2; const int horizontal_padding = (kTrayItemSize - icon_image.width()) / 2; icon_->SetBorder(views::CreateEmptyBorder( @@ -61,15 +75,18 @@ icon_->SetTooltipText( l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_DICTATION)); tray_container()->AddChildView(icon_); - Shell::Get()->AddShellObserver(this); - Shell::Get()->accessibility_controller()->AddObserver(this); - Shell::Get()->session_controller()->AddObserver(this); + shell->AddShellObserver(this); + shell->accessibility_controller()->AddObserver(this); + shell->session_controller()->AddObserver(this); + shell->window_tree_host_manager()->input_method()->AddObserver(this); } DictationButtonTray::~DictationButtonTray() { - Shell::Get()->RemoveShellObserver(this); - Shell::Get()->accessibility_controller()->RemoveObserver(this); - Shell::Get()->session_controller()->RemoveObserver(this); + Shell* shell = Shell::Get(); + shell->RemoveShellObserver(this); + shell->accessibility_controller()->RemoveObserver(this); + shell->session_controller()->RemoveObserver(this); + shell->window_tree_host_manager()->input_method()->RemoveObserver(this); } bool DictationButtonTray::PerformAction(const ui::Event& event) { @@ -116,8 +133,9 @@ void DictationButtonTray::OnThemeChanged() { TrayBackgroundView::OnThemeChanged(); - icon_->SetImage(GetIconImage( - Shell::Get()->accessibility_controller()->dictation_active())); + icon_->SetImage( + GetIconImage(Shell::Get()->accessibility_controller()->dictation_active(), + GetEnabled())); if (progress_indicator_) progress_indicator_->InvalidateLayer(); } @@ -137,7 +155,7 @@ } void DictationButtonTray::UpdateIcon(bool dictation_active) { - icon_->SetImage(GetIconImage(dictation_active)); + icon_->SetImage(GetIconImage(dictation_active, GetEnabled())); SetIsActive(dictation_active); } @@ -221,13 +239,31 @@ UpdateIcon(Shell::Get()->accessibility_controller()->dictation_active()); } +void DictationButtonTray::OnCaretBoundsChanged( + const ui::TextInputClient* client) { + TextInputChanged(client); +} + +void DictationButtonTray::OnTextInputStateChanged( + const ui::TextInputClient* client) { + TextInputChanged(client); +} + +void DictationButtonTray::TextInputChanged(const ui::TextInputClient* client) { + in_text_input_ = + client && client->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE; + SetEnabled((download_progress_ <= 0 || download_progress_ >= 100) && + in_text_input_); + CheckDictationStatusAndUpdateIcon(); +} + void DictationButtonTray::UpdateOnSpeechRecognitionDownloadChanged( int download_progress) { if (!visible_preferred()) return; bool download_in_progress = download_progress > 0 && download_progress < 100; - SetEnabled(!download_in_progress); + SetEnabled(!download_in_progress && in_text_input_); icon_->SetTooltipText(l10n_util::GetStringUTF16( download_in_progress ? IDS_ASH_ACCESSIBILITY_DICTATION_BUTTON_TOOLTIP_SODA_DOWNLOADING
diff --git a/ash/system/accessibility/dictation_button_tray.h b/ash/system/accessibility/dictation_button_tray.h index f496190..840162d 100644 --- a/ash/system/accessibility/dictation_button_tray.h +++ b/ash/system/accessibility/dictation_button_tray.h
@@ -11,6 +11,7 @@ #include "ash/public/cpp/session/session_observer.h" #include "ash/shell_observer.h" #include "ash/system/tray/tray_background_view.h" +#include "ui/base/ime/input_method_observer.h" #include "ui/events/event_constants.h" namespace views { @@ -28,7 +29,8 @@ class ASH_EXPORT DictationButtonTray : public TrayBackgroundView, public ShellObserver, public AccessibilityObserver, - public SessionObserver { + public SessionObserver, + public ui::InputMethodObserver { public: explicit DictationButtonTray(Shelf* shelf); @@ -62,6 +64,13 @@ // views::View: const char* GetClassName() const override; + // ui::InputMethodObserver: + void OnFocus() override {} + void OnBlur() override {} + void OnCaretBoundsChanged(const ui::TextInputClient* client) override; + void OnTextInputStateChanged(const ui::TextInputClient* client) override; + void OnInputMethodDestroyed(const ui::InputMethod* input_method) override {} + // Updates this button's state and progress indicator when speech recognition // file download state changes. void UpdateOnSpeechRecognitionDownloadChanged(int download_progress); @@ -89,6 +98,10 @@ // Actively looks up dictation status and calls UpdateIcon. void CheckDictationStatusAndUpdateIcon(); + // Called when text input state changes to determine whether Dictation + // should still be enabled and update the icon. + void TextInputChanged(const ui::TextInputClient* client); + // Weak pointer, will be parented by TrayContainer for its lifetime. views::ImageView* icon_; @@ -100,6 +113,9 @@ // to be notified of progress changed events. std::unique_ptr<ProgressIndicator> progress_indicator_; base::CallbackListSubscription progress_changed_subscription_; + + // Whether the cursor and focus is currently in a text input field. + bool in_text_input_ = false; }; } // namespace ash
diff --git a/ash/system/accessibility/dictation_button_tray_unittest.cc b/ash/system/accessibility/dictation_button_tray_unittest.cc index bbcd102..e320068e 100644 --- a/ash/system/accessibility/dictation_button_tray_unittest.cc +++ b/ash/system/accessibility/dictation_button_tray_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "ash/system/accessibility/dictation_button_tray.h" +#include <memory> #include "ash/accessibility/accessibility_controller_impl.h" #include "ash/accessibility/test_accessibility_controller_client.h" @@ -35,6 +36,10 @@ #include "ui/accessibility/accessibility_features.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" +#include "ui/base/ime/ash/ime_bridge.h" +#include "ui/base/ime/ash/input_method_ash.h" +#include "ui/base/ime/fake_text_input_client.h" +#include "ui/base/ime/text_input_type.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/display/display_switches.h" #include "ui/display/manager/display_manager.h" @@ -101,7 +106,15 @@ DictationButtonTrayTest& operator=(const DictationButtonTrayTest&) = delete; // AshTestBase: - void SetUp() override { AshTestBase::SetUp(); } + void SetUp() override { + // Focus some input text so the Dictation button will be enabled. + fake_text_input_client_ = + std::make_unique<ui::FakeTextInputClient>(ui::TEXT_INPUT_TYPE_TEXT); + ui::InputMethodAsh ime(nullptr); + ui::IMEBridge::Get()->SetInputContextHandler(&ime); + AshTestBase::SetUp(); + FocusTextInputClient(); + } protected: views::ImageView* GetImageView(DictationButtonTray* tray) { @@ -110,6 +123,20 @@ void CheckDictationStatusAndUpdateIcon(DictationButtonTray* tray) { tray->CheckDictationStatusAndUpdateIcon(); } + void FocusTextInputClient() { + Shell::Get() + ->window_tree_host_manager() + ->input_method() + ->SetFocusedTextInputClient(fake_text_input_client_.get()); + } + void DetachTextInputClient() { + Shell::Get() + ->window_tree_host_manager() + ->input_method() + ->SetFocusedTextInputClient(nullptr); + } + + std::unique_ptr<ui::FakeTextInputClient> fake_text_input_client_; }; // Ensures that creation doesn't cause any crashes and adds the image icon. @@ -159,6 +186,8 @@ ASSERT_FALSE(controller->dictation_active()); ASSERT_FALSE(GetTray()->is_active()); + // In an input text area by default. + EXPECT_TRUE(GetTray()->GetEnabled()); Shell::Get()->accelerator_controller()->PerformActionIfEnabled( AcceleratorAction::TOGGLE_DICTATION, {}); @@ -171,6 +200,28 @@ EXPECT_FALSE(GetTray()->is_active()); } +TEST_F(DictationButtonTrayTest, DisabledWhenNoInputFocused) { + DetachTextInputClient(); + + AccessibilityControllerImpl* controller = + Shell::Get()->accessibility_controller(); + controller->dictation().SetEnabled(true); + DictationButtonTray* tray = GetTray(); + EXPECT_FALSE(tray->GetEnabled()); + + // Action doesn't work because disabled. + Shell::Get()->accelerator_controller()->PerformActionIfEnabled( + AcceleratorAction::TOGGLE_DICTATION, {}); + EXPECT_FALSE(controller->dictation_active()); + EXPECT_FALSE(tray->GetEnabled()); + + FocusTextInputClient(); + EXPECT_TRUE(tray->GetEnabled()); + + DetachTextInputClient(); + EXPECT_FALSE(tray->GetEnabled()); +} + // Base class for SODA tests of the dictation button tray. class DictationButtonTraySodaTest : public DictationButtonTrayTest { public: @@ -260,6 +311,12 @@ EXPECT_FALSE(tray->GetEnabled()); EXPECT_EQ(base::UTF8ToUTF16(kDisabledTooltip), image->GetTooltipText()); + // Enabled state doesn't change even if text input is focused. + DetachTextInputClient(); + EXPECT_FALSE(tray->GetEnabled()); + FocusTextInputClient(); + EXPECT_FALSE(tray->GetEnabled()); + // The tray icon should *not* be visible when the download is in progress. ProgressIndicatorWaiter().WaitForProgress(progress_indicator, 0.5f); EXPECT_TRUE(IsProgressIndicatorVisible());
diff --git a/ash/system/keyboard_brightness/keyboard_backlight_color_controller.cc b/ash/system/keyboard_brightness/keyboard_backlight_color_controller.cc index ed8732a..654a594 100644 --- a/ash/system/keyboard_brightness/keyboard_backlight_color_controller.cc +++ b/ash/system/keyboard_brightness/keyboard_backlight_color_controller.cc
@@ -86,22 +86,12 @@ void KeyboardBacklightColorController::OnActiveUserPrefServiceChanged( PrefService* pref_service) { const auto backlight_color = GetBacklightColor(GetActiveAccountId()); - // Wallpaper extracted color may not be available at this state. Instead of - // setting wallpaper color here, let |OnWallpaperColorsChanged| handles it - // when the color is available. - if (backlight_color == personalization_app::mojom::BacklightColor::kWallpaper) - return; DisplayBacklightColor(backlight_color); } void KeyboardBacklightColorController::OnUserSessionUpdated( const AccountId& account_id) { const auto backlight_color = GetBacklightColor(account_id); - // Wallpaper extracted color may not be available at this state. Instead of - // setting wallpaper color here, let |OnWallpaperColorsChanged| handles it - // when the color is available. - if (backlight_color == personalization_app::mojom::BacklightColor::kWallpaper) - return; DisplayBacklightColor(backlight_color); }
diff --git a/ash/system/keyboard_brightness/keyboard_backlight_color_controller_unittest.cc b/ash/system/keyboard_brightness/keyboard_backlight_color_controller_unittest.cc index 940a84ea..ca65ee0 100644 --- a/ash/system/keyboard_brightness/keyboard_backlight_color_controller_unittest.cc +++ b/ash/system/keyboard_brightness/keyboard_backlight_color_controller_unittest.cc
@@ -119,10 +119,11 @@ SimulateUserLogin(account_id_1); EXPECT_EQ(personalization_app::mojom::BacklightColor::kWallpaper, controller_->GetBacklightColor(account_id_1)); - // Expect the Wallpaper color to be not set. + // Expect the Wallpaper color to be set to the default as wallpaper color is + // not valid in this state. histogram_tester().ExpectBucketCount( - "Ash.Personalization.KeyboardBacklight.WallpaperColor.Valid", false, 0); - EXPECT_EQ(SK_ColorTRANSPARENT, displayed_color()); + "Ash.Personalization.KeyboardBacklight.WallpaperColor.Valid", false, 1); + EXPECT_EQ(kDefaultColor, displayed_color()); controller_->SetBacklightColor( personalization_app::mojom::BacklightColor::kBlue, account_id_1); @@ -148,10 +149,11 @@ SimulateUserLogin(account_id_1); EXPECT_EQ(personalization_app::mojom::BacklightColor::kWallpaper, controller_->GetBacklightColor(account_id_1)); - // Expect the Wallpaper color to be not set. + // Expect the Wallpaper color to be set to the default as wallpaper color is + // not valid in this state. histogram_tester().ExpectBucketCount( - "Ash.Personalization.KeyboardBacklight.WallpaperColor.Valid", false, 0); - EXPECT_EQ(SK_ColorTRANSPARENT, displayed_color()); + "Ash.Personalization.KeyboardBacklight.WallpaperColor.Valid", false, 1); + EXPECT_EQ(kDefaultColor, displayed_color()); controller_->SetBacklightColor( personalization_app::mojom::BacklightColor::kBlue, account_id_1);
diff --git a/ash/webui/personalization_app/resources/js/ambient/ambient_weather_element.ts b/ash/webui/personalization_app/resources/js/ambient/ambient_weather_element.ts index f56dd7d..b635b70a 100644 --- a/ash/webui/personalization_app/resources/js/ambient/ambient_weather_element.ts +++ b/ash/webui/personalization_app/resources/js/ambient/ambient_weather_element.ts
@@ -9,7 +9,7 @@ import '../../css/common.css.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/shared_style_css.m.js'; import {TemperatureUnit} from '../personalization_app.mojom-webui.js';
diff --git a/ash/webui/shimless_rma/resources/BUILD.gn b/ash/webui/shimless_rma/resources/BUILD.gn index e9f99d85..f4335c94 100644 --- a/ash/webui/shimless_rma/resources/BUILD.gn +++ b/ash/webui/shimless_rma/resources/BUILD.gn
@@ -232,7 +232,7 @@ ":shimless_rma_types", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button.m", - "//ui/webui/resources/cr_elements/cr_radio_group:cr_radio_group.m", + "//ui/webui/resources/cr_elements/cr_radio_group:cr_radio_group", "//ui/webui/resources/js:i18n_behavior.m", ] } @@ -388,7 +388,7 @@ ":mojo_interface_provider", ":shimless_rma_types", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - "//ui/webui/resources/cr_elements/cr_radio_group:cr_radio_group.m", + "//ui/webui/resources/cr_elements/cr_radio_group:cr_radio_group", ] }
diff --git a/ash/webui/shimless_rma/resources/onboarding_choose_destination_page.js b/ash/webui/shimless_rma/resources/onboarding_choose_destination_page.js index 3abdcf77..0bef7e0 100644 --- a/ash/webui/shimless_rma/resources/onboarding_choose_destination_page.js +++ b/ash/webui/shimless_rma/resources/onboarding_choose_destination_page.js
@@ -5,7 +5,7 @@ import './shimless_rma_shared_css.js'; import './base_page.js'; import '//resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import '//resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import '//resources/cr_elements/cr_radio_group/cr_radio_group.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/ash/webui/shimless_rma/resources/onboarding_choose_wipe_device_page.js b/ash/webui/shimless_rma/resources/onboarding_choose_wipe_device_page.js index baecd00..33a4db1 100644 --- a/ash/webui/shimless_rma/resources/onboarding_choose_wipe_device_page.js +++ b/ash/webui/shimless_rma/resources/onboarding_choose_wipe_device_page.js
@@ -6,7 +6,7 @@ import './shimless_rma_shared_css.js'; import '//resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import '//resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import '//resources/cr_elements/cr_radio_group/cr_radio_group.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java index 3819a80..873ca0d 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java +++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java
@@ -789,6 +789,7 @@ boolean success; boolean usedFallback = sAlwaysFallback && mFallbackServiceName != null; if (useStrongBinding) { + mStrongBindingCount++; success = mStrongBinding.bindServiceConnection(); } else { mModerateBindingCount++;
diff --git a/base/hash/md5_constexpr_internal.h b/base/hash/md5_constexpr_internal.h index d68816a..1261722d 100644 --- a/base/hash/md5_constexpr_internal.h +++ b/base/hash/md5_constexpr_internal.h
@@ -82,7 +82,7 @@ DCHECK_EQ(m % 64, 0u); if (i < n) { // Emit the message itself... - return data[i]; + return static_cast<uint8_t>(data[i]); } else if (i == n) { // ...followed by the end of message marker. return 0x80;
diff --git a/build/android/gyp/compile_java.py b/build/android/gyp/compile_java.py index 358f345f..ed3c9be 100755 --- a/build/android/gyp/compile_java.py +++ b/build/android/gyp/compile_java.py
@@ -471,7 +471,7 @@ # Use jar_path's directory to ensure paths are relative (needed for goma). temp_dir = jar_path + '.staging' - shutil.rmtree(temp_dir, True) + build_utils.DeleteDirectory(temp_dir) os.makedirs(temp_dir) info_file_context = None try:
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 759842b..0272bf8 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -1525,6 +1525,13 @@ "-Wno-ignored-pragma-optimize", ] + if (llvm_force_head_revision && !is_nacl) { + cflags += [ + # TODO(crbug.com/1352183) Evaluate and possibly enable. + "-Wno-bitfield-constant-conversion", + ] + } + if (!is_nacl) { cflags += [ # TODO(crbug.com/1343975) Evaluate and possibly enable.
diff --git a/cc/base/math_util.cc b/cc/base/math_util.cc index 7c700f83..e7f0e37e 100644 --- a/cc/base/math_util.cc +++ b/cc/base/math_util.cc
@@ -1017,7 +1017,7 @@ res->AppendInteger(gradient.angle()); res->AppendInteger(gradient.step_count()); for (size_t i = 0; i < gradient.step_count(); i++) { - res->AppendDouble(gradient.steps()[i].percent); + res->AppendDouble(gradient.steps()[i].fraction); res->AppendInteger(gradient.steps()[i].alpha); } res->EndArray();
diff --git a/cc/trees/property_tree_builder_unittest.cc b/cc/trees/property_tree_builder_unittest.cc index a5e1770..b3a537c 100644 --- a/cc/trees/property_tree_builder_unittest.cc +++ b/cc/trees/property_tree_builder_unittest.cc
@@ -764,7 +764,7 @@ child1->SetIsDrawable(true); gfx::LinearGradient gradient_mask(45); - gradient_mask.AddStep(50, 0x50); + gradient_mask.AddStep(.5, 0x50); child1->SetGradientMask(gradient_mask); // Without render surface. @@ -915,12 +915,12 @@ grand_child1->SetIsDrawable(true); gfx::LinearGradient gradient_mask1(30); - gradient_mask1.AddStep(50, 0x50); + gradient_mask1.AddStep(.5, 0x50); child1->SetGradientMask(gradient_mask1); gfx::LinearGradient gradient_mask2(45); gradient_mask2.AddStep(0, 0xFF); - gradient_mask2.AddStep(100, 0x0); + gradient_mask2.AddStep(1, 0x0); grand_child1->SetGradientMask(gradient_mask2); CommitAndActivate();
diff --git a/chrome/VERSION b/chrome/VERSION index 3462af25..187da01 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=106 MINOR=0 -BUILD=5234 +BUILD=5235 PATCH=0
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 23bd9f7..7c71dff90 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
@@ -49,6 +49,7 @@ import org.chromium.base.supplier.Supplier; import org.chromium.base.task.PostTask; import org.chromium.chrome.R; +import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate; import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider.CloseButtonPosition; import org.chromium.chrome.browser.compositor.bottombar.ephemeraltab.EphemeralTabCoordinator; import org.chromium.chrome.browser.crash.ChromePureJavaExceptionReporter; @@ -116,6 +117,7 @@ private final CustomTabLocationBar mLocationBar = new CustomTabLocationBar(); private LocationBarModel mLocationBarModel; + private BrowserStateBrowserControlsVisibilityDelegate mBrowserControlsVisibilityDelegate; /** * Whether to use the toolbar as handle to resize the Window height. @@ -226,15 +228,20 @@ * @param actionModeCallback Callback to handle changes in contextual action Modes. * @param modalDialogManagerSupplier Supplier of {@link ModalDialogManager}. * @param ephemeralTabCoordinatorSupplier Supplier of {@link EphemeralTabCoordinator}. + * @param controlsVisibilityDelegate {@link BrowserStateBrowserControlsVisibilityDelegate} to + * show / hide the browser control. Used to ensure toolbar is shown for a certain + * duration. * @return The LocationBar implementation for this CustomTabToolbar. */ public LocationBar createLocationBar(LocationBarModel locationBarModel, ActionMode.Callback actionModeCallback, Supplier<ModalDialogManager> modalDialogManagerSupplier, - Supplier<EphemeralTabCoordinator> ephemeralTabCoordinatorSupplier) { + Supplier<EphemeralTabCoordinator> ephemeralTabCoordinatorSupplier, + BrowserStateBrowserControlsVisibilityDelegate controlsVisibilityDelegate) { mLocationBarModel = locationBarModel; mLocationBar.init(locationBarModel, modalDialogManagerSupplier, ephemeralTabCoordinatorSupplier, actionModeCallback); + mBrowserControlsVisibilityDelegate = controlsVisibilityDelegate; return mLocationBar; } @@ -630,6 +637,7 @@ View.OnLongClickListener, ToolbarBrandingDelegate { private static final int TITLE_ANIM_DELAY_MS = 800; private static final int BRANDING_DELAY_MS = 1800; + private static final int MIN_URL_BAR_VISIBLE_TIME_POST_BRANDING_MS = 3000; private static final int STATE_DOMAIN_ONLY = 0; private static final int STATE_TITLE_ONLY = 1; @@ -741,6 +749,13 @@ mCurrentlyShowingBranding = false; recoverFromRegularState(); runAfterBrandingRunnables(); + + int token = mBrowserControlsVisibilityDelegate.showControlsPersistent(); + PostTask.postDelayedTask(UiThreadTaskTraits.USER_VISIBLE, + () + -> mBrowserControlsVisibilityDelegate.releasePersistentShowingToken( + token), + MIN_URL_BAR_VISIBLE_TIME_POST_BRANDING_MS); } private void cacheRegularState() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java index 45f71389..17268e6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
@@ -261,7 +261,7 @@ mHistoryClustersCoordinator = new HistoryClustersCoordinator( Profile.getLastUsedRegularProfile(), activity, TemplateUrlServiceFactory.get(), - historyClustersDelegate, ChromeAccessibilityUtil.get()); + historyClustersDelegate, ChromeAccessibilityUtil.get(), mSnackbarManager); } // 1. Create selectable components.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index 206a2d04..13807af 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -606,7 +606,7 @@ CustomTabToolbar customTabToolbar = ((CustomTabToolbar) toolbarLayout); mLocationBar = customTabToolbar.createLocationBar(mLocationBarModel, mActionModeController.getActionModeCallback(), modalDialogManagerSupplier, - mEphemeralTabCoordinatorSupplier); + mEphemeralTabCoordinatorSupplier, mControlsVisibilityDelegate); } else { OverrideUrlLoadingDelegate overrideUrlLoadingDelegate = (url, transition, postDataType, postData, incognito)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java index f0caeb17..ede8596 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
@@ -851,7 +851,7 @@ mHistoryClustersCoordinator = new HistoryClustersCoordinator(profile, mActivity, TemplateUrlServiceFactory.get(), historyClustersDelegate, - ChromeAccessibilityUtil.get()); + ChromeAccessibilityUtil.get(), mSnackbarManagerSupplier.get()); mHistoryClustersCoordinatorSupplier.set(mHistoryClustersCoordinator); } }
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 c6fb8fca4..112cf73 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
@@ -6,6 +6,7 @@ import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -28,6 +29,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.robolectric.Robolectric; +import org.robolectric.Shadows; import org.robolectric.annotation.Config; import org.robolectric.annotation.LooperMode; import org.robolectric.annotation.LooperMode.Mode; @@ -38,6 +40,7 @@ import org.chromium.base.task.test.ShadowPostTask.TestImpl; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.R; +import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate; import org.chromium.chrome.browser.customtabs.features.toolbar.CustomTabToolbar.CustomTabLocationBar; import org.chromium.chrome.browser.flags.CachedFeatureFlags; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -45,6 +48,8 @@ import org.chromium.ui.base.TestActivity; import org.chromium.url.JUnitTestGURLs; +import java.util.concurrent.TimeUnit; + /** * Tests AMP url handling in the CustomTab Toolbar. */ @@ -61,6 +66,8 @@ ActionMode.Callback mActionModeCallback; @Mock CustomTabToolbarAnimationDelegate mAnimationDelegate; + @Mock + BrowserStateBrowserControlsVisibilityDelegate mControlsVisibleDelegate; private Activity mActivity; private CustomTabLocationBar mLocationBar; @@ -85,8 +92,8 @@ mActivity = Robolectric.buildActivity(TestActivity.class).get(); CustomTabToolbar toolbar = (CustomTabToolbar) LayoutInflater.from(mActivity).inflate( R.layout.custom_tabs_toolbar, null, false); - mLocationBar = (CustomTabLocationBar) toolbar.createLocationBar( - mLocationBarModel, mActionModeCallback, () -> null, () -> null); + mLocationBar = (CustomTabLocationBar) toolbar.createLocationBar(mLocationBarModel, + mActionModeCallback, () -> null, () -> null, mControlsVisibleDelegate); mUrlBar = toolbar.findViewById(R.id.url_bar); mTitleBar = toolbar.findViewById(R.id.title_bar); mLocationBar.setAnimDelegateForTesting(mAnimationDelegate); @@ -177,6 +184,7 @@ assertUrlAndTitleVisible(/*titleVisible=*/false, /*urlVisible=*/true); assertEquals("Runnables queue should be empty after reset to regular toolbar", 0, postBrandingRunnableCounts()); + verifyBrowserControlVisibleForRequiredDuration(); } @Test @@ -205,6 +213,7 @@ assertUrlAndTitleVisible(/*titleVisible=*/false, /*urlVisible=*/true); assertEquals("Runnables queue should be empty after reset to regular toolbar", 0, postBrandingRunnableCounts()); + verifyBrowserControlVisibleForRequiredDuration(); } private int postBrandingRunnableCounts() { @@ -226,4 +235,14 @@ "Title visibility is off.", expectedTitleVisibility, mTitleBar.getVisibility()); assertEquals("URL bar visibility is off.", expectedUrlVisibility, mUrlBar.getVisibility()); } + + private void verifyBrowserControlVisibleForRequiredDuration() { + // Verify browser control is visible for required duration (3000ms). + ShadowLooper looper = Shadows.shadowOf(Looper.getMainLooper()); + verify(mControlsVisibleDelegate).showControlsPersistent(); + looper.idleFor(2999, TimeUnit.MILLISECONDS); + verify(mControlsVisibleDelegate, never()).releasePersistentShowingToken(anyInt()); + looper.idleFor(1, TimeUnit.MILLISECONDS); + verify(mControlsVisibleDelegate).releasePersistentShowingToken(anyInt()); + } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinatorTest.java index bba917d..86ff4fe 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinatorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinatorTest.java
@@ -16,6 +16,9 @@ import static org.robolectric.Shadows.shadowOf; import android.app.Activity; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; import android.content.Intent; import android.view.MenuItem; import android.view.View; @@ -53,11 +56,14 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabCreator; +import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.components.browser_ui.widget.selectable_list.SelectableListLayout; import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate; import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.favicon.LargeIconBridgeJni; import org.chromium.components.search_engines.TemplateUrlService; +import org.chromium.ui.base.Clipboard; +import org.chromium.ui.base.ClipboardImpl; import org.chromium.ui.display.DisplayAndroidManager; import org.chromium.ui.util.AccessibilityUtil; import org.chromium.url.GURL; @@ -181,6 +187,8 @@ private HistoryClustersMetricsLogger mMetricsLogger; @Mock private AccessibilityUtil mAccessibilityUtil; + @Mock + private SnackbarManager mSnackbarManager; private ActivityScenario<ChromeTabbedActivity> mActivityScenario; private HistoryClustersCoordinator mHistoryClustersCoordinator; @@ -219,7 +227,7 @@ mActivity = activity; mHistoryClustersCoordinator = new HistoryClustersCoordinator(mProfile, activity, mTemplateUrlService, mHistoryClustersDelegate, mMetricsLogger, - mSelectionDelegate, mAccessibilityUtil); + mSelectionDelegate, mAccessibilityUtil, mSnackbarManager); }); } @@ -364,6 +372,26 @@ } @Test + public void testCopyMenuItem() { + final ClipboardManager clipboardManager = + (ClipboardManager) mActivity.getSystemService(Context.CLIPBOARD_SERVICE); + assertNotNull(clipboardManager); + ((ClipboardImpl) Clipboard.getInstance()) + .overrideClipboardManagerForTesting(clipboardManager); + clipboardManager.setPrimaryClip(ClipData.newPlainText(null, "dummy_val")); + doReturn("http://spec1.com").when(mGurl1).getSpec(); + + HistoryClustersToolbar toolbar = mHistoryClustersCoordinator.getActivityContentView() + .findViewById(R.id.selectable_list) + .findViewById(R.id.action_bar); + + mSelectionDelegate.setSelectedItems(new HashSet<>(Arrays.asList(mVisit1))); + mHistoryClustersCoordinator.onMenuItemClick( + toolbar.getMenu().findItem(R.id.selection_mode_copy_link)); + assertEquals(mVisit1.getNormalizedUrl().getSpec(), clipboardManager.getText()); + } + + @Test public void testSetQueryState() { mHistoryClustersCoordinator.inflateActivityView(); mHistoryClustersCoordinator.setInitialQuery(QueryState.forQuery("dogs", ""));
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 5223c1c..da934f52 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -7083,6 +7083,9 @@ <message name="IDS_READ_ANYTHING_INCREASE_FONT_SIZE_BUTTON_LABEL" desc="Accessibility label for the increase font size button of the Read Anything feature." translateable="false"> Increase font-size </message> + <message name="IDS_READ_ANYTHING_COLORS_COMBOBOX_LABEL" desc="Accessibility label for the colors combobox of the Read Anything feature." translateable="false"> + Theme + </message> <!-- User note strings --> <message name="IDS_USER_NOTE_TITLE" desc="Title of the User note feature, which gives users access to private user notes.">
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 0d9e9d2..09cf0e58 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -4029,6 +4029,8 @@ "performance_manager/mechanisms/page_discarder.h", "performance_manager/mechanisms/page_loader.cc", "performance_manager/mechanisms/page_loader.h", + "performance_manager/metrics/metrics_provider.cc", + "performance_manager/metrics/metrics_provider.h", "performance_manager/persistence/site_data/site_data_cache_facade.cc", "performance_manager/persistence/site_data/site_data_cache_facade.h", "performance_manager/persistence/site_data/site_data_cache_facade_factory.cc",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 0d9d09b..60ff85eb 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -500,6 +500,7 @@ "+chrome/browser/performance_manager/test_support", "+chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.h", "+chrome/browser/performance_manager/chrome_content_browser_client_performance_manager_part.h", + "+chrome/browser/performance_manager/metrics/metrics_provider.h", "+chrome/browser/performance_manager/policies/policy_features.h", # Explicitly disallow using SyncMessageFilter to prevent browser from
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 697f743..0da4658 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -9067,6 +9067,13 @@ password_manager::features::kBiometricAuthenticationForFilling)}, #endif +#if BUILDFLAG(IS_ANDROID) + {"reduce-gpu-priority-on-background", + flag_descriptions::kReduceGpuPriorityOnBackgroundName, + flag_descriptions::kReduceGpuPriorityOnBackgroundDescription, kOsAndroid, + FEATURE_VALUE_TYPE(::features::kReduceGpuPriorityOnBackground)}, +#endif + // NOTE: Adding a new flag requires adding a corresponding entry to enum // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/accessibility/accessibility_labels_service_factory.cc b/chrome/browser/accessibility/accessibility_labels_service_factory.cc index 8b5fa19..dec36626 100644 --- a/chrome/browser/accessibility/accessibility_labels_service_factory.cc +++ b/chrome/browser/accessibility/accessibility_labels_service_factory.cc
@@ -36,7 +36,7 @@ AccessibilityLabelsServiceFactory::AccessibilityLabelsServiceFactory() : ProfileKeyedServiceFactory( "AccessibilityLabelsService", - ProfileSelections::BuildServicesRedirectedToOriginal()) {} + ProfileSelections::BuildRedirectedInIncognito()) {} AccessibilityLabelsServiceFactory::~AccessibilityLabelsServiceFactory() {}
diff --git a/chrome/browser/accessibility/live_caption_controller_factory.cc b/chrome/browser/accessibility/live_caption_controller_factory.cc index a210cbf..2e0ec31 100644 --- a/chrome/browser/accessibility/live_caption_controller_factory.cc +++ b/chrome/browser/accessibility/live_caption_controller_factory.cc
@@ -34,7 +34,7 @@ LiveCaptionControllerFactory::LiveCaptionControllerFactory() : ProfileKeyedServiceFactory( "LiveCaptionController", - ProfileSelections::BuildServicesRedirectedToOriginal()) {} + ProfileSelections::BuildRedirectedInIncognito()) {} LiveCaptionControllerFactory::~LiveCaptionControllerFactory() = default;
diff --git a/chrome/browser/android/omnibox/autocomplete_controller_android.cc b/chrome/browser/android/omnibox/autocomplete_controller_android.cc index 7127216c..7aef586 100644 --- a/chrome/browser/android/omnibox/autocomplete_controller_android.cc +++ b/chrome/browser/android/omnibox/autocomplete_controller_android.cc
@@ -481,7 +481,7 @@ AutocompleteControllerAndroid::Factory::Factory() : ProfileKeyedServiceFactory( "AutocompleteControllerAndroid", - ProfileSelections::BuildServicesForAllProfiles()) { + ProfileSelections::BuildForRegularAndIncognito()) { DependsOn(TemplateURLServiceFactory::GetInstance()); DependsOn(ShortcutsBackendFactory::GetInstance()); }
diff --git a/chrome/browser/android/reading_list/reading_list_manager_factory.cc b/chrome/browser/android/reading_list/reading_list_manager_factory.cc index 44935da..6e95e7c 100644 --- a/chrome/browser/android/reading_list/reading_list_manager_factory.cc +++ b/chrome/browser/android/reading_list/reading_list_manager_factory.cc
@@ -26,7 +26,7 @@ ReadingListManagerFactory::ReadingListManagerFactory() : ProfileKeyedServiceFactory( "ReadingListManager", - ProfileSelections::BuildServicesRedirectedToOriginal()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(ReadingListModelFactory::GetInstance()); }
diff --git a/chrome/browser/android/reading_list/reading_list_notification_service_factory.cc b/chrome/browser/android/reading_list/reading_list_notification_service_factory.cc index d3d0d99..003a3ab 100644 --- a/chrome/browser/android/reading_list/reading_list_notification_service_factory.cc +++ b/chrome/browser/android/reading_list/reading_list_notification_service_factory.cc
@@ -33,7 +33,7 @@ ReadingListNotificationServiceFactory::ReadingListNotificationServiceFactory() : ProfileKeyedServiceFactory( "ReadingListNotificationService", - ProfileSelections::BuildServicesRedirectedToOriginal()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(ReadingListModelFactory::GetInstance()); DependsOn(NotificationScheduleServiceFactory::GetInstance()); }
diff --git a/chrome/browser/android/webapk/webapk_install_service_factory.cc b/chrome/browser/android/webapk/webapk_install_service_factory.cc index 32ba69e..9c0d9b0 100644 --- a/chrome/browser/android/webapk/webapk_install_service_factory.cc +++ b/chrome/browser/android/webapk/webapk_install_service_factory.cc
@@ -21,7 +21,7 @@ WebApkInstallServiceFactory::WebApkInstallServiceFactory() : ProfileKeyedServiceFactory( "WebApkInstallService", - ProfileSelections::BuildServicesRedirectedToOriginal()) {} + ProfileSelections::BuildRedirectedInIncognito()) {} WebApkInstallServiceFactory::~WebApkInstallServiceFactory() {}
diff --git a/chrome/browser/apps/platform_apps/app_load_service_factory.cc b/chrome/browser/apps/platform_apps/app_load_service_factory.cc index d2bb0c9e..a3cb3f3 100644 --- a/chrome/browser/apps/platform_apps/app_load_service_factory.cc +++ b/chrome/browser/apps/platform_apps/app_load_service_factory.cc
@@ -29,7 +29,7 @@ AppLoadServiceFactory::AppLoadServiceFactory() : ProfileKeyedServiceFactory( "AppLoadService", - ProfileSelections::BuildServicesRedirectedToOriginal()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(extensions::AppWindowRegistry::Factory::GetInstance()); DependsOn(extensions::ExtensionPrefsFactory::GetInstance()); DependsOn(extensions::ExtensionRegistryFactory::GetInstance());
diff --git a/chrome/browser/apps/platform_apps/app_termination_observer.cc b/chrome/browser/apps/platform_apps/app_termination_observer.cc index 1cf307e..171e967 100644 --- a/chrome/browser/apps/platform_apps/app_termination_observer.cc +++ b/chrome/browser/apps/platform_apps/app_termination_observer.cc
@@ -32,7 +32,7 @@ AppTerminationObserverFactory::AppTerminationObserverFactory() : ProfileKeyedServiceFactory( "AppTerminationObserver", - ProfileSelections::BuildServicesRedirectedToOriginal()) {} + ProfileSelections::BuildRedirectedInIncognito()) {} KeyedService* AppTerminationObserverFactory::BuildServiceInstanceFor( content::BrowserContext* browser_context) const {
diff --git a/chrome/browser/ash/apps/apk_web_app_service_factory.cc b/chrome/browser/ash/apps/apk_web_app_service_factory.cc index 9e5d533..3dbc440 100644 --- a/chrome/browser/ash/apps/apk_web_app_service_factory.cc +++ b/chrome/browser/ash/apps/apk_web_app_service_factory.cc
@@ -31,7 +31,7 @@ ApkWebAppServiceFactory::ApkWebAppServiceFactory() : ProfileKeyedServiceFactory( "ApkWebAppService", - ProfileSelections::BuildServicesRedirectedToOriginal()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(ArcAppListPrefsFactory::GetInstance()); DependsOn(web_app::WebAppProviderFactory::GetInstance()); }
diff --git a/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service.cc b/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service.cc index 5fe3843..4ba2e993 100644 --- a/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service.cc +++ b/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service.cc
@@ -70,7 +70,7 @@ CertStoreServiceFactory() : ProfileKeyedServiceFactory( "CertStoreService", - ProfileSelections::BuildServicesForAllProfiles()) { + ProfileSelections::BuildForRegularAndIncognito()) { DependsOn(NssServiceFactory::GetInstance()); }
diff --git a/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map_factory.cc b/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map_factory.cc index 0be4d4b..baf5307 100644 --- a/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map_factory.cc +++ b/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map_factory.cc
@@ -22,7 +22,7 @@ ArcDocumentsProviderRootMapFactory::ArcDocumentsProviderRootMapFactory() : ProfileKeyedServiceFactory( "ArcDocumentsProviderRootMap", - ProfileSelections::BuildServicesRedirectedToOriginal()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(ArcFileSystemOperationRunner::GetFactory()); }
diff --git a/chrome/browser/ash/drive/drive_integration_service.cc b/chrome/browser/ash/drive/drive_integration_service.cc index 9969c14..d65d903 100644 --- a/chrome/browser/ash/drive/drive_integration_service.cc +++ b/chrome/browser/ash/drive/drive_integration_service.cc
@@ -1434,7 +1434,7 @@ DriveIntegrationServiceFactory::DriveIntegrationServiceFactory() : ProfileKeyedServiceFactory( "DriveIntegrationService", - ProfileSelections::BuildServicesRedirectedToOriginal()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(IdentityManagerFactory::GetInstance()); DependsOn(DriveNotificationManagerFactory::GetInstance()); DependsOn(DownloadCoreServiceFactory::GetInstance());
diff --git a/chrome/browser/ash/file_manager/volume_manager_factory.cc b/chrome/browser/ash/file_manager/volume_manager_factory.cc index b5687be..d12be46 100644 --- a/chrome/browser/ash/file_manager/volume_manager_factory.cc +++ b/chrome/browser/ash/file_manager/volume_manager_factory.cc
@@ -51,7 +51,7 @@ : ProfileKeyedServiceFactory( "VolumeManagerFactory", // Explicitly allow this manager in guest login mode. - ProfileSelections::BuildServicesForAllProfiles()) { + ProfileSelections::BuildForRegularAndIncognito()) { DependsOn(drive::DriveIntegrationServiceFactory::GetInstance()); DependsOn(ash::file_system_provider::ServiceFactory::GetInstance()); }
diff --git a/chrome/browser/ash/file_system_provider/service_factory.cc b/chrome/browser/ash/file_system_provider/service_factory.cc index 555e5ef4..51b57a7f 100644 --- a/chrome/browser/ash/file_system_provider/service_factory.cc +++ b/chrome/browser/ash/file_system_provider/service_factory.cc
@@ -33,7 +33,7 @@ ServiceFactory::ServiceFactory() : ProfileKeyedServiceFactory( "Service", - ProfileSelections::BuildServicesRedirectedToOriginal()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(extensions::ExtensionRegistryFactory::GetInstance()); DependsOn(extensions::ExtensionSystemFactory::GetInstance()); DependsOn(NotificationDisplayServiceFactory::GetInstance());
diff --git a/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc b/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc index 8602cf4..e82ba577 100644 --- a/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc +++ b/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc
@@ -112,7 +112,7 @@ const test::UIPath kArcTosBackButton = {kArcTosId, "arcTosBackButton"}; const test::UIPath kArcTosNextButton = {kArcTosId, "arcTosNextButton"}; -const test::UIPath kCCLoadedDialog = {kConsolidatedConsentId, "loadedDialog"}; +const test::UIPath kCCAcceptButton = {kConsolidatedConsentId, "acceptButton"}; const test::UIPath kCCArcTosLink = {kConsolidatedConsentId, "arcTosLink"}; const test::UIPath kCCBackButton = {kConsolidatedConsentId, "backButton"}; @@ -316,11 +316,12 @@ } void WaitForConsolidatedConsentScreen() { - OobeScreenWaiter(ConsolidatedConsentScreenView::kScreenId).Wait(); - test::OobeJS().CreateVisibilityWaiter(true, kCCLoadedDialog)->Wait(); + test::WaitForConsolidatedConsentScreen(); // Make sure that ARC ToS link is visible. test::OobeJS().ExpectVisiblePath(kCCArcTosLink); + test::OobeJS().CreateVisibilityWaiter(true, kCCAcceptButton)->Wait(); + test::OobeJS().ExpectVisiblePath(kCCAcceptButton); } void AcceptArcTos() { @@ -488,9 +489,14 @@ IsConfirmationDialogHidden(); } -// TODO(crbug.com/1341234): flaky. +// TODO(crbug.com/1150349): Flaky on ChromeOS ASAN. +#if defined(ADDRESS_SANITIZER) +#define MAYBE_OnlineSetupFlowSuccess DISABLED_OnlineSetupFlowSuccess +#else +#define MAYBE_OnlineSetupFlowSuccess OnlineSetupFlowSuccess +#endif IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, - DISABLED_OnlineSetupFlowSuccess) { + MAYBE_OnlineSetupFlowSuccess) { // Simulate successful online setup. enrollment_helper_.ExpectEnrollmentMode( policy::EnrollmentConfig::MODE_ATTESTATION);
diff --git a/chrome/browser/ash/login/easy_unlock/easy_unlock_tpm_key_manager_factory.cc b/chrome/browser/ash/login/easy_unlock/easy_unlock_tpm_key_manager_factory.cc index 30a56c6..8c38752 100644 --- a/chrome/browser/ash/login/easy_unlock/easy_unlock_tpm_key_manager_factory.cc +++ b/chrome/browser/ash/login/easy_unlock/easy_unlock_tpm_key_manager_factory.cc
@@ -53,7 +53,7 @@ EasyUnlockTpmKeyManagerFactory::EasyUnlockTpmKeyManagerFactory() : ProfileKeyedServiceFactory( "EasyUnlockTpmKeyManager", - ProfileSelections::BuildServicesRedirectedToOriginal()) {} + ProfileSelections::BuildRedirectedInIncognito()) {} EasyUnlockTpmKeyManagerFactory::~EasyUnlockTpmKeyManagerFactory() {}
diff --git a/chrome/browser/ash/login/security_token_session_controller_factory.cc b/chrome/browser/ash/login/security_token_session_controller_factory.cc index d4d12c1e..695a2af 100644 --- a/chrome/browser/ash/login/security_token_session_controller_factory.cc +++ b/chrome/browser/ash/login/security_token_session_controller_factory.cc
@@ -20,7 +20,7 @@ SecurityTokenSessionControllerFactory::SecurityTokenSessionControllerFactory() : ProfileKeyedServiceFactory( "SecurityTokenSessionController", - ProfileSelections::BuildServicesRedirectedToOriginal()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(chromeos::CertificateProviderServiceFactory::GetInstance()); }
diff --git a/chrome/browser/ash/login/signin_partition_manager.cc b/chrome/browser/ash/login/signin_partition_manager.cc index c87d69a..96a1c18 100644 --- a/chrome/browser/ash/login/signin_partition_manager.cc +++ b/chrome/browser/ash/login/signin_partition_manager.cc
@@ -186,7 +186,7 @@ SigninPartitionManager::Factory::Factory() : ProfileKeyedServiceFactory( "SigninPartitionManager", - ProfileSelections::BuildServicesForAllProfiles()) {} + ProfileSelections::BuildForRegularAndIncognito()) {} SigninPartitionManager::Factory::~Factory() = default;
diff --git a/chrome/browser/ash/platform_keys/platform_keys_service_factory.cc b/chrome/browser/ash/platform_keys/platform_keys_service_factory.cc index f93f887..b63b2b9 100644 --- a/chrome/browser/ash/platform_keys/platform_keys_service_factory.cc +++ b/chrome/browser/ash/platform_keys/platform_keys_service_factory.cc
@@ -171,7 +171,7 @@ PlatformKeysServiceFactory::PlatformKeysServiceFactory() : ProfileKeyedServiceFactory( "PlatformKeysService", - ProfileSelections::BuildServicesRedirectedToOriginal()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(NssServiceFactory::GetInstance()); }
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_installer_factory.cc b/chrome/browser/ash/plugin_vm/plugin_vm_installer_factory.cc index ec4df1ec..b4eb7771 100644 --- a/chrome/browser/ash/plugin_vm/plugin_vm_installer_factory.cc +++ b/chrome/browser/ash/plugin_vm/plugin_vm_installer_factory.cc
@@ -24,7 +24,7 @@ PluginVmInstallerFactory::PluginVmInstallerFactory() : ProfileKeyedServiceFactory( "PluginVmInstaller", - ProfileSelections::BuildServicesRedirectedToOriginal()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(BackgroundDownloadServiceFactory::GetInstance()); }
diff --git a/chrome/browser/ash/policy/core/device_policy_decoder.cc b/chrome/browser/ash/policy/core/device_policy_decoder.cc index 61298b6..47bda04 100644 --- a/chrome/browser/ash/policy/core/device_policy_decoder.cc +++ b/chrome/browser/ash/policy/core/device_policy_decoder.cc
@@ -366,6 +366,10 @@ POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD, base::Value(container.transfer_saml_cookies()), nullptr); } + } + + if (policy.has_saml_username()) { + const em::SAMLUsernameProto& container(policy.saml_username()); if (container.has_url_parameter_to_autofill_saml_username()) { policies->Set( key::kDeviceAutofillSAMLUsername, POLICY_LEVEL_MANDATORY,
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 a9dea9d..3d537514 100644 --- a/chrome/browser/ash/policy/core/device_policy_decoder_unittest.cc +++ b/chrome/browser/ash/policy/core/device_policy_decoder_unittest.cc
@@ -416,7 +416,7 @@ key::kDeviceAutofillSAMLUsername); base::Value autofill_saml_username_value("login_hint"); - device_policy.mutable_saml_settings() + device_policy.mutable_saml_username() ->set_url_parameter_to_autofill_saml_username( autofill_saml_username_value.GetString());
diff --git a/chrome/browser/ash/printing/cups_print_job_manager_factory.cc b/chrome/browser/ash/printing/cups_print_job_manager_factory.cc index a694398..90889b9 100644 --- a/chrome/browser/ash/printing/cups_print_job_manager_factory.cc +++ b/chrome/browser/ash/printing/cups_print_job_manager_factory.cc
@@ -32,7 +32,7 @@ CupsPrintJobManagerFactory::CupsPrintJobManagerFactory() : ProfileKeyedServiceFactory( "CupsPrintJobManagerFactory", - ProfileSelections::BuildServicesRedirectedToOriginal()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(SyncedPrintersManagerFactory::GetInstance()); DependsOn(CupsPrintersManagerFactory::GetInstance()); }
diff --git a/chrome/browser/ash/printing/oauth2/authorization_zones_manager_factory.cc b/chrome/browser/ash/printing/oauth2/authorization_zones_manager_factory.cc index 7b9a84f6..a43dd31 100644 --- a/chrome/browser/ash/printing/oauth2/authorization_zones_manager_factory.cc +++ b/chrome/browser/ash/printing/oauth2/authorization_zones_manager_factory.cc
@@ -30,7 +30,7 @@ AuthorizationZonesManagerFactory::AuthorizationZonesManagerFactory() : ProfileKeyedServiceFactory( "AuthorizationZonesManagerFactory", - ProfileSelections::BuildServicesRedirectedToOriginal()) {} + ProfileSelections::BuildRedirectedInIncognito()) {} AuthorizationZonesManagerFactory::~AuthorizationZonesManagerFactory() = default;
diff --git a/chrome/browser/ash/printing/print_management/printing_manager_factory.cc b/chrome/browser/ash/printing/print_management/printing_manager_factory.cc index 59d3d1e..54b7cc1 100644 --- a/chrome/browser/ash/printing/print_management/printing_manager_factory.cc +++ b/chrome/browser/ash/printing/print_management/printing_manager_factory.cc
@@ -32,7 +32,7 @@ PrintingManagerFactory::PrintingManagerFactory() : ProfileKeyedServiceFactory( "PrintingManager", - ProfileSelections::BuildServicesRedirectedToOriginal()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(PrintJobHistoryServiceFactory::GetInstance()); DependsOn(HistoryServiceFactory::GetInstance()); DependsOn(CupsPrintJobManagerFactory::GetInstance());
diff --git a/chrome/browser/ash/printing/printer_event_tracker_factory.cc b/chrome/browser/ash/printing/printer_event_tracker_factory.cc index 38f612f4..812c10d 100644 --- a/chrome/browser/ash/printing/printer_event_tracker_factory.cc +++ b/chrome/browser/ash/printing/printer_event_tracker_factory.cc
@@ -31,7 +31,7 @@ PrinterEventTrackerFactory::PrinterEventTrackerFactory() : ProfileKeyedServiceFactory( "PrinterEventTracker", - ProfileSelections::BuildServicesForAllProfiles()) {} + ProfileSelections::BuildForRegularAndIncognito()) {} PrinterEventTrackerFactory::~PrinterEventTrackerFactory() = default; void PrinterEventTrackerFactory::SetLogging(bool enabled) {
diff --git a/chrome/browser/ash/printing/synced_printers_manager_factory.cc b/chrome/browser/ash/printing/synced_printers_manager_factory.cc index 110c31e..a76551f 100644 --- a/chrome/browser/ash/printing/synced_printers_manager_factory.cc +++ b/chrome/browser/ash/printing/synced_printers_manager_factory.cc
@@ -42,7 +42,7 @@ SyncedPrintersManagerFactory::SyncedPrintersManagerFactory() : ProfileKeyedServiceFactory( "SyncedPrintersManager", - ProfileSelections::BuildServicesRedirectedToOriginal()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(ModelTypeStoreServiceFactory::GetInstance()); }
diff --git a/chrome/browser/ash/scanning/scan_service_factory.cc b/chrome/browser/ash/scanning/scan_service_factory.cc index 1dc3069..17e8c87 100644 --- a/chrome/browser/ash/scanning/scan_service_factory.cc +++ b/chrome/browser/ash/scanning/scan_service_factory.cc
@@ -54,7 +54,7 @@ ScanServiceFactory::ScanServiceFactory() : ProfileKeyedServiceFactory( "ScanService", - ProfileSelections::BuildServicesRedirectedToOriginal()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(LorgnetteScannerManagerFactory::GetInstance()); DependsOn(HoldingSpaceKeyedServiceFactory::GetInstance()); }
diff --git a/chrome/browser/ash/smb_client/smb_service_factory.cc b/chrome/browser/ash/smb_client/smb_service_factory.cc index 3a6571dc..2a4a322 100644 --- a/chrome/browser/ash/smb_client/smb_service_factory.cc +++ b/chrome/browser/ash/smb_client/smb_service_factory.cc
@@ -48,7 +48,7 @@ SmbServiceFactory::SmbServiceFactory() : ProfileKeyedServiceFactory( /*name=*/"SmbService", - ProfileSelections::BuildServicesRedirectedToOriginal()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(file_system_provider::ServiceFactory::GetInstance()); DependsOn(AuthPolicyCredentialsManagerFactory::GetInstance()); DependsOn(KerberosCredentialsManagerFactory::GetInstance());
diff --git a/chrome/browser/assist_ranker/assist_ranker_service_factory.cc b/chrome/browser/assist_ranker/assist_ranker_service_factory.cc index 698853e..2d5a580f 100644 --- a/chrome/browser/assist_ranker/assist_ranker_service_factory.cc +++ b/chrome/browser/assist_ranker/assist_ranker_service_factory.cc
@@ -6,9 +6,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/net/system_network_context_manager.h" -#include "chrome/browser/profiles/incognito_helpers.h" #include "components/assist_ranker/assist_ranker_service_impl.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/keyed_service/core/keyed_service.h" #include "content/public/browser/browser_context.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -28,9 +26,9 @@ } AssistRankerServiceFactory::AssistRankerServiceFactory() - : BrowserContextKeyedServiceFactory( + : ProfileKeyedServiceFactory( "AssistRankerService", - BrowserContextDependencyManager::GetInstance()) {} + ProfileSelections::BuildRedirectedInIncognito()) {} AssistRankerServiceFactory::~AssistRankerServiceFactory() {} @@ -42,9 +40,4 @@ ->GetSharedURLLoaderFactory()); } -content::BrowserContext* AssistRankerServiceFactory::GetBrowserContextToUse( - content::BrowserContext* context) const { - return chrome::GetBrowserContextRedirectedInIncognito(context); -} - } // namespace assist_ranker
diff --git a/chrome/browser/assist_ranker/assist_ranker_service_factory.h b/chrome/browser/assist_ranker/assist_ranker_service_factory.h index 97bd0dd5..f59a340 100644 --- a/chrome/browser/assist_ranker/assist_ranker_service_factory.h +++ b/chrome/browser/assist_ranker/assist_ranker_service_factory.h
@@ -6,7 +6,7 @@ #define CHROME_BROWSER_ASSIST_RANKER_ASSIST_RANKER_SERVICE_FACTORY_H_ #include "base/memory/singleton.h" -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" namespace content { class BrowserContext; @@ -18,7 +18,7 @@ namespace assist_ranker { -class AssistRankerServiceFactory : public BrowserContextKeyedServiceFactory { +class AssistRankerServiceFactory : public ProfileKeyedServiceFactory { public: static AssistRankerServiceFactory* GetInstance(); static AssistRankerService* GetForBrowserContext( @@ -37,8 +37,6 @@ // BrowserContextKeyedServiceFactory: KeyedService* BuildServiceInstanceFor( content::BrowserContext* context) const override; - content::BrowserContext* GetBrowserContextToUse( - content::BrowserContext* context) const override; }; } // namespace assist_ranker
diff --git a/chrome/browser/autocomplete/autocomplete_classifier_factory.cc b/chrome/browser/autocomplete/autocomplete_classifier_factory.cc index 16ccca1..fd72d04 100644 --- a/chrome/browser/autocomplete/autocomplete_classifier_factory.cc +++ b/chrome/browser/autocomplete/autocomplete_classifier_factory.cc
@@ -11,10 +11,8 @@ #include "chrome/browser/autocomplete/in_memory_url_index_factory.h" #include "chrome/browser/autocomplete/remote_suggestions_service_factory.h" #include "chrome/browser/autocomplete/shortcuts_backend_factory.h" -#include "chrome/browser/profiles/incognito_helpers.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search_engines/template_url_service_factory.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/omnibox/browser/autocomplete_classifier.h" #include "components/omnibox/browser/autocomplete_controller.h" #include "extensions/buildflags/buildflags.h" @@ -48,9 +46,9 @@ } AutocompleteClassifierFactory::AutocompleteClassifierFactory() - : BrowserContextKeyedServiceFactory( - "AutocompleteClassifier", - BrowserContextDependencyManager::GetInstance()) { + : ProfileKeyedServiceFactory( + "AutocompleteClassifier", + ProfileSelections::BuildRedirectedInIncognito()) { #if BUILDFLAG(ENABLE_EXTENSIONS) DependsOn( extensions::ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); @@ -64,11 +62,6 @@ AutocompleteClassifierFactory::~AutocompleteClassifierFactory() { } -content::BrowserContext* AutocompleteClassifierFactory::GetBrowserContextToUse( - content::BrowserContext* context) const { - return chrome::GetBrowserContextRedirectedInIncognito(context); -} - bool AutocompleteClassifierFactory::ServiceIsNULLWhileTesting() const { return true; }
diff --git a/chrome/browser/autocomplete/autocomplete_classifier_factory.h b/chrome/browser/autocomplete/autocomplete_classifier_factory.h index 7e8a3f32..6b05499f 100644 --- a/chrome/browser/autocomplete/autocomplete_classifier_factory.h +++ b/chrome/browser/autocomplete/autocomplete_classifier_factory.h
@@ -8,14 +8,14 @@ #include <memory> #include "base/memory/singleton.h" -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" class AutocompleteClassifier; class Profile; // Singleton that owns all AutocompleteClassifiers and associates them with // Profiles. -class AutocompleteClassifierFactory : public BrowserContextKeyedServiceFactory { +class AutocompleteClassifierFactory : public ProfileKeyedServiceFactory { public: // Returns the AutocompleteClassifier for |profile|. static AutocompleteClassifier* GetForProfile(Profile* profile); @@ -36,8 +36,6 @@ ~AutocompleteClassifierFactory() override; // BrowserContextKeyedServiceFactory: - content::BrowserContext* GetBrowserContextToUse( - content::BrowserContext* context) const override; bool ServiceIsNULLWhileTesting() const override; KeyedService* BuildServiceInstanceFor( content::BrowserContext* profile) const override;
diff --git a/chrome/browser/autocomplete/document_suggestions_service_factory.cc b/chrome/browser/autocomplete/document_suggestions_service_factory.cc index be19b43..b7422bc 100644 --- a/chrome/browser/autocomplete/document_suggestions_service_factory.cc +++ b/chrome/browser/autocomplete/document_suggestions_service_factory.cc
@@ -7,7 +7,6 @@ #include "base/memory/singleton.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/omnibox/browser/document_suggestions_service.h" #include "content/public/browser/storage_partition.h" @@ -37,9 +36,7 @@ } DocumentSuggestionsServiceFactory::DocumentSuggestionsServiceFactory() - : BrowserContextKeyedServiceFactory( - "DocumentSuggestionsService", - BrowserContextDependencyManager::GetInstance()) { + : ProfileKeyedServiceFactory("DocumentSuggestionsService") { DependsOn(IdentityManagerFactory::GetInstance()); }
diff --git a/chrome/browser/autocomplete/document_suggestions_service_factory.h b/chrome/browser/autocomplete/document_suggestions_service_factory.h index d496d3e..7823b8f 100644 --- a/chrome/browser/autocomplete/document_suggestions_service_factory.h +++ b/chrome/browser/autocomplete/document_suggestions_service_factory.h
@@ -6,13 +6,12 @@ #define CHROME_BROWSER_AUTOCOMPLETE_DOCUMENT_SUGGESTIONS_SERVICE_FACTORY_H_ #include "base/memory/singleton.h" -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" class DocumentSuggestionsService; class Profile; -class DocumentSuggestionsServiceFactory - : public BrowserContextKeyedServiceFactory { +class DocumentSuggestionsServiceFactory : public ProfileKeyedServiceFactory { public: static DocumentSuggestionsService* GetForProfile(Profile* profile, bool create_if_necessary);
diff --git a/chrome/browser/autocomplete/in_memory_url_index_factory.cc b/chrome/browser/autocomplete/in_memory_url_index_factory.cc index 781cdaa..69828c7b 100644 --- a/chrome/browser/autocomplete/in_memory_url_index_factory.cc +++ b/chrome/browser/autocomplete/in_memory_url_index_factory.cc
@@ -7,10 +7,8 @@ #include "base/memory/singleton.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/history/history_service_factory.h" -#include "chrome/browser/profiles/incognito_helpers.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search_engines/template_url_service_factory.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/keyed_service/core/service_access_type.h" #include "components/omnibox/browser/in_memory_url_index.h" #include "content/public/common/url_constants.h" @@ -27,9 +25,9 @@ } InMemoryURLIndexFactory::InMemoryURLIndexFactory() - : BrowserContextKeyedServiceFactory( + : ProfileKeyedServiceFactory( "InMemoryURLIndex", - BrowserContextDependencyManager::GetInstance()) { + ProfileSelections::BuildRedirectedInIncognito()) { DependsOn(BookmarkModelFactory::GetInstance()); DependsOn(HistoryServiceFactory::GetInstance()); DependsOn(TemplateURLServiceFactory::GetInstance()); @@ -54,11 +52,6 @@ return in_memory_url_index; } -content::BrowserContext* InMemoryURLIndexFactory::GetBrowserContextToUse( - content::BrowserContext* context) const { - return chrome::GetBrowserContextRedirectedInIncognito(context); -} - bool InMemoryURLIndexFactory::ServiceIsNULLWhileTesting() const { return true; }
diff --git a/chrome/browser/autocomplete/in_memory_url_index_factory.h b/chrome/browser/autocomplete/in_memory_url_index_factory.h index 4f925e8..c99da8d 100644 --- a/chrome/browser/autocomplete/in_memory_url_index_factory.h +++ b/chrome/browser/autocomplete/in_memory_url_index_factory.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_AUTOCOMPLETE_IN_MEMORY_URL_INDEX_FACTORY_H_ #define CHROME_BROWSER_AUTOCOMPLETE_IN_MEMORY_URL_INDEX_FACTORY_H_ -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" namespace base { template <typename T> struct DefaultSingletonTraits; @@ -14,7 +14,7 @@ class InMemoryURLIndex; class Profile; -class InMemoryURLIndexFactory : public BrowserContextKeyedServiceFactory { +class InMemoryURLIndexFactory : public ProfileKeyedServiceFactory { public: static InMemoryURLIndex* GetForProfile(Profile* profile); static InMemoryURLIndexFactory* GetInstance(); @@ -28,8 +28,6 @@ // BrowserContextKeyedServiceFactory: KeyedService* BuildServiceInstanceFor( content::BrowserContext* context) const override; - content::BrowserContext* GetBrowserContextToUse( - content::BrowserContext* context) const override; bool ServiceIsNULLWhileTesting() const override; };
diff --git a/chrome/browser/autocomplete/remote_suggestions_service_factory.cc b/chrome/browser/autocomplete/remote_suggestions_service_factory.cc index d9fa615..13180fa 100644 --- a/chrome/browser/autocomplete/remote_suggestions_service_factory.cc +++ b/chrome/browser/autocomplete/remote_suggestions_service_factory.cc
@@ -6,7 +6,6 @@ #include "base/memory/singleton.h" #include "chrome/browser/profiles/profile.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/omnibox/browser/remote_suggestions_service.h" #include "content/public/browser/storage_partition.h" @@ -33,9 +32,6 @@ } RemoteSuggestionsServiceFactory::RemoteSuggestionsServiceFactory() - : BrowserContextKeyedServiceFactory( - "RemoteSuggestionsService", - BrowserContextDependencyManager::GetInstance()) { -} + : ProfileKeyedServiceFactory("RemoteSuggestionsService") {} RemoteSuggestionsServiceFactory::~RemoteSuggestionsServiceFactory() {}
diff --git a/chrome/browser/autocomplete/remote_suggestions_service_factory.h b/chrome/browser/autocomplete/remote_suggestions_service_factory.h index 8419b5e..42884738 100644 --- a/chrome/browser/autocomplete/remote_suggestions_service_factory.h +++ b/chrome/browser/autocomplete/remote_suggestions_service_factory.h
@@ -6,13 +6,12 @@ #define CHROME_BROWSER_AUTOCOMPLETE_REMOTE_SUGGESTIONS_SERVICE_FACTORY_H_ #include "base/memory/singleton.h" -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" class RemoteSuggestionsService; class Profile; -class RemoteSuggestionsServiceFactory - : public BrowserContextKeyedServiceFactory { +class RemoteSuggestionsServiceFactory : public ProfileKeyedServiceFactory { public: static RemoteSuggestionsService* GetForProfile(Profile* profile, bool create_if_necessary);
diff --git a/chrome/browser/autofill/autocomplete_history_manager_factory.cc b/chrome/browser/autofill/autocomplete_history_manager_factory.cc index 62f6173c..11e916178 100644 --- a/chrome/browser/autofill/autocomplete_history_manager_factory.cc +++ b/chrome/browser/autofill/autocomplete_history_manager_factory.cc
@@ -5,12 +5,10 @@ #include "chrome/browser/autofill/autocomplete_history_manager_factory.h" #include "base/memory/singleton.h" -#include "chrome/browser/profiles/incognito_helpers.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/web_data_service_factory.h" #include "components/autofill/core/browser/autocomplete_history_manager.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" namespace autofill { @@ -28,9 +26,9 @@ } AutocompleteHistoryManagerFactory::AutocompleteHistoryManagerFactory() - : BrowserContextKeyedServiceFactory( + : ProfileKeyedServiceFactory( "AutocompleteHistoryManager", - BrowserContextDependencyManager::GetInstance()) { + ProfileSelections::BuildForRegularAndIncognito()) { DependsOn(WebDataServiceFactory::GetInstance()); } @@ -49,10 +47,4 @@ return service; } -content::BrowserContext* -AutocompleteHistoryManagerFactory::GetBrowserContextToUse( - content::BrowserContext* context) const { - return chrome::GetBrowserContextOwnInstanceInIncognito(context); -} - } // namespace autofill
diff --git a/chrome/browser/autofill/autocomplete_history_manager_factory.h b/chrome/browser/autofill/autocomplete_history_manager_factory.h index 29f6475b..dbd57a673 100644 --- a/chrome/browser/autofill/autocomplete_history_manager_factory.h +++ b/chrome/browser/autofill/autocomplete_history_manager_factory.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_AUTOFILL_AUTOCOMPLETE_HISTORY_MANAGER_FACTORY_H_ #define CHROME_BROWSER_AUTOFILL_AUTOCOMPLETE_HISTORY_MANAGER_FACTORY_H_ -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" #include "components/keyed_service/core/keyed_service.h" namespace base { @@ -23,8 +23,7 @@ // Profiles. // Listens for the Profile's destruction notification and cleans up the // associated AutocompleteHistoryManager. -class AutocompleteHistoryManagerFactory - : public BrowserContextKeyedServiceFactory { +class AutocompleteHistoryManagerFactory : public ProfileKeyedServiceFactory { public: // Returns the AutocompleteHistoryManager for |profile|, creating it if it is // not yet created. @@ -41,8 +40,6 @@ // BrowserContextKeyedServiceFactory: KeyedService* BuildServiceInstanceFor( content::BrowserContext* profile) const override; - content::BrowserContext* GetBrowserContextToUse( - content::BrowserContext* context) const override; }; } // namespace autofill
diff --git a/chrome/browser/autofill/autofill_image_fetcher_factory.cc b/chrome/browser/autofill/autofill_image_fetcher_factory.cc index 50f7ebcb..6871f96f5 100644 --- a/chrome/browser/autofill/autofill_image_fetcher_factory.cc +++ b/chrome/browser/autofill/autofill_image_fetcher_factory.cc
@@ -7,10 +7,8 @@ #include "base/no_destructor.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/image_fetcher/image_decoder_impl.h" -#include "chrome/browser/profiles/incognito_helpers.h" #include "chrome/browser/profiles/profile.h" #include "components/autofill/core/browser/ui/autofill_image_fetcher.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" #include "content/public/browser/storage_partition.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -30,9 +28,9 @@ } AutofillImageFetcherFactory::AutofillImageFetcherFactory() - : BrowserContextKeyedServiceFactory( + : ProfileKeyedServiceFactory( "AutofillImageFetcher", - BrowserContextDependencyManager::GetInstance()) {} + ProfileSelections::BuildRedirectedInIncognito()) {} AutofillImageFetcherFactory::~AutofillImageFetcherFactory() = default; @@ -51,10 +49,4 @@ return BuildAutofillImageFetcher(context); } -content::BrowserContext* AutofillImageFetcherFactory::GetBrowserContextToUse( - content::BrowserContext* context) const { - // Use the image fetcher from the original browser context. - return chrome::GetBrowserContextRedirectedInIncognito(context); -} - } // namespace autofill
diff --git a/chrome/browser/autofill/autofill_image_fetcher_factory.h b/chrome/browser/autofill/autofill_image_fetcher_factory.h index 21bb0461..0dc1b96 100644 --- a/chrome/browser/autofill/autofill_image_fetcher_factory.h +++ b/chrome/browser/autofill/autofill_image_fetcher_factory.h
@@ -6,16 +6,16 @@ #define CHROME_BROWSER_AUTOFILL_AUTOFILL_IMAGE_FETCHER_FACTORY_H_ #include "base/no_destructor.h" -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" -#include "components/keyed_service/core/keyed_service.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" +class KeyedService; class Profile; namespace autofill { class AutofillImageFetcher; -class AutofillImageFetcherFactory : public BrowserContextKeyedServiceFactory { +class AutofillImageFetcherFactory : public ProfileKeyedServiceFactory { public: // Returns the AutofillImageFetcher for |profile|, creating it if it is not // yet created. @@ -35,8 +35,6 @@ // BrowserContextKeyedServiceFactory: KeyedService* BuildServiceInstanceFor( content::BrowserContext* profile) const override; - content::BrowserContext* GetBrowserContextToUse( - content::BrowserContext* context) const override; }; } // namespace autofill
diff --git a/chrome/browser/autofill/autofill_offer_manager_factory.cc b/chrome/browser/autofill/autofill_offer_manager_factory.cc index 0ce1d47b..859ec1a6 100644 --- a/chrome/browser/autofill/autofill_offer_manager_factory.cc +++ b/chrome/browser/autofill/autofill_offer_manager_factory.cc
@@ -8,7 +8,6 @@ #include "build/build_config.h" #include "chrome/browser/autofill/personal_data_manager_factory.h" #include "components/autofill/core/browser/payments/autofill_offer_manager.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" #if !BUILDFLAG(IS_ANDROID) #include "chrome/browser/commerce/coupons/coupon_service.h" #include "chrome/browser/commerce/coupons/coupon_service_factory.h" @@ -30,9 +29,7 @@ } AutofillOfferManagerFactory::AutofillOfferManagerFactory() - : BrowserContextKeyedServiceFactory( - "AutofillOfferManager", - BrowserContextDependencyManager::GetInstance()) { + : ProfileKeyedServiceFactory("AutofillOfferManager") { DependsOn(PersonalDataManagerFactory::GetInstance()); #if !BUILDFLAG(IS_ANDROID) DependsOn(CouponServiceFactory::GetInstance());
diff --git a/chrome/browser/autofill/autofill_offer_manager_factory.h b/chrome/browser/autofill/autofill_offer_manager_factory.h index 1af610b..1a85f66 100644 --- a/chrome/browser/autofill/autofill_offer_manager_factory.h +++ b/chrome/browser/autofill/autofill_offer_manager_factory.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_AUTOFILL_AUTOFILL_OFFER_MANAGER_FACTORY_H_ #define CHROME_BROWSER_AUTOFILL_AUTOFILL_OFFER_MANAGER_FACTORY_H_ -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" #include "components/keyed_service/core/keyed_service.h" namespace base { @@ -19,7 +19,7 @@ // Singleton that owns all AutofillOfferManager and associates them with // Profiles. -class AutofillOfferManagerFactory : public BrowserContextKeyedServiceFactory { +class AutofillOfferManagerFactory : public ProfileKeyedServiceFactory { public: AutofillOfferManagerFactory(const AutofillOfferManagerFactory&) = delete; AutofillOfferManagerFactory& operator=(const AutofillOfferManagerFactory&) =
diff --git a/chrome/browser/autofill/form_structure_browsertest.cc b/chrome/browser/autofill/form_structure_browsertest.cc index a6a57bd..9c385fb 100644 --- a/chrome/browser/autofill/form_structure_browsertest.cc +++ b/chrome/browser/autofill/form_structure_browsertest.cc
@@ -219,14 +219,16 @@ // TODO(crbug.com/1150895) Remove once launched. features::kAutofillParsingPatternProvider, features::kAutofillPageLanguageDetection, - // TODO(crbug/1165780): Remove once shared labels are launched. + // TODO(crbug.com/1165780): Remove once shared labels are launched. features::kAutofillEnableSupportForParsingWithSharedLabels, // TODO(crbug.com/1277480): Remove once launched. features::kAutofillEnableNameSurenameParsing, // TODO(crbug.com/1190334): Remove once launched. features::kAutofillParseMerchantPromoCodeFields, // TODO(crbug.com/1113970): Remove once launched. - features::kAutofillSectionUponRedundantNameInfo}, + features::kAutofillSectionUponRedundantNameInfo, + // TODO(crbug.com/1335549): Remove once launched. + features::kAutofillParseIBANFields}, // Disabled {}); }
diff --git a/chrome/browser/autofill/merchant_promo_code_manager_factory.cc b/chrome/browser/autofill/merchant_promo_code_manager_factory.cc index 388ec511..4e758ad 100644 --- a/chrome/browser/autofill/merchant_promo_code_manager_factory.cc +++ b/chrome/browser/autofill/merchant_promo_code_manager_factory.cc
@@ -6,10 +6,8 @@ #include "base/memory/singleton.h" #include "chrome/browser/autofill/personal_data_manager_factory.h" -#include "chrome/browser/profiles/incognito_helpers.h" #include "chrome/browser/profiles/profile.h" #include "components/autofill/core/browser/merchant_promo_code_manager.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" namespace autofill { @@ -27,9 +25,9 @@ } MerchantPromoCodeManagerFactory::MerchantPromoCodeManagerFactory() - : BrowserContextKeyedServiceFactory( + : ProfileKeyedServiceFactory( "MerchantPromoCodeManager", - BrowserContextDependencyManager::GetInstance()) { + ProfileSelections::BuildForRegularAndIncognito()) { DependsOn(PersonalDataManagerFactory::GetInstance()); } @@ -44,10 +42,4 @@ return service; } -content::BrowserContext* -MerchantPromoCodeManagerFactory::GetBrowserContextToUse( - content::BrowserContext* context) const { - return chrome::GetBrowserContextOwnInstanceInIncognito(context); -} - } // namespace autofill
diff --git a/chrome/browser/autofill/merchant_promo_code_manager_factory.h b/chrome/browser/autofill/merchant_promo_code_manager_factory.h index 7eaa0831..e95ada0f 100644 --- a/chrome/browser/autofill/merchant_promo_code_manager_factory.h +++ b/chrome/browser/autofill/merchant_promo_code_manager_factory.h
@@ -5,8 +5,7 @@ #ifndef CHROME_BROWSER_AUTOFILL_MERCHANT_PROMO_CODE_MANAGER_FACTORY_H_ #define CHROME_BROWSER_AUTOFILL_MERCHANT_PROMO_CODE_MANAGER_FACTORY_H_ -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" -#include "components/keyed_service/core/keyed_service.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" namespace base { template <typename T> @@ -22,8 +21,7 @@ // Singleton that owns all MerchantPromoCodeManagers and associates // them with Profiles. Listens for the Profile's destruction notification and // cleans up the associated MerchantPromoCodeManager. -class MerchantPromoCodeManagerFactory - : public BrowserContextKeyedServiceFactory { +class MerchantPromoCodeManagerFactory : public ProfileKeyedServiceFactory { public: // Returns the MerchantPromoCodeManager for |profile|, creating it // if it is not yet created. @@ -40,8 +38,6 @@ // BrowserContextKeyedServiceFactory: KeyedService* BuildServiceInstanceFor( content::BrowserContext* profile) const override; - content::BrowserContext* GetBrowserContextToUse( - content::BrowserContext* context) const override; }; } // namespace autofill
diff --git a/chrome/browser/autofill_assistant/annotate_dom_model_service_factory.cc b/chrome/browser/autofill_assistant/annotate_dom_model_service_factory.cc index 2c6e41e..6851a32d 100644 --- a/chrome/browser/autofill_assistant/annotate_dom_model_service_factory.cc +++ b/chrome/browser/autofill_assistant/annotate_dom_model_service_factory.cc
@@ -17,12 +17,9 @@ #include "components/autofill_assistant/browser/features.h" #include "components/autofill_assistant/browser/switches.h" #include "components/autofill_assistant/content/browser/annotate_dom_model_service.h" -#include "components/keyed_service/content/browser_context_dependency_manager.h" AnnotateDomModelServiceFactory::AnnotateDomModelServiceFactory() - : BrowserContextKeyedServiceFactory( - "AnnotateDomModelService", - BrowserContextDependencyManager::GetInstance()) {} + : ProfileKeyedServiceFactory("AnnotateDomModelService") {} AnnotateDomModelServiceFactory::~AnnotateDomModelServiceFactory() = default;
diff --git a/chrome/browser/autofill_assistant/annotate_dom_model_service_factory.h b/chrome/browser/autofill_assistant/annotate_dom_model_service_factory.h index 8603902..0213b2d5 100644 --- a/chrome/browser/autofill_assistant/annotate_dom_model_service_factory.h +++ b/chrome/browser/autofill_assistant/annotate_dom_model_service_factory.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_AUTOFILL_ASSISTANT_ANNOTATE_DOM_MODEL_SERVICE_FACTORY_H_ #define CHROME_BROWSER_AUTOFILL_ASSISTANT_ANNOTATE_DOM_MODEL_SERVICE_FACTORY_H_ -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" namespace content { class BrowserContext; @@ -16,8 +16,7 @@ } // namespace autofill_assistant // Creates instances of |AnnotateDomMOdelService| per |BrowserContext|. -class AnnotateDomModelServiceFactory - : public BrowserContextKeyedServiceFactory { +class AnnotateDomModelServiceFactory : public ProfileKeyedServiceFactory { public: AnnotateDomModelServiceFactory(); ~AnnotateDomModelServiceFactory() override;
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index 1c17560..293386b 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -79,6 +79,7 @@ #include "content/public/browser/browser_context.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_ui_browser_interface_broker_registry.h" +#include "content/public/browser/web_ui_controller_interface_binder.h" #include "content/public/common/content_features.h" #include "content/public/common/url_constants.h" #include "extensions/buildflags/buildflags.h" @@ -355,6 +356,8 @@ namespace chrome { namespace internal { +using content::RegisterWebUIControllerInterfaceBinder; + #if BUILDFLAG(ENABLE_UNHANDLED_TAP) void BindUnhandledTapWebContentsObserver( content::RenderFrameHost* const host,
diff --git a/chrome/browser/chrome_browser_interface_binders.h b/chrome/browser/chrome_browser_interface_binders.h index 7e8f7c3..464012c 100644 --- a/chrome/browser/chrome_browser_interface_binders.h +++ b/chrome/browser/chrome_browser_interface_binders.h
@@ -5,16 +5,11 @@ #ifndef CHROME_BROWSER_CHROME_BROWSER_INTERFACE_BINDERS_H_ #define CHROME_BROWSER_CHROME_BROWSER_INTERFACE_BINDERS_H_ -#include "chrome/browser/bad_message.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_ui.h" -#include "content/public/browser/web_ui_controller.h" #include "mojo/public/cpp/bindings/binder_map.h" namespace content { - class RenderFrameHost; +class WebUIBrowserInterfaceBrokerRegistry; } // namespace content namespace chrome { @@ -44,83 +39,6 @@ void PopulateChromeWebUIFrameInterfaceBrokers( content::WebUIBrowserInterfaceBrokerRegistry& registry); -template <typename Interface, int N, typename... Subclasses> -struct BinderHelper; - -template <typename Interface, typename WebUIControllerSubclass> -bool SafeDownCastAndBindInterface(content::WebUI* web_ui, - mojo::PendingReceiver<Interface>& receiver) { - // Performs a safe downcast to the concrete WebUIController subclass. - WebUIControllerSubclass* concrete_controller = - web_ui ? web_ui->GetController()->GetAs<WebUIControllerSubclass>() - : nullptr; - - if (!concrete_controller) - return false; - - // Fails to compile if |Subclass| does not implement the appropriate overload - // for |Interface|. - concrete_controller->BindInterface(std::move(receiver)); - return true; -} - -template <typename Interface, int N, typename Subclass, typename... Subclasses> -struct BinderHelper<Interface, N, std::tuple<Subclass, Subclasses...>> { - static bool BindInterface(content::WebUI* web_ui, - mojo::PendingReceiver<Interface> receiver) { - // Try a different subclass if the current one is not the right - // WebUIController for the current WebUI page, and only fail if none of the - // passed subclasses match. - if (!SafeDownCastAndBindInterface<Interface, Subclass>(web_ui, receiver)) { - return BinderHelper<Interface, N - 1, std::tuple<Subclasses...>>:: - BindInterface(web_ui, std::move(receiver)); - } - return true; - } -}; - -template <typename Interface, typename Subclass, typename... Subclasses> -struct BinderHelper<Interface, 0, std::tuple<Subclass, Subclasses...>> { - static bool BindInterface(content::WebUI* web_ui, - mojo::PendingReceiver<Interface> receiver) { - return SafeDownCastAndBindInterface<Interface, Subclass>(web_ui, receiver); - } -}; - -// Registers a binder in |map| that binds |Interface| iff the RenderFrameHost -// has a WebUIController among type |WebUIControllerSubclasses|. -template <typename Interface, typename... WebUIControllerSubclasses> -void RegisterWebUIControllerInterfaceBinder( - mojo::BinderMapWithContext<content::RenderFrameHost*>* map) { - DCHECK(!map->Contains<Interface>()) - << "A binder for " << Interface::Name_ << " has already been registered."; - map->Add<Interface>( - base::BindRepeating([](content::RenderFrameHost* host, - mojo::PendingReceiver<Interface> receiver) { - // This is expected to be called only for outermost main frames. - if (host->GetParentOrOuterDocument()) { - ReceivedBadMessage( - host->GetProcess(), - bad_message::BadMessageReason::RFH_INVALID_WEB_UI_CONTROLLER); - return; - } - - const int size = sizeof...(WebUIControllerSubclasses); - bool is_bound = BinderHelper<Interface, size - 1, - std::tuple<WebUIControllerSubclasses...>>:: - BindInterface(host->GetWebUI(), std::move(receiver)); - - // This is expected to be called only for the right WebUI pages matching - // the same WebUI associated to the RenderFrameHost. - if (!is_bound) { - ReceivedBadMessage( - host->GetProcess(), - bad_message::BadMessageReason::RFH_INVALID_WEB_UI_CONTROLLER); - return; - } - })); -} - } // namespace internal } // namespace chrome
diff --git a/chrome/browser/content_settings/page_specific_content_settings_delegate.h b/chrome/browser/content_settings/page_specific_content_settings_delegate.h index 91de10e..c7a09f4a 100644 --- a/chrome/browser/content_settings/page_specific_content_settings_delegate.h +++ b/chrome/browser/content_settings/page_specific_content_settings_delegate.h
@@ -9,6 +9,7 @@ #include "chrome/browser/browsing_data/access_context_audit_service.h" #include "components/content_settings/browser/page_specific_content_settings.h" #include "components/custom_handlers/protocol_handler.h" +#include "content/public/browser/web_contents_observer.h" namespace chrome {
diff --git a/chrome/browser/content_settings/page_specific_content_settings_unittest.cc b/chrome/browser/content_settings/page_specific_content_settings_unittest.cc index 66fc55a..fd2dc0b 100644 --- a/chrome/browser/content_settings/page_specific_content_settings_unittest.cc +++ b/chrome/browser/content_settings/page_specific_content_settings_unittest.cc
@@ -9,6 +9,7 @@ #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "content/public/browser/web_contents.h" #include "testing/gmock/include/gmock/gmock-matchers.h" namespace content_settings {
diff --git a/chrome/browser/dips/dips_helper.cc b/chrome/browser/dips/dips_helper.cc index b4b4936..6e587ed 100644 --- a/chrome/browser/dips/dips_helper.cc +++ b/chrome/browser/dips/dips_helper.cc
@@ -6,9 +6,11 @@ #include <utility> +#include "base/metrics/histogram_functions.h" +#include "base/strings/strcat.h" #include "base/time/default_clock.h" #include "chrome/browser/dips/dips_service.h" -#include "chrome/browser/dips/dips_utils.h" +#include "chrome/browser/dips/dips_storage.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/cookie_access_details.h" #include "content/public/browser/navigation_handle.h" @@ -16,6 +18,26 @@ namespace { +inline void UmaHistogramTimeToInteraction(base::TimeDelta sample, + DIPSCookieMode mode) { + const std::string name = base::StrCat( + {"Privacy.DIPS.TimeFromStorageToInteraction", GetHistogramSuffix(mode)}); + + base::UmaHistogramCustomTimes(name, sample, + /*min=*/base::TimeDelta(), + /*max=*/base::Days(7), 100); +} + +inline void UmaHistogramTimeToStorage(base::TimeDelta sample, + DIPSCookieMode mode) { + const std::string name = base::StrCat( + {"Privacy.DIPS.TimeFromInteractionToStorage", GetHistogramSuffix(mode)}); + + base::UmaHistogramCustomTimes(name, sample, + /*min=*/base::TimeDelta(), + /*max=*/base::Days(7), 100); +} + // The Clock that a new DIPSTabHelper will use internally. Exposed as a global // so that browser tests (which don't call the DIPSTabHelper constructor // directly) can inject a fake clock. @@ -38,18 +60,8 @@ service_->ShouldBlockThirdPartyCookies()); } -void DIPSTabHelper::FlushForTesting(base::OnceClosure flushed) { - service_->storage() - ->AsyncCall(&DIPSStorage::DoNothing) - .Then(std::move(flushed)); -} - -void DIPSTabHelper::StateForURLForTesting(const GURL& url, - StateForURLCallback callback) { - service_->storage() - ->AsyncCall(&DIPSStorage::Read) - .WithArgs(url) - .Then(std::move(callback)); +DIPSState DIPSTabHelper::StateForURL(const GURL& url) { + return service_->storage()->Read(url); } /* static */ @@ -57,29 +69,29 @@ return std::exchange(g_clock, clock); } -void DIPSTabHelper::RecordStorage(const GURL& url) { +void DIPSTabHelper::MaybeRecordStorage(const GURL& url) { + DIPSState state = StateForURL(url); + if (state.site_storage_time()) { + // We want the time that storage was first written, so don't overwrite the + // existing timestamp. + return; + } + base::Time now = clock_->Now(); - DIPSCookieMode mode = GetCookieMode(); + if (state.user_interaction_time()) { + // First storage, but previous interaction. + UmaHistogramTimeToStorage(now - state.user_interaction_time().value(), + GetCookieMode()); + } - service_->storage() - ->AsyncCall(&DIPSStorage::RecordStorage) - .WithArgs(url, now, mode); -} - -void DIPSTabHelper::RecordInteraction(const GURL& url) { - base::Time now = clock_->Now(); - DIPSCookieMode mode = GetCookieMode(); - - service_->storage() - ->AsyncCall(&DIPSStorage::RecordInteraction) - .WithArgs(url, now, mode); + state.set_site_storage_time(now); } void DIPSTabHelper::OnCookiesAccessed( content::RenderFrameHost* render_frame_host, const content::CookieAccessDetails& details) { if (details.type == content::CookieAccessDetails::Type::kChange) { - RecordStorage(details.url); + MaybeRecordStorage(details.url); } } @@ -87,7 +99,7 @@ content::NavigationHandle* handle, const content::CookieAccessDetails& details) { if (details.type == content::CookieAccessDetails::Type::kChange) { - RecordStorage(details.url); + MaybeRecordStorage(details.url); } } @@ -101,4 +113,24 @@ RecordInteraction(url); } +void DIPSTabHelper::RecordInteraction(const GURL& url) { + DIPSState state = StateForURL(url); + + base::Time now = clock_->Now(); + if (!state.user_interaction_time()) { + // First interaction on site. + if (state.site_storage_time()) { + // Site previously wrote to storage. Record metric for the time delay + // between storage and interaction. + UmaHistogramTimeToInteraction(now - state.site_storage_time().value(), + GetCookieMode()); + } + } + + // Unlike for storage, we want to know the time of the most recent user + // interaction, so overwrite any existing timestamp. (If interaction happened + // a long time ago, it may no longer be relevant.) + state.set_user_interaction_time(now); +} + WEB_CONTENTS_USER_DATA_KEY_IMPL(DIPSTabHelper);
diff --git a/chrome/browser/dips/dips_helper.h b/chrome/browser/dips/dips_helper.h index 8250849b..42a54772 100644 --- a/chrome/browser/dips/dips_helper.h +++ b/chrome/browser/dips/dips_helper.h
@@ -26,14 +26,12 @@ // Record that |url| wrote to storage, if it was the first such time (we // currently don't care about later writes to storage.) - void RecordStorage(const GURL& url); + void MaybeRecordStorage(const GURL& url); // Record that the user interacted on |url| . void RecordInteraction(const GURL& url); - void FlushForTesting(base::OnceClosure flushed); + DIPSState StateForURL(const GURL& url); - using StateForURLCallback = base::OnceCallback<void(DIPSState)>; - void StateForURLForTesting(const GURL& url, StateForURLCallback callback); static base::Clock* SetClockForTesting(base::Clock* clock); private:
diff --git a/chrome/browser/dips/dips_helper_browsertest.cc b/chrome/browser/dips/dips_helper_browsertest.cc index 341738c3..0011ab9f 100644 --- a/chrome/browser/dips/dips_helper_browsertest.cc +++ b/chrome/browser/dips/dips_helper_browsertest.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/dips/dips_helper.h" #include "base/memory/raw_ptr.h" -#include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/simple_test_clock.h" #include "base/time/time.h" @@ -103,32 +102,8 @@ DIPSTabHelper* dips_helper() { return helper_; } - void BlockUntilHelperProcessesPendingRequests() { - base::RunLoop run_loop; - helper_->FlushForTesting(run_loop.QuitClosure()); - run_loop.Run(); - } - void SetDIPSTime(base::Time time) { test_clock_.SetNow(time); } - void CopyDIPSState(DIPSState* a, DIPSState* b) { - a->set_site_storage_time_on_load(b->site_storage_time()); - a->set_user_interaction_time_on_load(b->user_interaction_time()); - a->set_was_loaded_for_testing(b->was_loaded()); - } - - DIPSState GetDIPSState(const GURL& url) { - DIPSState state; - - helper_->StateForURLForTesting( - url, base::BindLambdaForTesting([&](DIPSState loaded_state) { - CopyDIPSState(&state, &loaded_state); - })); - BlockUntilHelperProcessesPendingRequests(); - - return state; - } - private: base::SimpleTestClock test_clock_; raw_ptr<DIPSTabHelper> helper_ = nullptr; @@ -153,8 +128,8 @@ content::WaitForHitTestData(iframe); // Before clicking, no DIPS state for either site. - EXPECT_FALSE(GetDIPSState(url_a).was_loaded()); - EXPECT_FALSE(GetDIPSState(url_b).was_loaded()); + EXPECT_FALSE(dips_helper()->StateForURL(url_a).was_loaded()); + EXPECT_FALSE(dips_helper()->StateForURL(url_b).was_loaded()); // Click on the b.test iframe. SetDIPSTime(time); @@ -163,12 +138,12 @@ observer.Wait(); // User interaction is recorded for a.test (the top-level frame). - DIPSState state_a = GetDIPSState(url_a); + DIPSState state_a = dips_helper()->StateForURL(url_a); EXPECT_TRUE(state_a.was_loaded()); EXPECT_FALSE(state_a.site_storage_time().has_value()); EXPECT_EQ(time, state_a.user_interaction_time().value()); // User interaction is also recorded for b.test (the iframe). - DIPSState state_b = GetDIPSState(url_b); + DIPSState state_b = dips_helper()->StateForURL(url_b); EXPECT_TRUE(state_b.was_loaded()); EXPECT_FALSE(state_b.site_storage_time().has_value()); EXPECT_EQ(time, state_b.user_interaction_time().value()); @@ -197,8 +172,8 @@ base::BindRepeating(&content::FrameIsChildOfMainFrame)); // Initially, no DIPS state for either site. - EXPECT_FALSE(GetDIPSState(url_a).was_loaded()); - EXPECT_FALSE(GetDIPSState(url_b).was_loaded()); + EXPECT_FALSE(dips_helper()->StateForURL(url_a).was_loaded()); + EXPECT_FALSE(dips_helper()->StateForURL(url_b).was_loaded()); // Write a cookie in the b.test iframe. SetDIPSTime(time); @@ -209,10 +184,10 @@ observer.Wait(); // Nothing recorded for a.test (the top-level frame). - DIPSState state_a = GetDIPSState(url_a); + DIPSState state_a = dips_helper()->StateForURL(url_a); EXPECT_FALSE(state_a.was_loaded()); // Site storage was recorded for b.test (the iframe). - DIPSState state_b = GetDIPSState(url_b); + DIPSState state_b = dips_helper()->StateForURL(url_b); EXPECT_TRUE(state_b.was_loaded()); EXPECT_EQ(time, state_b.site_storage_time().value()); EXPECT_FALSE(state_b.user_interaction_time().has_value());
diff --git a/chrome/browser/dips/dips_service.cc b/chrome/browser/dips/dips_service.cc index 50f7b15..68af45328 100644 --- a/chrome/browser/dips/dips_service.cc +++ b/chrome/browser/dips/dips_service.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/dips/dips_service.h" -#include "base/task/thread_pool.h" #include "chrome/browser/content_settings/cookie_settings_factory.h" #include "chrome/browser/dips/dips_service_factory.h" #include "chrome/browser/profiles/profile.h" @@ -13,8 +12,7 @@ DIPSService::DIPSService(content::BrowserContext* context) : browser_context_(context), cookie_settings_(CookieSettingsFactory::GetForProfile( - Profile::FromBrowserContext(context))), - storage_(base::SequenceBound<DIPSStorage>(CreateTaskRunner())) {} + Profile::FromBrowserContext(context))) {} DIPSService::~DIPSService() = default; @@ -27,12 +25,6 @@ cookie_settings_.reset(); } -scoped_refptr<base::SequencedTaskRunner> DIPSService::CreateTaskRunner() { - return base::ThreadPool::CreateSequencedTaskRunner( - {base::MayBlock(), base::TaskPriority::BEST_EFFORT, - base::ThreadPolicy::PREFER_BACKGROUND}); -} - bool DIPSService::ShouldBlockThirdPartyCookies() const { return cookie_settings_->ShouldBlockThirdPartyCookies(); }
diff --git a/chrome/browser/dips/dips_service.h b/chrome/browser/dips/dips_service.h index 046d971..45fa818e 100644 --- a/chrome/browser/dips/dips_service.h +++ b/chrome/browser/dips/dips_service.h
@@ -7,7 +7,6 @@ #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" -#include "base/threading/sequence_bound.h" #include "chrome/browser/dips/dips_storage.h" #include "components/keyed_service/core/keyed_service.h" @@ -25,8 +24,7 @@ static DIPSService* Get(content::BrowserContext* context); - base::SequenceBound<DIPSStorage>* storage() { return &storage_; } - + DIPSStorage* storage() { return &storage_; } bool ShouldBlockThirdPartyCookies() const; private: @@ -35,11 +33,9 @@ explicit DIPSService(content::BrowserContext* context); void Shutdown() override; - scoped_refptr<base::SequencedTaskRunner> CreateTaskRunner(); - raw_ptr<content::BrowserContext> browser_context_; scoped_refptr<content_settings::CookieSettings> cookie_settings_; - base::SequenceBound<DIPSStorage> storage_; + DIPSStorage storage_; }; #endif // CHROME_BROWSER_DIPS_DIPS_SERVICE_H_
diff --git a/chrome/browser/dips/dips_state.cc b/chrome/browser/dips/dips_state.cc index 3c6257db..5546154 100644 --- a/chrome/browser/dips/dips_state.cc +++ b/chrome/browser/dips/dips_state.cc
@@ -28,10 +28,6 @@ dirty_ = true; } -void DIPSState::set_site_storage_time_on_load(absl::optional<base::Time> time) { - site_storage_time_ = time; -} - void DIPSState::set_user_interaction_time(absl::optional<base::Time> time) { if (time == user_interaction_time_) { return; @@ -40,12 +36,3 @@ user_interaction_time_ = time; dirty_ = true; } - -void DIPSState::set_user_interaction_time_on_load( - absl::optional<base::Time> time) { - user_interaction_time_ = time; -} - -void DIPSState::set_was_loaded_for_testing(bool loaded) { - was_loaded_ = loaded; -}
diff --git a/chrome/browser/dips/dips_state.h b/chrome/browser/dips/dips_state.h index ae11d1b2..b138357 100644 --- a/chrome/browser/dips/dips_state.h +++ b/chrome/browser/dips/dips_state.h
@@ -34,7 +34,6 @@ // DIPSState represents the state recorded by DIPSService itself. class DIPSState { public: - DIPSState() = default; DIPSState(DIPSStorage* storage, std::string site, bool was_loaded); DIPSState(DIPSState&&); // Flushes changes to storage_. @@ -44,22 +43,16 @@ // True iff this DIPSState was loaded from DIPSStorage (as opposed to being // default-initialized for a new site). bool was_loaded() const { return was_loaded_; } - // For testing only. - void set_was_loaded_for_testing(bool loaded); absl::optional<base::Time> site_storage_time() const { return site_storage_time_; } void set_site_storage_time(absl::optional<base::Time> time); - // For loading/copying DIPSState objects only. - void set_site_storage_time_on_load(absl::optional<base::Time> time); absl::optional<base::Time> user_interaction_time() const { return user_interaction_time_; } void set_user_interaction_time(absl::optional<base::Time> time); - // For loading/copying DIPSState objects only. - void set_user_interaction_time_on_load(absl::optional<base::Time> time); private: raw_ptr<DIPSStorage> storage_;
diff --git a/chrome/browser/dips/dips_storage.cc b/chrome/browser/dips/dips_storage.cc index 23ca184..364e053 100644 --- a/chrome/browser/dips/dips_storage.cc +++ b/chrome/browser/dips/dips_storage.cc
@@ -4,42 +4,14 @@ #include "chrome/browser/dips/dips_storage.h" -#include "base/metrics/histogram_functions.h" -#include "base/strings/strcat.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "url/gurl.h" -namespace { - -inline void UmaHistogramTimeToInteraction(base::TimeDelta sample, - DIPSCookieMode mode) { - const std::string name = base::StrCat( - {"Privacy.DIPS.TimeFromStorageToInteraction", GetHistogramSuffix(mode)}); - - base::UmaHistogramCustomTimes(name, sample, - /*min=*/base::TimeDelta(), - /*max=*/base::Days(7), 100); -} - -inline void UmaHistogramTimeToStorage(base::TimeDelta sample, - DIPSCookieMode mode) { - const std::string name = base::StrCat( - {"Privacy.DIPS.TimeFromInteractionToStorage", GetHistogramSuffix(mode)}); - - base::UmaHistogramCustomTimes(name, sample, - /*min=*/base::TimeDelta(), - /*max=*/base::Days(7), 100); -} - -} // namespace - DIPSStorage::DIPSStorage() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DETACH_FROM_SEQUENCE(sequence_checker_); } -DIPSStorage::~DIPSStorage() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -} +DIPSStorage::~DIPSStorage() = default; DIPSState DIPSStorage::Read(const GURL& url) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -50,8 +22,8 @@ } const StateValue& value = iter->second; DIPSState state(this, std::move(site), /*was_loaded=*/true); - state.set_site_storage_time_on_load(value.site_storage_time); - state.set_user_interaction_time_on_load(value.user_interaction_time); + state.set_site_storage_time(value.site_storage_time); + state.set_user_interaction_time(value.user_interaction_time); return state; } @@ -62,47 +34,6 @@ value.user_interaction_time = state.user_interaction_time(); } -void DIPSStorage::RecordStorage(const GURL& url, - base::Time time, - DIPSCookieMode mode) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DIPSState state = Read(url); - if (state.site_storage_time()) { - // We want the time that storage was first written, so don't overwrite the - // existing timestamp. - return; - } - - if (state.user_interaction_time()) { - // First storage, but previous interaction. - UmaHistogramTimeToStorage(time - state.user_interaction_time().value(), - mode); - } - - state.set_site_storage_time(time); -} - -void DIPSStorage::RecordInteraction(const GURL& url, - base::Time time, - DIPSCookieMode mode) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DIPSState state = Read(url); - if (!state.user_interaction_time()) { - // First interaction on site. - if (state.site_storage_time()) { - // Site previously wrote to storage. Record metric for the time delay - // between storage and interaction. - UmaHistogramTimeToInteraction(time - state.site_storage_time().value(), - mode); - } - } - - // Unlike for storage, we want to know the time of the most recent user - // interaction, so overwrite any existing timestamp. (If interaction happened - // a long time ago, it may no longer be relevant.) - state.set_user_interaction_time(time); -} - /* static */ std::string DIPSStorage::GetSite(const GURL& url) { // TODO(crbug.com/1306935): use privacy boundary instead of eTLD+1
diff --git a/chrome/browser/dips/dips_storage.h b/chrome/browser/dips/dips_storage.h index b26f5a6..ccf53a2 100644 --- a/chrome/browser/dips/dips_storage.h +++ b/chrome/browser/dips/dips_storage.h
@@ -11,7 +11,6 @@ #include "base/sequence_checker.h" #include "base/time/time.h" #include "chrome/browser/dips/dips_state.h" -#include "chrome/browser/dips/dips_utils.h" #include "third_party/abseil-cpp/absl/types/optional.h" class GURL; @@ -27,23 +26,11 @@ DIPSState Read(const GURL& url); - // DIPS Helper Method Impls -------------------------------------------------- - - // Record that |url| wrote to storage, if it was the first such time (we - // currently don't care about later writes to storage.) - void RecordStorage(const GURL& url, base::Time time, DIPSCookieMode mode); - // Record that the user interacted on |url|. - void RecordInteraction(const GURL& url, base::Time time, DIPSCookieMode mode); - - /* static */ // Returns an opaque value representing the "privacy boundary" that the URL // belongs to. Currently returns eTLD+1, but this is an implementation detail // and will change (e.g. after adding support for First-Party Sets). static std::string GetSite(const GURL& url); - // Empty method intended for testing use only. - void DoNothing() {} - private: friend class DIPSState; void Write(const DIPSState& state);
diff --git a/chrome/browser/dips/dips_storage_unittest.cc b/chrome/browser/dips/dips_storage_unittest.cc index 2c6a824..7bc25a60 100644 --- a/chrome/browser/dips/dips_storage_unittest.cc +++ b/chrome/browser/dips/dips_storage_unittest.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/dips/dips_storage.h" +#include "base/test/simple_test_clock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h"
diff --git a/chrome/browser/download/download_item_model_unittest.cc b/chrome/browser/download/download_item_model_unittest.cc index d30021f42..5646432 100644 --- a/chrome/browser/download/download_item_model_unittest.cc +++ b/chrome/browser/download/download_item_model_unittest.cc
@@ -740,6 +740,86 @@ #if !BUILDFLAG(IS_ANDROID) +TEST_F(DownloadItemModelTest, InProgressOrCompletedBubbleUIInfo_V2On) { + SetupDownloadItemDefaults(); + + SetupCompletedDownloadItem(base::Hours(1)); + DownloadUIModel::BubbleUIInfo bubble_ui_info = + model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true); + std::vector<DownloadCommands::Command> quick_action_commands; + for (auto quick_action : bubble_ui_info.quick_actions) { + quick_action_commands.push_back(quick_action.command); + } + EXPECT_EQ(quick_action_commands, + std::vector({DownloadCommands::Command::OPEN_WHEN_COMPLETE, + DownloadCommands::Command::SHOW_IN_FOLDER})); + EXPECT_FALSE(bubble_ui_info.primary_button_command.has_value()); + + Mock::VerifyAndClearExpectations(&item()); + Mock::VerifyAndClearExpectations(&model()); + + ON_CALL(item(), GetState()) + .WillByDefault(Return(download::DownloadItem::IN_PROGRESS)); + EXPECT_CALL(item(), IsPaused()).WillRepeatedly(Return(true)); + bubble_ui_info = model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true); + quick_action_commands = {}; + for (auto quick_action : bubble_ui_info.quick_actions) { + quick_action_commands.push_back(quick_action.command); + } + EXPECT_EQ(quick_action_commands, + std::vector({DownloadCommands::Command::RESUME, + DownloadCommands::Command::CANCEL})); + EXPECT_FALSE(bubble_ui_info.primary_button_command.has_value()); + + Mock::VerifyAndClearExpectations(&item()); + Mock::VerifyAndClearExpectations(&model()); + + EXPECT_CALL(item(), IsPaused()).WillRepeatedly(Return(false)); + bubble_ui_info = model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true); + quick_action_commands = {}; + for (auto quick_action : bubble_ui_info.quick_actions) { + quick_action_commands.push_back(quick_action.command); + } + EXPECT_EQ(quick_action_commands, + std::vector({DownloadCommands::Command::PAUSE, + DownloadCommands::Command::CANCEL})); + EXPECT_FALSE(bubble_ui_info.primary_button_command.has_value()); +} + +TEST_F(DownloadItemModelTest, InProgressOrCompletedBubbleUIInfo_V2Off) { + SetupDownloadItemDefaults(); + + SetupCompletedDownloadItem(base::Hours(1)); + DownloadUIModel::BubbleUIInfo bubble_ui_info = + model().GetBubbleUIInfo(/*is_download_bubble_v2=*/false); + std::vector<DownloadCommands::Command> quick_action_commands; + for (auto quick_action : bubble_ui_info.quick_actions) { + quick_action_commands.push_back(quick_action.command); + } + EXPECT_EQ(quick_action_commands, std::vector<DownloadCommands::Command>()); + EXPECT_FALSE(bubble_ui_info.primary_button_command.has_value()); + + Mock::VerifyAndClearExpectations(&item()); + Mock::VerifyAndClearExpectations(&model()); + + ON_CALL(item(), GetState()) + .WillByDefault(Return(download::DownloadItem::IN_PROGRESS)); + EXPECT_CALL(item(), IsPaused()).WillRepeatedly(Return(true)); + bubble_ui_info = model().GetBubbleUIInfo(/*is_download_bubble_v2=*/false); + EXPECT_TRUE(bubble_ui_info.quick_actions.empty()); + EXPECT_EQ(bubble_ui_info.primary_button_command.value(), + DownloadCommands::Command::RESUME); + + Mock::VerifyAndClearExpectations(&item()); + Mock::VerifyAndClearExpectations(&model()); + + EXPECT_CALL(item(), IsPaused()).WillRepeatedly(Return(false)); + bubble_ui_info = model().GetBubbleUIInfo(/*is_download_bubble_v2=*/false); + EXPECT_TRUE(bubble_ui_info.quick_actions.empty()); + EXPECT_EQ(bubble_ui_info.primary_button_command.value(), + DownloadCommands::Command::CANCEL); +} + TEST_F(DownloadItemModelTest, DangerousWarningBubbleUIInfo_V2On) { SetupCompletedDownloadItem(base::Hours(1)); const struct DangerTypeTestCase {
diff --git a/chrome/browser/download/download_ui_model.cc b/chrome/browser/download/download_ui_model.cc index 8601272..25ce5d54 100644 --- a/chrome/browser/download/download_ui_model.cc +++ b/chrome/browser/download/download_ui_model.cc
@@ -1136,36 +1136,51 @@ case download::DOWNLOAD_DANGER_TYPE_MAX: break; } + + // Add primary button/quick actions for in-progress (paused or active), and + // completed downloads bool has_progress_bar = GetState() == DownloadItem::IN_PROGRESS; BubbleUIInfo bubble_ui_info = DownloadUIModel::BubbleUIInfo(has_progress_bar); if (has_progress_bar) { if (IsPaused()) { - bubble_ui_info.AddPrimaryButton(DownloadCommands::Command::RESUME); - bubble_ui_info.AddQuickAction( - DownloadCommands::Command::RESUME, - l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_RESUME_QUICK_ACTION), - &vector_icons::kPlayArrowIcon); + if (is_download_bubble_v2) { + bubble_ui_info.AddQuickAction( + DownloadCommands::Command::RESUME, + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_RESUME_QUICK_ACTION), + &vector_icons::kPlayArrowIcon); + bubble_ui_info.AddQuickAction( + DownloadCommands::Command::CANCEL, + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CANCEL_QUICK_ACTION), + &vector_icons::kCloseIcon); + } else { + bubble_ui_info.AddPrimaryButton(DownloadCommands::Command::RESUME); + } } else { - bubble_ui_info.AddPrimaryButton(DownloadCommands::Command::CANCEL); - bubble_ui_info.AddQuickAction( - DownloadCommands::Command::PAUSE, - l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_PAUSE_QUICK_ACTION), - &vector_icons::kPauseIcon); + if (is_download_bubble_v2) { + bubble_ui_info.AddQuickAction( + DownloadCommands::Command::PAUSE, + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_PAUSE_QUICK_ACTION), + &vector_icons::kPauseIcon); + bubble_ui_info.AddQuickAction( + DownloadCommands::Command::CANCEL, + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CANCEL_QUICK_ACTION), + &vector_icons::kCloseIcon); + } else { + bubble_ui_info.AddPrimaryButton(DownloadCommands::Command::CANCEL); + } } - bubble_ui_info.AddQuickAction( - DownloadCommands::Command::CANCEL, - l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CANCEL_QUICK_ACTION), - &vector_icons::kCloseIcon); } else { - bubble_ui_info.AddQuickAction( - DownloadCommands::Command::OPEN_WHEN_COMPLETE, - l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_OPEN_QUICK_ACTION), - &vector_icons::kOpenInNewIcon); - bubble_ui_info.AddQuickAction( - DownloadCommands::Command::SHOW_IN_FOLDER, - l10n_util::GetStringUTF16( - IDS_DOWNLOAD_BUBBLE_SHOW_IN_FOLDER_QUICK_ACTION), - &vector_icons::kFolderIcon); + if (is_download_bubble_v2) { + bubble_ui_info.AddQuickAction( + DownloadCommands::Command::OPEN_WHEN_COMPLETE, + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_OPEN_QUICK_ACTION), + &vector_icons::kOpenInNewIcon); + bubble_ui_info.AddQuickAction( + DownloadCommands::Command::SHOW_IN_FOLDER, + l10n_util::GetStringUTF16( + IDS_DOWNLOAD_BUBBLE_SHOW_IN_FOLDER_QUICK_ACTION), + &vector_icons::kFolderIcon); + } } return bubble_ui_info; }
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/mock_secure_enclave_client.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/mock_secure_enclave_client.h index cd77c6c5..f4d10ba 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/mock_secure_enclave_client.h +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/mock_secure_enclave_client.h
@@ -25,14 +25,14 @@ ~MockSecureEnclaveClient() override; MOCK_METHOD(base::ScopedCFTypeRef<SecKeyRef>, - CreateTemporaryKey, + CreatePermanentKey, (), (override)); MOCK_METHOD(base::ScopedCFTypeRef<SecKeyRef>, CopyStoredKey, (KeyType), (override)); - MOCK_METHOD(bool, MoveTemporaryKeyToPermanent, (), (override)); + MOCK_METHOD(bool, UpdateStoredKeyLabel, (KeyType, KeyType), (override)); MOCK_METHOD(bool, DeleteKey, (KeyType), (override)); MOCK_METHOD(bool, GetStoredKeyLabel,
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client.h index dbaa1f4..ec28ba7d 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client.h +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client.h
@@ -36,16 +36,18 @@ static std::unique_ptr<SecureEnclaveClient> Create(); - // Creates a new Secure Enclave private key with a temporary key label. - virtual base::ScopedCFTypeRef<SecKeyRef> CreateTemporaryKey() = 0; + // Creates a new Secure Enclave private key with a permanent key label. + virtual base::ScopedCFTypeRef<SecKeyRef> CreatePermanentKey() = 0; // Queries for the secure key using its label determined by the key `type`. // Returns the secure key reference or a nullptr if no key was found. virtual base::ScopedCFTypeRef<SecKeyRef> CopyStoredKey(KeyType type) = 0; - // Updates the private key label from the temporary key label to the - // non-temporary label. - virtual bool MoveTemporaryKeyToPermanent() = 0; + // Deletes any key stored in `new_key_type` and updates the private key + // storage in `current_key_type` to `new_key_type` and modifies the key label + // to reflect this change. + virtual bool UpdateStoredKeyLabel(KeyType current_key_type, + KeyType new_key_type) = 0; // Queries for the secure key using its label determined by the key `type` // and deletes it from the secure enclave.
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client_impl.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client_impl.h index 2f4e5e5..1d544e4 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client_impl.h +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client_impl.h
@@ -27,9 +27,10 @@ ~SecureEnclaveClientImpl() override; // SecureEnclaveClient: - base::ScopedCFTypeRef<SecKeyRef> CreateTemporaryKey() override; + base::ScopedCFTypeRef<SecKeyRef> CreatePermanentKey() override; base::ScopedCFTypeRef<SecKeyRef> CopyStoredKey(KeyType type) override; - bool MoveTemporaryKeyToPermanent() override; + bool UpdateStoredKeyLabel(KeyType current_key_type, + KeyType new_key_type) override; bool DeleteKey(KeyType type) override; bool GetStoredKeyLabel(KeyType type, std::vector<uint8_t>& output) override; bool ExportPublicKey(SecKeyRef key, std::vector<uint8_t>& output) override;
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client_impl.mm b/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client_impl.mm index 367af64..9ee02daf 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client_impl.mm +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client_impl.mm
@@ -69,7 +69,8 @@ #pragma clang diagnostic pop // Creates and returns the secure enclave private key attributes used -// for key creation. +// for key creation. These key attributes represent the key created in +// the permanent key location. base::ScopedCFTypeRef<CFMutableDictionaryRef> CreateAttributesForKey() { auto access_ref = CreateACL(); if (!access_ref) @@ -84,9 +85,9 @@ CFDictionarySetValue(attributes, kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom); CFDictionarySetValue(attributes, kSecAttrKeySizeInBits, @256); - CFDictionarySetValue(attributes, kSecAttrLabel, - base::SysUTF8ToCFStringRef( - constants::kTemporaryDeviceTrustSigningKeyLabel)); + CFDictionarySetValue( + attributes, kSecAttrLabel, + base::SysUTF8ToCFStringRef(constants::kDeviceTrustSigningKeyLabel)); base::ScopedCFTypeRef<CFMutableDictionaryRef> private_key_params( CFDictionaryCreateMutable(kCFAllocatorDefault, 0, @@ -123,14 +124,14 @@ SecureEnclaveClientImpl::~SecureEnclaveClientImpl() = default; -base::ScopedCFTypeRef<SecKeyRef> SecureEnclaveClientImpl::CreateTemporaryKey() { +base::ScopedCFTypeRef<SecKeyRef> SecureEnclaveClientImpl::CreatePermanentKey() { auto attributes = CreateAttributesForKey(); if (!attributes) return base::ScopedCFTypeRef<SecKeyRef>(); - // Deletes a temporary Secure Enclave key if it exists from a previous + // Deletes a permanent Secure Enclave key if it exists from a previous // key rotation. - DeleteKey(KeyType::kTemporary); + DeleteKey(KeyType::kPermanent); return helper_->CreateSecureKey(attributes); } @@ -139,19 +140,23 @@ return helper_->CopyKey(CreateQueryForKey(type)); } -bool SecureEnclaveClientImpl::MoveTemporaryKeyToPermanent() { - // Deletes an old Secure Enclave key if it exists. - DeleteKey(SecureEnclaveClient::KeyType::kPermanent); +bool SecureEnclaveClientImpl::UpdateStoredKeyLabel(KeyType current_key_type, + KeyType new_key_type) { + // Deletes the `new_key_type` label if it exists in the keychain. + DeleteKey(new_key_type); base::ScopedCFTypeRef<CFMutableDictionaryRef> attributes_to_update( CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - CFDictionarySetValue( - attributes_to_update, kSecAttrLabel, - base::SysUTF8ToCFStringRef(constants::kDeviceTrustSigningKeyLabel)); + auto label = GetLabelFromKeyType(new_key_type); + if (label.empty()) + return false; - return helper_->Update(CreateQueryForKey(KeyType::kTemporary), + CFDictionarySetValue(attributes_to_update, kSecAttrLabel, + base::SysUTF8ToCFStringRef(label)); + + return helper_->Update(CreateQueryForKey(current_key_type), attributes_to_update); }
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client_unittest.mm b/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client_unittest.mm index 4453395..4f88769 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client_unittest.mm +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_client_unittest.mm
@@ -36,7 +36,7 @@ CreateAndSetTestKey(); } - // Creates a temporary key. + // Creates a test key. void CreateAndSetTestKey() { base::ScopedCFTypeRef<CFMutableDictionaryRef> test_attributes( CFDictionaryCreateMutable(kCFAllocatorDefault, 0, @@ -71,27 +71,25 @@ base::ScopedCFTypeRef<SecKeyRef> test_key_; }; -// Tests that the CreateTemporaryKey method invokes both the SE helper's +// Tests that the CreatePermanentKey method invokes both the SE helper's // Delete and CreateSecureKey method and that the key attributes are set // correctly. TEST_F(SecureEnclaveClientTest, CreateKey) { EXPECT_CALL(*mock_secure_enclave_helper_, Delete(_)) .Times(1) .WillOnce([this](CFDictionaryRef query) { - VerifyQuery(query, - base::SysUTF8ToCFStringRef( - constants::kTemporaryDeviceTrustSigningKeyLabel)); + VerifyQuery(query, base::SysUTF8ToCFStringRef( + constants::kDeviceTrustSigningKeyLabel)); return true; }); EXPECT_CALL(*mock_secure_enclave_helper_, CreateSecureKey(_)) .Times(1) .WillOnce([this](CFDictionaryRef attributes) { - EXPECT_TRUE( - CFEqual(base::SysUTF8ToCFStringRef( - constants::kTemporaryDeviceTrustSigningKeyLabel), - base::mac::GetValueFromDictionary<CFStringRef>( - attributes, kSecAttrLabel))); + EXPECT_TRUE(CFEqual( + base::SysUTF8ToCFStringRef(constants::kDeviceTrustSigningKeyLabel), + base::mac::GetValueFromDictionary<CFStringRef>(attributes, + kSecAttrLabel))); EXPECT_TRUE(CFEqual(kSecAttrKeyTypeECSECPrimeRandom, base::mac::GetValueFromDictionary<CFStringRef>( attributes, kSecAttrKeyType))); @@ -109,7 +107,7 @@ private_key_attributes, kSecAttrTokenID))); return test_key_; }); - EXPECT_EQ(secure_enclave_client_->CreateTemporaryKey(), test_key_); + EXPECT_EQ(secure_enclave_client_->CreatePermanentKey(), test_key_); } // Tests when the CopyStoredKey method invokes the SE helper's CopyKey method @@ -140,9 +138,32 @@ SecureEnclaveClient::KeyType::kTemporary)); } -// Tests that the MoveTemporaryKeyToPermanent method invokes the SE helper's -// Update method and that the key attributes and query are set correctly. -TEST_F(SecureEnclaveClientTest, MoveTemporaryKeyToPermanent) { +// Tests that the UpdateStoredKeyLabel method invokes the SE helper's +// Update method and that the key attributes and query are set correctly for +// the permanent key label being updated to the temporary key label. +TEST_F(SecureEnclaveClientTest, UpdateStoredKeyLabel_PermanentToTemporary) { + EXPECT_CALL(*mock_secure_enclave_helper_, Update(_, _)) + .Times(1) + .WillOnce( + [this](CFDictionaryRef query, CFDictionaryRef attribute_to_update) { + EXPECT_TRUE( + CFEqual(base::SysUTF8ToCFStringRef( + constants::kTemporaryDeviceTrustSigningKeyLabel), + base::mac::GetValueFromDictionary<CFStringRef>( + attribute_to_update, kSecAttrLabel))); + VerifyQuery(query, base::SysUTF8ToCFStringRef( + constants::kDeviceTrustSigningKeyLabel)); + return true; + }); + EXPECT_TRUE(secure_enclave_client_->UpdateStoredKeyLabel( + SecureEnclaveClient::KeyType::kPermanent, + SecureEnclaveClient::KeyType::kTemporary)); +} + +// Tests that the UpdateStoredKeyLabel method invokes the SE helper's +// Update method and that the key attributes and query are set correctly for +// the temporary key label being updated to the permanent key label. +TEST_F(SecureEnclaveClientTest, UpdateStoredKeyLabel_TemporaryToPermanent) { EXPECT_CALL(*mock_secure_enclave_helper_, Update(_, _)) .Times(1) .WillOnce([this](CFDictionaryRef query, @@ -156,7 +177,9 @@ constants::kTemporaryDeviceTrustSigningKeyLabel)); return true; }); - EXPECT_TRUE(secure_enclave_client_->MoveTemporaryKeyToPermanent()); + EXPECT_TRUE(secure_enclave_client_->UpdateStoredKeyLabel( + SecureEnclaveClient::KeyType::kTemporary, + SecureEnclaveClient::KeyType::kPermanent)); } // Tests that the DeleteKey method invokes the SE helper's Delete method
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_signing_key.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_signing_key.cc index fe73436b..aca89f38 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_signing_key.cc +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_signing_key.cc
@@ -129,7 +129,7 @@ SecureEnclaveSigningKeyProvider::GenerateSigningKeySlowly( base::span<const crypto::SignatureVerifier::SignatureAlgorithm> acceptable_algorithms) { - if (provider_key_type_ != SecureEnclaveClient::KeyType::kTemporary) + if (provider_key_type_ != SecureEnclaveClient::KeyType::kPermanent) return nullptr; auto algo = SelectAlgorithm(acceptable_algorithms); @@ -139,7 +139,7 @@ DCHECK_EQ(crypto::SignatureVerifier::ECDSA_SHA256, *algo); auto client = SecureEnclaveClient::Create(); - auto key = client->CreateTemporaryKey(); + auto key = client->CreatePermanentKey(); if (!key) return nullptr;
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_signing_key_unittest.mm b/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_signing_key_unittest.mm index ac0bd94..bf8b529 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_signing_key_unittest.mm +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/mac/secure_enclave_signing_key_unittest.mm
@@ -40,7 +40,7 @@ } protected: - // Creates a temporary key. + // Creates a test key. void CreateTestKey() { base::ScopedCFTypeRef<CFMutableDictionaryRef> test_attributes( CFDictionaryCreateMutable(kCFAllocatorDefault, 0, @@ -65,8 +65,8 @@ // Sets the unexportable key using the test key. void SetUnexportableKey() { auto provider = SecureEnclaveSigningKeyProvider( - SecureEnclaveClient::KeyType::kTemporary); - EXPECT_CALL(*mock_secure_enclave_client_, CreateTemporaryKey()) + SecureEnclaveClient::KeyType::kPermanent); + EXPECT_CALL(*mock_secure_enclave_client_, CreatePermanentKey()) .Times(1) .WillOnce([this]() { return test_key_; }); auto acceptable_algorithms = {crypto::SignatureVerifier::ECDSA_SHA256}; @@ -79,15 +79,16 @@ }; // Tests that the GenerateSigningKeySlowly method invokes the SE client's -// CreateTemporaryKey method only when the provider is a temporary key provider. +// CreatePermanentKey method only when the provider is a permanent key provider. TEST_F(SecureEnclaveSigningKeyTest, GenerateSigningKeySlowly) { auto acceptable_algorithms = {crypto::SignatureVerifier::ECDSA_SHA256}; InSequence s; auto provider = - SecureEnclaveSigningKeyProvider(SecureEnclaveClient::KeyType::kTemporary); - EXPECT_CALL(*mock_secure_enclave_client_, CreateTemporaryKey()) + SecureEnclaveSigningKeyProvider(SecureEnclaveClient::KeyType::kPermanent); + + EXPECT_CALL(*mock_secure_enclave_client_, CreatePermanentKey()) .Times(1) .WillOnce([this]() { return test_key_; }); auto unexportable_key = @@ -97,8 +98,8 @@ unexportable_key->Algorithm()); provider = - SecureEnclaveSigningKeyProvider(SecureEnclaveClient::KeyType::kPermanent); - EXPECT_CALL(*mock_secure_enclave_client_, CreateTemporaryKey()).Times(0); + SecureEnclaveSigningKeyProvider(SecureEnclaveClient::KeyType::kTemporary); + EXPECT_CALL(*mock_secure_enclave_client_, CreatePermanentKey()).Times(0); unexportable_key = provider.GenerateSigningKeySlowly(acceptable_algorithms); EXPECT_FALSE(unexportable_key); } @@ -186,12 +187,12 @@ } // Tests that the GetWrappedKey method invokes the SE client's -// GetStoredKeyLabel method and that the wrapped key label is the temporary -// key label since the SecureEnclaveSigningKey is currently a temporary key. +// GetStoredKeyLabel method and that the wrapped key label is the permanent +// key label since the SecureEnclaveSigningKey is currently a permanent key. TEST_F(SecureEnclaveSigningKeyTest, GetWrappedKey) { SetUnexportableKey(); EXPECT_CALL(*mock_secure_enclave_client_, - GetStoredKeyLabel(SecureEnclaveClient::KeyType::kTemporary, _)) + GetStoredKeyLabel(SecureEnclaveClient::KeyType::kPermanent, _)) .WillOnce( [](SecureEnclaveClient::KeyType type, std::vector<uint8_t>& output) { std::string label = @@ -202,7 +203,7 @@ return true; }); auto wrapped = key_->GetWrappedKey(); - EXPECT_EQ(constants::kTemporaryDeviceTrustSigningKeyLabel, + EXPECT_EQ(constants::kDeviceTrustSigningKeyLabel, std::string(wrapped.begin(), wrapped.end())); }
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h index 997b583..4ceda4f 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/key_persistence_delegate.h
@@ -46,6 +46,12 @@ // BPKUR::CHROME_BROWSER_OS_KEY is created if available. If neither are // available, a nullptr is returned. virtual std::unique_ptr<SigningKeyPair> CreateKeyPair() = 0; + + // Deletes the signing key in the temporary key storage after a successful + // key rotation. This method is only overridden in Mac platforms since signing + // key rollback is handled in the StoreKeyPair method in Linux and Windows + // platforms. + virtual void CleanupTemporaryKeyData() {} }; } // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.cc index d5d0517..2923b17 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.cc +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.cc
@@ -35,4 +35,8 @@ return nullptr; } +void MacKeyPersistenceDelegate::CleanupTemporaryKeyData() { + NOTIMPLEMENTED(); +} + } // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.h index 1ada540..c093e1fb 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.h +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mac_key_persistence_delegate.h
@@ -25,6 +25,7 @@ std::vector<uint8_t> wrapped) override; std::unique_ptr<SigningKeyPair> LoadKeyPair() override; std::unique_ptr<SigningKeyPair> CreateKeyPair() override; + void CleanupTemporaryKeyData() override; }; } // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.h b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.h index f8f76d2..840eb1f 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.h +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/core/persistence/mock_key_persistence_delegate.h
@@ -32,6 +32,7 @@ CreateKeyPair, (), (override)); + MOCK_METHOD(void, CleanupTemporaryKeyData, (), (override)); }; } // namespace test
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.cc index 189c710..89d9f33 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.cc +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.cc
@@ -181,6 +181,7 @@ std::move(result_callback).Run(false); return; } + persistence_delegate_->CleanupTemporaryKeyData(); key_pair_ = std::move(new_key_pair); RecordRotationStatus(nonce, RotationStatus::SUCCESS); std::move(result_callback).Run(true);
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_unittest.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_unittest.cc index ec43a00..20961f04 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_unittest.cc +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_unittest.cc
@@ -116,6 +116,7 @@ captured_body = body; std::move(callback).Run(kSuccessCode); })); + EXPECT_CALL(*mock_persistence_delegate, CleanupTemporaryKeyData()); auto manager = KeyRotationManager::CreateForTesting( std::move(mock_network_delegate), std::move(mock_persistence_delegate)); @@ -171,6 +172,7 @@ base::OnceCallback<void(int)> callback) { std::move(callback).Run(kSuccessCode); })); + EXPECT_CALL(*mock_persistence_delegate, CleanupTemporaryKeyData()); auto manager = KeyRotationManager::CreateForTesting( std::move(mock_network_delegate), std::move(mock_persistence_delegate)); @@ -213,6 +215,7 @@ base::OnceCallback<void(int)> callback) { std::move(callback).Run(kSuccessCode); })); + EXPECT_CALL(*mock_persistence_delegate, CleanupTemporaryKeyData()); auto manager = KeyRotationManager::CreateForTesting( std::move(mock_network_delegate), std::move(mock_persistence_delegate)); @@ -445,6 +448,7 @@ base::OnceCallback<void(int)> callback) { std::move(callback).Run(kSuccessCode); })); + EXPECT_CALL(*mock_persistence_delegate, CleanupTemporaryKeyData()); auto manager = KeyRotationManager::CreateForTesting( std::move(mock_network_delegate), std::move(mock_persistence_delegate));
diff --git a/chrome/browser/extensions/api/commands/command_service.cc b/chrome/browser/extensions/api/commands/command_service.cc index 2c95d52a..87ea997b 100644 --- a/chrome/browser/extensions/api/commands/command_service.cc +++ b/chrome/browser/extensions/api/commands/command_service.cc
@@ -554,23 +554,19 @@ void CommandService::RemoveDefunctExtensionSuggestedCommandPrefs( const Extension* extension) { ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile_); - const base::DictionaryValue* current_prefs = nullptr; - extension_prefs->ReadPrefAsDictionary(extension->id(), - kCommands, - ¤t_prefs); + const base::Value::Dict* current_prefs = + extension_prefs->ReadPrefAsDict(extension->id(), kCommands); if (current_prefs) { - std::unique_ptr<base::DictionaryValue> suggested_key_prefs = - base::DictionaryValue::From( - base::Value::ToUniquePtrValue(current_prefs->Clone())); + base::Value::Dict suggested_key_prefs = current_prefs->Clone(); + const CommandMap* named_commands = CommandsInfo::GetNamedCommands(extension); const Command* browser_action_command = CommandsInfo::GetBrowserActionCommand(extension); - for (base::DictionaryValue::Iterator it(*current_prefs); - !it.IsAtEnd(); it.Advance()) { - if (it.key() == manifest_values::kBrowserActionCommandEvent) { + for (const auto [key, _] : *current_prefs) { + if (key == manifest_values::kBrowserActionCommandEvent) { // The browser action command may be defaulted to an unassigned // accelerator if a browser action is specified by the extension but a // keybinding is not declared. See @@ -578,22 +574,23 @@ if (!browser_action_command || browser_action_command->accelerator().key_code() == ui::VKEY_UNKNOWN) { - suggested_key_prefs->RemoveKey(it.key()); + suggested_key_prefs.Remove(key); } - } else if (it.key() == manifest_values::kPageActionCommandEvent) { + } else if (key == manifest_values::kPageActionCommandEvent) { if (!CommandsInfo::GetPageActionCommand(extension)) - suggested_key_prefs->RemoveKey(it.key()); - } else if (it.key() == manifest_values::kActionCommandEvent) { + suggested_key_prefs.Remove(key); + } else if (key == manifest_values::kActionCommandEvent) { if (!CommandsInfo::GetActionCommand(extension)) - suggested_key_prefs->RemoveKey(it.key()); + suggested_key_prefs.Remove(key); } else if (named_commands) { - if (named_commands->find(it.key()) == named_commands->end()) - suggested_key_prefs->RemoveKey(it.key()); + if (named_commands->find(key) == named_commands->end()) + suggested_key_prefs.Remove(key); } } - extension_prefs->UpdateExtensionPref(extension->id(), kCommands, - std::move(suggested_key_prefs)); + extension_prefs->UpdateExtensionPref( + extension->id(), kCommands, + std::make_unique<base::Value>(std::move(suggested_key_prefs))); } }
diff --git a/chrome/browser/extensions/api/proxy/proxy_apitest.cc b/chrome/browser/extensions/api/proxy/proxy_apitest.cc index 419d674..599925fd 100644 --- a/chrome/browser/extensions/api/proxy/proxy_apitest.cc +++ b/chrome/browser/extensions/api/proxy/proxy_apitest.cc
@@ -46,8 +46,10 @@ ASSERT_TRUE(pref != NULL); EXPECT_TRUE(pref->IsExtensionControlled()); + // TODO(https://crbug.com/1348219) This should call + // `PrefService::GetValueDict`. ProxyConfigDictionary dict( - pref_service->GetDictionary(proxy_config::prefs::kProxy)->Clone()); + pref_service->GetValue(proxy_config::prefs::kProxy).Clone()); ProxyPrefs::ProxyMode mode; ASSERT_TRUE(dict.GetMode(&mode));
diff --git a/chrome/browser/extensions/api/scripting/scripting_api.cc b/chrome/browser/extensions/api/scripting/scripting_api.cc index 08ba987..23d0a10 100644 --- a/chrome/browser/extensions/api/scripting/scripting_api.cc +++ b/chrome/browser/extensions/api/scripting/scripting_api.cc
@@ -682,10 +682,12 @@ : mojom::RunLocation::kDocumentIdle; script_executor->ExecuteScript( mojom::HostID(mojom::HostID::HostType::kExtensions, extension()->id()), - mojom::CodeInjection::NewJs( - mojom::JSInjection::New(std::move(sources), execution_world, - /*wants_result=*/true, user_gesture(), - /*wait_for_promise=*/true)), + mojom::CodeInjection::NewJs(mojom::JSInjection::New( + std::move(sources), execution_world, + blink::mojom::WantResultOption::kWantResult, + user_gesture() ? blink::mojom::UserActivationOption::kActivate + : blink::mojom::UserActivationOption::kDoNotActivate, + blink::mojom::PromiseResultOption::kAwait)), frame_scope, frame_ids, ScriptExecutor::MATCH_ABOUT_BLANK, run_location, ScriptExecutor::DEFAULT_PROCESS, /* webview_src */ GURL(),
diff --git a/chrome/browser/extensions/extension_web_ui.cc b/chrome/browser/extensions/extension_web_ui.cc index bec13da5..4c136ca 100644 --- a/chrome/browser/extensions/extension_web_ui.cc +++ b/chrome/browser/extensions/extension_web_ui.cc
@@ -355,13 +355,11 @@ DCHECK(url.SchemeIs(content::kChromeUIScheme)); Profile* profile = Profile::FromBrowserContext(browser_context); - const base::Value* overrides = profile->GetPrefs()->GetDictionary( - ExtensionWebUI::kExtensionURLOverrides); + const base::Value::Dict& overrides = + profile->GetPrefs()->GetValueDict(ExtensionWebUI::kExtensionURLOverrides); - if (!overrides) - return {}; // No overrides present for this host. - - const base::Value* url_list = overrides->FindListPath(url.host_piece()); + const base::Value::List* url_list = + overrides.FindListByDottedPath(url.host_piece()); if (!url_list) return {}; // No overrides present for this host. @@ -374,7 +372,7 @@ std::vector<GURL> component_overrides; // Iterate over the URL list looking for suitable overrides. - for (const auto& value : url_list->GetListDeprecated()) { + for (const auto& value : *url_list) { GURL override_url; const Extension* extension = nullptr; if (!ValidateOverrideURL(&value, url, extensions, &override_url,
diff --git a/chrome/browser/extensions/script_executor_browsertest.cc b/chrome/browser/extensions/script_executor_browsertest.cc index 12a395a..b05581e 100644 --- a/chrome/browser/extensions/script_executor_browsertest.cc +++ b/chrome/browser/extensions/script_executor_browsertest.cc
@@ -133,8 +133,9 @@ mojom::HostID(mojom::HostID::HostType::kExtensions, extension->id()), mojom::CodeInjection::NewJs(mojom::JSInjection::New( std::move(sources), mojom::ExecutionWorld::kMain, - true /* wants_result */, false /* user_gesture */, - true /* wait_for_promise */)), + blink::mojom::WantResultOption::kWantResult, + blink::mojom::UserActivationOption::kDoNotActivate, + blink::mojom::PromiseResultOption::kAwait)), ScriptExecutor::SPECIFIED_FRAMES, {ExtensionApiFrameIdMap::kTopFrameId}, ScriptExecutor::DONT_MATCH_ABOUT_BLANK, mojom::RunLocation::kDocumentIdle, ScriptExecutor::DEFAULT_PROCESS, GURL() /* webview_src */, @@ -181,8 +182,9 @@ mojom::HostID(mojom::HostID::HostType::kExtensions, extension->id()), mojom::CodeInjection::NewJs(mojom::JSInjection::New( std::move(sources), mojom::ExecutionWorld::kIsolated, - true /* wants_result */, false /* user_gesture */, - true /* wait_for_promise */)), + blink::mojom::WantResultOption::kWantResult, + blink::mojom::UserActivationOption::kDoNotActivate, + blink::mojom::PromiseResultOption::kAwait)), ScriptExecutor::SPECIFIED_FRAMES, {ExtensionApiFrameIdMap::kTopFrameId}, ScriptExecutor::DONT_MATCH_ABOUT_BLANK, mojom::RunLocation::kDocumentIdle, ScriptExecutor::DEFAULT_PROCESS, GURL() /* webview_src */, @@ -236,8 +238,9 @@ mojom::HostID(mojom::HostID::HostType::kExtensions, extension->id()), mojom::CodeInjection::NewJs(mojom::JSInjection::New( std::move(sources), mojom::ExecutionWorld::kIsolated, - true /* wants_result */, false /* user_gesture */, - true /* wait_for_promise */)), + blink::mojom::WantResultOption::kWantResult, + blink::mojom::UserActivationOption::kDoNotActivate, + blink::mojom::PromiseResultOption::kAwait)), ScriptExecutor::SPECIFIED_FRAMES, {ExtensionApiFrameIdMap::kTopFrameId}, ScriptExecutor::DONT_MATCH_ABOUT_BLANK, mojom::RunLocation::kDocumentIdle, ScriptExecutor::DEFAULT_PROCESS, GURL() /* webview_src */, @@ -301,8 +304,9 @@ mojom::HostID(mojom::HostID::HostType::kExtensions, extension->id()), mojom::CodeInjection::NewJs(mojom::JSInjection::New( std::move(sources), mojom::ExecutionWorld::kIsolated, - true /* wants_result */, false /* user_gesture */, - true /* wait_for_promise */)), + blink::mojom::WantResultOption::kWantResult, + blink::mojom::UserActivationOption::kDoNotActivate, + blink::mojom::PromiseResultOption::kAwait)), ScriptExecutor::SPECIFIED_FRAMES, {ExtensionApiFrameIdMap::kTopFrameId}, ScriptExecutor::DONT_MATCH_ABOUT_BLANK, mojom::RunLocation::kDocumentIdle, ScriptExecutor::DEFAULT_PROCESS, @@ -330,8 +334,9 @@ mojom::HostID(mojom::HostID::HostType::kExtensions, extension->id()), mojom::CodeInjection::NewJs(mojom::JSInjection::New( std::move(sources), mojom::ExecutionWorld::kIsolated, - true /* wants_result */, false /* user_gesture */, - false /* wait_for_promise */)), + blink::mojom::WantResultOption::kWantResult, + blink::mojom::UserActivationOption::kDoNotActivate, + blink::mojom::PromiseResultOption::kDoNotWait)), ScriptExecutor::SPECIFIED_FRAMES, {ExtensionApiFrameIdMap::kTopFrameId}, ScriptExecutor::DONT_MATCH_ABOUT_BLANK, mojom::RunLocation::kDocumentIdle, ScriptExecutor::DEFAULT_PROCESS, @@ -416,8 +421,9 @@ mojom::HostID(mojom::HostID::HostType::kExtensions, extension->id()), mojom::CodeInjection::NewJs(mojom::JSInjection::New( std::move(sources), mojom::ExecutionWorld::kIsolated, - true /* wants_result */, false /* user_gesture */, - true /* wait_for_promise */)), + blink::mojom::WantResultOption::kWantResult, + blink::mojom::UserActivationOption::kDoNotActivate, + blink::mojom::PromiseResultOption::kAwait)), ScriptExecutor::SPECIFIED_FRAMES, {frame1_id, frame2_id}, ScriptExecutor::DONT_MATCH_ABOUT_BLANK, mojom::RunLocation::kDocumentIdle, ScriptExecutor::DEFAULT_PROCESS, @@ -440,8 +446,9 @@ mojom::HostID(mojom::HostID::HostType::kExtensions, extension->id()), mojom::CodeInjection::NewJs(mojom::JSInjection::New( std::move(sources), mojom::ExecutionWorld::kIsolated, - true /* wants_result */, false /* user_gesture */, - true /* wait_for_promise */)), + blink::mojom::WantResultOption::kWantResult, + blink::mojom::UserActivationOption::kDoNotActivate, + blink::mojom::PromiseResultOption::kAwait)), ScriptExecutor::INCLUDE_SUB_FRAMES, {frame1_id, frame2_id}, ScriptExecutor::DONT_MATCH_ABOUT_BLANK, mojom::RunLocation::kDocumentIdle, ScriptExecutor::DEFAULT_PROCESS, @@ -473,8 +480,9 @@ mojom::HostID(mojom::HostID::HostType::kExtensions, extension->id()), mojom::CodeInjection::NewJs(mojom::JSInjection::New( std::move(sources), mojom::ExecutionWorld::kIsolated, - true /* wants_result */, false /* user_gesture */, - true /* wait_for_promise */)), + blink::mojom::WantResultOption::kWantResult, + blink::mojom::UserActivationOption::kDoNotActivate, + blink::mojom::PromiseResultOption::kAwait)), ScriptExecutor::SPECIFIED_FRAMES, {frame1_id, frame2_id, kNonExistentFrameId}, ScriptExecutor::DONT_MATCH_ABOUT_BLANK, @@ -499,8 +507,9 @@ mojom::HostID(mojom::HostID::HostType::kExtensions, extension->id()), mojom::CodeInjection::NewJs(mojom::JSInjection::New( std::move(sources), mojom::ExecutionWorld::kIsolated, - true /* wants_result */, false /* user_gesture */, - true /* wait_for_promise */)), + blink::mojom::WantResultOption::kWantResult, + blink::mojom::UserActivationOption::kDoNotActivate, + blink::mojom::PromiseResultOption::kAwait)), ScriptExecutor::SPECIFIED_FRAMES, {kNonExistentFrameId}, ScriptExecutor::DONT_MATCH_ABOUT_BLANK, mojom::RunLocation::kDocumentIdle, ScriptExecutor::DEFAULT_PROCESS,
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 1a70ed48..4ae2e3f 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -791,7 +791,7 @@ { "name": "canvas-oop-rasterization", "owners": [ "junov", "vasilyt" ], - "expiry_milestone": 105 + "expiry_milestone": 110 }, { "name": "cct-brand-transparency", @@ -5421,12 +5421,12 @@ { "name": "read-later", "owners": [ "chrome-desktop-ui-sea@google.com", "corising", "wylieb", "chrome-collections@google.com" ], - "expiry_milestone": 105 + "expiry_milestone": 110 }, { "name": "read-later-reminder-notification", "owners": [ "wylieb" ], - "expiry_milestone": 102 + "expiry_milestone": 110 }, { "name": "read-printer-capabilities-with-xps", @@ -5463,6 +5463,11 @@ "expiry_milestone": 112 }, { + "name": "reduce-gpu-priority-on-background", + "owners": [ "boliu" ], + "expiry_milestone": 108 + }, + { "name": "reduce-horizontal-fling-velocity", "owners": [ "flackr", "input-dev" ], "expiry_milestone": 95
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index db30769..2381b58 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -3707,6 +3707,12 @@ "Enables showing UI which allows for easy reverting of the decision to " "never save passwords on a certain webiste"; +const char kReduceGpuPriorityOnBackgroundName[] = + "Reduce GPU process priority when in background"; +const char kReduceGpuPriorityOnBackgroundDescription[] = + "Enable to reduce GPU process priority when Chrome is the background. " + "This hints to Android OS to kill GPU process first to free memory."; + const char kReengagementNotificationName[] = "Enable re-engagement notifications"; const char kReengagementNotificationDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 9ecb665..0b25f85f 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -2113,6 +2113,9 @@ extern const char kRecoverFromNeverSaveAndroidName[]; extern const char kRecoverFromNeverSaveAndroidDescription[]; +extern const char kReduceGpuPriorityOnBackgroundName[]; +extern const char kReduceGpuPriorityOnBackgroundDescription[]; + extern const char kReengagementNotificationName[]; extern const char kReengagementNotificationDescription[];
diff --git a/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc b/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc index ca7dabc..8c45956 100644 --- a/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc +++ b/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc
@@ -14,6 +14,7 @@ #include "components/permissions/permission_request_manager.h" #include "components/permissions/permission_result.h" #include "components/permissions/test/mock_permission_prompt_factory.h" +#include "content/public/browser/permission_result.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/permissions/permission_utils.h" @@ -84,12 +85,12 @@ std::move(callback))); } - permissions::PermissionResult GetPermissionStatusForDisplayOnSettingsUI( + content::PermissionResult GetPermissionResultForOriginWithoutContext( Profile* profile, - ContentSettingsType permission, - const GURL& origin) { + blink::PermissionType permission, + const url::Origin& origin) { return PermissionManagerFactory::GetForProfile(profile) - ->GetPermissionStatusForDisplayOnSettingsUI(permission, origin); + ->GetPermissionResultForOriginWithoutContext(permission, origin); } }; @@ -125,7 +126,7 @@ // TODO(https://crbug.com/1318240): Flaky. TEST_F(GeolocationPermissionContextDelegateTests, DISABLED_SearchGeolocationInIncognito) { - GURL requesting_frame_url(kDSETestUrl); + url::Origin requesting_frame_url = url::Origin::Create(GURL(kDSETestUrl)); SearchPermissionsService* service = SearchPermissionsService::Factory::GetForBrowserContext(profile()); @@ -136,19 +137,19 @@ // The DSE geolocation should not be auto-granted even in a non-OTR profile. ASSERT_EQ( - CONTENT_SETTING_ASK, - GetPermissionStatusForDisplayOnSettingsUI( - profile(), ContentSettingsType::GEOLOCATION, requesting_frame_url) - .content_setting); + blink::mojom::PermissionStatus::ASK, + GetPermissionResultForOriginWithoutContext( + profile(), blink::PermissionType::GEOLOCATION, requesting_frame_url) + .status); Profile* otr_profile = profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true); // The DSE geolocation should not be auto-granted in an OTR profile. ASSERT_EQ( - CONTENT_SETTING_ASK, - GetPermissionStatusForDisplayOnSettingsUI( - otr_profile, ContentSettingsType::GEOLOCATION, requesting_frame_url) - .content_setting); + blink::mojom::PermissionStatus::ASK, + GetPermissionResultForOriginWithoutContext( + otr_profile, blink::PermissionType::GEOLOCATION, requesting_frame_url) + .status); } #endif
diff --git a/chrome/browser/history_clusters/BUILD.gn b/chrome/browser/history_clusters/BUILD.gn index 4bfc7ede6..23a9848 100644 --- a/chrome/browser/history_clusters/BUILD.gn +++ b/chrome/browser/history_clusters/BUILD.gn
@@ -55,6 +55,7 @@ "//chrome/browser/tabmodel:java", "//chrome/browser/ui/android/favicon:java", "//chrome/browser/ui/android/strings:ui_strings_grd", + "//chrome/browser/ui/messages/android:java", "//components/browser_ui/styles/android:java", "//components/browser_ui/widget/android:java", "//components/embedder_support/android:util_java",
diff --git a/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinator.java b/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinator.java index 9524fca..a8d2aa75 100644 --- a/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinator.java +++ b/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinator.java
@@ -18,12 +18,16 @@ import org.chromium.chrome.browser.history_clusters.HistoryClustersItemProperties.ItemType; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; +import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; +import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarController; import org.chromium.components.browser_ui.widget.selectable_list.SelectableItemView; import org.chromium.components.browser_ui.widget.selectable_list.SelectableListLayout; import org.chromium.components.browser_ui.widget.selectable_list.SelectableListToolbar; import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate; import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.search_engines.TemplateUrlService; +import org.chromium.ui.base.Clipboard; import org.chromium.ui.modelutil.MVCListAdapter.ModelList; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; @@ -34,7 +38,7 @@ * Root component for the HistoryClusters UI component, which displays lists of related history * visits grouped into clusters. */ -public class HistoryClustersCoordinator implements OnMenuItemClickListener { +public class HistoryClustersCoordinator implements OnMenuItemClickListener, SnackbarController { private static class DisabledSelectionDelegate extends SelectionDelegate { @Override public boolean toggleSelectionForItem(Object o) { @@ -66,13 +70,14 @@ private SelectionDelegate mDisabledSelectionDelegate = new DisabledSelectionDelegate(); private RecyclerView mRecyclerView; private final HistoryClustersMetricsLogger mMetricsLogger; + private final SnackbarManager mSnackbarManager; @VisibleForTesting HistoryClustersCoordinator(@NonNull Profile profile, @NonNull Activity activity, TemplateUrlService templateUrlService, HistoryClustersDelegate historyClustersDelegate, HistoryClustersMetricsLogger metricsLogger, - SelectionDelegate<ClusterVisit> selectionDelegate, - AccessibilityUtil accessibilityUtil) { + SelectionDelegate<ClusterVisit> selectionDelegate, AccessibilityUtil accessibilityUtil, + SnackbarManager snackbarManager) { mActivity = activity; mDelegate = historyClustersDelegate; mModelList = new ModelList(); @@ -82,6 +87,7 @@ .build(); mMetricsLogger = metricsLogger; mSelectionDelegate = selectionDelegate; + mSnackbarManager = snackbarManager; mMediator = new HistoryClustersMediator(HistoryClustersBridge.getForProfile(profile), new LargeIconBridge(profile), mActivity, mActivity.getResources(), mModelList, @@ -96,13 +102,14 @@ * @param historyClustersDelegate Delegate that provides functionality that must be implemented * externally, e.g. populating intents targeting activities we can't reference directly. * @param accessibilityUtil Utility object that tells us about the current accessibility state. + * @param snackbarManager The {@link SnackbarManager} used to display snackbars. */ public HistoryClustersCoordinator(@NonNull Profile profile, @NonNull Activity activity, TemplateUrlService templateUrlService, HistoryClustersDelegate historyClustersDelegate, - AccessibilityUtil accessibilityUtil) { + AccessibilityUtil accessibilityUtil, SnackbarManager snackbarManager) { this(profile, activity, templateUrlService, historyClustersDelegate, new HistoryClustersMetricsLogger(templateUrlService), new SelectionDelegate<>(), - accessibilityUtil); + accessibilityUtil, snackbarManager); } public void destroy() { @@ -260,10 +267,26 @@ } else if (menuItem.getItemId() == R.id.selection_mode_open_in_tab_group) { mMediator.openVisitsInNewTabs(mSelectionDelegate.getSelectedItemsAsList(), false, true); return true; + } else if (menuItem.getItemId() == R.id.selection_mode_copy_link) { + Clipboard.getInstance().setText(mSelectionDelegate.getSelectedItemsAsList() + .get(0) + .getNormalizedUrl() + .getSpec()); + mSelectionDelegate.clearSelection(); + Snackbar snackbar = Snackbar.make(mActivity.getString(R.string.copied), this, + Snackbar.TYPE_NOTIFICATION, Snackbar.UMA_HISTORY_LINK_COPIED); + mSnackbarManager.showSnackbar(snackbar); } return false; } + // SnackbarController implementation. + @Override + public void onAction(Object actionData) {} + + @Override + public void onDismissNoAction(Object actionData) {} + @VisibleForTesting public RecyclerView getRecyclerViewFortesting() { return mRecyclerView;
diff --git a/chrome/browser/login_detection/login_detection_keyed_service_factory.cc b/chrome/browser/login_detection/login_detection_keyed_service_factory.cc index 7bdbfdb..3b19867 100644 --- a/chrome/browser/login_detection/login_detection_keyed_service_factory.cc +++ b/chrome/browser/login_detection/login_detection_keyed_service_factory.cc
@@ -18,7 +18,7 @@ ProfileSelections BuildLoginDetectionProfileSelection() { if (!IsLoginDetectionFeatureEnabled()) { - return ProfileSelections::BuildNoServicesForAllProfiles(); + return ProfileSelections::BuildNoProfilesSelected(); } return ProfileSelections::BuildDefault();
diff --git a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc index 023466f..2dbfa31 100644 --- a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc +++ b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc
@@ -14,12 +14,10 @@ #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" #include "chrome/browser/media/webrtc/media_stream_device_permissions.h" -#include "chrome/browser/permissions/permission_manager_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" #include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" -#include "components/permissions/permission_manager.h" #include "components/permissions/permission_result.h" #include "components/permissions/permission_util.h" #include "components/permissions/permissions_client.h" @@ -122,7 +120,7 @@ // Otherwise, the Microphone permission request on NTP will be gated for // incorrect origin. GURL embedding_origin; - if (permissions::PermissionsClient::Get()->DoOriginsMatchNewTabPage( + if (permissions::PermissionsClient::Get()->DoURLsMatchNewTabPage( request.security_origin, web_contents->GetLastCommittedURL().DeprecatedGetOriginAsURL())) { embedding_origin = @@ -133,7 +131,7 @@ } content_settings->OnMediaStreamPermissionSet( - PermissionManagerFactory::GetForProfile(profile)->GetCanonicalOrigin( + permissions::PermissionUtil::GetCanonicalOrigin( ContentSettingsType::MEDIASTREAM_CAMERA, request.security_origin, embedding_origin), microphone_camera_state, selected_audio_device, selected_video_device,
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc index 12556b1..393ae70 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -20,6 +20,7 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/lazy_instance.h" +#include "base/memory/ptr_util.h" #include "base/memory/raw_ptr.h" #include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_macros.h" @@ -127,7 +128,7 @@ #include "components/metrics/android_metrics_provider.h" #else #include "chrome/browser/metrics/browser_activity_watcher.h" -#include "components/performance_manager/public/metrics/metrics_provider.h" +#include "chrome/browser/performance_manager/metrics/metrics_provider.h" #endif #if BUILDFLAG(IS_POSIX) @@ -785,7 +786,7 @@ std::make_unique<FamilyLinkUserMetricsProvider>()); #else metrics_service_->RegisterMetricsProvider( - std::make_unique<performance_manager::MetricsProvider>(local_state)); + base::WrapUnique(new performance_manager::MetricsProvider(local_state))); #endif // BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_WIN)
diff --git a/chrome/browser/net/cookie_policy_browsertest.cc b/chrome/browser/net/cookie_policy_browsertest.cc index c5408a8..6b0fddec 100644 --- a/chrome/browser/net/cookie_policy_browsertest.cc +++ b/chrome/browser/net/cookie_policy_browsertest.cc
@@ -291,7 +291,8 @@ bool expected) { switch (test_type) { case TestType::kFrame: - storage::test::ExpectStorageForFrame(frame, expected); + storage::test::ExpectStorageForFrame(frame, /*include_cookies=*/true, + expected); return; case TestType::kWorker: storage::test::ExpectStorageForWorker(frame, expected); @@ -302,7 +303,7 @@ void SetStorage(TestType test_type, content::RenderFrameHost* frame) { switch (test_type) { case TestType::kFrame: - storage::test::SetStorageForFrame(frame); + storage::test::SetStorageForFrame(frame, /*include_cookies=*/true); return; case TestType::kWorker: storage::test::SetStorageForWorker(frame);
diff --git a/chrome/browser/net/profile_network_context_service_browsertest.cc b/chrome/browser/net/profile_network_context_service_browsertest.cc index 889e3f3..ed870f2b 100644 --- a/chrome/browser/net/profile_network_context_service_browsertest.cc +++ b/chrome/browser/net/profile_network_context_service_browsertest.cc
@@ -57,6 +57,7 @@ #include "content/public/common/content_features.h" #include "content/public/test/browser_test.h" #include "content/public/test/simple_url_loader_test_helper.h" +#include "content/public/test/test_cert_verifier_service_factory.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/system/data_pipe_utils.h" #include "net/base/features.h" @@ -70,7 +71,6 @@ #include "net/test/embedded_test_server/request_handler_util.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h" -#include "services/cert_verifier/test_cert_verifier_service_factory.h" #include "services/network/public/cpp/cors/cors.h" #include "services/network/public/cpp/features.h" #include "services/network/public/mojom/network_context.mojom.h"
diff --git a/chrome/browser/net/storage_test_utils.cc b/chrome/browser/net/storage_test_utils.cc index 5beb600..a9b53553 100644 --- a/chrome/browser/net/storage_test_utils.cc +++ b/chrome/browser/net/storage_test_utils.cc
@@ -8,10 +8,12 @@ namespace storage::test { +const std::vector<std::string> kCookiesTypesForFrame{"Cookie", "CookieStore"}; + const std::vector<std::string> kStorageTypesForFrame{ - "Cookie", "LocalStorage", "FileSystem", "FileSystemAccess", - "SessionStorage", "IndexedDb", "WebSql", "CacheStorage", - "ServiceWorker", "CookieStore", "StorageFoundation"}; + "LocalStorage", "FileSystem", "FileSystemAccess", + "SessionStorage", "IndexedDb", "WebSql", + "CacheStorage", "ServiceWorker", "StorageFoundation"}; const std::vector<std::string> kStorageTypesForWorker{ "WorkerFileSystemAccess", "WorkerCacheStorage", "WorkerIndexedDb", @@ -34,14 +36,23 @@ " () => { window.domAutomationController.send(false); }," ");"; +std::vector<std::string> GetStorageTypesForFrame(bool include_cookies) { + std::vector<std::string> types(kStorageTypesForFrame); + if (include_cookies) { + types.insert(types.end(), kCookiesTypesForFrame.begin(), + kCookiesTypesForFrame.end()); + } + return types; +} + std::string GetFrameContent(content::RenderFrameHost* frame) { return content::EvalJs(frame, "document.body.textContent").ExtractString(); } -void SetStorageForFrame(content::RenderFrameHost* frame) { +void SetStorageForFrame(content::RenderFrameHost* frame, bool include_cookies) { base::flat_map<std::string, bool> actual; base::flat_map<std::string, bool> expected; - for (const auto& data_type : kStorageTypesForFrame) { + for (const auto& data_type : GetStorageTypesForFrame(include_cookies)) { actual[data_type] = content::EvalJs(frame, "set" + data_type + "()", content::EXECUTE_SCRIPT_USE_MANUAL_REPLY) @@ -71,10 +82,12 @@ EXPECT_THAT(actual, testing::UnorderedElementsAreArray(expected)); } -void ExpectStorageForFrame(content::RenderFrameHost* frame, bool expected) { +void ExpectStorageForFrame(content::RenderFrameHost* frame, + bool include_cookies, + bool expected) { base::flat_map<std::string, bool> actual; base::flat_map<std::string, bool> expected_elts; - for (const auto& data_type : kStorageTypesForFrame) { + for (const auto& data_type : GetStorageTypesForFrame(include_cookies)) { actual[data_type] = content::EvalJs(frame, "has" + data_type + "();", content::EXECUTE_SCRIPT_USE_MANUAL_REPLY)
diff --git a/chrome/browser/net/storage_test_utils.h b/chrome/browser/net/storage_test_utils.h index 274f663b..bfabd381 100644 --- a/chrome/browser/net/storage_test_utils.h +++ b/chrome/browser/net/storage_test_utils.h
@@ -19,9 +19,11 @@ // Helpers to set and check various types of storage on a given frame. Typically // used on page like //chrome/test/data/browsing_data/site_data.html -void SetStorageForFrame(content::RenderFrameHost* frame); +void SetStorageForFrame(content::RenderFrameHost* frame, bool include_cookies); void SetStorageForWorker(content::RenderFrameHost* frame); -void ExpectStorageForFrame(content::RenderFrameHost* frame, bool expected); +void ExpectStorageForFrame(content::RenderFrameHost* frame, + bool include_cookies, + bool expected); void ExpectStorageForWorker(content::RenderFrameHost* frame, bool expected); // Helpers to set and check various types of cross tab info for a given frame.
diff --git a/chrome/browser/net/system_network_context_manager_browsertest.cc b/chrome/browser/net/system_network_context_manager_browsertest.cc index 42b69ed5..c73337ac 100644 --- a/chrome/browser/net/system_network_context_manager_browsertest.cc +++ b/chrome/browser/net/system_network_context_manager_browsertest.cc
@@ -35,11 +35,11 @@ #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/frame_test_utils.h" +#include "content/public/test/test_cert_verifier_service_factory.h" #include "content/public/test/test_utils.h" #include "net/cookies/canonical_cookie_test_helpers.h" #include "net/dns/mock_host_resolver.h" #include "net/net_buildflags.h" -#include "services/cert_verifier/test_cert_verifier_service_factory.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/network_service_buildflags.h" #include "services/network/public/mojom/network_context.mojom.h"
diff --git a/chrome/browser/notifications/chrome_ash_message_center_client_unittest.cc b/chrome/browser/notifications/chrome_ash_message_center_client_unittest.cc index 7c284cda..b63879a 100644 --- a/chrome/browser/notifications/chrome_ash_message_center_client_unittest.cc +++ b/chrome/browser/notifications/chrome_ash_message_center_client_unittest.cc
@@ -26,6 +26,7 @@ #include "components/permissions/test/permission_test_util.h" #include "components/user_manager/scoped_user_manager.h" #include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "content/public/test/browser_task_environment.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" @@ -251,19 +252,21 @@ // (1) Enable the permission when the default is to ask (expected to set). message_center_client()->SetNotifierEnabled(notifier_id, true); - EXPECT_EQ(blink::mojom::PermissionStatus::GRANTED, - profile->GetPermissionController() - ->GetPermissionStatusForOriginWithoutContext( - blink::PermissionType::NOTIFICATIONS, - url::Origin::Create(origin))); + EXPECT_EQ( + blink::mojom::PermissionStatus::GRANTED, + profile->GetPermissionController() + ->GetPermissionResultForOriginWithoutContext( + blink::PermissionType::NOTIFICATIONS, url::Origin::Create(origin)) + .status); // (2) Disable the permission when the default is to ask (expected to clear). message_center_client()->SetNotifierEnabled(notifier_id, false); - EXPECT_EQ(blink::mojom::PermissionStatus::ASK, - profile->GetPermissionController() - ->GetPermissionStatusForOriginWithoutContext( - blink::PermissionType::NOTIFICATIONS, - url::Origin::Create(origin))); + EXPECT_EQ( + blink::mojom::PermissionStatus::ASK, + profile->GetPermissionController() + ->GetPermissionResultForOriginWithoutContext( + blink::PermissionType::NOTIFICATIONS, url::Origin::Create(origin)) + .status); // Change the default content setting vaule for notifications to ALLOW. HostContentSettingsMapFactory::GetForProfile(profile) @@ -272,20 +275,22 @@ // (3) Disable the permission when the default is allowed (expected to set). message_center_client()->SetNotifierEnabled(notifier_id, false); - EXPECT_EQ(blink::mojom::PermissionStatus::DENIED, - profile->GetPermissionController() - ->GetPermissionStatusForOriginWithoutContext( - blink::PermissionType::NOTIFICATIONS, - url::Origin::Create(origin))); + EXPECT_EQ( + blink::mojom::PermissionStatus::DENIED, + profile->GetPermissionController() + ->GetPermissionResultForOriginWithoutContext( + blink::PermissionType::NOTIFICATIONS, url::Origin::Create(origin)) + .status); // (4) Enable the permission when the default is allowed (expected to clear). message_center_client()->SetNotifierEnabled(notifier_id, true); - EXPECT_EQ(blink::mojom::PermissionStatus::GRANTED, - profile->GetPermissionController() - ->GetPermissionStatusForOriginWithoutContext( - blink::PermissionType::NOTIFICATIONS, - url::Origin::Create(origin))); + EXPECT_EQ( + blink::mojom::PermissionStatus::GRANTED, + profile->GetPermissionController() + ->GetPermissionResultForOriginWithoutContext( + blink::PermissionType::NOTIFICATIONS, url::Origin::Create(origin)) + .status); // Now change the default content setting value to BLOCK. HostContentSettingsMapFactory::GetForProfile(profile) @@ -294,19 +299,21 @@ // (5) Enable the permission when the default is blocked (expected to set). message_center_client()->SetNotifierEnabled(notifier_id, true); - EXPECT_EQ(blink::mojom::PermissionStatus::GRANTED, - profile->GetPermissionController() - ->GetPermissionStatusForOriginWithoutContext( - blink::PermissionType::NOTIFICATIONS, - url::Origin::Create(origin))); + EXPECT_EQ( + blink::mojom::PermissionStatus::GRANTED, + profile->GetPermissionController() + ->GetPermissionResultForOriginWithoutContext( + blink::PermissionType::NOTIFICATIONS, url::Origin::Create(origin)) + .status); // (6) Disable the permission when the default is blocked (expected to clear). message_center_client()->SetNotifierEnabled(notifier_id, false); - EXPECT_EQ(blink::mojom::PermissionStatus::DENIED, - profile->GetPermissionController() - ->GetPermissionStatusForOriginWithoutContext( - blink::PermissionType::NOTIFICATIONS, - url::Origin::Create(origin))); + EXPECT_EQ( + blink::mojom::PermissionStatus::DENIED, + profile->GetPermissionController() + ->GetPermissionResultForOriginWithoutContext( + blink::PermissionType::NOTIFICATIONS, url::Origin::Create(origin)) + .status); } } // namespace
diff --git a/chrome/browser/notifications/notifier_state_tracker.cc b/chrome/browser/notifications/notifier_state_tracker.cc index 4d83cfb..465f3be 100644 --- a/chrome/browser/notifications/notifier_state_tracker.cc +++ b/chrome/browser/notifications/notifier_state_tracker.cc
@@ -19,6 +19,7 @@ #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/scoped_user_pref_update.h" #include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "extensions/buildflags/buildflags.h" #include "third_party/blink/public/common/permissions/permission_utils.h" #include "ui/message_center/public/cpp/notifier_id.h" @@ -69,10 +70,10 @@ disabled_extension_ids_.end(); case message_center::NotifierType::WEB_PAGE: return profile_->GetPermissionController() - ->GetPermissionStatusForOriginWithoutContext( + ->GetPermissionResultForOriginWithoutContext( blink::PermissionType::NOTIFICATIONS, - url::Origin::Create(notifier_id.url)) == - blink::mojom::PermissionStatus::GRANTED; + url::Origin::Create(notifier_id.url)) + .status == blink::mojom::PermissionStatus::GRANTED; case message_center::NotifierType::SYSTEM_COMPONENT: // We do not disable system component notifications. return true;
diff --git a/chrome/browser/notifications/persistent_notification_handler.cc b/chrome/browser/notifications/persistent_notification_handler.cc index 45a3e5d..0d5b6973 100644 --- a/chrome/browser/notifications/persistent_notification_handler.cc +++ b/chrome/browser/notifications/persistent_notification_handler.cc
@@ -23,6 +23,7 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_event_dispatcher.h" #include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "content/public/common/persistent_notification_status.h" #include "third_party/blink/public/common/permissions/permission_utils.h" #include "url/gurl.h" @@ -109,9 +110,9 @@ blink::mojom::PermissionStatus permission_status = profile->GetPermissionController() - ->GetPermissionStatusForOriginWithoutContext( - blink::PermissionType::NOTIFICATIONS, - url::Origin::Create(origin)); + ->GetPermissionResultForOriginWithoutContext( + blink::PermissionType::NOTIFICATIONS, url::Origin::Create(origin)) + .status; // Don't process click events when the |origin| doesn't have permission. This // can't be a DCHECK because of potential races with native notifications.
diff --git a/chrome/browser/notifications/persistent_notification_handler_unittest.cc b/chrome/browser/notifications/persistent_notification_handler_unittest.cc index 59d7c3db..340327de 100644 --- a/chrome/browser/notifications/persistent_notification_handler_unittest.cc +++ b/chrome/browser/notifications/persistent_notification_handler_unittest.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/notifications/platform_notification_service_factory.h" #include "chrome/browser/notifications/platform_notification_service_impl.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/browser/permission_result.h" #include "content/public/common/persistent_notification_status.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/mock_permission_manager.h" @@ -51,9 +52,10 @@ // Sets the notification permission status to |permission_status|. void SetNotificationPermissionStatus( blink::mojom::PermissionStatus permission_status) { - ON_CALL(*permission_manager_, - GetPermissionStatus(blink::PermissionType::NOTIFICATIONS, _, _)) - .WillByDefault(Return(permission_status)); + ON_CALL(*permission_manager_, GetPermissionResultForOriginWithoutContext( + blink::PermissionType::NOTIFICATIONS, _)) + .WillByDefault(Return(content::PermissionResult( + permission_status, content::PermissionStatusSource::UNSPECIFIED))); } // TestingProfile overrides:
diff --git a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc index 918c451..15f21c3 100644 --- a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc +++ b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper.h" #include "chrome/browser/performance_manager/decorators/page_aggregator.h" #include "chrome/browser/performance_manager/metrics/memory_pressure_metrics.h" +#include "chrome/browser/performance_manager/metrics/metrics_provider.h" #include "chrome/browser/performance_manager/observers/page_load_metrics_observer.h" #include "chrome/browser/performance_manager/policies/background_tab_loading_policy.h" #include "chrome/browser/performance_manager/policies/policy_features.h" @@ -211,9 +212,15 @@ performance_manager::features::kHighEfficiencyModeAvailable) || base::FeatureList::IsEnabled( performance_manager::features::kBatterySaverModeAvailable)) { - user_performance_tuning_manager_ = std::make_unique< + user_performance_tuning_manager_ = std::unique_ptr< performance_manager::user_tuning::UserPerformanceTuningManager>( - g_browser_process->local_state()); + new performance_manager::user_tuning::UserPerformanceTuningManager( + g_browser_process->local_state())); + + // This object is created by the metrics service before threads, but it + // needs the UserPerformanceTuningManager to exist. At this point it's + // instantiated, but still needs to be initialized. + performance_manager::MetricsProvider::GetInstance()->Initialize(); } #endif }
diff --git a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.h b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.h index 7b7594a..d69ce6e7 100644 --- a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.h +++ b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.h
@@ -35,12 +35,10 @@ #endif namespace user_tuning { +class ProfileDiscardOptOutListHelper; class UserPerformanceTuningManager; } -namespace user_tuning { -class ProfileDiscardOptOutListHelper; -} } // namespace performance_manager // Handles the initialization of the performance manager and a few dependent
diff --git a/chrome/browser/performance_manager/metrics/metrics_provider.cc b/chrome/browser/performance_manager/metrics/metrics_provider.cc new file mode 100644 index 0000000..41056ab --- /dev/null +++ b/chrome/browser/performance_manager/metrics/metrics_provider.cc
@@ -0,0 +1,115 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/performance_manager/metrics/metrics_provider.h" + +#include "base/metrics/histogram_functions.h" +#include "chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.h" +#include "components/performance_manager/public/user_tuning/prefs.h" +#include "components/prefs/pref_service.h" + +namespace performance_manager { + +namespace { + +MetricsProvider* g_metrics_provider = nullptr; + +} + +// static +MetricsProvider* MetricsProvider::GetInstance() { + DCHECK(g_metrics_provider); + return g_metrics_provider; +} + +MetricsProvider::~MetricsProvider() { + DCHECK_EQ(this, g_metrics_provider); + g_metrics_provider = nullptr; +} + +void MetricsProvider::Initialize() { + DCHECK(!initialized_); + + pref_change_registrar_.Init(local_state_); + pref_change_registrar_.Add( + performance_manager::user_tuning::prefs::kHighEfficiencyModeEnabled, + base::BindRepeating(&MetricsProvider::OnTuningModesChanged, + base::Unretained(this))); + performance_manager::user_tuning::UserPerformanceTuningManager::GetInstance() + ->AddObserver(this); + + initialized_ = true; + current_mode_ = ComputeCurrentMode(); +} + +void MetricsProvider::ProvideCurrentSessionData( + metrics::ChromeUserMetricsExtension* uma_proto) { + // It's valid for this to be called when `initialized_` is false if the finch + // features controlling battery saver and high efficiency are disabled. + // TODO(crbug.com/1348590): CHECK(initialized_) when the features are enabled + // and removed. + base::UmaHistogramEnumeration("PerformanceManager.UserTuning.EfficiencyMode", + current_mode_); + + // Set `current_mode_` to represent the state of the modes as they are now, so + // that this mode is what is adequately reported at the next report, unless it + // changes in the meantime. + current_mode_ = ComputeCurrentMode(); +} + +MetricsProvider::MetricsProvider(PrefService* local_state) + : local_state_(local_state) { + DCHECK(!g_metrics_provider); + g_metrics_provider = this; +} + +void MetricsProvider::OnBatterySaverModeChanged(bool is_active) { + OnTuningModesChanged(); +} + +void MetricsProvider::OnTuningModesChanged() { + EfficiencyMode new_mode = ComputeCurrentMode(); + + // If the mode changes between UMA reports, mark it as Mixed for this + // interval. + if (current_mode_ != new_mode) { + current_mode_ = EfficiencyMode::kMixed; + } +} + +MetricsProvider::EfficiencyMode MetricsProvider::ComputeCurrentMode() const { + // It's valid for this to be uninitialized if the battery saver/high + // efficiency modes are unavailable. In that case, the browser is running in + // normal mode, so return kNormal. + // TODO(crbug.com/1348590): Change this to a DCHECK when the features are + // enabled and removed. + if (!initialized_) { + return EfficiencyMode::kNormal; + } + + bool high_efficiency_enabled = local_state_->GetBoolean( + performance_manager::user_tuning::prefs::kHighEfficiencyModeEnabled); + + performance_manager::user_tuning::UserPerformanceTuningManager* + user_performance_tuning_manager = performance_manager::user_tuning:: + UserPerformanceTuningManager::GetInstance(); + bool battery_saver_enabled = + user_performance_tuning_manager->IsBatterySaverActive(); + + if (high_efficiency_enabled && battery_saver_enabled) { + return EfficiencyMode::kBoth; + } + + if (high_efficiency_enabled) { + return EfficiencyMode::kHighEfficiency; + } + + if (battery_saver_enabled) { + return EfficiencyMode::kBatterySaver; + } + + return EfficiencyMode::kNormal; +} + +} // namespace performance_manager
diff --git a/chrome/browser/performance_manager/metrics/metrics_provider.h b/chrome/browser/performance_manager/metrics/metrics_provider.h new file mode 100644 index 0000000..d42d7be --- /dev/null +++ b/chrome/browser/performance_manager/metrics/metrics_provider.h
@@ -0,0 +1,79 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_METRICS_METRICS_PROVIDER_H_ +#define CHROME_BROWSER_PERFORMANCE_MANAGER_METRICS_METRICS_PROVIDER_H_ + +#include "base/memory/raw_ptr.h" +#include "chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.h" +#include "components/metrics/metrics_provider.h" +#include "components/prefs/pref_change_registrar.h" + +class ChromeMetricsServiceClient; +class PerformanceManagerMetricsProviderTest; +class PrefService; + +namespace performance_manager { + +// A metrics provider to add some performance manager related metrics to the UMA +// protos on each upload. +class MetricsProvider : public ::metrics::MetricsProvider, + public performance_manager::user_tuning:: + UserPerformanceTuningManager::Observer { + public: + enum class EfficiencyMode { + // No efficiency mode for the entire upload window + kNormal = 0, + // In high efficiency mode for the entire upload window + kHighEfficiency = 1, + // In battery saver mode for the entire upload window + kBatterySaver = 2, + // Both modes enabled for the entire upload window + kBoth = 3, + // The modes were changed during the upload window + kMixed = 4, + // Max value, used in UMA histograms macros + kMaxValue = kMixed + }; + + static MetricsProvider* GetInstance(); + + ~MetricsProvider() override; + + void Initialize(); + + // metrics::MetricsProvider: + // This is only called from UMA code but is public for testing. + void ProvideCurrentSessionData( + ::metrics::ChromeUserMetricsExtension* uma_proto) override; + + private: + friend class ::ChromeMetricsServiceClient; + friend class ::PerformanceManagerMetricsProviderTest; + + explicit MetricsProvider(PrefService* local_state); + + // UserPerformanceTuningManager::Observer: + void OnBatterySaverModeChanged(bool is_active) override; + void OnExternalPowerConnectedChanged( + bool external_power_connected) override{}; + void OnBatteryThresholdReached() override{}; + void OnMemoryThresholdReached() override{}; + void OnTabCountThresholdReached() override{}; + void OnJankThresholdReached() override{}; + + void OnTuningModesChanged(); + EfficiencyMode ComputeCurrentMode() const; + + PrefChangeRegistrar pref_change_registrar_; + const raw_ptr<PrefService> local_state_; + EfficiencyMode current_mode_ = EfficiencyMode::kNormal; + + bool initialized_ = false; + ; +}; + +} // namespace performance_manager + +#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_METRICS_METRICS_PROVIDER_H_
diff --git a/components/performance_manager/metrics/metrics_provider_unittest.cc b/chrome/browser/performance_manager/metrics/metrics_provider_unittest.cc similarity index 63% rename from components/performance_manager/metrics/metrics_provider_unittest.cc rename to chrome/browser/performance_manager/metrics/metrics_provider_unittest.cc index ef18ea4..a221e79 100644 --- a/components/performance_manager/metrics/metrics_provider_unittest.cc +++ b/chrome/browser/performance_manager/metrics/metrics_provider_unittest.cc
@@ -2,13 +2,27 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/performance_manager/public/metrics/metrics_provider.h" +#include "chrome/browser/performance_manager/metrics/metrics_provider.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/performance_manager/user_tuning/fake_frame_throttling_delegate.h" +#include "chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.h" +#include "components/performance_manager/public/features.h" #include "components/performance_manager/public/user_tuning/prefs.h" #include "components/prefs/testing_pref_service.h" #include "testing/gtest/include/gtest/gtest.h" +#include "base/logging.h" + +class FakeHighEfficiencyModeToggleDelegate + : public performance_manager::user_tuning::UserPerformanceTuningManager:: + HighEfficiencyModeToggleDelegate { + public: + void ToggleHighEfficiencyMode(bool enabled) override {} + ~FakeHighEfficiencyModeToggleDelegate() override = default; +}; + class PerformanceManagerMetricsProviderTest : public testing::Test { protected: PrefService* local_state() { return &local_state_; } @@ -32,32 +46,55 @@ sample, 1); } + void InitProvider() { provider_->Initialize(); } + + performance_manager::MetricsProvider* provider() { return provider_.get(); } + private: void SetUp() override { + feature_list_.InitWithFeatures( + {performance_manager::features::kHighEfficiencyModeAvailable, + performance_manager::features::kBatterySaverModeAvailable}, + {}); + performance_manager::user_tuning::prefs::RegisterLocalStatePrefs( local_state_.registry()); + + manager_.reset( + new performance_manager::user_tuning::UserPerformanceTuningManager( + &local_state_, + std::make_unique<performance_manager::FakeFrameThrottlingDelegate>( + &throttling_enabled_), + std::make_unique<FakeHighEfficiencyModeToggleDelegate>())); + provider_.reset(new performance_manager::MetricsProvider(local_state())); } TestingPrefServiceSimple local_state_; + base::test::ScopedFeatureList feature_list_; + + bool throttling_enabled_ = false; + std::unique_ptr< + performance_manager::user_tuning::UserPerformanceTuningManager> + manager_; + std::unique_ptr<performance_manager::MetricsProvider> provider_; }; TEST_F(PerformanceManagerMetricsProviderTest, TestNormalMode) { + InitProvider(); base::HistogramTester tester; - performance_manager::MetricsProvider provider(local_state()); - provider.ProvideCurrentSessionData(nullptr); + provider()->ProvideCurrentSessionData(nullptr); ExpectSingleUniqueSample( tester, performance_manager::MetricsProvider::EfficiencyMode::kNormal); } TEST_F(PerformanceManagerMetricsProviderTest, TestMixedMode) { - performance_manager::MetricsProvider provider(local_state()); - + InitProvider(); { base::HistogramTester tester; // Start in normal mode - provider.ProvideCurrentSessionData(nullptr); + provider()->ProvideCurrentSessionData(nullptr); ExpectSingleUniqueSample( tester, performance_manager::MetricsProvider::EfficiencyMode::kNormal); } @@ -68,7 +105,7 @@ // because we transitioned from normal to High-Efficiency during the // interval. SetHighEfficiencyEnabled(true); - provider.ProvideCurrentSessionData(nullptr); + provider()->ProvideCurrentSessionData(nullptr); ExpectSingleUniqueSample( tester, performance_manager::MetricsProvider::EfficiencyMode::kMixed); } @@ -77,7 +114,7 @@ base::HistogramTester tester; // If another UMA upload happens without mode changes, this one will report // High-Efficiency Mode. - provider.ProvideCurrentSessionData(nullptr); + provider()->ProvideCurrentSessionData(nullptr); ExpectSingleUniqueSample( tester, performance_manager::MetricsProvider::EfficiencyMode::kHighEfficiency); @@ -88,13 +125,13 @@ SetHighEfficiencyEnabled(true); SetBatterySaverEnabled(true); - performance_manager::MetricsProvider provider(local_state()); + InitProvider(); { base::HistogramTester tester; // Start with both modes enabled (such as a Chrome startup after having // enabled both modes in a previous session). - provider.ProvideCurrentSessionData(nullptr); + provider()->ProvideCurrentSessionData(nullptr); ExpectSingleUniqueSample( tester, performance_manager::MetricsProvider::EfficiencyMode::kBoth); } @@ -103,7 +140,7 @@ base::HistogramTester tester; // Disabling High-Efficiency Mode will cause the next report to be "mixed". SetHighEfficiencyEnabled(false); - provider.ProvideCurrentSessionData(nullptr); + provider()->ProvideCurrentSessionData(nullptr); ExpectSingleUniqueSample( tester, performance_manager::MetricsProvider::EfficiencyMode::kMixed); } @@ -111,7 +148,7 @@ { base::HistogramTester tester; // No changes until the following report, "Battery saver" is reported - provider.ProvideCurrentSessionData(nullptr); + provider()->ProvideCurrentSessionData(nullptr); ExpectSingleUniqueSample( tester, performance_manager::MetricsProvider::EfficiencyMode::kBatterySaver); @@ -122,7 +159,7 @@ // Re-enabling High-Efficiency Mode will cause the next report to indicate // "mixed". SetHighEfficiencyEnabled(true); - provider.ProvideCurrentSessionData(nullptr); + provider()->ProvideCurrentSessionData(nullptr); ExpectSingleUniqueSample( tester, performance_manager::MetricsProvider::EfficiencyMode::kMixed); } @@ -130,8 +167,8 @@ { base::HistogramTester tester; // One more report with no changes, this one reports "both" again. - provider.ProvideCurrentSessionData(nullptr); + provider()->ProvideCurrentSessionData(nullptr); ExpectSingleUniqueSample( tester, performance_manager::MetricsProvider::EfficiencyMode::kBoth); } -} \ No newline at end of file +}
diff --git a/chrome/browser/performance_manager/user_tuning/fake_frame_throttling_delegate.cc b/chrome/browser/performance_manager/user_tuning/fake_frame_throttling_delegate.cc new file mode 100644 index 0000000..c2ded5b --- /dev/null +++ b/chrome/browser/performance_manager/user_tuning/fake_frame_throttling_delegate.cc
@@ -0,0 +1,20 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/performance_manager/user_tuning/fake_frame_throttling_delegate.h" + +namespace performance_manager { + +void FakeFrameThrottlingDelegate::StartThrottlingAllFrameSinks() { + *throttling_enabled_ = true; +} +void FakeFrameThrottlingDelegate::StopThrottlingAllFrameSinks() { + *throttling_enabled_ = false; +} + +FakeFrameThrottlingDelegate::FakeFrameThrottlingDelegate( + bool* throttling_enabled) + : throttling_enabled_(throttling_enabled) {} + +} // namespace performance_manager
diff --git a/chrome/browser/performance_manager/user_tuning/fake_frame_throttling_delegate.h b/chrome/browser/performance_manager/user_tuning/fake_frame_throttling_delegate.h new file mode 100644 index 0000000..a36b08b --- /dev/null +++ b/chrome/browser/performance_manager/user_tuning/fake_frame_throttling_delegate.h
@@ -0,0 +1,27 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_USER_TUNING_FAKE_FRAME_THROTTLING_DELEGATE_H_ +#define CHROME_BROWSER_PERFORMANCE_MANAGER_USER_TUNING_FAKE_FRAME_THROTTLING_DELEGATE_H_ + +#include "chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.h" + +namespace performance_manager { + +class FakeFrameThrottlingDelegate + : public performance_manager::user_tuning::UserPerformanceTuningManager:: + FrameThrottlingDelegate { + public: + void StartThrottlingAllFrameSinks() override; + void StopThrottlingAllFrameSinks() override; + + explicit FakeFrameThrottlingDelegate(bool* throttling_enabled); + ~FakeFrameThrottlingDelegate() override = default; + + bool* throttling_enabled_; +}; + +} // namespace performance_manager + +#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_USER_TUNING_FAKE_FRAME_THROTTLING_DELEGATE_H_
diff --git a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.cc b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.cc index 4cdeea92..01fd0f8 100644 --- a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.cc +++ b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.cc
@@ -15,6 +15,8 @@ namespace performance_manager::user_tuning { namespace { +UserPerformanceTuningManager* g_user_performance_tuning_manager = nullptr; + class FrameThrottlingDelegateImpl : public performance_manager::user_tuning::UserPerformanceTuningManager:: FrameThrottlingDelegate { @@ -30,40 +32,35 @@ ~FrameThrottlingDelegateImpl() override = default; }; +class HighEfficiencyModeToggleDelegateImpl + : public performance_manager::user_tuning::UserPerformanceTuningManager:: + HighEfficiencyModeToggleDelegate { + public: + void ToggleHighEfficiencyMode(bool enabled) override { + performance_manager::PerformanceManager::CallOnGraph( + FROM_HERE, base::BindOnce( + [](bool enabled, performance_manager::Graph* graph) { + policies::HighEfficiencyModePolicy::GetInstance() + ->OnHighEfficiencyModeChanged(enabled); + }, + enabled)); + } + + ~HighEfficiencyModeToggleDelegateImpl() override = default; +}; + } // namespace -UserPerformanceTuningManager::UserPerformanceTuningManager( - PrefService* local_state, - std::unique_ptr<FrameThrottlingDelegate> frame_throttling_delegate) - : frame_throttling_delegate_( - frame_throttling_delegate - ? std::move(frame_throttling_delegate) - : std::make_unique<FrameThrottlingDelegateImpl>()) { - pref_change_registrar_.Init(local_state); - - if (base::FeatureList::IsEnabled( - performance_manager::features::kHighEfficiencyModeAvailable)) { - pref_change_registrar_.Add( - performance_manager::user_tuning::prefs::kHighEfficiencyModeEnabled, - base::BindRepeating( - &UserPerformanceTuningManager::OnHighEfficiencyModePrefChanged, - base::Unretained(this))); - // Make sure the initial state of the pref is passed on to the policy. - OnHighEfficiencyModePrefChanged(); - } - - if (base::FeatureList::IsEnabled( - performance_manager::features::kBatterySaverModeAvailable)) { - pref_change_registrar_.Add( - performance_manager::user_tuning::prefs::kBatterySaverModeEnabled, - base::BindRepeating( - &UserPerformanceTuningManager::OnBatterySaverModePrefChanged, - base::Unretained(this))); - OnBatterySaverModePrefChanged(); - } +// static +UserPerformanceTuningManager* UserPerformanceTuningManager::GetInstance() { + DCHECK(g_user_performance_tuning_manager); + return g_user_performance_tuning_manager; } -UserPerformanceTuningManager::~UserPerformanceTuningManager() = default; +UserPerformanceTuningManager::~UserPerformanceTuningManager() { + DCHECK_EQ(this, g_user_performance_tuning_manager); + g_user_performance_tuning_manager = nullptr; +} void UserPerformanceTuningManager::AddObserver(Observer* o) { observers_.AddObserver(o); @@ -92,16 +89,50 @@ return battery_saver_mode_enabled_; } +UserPerformanceTuningManager::UserPerformanceTuningManager( + PrefService* local_state, + std::unique_ptr<FrameThrottlingDelegate> frame_throttling_delegate, + std::unique_ptr<HighEfficiencyModeToggleDelegate> + high_efficiency_mode_toggle_delegate) + : frame_throttling_delegate_( + frame_throttling_delegate + ? std::move(frame_throttling_delegate) + : std::make_unique<FrameThrottlingDelegateImpl>()), + high_efficiency_mode_toggle_delegate_( + high_efficiency_mode_toggle_delegate + ? std::move(high_efficiency_mode_toggle_delegate) + : std::make_unique<HighEfficiencyModeToggleDelegateImpl>()) { + DCHECK(!g_user_performance_tuning_manager); + g_user_performance_tuning_manager = this; + + pref_change_registrar_.Init(local_state); + + if (base::FeatureList::IsEnabled( + performance_manager::features::kHighEfficiencyModeAvailable)) { + pref_change_registrar_.Add( + performance_manager::user_tuning::prefs::kHighEfficiencyModeEnabled, + base::BindRepeating( + &UserPerformanceTuningManager::OnHighEfficiencyModePrefChanged, + base::Unretained(this))); + // Make sure the initial state of the pref is passed on to the policy. + OnHighEfficiencyModePrefChanged(); + } + + if (base::FeatureList::IsEnabled( + performance_manager::features::kBatterySaverModeAvailable)) { + pref_change_registrar_.Add( + performance_manager::user_tuning::prefs::kBatterySaverModeEnabled, + base::BindRepeating( + &UserPerformanceTuningManager::OnBatterySaverModePrefChanged, + base::Unretained(this))); + OnBatterySaverModePrefChanged(); + } +} + void UserPerformanceTuningManager::OnHighEfficiencyModePrefChanged() { bool enabled = pref_change_registrar_.prefs()->GetBoolean( performance_manager::user_tuning::prefs::kHighEfficiencyModeEnabled); - performance_manager::PerformanceManager::CallOnGraph( - FROM_HERE, base::BindOnce( - [](bool enabled, performance_manager::Graph* graph) { - policies::HighEfficiencyModePolicy::GetInstance() - ->OnHighEfficiencyModeChanged(enabled); - }, - enabled)); + high_efficiency_mode_toggle_delegate_->ToggleHighEfficiencyMode(enabled); } void UserPerformanceTuningManager::OnBatterySaverModePrefChanged() {
diff --git a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.h b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.h index 47014aa8..0765d0e 100644 --- a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.h +++ b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.h
@@ -9,6 +9,8 @@ #include "base/observer_list_types.h" #include "components/prefs/pref_change_registrar.h" +class ChromeBrowserMainExtraPartsPerformanceManager; +class PerformanceManagerMetricsProviderTest; class PrefService; namespace performance_manager::user_tuning { @@ -23,6 +25,12 @@ virtual ~FrameThrottlingDelegate() = default; }; + class HighEfficiencyModeToggleDelegate { + public: + virtual void ToggleHighEfficiencyMode(bool enabled) = 0; + virtual ~HighEfficiencyModeToggleDelegate() = default; + }; + class Observer : public base::CheckedObserver { public: // Raised when the battery saver mode interventions are activated or @@ -53,10 +61,8 @@ virtual void OnJankThresholdReached() = 0; }; - explicit UserPerformanceTuningManager( - PrefService* local_state, - std::unique_ptr<FrameThrottlingDelegate> frame_throttling_delegate = - nullptr); + static UserPerformanceTuningManager* GetInstance(); + ~UserPerformanceTuningManager(); void AddObserver(Observer* o); @@ -76,6 +82,17 @@ bool IsBatterySaverActive() const; private: + friend class ::ChromeBrowserMainExtraPartsPerformanceManager; + friend class ::PerformanceManagerMetricsProviderTest; + friend class UserPerformanceTuningManagerTest; + + explicit UserPerformanceTuningManager( + PrefService* local_state, + std::unique_ptr<FrameThrottlingDelegate> frame_throttling_delegate = + nullptr, + std::unique_ptr<HighEfficiencyModeToggleDelegate> + high_efficiency_mode_toggle_delegate = nullptr); + void OnHighEfficiencyModePrefChanged(); void OnBatterySaverModePrefChanged(); @@ -84,6 +101,8 @@ bool battery_saver_mode_enabled_ = false; bool temporary_battery_saver_enabled_ = false; std::unique_ptr<FrameThrottlingDelegate> frame_throttling_delegate_; + std::unique_ptr<HighEfficiencyModeToggleDelegate> + high_efficiency_mode_toggle_delegate_; PrefChangeRegistrar pref_change_registrar_; base::ObserverList<Observer> observers_;
diff --git a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager_unittest.cc b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager_unittest.cc index 8fd99fa..cb0429a 100644 --- a/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager_unittest.cc +++ b/chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/performance_manager/user_tuning/user_performance_tuning_manager.h" #include "base/test/scoped_feature_list.h" +#include "chrome/browser/performance_manager/user_tuning/fake_frame_throttling_delegate.h" #include "components/performance_manager/public/features.h" #include "components/performance_manager/public/user_tuning/prefs.h" #include "components/prefs/testing_pref_service.h" @@ -12,19 +13,6 @@ namespace performance_manager::user_tuning { -class FakeFrameThrottlingDelegate - : public UserPerformanceTuningManager::FrameThrottlingDelegate { - public: - void StartThrottlingAllFrameSinks() override { *throttling_enabled_ = true; } - void StopThrottlingAllFrameSinks() override { *throttling_enabled_ = false; } - - explicit FakeFrameThrottlingDelegate(bool* throttling_enabled) - : throttling_enabled_(throttling_enabled) {} - ~FakeFrameThrottlingDelegate() override = default; - - bool* throttling_enabled_; -}; - class UserPerformanceTuningManagerTest : public testing::Test { public: void SetUp() override { @@ -33,66 +21,64 @@ performance_manager::user_tuning::prefs::RegisterLocalStatePrefs( local_state_.registry()); + manager_.reset(new UserPerformanceTuningManager( + &local_state_, + std::make_unique<FakeFrameThrottlingDelegate>(&throttling_enabled_))); } + UserPerformanceTuningManager* manager() { + return UserPerformanceTuningManager::GetInstance(); + } + bool throttling_enabled() const { return throttling_enabled_; } + TestingPrefServiceSimple local_state_; base::test::ScopedFeatureList feature_list_; + + bool throttling_enabled_ = false; + std::unique_ptr<UserPerformanceTuningManager> manager_; }; TEST_F(UserPerformanceTuningManagerTest, TemporaryBatterySaver) { - bool throttling_enabled = false; - UserPerformanceTuningManager manager( - &local_state_, - std::make_unique<FakeFrameThrottlingDelegate>(&throttling_enabled)); - EXPECT_FALSE(manager.IsBatterySaverActive()); - EXPECT_FALSE(throttling_enabled); + EXPECT_FALSE(manager()->IsBatterySaverActive()); + EXPECT_FALSE(throttling_enabled()); - manager.SetTemporaryBatterySaver(true); - EXPECT_TRUE(manager.IsBatterySaverActive()); - EXPECT_TRUE(throttling_enabled); + manager()->SetTemporaryBatterySaver(true); + EXPECT_TRUE(manager()->IsBatterySaverActive()); + EXPECT_TRUE(throttling_enabled()); - manager.SetTemporaryBatterySaver(false); - EXPECT_FALSE(manager.IsBatterySaverActive()); - EXPECT_FALSE(throttling_enabled); + manager()->SetTemporaryBatterySaver(false); + EXPECT_FALSE(manager()->IsBatterySaverActive()); + EXPECT_FALSE(throttling_enabled()); } TEST_F(UserPerformanceTuningManagerTest, BatterySaverModePref) { - bool throttling_enabled = false; - UserPerformanceTuningManager manager( - &local_state_, - std::make_unique<FakeFrameThrottlingDelegate>(&throttling_enabled)); - EXPECT_FALSE(manager.IsBatterySaverActive()); - EXPECT_FALSE(throttling_enabled); + EXPECT_FALSE(manager()->IsBatterySaverActive()); + EXPECT_FALSE(throttling_enabled()); local_state_.SetBoolean( performance_manager::user_tuning::prefs::kBatterySaverModeEnabled, true); - EXPECT_TRUE(manager.IsBatterySaverActive()); - EXPECT_TRUE(throttling_enabled); + EXPECT_TRUE(manager()->IsBatterySaverActive()); + EXPECT_TRUE(throttling_enabled()); local_state_.SetBoolean( performance_manager::user_tuning::prefs::kBatterySaverModeEnabled, false); - EXPECT_FALSE(manager.IsBatterySaverActive()); - EXPECT_FALSE(throttling_enabled); + EXPECT_FALSE(manager()->IsBatterySaverActive()); + EXPECT_FALSE(throttling_enabled()); } TEST_F(UserPerformanceTuningManagerTest, PrefSupersedesTemporary) { - bool throttling_enabled = false; - UserPerformanceTuningManager manager( - &local_state_, - std::make_unique<FakeFrameThrottlingDelegate>(&throttling_enabled)); - local_state_.SetBoolean( performance_manager::user_tuning::prefs::kBatterySaverModeEnabled, true); - EXPECT_TRUE(manager.IsBatterySaverActive()); - EXPECT_TRUE(throttling_enabled); + EXPECT_TRUE(manager()->IsBatterySaverActive()); + EXPECT_TRUE(throttling_enabled()); - manager.SetTemporaryBatterySaver(true); - EXPECT_TRUE(manager.IsBatterySaverActive()); - EXPECT_TRUE(throttling_enabled); + manager()->SetTemporaryBatterySaver(true); + EXPECT_TRUE(manager()->IsBatterySaverActive()); + EXPECT_TRUE(throttling_enabled()); - manager.SetTemporaryBatterySaver(false); - EXPECT_TRUE(manager.IsBatterySaverActive()); - EXPECT_TRUE(throttling_enabled); + manager()->SetTemporaryBatterySaver(false); + EXPECT_TRUE(manager()->IsBatterySaverActive()); + EXPECT_TRUE(throttling_enabled()); } } // namespace performance_manager::user_tuning
diff --git a/chrome/browser/permissions/chrome_permission_manager_unittest.cc b/chrome/browser/permissions/chrome_permission_manager_unittest.cc index 05b2e602..3c5b269 100644 --- a/chrome/browser/permissions/chrome_permission_manager_unittest.cc +++ b/chrome/browser/permissions/chrome_permission_manager_unittest.cc
@@ -10,6 +10,7 @@ #include "chrome/test/base/testing_profile.h" #include "components/permissions/features.h" #include "components/permissions/permission_manager.h" +#include "components/permissions/permission_util.h" #include "extensions/buildflags/buildflags.h" #include "testing/gtest/include/gtest/gtest.h" @@ -63,32 +64,32 @@ // "Normal" URLs are not affected by GetCanonicalOrigin. EXPECT_EQ(google_com, - GetPermissionControllerDelegate()->GetCanonicalOrigin( + permissions::PermissionUtil::GetCanonicalOrigin( ContentSettingsType::GEOLOCATION, google_com, google_com)); EXPECT_EQ(google_de, - GetPermissionControllerDelegate()->GetCanonicalOrigin( + permissions::PermissionUtil::GetCanonicalOrigin( ContentSettingsType::GEOLOCATION, google_de, google_de)); EXPECT_EQ(other_url, - GetPermissionControllerDelegate()->GetCanonicalOrigin( + permissions::PermissionUtil::GetCanonicalOrigin( ContentSettingsType::GEOLOCATION, other_url, other_url)); EXPECT_EQ(google_base, - GetPermissionControllerDelegate()->GetCanonicalOrigin( + permissions::PermissionUtil::GetCanonicalOrigin( ContentSettingsType::GEOLOCATION, google_base, google_base)); // The WebUI NTP URL gets mapped to the Google base URL. EXPECT_EQ(google_base, - GetPermissionControllerDelegate()->GetCanonicalOrigin( + permissions::PermissionUtil::GetCanonicalOrigin( ContentSettingsType::GEOLOCATION, webui_ntp, top_level_ntp)); // chrome-search://remote-ntp and other URLs are not affected. EXPECT_EQ(remote_ntp, - GetPermissionControllerDelegate()->GetCanonicalOrigin( + permissions::PermissionUtil::GetCanonicalOrigin( ContentSettingsType::GEOLOCATION, remote_ntp, top_level_ntp)); EXPECT_EQ(google_com, - GetPermissionControllerDelegate()->GetCanonicalOrigin( + permissions::PermissionUtil::GetCanonicalOrigin( ContentSettingsType::GEOLOCATION, google_com, top_level_ntp)); EXPECT_EQ(other_chrome_search, - GetPermissionControllerDelegate()->GetCanonicalOrigin( + permissions::PermissionUtil::GetCanonicalOrigin( ContentSettingsType::GEOLOCATION, other_chrome_search, top_level_ntp)); } @@ -99,19 +100,17 @@ // The embedding origin should be returned except in the case of notifications // and, if they're enabled, extensions. - EXPECT_EQ(embedding_origin, - GetPermissionControllerDelegate()->GetCanonicalOrigin( - ContentSettingsType::GEOLOCATION, requesting_origin, - embedding_origin)); - EXPECT_EQ(requesting_origin, - GetPermissionControllerDelegate()->GetCanonicalOrigin( - ContentSettingsType::NOTIFICATIONS, requesting_origin, - embedding_origin)); + EXPECT_EQ(embedding_origin, permissions::PermissionUtil::GetCanonicalOrigin( + ContentSettingsType::GEOLOCATION, + requesting_origin, embedding_origin)); + EXPECT_EQ(requesting_origin, permissions::PermissionUtil::GetCanonicalOrigin( + ContentSettingsType::NOTIFICATIONS, + requesting_origin, embedding_origin)); #if BUILDFLAG(ENABLE_EXTENSIONS) const GURL extensions_requesting_origin( "chrome-extension://abcdefghijklmnopqrstuvxyz"); EXPECT_EQ(extensions_requesting_origin, - GetPermissionControllerDelegate()->GetCanonicalOrigin( + permissions::PermissionUtil::GetCanonicalOrigin( ContentSettingsType::GEOLOCATION, extensions_requesting_origin, embedding_origin)); #endif
diff --git a/chrome/browser/permissions/chrome_permissions_client.cc b/chrome/browser/permissions/chrome_permissions_client.cc index 5b7804cf..994b78d9 100644 --- a/chrome/browser/permissions/chrome_permissions_client.cc +++ b/chrome/browser/permissions/chrome_permissions_client.cc
@@ -21,7 +21,6 @@ #include "chrome/browser/permissions/contextual_notification_permission_ui_selector.h" #include "chrome/browser/permissions/permission_actions_history_factory.h" #include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h" -#include "chrome/browser/permissions/permission_manager_factory.h" #include "chrome/browser/permissions/permission_revocation_request.h" #include "chrome/browser/permissions/prediction_based_permission_ui_selector.h" #include "chrome/browser/permissions/pref_notification_permission_ui_selector.h" @@ -208,12 +207,6 @@ Profile::FromBrowserContext(browser_context)); } -permissions::PermissionManager* ChromePermissionsClient::GetPermissionManager( - content::BrowserContext* browser_context) { - return PermissionManagerFactory::GetForProfile( - Profile::FromBrowserContext(browser_context)); -} - double ChromePermissionsClient::GetSiteEngagementScore( content::BrowserContext* browser_context, const GURL& origin) { @@ -442,7 +435,7 @@ return absl::nullopt; } -bool ChromePermissionsClient::DoOriginsMatchNewTabPage( +bool ChromePermissionsClient::DoURLsMatchNewTabPage( const GURL& requesting_origin, const GURL& embedding_origin) { return embedding_origin ==
diff --git a/chrome/browser/permissions/chrome_permissions_client.h b/chrome/browser/permissions/chrome_permissions_client.h index 788d851..f0ffb9f 100644 --- a/chrome/browser/permissions/chrome_permissions_client.h +++ b/chrome/browser/permissions/chrome_permissions_client.h
@@ -30,8 +30,6 @@ content::BrowserContext* browser_context) override; permissions::PermissionDecisionAutoBlocker* GetPermissionDecisionAutoBlocker( content::BrowserContext* browser_context) override; - permissions::PermissionManager* GetPermissionManager( - content::BrowserContext* browser_context) override; permissions::ObjectPermissionContextBase* GetChooserContext( content::BrowserContext* browser_context, ContentSettingsType type) override; @@ -74,8 +72,10 @@ absl::optional<GURL> OverrideCanonicalOrigin( const GURL& requesting_origin, const GURL& embedding_origin) override; - bool DoOriginsMatchNewTabPage(const GURL& requesting_origin, - const GURL& embedding_origin) override; + // Checks if `requesting_origin` and `embedding_origin` are the new tab page + // origins. + bool DoURLsMatchNewTabPage(const GURL& requesting_origin, + const GURL& embedding_origin) override; #if BUILDFLAG(IS_ANDROID) bool IsDseOrigin(content::BrowserContext* browser_context, const url::Origin& origin) override;
diff --git a/chrome/browser/policy/test/content_settings_policy_browsertest.cc b/chrome/browser/policy/test/content_settings_policy_browsertest.cc index d95ea47..31e197b 100644 --- a/chrome/browser/policy/test/content_settings_policy_browsertest.cc +++ b/chrome/browser/policy/test/content_settings_policy_browsertest.cc
@@ -23,6 +23,7 @@ #include "components/policy/core/common/policy_map.h" #include "components/policy/policy_constants.h" #include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_switches.h" @@ -392,8 +393,10 @@ content::PermissionController* permission_controller = browser()->profile()->GetPermissionController(); EXPECT_EQ( - permission_controller->GetPermissionStatusForOriginWithoutContext( - blink::PermissionType::SENSORS, url::Origin::Create(GURL(url))), + permission_controller + ->GetPermissionResultForOriginWithoutContext( + blink::PermissionType::SENSORS, url::Origin::Create(GURL(url))) + .status, status); }
diff --git a/chrome/browser/profiles/profile_keyed_service_factory.h b/chrome/browser/profiles/profile_keyed_service_factory.h index e515de3..c7e3320 100644 --- a/chrome/browser/profiles/profile_keyed_service_factory.h +++ b/chrome/browser/profiles/profile_keyed_service_factory.h
@@ -33,7 +33,8 @@ // MyRedirectingKeyedServiceFactory() // : ProfileKeyedServiceFactory( // "MyRedirectingKeyedService", -// ProfileSelections::BuildServicesRedirectedInIncognito()) {} +// ProfileSelections::BuildRedirectedInIncognitoNonExperimental()) +// {} // } // }; //
diff --git a/chrome/browser/profiles/profile_keyed_service_factory_unittest.cc b/chrome/browser/profiles/profile_keyed_service_factory_unittest.cc index 08982ac..2b0b422 100644 --- a/chrome/browser/profiles/profile_keyed_service_factory_unittest.cc +++ b/chrome/browser/profiles/profile_keyed_service_factory_unittest.cc
@@ -104,7 +104,7 @@ PredefinedProfileSelectionsFactoryTest() : ProfileKeyedServiceFactoryTest( "PredefinedProfileSelectionsFactoryTest", - ProfileSelections::BuildServicesRedirectedToOriginal()) {} + ProfileSelections::BuildRedirectedInIncognito()) {} }; TEST_F(ProfileKeyedServiceFactoryUnittest,
diff --git a/chrome/browser/profiles/profile_selections.cc b/chrome/browser/profiles/profile_selections.cc index 88d332ec..40b7d03 100644 --- a/chrome/browser/profiles/profile_selections.cc +++ b/chrome/browser/profiles/profile_selections.cc
@@ -44,30 +44,29 @@ ProfileSelections::~ProfileSelections() = default; ProfileSelections::ProfileSelections(const ProfileSelections& other) = default; -ProfileSelections ProfileSelections::BuildDefault() { - return ProfileSelections::Builder().Build(); -} - -ProfileSelections ProfileSelections::BuildServicesForAllProfiles() { +ProfileSelections ProfileSelections::BuildForAllProfiles() { return ProfileSelections::Builder() .WithRegular(ProfileSelection::kOwnInstance) + .WithGuest(ProfileSelection::kOwnInstance) + .WithSystem(ProfileSelection::kOwnInstance) .Build(); } -ProfileSelections ProfileSelections::BuildNoServicesForAllProfiles() { +ProfileSelections ProfileSelections::BuildNoProfilesSelected() { return ProfileSelections::Builder() .WithRegular(ProfileSelection::kNone) .Build(); } -ProfileSelections ProfileSelections::BuildServicesForRegularProfile() { +ProfileSelections ProfileSelections::BuildForRegularProfile() { return ProfileSelections::Builder() .WithGuest(ProfileSelection::kNone) .WithSystem(ProfileSelection::kNone) .Build(); } -ProfileSelections ProfileSelections::BuildServicesRedirectedInIncognito() { +ProfileSelections +ProfileSelections::BuildRedirectedInIncognitoNonExperimental() { return ProfileSelections::Builder() .WithRegular(ProfileSelection::kRedirectedToOriginal) .WithGuest(ProfileSelection::kNone) @@ -75,12 +74,48 @@ .Build(); } -ProfileSelections ProfileSelections::BuildServicesRedirectedToOriginal() { +ProfileSelections ProfileSelections::BuildRedirectedToOriginal() { return ProfileSelections::Builder() .WithRegular(ProfileSelection::kRedirectedToOriginal) + .WithGuest(ProfileSelection::kRedirectedToOriginal) + .WithSystem(ProfileSelection::kRedirectedToOriginal) .Build(); } +ProfileSelections ProfileSelections::BuildDefault(bool force_guest, + bool force_system) { + Builder builder; + if (force_guest) + builder.WithGuest(ProfileSelection::kOriginalOnly); + if (force_system) + builder.WithSystem(ProfileSelection::kOriginalOnly); + return builder.Build(); +} + +ProfileSelections ProfileSelections::BuildRedirectedInIncognito( + bool force_guest, + bool force_system) { + Builder builder; + builder.WithRegular(ProfileSelection::kRedirectedToOriginal); + if (force_guest) + builder.WithGuest(ProfileSelection::kRedirectedToOriginal); + if (force_system) + builder.WithSystem(ProfileSelection::kRedirectedToOriginal); + return builder.Build(); +} + +ProfileSelections ProfileSelections::BuildForRegularAndIncognito( + bool force_guest, + bool force_system) { + Builder builder; + builder.WithRegular(ProfileSelection::kOwnInstance); + if (force_guest) + builder.WithGuest(ProfileSelection::kOwnInstance); + if (force_system) + builder.WithSystem(ProfileSelection::kOwnInstance); + return builder.Build(); +} + Profile* ProfileSelections::ApplyProfileSelection(Profile* profile) const { DCHECK(profile);
diff --git a/chrome/browser/profiles/profile_selections.h b/chrome/browser/profiles/profile_selections.h index fa3beeb..35d5d2ce 100644 --- a/chrome/browser/profiles/profile_selections.h +++ b/chrome/browser/profiles/profile_selections.h
@@ -9,8 +9,15 @@ class Profile; -// Enum used to map the logic of selecting the right profile for the service to -// be created for, based on the given profile. +// The class `ProfileSelections` and enum `ProfileSelection` are not coupled +// with the usage of `ProfileKeyedServiceFactory`, however the experiment of +// changing the default value of `ProfileSelections` behavior is mainly done for +// the `ProfileKeyedServiceFactory`. +// If other usages are needed it is best not to use the builders that contains +// experimental code (mentioned below). + +// Enum used to map the logic of selecting the right profile based on the given +// profile. enum class ProfileSelection { kNone, // Original: No Profile -- OTR: No Profile kOriginalOnly, // Original: Self -- OTR: No Profile @@ -32,35 +39,160 @@ // - Predefined `ProfileSelections` - // Default implementation, as of now: - // - No services in OTR. - // - Regular profile returns itself (original). - // - Guest and System profiles follow Regular profile behaviour. + // Regular builders (independent of the experiments): + + // All Profiles are selected. + // +---------+------------+------------+ + // | | Original | OTR | + // +---------+------------+------------+ + // | Regular | self | self | + // | Guest | self | self | + // | System | self | self | + // +---------+------------+------------+ + static ProfileSelections BuildForAllProfiles(); + + // No Profiles are selected. + // +---------+------------+------------+ + // | | Original | OTR | + // +---------+------------+------------+ + // | Regular | no profile | no profile | + // | Guest | no profile | no profile | + // | System | no profile | no profile | + // +---------+------------+------------+ + static ProfileSelections BuildNoProfilesSelected(); + + // Only select the regular profile. + // +---------+------------+------------+ + // | | Original | OTR | + // +---------+------------+------------+ + // | Regular | self | no profile | + // | Guest | no profile | no profile | + // | System | no profile | no profile | + // +---------+------------+------------+ + static ProfileSelections BuildForRegularProfile(); + + // Redirects incognito profiles to their original regular profile. No + // profiles for Guest and System profiles. "NonExperimental" is added to + // differentiate with the experimental behavior during the experiment, once + // done it will be the equivalent builder. + // +---------+------------+------------+ + // | | Original | OTR | + // +---------+------------+------------+ + // | Regular | self | original | + // | Guest | no profile | no profile | + // | System | no profile | no profile | + // +---------+------------+------------+ + static ProfileSelections BuildRedirectedInIncognitoNonExperimental(); + + // Redirects all OTR profiles to their original profiles. + // Includes all profile types (Regular, Guest and System). + // +---------+------------+------------+ + // | | Original | OTR | + // +---------+------------+------------+ + // | Regular | self | original | + // | Guest | self | original | + // | System | self | original | + // +---------+------------+------------+ + static ProfileSelections BuildRedirectedToOriginal(); + + // Experimental builders: + // + // Experimental builders (should only be used for the transition from + // `BrowserContextKeyedServiceFactory` to `ProfileKeyedServiceFactory`): + // The following builder will contain experimental code indirectly, by not + // giving a value to Guest and System Profile (unless forced by parameters). + // The experiment is targeted to affect usages on + // `ProfileKeyedServiceFactory`. During the experiment phase, these builders + // will not have very accurate function names, the name is based on the end + // result behavior the experiment enforced behavior. With/Without experiment + // behavior is described per experimental builder. The parameters force_* will + // allow to have an easier transition when adapting to the experiment. + + // Default implementation, without the experiment: + // +---------+------------+------------+ + // | | Original | OTR | + // +---------+------------+------------+ + // | Regular | self | no profile | + // | Guest | self | no profile | + // | System | self | no profile | + // +---------+------------+------------+ // // After the migration(crbug.com/1284664) this default behaviour will change. - // It will be similar to the current `BuildServicesForRegularProfile()`. - // - No services in OTR. - // - Regular profile returns itself (original). - // - No services for Guest and System profile. - static ProfileSelections BuildDefault(); + // +---------+------------+------------+ + // | | Original | OTR | + // +---------+------------+------------+ + // | Regular | self | no profile | + // | Guest | no profile | no profile | + // | System | no profile | no profile | + // +---------+------------+------------+ + // + // Parameters: (used during the experiment) + // - force_guest: true, force Guest with `ProfileSelection::kOriginalOnly`. + // - force_system: true, force System with `ProfileSelection::kOriginalOnly`. + static ProfileSelections BuildDefault(bool force_guest = false, + bool force_system = false); - // Services available for all profiles. - static ProfileSelections BuildServicesForAllProfiles(); + // Without the experiment: + // - Returns Regular for Regular, incognito and other regular OTR profiles. + // - Returns Guest Original for GuestOriginal and GuestOTR (same as Regular). + // - Returns System Original for SystemOriginal and SystemOTR (same as + // Regular). + // + // With the experiment: + // - Returns Regular for Regular, incognito and other regular OTR profiles. + // - Return nullptr for all Guest and System profiles. + // + // Without the experiment: + // +---------+------------+------------+ + // | | Original | OTR | + // +---------+------------+------------+ + // | Regular | self | original | + // | Guest | self | original | + // | System | self | original | + // +---------+------------+------------+ + // + // With the experiment: + // +---------+------------+------------+ + // | | Original | OTR | + // +---------+------------+------------+ + // | Regular | self | original | + // | Guest | no profile | no profile | + // | System | no profile | no profile | + // +---------+------------+------------+ + // + // Parameters: (used during the experiment) + // - force_guest: true, force Guest with + // `ProfileSelecion::kRedirectedToOriginal`. + // - force_system: true, force System with + // `ProfileSelecion::kRedirectedToOriginal`. + static ProfileSelections BuildRedirectedInIncognito( + bool force_guest = false, + bool force_system = false); - // No services for all profiles. - static ProfileSelections BuildNoServicesForAllProfiles(); - - // Only build services for the regular profile. - static ProfileSelections BuildServicesForRegularProfile(); - - // Redirects building services for regular off the record profiles (incognito - // and other off the record profiles) to regular Profile. Doesn't build - // services for Guest and System profiles. - static ProfileSelections BuildServicesRedirectedInIncognito(); - - // Redirects building services for both OTR and Original profile to Original - // Profile for all profile types (Regular, Guest and System). - static ProfileSelections BuildServicesRedirectedToOriginal(); + // Without the experiment: + // +---------+------------+------------+ + // | | Original | OTR | + // +---------+------------+------------+ + // | Regular | self | self | + // | Guest | self | self | + // | System | self | self | + // +---------+------------+------------+ + // + // With the experiment: + // +---------+------------+------------+ + // | | Original | OTR | + // +---------+------------+------------+ + // | Regular | self | self | + // | Guest | no profile | no profile | + // | System | no profile | no profile | + // +---------+------------+------------+ + // + // Parameters: (used during the experiment) + // - force_guest: true, force Guest with `ProfileSelecion::kOwnInstance`. + // - force_system: true, force System with `ProfileSelecion::kOwnInstance`. + static ProfileSelections BuildForRegularAndIncognito( + bool force_guest = false, + bool force_system = false); // Builder to construct the `ProfileSelections` parameters. class Builder {
diff --git a/chrome/browser/profiles/profile_selections_unittest.cc b/chrome/browser/profiles/profile_selections_unittest.cc index 8ac6354..e7c126a 100644 --- a/chrome/browser/profiles/profile_selections_unittest.cc +++ b/chrome/browser/profiles/profile_selections_unittest.cc
@@ -49,21 +49,6 @@ ProfileTestingHelper profile_testing_helper_; }; -TEST_F(ProfileSelectionsTest, DefaultImplementation) { - ProfileSelections selections = ProfileSelections::BuildDefault(); - - TestProfileSelection(selections, regular_profile(), regular_profile()); - TestProfileSelection(selections, incognito_profile(), nullptr); - - TestProfileSelection(selections, guest_profile(), guest_profile()); - TestProfileSelection(selections, guest_profile_otr(), nullptr); - -#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) - TestProfileSelection(selections, system_profile(), system_profile()); - TestProfileSelection(selections, system_profile_otr(), nullptr); -#endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) -} - TEST_F(ProfileSelectionsTest, CustomImplementation) { ProfileSelections selections = ProfileSelections::Builder() @@ -85,8 +70,7 @@ } TEST_F(ProfileSelectionsTest, OnlyRegularProfile) { - ProfileSelections selections = - ProfileSelections::BuildServicesForRegularProfile(); + ProfileSelections selections = ProfileSelections::BuildForRegularProfile(); TestProfileSelection(selections, regular_profile(), regular_profile()); TestProfileSelection(selections, incognito_profile(), nullptr); @@ -102,7 +86,7 @@ TEST_F(ProfileSelectionsTest, RedirectedInIncognito) { ProfileSelections selections = - ProfileSelections::BuildServicesRedirectedInIncognito(); + ProfileSelections::BuildRedirectedInIncognitoNonExperimental(); TestProfileSelection(selections, regular_profile(), regular_profile()); TestProfileSelection(selections, incognito_profile(), regular_profile()); @@ -117,8 +101,7 @@ } TEST_F(ProfileSelectionsTest, RedirectedToOriginal) { - ProfileSelections selections = - ProfileSelections::BuildServicesRedirectedToOriginal(); + ProfileSelections selections = ProfileSelections::BuildRedirectedToOriginal(); TestProfileSelection(selections, regular_profile(), regular_profile()); TestProfileSelection(selections, incognito_profile(), regular_profile()); @@ -133,8 +116,7 @@ } TEST_F(ProfileSelectionsTest, ForAllProfiles) { - ProfileSelections selections = - ProfileSelections::BuildServicesForAllProfiles(); + ProfileSelections selections = ProfileSelections::BuildForAllProfiles(); TestProfileSelection(selections, regular_profile(), regular_profile()); TestProfileSelection(selections, incognito_profile(), incognito_profile()); @@ -149,8 +131,7 @@ } TEST_F(ProfileSelectionsTest, NoProfiles) { - ProfileSelections selections = - ProfileSelections::BuildNoServicesForAllProfiles(); + ProfileSelections selections = ProfileSelections::BuildNoProfilesSelected(); TestProfileSelection(selections, regular_profile(), nullptr); TestProfileSelection(selections, incognito_profile(), nullptr); @@ -163,3 +144,70 @@ TestProfileSelection(selections, system_profile_otr(), nullptr); #endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) } + +// Testing Experimental Builders. +// As long as the experiments are not active, force values will not have an +// effect on the expected values, the tests will be adapted to reflect that when +// taking into account the experiment. +class ProfileSelectionsTestWithParams + : public ProfileSelectionsTest, + public ::testing::WithParamInterface<std::tuple<bool, bool>> {}; + +TEST_P(ProfileSelectionsTestWithParams, BuildDefault) { + bool force_guest = std::get<0>(GetParam()); + bool force_system = std::get<1>(GetParam()); + ProfileSelections selections = + ProfileSelections::BuildDefault(force_guest, force_system); + + TestProfileSelection(selections, regular_profile(), regular_profile()); + TestProfileSelection(selections, incognito_profile(), nullptr); + + TestProfileSelection(selections, guest_profile(), guest_profile()); + TestProfileSelection(selections, guest_profile_otr(), nullptr); + +#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) + TestProfileSelection(selections, system_profile(), system_profile()); + TestProfileSelection(selections, system_profile_otr(), nullptr); +#endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) +} + +TEST_P(ProfileSelectionsTestWithParams, BuildRedirectedInIncognito) { + bool force_guest = std::get<0>(GetParam()); + bool force_system = std::get<1>(GetParam()); + ProfileSelections selections = + ProfileSelections::BuildRedirectedInIncognito(force_guest, force_system); + + TestProfileSelection(selections, regular_profile(), regular_profile()); + TestProfileSelection(selections, incognito_profile(), regular_profile()); + + TestProfileSelection(selections, guest_profile(), guest_profile()); + TestProfileSelection(selections, guest_profile_otr(), guest_profile()); + +#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) + TestProfileSelection(selections, system_profile(), system_profile()); + TestProfileSelection(selections, system_profile_otr(), system_profile()); +#endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) +} + +TEST_P(ProfileSelectionsTestWithParams, BuildForRegularAndIncognito) { + bool force_guest = std::get<0>(GetParam()); + bool force_system = std::get<1>(GetParam()); + ProfileSelections selections = + ProfileSelections::BuildForRegularAndIncognito(force_guest, force_system); + + TestProfileSelection(selections, regular_profile(), regular_profile()); + TestProfileSelection(selections, incognito_profile(), incognito_profile()); + + TestProfileSelection(selections, guest_profile(), guest_profile()); + TestProfileSelection(selections, guest_profile_otr(), guest_profile_otr()); + +#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) + TestProfileSelection(selections, system_profile(), system_profile()); + TestProfileSelection(selections, system_profile_otr(), system_profile_otr()); +#endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) +} + +INSTANTIATE_TEST_SUITE_P(ExperimentalBuilders, + ProfileSelectionsTestWithParams, + ::testing::Combine(::testing::Bool(), + ::testing::Bool()));
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.cc b/chrome/browser/push_messaging/push_messaging_service_impl.cc index 993582aa0..bbbf4d8a 100644 --- a/chrome/browser/push_messaging/push_messaging_service_impl.cc +++ b/chrome/browser/push_messaging/push_messaging_service_impl.cc
@@ -55,6 +55,7 @@ #include "content/public/browser/browser_context.h" #include "content/public/browser/devtools_background_services_context.h" #include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/service_worker_context.h" @@ -961,8 +962,9 @@ url::Origin::Create(origin)); } else { return profile_->GetPermissionController() - ->GetPermissionStatusForOriginWithoutContext( - blink::PermissionType::NOTIFICATIONS, url::Origin::Create(origin)); + ->GetPermissionResultForOriginWithoutContext( + blink::PermissionType::NOTIFICATIONS, url::Origin::Create(origin)) + .status; } }
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index 48833e05..754df5997 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -3241,8 +3241,9 @@ if (!base::FeatureList::IsEnabled( lens::features::kEnableRegionSearchOnPdfViewer) && - IsFrameInPdfViewer(GetRenderFrameHost())) + IsFrameInPdfViewer(GetRenderFrameHost())) { return false; + } const TemplateURL* provider = service->GetDefaultSearchProvider(); const bool provider_supports_image_search = @@ -3587,14 +3588,12 @@ #if BUILDFLAG(GOOGLE_CHROME_BRANDING) if (!lens_region_search_controller_) { Browser* browser = GetBrowser(); - WebContents* web_contents; + WebContents* web_contents = source_web_contents_; if (base::FeatureList::IsEnabled( lens::features::kEnableRegionSearchOnPdfViewer)) { - // We don't use |source_web_contents_| here because it doesn't work with + // We don't use `source_web_contents_` here because it doesn't work with // the PDF reader. web_contents = browser->tab_strip_model()->GetActiveWebContents(); - } else { - web_contents = source_web_contents_; } lens_region_search_controller_ = std::make_unique<lens::LensRegionSearchController>(web_contents,
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn index 37e1d397..16032ed5 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
@@ -21,7 +21,6 @@ chromevox_modules = [ "../common/automation_predicate.js", "../common/constants.js", - "../common/cursors/recovery_strategy.js", "background/braille/cursor_dots.js", "background/braille/pan_strategy.js", "common/abstract_earcons.js", @@ -40,6 +39,7 @@ "../common/automation_util.js", "../common/cursors/cursor.js", "../common/cursors/range.js", + "../common/cursors/recovery_strategy.js", "../common/event_generator.js", "../common/instance_checker.js", "../common/key_code.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/auto_scroll_handler_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/auto_scroll_handler_test.js index 9e54419..0cff5bd 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/auto_scroll_handler_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/auto_scroll_handler_test.js
@@ -218,8 +218,8 @@ .call(doCmd('nextObject')) .expectSpeech('4th item') .call(doCmd('nextObject')) - .expectSpeech('5th item') - .replay(); + .expectSpeech('5th item'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -238,8 +238,8 @@ .call(doCmd('nextObject')) .expectSpeech('hello') .call(doCmd('nextObject')) - .expectSpeech('world') - .replay(); + .expectSpeech('world'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -252,8 +252,8 @@ .call(doCmd('nextObject')) // scroll forward .expectSpeech('3rd item') .call(doCmd('previousObject')) // scroll backward - .expectSpeech('2nd item') - .replay(); + .expectSpeech('2nd item'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -270,8 +270,8 @@ .call(doCmd('previousWord')) // scroll backward .expectSpeech('item') .call(doCmd('previousWord')) - .expectSpeech('2nd') - .replay(); + .expectSpeech('2nd'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -299,8 +299,8 @@ .call(doCmd('previousCharacter')) // scroll backward .expectSpeech('m') .call(doCmd('previousCharacter')) - .expectSpeech('e') - .replay(); + .expectSpeech('e'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -318,6 +318,6 @@ .call(doCmd('nextSimilarItem')) // scroll forward .expectSpeech('3rd item') .call(doCmd('previousSimilarItem')) // scroll backward - .expectSpeech('2nd item') - .replay(); + .expectSpeech('2nd item'); + await mockFeedback.replay(); });
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js index 1ee59192..32c57c5e 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
@@ -311,7 +311,7 @@ .expectSpeech('of test') .expectBraille('of test'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'CaretNavigation', async function() { @@ -338,7 +338,7 @@ mockFeedback.call(doCmd('previousCharacter')).expectSpeech('a', 'Link'); mockFeedback.call(doCmd('previousCharacter')).expectSpeech('t'); mockFeedback.call(doCmd('nextWord')).expectSpeech('echo', 'Link'); - mockFeedback.replay(); + await mockFeedback.replay(); }); /** Tests that individual buttons are stops for move-by-word functionality. */ @@ -366,7 +366,7 @@ mockFeedback.call(doCmd('previousWord')).expectSpeech('one'); mockFeedback.call(doCmd('previousWord')).expectSpeech('button'); mockFeedback.call(doCmd('previousWord')).expectSpeech('hello'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'SelectSingleBasic', async function() { @@ -380,7 +380,7 @@ .call(press(KeyCode.DOWN)) .expectSpeech('banana', /3 of 3/) .expectBraille('banana 3/3'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'ContinuousRead', async function() { @@ -390,14 +390,14 @@ .call(doCmd('readFromHere')) .expectSpeech( 'start', 'alpha', 'Link', 'beta', 'Link', 'charlie', 'Heading 1'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'InitialFocus', async function() { const mockFeedback = this.createMockFeedback(); await this.runWithLoadedTree('<a href="a">a</a>'); mockFeedback.expectSpeech('a').expectSpeech('Link'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'AriaLabel', async function() { @@ -409,7 +409,7 @@ .expectSpeech('Link') .expectSpeech('Press Search+Space to activate') .expectBraille('foo lnk'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'ShowContextMenu', async function() { @@ -423,7 +423,7 @@ .expectSpeech(/menu opened/) .call(press(KeyCode.ESCAPE)) .expectSpeech('a', 'Link'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'BrailleRouting', async function() { @@ -462,7 +462,7 @@ .call(function() { assertEquals(3, textField.textSelStart); }); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'FocusInputElement', async function() { @@ -484,7 +484,7 @@ .call(focus(name)) .expectNextSpeechUtteranceIsNot('Blue') .expectSpeech('Lancelot', 'Edit text'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'UseEditableState', async function() { @@ -549,7 +549,7 @@ .expectSpeech(/Slider/) .expectEarcon(Earcon.SLIDER); - mockFeedback.replay(); + await mockFeedback.replay(); }); TEST_F('ChromeVoxBackgroundTest', 'GlobsToRegExp', function() { @@ -632,8 +632,8 @@ .expectNextSpeechUtteranceIsNot('noisy') .call(focus(slider)) .expectSpeech('noisy') - .expectSpeech('noisy') - .replay(); + .expectSpeech('noisy'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'Checkbox', async function() { @@ -666,15 +666,16 @@ .call(doDefault(cbx)) .expectSpeech('go') .expectSpeech('Check box') - .expectSpeech('Not checked') - .replay(); + .expectSpeech('Not checked'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'MixedCheckbox', async function() { const mockFeedback = this.createMockFeedback(); const site = '<div id="go" role="checkbox" aria-checked="mixed">go</div>'; const root = await this.runWithLoadedTree(site); - mockFeedback.expectSpeech('go', 'Check box', 'Partially checked').replay(); + mockFeedback.expectSpeech('go', 'Check box', 'Partially checked'); + await mockFeedback.replay(); }); /** Tests navigating into and out of iframes using nextButton */ @@ -684,7 +685,7 @@ const mockFeedback = this.createMockFeedback(); let running = false; - const runTestIfIframeIsLoaded = function(rootNode) { + const runTestIfIframeIsLoaded = async function(rootNode) { if (running) { return; } @@ -707,7 +708,7 @@ .expectSpeech('Inside', 'Button'); mockFeedback.call(doCmd('previousButton')) .expectSpeech('Before', 'Button'); - mockFeedback.replay(); + await mockFeedback.replay(); }.bind(this); const rootNode = await this.runWithLoadedTree(this.iframesDoc); @@ -727,7 +728,7 @@ const mockFeedback = this.createMockFeedback(); let running = false; - const runTestIfIframeIsLoaded = function(rootNode) { + const runTestIfIframeIsLoaded = async function(rootNode) { if (running) { return; } @@ -759,7 +760,7 @@ .expectSpeech('Inside', 'Button'); mockFeedback.call(doCmd('previousObject')) .expectSpeech('Before', 'Button'); - mockFeedback.replay(); + await mockFeedback.replay(); }.bind(this); const rootNode = await this.runWithLoadedTree(this.iframesDoc); @@ -800,8 +801,8 @@ .expectSpeech('Expanded') .call(selectLastOption) .expectNextSpeechUtteranceIsNot('apple') - .expectSpeech('grapefruit') - .replay(); + .expectSpeech('grapefruit'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'ToggleButton', async function() { @@ -832,9 +833,9 @@ .call(move) .expectSpeech('close') - .expectSpeech('Button') + .expectSpeech('Button'); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'EditText', async function() { @@ -849,15 +850,15 @@ mockFeedback.call(nextEditText) .expectSpeech('Combo box') .call(previousEditText) - .expectSpeech('Edit text') - .replay(); + .expectSpeech('Edit text'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'ComboBox', async function() { const mockFeedback = this.createMockFeedback(); await this.runWithLoadedTree(this.comboBoxDoc); - mockFeedback.expectSpeech('Edit text', 'Choose an item', 'Combo box') - .replay(); + mockFeedback.expectSpeech('Edit text', 'Choose an item', 'Combo box'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'BackwardForwardSync', async function() { @@ -888,8 +889,8 @@ .call(this.doCmd('previousObject')) .expectSpeech('Edit text') .call(this.doCmd('previousObject')) - .expectSpeech('Group') - .replay(); + .expectSpeech('Group'); + await mockFeedback.replay(); }); /** Tests that navigation works when the current object disappears. */ @@ -927,7 +928,7 @@ .expectSpeech('Before3'); */ - mockFeedback.replay(); + await mockFeedback.replay(); }); /** Tests that focus jumps to details properly when indicated. */ @@ -935,7 +936,7 @@ const mockFeedback = this.createMockFeedback(); const rootNode = await this.runWithLoadedTree(this.detailsDoc); mockFeedback.call(doCmd('jumpToDetails')).expectSpeech('Details'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -944,10 +945,8 @@ const site = '<input type="submit" aria-label="foo" value="foo"></input>'; const root = await this.runWithLoadedTree(site); const btn = root.find({role: RoleType.BUTTON}); - mockFeedback.call(focus(btn)) - .expectSpeech('foo') - .expectSpeech('Button') - .replay(); + mockFeedback.call(focus(btn)).expectSpeech('foo').expectSpeech('Button'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'NameFromHeadingLink', async function() { @@ -961,8 +960,8 @@ mockFeedback.call(focus(link)) .expectSpeech('go') .expectSpeech('Link') - .expectSpeech('Heading 1') - .replay(); + .expectSpeech('Heading 1'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'OptionChildIndexCount', async function() { @@ -991,8 +990,8 @@ .expectSpeech(' 1 of 2 ') .call(doCmd('nextObject')) .expectSpeech('banana') - .expectSpeech(' 2 of 2 ') - .replay(); + .expectSpeech(' 2 of 2 '); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'ListMarkerIsIgnored', async function() { @@ -1000,8 +999,8 @@ const root = await this.runWithLoadedTree('<ul><li>apple</ul>'); mockFeedback.call(doCmd('nextObject')) .expectNextSpeechUtteranceIsNot('listMarker') - .expectSpeech('\u2022 apple') // bullet apple - .replay(); + .expectSpeech('\u2022 apple'); // bullet apple + await mockFeedback.replay(); }); AX_TEST_F( @@ -1017,8 +1016,8 @@ .expectSpeech('NW') .call(doCmd('previousHeading')) .expectNextSpeechUtteranceIsNot('NE') - .expectSpeech('NW') - .replay(); + .expectSpeech('NW'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -1051,8 +1050,8 @@ .call(assertRangeHasText('Most Popular')) .call(doCmd('nextHeading')) .expectSpeech('Sports') - .call(assertRangeHasText('Sports')) - .replay(); + .call(assertRangeHasText('Sports')); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'Selection', async function() { @@ -1081,8 +1080,8 @@ .expectSpeech('i', 'unselected') .call(doCmd('nextCharacter')) .call(doCmd('nextCharacter')) - .expectSpeech('End selection', 'sim') - .replay(); + .expectSpeech('End selection', 'sim'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'BasicTableCommands', async function() { @@ -1150,9 +1149,9 @@ .call(doCmd('goToFirstCell')) .expectSpeech('name', 'row 1 column 1') .call(doCmd('goToFirstCell')) - .expectSpeech('name') + .expectSpeech('name'); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'MissingTableCells', async function() { @@ -1193,15 +1192,16 @@ .call(doCmd('goToLastCell')) .expectSpeech('f', 'row 3 column 1') .call(doCmd('goToLastCell')) - .expectSpeech('f') - .replay(); + .expectSpeech('f'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'DisabledState', async function() { const mockFeedback = this.createMockFeedback(); const site = '<button aria-disabled="true">ok</button>'; const root = await this.runWithLoadedTree(site); - mockFeedback.expectSpeech('ok', 'Disabled', 'Button').replay(); + mockFeedback.expectSpeech('ok', 'Disabled', 'Button'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'HeadingLevels', async function() { @@ -1221,7 +1221,7 @@ for (let i = 1; i <= 6; i++) { makeLevelAssertions(i); } - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'EditableNavigation', async function() { @@ -1239,8 +1239,8 @@ .call(doCmd('nextWord')) .expectSpeech('a') .call(doCmd('nextWord')) - .expectSpeech('test') - .replay(); + .expectSpeech('test'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'NavigationMovesFocus', async function() { @@ -1274,8 +1274,8 @@ .expectBraille(text, {startIndex: 0, endIndex: 4}) // This .call(doCmd('nextLine')) // Ensure nothing is selected when the range covers the entire line. - .expectBraille('with a second line', {startIndex: -1, endIndex: -1}) - .replay(); + .expectBraille('with a second line', {startIndex: -1, endIndex: -1}); + await mockFeedback.replay(); }); // This tests ChromeVox's special support for following an in-page link @@ -1289,8 +1289,8 @@ const root = await this.runWithLoadedTree(site); mockFeedback.expectSpeech('hi', 'Internal link') .call(doCmd('forceClickOnCurrentItem')) - .expectSpeech('there', 'Button') - .replay(); + .expectSpeech('there', 'Button'); + await mockFeedback.replay(); }); // This tests ChromeVox's handling of the scrolledToAnchor event, which is @@ -1314,8 +1314,8 @@ .call(press(KeyCode.RETURN)) .expectSpeech('Found It') .call(doCmd('nextHeading')) - .expectSpeech('Continue Here', 'Heading 2') - .replay(); + .expectSpeech('Continue Here', 'Heading 2'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'ListItem', async function() { @@ -1348,8 +1348,8 @@ // Mixing with line nav. .call(doCmd('nextLine')) .expectSpeech('3. chicken', 'List item') - .expectBraille('3. chicken lstitm lst end') - .replay(); + .expectBraille('3. chicken lstitm lst end'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'BusyHeading', async function() { @@ -1365,8 +1365,8 @@ mockFeedback.call(doCmd('nextLine')) .expectSpeech( 'Lots', 'Link', 'going', 'Link', 'here', 'Link', 'Heading 2') - .expectBraille('Lots lnk going lnk here lnk h2') - .replay(); + .expectBraille('Lots lnk going lnk here lnk h2'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'NodeVsSubnode', async function() { @@ -1394,8 +1394,8 @@ .expectNextSpeechUtteranceIsNot('Internal link') .expectSpeech('es') .call(outputLinkRange(0, 4)) - .expectSpeech('test', 'Internal link') - .replay(); + .expectSpeech('test', 'Internal link'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'NativeFind', async function() { @@ -1411,8 +1411,8 @@ .expectSpeech('grape', 'Link') .call(press(KeyCode.BACK)) .call(press(KeyCode.L)) - .expectSpeech('pineapple', 'Link') - .replay(); + .expectSpeech('pineapple', 'Link'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'EditableKeyCommand', async function() { @@ -1442,9 +1442,9 @@ .expectSpeech('Text area') .call(assertCurNode(textArea)) .call(doCmd('previousObject')) - .call(assertCurNode(textField)) + .call(assertCurNode(textField)); - .replay(); + await mockFeedback.replay(); }); // TODO(crbug.com/935678): Test times out flakily in MSAN builds. @@ -1495,9 +1495,9 @@ .call(doDefault(div)) .expectSpeechWithQueueMode('interrupted', QueueMode.QUEUE) - .expectSpeechWithQueueMode('s', QueueMode.CATEGORY_FLUSH) + .expectSpeechWithQueueMode('s', QueueMode.CATEGORY_FLUSH); - .replay(); + await mockFeedback.replay(); })(); }); @@ -1537,8 +1537,8 @@ .call(doCmd('previousRow')) .expectSpeech('CA', 'row 2 column 2') .call(doCmd('previousRow')) - .expectSpeech('state', 'row 1 column 2') - .replay(); + .expectSpeech('state', 'row 1 column 2'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -1567,8 +1567,8 @@ .call(doDefault(group)) .expectSpeech('Tree item', ' 2 of 2 ') .call(doDefault(group)) - .expectSpeech('Tree item', 'Not selected', ' 1 of 2 ') - .replay(); + .expectSpeech('Tree item', 'Not selected', ' 1 of 2 '); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'NavigationEscapesEdit', async function() { @@ -1631,9 +1631,9 @@ .call(press(40 /* ArrowDown */)) .expectSpeech('test') .call(assertBeginning.bind(this, false)) - .call(assertEnd.bind(this, true)) + .call(assertEnd.bind(this, true)); - .replay(); + await mockFeedback.replay(); // TODO: soft line breaks currently won't work in <textarea>. }); @@ -1665,8 +1665,8 @@ .expectSpeech('apple', 'List item', ' 1 of 2 ') .call( () => assertEquals( - select, ChromeVoxState.instance.currentRange.start.node)) - .replay(); + select, ChromeVoxState.instance.currentRange.start.node)); + await mockFeedback.replay(); }); AX_TEST_F( @@ -1705,8 +1705,8 @@ .call(doCmd('nextObject')) .expectEarcon(Earcon.WRAP) .call(doCmd('nextObject')) - .expectSpeech('before') - .replay(); + .expectSpeech('before'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -1739,8 +1739,8 @@ .call(doCmd('nextObject')) .expectEarcon(Earcon.WRAP) .call(doCmd('nextObject')) - .expectSpeech('before') - .replay(); + .expectSpeech('before'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -1782,8 +1782,8 @@ const root = await this.runWithLoadedTree(site); mockFeedback.call(doCmd('nextObject')) .expectSpeech('a ( y + m ) squared + b ( y + m ) + c = 0 .') - .expectSpeech('Press up, down, left, or right to explore math') - .replay(); + .expectSpeech('Press up, down, left, or right to explore math'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'GestureGranularity', async function() { @@ -1849,9 +1849,9 @@ .call(doGesture(Gesture.SWIPE_RIGHT3)) .expectSpeech('Form field control') .call(doGesture(Gesture.SWIPE_RIGHT3)) - .expectSpeech('Character') + .expectSpeech('Character'); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'LinesFilterWhitespace', async function() { @@ -1871,8 +1871,8 @@ .call(doCmd('nextLine')) .expectSpeech('Munich') .expectNextSpeechUtteranceIsNot(' ') - .expectSpeech('London') - .replay(); + .expectSpeech('London'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -1894,8 +1894,8 @@ .call(() => { assertEquals( 'tab2', ChromeVoxState.instance.currentRange.start.node.name); - }) - .replay(); + }); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'ListName', async function() { @@ -1911,7 +1911,8 @@ </div> `; const root = await this.runWithLoadedTree(site); - mockFeedback.expectSpeech('Favorite Sports').replay(); + mockFeedback.expectSpeech('Favorite Sports'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'LayoutTable', async function() { @@ -1924,8 +1925,8 @@ .call(doCmd('nextObject')) .expectNextSpeechUtteranceIsNot('row 1 column 1') .expectNextSpeechUtteranceIsNot('Table , 1 by 1') - .expectSpeech('end') - .replay(); + .expectSpeech('end'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -1953,8 +1954,8 @@ .call(doCmd('nextObject')) .call(doCmd('nextObject')) .call(doCmd('nextObject')) - .expectSpeech('end', 'Button') - .replay(); + .expectSpeech('end', 'Button'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -1974,8 +1975,8 @@ assertNotNullNorUndefined(buttonText); mockFeedback.call(simulateHitTestResult(buttonText)) .expectSpeech('Jefferson') - .expectSpeech('Button') - .replay(); + .expectSpeech('Button'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -1995,7 +1996,8 @@ const root = await this.runWithLoadedTree(site); const slider = root.find({role: RoleType.SLIDER}); assertNotNullNorUndefined(slider); - mockFeedback.call(doDefault(slider)).expectSpeech('51').replay(); + mockFeedback.call(doDefault(slider)).expectSpeech('51'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2019,8 +2021,8 @@ mockFeedback.clearPendingOutput() .call(doDefault(slider)) .expectNextSpeechUtteranceIsNot('51') - .expectSpeech('large') - .replay(); + .expectSpeech('large'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'SelectValidityOutput', async function() { @@ -2046,8 +2048,8 @@ .expectSpeech('Edit text') .expectSpeech('Required') .expectNextSpeechUtteranceIsNot('Alert') - .expectSpeech('Please enter name') - .replay(); + .expectSpeech('Please enter name'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'EventFromAction', async function() { @@ -2118,7 +2120,7 @@ .call(doCmd('nextEditText')) .call(doCmd('readPhoneticPronunciation')) .expectSpeech('No available text for this item'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'SimilarItemNavigation', async function() { @@ -2146,7 +2148,7 @@ .call(doCmd('previousSimilarItem')) .expectSpeech('inner', 'Heading 3'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'InvalidItemNavigation', async function() { @@ -2185,7 +2187,7 @@ .call(doCmd('previousInvalidItem')) .expectSpeech('this are', 'grammar error'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2208,7 +2210,7 @@ .call(doCmd('previousInvalidItem')) .expectSpeech('No invalid item'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'TableWithAriaRowCol', async function() { @@ -2222,8 +2224,8 @@ `; const root = await this.runWithLoadedTree(site); mockFeedback.call(doCmd('fullyDescribe')) - .expectSpeech('test', 'row 3 column 1', 'Table , 1 by 1') - .replay(); + .expectSpeech('test', 'row 3 column 1', 'Table , 1 by 1'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2239,8 +2241,8 @@ mockFeedback.call(doCmd('nextHeading')) .expectSpeech('Heading inside dialog') .call(doCmd('previousHeading')) - .expectSpeech('Heading outside dialog') - .replay(); + .expectSpeech('Heading outside dialog'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2292,8 +2294,8 @@ '■ Mandarins', 'List item', 'List end', 'nested level 3') .call(doCmd('nextObject')) // Nested level is not mentioned for level 1. - .expectSpeech('• Bananas', 'List item', 'List end') - .replay(); + .expectSpeech('• Bananas', 'List item', 'List end'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2312,8 +2314,8 @@ .expectSpeech('◦ Raspberries', 'List item', 'List end') .call(doCmd('nextObject')) .expectSpeech('• Bananas', 'List item', 'List end') - .expectBraille('• Bananas lstitm lst end') - .replay(); + .expectBraille('• Bananas lstitm lst end'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2344,8 +2346,8 @@ .expectSpeech('◦ Strawberries', '◦ Raspberries') .clearPendingOutput() .call(doCmd('previousGroup')) - .expectSpeech('• Oranges') - .replay(); + .expectSpeech('• Oranges'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'NavigationByList', async function() { @@ -2419,8 +2421,8 @@ .call(doCmd('previousObject')) .expectSpeech('A random paragraph') .call(doCmd('previousList')) - .expectSpeech('Drinks', 'List', 'with 2 items') - .replay(); + .expectSpeech('Drinks', 'List', 'with 2 items'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'NoListTest', async function() { @@ -2430,7 +2432,7 @@ .expectSpeech('No next list') .call(doCmd('previousList')) .expectSpeech('No previous list'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'NavigateToLastHeading', async function() { @@ -2444,8 +2446,8 @@ mockFeedback.call(doCmd('jumpToTop')) .expectSpeech('First', 'Heading 1') .call(doCmd('previousHeading')) - .expectSpeech('Third', 'Heading 1') - .replay(); + .expectSpeech('Third', 'Heading 1'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'ReadLinkURLTest', async function() { @@ -2462,8 +2464,8 @@ .call(doCmd('nextObject')) .expectSpeech('Not a link', 'Button', 'Press Search+Space to activate') .call(doCmd('readLinkURL')) - .expectSpeech('No URL found') - .replay(); + .expectSpeech('No URL found'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'NoRepeatTitle', async function() { @@ -2475,8 +2477,8 @@ mockFeedback.expectSpeech('title') .expectSpeech('Button') .expectNextSpeechUtteranceIsNot('title') - .expectSpeech('Press Search+Space to activate') - .replay(); + .expectSpeech('Press Search+Space to activate'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'PhoneticsAndCommands', async function() { @@ -2505,7 +2507,7 @@ .expectSpeechWithProperties(phonetics, 'o') .call(doCmd('jumpToBottom')) .expectSpeechWithProperties(noPhonetics, 'A'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'ToggleScreen', async function() { @@ -2518,8 +2520,8 @@ .call(doCmd('toggleScreen')) .expectSpeech('Screen on') .call(doCmd('toggleScreen')) - .expectSpeech('Screen off') - .replay(); + .expectSpeech('Screen off'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2538,7 +2540,7 @@ .expectSpeech( 'No current ChromeVox focus. Press Alt+Shift+L to go to the ' + 'launcher.'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2562,7 +2564,7 @@ () => assertFalse(mockFeedback.utteranceInQueue( 'No current ChromeVox focus. ' + 'Press Alt+Shift+L to go to the launcher.'))); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2597,8 +2599,8 @@ .call(doCmd('previousLine')) .expectSpeech('Testing testing') .call(doCmd('previousLine')) - .expectSpeech('before') - .replay(); + .expectSpeech('before'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'ReadWindowTitle', async function() { @@ -2629,8 +2631,8 @@ // This test may run against official builds, so match against // utterances starting with 'bar'. This should exclude any other // utterances that contain 'bar' e.g. data:...bar.. or the data url. - .expectSpeech(/^bar*/) - .replay(); + .expectSpeech(/^bar*/); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'OutputEmptyQueueMode', async function() { @@ -2645,8 +2647,8 @@ mockFeedback.clearPendingOutput() .call(output.go.bind(output)) .expectSpeechWithQueueMode('', QueueMode.CATEGORY_FLUSH) - .expectSpeechWithQueueMode('test', QueueMode.CATEGORY_FLUSH) - .replay(); + .expectSpeechWithQueueMode('test', QueueMode.CATEGORY_FLUSH); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'SetAccessibilityFocus', async function() { @@ -2677,8 +2679,8 @@ .call(doCmd('nextObject')) .expectSpeech('Small, menu item radio button selected', ' 1 of 3 ') .call(doCmd('nextObject')) - .expectSpeech('Medium, menu item radio button unselected', ' 2 of 3 ') - .replay(); + .expectSpeech('Medium, menu item radio button unselected', ' 2 of 3 '); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2700,7 +2702,7 @@ .call(doCmd('nextButton')) .expectSpeech('Action 2', 'Button'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2786,8 +2788,8 @@ .expectSpeech('Button') .call(simulateHitTestResult(group)) .expectSpeech('range cleared!') - .expectEarcon(Earcon.NO_POINTER_ANCHOR) - .replay(); + .expectEarcon(Earcon.NO_POINTER_ANCHOR); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'FocusOnUnknown', async function() { @@ -2823,8 +2825,8 @@ mockFeedback .call(DesktopAutomationInterface.instance.onFocus.bind( DesktopAutomationInterface.instance, evt1)) - .expectSpeech('hello') - .replay(); + .expectSpeech('hello'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'TimeDateCommand', async function() { @@ -2832,8 +2834,8 @@ const root = await this.runWithLoadedTree('<p></p>'); mockFeedback.call(doCmd('speakTimeAndDate')) .expectSpeech(/(AM|PM)*(2)/) - .expectBraille(/(AM|PM)*(2)/) - .replay(); + .expectBraille(/(AM|PM)*(2)/); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'SwipeToScrollByPage', async function() { @@ -2855,8 +2857,8 @@ .call(doGesture(Gesture.SWIPE_DOWN3)) .expectSpeech(/Page 2 of/) .call(doGesture(Gesture.SWIPE_DOWN3)) - .expectSpeech(/Page 1 of/) - .replay(); + .expectSpeech(/Page 1 of/); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2885,8 +2887,8 @@ .expectEarcon(Earcon.NO_POINTER_ANCHOR) .clearPendingOutput() .call(simulateHitTestResult(button)) - .expectSpeech('hi', 'Button') - .replay(); + .expectSpeech('hi', 'Button'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'PopupButtonCollapsed', async function() { @@ -2901,8 +2903,8 @@ mockFeedback.call(doCmd('jumpToTop')) .expectSpeech( 'Apple', 'Button', 'has pop up', 'Collapsed', - 'Press Search+Space to activate') - .replay(); + 'Press Search+Space to activate'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'PopupButtonExpanded', async function() { @@ -2926,8 +2928,8 @@ // SetSize is only reported if popup button is expanded. .expectSpeech( 'Click me', 'Button', 'has pop up', 'with 3 items', 'Expanded', - 'Press Search+Space to activate') - .replay(); + 'Press Search+Space to activate'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'SortDirection', async function() { @@ -2956,8 +2958,8 @@ .call(doDefault(sortButton)) .expectSpeech('Ascending sort') .call(doDefault(sortButton)) - .expectSpeech('Descending sort') - .replay(); + .expectSpeech('Descending sort'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'InlineLineNavigation', async function() { @@ -2967,9 +2969,8 @@ <p><strong>This</strong><b>is</b>a <em>test</em></p> `; const root = await this.runWithLoadedTree(site); - mockFeedback.call(doCmd('nextLine')) - .expectSpeech('This', 'is', 'a ', 'test') - .replay(); + mockFeedback.call(doCmd('nextLine')).expectSpeech('This', 'is', 'a ', 'test'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'AudioVideo', async function() { @@ -3005,8 +3006,8 @@ mockFeedback.call(doCmd('nextObject')) .expectSpeech('Video') .call(doCmd('previousObject')) - .expectSpeech('Audio') - .replay(); + .expectSpeech('Audio'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'AlertNoAnnouncement', async function() { @@ -3022,8 +3023,8 @@ mockFeedback .call(DesktopAutomationInterface.instance.onAlert.bind( DesktopAutomationInterface.instance, alertEvt)) - .call(() => assertFalse(mockFeedback.utteranceInQueue('Alert'))) - .replay(); + .call(() => assertFalse(mockFeedback.utteranceInQueue('Alert'))); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'AlertAnnouncement', async function() { @@ -3041,8 +3042,8 @@ .call(DesktopAutomationInterface.instance.onAlert.bind( DesktopAutomationInterface.instance, alertEvt)) .expectNextSpeechUtteranceIsNot('Alert') - .expectSpeech('hello world') - .replay(); + .expectSpeech('hello world'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -3061,9 +3062,9 @@ .call(doGesture(Gesture.SWIPE_LEFT4)) .expectSpeech(/Calendar*/) .call(doGesture(Gesture.SWIPE_LEFT4)) - .expectSpeech('Shelf', 'Tool bar') + .expectSpeech('Shelf', 'Tool bar'); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'SwipeLeftRight2', async function() { @@ -3078,9 +3079,8 @@ `; const root = await this.runWithLoadedTree(site); mockFeedback.call(doGesture(Gesture.SWIPE_RIGHT2)).expectSpeech('Enter'); - mockFeedback.call(doGesture(Gesture.SWIPE_LEFT2)) - .expectSpeech('Escape') - .replay(); + mockFeedback.call(doGesture(Gesture.SWIPE_LEFT2)).expectSpeech('Escape'); + await mockFeedback.replay(); }); // TODO(crbug.com/1228418) - Improve the generation of summaries across ChromeOS @@ -3116,9 +3116,9 @@ .call(doCmd('previousObject')) .expectSpeech(`Let's go`, 'Button') .expectSpeech('Setup') - .expectSpeech(`Welcome This is some introductory text Exit Let's go`) + .expectSpeech(`Welcome This is some introductory text Exit Let's go`); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'ImageAnnotations', async function() { @@ -3155,8 +3155,8 @@ .expectSpeech('bar', 'Image') .call(doCmd('nextObject')) .expectNextSpeechUtteranceIsNot('bar') - .expectSpeech('foo', 'Image') - .replay(); + .expectSpeech('foo', 'Image'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'VolumeChanges', async function() { @@ -3168,8 +3168,8 @@ .call(() => { // The bounds should not have changed. assertEquals(JSON.stringify(bounds), JSON.stringify(FocusBounds.get())); - }) - .replay(); + }); + await mockFeedback.replay(); }); AX_TEST_F( @@ -3185,8 +3185,8 @@ .expectEarcon(Earcon.WRAP) .expectSpeech('Web Content') .call(doCmd('nextObject')) - .expectSpeech('start') - .replay(); + .expectSpeech('start'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -3202,8 +3202,8 @@ // and once during the 'read from here' command. mockFeedback.expectSpeech('start') .call(doCmd('readFromHere')) - .expectSpeech('start', 'end') - .replay(); + .expectSpeech('start', 'end'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'ContainerButtons', async function() { @@ -3228,8 +3228,8 @@ mockFeedback.call(doCmd('nextObject')) .expectSpeech('Cat Video', 'Button') .call(doCmd('nextObject')) - .expectSpeech('4 minutes, Cat Video') - .replay(); + .expectSpeech('4 minutes, Cat Video'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -3321,9 +3321,9 @@ .call( () => assertEquals( RoleType.CHECK_BOX, - ChromeVoxState.instance.currentRange.start.node.role)) + ChromeVoxState.instance.currentRange.start.node.role)); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'MarkedContent', async function() { @@ -3376,8 +3376,8 @@ .expectBraille(`Suggest Delete everyone's Delete end Suggest end`) .call(doCmd('nextObject')) .expectSpeech(' text.') - .expectBraille(' text.') - .replay(); + .expectBraille(' text.'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -3407,8 +3407,8 @@ .call(doCmd('nextObject')) .expectSpeech('more info') .call(doCmd('nextObject')) - .expectSpeech('end') - .replay(); + .expectSpeech('end'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'TouchEditingState', async function() { @@ -3426,8 +3426,8 @@ .expectSpeech('Edit text', 'Double tap to start editing') .call(doGesture( chrome.accessibilityPrivate.Gesture.CLICK, bounds.left, bounds.top)) - .expectSpeech('Edit text', 'is editing') - .replay(); + .expectSpeech('Edit text', 'is editing'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -3449,8 +3449,8 @@ .expectEarcon(Earcon.LINK) .call(doGesture(chrome.accessibilityPrivate.Gesture.SWIPE_LEFT1)) .expectSpeech('ok', 'Button') - .expectEarcon(Earcon.BUTTON) - .replay(); + .expectEarcon(Earcon.BUTTON); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'Separator', async function() { @@ -3469,8 +3469,8 @@ .expectSpeech('Separator content should be read', 'Separator') .expectBraille('Separator content should be read seprtr') .call(doCmd('nextObject')) - .expectSpeech('World') - .replay(); + .expectSpeech('World'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'FocusAfterClick', async function() { @@ -3496,8 +3496,8 @@ assertEquals( 'Focus me', ChromeVoxState.instance.getCurrentRange().start.node.name); - }) - .replay(); + }); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'EarconPlayback', function() { @@ -3609,9 +3609,10 @@ .call(toggleTalkBack) .call(nextObjectKeyboard) - .call(() => assertTrue(Boolean(ChromeVoxState.instance.currentRange))) + .call( + () => assertTrue(Boolean(ChromeVoxState.instance.currentRange))); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'DetailsChanged', async function() { @@ -3634,8 +3635,8 @@ const button = root.find({role: RoleType.BUTTON}); mockFeedback.expectSpeech('ok') .call(doDefault(button)) - .expectSpeech('Press Search+A, J to jump to details') - .replay(); + .expectSpeech('Press Search+A, J to jump to details'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'PageLoadEarcons', function() { @@ -3680,8 +3681,8 @@ mockFeedback.call(doCmd('nextObject')) .expectSpeech('end') .call(press(KeyCode.T, {ctrl: true})) - .expectSpeech(/New Tab/) - .replay(); + .expectSpeech(/New Tab/); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'NestedMenuHints', async function() { @@ -3699,8 +3700,8 @@ .expectSpeech('Press left or right arrow to navigate; enter to activate') .call( () => assertFalse(mockFeedback.utteranceInQueue( - 'Press up or down arrow to navigate; enter to activate'))) - .replay(); + 'Press up or down arrow to navigate; enter to activate'))); + await mockFeedback.replay(); }); AX_TEST_F( @@ -3723,8 +3724,8 @@ .call(doCmd('previousObject')) .expectSpeech('Enable speech logging', 'Check box') .call(doCmd('previousObject')) - .expectSpeech('start') - .replay(); + .expectSpeech('start'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'Abbreviation', async function() { @@ -3733,8 +3734,8 @@ <abbr title="uniform resource locator">URL</abbr> `; await this.runWithLoadedTree(site); - mockFeedback.expectSpeech('URL', 'uniform resource locator', 'Abbreviation') - .replay(); + mockFeedback.expectSpeech('URL', 'uniform resource locator', 'Abbreviation'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'EndOfText', async function() { @@ -3776,9 +3777,9 @@ .call(press(KeyCode.LEFT)) .expectSpeech('b') .call(press(KeyCode.LEFT)) - .expectSpeech('a') + .expectSpeech('a'); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -3789,7 +3790,8 @@ const tabs = root.findAll({Role: RoleType.TAB}); assertTrue(tabs.length > 0); tabs[0].showContextMenu(); - mockFeedback.expectSpeech(/menu opened/).replay(); + mockFeedback.expectSpeech(/menu opened/); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'SelectWithOptGroup', async function() { @@ -3812,8 +3814,8 @@ .call(press(KeyCode.DOWN)) .expectSpeech('Deinonychus') .call(press(KeyCode.UP)) - .expectSpeech('Velociraptor') - .replay(); + .expectSpeech('Velociraptor'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'GroupNavigation', async function() { @@ -3830,8 +3832,8 @@ .call(doCmd('nextObject')) .expectSpeech('bye', 'Link') .call(doCmd('previousGroup')) - .expectSpeech('hello', 'hi', 'Link', 'hey', 'Link') - .replay(); + .expectSpeech('hello', 'hi', 'Link', 'hey', 'Link'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -3853,8 +3855,8 @@ const button = root.find({role: RoleType.BUTTON}); mockFeedback.expectSpeech('hello') .call(doDefault(button)) - .expectSpeech('test title') - .replay(); + .expectSpeech('test title'); + await mockFeedback.replay(); }); TEST_F('ChromeVoxBackgroundTest', 'NewWindowWebSpeech', function() { @@ -3957,8 +3959,9 @@ .call(press(KeyCode.TAB)) .expectSpeech('Listbox item 2', ' 2 of 3 ', 'Configuration 2', 'List box') .call(press(KeyCode.TAB)) - .expectSpeech('Listbox item 3', ' 3 of 3 ', 'Configuration 3', 'List box') - .replay(); + .expectSpeech( + 'Listbox item 3', ' 3 of 3 ', 'Configuration 3', 'List box'); + await mockFeedback.replay(); }); // Make sure linear navigation does not go inside ListBox's options. @@ -3971,8 +3974,8 @@ .call(doCmd('nextObject')) .expectSpeech('Click', 'Button') .call(doCmd('previousObject')) - .expectSpeech('Select an item', 'List box') - .replay(); + .expectSpeech('Select an item', 'List box'); + await mockFeedback.replay(); }); // Make sure navigation with Tab to ListBox lands on options. @@ -3987,8 +3990,8 @@ .call(doCmd('nextObject')) .expectSpeech('Listbox item two', ' 2 of 3 ') .call(doCmd('nextObject')) - .expectSpeech('Listbox item three', ' 3 of 3 ') - .replay(); + .expectSpeech('Listbox item three', ' 3 of 3 '); + await mockFeedback.replay(); }); // Make sure navigation with touch to ListBox lands on options. @@ -4009,8 +4012,8 @@ .call(doGesture(chrome.accessibilityPrivate.Gesture.SWIPE_RIGHT1)) .expectSpeech('Listbox item two', ' 2 of 3 ') .call(doGesture(chrome.accessibilityPrivate.Gesture.SWIPE_RIGHT1)) - .expectSpeech('Listbox item three', ' 3 of 3 ') - .replay(); + .expectSpeech('Listbox item three', ' 3 of 3 '); + await mockFeedback.replay(); }); AX_TEST_F( @@ -4072,9 +4075,9 @@ // window2 -> window1. .call(doCmd('nextObject')) - .expectSpeech('second', 'Button', 'first, window') + .expectSpeech('second', 'Button', 'first, window'); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'GestureOnPopUpButton', async function() { @@ -4089,8 +4092,8 @@ .call(doGesture(Gesture.SWIPE_DOWN1)) .expectSpeech('banana') .call(doGesture(Gesture.SWIPE_UP1)) - .expectSpeech('apple') - .replay(); + .expectSpeech('apple'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxBackgroundTest', 'NestedImages', async function() { @@ -4124,6 +4127,6 @@ .expectSpeech('third', 'Image') .call(doCmd('nextObject')) - .expectSpeech('end') - .replay(); + .expectSpeech('end'); + await mockFeedback.replay(); });
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler_test.js index 53e964fa..eec632c 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler_test.js
@@ -81,9 +81,9 @@ .call(() => this.handler_.onValueChanged(event)) .expectNextSpeechUtteranceIsNot('70%') - .expectSpeech('80%') + .expectSpeech('80%'); - .replay(); + await mockFeedback.replay(); }); TEST_F( @@ -105,9 +105,9 @@ }) // Make sure it doesn't repeat the previous line! .expectNextSpeechUtteranceIsNot('Browser') - .expectSpeech('row 3 column 1'); + .expectSpeech('row 3 column 1') - mockFeedback.replay(); + .replay(); }); }); @@ -138,8 +138,8 @@ 'S: sierra, e: echo, c: charlie, o: oscar, n: november, d: delta') .call(() => this.handler_.onSelection(selectFirst)) .expectSpeech('First') - .expectSpeech(/foxtrot/) - .replay(); + .expectSpeech(/foxtrot/); + await mockFeedback.replay(); }); AX_TEST_F( @@ -164,8 +164,8 @@ assertFalse(mockFeedback.utteranceInQueue('Hello world')); this.handler_.onAlert(event); assertFalse(mockFeedback.utteranceInQueue('Hello world')); - }) - .replay(); + }); + await mockFeedback.replay(); }); AX_TEST_F( @@ -197,6 +197,6 @@ .expectBraille('bar lstitm 2/2 (x)') .call(press(KeyCode.UP)) .expectSpeech('foo', 'List item', ' 1 of 2 ') - .expectBraille('foo lstitm 1/2 (x)') - .replay(); + .expectBraille('foo lstitm 1/2 (x)'); + await mockFeedback.replay(); });
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_line.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_line.js index 5c508ee9..e7c0e8a 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_line.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editable_line.js
@@ -11,6 +11,7 @@ import {AutomationUtil} from '../../../common/automation_util.js'; import {Cursor, CURSOR_NODE_INDEX, CursorMovement, CursorUnit} from '../../../common/cursors/cursor.js'; import {CursorRange} from '../../../common/cursors/range.js'; +import {RecoveryStrategy, TreePathRecoveryStrategy} from '../../../common/cursors/recovery_strategy.js'; import {Spannable} from '../../common/spannable.js'; import {LibLouis} from '../braille/liblouis.js'; import {Output} from '../output/output.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js index 2a071f47..d48f5527 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing/editing_test.js
@@ -84,7 +84,7 @@ .expectBraille( 'textArea Line 1\nline 2\nline 3 mled', {startIndex: 9, endIndex: 9}); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'Multiline', async function() { @@ -106,7 +106,7 @@ .expectSpeech('line 2', 'selected') .expectBraille('line 2\n', {startIndex: 0, endIndex: 6}); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'TextButNoSelectionChange', async function() { @@ -138,7 +138,7 @@ .call(input.setSelection.bind(input, 5, 5)) .expectBraille('text2 ed', {startIndex: 5, endIndex: 5}); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'RichTextMoveByLine', async function() { @@ -189,8 +189,8 @@ .expectBraille('\n') .call(moveByLine) .expectSpeech('hello', 'Heading 2') - .expectBraille('hello h2 mled') - .replay(); + .expectBraille('hello h2 mled'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'RichTextMoveByCharacter', async function() { @@ -262,9 +262,9 @@ .call(moveByChar) .expectSpeech(' ') - .expectBraille(lineText, {startIndex: 9, endIndex: 9}) + .expectBraille(lineText, {startIndex: 9, endIndex: 9}); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -428,9 +428,9 @@ .expectSpeech('Black, 100% opacity.') .expectSpeech('Not link') .expectSpeech('Not underline') - .expectBraille(lineText, {startIndex: 35, endIndex: 35}) + .expectBraille(lineText, {startIndex: 35, endIndex: 35}); - .replay(); + await mockFeedback.replay(); }); // Tests specifically for cursor workarounds. @@ -472,8 +472,8 @@ .expectBraille(lineText, {startIndex: 5, endIndex: 5}) .call(moveByChar) .expectSpeech('w') - .expectBraille(lineText, {startIndex: 6, endIndex: 6}) - .replay(); + .expectBraille(lineText, {startIndex: 6, endIndex: 6}); + await mockFeedback.replay(); }); AX_TEST_F( @@ -508,9 +508,9 @@ .expectBraille(lineText, {startIndex: 3, endIndex: 3}) .call(moveByChar) .expectSpeech('End of text') - .expectBraille(lineText, {startIndex: 4, endIndex: 4}) + .expectBraille(lineText, {startIndex: 4, endIndex: 4}); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'RichTextLinkOutput', async function() { @@ -552,9 +552,9 @@ .expectBraille(lineOnLinkText, {startIndex: 4, endIndex: 4}) .call(moveByChar) .expectSpeech('t') - .expectBraille(lineOnLinkText, {startIndex: 5, endIndex: 5}) + .expectBraille(lineOnLinkText, {startIndex: 5, endIndex: 5}); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -585,9 +585,9 @@ .call(moveByChar) .expectSpeech('s', 'selected') .call(moveByChar) - .expectSpeech('t', 'selected') + .expectSpeech('t', 'selected'); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'RichTextImageByCharacter', async function() { @@ -652,7 +652,7 @@ mockFeedback.expectBraille.apply(mockFeedback, backItem.braille); } - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'RichTextSelectByLine', async function() { @@ -760,9 +760,9 @@ // Shrinking. .call(move) .expectSpeech('ne', '22222 li', 'unselected') - .expectBraille('22222 line\n', {startIndex: 8, endIndex: 11}) + .expectBraille('22222 line\n', {startIndex: 8, endIndex: 11}); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -868,9 +868,9 @@ .call(move) .expectSpeech('ine', 'Link') .expectSpeech('33333 li', 'List item', 'selected') - .expectBraille('11111 line h1', {startIndex: 7, endIndex: 10}) + .expectBraille('11111 line h1', {startIndex: 7, endIndex: 10}); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -1232,8 +1232,8 @@ // Deletion. .call(enterKey) - .expectSpeech('1') - .replay(); + .expectSpeech('1'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'BackwardWordDelete', async function() { @@ -1260,8 +1260,8 @@ .expectSpeech('is , deleted') .expectBraille('this\u00a0mled', {startIndex: 5, endIndex: 5}) .call(this.press(KeyCode.BACK, {ctrl: true})) - .expectBraille(' mled', {startIndex: 0, endIndex: 0}) - .replay(); + .expectBraille(' mled', {startIndex: 0, endIndex: 0}); + await mockFeedback.replay(); }); AX_TEST_F( @@ -1290,8 +1290,8 @@ .call(this.press(KeyCode.BACK, {ctrl: true})) .expectSpeech('line, deleted') .call(this.press(KeyCode.BACK, {ctrl: true})) - .expectSpeech('first , deleted') - .replay(); + .expectSpeech('first , deleted'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'GrammarErrors', async function() { @@ -1330,9 +1330,9 @@ .call(moveByChar) .expectSpeech('e') .call(moveByChar) - .expectSpeech(' ', 'Leaving grammar error') + .expectSpeech(' ', 'Leaving grammar error'); - .replay(); + await mockFeedback.replay(); }); // Flaky test, crbug.com/1098642. @@ -1353,8 +1353,8 @@ .call(this.press(KeyCode.RETURN)) .expectSpeech('\n') .call(this.press(KeyCode.A)) - .expectSpeech('a') - .replay(); + .expectSpeech('a'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'SelectAll', async function() { @@ -1379,8 +1379,8 @@ .call(this.press(KeyCode.HOME, {ctrl: true})) .expectSpeech('first line') .call(this.press(KeyCode.A, {ctrl: true})) - .expectSpeech('first line', 'second line', 'third line', 'selected') - .replay(); + .expectSpeech('first line', 'second line', 'third line', 'selected'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'TextAreaBrailleEmptyLine', async function() { @@ -1393,9 +1393,8 @@ mockFeedback.call(this.press(KeyCode.UP)).expectBraille('two\n'); mockFeedback.call(this.press(KeyCode.UP)).expectBraille('one\n'); mockFeedback.call(this.press(KeyCode.UP)).expectBraille('\n'); - mockFeedback.call(this.press(KeyCode.UP)) - .expectBraille('test\nmled') - .replay(); + mockFeedback.call(this.press(KeyCode.UP)).expectBraille('test\nmled'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'MoveByCharacterIntent', async function() { @@ -1419,8 +1418,8 @@ .call(this.press(KeyCode.LEFT)) .expectSpeech('\n') .call(this.press(KeyCode.LEFT)) - .expectSpeech('3') - .replay(); + .expectSpeech('3'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'MoveByLineIntent', async function() { @@ -1441,8 +1440,8 @@ .call(this.press(KeyCode.UP)) .expectSpeech('456') .call(this.press(KeyCode.UP)) - .expectSpeech('123') - .replay(); + .expectSpeech('123'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'SelectAllBareTextContent', async function() { @@ -1455,8 +1454,8 @@ mockFeedback.call(this.press(KeyCode.END, {ctrl: true})) .expectSpeech('unread') .call(this.press(KeyCode.A, {ctrl: true})) - .expectSpeech('unread', 'selected') - .replay(); + .expectSpeech('unread', 'selected'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'InputEvents', async function() { @@ -1577,8 +1576,8 @@ .call(this.press(KeyCode.DOWN)) .expectSpeech('This is ') .expectSpeech( - 'Suggest', 'Delete', `everyone's`, 'Delete end', 'Suggest end') - .replay(); + 'Suggest', 'Delete', `everyone's`, 'Delete end', 'Suggest end'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'NestedInsertionDeletion', async function() { @@ -1601,8 +1600,8 @@ 'I ', 'Suggest', 'Username', 'Insert', 'was', 'Insert end', 'Delete', 'am', 'Delete end', 'Suggest end', ' typing') .call(this.press(KeyCode.DOWN)) - .expectSpeech('End') - .replay(); + .expectSpeech('End'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'MoveByCharSuggestions', async function() { @@ -1649,8 +1648,8 @@ .call(this.press(KeyCode.LEFT)) .expectSpeech('Suggest', 'Insert', 'w') .call(this.press(KeyCode.DOWN)) - .expectSpeech('End') - .replay(); + .expectSpeech('End'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'MoveByWordSuggestions', async function() { @@ -1685,8 +1684,8 @@ .call(this.press(KeyCode.LEFT, {ctrl: true})) .expectSpeech('I') .call(this.press(KeyCode.DOWN)) - .expectSpeech('End') - .replay(); + .expectSpeech('End'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -1746,8 +1745,8 @@ // right arrow key. .call(doCmd('nativeNextWord')) .call(this.press(KeyCode.RIGHT, {ctrl: true})) - .expectSpeech('Suggest', 'Username', 'Insert', 'was', 'Insert end') - .replay(); + .expectSpeech('Suggest', 'Username', 'Insert', 'was', 'Insert end'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'Separator', async function() { @@ -1785,9 +1784,9 @@ .call(this.press(KeyCode.LEFT)) // Notice this reads the entire line which is generally undesirable // except for special cases like this. - .expectSpeech('Hello') + .expectSpeech('Hello'); - .replay(); + await mockFeedback.replay(); }); // Test for the issue in crbug.com/1203840. This case was causing an infinite @@ -1820,8 +1819,8 @@ mockFeedback.call(this.press(KeyCode.DOWN)) .expectSpeech('This is a test') .call(this.press(KeyCode.DOWN)) - .expectSpeech('End') - .replay(); + .expectSpeech('End'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -1966,8 +1965,8 @@ .call(ctrlDown) .expectSpeech('Another paragraph, number two.') .call(this.press(KeyCode.DOWN)) - .expectSpeech('paragraph, ') - .replay(); + .expectSpeech('paragraph, '); + await mockFeedback.replay(); }); AX_TEST_F( @@ -1989,8 +1988,8 @@ .call(this.press(KeyCode.UP)) .expectNextSpeechUtteranceIsNot('Article') .expectNextSpeechUtteranceIsNot('Article end') - .expectSpeech('hello') - .replay(); + .expectSpeech('hello'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'TableNavigation', async function() { @@ -2019,8 +2018,8 @@ .expectSpeech('hello', 'world') .expectSpeech('row 1 column 1') .call(this.press(KeyCode.RIGHT)) - .expectSpeech('e') - .replay(); + .expectSpeech('e'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2128,8 +2127,8 @@ .call(doCmd('contextMenu')) .expectSpeech(' menu opened') .call(this.press(KeyCode.ESCAPE)) - .expectSpeech('ab', 'selected') - .replay(); + .expectSpeech('ab', 'selected'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'NativeCharWordCommands', async function() { @@ -2158,9 +2157,9 @@ .call(this.press(KeyCode.LEFT, {ctrl: true})) .expectSpeech('is') .call(this.press(KeyCode.LEFT, {ctrl: true})) - .expectSpeech('This') + .expectSpeech('This'); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxEditingTest', 'TablesWithEmptyCells', async function() { @@ -2212,9 +2211,9 @@ .call(doCmd('nativeNextCharacter')) .call(() => cell22.setSelection(0, 0)) - .expectSpeech('\u00a0', 'row 2 column 2') + .expectSpeech('\u00a0', 'row 2 column 2'); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2284,9 +2283,9 @@ .call(this.press(KeyCode.LEFT)) .expectSpeech('\n') .call(this.press(KeyCode.LEFT)) - .expectSpeech('e') + .expectSpeech('e'); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2320,9 +2319,9 @@ .call(doCmd('nextLink')) .expectSpeech('fourth', 'Internal link') .call(this.press(KeyCode.RIGHT, {shift: true, ctrl: true})) - .expectSpeech('fourth', 'Link', 'selected') + .expectSpeech('fourth', 'Link', 'selected'); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -2341,7 +2340,7 @@ .call(this.press(KeyCode.A)) .expectBraille('a mled', {startIndex: 1, endIndex: 1}) .call(this.press(KeyCode.BACK)) - .expectBraille(' mled', {startIndex: 0, endIndex: 0}) + .expectBraille(' mled', {startIndex: 0, endIndex: 0}); - .replay(); + await mockFeedback.replay(); });
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/live_regions_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/live_regions_test.js index ec35b29..8e82f2eb 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/live_regions_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/live_regions_test.js
@@ -47,7 +47,7 @@ const go = rootNode.find({role: RoleType.BUTTON}); mockFeedback.call(go.doDefault.bind(go)) .expectCategoryFlushSpeech('Hello, world'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -67,7 +67,7 @@ go.doDefault(); mockFeedback.expectCategoryFlushSpeech('removed:') .expectQueuedSpeech('Hello, world'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -89,7 +89,7 @@ const go = rootNode.find({role: RoleType.BUTTON}); mockFeedback.call(go.doDefault.bind(go)) .expectCategoryFlushSpeech('Alpha Bravo Charlie'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -108,7 +108,7 @@ const go = rootNode.find({role: RoleType.BUTTON}); mockFeedback.call(go.doDefault.bind(go)) .expectCategoryFlushSpeech('bar', 'Heading 1'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -134,7 +134,7 @@ const go = rootNode.find({role: RoleType.BUTTON}); mockFeedback.call(go.doDefault.bind(go)) .expectCategoryFlushSpeech('After'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxLiveRegionsTest', 'LiveRegionThenFocus', async function() { @@ -174,7 +174,7 @@ .call(go.doDefault.bind(go)) .expectSpeech(focusOrLive) .expectSpeech(focusOrLive); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxLiveRegionsTest', 'FocusThenLiveRegion', async function() { @@ -201,7 +201,7 @@ (candidate.queueMode === QueueMode.CATEGORY_FLUSH || candidate.queueMode === QueueMode.QUEUE); }); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -228,7 +228,7 @@ mockFeedback.call(go.doDefault.bind(go)) .expectCategoryFlushSpeech('Live1') .expectCategoryFlushSpeech('Live2'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxLiveRegionsTest', 'SilentOnNodeChange', async function() { @@ -255,7 +255,7 @@ .expectSpeech('hello!') .expectNextSpeechUtteranceIsNot('hello!') .expectNextSpeechUtteranceIsNot('hello!'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxLiveRegionsTest', 'SimulateTreeChanges', async function() { @@ -287,7 +287,7 @@ }) .expectSpeech('hello') .expectSpeech('there'); - mockFeedback.replay(); + await mockFeedback.replay(); }); // Flaky: https://crbug.com/945199 @@ -322,8 +322,8 @@ .clearPendingOutput() .call(clickInput) .expectNextSpeechUtteranceIsNot('bba') - .expectSpeech('a') - .replay(); + .expectSpeech('a'); + await mockFeedback.replay(); }); AX_TEST_F( @@ -346,8 +346,8 @@ `); const button = root.find({role: chrome.automation.RoleType.BUTTON}); mockFeedback.call(button.doDefault.bind(button)) - .expectSpeech('Alert', 'hi') - .replay(); + .expectSpeech('Alert', 'hi'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxLiveRegionsTest', 'ShouldIgnoreLiveRegion', function() { @@ -395,6 +395,6 @@ mockFeedback.call(button.doDefault.bind(button)) .expectSpeech('hello') .call(button.doDefault.bind(button)) - .expectSpeech('there') - .replay(); + .expectSpeech('there'); + await mockFeedback.replay(); });
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js index 479db39..91b2bee 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/loader.js
@@ -7,13 +7,10 @@ */ goog.require('AbstractEarcons'); -goog.require('AncestryRecoveryStrategy'); goog.require('AutomationPredicate'); goog.require('JaPhoneticData'); goog.require('PanelNodeMenuData'); goog.require('PanelTabMenuItemData'); -goog.require('RecoveryStrategy'); -goog.require('TreePathRecoveryStrategy'); goog.require('constants'); goog.require('goog.i18n.MessageFormat');
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/logging/log_store.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/logging/log_store.js index abc248d..34275ae 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/logging/log_store.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/logging/log_store.js
@@ -159,4 +159,4 @@ () => LogStore.instance.clearLog()); BridgeHelper.registerHandler( BridgeConstants.LogStore.TARGET, BridgeConstants.LogStore.Action.GET_LOGS, - () => LogStore.instance.getLogs()); + () => LogStore.instance.getLogs().map(log => log.serialize()));
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/settings_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/settings_test.js index ee66b34..813c2698 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/settings_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/settings_test.js
@@ -86,7 +86,7 @@ .call(increaseRate) .expectSpeech('Rate 2 percent') .call(increaseRate) - .expectSpeech('Rate 4 percent') + .expectSpeech('Rate 4 percent'); - .replay(); + await mockFeedback.replay(); });
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/smart_sticky_mode_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/smart_sticky_mode_test.js index 4659ceb0..54704be7 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/smart_sticky_mode_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/smart_sticky_mode_test.js
@@ -152,8 +152,8 @@ .call(doCmd('previousObject')) .expectSpeech('Sticky mode disabled') .expectSpeech('Edit text') - .call(() => assertFalse(ChromeVox.isStickyModeOn())) - .replay(); + .call(() => assertFalse(ChromeVox.isStickyModeOn())); + await mockFeedback.replay(); }); AX_TEST_F( @@ -175,8 +175,8 @@ .expectEarcon(Earcon.SMART_STICKY_MODE_ON) .expectSpeech('Sticky mode enabled') .expectSpeech('Button') - .call(() => assertTrue(ChromeVox.isStickyModeOn())) - .replay(); + .call(() => assertTrue(ChromeVox.isStickyModeOn())); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxSmartStickyModeTest', 'ContinuousRead', async function() { @@ -198,6 +198,6 @@ .call(doCmd('nextObject')) .expectNextSpeechUtteranceIsNot('Sticky mode enabled') .expectSpeech('Button') - .call(() => assertTrue(ChromeVox.isStickyModeOn())) - .replay(); + .call(() => assertTrue(ChromeVox.isStickyModeOn())); + await mockFeedback.replay(); });
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/user_action_monitor_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/user_action_monitor_test.js index a8f3d64..f4e3c143 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/user_action_monitor_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/user_action_monitor_test.js
@@ -225,7 +225,7 @@ assertTrue(finished); }) .expectSpeech('You did it!'); - mockFeedback.replay(); + await mockFeedback.replay(); }); // Tests that we can match a single key. Serves as an integration test @@ -328,7 +328,7 @@ assertTrue(finished); }) .expectSpeech('You pressed the second sequence!'); - mockFeedback.replay(); + await mockFeedback.replay(); }); // Tests that we can provide expectations for ChromeVox commands and block @@ -390,8 +390,8 @@ keyboardHandler.onKeyUp(previousObject); assertEquals('Start', this.getRangeStart().name); }) - .expectSpeech('Start') - .replay(); + .expectSpeech('Start'); + await mockFeedback.replay(); }); // Tests that a user can close ChromeVox (Ctrl + Alt + Z) when UserActionMonitor @@ -488,6 +488,6 @@ doGesture(Gesture.SWIPE_RIGHT1)(); assertTrue(finished); }) - .expectSpeech(/Battery at [0-9]+ percent/) - .replay(); + .expectSpeech(/Battery at [0-9]+ percent/); + await mockFeedback.replay(); });
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js index 319ca14e..f43a5f6 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/background_bridge.js
@@ -9,7 +9,7 @@ import {BridgeConstants} from './bridge_constants.js'; import {BridgeHelper} from './bridge_helper.js'; -import {BaseLog} from './log_types.js'; +import {SerializableLog} from './log_types.js'; export const BackgroundBridge = {}; @@ -188,7 +188,7 @@ /** * Create logs in order. * This function is not currently optimized for speed. - * @return {!Promise<!Array<BaseLog>>} + * @return {!Promise<!Array<!SerializableLog>>} */ async getLogs() { return BridgeHelper.sendMessage(
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/locale_output_helper_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/locale_output_helper_test.js index 9924d7a3..17d403b 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/locale_output_helper_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/locale_output_helper_test.js
@@ -203,7 +203,7 @@ .expectSpeechWithLocale('fr', 'français: Salut.'); mockFeedback.call(doCmd('nextLine')) .expectSpeechWithLocale('it', 'italiano: Ciao amico.'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -230,7 +230,7 @@ .expectSpeechWithLocale('es', 'español: Hola.'); mockFeedback.call(doCmd('nextLine')) .expectSpeechWithLocale('en', 'English: Goodbye.'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -252,7 +252,7 @@ .call(doCmd('nextObject')) .expectSpeechWithLocale('es', 'Este es un enlace.') .expectSpeechWithLocale(undefined, 'Link'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -275,7 +275,7 @@ 'en-us', 'Hello, my name is 太田あきひろ. It\'s a pleasure to meet' + ' you. どうぞよろしくお願いします.'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -291,7 +291,7 @@ 'en-us', 'This text is written in English. 차에 한하여 중임할 수.' + ' This text is also written in English.'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -309,7 +309,7 @@ ' the following French passage: ' + 'salut mon ami! Ca va? Bien, et toi? It\'s hard to' + ' differentiate between latin-based languages.'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -322,7 +322,7 @@ this.setAvailableVoices(); mockFeedback.call(doCmd('jumpToTop')) .expectSpeechWithLocale('en-us', 'ど'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -337,7 +337,7 @@ .expectSpeechWithLocale( 'en-us', '天気はいいですね. 右万諭全中結社原済権人点掲年難出面者会追'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -358,7 +358,7 @@ .expectSpeechWithLocale( 'zh', '中文: 天気はいいですね. 右万諭全中結社原済権人点掲年難出面者会追'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -375,7 +375,7 @@ 'ko', '한국어: 私は. 법률이 정하는 바에 의하여 대법관이 아닌 법관을 둘 수' + ' 있다'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -392,7 +392,7 @@ 'ast', 'asturianu: Pretend that this text is Asturian. Testing' + ' three-letter language code logic.'); - mockFeedback.replay(); + await mockFeedback.replay(); }); @@ -413,7 +413,7 @@ .expectSpeechWithLocale(undefined, 'Salut.') .call(doCmd('nextObject')) .expectSpeechWithLocale(undefined, 'Ciao amico.'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -430,7 +430,7 @@ .expectSpeechWithLocale('en-us', 'English (United States): Test') .call(doCmd('nextObject')) .expectSpeechWithLocale('en-us', 'Yikes'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -447,7 +447,7 @@ .call(doCmd('nextObject')) .expectSpeechWithLocale( 'en-us', 'No voice available for language: Urdu'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -497,8 +497,8 @@ .call(doCmd('previousWord')) .expectSpeechWithLocale('en', `English: .`) .call(doCmd('previousWord')) - .expectSpeechWithLocale('en', `you`) - .replay(); + .expectSpeechWithLocale('en', `you`); + await mockFeedback.replay(); }); AX_TEST_F( @@ -542,8 +542,8 @@ .call(doCmd('previousCharacter')) .expectSpeechWithLocale('fr', `e`) .call(doCmd('previousCharacter')) - .expectSpeechWithLocale('fr', `j`) - .replay(); + .expectSpeechWithLocale('fr', `j`); + await mockFeedback.replay(); }); AX_TEST_F( @@ -560,7 +560,7 @@ .call(doCmd('nextLine')) .expectSpeechWithLocale( 'zh-hant', '中文(繁體): Traditional Chinese'); - mockFeedback.replay(); + await mockFeedback.replay(); }); AX_TEST_F( @@ -576,7 +576,7 @@ .expectSpeechWithLocale('pt-br', 'português (Brasil): Brazil') .call(doCmd('nextLine')) .expectSpeechWithLocale('pt-pt', 'português (Portugal): Portugal'); - mockFeedback.replay(); + await mockFeedback.replay(); }); // Tests logic in shouldAnnounceLocale_(). We only announce the locale once when @@ -602,6 +602,6 @@ .call(doCmd('nextObject')) .expectSpeechWithLocale('en', 'Penultimate') .call(doCmd('nextObject')) - .expectSpeechWithLocale('en-ca', 'End') - .replay(); + .expectSpeechWithLocale('en-ca', 'End'); + await mockFeedback.replay(); });
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/log_types.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/log_types.js index 1ed02fb..182327c8 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/log_types.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/log_types.js
@@ -25,6 +25,15 @@ TREE: 'tree', }; +/** + * @typedef {{ + * logType: !LogType, + * date: !Date, + * value: string + * }} + */ +export let SerializableLog; + export class BaseLog { constructor(logType) { /** @@ -38,6 +47,12 @@ this.date = new Date(); } + /** @return {!SerializableLog} */ + serialize() { + return /** @type {!SerializableLog} */ ( + {logType: this.logType, date: this.date, value: this.toString()}); + } + /** @return {string} */ toString() { return '';
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/learn_mode_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/learn_mode_test.js index 917d1b4e..ff1f051 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/learn_mode_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/learn_mode/learn_mode_test.js
@@ -119,9 +119,9 @@ .call(doKeyDown({keyCode: KeyCode.RIGHT, metaKey: true})) .expectSpeechWithQueueMode('Right arrow', QueueMode.CATEGORY_FLUSH) .expectSpeechWithQueueMode('Next Object', QueueMode.QUEUE) - .call(doKeyUp({keyCode: KeyCode.RIGHT, metaKey: true})) + .call(doKeyUp({keyCode: KeyCode.RIGHT, metaKey: true})); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxLearnModeTest', 'KeyboardInputRepeat', async function() { @@ -139,9 +139,9 @@ .call(doKeyDown({keyCode: KeyCode.SEARCH, metaKey: true, repeat: true})) .call(doKeyDown({keyCode: KeyCode.CONTROL, ctrlKey: true})) .expectNextSpeechUtteranceIsNot('Search') - .expectSpeechWithQueueMode('Control', QueueMode.QUEUE) + .expectSpeechWithQueueMode('Control', QueueMode.QUEUE); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxLearnModeTest', 'Gesture', async function() { @@ -165,9 +165,9 @@ .call(doLearnModeGesture(Gesture.SWIPE_LEFT2)) .expectSpeechWithQueueMode( 'Swipe two fingers left', QueueMode.CATEGORY_FLUSH) - .expectSpeechWithQueueMode('Escape', QueueMode.QUEUE) + .expectSpeechWithQueueMode('Escape', QueueMode.QUEUE); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxLearnModeTest', 'Braille', async function() { @@ -187,9 +187,9 @@ .call(doBrailleKeyEvent( {command: BrailleKeyCommand.CHORD, brailleDots: 0b011001})) .expectSpeechWithQueueMode('dots 1-4-5 chord', QueueMode.CATEGORY_FLUSH) - .expectBraille('dots 1-4-5 chord') + .expectBraille('dots 1-4-5 chord'); - .replay(); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxLearnModeTest', 'HardwareFunctionKeys', async function() { @@ -213,7 +213,7 @@ // Search+Volume Mute does though. .call(doKeyDown({keyCode: KeyCode.VOLUME_MUTE, metaKey: true})) .expectSpeechWithQueueMode('volume mute', QueueMode.CATEGORY_FLUSH) - .expectSpeechWithQueueMode('Toggle speech on or off', QueueMode.QUEUE) + .expectSpeechWithQueueMode('Toggle speech on or off', QueueMode.QUEUE); - .replay(); + await mockFeedback.replay(); });
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/log_page/log.js b/chrome/browser/resources/chromeos/accessibility/chromevox/log_page/log.js index 4b6ec3e..c013e7b 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/log_page/log.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/log_page/log.js
@@ -4,11 +4,10 @@ /** * @fileoverview ChromeVox log page. - * */ import {BackgroundBridge} from '../common/background_bridge.js'; -import {BaseLog, LogType} from '../common/log_types.js'; +import {BaseLog, LogType, SerializableLog} from '../common/log_types.js'; /** * Class to manage the log page. @@ -107,7 +106,7 @@ /** * Updates the log section. - * @param {Array<BaseLog>} log Array of speech. + * @param {Array<!SerializableLog>} log Array of logs to record. * @param {Element} div */ static updateLog(log, div) { @@ -125,7 +124,7 @@ timeStamp.className = 'log-time-tag'; /** textWrapper should be in block scope, not function scope. */ const textWrapper = document.createElement('pre'); - textWrapper.textContent = log[i].toString(); + textWrapper.textContent = log[i].value; textWrapper.className = 'log-text'; p.appendChild(typeName);
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/options/options_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/options/options_test.js index f54fc37..2518a7d 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/options/options_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/options/options_test.js
@@ -79,9 +79,9 @@ .expectSpeech('Digits', 'Collapsed') .call(() => { assertEquals('asDigits', localStorage['numberReadingStyle']); - }) + }); - .replay(); + await mockFeedback.replay(); }); // TODO(crbug.com/1128926, crbug.com/1172387): @@ -125,9 +125,9 @@ assertEquals( PUNCTUATION_ECHO_ALL, localStorage[AbstractTts.PUNCTUATION_ECHO]); - }) + }); - .replay(); + await mockFeedback.replay(); }); // TODO(crbug.com/1128926, crbug.com/1172387): @@ -153,9 +153,9 @@ 'Check box', 'Not checked') .call(() => { assertEquals('false', localStorage['smartStickyMode']); - }) + }); - .replay(); + await mockFeedback.replay(); }); // TODO(crbug.com/1169396, crbug.com/1172387): @@ -230,5 +230,5 @@ }) .call(capitalStrategySelect.focus.bind(capitalStrategySelect)) .expectSpeech('When reading capitals:', 'Increase pitch', 'Collapsed'); - mockFeedback.replay(); + await mockFeedback.replay(); });
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js index 571b280..762459d 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js
@@ -1271,7 +1271,8 @@ const bkgnd = chrome.extension.getBackgroundPage(); // Save the sticky state when a user first focuses the panel. - if (location.hash === '#fullscreen' || location.hash === '#focus') { + if (bkgnd['ChromeVox'] && + (location.hash === '#fullscreen' || location.hash === '#focus')) { Panel.originalStickyState_ = bkgnd['ChromeVox']['isStickyPrefOn']; }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_loader.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_loader.js index 7e4823382..217d17f 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_loader.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_loader.js
@@ -6,12 +6,10 @@ * @fileoverview Loads the panel script. */ -goog.require('AncestryRecoveryStrategy'); goog.require('AutomationPredicate'); goog.require('EarconDescription'); goog.require('PanelNodeMenuData'); goog.require('PanelNodeMenuItemData'); -goog.require('RecoveryStrategy'); goog.require('constants'); goog.require('goog.i18n.MessageFormat');
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/tutorial_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/tutorial_test.js index 8835fe2..e029b105 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/tutorial_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/tutorial_test.js
@@ -112,8 +112,8 @@ .call(doCmd('nextObject')) .expectSpeech('Resources', 'Link') .call(doCmd('nextObject')) - .expectSpeech('Exit tutorial', 'Button') - .replay(); + .expectSpeech('Exit tutorial', 'Button'); + await mockFeedback.replay(); }); // Tests that different lessons are shown when choosing an experience from the @@ -148,8 +148,8 @@ .call(doCmd('forceClickOnCurrentItem')) .expectSpeech(/Essential Keys Tutorial, [0-9]+ Lessons/) .call(doCmd('nextObject')) - .expectSpeech('On, Off, and Stop') - .replay(); + .expectSpeech('On, Off, and Stop'); + await mockFeedback.replay(); }); // Tests that a static lesson does not show the 'Practice area' button. @@ -176,8 +176,8 @@ ' Press Search + Right Arrow, or Search + Left Arrow to navigate ' + 'this lesson ') .call(doCmd('nextButton')) - .expectSpeech('Next lesson') - .replay(); + .expectSpeech('Next lesson'); + await mockFeedback.replay(); }); // Tests that an interactive lesson shows the 'Practice area' button. @@ -203,8 +203,8 @@ }) .expectSpeech('Jump Commands', 'Heading 1') .call(doCmd('nextButton')) - .expectSpeech('Practice area') - .replay(); + .expectSpeech('Practice area'); + await mockFeedback.replay(); }); // Tests nudges given in the general tutorial context. @@ -231,8 +231,8 @@ .expectSpeech('Hint: Press Search + Space to activate the current item.') .call(giveNudge) .expectSpeech( - 'Hint: Press Escape if you would like to exit this tutorial.') - .replay(); + 'Hint: Press Escape if you would like to exit this tutorial.'); + await mockFeedback.replay(); }); // Tests nudges given in the practice area context. Note, each practice area @@ -270,8 +270,8 @@ 'Try pressing Search + left/right arrow. The search key is ' + 'directly above the shift key') .call(giveNudge) - .expectSpeech('Press Search + Space to activate the current item.') - .replay(); + .expectSpeech('Press Search + Space to activate the current item.'); + await mockFeedback.replay(); }); // Tests that the tutorial closes when the 'Exit tutorial' button is clicked. @@ -285,8 +285,8 @@ .call(doCmd('previousButton')) .expectSpeech('Exit tutorial') .call(doCmd('forceClickOnCurrentItem')) - .expectSpeech('Some web content') - .replay(); + .expectSpeech('Some web content'); + await mockFeedback.replay(); }); // Tests that the tutorial closes when Escape is pressed. @@ -305,8 +305,8 @@ stopPropagation: () => {}, }); }) - .expectSpeech('Some web content') - .replay(); + .expectSpeech('Some web content'); + await mockFeedback.replay(); }); // Tests that the main menu button navigates the user to the main menu screen. @@ -332,8 +332,8 @@ .expectSpeech('Main menu') .call(doCmd('forceClickOnCurrentItem')) .expectSpeech('ChromeVox tutorial') - .call(this.assertActiveScreen.bind(this, 'main_menu')) - .replay(); + .call(this.assertActiveScreen.bind(this, 'main_menu')); + await mockFeedback.replay(); }); // Tests that the all lessons button navigates the user to the lesson menu @@ -366,8 +366,8 @@ .expectSpeech('All lessons') .call(doCmd('forceClickOnCurrentItem')) .expectSpeech(/Essential Keys Tutorial, [0-9]+ Lessons/) - .call(this.assertActiveScreen.bind(this, 'lesson_menu')) - .replay(); + .call(this.assertActiveScreen.bind(this, 'lesson_menu')); + await mockFeedback.replay(); }); // Tests that the next and previous lesson buttons navigate properly. @@ -396,8 +396,8 @@ .expectSpeech('Previous lesson') .call(doCmd('forceClickOnCurrentItem')) .expectSpeech('On, Off, and Stop', 'Heading 1') - .call(this.assertActiveLessonIndex.bind(this, 0)) - .replay(); + .call(this.assertActiveLessonIndex.bind(this, 0)); + await mockFeedback.replay(); }); // Tests that the title of an interactive lesson is read when shown. @@ -420,8 +420,8 @@ 'time, press the Escape key on the top left corner of the ' + 'keyboard. To turn off ChromeVox, hold Control and Alt, and ' + `press Z. When you're ready, use the spacebar to move to the ` + - 'next lesson.') - .replay(); + 'next lesson.'); + await mockFeedback.replay(); }); // Tests that we read a hint for navigating a lesson when it is shown. @@ -445,8 +445,8 @@ .expectSpeech('On, Off, and Stop', 'Heading 1') .expectSpeech( ' Press Search + Right Arrow, or Search + Left Arrow to navigate' + - ' this lesson ') - .replay(); + ' this lesson '); + await mockFeedback.replay(); }); // Tests for correct speech and earcons on the earcons lesson. @@ -475,7 +475,7 @@ nextObjectAndExpectSpeechAndEarcon( 'A non modal alert', Earcon.ALERT_NONMODAL); nextObjectAndExpectSpeechAndEarcon('A button', Earcon.BUTTON); - mockFeedback.replay(); + await mockFeedback.replay(); }); // Tests that a lesson from the quick orientation blocks ChromeVox execution @@ -546,8 +546,8 @@ .expectSpeech('Essential Keys: Shift') .call(() => { assertEquals(2, tutorial.activeLessonId); - }) - .replay(); + }); + await mockFeedback.replay(); }); // Tests that tutorial nudges are restarted whenever the current range changes. @@ -591,8 +591,8 @@ .call(doCmd('nextObject')) .expectSpeech('ChromeVox Command Reference', 'Link') .call(doCmd('forceClickOnCurrentItem')) - .expectSpeech('support.google.com') - .replay(); + .expectSpeech('support.google.com'); + await mockFeedback.replay(); }); // Tests that choosing a curriculum with only 1 lesson automatically opens the @@ -625,8 +625,8 @@ .call(doCmd('nextButton')) .expectSpeech('Main menu') .call(doCmd('nextButton')) - .expectSpeech('Exit tutorial') - .replay(); + .expectSpeech('Exit tutorial'); + await mockFeedback.replay(); }); // Tests that interactive mode and UserActionMonitor are properly set when @@ -699,8 +699,8 @@ .call(doGesture(Gesture.SWIPE_LEFT1)) .expectSpeech('Quick orientation', 'Link') .call(doGesture(Gesture.SWIPE_LEFT2)) - .expectSpeech('Some web content') - .replay(); + .expectSpeech('Some web content'); + await mockFeedback.replay(); }); // Tests that touch orientation loads properly. Tests string content, but does @@ -737,8 +737,8 @@ .call(doGesture(Gesture.SWIPE_RIGHT4)) .expectSpeech(/swiping with four fingers from right to left/) .call(doGesture(Gesture.SWIPE_LEFT4)) - .expectSpeech('Touch tutorial complete') - .replay(); + .expectSpeech('Touch tutorial complete'); + await mockFeedback.replay(); }); AX_TEST_F('ChromeVoxTutorialTest', 'GeneralTouchNudges', async function() { @@ -767,6 +767,6 @@ .call(giveNudge) .expectSpeech( 'Hint: Swipe from right to left with two fingers if you would ' + - 'like to exit this tutorial.') - .replay(); + 'like to exit this tutorial.'); + await mockFeedback.replay(); });
diff --git a/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js b/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js index ad5fb51..1e60fcdf 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js +++ b/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js
@@ -14,6 +14,7 @@ import {StringUtil} from '../string_util.js'; import {AutomationUtil} from '../automation_util.js'; +import {RecoveryStrategy, AncestryRecoveryStrategy} from './recovery_strategy.js'; /** * The special index that represents a cursor pointing to a node without
diff --git a/chrome/browser/resources/chromeos/accessibility/common/cursors/recovery_strategy.js b/chrome/browser/resources/chromeos/accessibility/common/cursors/recovery_strategy.js index 380fb1a..886c072d 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/cursors/recovery_strategy.js +++ b/chrome/browser/resources/chromeos/accessibility/common/cursors/recovery_strategy.js
@@ -6,15 +6,10 @@ * @fileoverview Defines various strategies for recovering automation nodes. */ -goog.provide('AncestryRecoveryStrategy'); -goog.provide('RecoveryStrategy'); -goog.provide('TreePathRecoveryStrategy'); - -goog.scope(function() { const AutomationNode = chrome.automation.AutomationNode; const RoleType = chrome.automation.RoleType; -RecoveryStrategy = class { +export class RecoveryStrategy { /** * @param {!AutomationNode} node */ @@ -48,13 +43,13 @@ equalsWithoutRecovery(rhs) { return this.node_ === rhs.node_; } -}; +} /** * A recovery strategy that uses the node's ancestors. */ -AncestryRecoveryStrategy = class extends RecoveryStrategy { +export class AncestryRecoveryStrategy extends RecoveryStrategy { constructor(node) { super(node); @@ -89,13 +84,13 @@ } return 0; } -}; +} /** * A recovery strategy that uses the node's tree path. */ -TreePathRecoveryStrategy = class extends AncestryRecoveryStrategy { +export class TreePathRecoveryStrategy extends AncestryRecoveryStrategy { constructor(node) { super(node); @@ -130,5 +125,4 @@ } return node; } -}; -}); // goog.scope +}
diff --git a/chrome/browser/resources/chromeos/accessibility/common/cursors/recovery_strategy_test.js b/chrome/browser/resources/chromeos/accessibility/common/cursors/recovery_strategy_test.js index 6c74d98..723c6320 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/cursors/recovery_strategy_test.js +++ b/chrome/browser/resources/chromeos/accessibility/common/cursors/recovery_strategy_test.js
@@ -15,6 +15,18 @@ constructor() { super(); } + + /** @override */ + async setUpDeferred() { + await super.setUpDeferred(); + await importModule( + [ + 'RecoveryStrategy', + 'AncestryRecoveryStrategy', + 'TreePathRecoveryStrategy', + ], + '/common/cursors/recovery_strategy.js'); + } };
diff --git a/chrome/browser/resources/chromeos/crostini_installer/app.js b/chrome/browser/resources/chromeos/crostini_installer/app.js index 932f1d7..b4e4c8a 100644 --- a/chrome/browser/resources/chromeos/crostini_installer/app.js +++ b/chrome/browser/resources/chromeos/crostini_installer/app.js
@@ -4,7 +4,7 @@ import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; import 'chrome://resources/cr_elements/cr_slider/cr_slider.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; import 'chrome://resources/cr_elements/icons.m.js'; import 'chrome://resources/cr_elements/shared_vars_css.m.js';
diff --git a/chrome/browser/resources/chromeos/emulator/audio_settings.js b/chrome/browser/resources/chromeos/emulator/audio_settings.js index 58ec2f7..8fe8225 100644 --- a/chrome/browser/resources/chromeos/emulator/audio_settings.js +++ b/chrome/browser/resources/chromeos/emulator/audio_settings.js
@@ -8,7 +8,7 @@ import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/shared_style_css.m.js'; import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; import './icons.js';
diff --git a/chrome/browser/resources/chromeos/emulator/battery_settings.js b/chrome/browser/resources/chromeos/emulator/battery_settings.js index f2c37f0..734c508 100644 --- a/chrome/browser/resources/chromeos/emulator/battery_settings.js +++ b/chrome/browser/resources/chromeos/emulator/battery_settings.js
@@ -7,7 +7,7 @@ import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/shared_vars_css.m.js'; import 'chrome://resources/cr_elements/md_select_css.m.js'; import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
diff --git a/chrome/browser/resources/chromeos/emulator/bluetooth_settings.js b/chrome/browser/resources/chromeos/emulator/bluetooth_settings.js index cdaf2b5..7a60df1 100644 --- a/chrome/browser/resources/chromeos/emulator/bluetooth_settings.js +++ b/chrome/browser/resources/chromeos/emulator/bluetooth_settings.js
@@ -8,7 +8,7 @@ import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/shared_style_css.m.js'; import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; import './icons.js';
diff --git a/chrome/browser/resources/chromeos/login/oobe_auto_imports.gni b/chrome/browser/resources/chromeos/login/oobe_auto_imports.gni index d348bc38..2ecd44dc 100644 --- a/chrome/browser/resources/chromeos/login/oobe_auto_imports.gni +++ b/chrome/browser/resources/chromeos/login/oobe_auto_imports.gni
@@ -98,4 +98,5 @@ "ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.html", "ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html", "ui/webui/resources/cr_elements/cr_lazy_render/cr_lazy_render.html", + "ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.html", ]
diff --git a/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn b/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn index 7064d52..13891f5b 100644 --- a/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn
@@ -874,6 +874,7 @@ html_file = "user_creation.html" html_type = "dom-module" auto_imports = oobe_auto_imports + migrated_imports = oobe_migrated_imports namespace_rewrites = oobe_namespace_rewrites }
diff --git a/chrome/browser/resources/chromeos/network_ui/network_logs_ui.js b/chrome/browser/resources/chromeos/network_ui/network_logs_ui.js index 10d74855..c9bc44a 100644 --- a/chrome/browser/resources/chromeos/network_ui/network_logs_ui.js +++ b/chrome/browser/resources/chromeos/network_ui/network_logs_ui.js
@@ -5,7 +5,7 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/shared_style_css.m.js'; import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/chrome/browser/resources/chromeos/notification_tester/notification_tester.js b/chrome/browser/resources/chromeos/notification_tester/notification_tester.js index 790fbbc..6878faf 100644 --- a/chrome/browser/resources/chromeos/notification_tester/notification_tester.js +++ b/chrome/browser/resources/chromeos/notification_tester/notification_tester.js
@@ -4,7 +4,7 @@ import './select_custom.js'; import 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js'; import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd index 9f73a001..e9f817d 100644 --- a/chrome/browser/resources/component_extension_resources.grd +++ b/chrome/browser/resources/component_extension_resources.grd
@@ -69,6 +69,10 @@ <include name="IDS_ARC_INPUT_OVERLAY_ONBOARDING_ILLUSTRATION" file="chromeos/arc_input_overlay/onboarding_illustration.png" type="BINDATA" /> <include name="IDS_ARC_INPUT_OVERLAY_ONBOARDING_ILLUSTRATION_DARK" file="chromeos/arc_input_overlay/onboarding_illustration_dark.png" type="BINDATA" /> </if> + <include name="IDS_READ_ANYTHING_DEFAULT_PNG" file="side_panel/images/read_anything_default.png" type="BINDATA" /> + <include name="IDS_READ_ANYTHING_LIGHT_PNG" file="side_panel/images/read_anything_light.png" type="BINDATA" /> + <include name="IDS_READ_ANYTHING_DARK_PNG" file="side_panel/images/read_anything_dark.png" type="BINDATA" /> + <include name="IDS_READ_ANYTHING_YELLOW_PNG" file="side_panel/images/read_anything_yellow.png" type="BINDATA" /> <include name="IDR_CRYPTOTOKEN_UTIL_JS" file="cryptotoken/util.js" type="BINDATA" /> <include name="IDR_CRYPTOTOKEN_B64_JS" file="cryptotoken/b64.js" type="BINDATA" /> <include name="IDR_CRYPTOTOKEN_COUNTDOWN_JS" file="cryptotoken/countdown.js" type="BINDATA" />
diff --git a/chrome/browser/resources/extensions/runtime_host_permissions.ts b/chrome/browser/resources/extensions/runtime_host_permissions.ts index 1b7813f..0a2348b2c 100644 --- a/chrome/browser/resources/extensions/runtime_host_permissions.ts +++ b/chrome/browser/resources/extensions/runtime_host_permissions.ts
@@ -6,7 +6,7 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; import 'chrome://resources/cr_elements/icons.m.js'; import 'chrome://resources/cr_elements/shared_style_css.m.js';
diff --git a/chrome/browser/resources/extensions/site_permissions_edit_permissions_dialog.ts b/chrome/browser/resources/extensions/site_permissions_edit_permissions_dialog.ts index 77e261b1..3f69da0 100644 --- a/chrome/browser/resources/extensions/site_permissions_edit_permissions_dialog.ts +++ b/chrome/browser/resources/extensions/site_permissions_edit_permissions_dialog.ts
@@ -5,7 +5,7 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/shared_style_css.m.js'; import './strings.m.js';
diff --git a/chrome/browser/resources/media_router/cast_feedback/cast_feedback_ui.ts b/chrome/browser/resources/media_router/cast_feedback/cast_feedback_ui.ts index bc13a27e..cba1eec 100644 --- a/chrome/browser/resources/media_router/cast_feedback/cast_feedback_ui.ts +++ b/chrome/browser/resources/media_router/cast_feedback/cast_feedback_ui.ts
@@ -8,7 +8,7 @@ import '//resources/cr_elements/cr_dialog/cr_dialog.m.js'; import '//resources/cr_elements/cr_input/cr_input.m.js'; import '//resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import '//resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import '//resources/cr_elements/cr_radio_group/cr_radio_group.js'; import '//resources/cr_elements/shared_style_css.m.js'; import '//resources/cr_elements/shared_vars_css.m.js';
diff --git a/chrome/browser/resources/nearby_share/shared/BUILD.gn b/chrome/browser/resources/nearby_share/shared/BUILD.gn index 495922d..9f9ee47 100644 --- a/chrome/browser/resources/nearby_share/shared/BUILD.gn +++ b/chrome/browser/resources/nearby_share/shared/BUILD.gn
@@ -124,7 +124,7 @@ ":nearby_share_settings_behavior", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/cr_elements/cr_radio_button:cr_card_radio_button.m", - "//ui/webui/resources/cr_elements/cr_radio_group:cr_radio_group.m", + "//ui/webui/resources/cr_elements/cr_radio_group:cr_radio_group", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:cr.m", "//ui/webui/resources/js:i18n_behavior.m",
diff --git a/chrome/browser/resources/nearby_share/shared/nearby_contact_visibility.js b/chrome/browser/resources/nearby_share/shared/nearby_contact_visibility.js index 17e331e..d144415d 100644 --- a/chrome/browser/resources/nearby_share/shared/nearby_contact_visibility.js +++ b/chrome/browser/resources/nearby_share/shared/nearby_contact_visibility.js
@@ -9,7 +9,7 @@ */ import 'chrome://resources/cr_elements/shared_style_css.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_card_radio_button.m.js'; import 'chrome://resources/cr_elements/cr_icons_css.m.js'; import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.m.js';
diff --git a/chrome/browser/resources/new_tab_page/customize_modules.ts b/chrome/browser/resources/new_tab_page/customize_modules.ts index 1d48086..01bf87c 100644 --- a/chrome/browser/resources/new_tab_page/customize_modules.ts +++ b/chrome/browser/resources/new_tab_page/customize_modules.ts
@@ -5,7 +5,7 @@ import 'chrome://resources/cr_elements/cr_icons_css.m.js'; import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.m.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; import 'chrome://resources/cr_elements/policy/cr_policy_indicator.m.js';
diff --git a/chrome/browser/resources/safe_browsing/OWNERS b/chrome/browser/resources/safe_browsing/OWNERS index 70e4b68..5225674 100644 --- a/chrome/browser/resources/safe_browsing/OWNERS +++ b/chrome/browser/resources/safe_browsing/OWNERS
@@ -1,3 +1 @@ -drubery@chromium.org -nparker@chromium.org -vakh@chromium.org +file://components/safe_browsing/OWNERS
diff --git a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html index 94db42b..b415aafa 100644 --- a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html +++ b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html
@@ -4,11 +4,19 @@ display: flex; flex: 1; } + .list-item { + margin-bottom: 8px; + margin-top: 8px; + } #creditCardExpiration { flex: 1; } + #summarySublabel { + color: var(--cr-secondary-text-color); + } + .payments-label { color: var(--cr-secondary-text-color); margin-inline-start: 16px; @@ -20,11 +28,17 @@ </style> <div class="list-item"> <div class="type-column"> - <span id="creditCardLabel" class="ellipses"> - [[creditCard.metadata.summaryLabel]] - </span> + <div class="summary-column"> + <div id = "summaryLabel" class="ellipses"> + [[creditCard.metadata.summaryLabel]] + </div> + <div id = "summarySublabel" + hidden$="[[!shouldShowSecondarySublabel_()]]" class="ellipses"> + [[getSecondarySublabel_(creditCard.metadata)]] + </div> + </div> <span id="virtualCardLabel" - hidden$="[[!isVirtualCardEnrolled_(creditCard.metadata)]]"> + hidden$="[[!shouldShowVirtualCardLabel_(creditCard.metadata)]]"> $i18n{virtualCardEnabled} </span> <span class="payments-label"
diff --git a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts index 0b1d9395..4315681a 100644 --- a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts +++ b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts
@@ -47,11 +47,23 @@ }, readOnly: true, }, + + /** + * Whether virtual card metadata on settings page is enabled. + */ + virtualCardMetadataEnabled_: { + type: Boolean, + value() { + return loadTimeData.getBoolean('virtualCardMetadataEnabled'); + }, + readOnly: true, + }, }; } creditCard: chrome.autofillPrivate.CreditCardEntry; private virtualCardEnrollmentEnabled_: boolean; + private virtualCardMetadataEnabled_: boolean; /** * Opens the credit card action menu. @@ -121,6 +133,32 @@ return this.virtualCardEnrollmentEnabled_ && this.creditCard.metadata!.isVirtualCardEnrolled!; } + + private isVirtualCardMetadataEnabled_(): boolean { + return this.virtualCardMetadataEnabled_; + } + + private shouldShowVirtualCardLabel_(): boolean { + return this.isVirtualCardEnrolled_() && + !this.isVirtualCardMetadataEnabled_(); + } + + private shouldShowSecondarySublabel_(): boolean { + return !!(this.creditCard.metadata!.summarySublabel!.trim() !== '' || + this.isVirtualCardEnrolled_() || + this.isVirtualCardEnrollmentEligible_()) && + this.isVirtualCardMetadataEnabled_(); + } + + private getSecondarySublabel_(): string { + if (this.isVirtualCardEnrolled_()) { + return this.i18nAdvanced('virtualCardTurnedOn'); + } + if (this.isVirtualCardEnrollmentEligible_()) { + return this.i18nAdvanced('virtualCardAvailable'); + } + return this.creditCard.metadata!.summarySublabel!; + } } customElements.define(
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn index 24b68d93..184cc040 100644 --- a/chrome/browser/resources/settings/chromeos/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -433,12 +433,7 @@ "os_privacy_page:web_components", "os_reset_page:web_components", "os_search_page:web_components", - "os_settings_main:web_components", - "os_settings_menu:web_components", - "os_settings_page:web_components", "os_settings_search_box:web_components", - "os_settings_ui:web_components", - "os_toolbar:web_components", "parental_controls_page:web_components", "personalization_page:web_components", "settings_scheduler_slider:web_components",
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_subpage.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_subpage.js index 151bb04..4903688 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_subpage.js +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_subpage.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import './multidevice_feature_toggle.js'; import './multidevice_radio_button.js'; import '../../settings_shared.css.js';
diff --git a/chrome/browser/resources/settings/chromeos/nearby_share_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/nearby_share_page/BUILD.gn index c9c6b80..9e2a542 100644 --- a/chrome/browser/resources/settings/chromeos/nearby_share_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/BUILD.gn
@@ -53,7 +53,7 @@ "//ui/webui/resources/cr_elements/cr_button:cr_button.m", "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m", "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button.m", - "//ui/webui/resources/cr_elements/cr_radio_group:cr_radio_group.m", + "//ui/webui/resources/cr_elements/cr_radio_group:cr_radio_group", "//ui/webui/resources/js:i18n_behavior.m", ] }
diff --git a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_data_usage_dialog.js b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_data_usage_dialog.js index d370909a..c51300ce 100644 --- a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_data_usage_dialog.js +++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_data_usage_dialog.js
@@ -11,7 +11,7 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/channel_switcher_dialog.ts b/chrome/browser/resources/settings/chromeos/os_about_page/channel_switcher_dialog.ts index 533f5c53..aa43efc 100644 --- a/chrome/browser/resources/settings/chromeos/os_about_page/channel_switcher_dialog.ts +++ b/chrome/browser/resources/settings/chromeos/os_about_page/channel_switcher_dialog.ts
@@ -12,7 +12,7 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js'; import '../../settings_shared.css.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/edit_hostname_dialog.ts b/chrome/browser/resources/settings/chromeos/os_about_page/edit_hostname_dialog.ts index fd7d408f..d0ff186 100644 --- a/chrome/browser/resources/settings/chromeos/os_about_page/edit_hostname_dialog.ts +++ b/chrome/browser/resources/settings/chromeos/os_about_page/edit_hostname_dialog.ts
@@ -10,7 +10,7 @@ import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js'; import '../../settings_shared.css.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn index 05c88a6..5ce48ec 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn
@@ -252,7 +252,7 @@ ":util", "../..:metrics_recorder", "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button.m", - "//ui/webui/resources/cr_elements/cr_radio_group:cr_radio_group.m", + "//ui/webui/resources/cr_elements/cr_radio_group:cr_radio_group", "//ui/webui/resources/js/cr/ui:focus_without_ink.m", ] }
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js index 7f39fb4..9cf2106 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js
@@ -6,7 +6,7 @@ import './supported_links_dialog.js'; import 'chrome://resources/cr_components/localized_link/localized_link.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import {AppManagementUserAction, AppType, WindowMode} from 'chrome://resources/cr_components/app_management/constants.js'; import {recordAppManagementUserAction} from 'chrome://resources/cr_components/app_management/util.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js b/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js index 1a12668..0c1a1e21 100644 --- a/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js +++ b/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js
@@ -16,7 +16,7 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/shared_vars_css.m.js'; import 'chrome://resources/cr_elements/policy/cr_policy_indicator.m.js'; import '../../controls/settings_toggle_button.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni index c0cc1ce..ded5bd0e 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.gni +++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -14,6 +14,12 @@ "chromeos/os_about_page/edit_hostname_dialog.ts", "chromeos/os_about_page/os_about_page.ts", "chromeos/os_about_page/update_warning_dialog.ts", + "chromeos/os_settings_main/os_settings_main.js", + "chromeos/os_settings_menu/os_settings_menu.js", + "chromeos/os_settings_page/os_settings_page.js", + "chromeos/os_settings_page/settings_idle_load.js", + "chromeos/os_settings_ui/os_settings_ui.js", + "chromeos/os_toolbar/os_toolbar.js", ] # Files that are passed as input to html_to_wrapper(). @@ -327,14 +333,8 @@ "chromeos/os_search_page/search_engine.js", "chromeos/os_search_page/search_subpage.js", "chromeos/os_settings_icons_css.js", - "chromeos/os_settings_main/os_settings_main.js", - "chromeos/os_settings_menu/os_settings_menu.js", - "chromeos/os_settings_page/os_settings_page.js", - "chromeos/os_settings_page/settings_idle_load.js", "chromeos/os_settings_search_box/os_search_result_row.js", "chromeos/os_settings_search_box/os_settings_search_box.js", - "chromeos/os_settings_ui/os_settings_ui.js", - "chromeos/os_toolbar/os_toolbar.js", "chromeos/parental_controls_page/parental_controls_page.js", "chromeos/personalization_page/change_picture.js", "chromeos/personalization_page/personalization_page.js",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_main/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_settings_main/BUILD.gn index 245e660..51f630b5 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_main/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_settings_main/BUILD.gn
@@ -3,7 +3,6 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") -import("//tools/polymer/html_to_js.gni") import("../os_settings.gni") js_type_check("closure_compile_module") { @@ -23,7 +22,3 @@ "//ui/webui/resources/js:assert.m", ] } - -html_to_js("web_components") { - js_files = [ "os_settings_main.js" ] -}
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.js b/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.js index 85376aac..c66a4daa 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.js +++ b/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.js
@@ -17,7 +17,7 @@ import '../../settings_shared.css.js'; import '../../settings_vars.css.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {loadTimeData} from '../../i18n_setup.js'; import {Route, Router} from '../../router.js'; @@ -25,6 +25,8 @@ import {routes} from '../os_route.js'; import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; +import {getTemplate} from './os_settings_main.html.js'; + /** * @typedef {{about: boolean, settings: boolean}} */ @@ -45,7 +47,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_menu/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_settings_menu/BUILD.gn index 2d79465..ab808f8 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_menu/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_settings_menu/BUILD.gn
@@ -3,7 +3,6 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") -import("//tools/polymer/html_to_js.gni") import("../os_settings.gni") js_type_check("closure_compile_module") { @@ -21,7 +20,3 @@ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ] } - -html_to_js("web_components") { - js_files = [ "os_settings_menu.js" ] -}
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js index 48e2da0..ac583d06 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js +++ b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js
@@ -15,12 +15,14 @@ import '../os_icons.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Route, Router} from '../../router.js'; import {routes} from '../os_route.js'; import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; +import {getTemplate} from './os_settings_menu.html.js'; + /** * @constructor * @extends {PolymerElement} @@ -36,7 +38,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_settings_page/BUILD.gn index e19229a2..694b6f71 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_settings_page/BUILD.gn
@@ -3,7 +3,6 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") -import("//tools/polymer/html_to_js.gni") import("../os_settings.gni") js_type_check("closure_compile_module") { @@ -61,10 +60,3 @@ "//ui/webui/resources/js:assert.m", ] } - -html_to_js("web_components") { - js_files = [ - "os_settings_page.js", - "settings_idle_load.js", - ] -}
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.js b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.js index 3b8bd56..64c8c01 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.js +++ b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.js
@@ -32,7 +32,7 @@ import {assert} from 'chrome://resources/js/assert.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; -import {beforeNextRender, html, microTask, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {beforeNextRender, microTask, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Route, Router} from '../../router.js'; import {AndroidAppsBrowserProxyImpl, AndroidAppsInfo} from '../os_apps_page/android_apps_browser_proxy.js'; @@ -41,6 +41,7 @@ import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {MainPageBehavior, MainPageBehaviorInterface} from './main_page_behavior.js'; +import {getTemplate} from './os_settings_page.html.js'; /** * @constructor @@ -60,7 +61,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/settings_idle_load.js b/chrome/browser/resources/settings/chromeos/os_settings_page/settings_idle_load.js index c205eea..585a277 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_page/settings_idle_load.js +++ b/chrome/browser/resources/settings/chromeos/os_settings_page/settings_idle_load.js
@@ -10,10 +10,12 @@ */ import {assert} from 'chrome://resources/js/assert.m.js'; -import {html, PolymerElement, TemplateInstanceBase, templatize} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {PolymerElement, TemplateInstanceBase, templatize} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {ensureLazyLoaded} from '../ensure_lazy_loaded.js'; +import {getTemplate} from './settings_idle_load.html.js'; + /** @polymer */ class SettingsIdleLoadElement extends PolymerElement { static get is() { @@ -21,7 +23,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_ui/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_settings_ui/BUILD.gn index 87b2bca..60f3e8f2 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_ui/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_settings_ui/BUILD.gn
@@ -3,7 +3,6 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") -import("//tools/polymer/html_to_js.gni") import("../os_settings.gni") js_type_check("closure_compile_module") { @@ -33,7 +32,3 @@ "//ui/webui/resources/cr_elements/cr_drawer/cr_drawer_externs.js", ] } - -html_to_js("web_components") { - js_files = [ "os_settings_ui.js" ] -}
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js index 81164921..757440b 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js +++ b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js
@@ -26,7 +26,7 @@ import {FindShortcutBehavior, FindShortcutBehaviorInterface} from 'chrome://resources/cr_elements/find_shortcut_behavior.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {listenOnce} from 'chrome://resources/js/util.m.js'; -import {Debouncer, html, microTask, mixinBehaviors, PolymerElement, timeOut} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {Debouncer, microTask, mixinBehaviors, PolymerElement, timeOut} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {loadTimeData} from '../../i18n_setup.js'; import {SettingChangeValue} from '../../mojom-webui/search/user_action_recorder.mojom-webui.js'; @@ -38,6 +38,8 @@ import {PrefToSettingMetricConverter} from '../pref_to_setting_metric_converter.js'; import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; +import {getTemplate} from './os_settings_ui.html.js'; + /** Global defined when the main Settings script runs. */ let defaultResourceLoaded = true; // eslint-disable-line prefer-const @@ -68,7 +70,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/os_toolbar/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_toolbar/BUILD.gn index 9b8ca80..90205371 100644 --- a/chrome/browser/resources/settings/chromeos/os_toolbar/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_toolbar/BUILD.gn
@@ -3,7 +3,6 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") -import("//tools/polymer/html_to_js.gni") import("../os_settings.gni") js_type_check("closure_compile_module") { @@ -21,7 +20,3 @@ ] externs_list = [ "//ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field_externs.js" ] } - -html_to_js("web_components") { - js_files = [ "os_toolbar.js" ] -}
diff --git a/chrome/browser/resources/settings/chromeos/os_toolbar/os_toolbar.js b/chrome/browser/resources/settings/chromeos/os_toolbar/os_toolbar.js index 3997681..634087c 100644 --- a/chrome/browser/resources/settings/chromeos/os_toolbar/os_toolbar.js +++ b/chrome/browser/resources/settings/chromeos/os_toolbar/os_toolbar.js
@@ -11,7 +11,9 @@ import '../os_settings_search_box/os_settings_search_box.js'; import 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js'; -import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {getTemplate} from './os_toolbar.html.js'; /** @polymer */ class OsToolbarElement extends PolymerElement { @@ -20,7 +22,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/controls/settings_radio_group.ts b/chrome/browser/resources/settings/controls/settings_radio_group.ts index 47b6760..6e7b75e 100644 --- a/chrome/browser/resources/settings/controls/settings_radio_group.ts +++ b/chrome/browser/resources/settings/controls/settings_radio_group.ts
@@ -13,7 +13,7 @@ * </settings-radio-group> */ import '//resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import '//resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import '//resources/cr_elements/cr_radio_group/cr_radio_group.js'; import '../settings_shared.css.js'; import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/people_page/sync_controls.ts b/chrome/browser/resources/settings/people_page/sync_controls.ts index 0eba1fc0..4b277bc88a 100644 --- a/chrome/browser/resources/settings/people_page/sync_controls.ts +++ b/chrome/browser/resources/settings/people_page/sync_controls.ts
@@ -5,7 +5,7 @@ import '//resources/js/util.m.js'; import '//resources/cr_components/localized_link/localized_link.js'; import '//resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import '//resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import '//resources/cr_elements/cr_radio_group/cr_radio_group.js'; import '//resources/cr_elements/cr_toggle/cr_toggle.m.js'; import '//resources/cr_elements/shared_style_css.m.js'; import '//resources/cr_elements/shared_vars_css.m.js';
diff --git a/chrome/browser/resources/settings/people_page/sync_encryption_options.ts b/chrome/browser/resources/settings/people_page/sync_encryption_options.ts index 34b9b74..ccbe493 100644 --- a/chrome/browser/resources/settings/people_page/sync_encryption_options.ts +++ b/chrome/browser/resources/settings/people_page/sync_encryption_options.ts
@@ -5,14 +5,14 @@ import '//resources/cr_elements/cr_button/cr_button.m.js'; import '//resources/cr_elements/cr_input/cr_input.m.js'; import '//resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import '//resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import '//resources/cr_elements/cr_radio_group/cr_radio_group.js'; import '//resources/cr_elements/shared_style_css.m.js'; import '../settings_shared.css.js'; import '../settings_vars.css.js'; import {CrInputElement} from '//resources/cr_elements/cr_input/cr_input.m.js'; // <if expr="chromeos_ash"> -import {CrRadioGroupElement} from '//resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import {CrRadioGroupElement} from '//resources/cr_elements/cr_radio_group/cr_radio_group.js'; // </if> import {assert} from '//resources/js/assert_ts.js';
diff --git a/chrome/browser/resources/settings/privacy_page/secure_dns.ts b/chrome/browser/resources/settings/privacy_page/secure_dns.ts index 0882e65..31d98d9 100644 --- a/chrome/browser/resources/settings/privacy_page/secure_dns.ts +++ b/chrome/browser/resources/settings/privacy_page/secure_dns.ts
@@ -15,14 +15,14 @@ */ import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/md_select_css.m.js'; import '../controls/settings_toggle_button.js'; import '../prefs/prefs.js'; import '../settings_shared.css.js'; import './secure_dns_input.js'; -import {CrRadioGroupElement} from 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import {CrRadioGroupElement} from 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import {assertNotReached} from 'chrome://resources/js/assert_ts.js'; import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/settings.ts b/chrome/browser/resources/settings/settings.ts index affedc8..1e1bf117 100644 --- a/chrome/browser/resources/settings/settings.ts +++ b/chrome/browser/resources/settings/settings.ts
@@ -9,7 +9,7 @@ export {CrDrawerElement} from 'chrome://resources/cr_elements/cr_drawer/cr_drawer.js'; export {CrLinkRowElement} from 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js'; export {CrRadioButtonElement} from 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -export {CrRadioGroupElement} from 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +export {CrRadioGroupElement} from 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; export {CrToggleElement} from 'chrome://resources/cr_elements/cr_toggle/cr_toggle.m.js'; export {CrToolbarElement} from 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar.js'; export {CrToolbarSearchFieldElement} from 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js';
diff --git a/chrome/browser/resources/settings/site_settings/protocol_handlers.ts b/chrome/browser/resources/settings/site_settings/protocol_handlers.ts index e093fc4..c655183 100644 --- a/chrome/browser/resources/settings/site_settings/protocol_handlers.ts +++ b/chrome/browser/resources/settings/site_settings/protocol_handlers.ts
@@ -10,7 +10,7 @@ import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js'; import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js'; import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.m.js'; import 'chrome://resources/cr_elements/shared_style_css.m.js';
diff --git a/chrome/browser/resources/side_panel/images/read_anything_dark.png b/chrome/browser/resources/side_panel/images/read_anything_dark.png new file mode 100644 index 0000000..b8f9f73 --- /dev/null +++ b/chrome/browser/resources/side_panel/images/read_anything_dark.png Binary files differ
diff --git a/chrome/browser/resources/side_panel/images/read_anything_default.png b/chrome/browser/resources/side_panel/images/read_anything_default.png new file mode 100644 index 0000000..b0b67a7 --- /dev/null +++ b/chrome/browser/resources/side_panel/images/read_anything_default.png Binary files differ
diff --git a/chrome/browser/resources/side_panel/images/read_anything_light.png b/chrome/browser/resources/side_panel/images/read_anything_light.png new file mode 100644 index 0000000..7c1764b7 --- /dev/null +++ b/chrome/browser/resources/side_panel/images/read_anything_light.png Binary files differ
diff --git a/chrome/browser/resources/side_panel/images/read_anything_yellow.png b/chrome/browser/resources/side_panel/images/read_anything_yellow.png new file mode 100644 index 0000000..5d218080 --- /dev/null +++ b/chrome/browser/resources/side_panel/images/read_anything_yellow.png Binary files differ
diff --git a/chrome/browser/resources/side_panel/read_anything/app.html b/chrome/browser/resources/side_panel/read_anything/app.html index 21e59de6..186c7b8 100644 --- a/chrome/browser/resources/side_panel/read_anything/app.html +++ b/chrome/browser/resources/side_panel/read_anything/app.html
@@ -1,9 +1,8 @@ <style> #container { - background: var(--google-grey-900); - color: var(--google-grey-200); - font-size: 18px; - padding: 20px; + background-color: var(--background-color); + color: var(--foreground-color); + padding: 20px; } </style> <div id="container"
diff --git a/chrome/browser/resources/side_panel/read_anything/app.ts b/chrome/browser/resources/side_panel/read_anything/app.ts index 1e64e1e..399d9638 100644 --- a/chrome/browser/resources/side_panel/read_anything/app.ts +++ b/chrome/browser/resources/side_panel/read_anything/app.ts
@@ -5,7 +5,9 @@ import '../strings.m.js'; import {assert} from 'chrome://resources/js/assert_ts.js'; +import {skColorToRgba} from 'chrome://resources/js/color_utils.js'; import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js'; +import {SkColor} from 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-webui.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {getTemplate} from './app.html.js'; @@ -53,6 +55,8 @@ private fontName_: string; private fontSize_: number; + private foregroundColor_: SkColor = new SkColor(); + private backgroundColor_: SkColor = new SkColor(); // Defines the valid font names that can be passed to front-end and maps // them to a corresponding class style in app.html. Must stay in-sync with @@ -178,6 +182,13 @@ updateTheme() { this.fontName_ = this.validatedFontName(); this.fontSize_ = chrome.readAnything.fontSize; + this.foregroundColor_.value = chrome.readAnything.foregroundColor; + this.backgroundColor_.value = chrome.readAnything.backgroundColor; + + this.updateStyles({ + '--foreground-color': skColorToRgba(this.foregroundColor_), + '--background-color': skColorToRgba(this.backgroundColor_), + }); } }
diff --git a/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts b/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts index 6402a07..6282645 100644 --- a/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts +++ b/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts
@@ -17,6 +17,8 @@ // Items in the ReadAnythingTheme struct, see read_anything.mojom for info. let fontName: string; let fontSize: number; + let foregroundColor: number; + let backgroundColor: number; // Returns a list of AXNodeIDs corresponding to the unignored children of // the AXNode for the provided AXNodeID. @@ -69,7 +71,9 @@ snapshotLite: Object, contentNodeIds: number[]): void; // Set the theme. Used by tests only. - function setThemeForTesting(fontName: string, fontSize: number): void; + function setThemeForTesting( + fontName: string, fontSize: number, foregroundColor: number, + backgroundColor: number): void; //////////////////////////////////////////////////////////////// // Implemented in read_anything/app.ts and called by native c++.
diff --git a/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.ts b/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.ts index c068727..3ce20c0 100644 --- a/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.ts +++ b/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.ts
@@ -4,7 +4,7 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/shared_vars_css.m.js'; import './signin_shared.css.js'; import './strings.m.js';
diff --git a/chrome/browser/resources/support_tool/pii_selection.ts b/chrome/browser/resources/support_tool/pii_selection.ts index 26fb2de..a68643a9 100644 --- a/chrome/browser/resources/support_tool/pii_selection.ts +++ b/chrome/browser/resources/support_tool/pii_selection.ts
@@ -6,7 +6,7 @@ import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js'; import 'chrome://resources/cr_elements/cr_expand_button/cr_expand_button.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/shared_vars_css.m.js'; import './support_tool_shared.css.js';
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_radio_demo.html b/chrome/browser/resources/webui_gallery/demos/cr_radio_demo.html index 21812dcb..2203dbc6 100644 --- a/chrome/browser/resources/webui_gallery/demos/cr_radio_demo.html +++ b/chrome/browser/resources/webui_gallery/demos/cr_radio_demo.html
@@ -23,7 +23,7 @@ </template> </dom-bind> - <script src="chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js" + <script src="chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js" type="module"></script> <script src="chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js" type="module"></script>
diff --git a/chrome/browser/safe_browsing/OWNERS b/chrome/browser/safe_browsing/OWNERS index 3e4d613..5225674 100644 --- a/chrome/browser/safe_browsing/OWNERS +++ b/chrome/browser/safe_browsing/OWNERS
@@ -1,6 +1 @@ -drubery@chromium.org -nparker@chromium.org -vakh@chromium.org -xinghuilu@chromium.org - -per-file *password_protection*=file://components/safe_browsing/content/password_protection/OWNERS +file://components/safe_browsing/OWNERS
diff --git a/chrome/browser/safe_browsing/download_protection/OWNERS b/chrome/browser/safe_browsing/download_protection/OWNERS deleted file mode 100644 index 70e4b68..0000000 --- a/chrome/browser/safe_browsing/download_protection/OWNERS +++ /dev/null
@@ -1,3 +0,0 @@ -drubery@chromium.org -nparker@chromium.org -vakh@chromium.org
diff --git a/chrome/browser/signin/account_consistency_mode_manager_factory.cc b/chrome/browser/signin/account_consistency_mode_manager_factory.cc index db15271..e5a81dc9 100644 --- a/chrome/browser/signin/account_consistency_mode_manager_factory.cc +++ b/chrome/browser/signin/account_consistency_mode_manager_factory.cc
@@ -22,9 +22,8 @@ } AccountConsistencyModeManagerFactory::AccountConsistencyModeManagerFactory() - : ProfileKeyedServiceFactory( - "AccountConsistencyModeManager", - ProfileSelections::BuildServicesForRegularProfile()) {} + : ProfileKeyedServiceFactory("AccountConsistencyModeManager", + ProfileSelections::BuildForRegularProfile()) {} AccountConsistencyModeManagerFactory::~AccountConsistencyModeManagerFactory() = default;
diff --git a/chrome/browser/storage_access_api/api_browsertest.cc b/chrome/browser/storage_access_api/api_browsertest.cc index ea3a3e5..1a0e540 100644 --- a/chrome/browser/storage_access_api/api_browsertest.cc +++ b/chrome/browser/storage_access_api/api_browsertest.cc
@@ -49,11 +49,32 @@ enum class TestType { kFrame, kWorker }; -class StorageAccessAPIBrowserTest : public InProcessBrowserTest { +std::string BoolToString(bool b) { + return b ? "true" : "false"; +} + +class StorageAccessAPIBaseBrowserTest : public InProcessBrowserTest { protected: - StorageAccessAPIBrowserTest() - : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { - feature_enable_.InitAndEnableFeature(net::features::kStorageAccessAPI); + StorageAccessAPIBaseBrowserTest(bool permission_grants_unpartitioned_storage, + bool is_storage_partitioned) + : https_server_(net::EmbeddedTestServer::TYPE_HTTPS), + permission_grants_unpartitioned_storage_( + permission_grants_unpartitioned_storage), + is_storage_partitioned_(is_storage_partitioned) { + std::vector<base::test::ScopedFeatureList::FeatureAndParams> enabled({ + {net::features::kStorageAccessAPI, + {{"storage-access-api-grants-unpartitioned-storage", + BoolToString(permission_grants_unpartitioned_storage)}}}, + }); + std::vector<base::Feature> disabled; + + if (is_storage_partitioned) { + enabled.push_back({net::features::kThirdPartyStoragePartitioning, {}}); + } else { + disabled.push_back(net::features::kThirdPartyStoragePartitioning); + } + + features_.InitWithFeaturesAndParameters(enabled, disabled); } void SetUpOnMainThread() override { @@ -148,14 +169,30 @@ net::test_server::EmbeddedTestServer& https_server() { return https_server_; } + bool PermissionGrantsUnpartitionedStorage() const { + return permission_grants_unpartitioned_storage_; + } + bool IsStoragePartitioned() const { return is_storage_partitioned_; } + private: net::test_server::EmbeddedTestServer https_server_; - base::test::ScopedFeatureList feature_enable_; + base::test::ScopedFeatureList features_; + bool permission_grants_unpartitioned_storage_; + bool is_storage_partitioned_; +}; + +class StorageAccessAPIBrowserTest + : public StorageAccessAPIBaseBrowserTest, + public testing::WithParamInterface<std::tuple<bool, bool>> { + public: + StorageAccessAPIBrowserTest() + : StorageAccessAPIBaseBrowserTest(std::get<0>(GetParam()), + std::get<1>(GetParam())) {} }; // Validate that if an iframe requests access that cookies become unblocked for // just that top-level/third-party combination. -IN_PROC_BROWSER_TEST_F(StorageAccessAPIBrowserTest, +IN_PROC_BROWSER_TEST_P(StorageAccessAPIBrowserTest, ThirdPartyCookiesIFrameRequestsAccess) { SetBlockThirdPartyCookies(true); base::HistogramTester histogram_tester; @@ -272,7 +309,7 @@ // Validate that the Storage Access API does not override any explicit user // settings to block storage access. -IN_PROC_BROWSER_TEST_F(StorageAccessAPIBrowserTest, +IN_PROC_BROWSER_TEST_P(StorageAccessAPIBrowserTest, ThirdPartyCookiesIFrameThirdPartyExceptions) { SetBlockThirdPartyCookies(true); @@ -322,43 +359,8 @@ EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetNestedFrame())); } -// Test third-party cookie blocking of features that allow to communicate -// between tabs such as SharedWorkers. -IN_PROC_BROWSER_TEST_F(StorageAccessAPIBrowserTest, MultiTabTest) { - NavigateToPageWithFrame("a.com"); - NavigateFrameTo("b.com", "/browsing_data/site_data.html"); - - storage::test::ExpectCrossTabInfoForFrame(GetFrame(), false); - storage::test::SetCrossTabInfoForFrame(GetFrame()); - storage::test::ExpectCrossTabInfoForFrame(GetFrame(), true); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); - - // Create a second tab to test communication between tabs. - NavigateToNewTabWithFrame("a.com"); - NavigateFrameTo("b.com", "/browsing_data/site_data.html"); - storage::test::ExpectCrossTabInfoForFrame(GetFrame(), true); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); - - SetBlockThirdPartyCookies(true); - - NavigateToPageWithFrame("a.com"); - NavigateFrameTo("b.com", "/browsing_data/site_data.html"); - storage::test::ExpectCrossTabInfoForFrame(GetFrame(), false); - EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); - - // Allow all requests to b.com to access cookies. - // Allow all requests to b.com on a.com to access storage. - EXPECT_TRUE(storage::test::RequestStorageAccessForFrame(GetFrame())); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); - - NavigateToPageWithFrame("a.com"); - NavigateFrameTo("b.com", "/browsing_data/site_data.html"); - storage::test::ExpectCrossTabInfoForFrame(GetFrame(), true); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); -} - // Validates that once a grant is removed access is also removed. -IN_PROC_BROWSER_TEST_F(StorageAccessAPIBrowserTest, +IN_PROC_BROWSER_TEST_P(StorageAccessAPIBrowserTest, ThirdPartyGrantsDeletedAccess) { SetBlockThirdPartyCookies(true); @@ -393,7 +395,7 @@ EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); } -IN_PROC_BROWSER_TEST_F(StorageAccessAPIBrowserTest, OpaqueOriginRejects) { +IN_PROC_BROWSER_TEST_P(StorageAccessAPIBrowserTest, OpaqueOriginRejects) { SetBlockThirdPartyCookies(true); NavigateToPageWithFrame("a.com"); @@ -407,7 +409,7 @@ EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); } -IN_PROC_BROWSER_TEST_F(StorageAccessAPIBrowserTest, +IN_PROC_BROWSER_TEST_P(StorageAccessAPIBrowserTest, MissingSandboxTokenRejects) { SetBlockThirdPartyCookies(true); @@ -422,7 +424,7 @@ EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); } -IN_PROC_BROWSER_TEST_F(StorageAccessAPIBrowserTest, SandboxTokenResolves) { +IN_PROC_BROWSER_TEST_P(StorageAccessAPIBrowserTest, SandboxTokenResolves) { SetBlockThirdPartyCookies(true); NavigateToPageWithFrame("a.com"); @@ -438,7 +440,7 @@ } // Validates that expiry data is transferred over IPC to the Network Service. -IN_PROC_BROWSER_TEST_F(StorageAccessAPIBrowserTest, +IN_PROC_BROWSER_TEST_P(StorageAccessAPIBrowserTest, ThirdPartyGrantsExpireOverIPC) { SetBlockThirdPartyCookies(true); @@ -503,14 +505,23 @@ EXPECT_EQ(ReadCookiesViaJS(GetNestedFrame()), "thirdparty=c"); } +INSTANTIATE_TEST_CASE_P(/* no prefix */, + StorageAccessAPIBrowserTest, + testing::Combine(testing::Bool(), testing::Bool())); + class StorageAccessAPIStorageBrowserTest - : public StorageAccessAPIBrowserTest, - public testing::WithParamInterface<TestType> { + : public StorageAccessAPIBaseBrowserTest, + public testing::WithParamInterface<std::tuple<TestType, bool, bool>> { public: + StorageAccessAPIStorageBrowserTest() + : StorageAccessAPIBaseBrowserTest(std::get<1>(GetParam()), + std::get<2>(GetParam())) {} + void ExpectStorage(content::RenderFrameHost* frame, bool expected) { switch (GetTestType()) { case TestType::kFrame: - storage::test::ExpectStorageForFrame(frame, expected); + storage::test::ExpectStorageForFrame(frame, /*include_cookies=*/false, + expected); return; case TestType::kWorker: storage::test::ExpectStorageForWorker(frame, expected); @@ -521,7 +532,7 @@ void SetStorage(content::RenderFrameHost* frame) { switch (GetTestType()) { case TestType::kFrame: - storage::test::SetStorageForFrame(frame); + storage::test::SetStorageForFrame(frame, /*include_cookies=*/false); return; case TestType::kWorker: storage::test::SetStorageForWorker(frame); @@ -529,8 +540,12 @@ } } + bool DoesPermissionGrantStorage() const { + return IsStoragePartitioned() || PermissionGrantsUnpartitionedStorage(); + } + private: - TestType GetTestType() const { return GetParam(); } + TestType GetTestType() const { return std::get<0>(GetParam()); } }; // Validate that the Storage Access API will unblock other types of storage @@ -558,7 +573,7 @@ NavigateToPageWithFrame("a.com"); NavigateFrameTo("b.com", "/browsing_data/site_data.html"); - ExpectStorage(GetFrame(), true); + ExpectStorage(GetFrame(), DoesPermissionGrantStorage()); EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); } @@ -587,12 +602,51 @@ NavigateToPageWithFrame("a.com"); NavigateFrameTo("b.com", "/iframe.html"); NavigateNestedFrameTo("c.com", "/browsing_data/site_data.html"); - ExpectStorage(GetNestedFrame(), true); + ExpectStorage(GetNestedFrame(), DoesPermissionGrantStorage()); EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetNestedFrame())); } +// Test third-party cookie blocking of features that allow to communicate +// between tabs such as SharedWorkers. +IN_PROC_BROWSER_TEST_P(StorageAccessAPIStorageBrowserTest, MultiTabTest) { + NavigateToPageWithFrame("a.com"); + NavigateFrameTo("b.com", "/browsing_data/site_data.html"); + + storage::test::ExpectCrossTabInfoForFrame(GetFrame(), false); + storage::test::SetCrossTabInfoForFrame(GetFrame()); + storage::test::ExpectCrossTabInfoForFrame(GetFrame(), true); + EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); + + // Create a second tab to test communication between tabs. + NavigateToNewTabWithFrame("a.com"); + NavigateFrameTo("b.com", "/browsing_data/site_data.html"); + storage::test::ExpectCrossTabInfoForFrame(GetFrame(), true); + EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); + + SetBlockThirdPartyCookies(true); + + NavigateToPageWithFrame("a.com"); + NavigateFrameTo("b.com", "/browsing_data/site_data.html"); + storage::test::ExpectCrossTabInfoForFrame(GetFrame(), false); + EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + + // Allow all requests to b.com to access cookies. + // Allow all requests to b.com on a.com to access storage. + EXPECT_TRUE(storage::test::RequestStorageAccessForFrame(GetFrame())); + EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); + + NavigateToPageWithFrame("a.com"); + NavigateFrameTo("b.com", "/browsing_data/site_data.html"); + storage::test::ExpectCrossTabInfoForFrame(GetFrame(), + DoesPermissionGrantStorage()); + EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); +} + INSTANTIATE_TEST_SUITE_P(/*no prefix*/, StorageAccessAPIStorageBrowserTest, - testing::Values(TestType::kFrame, TestType::kWorker)); + testing::Combine(testing::Values(TestType::kFrame, + TestType::kWorker), + testing::Bool(), + testing::Bool())); } // namespace
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_file_system_delegate.cc b/chrome/browser/ui/ash/holding_space/holding_space_file_system_delegate.cc index 2adad6e1..a83af60 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_file_system_delegate.cc +++ b/chrome/browser/ui/ash/holding_space/holding_space_file_system_delegate.cc
@@ -20,6 +20,7 @@ #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "base/threading/sequenced_task_runner_handle.h" +#include "base/time/time.h" #include "chrome/browser/ash/arc/arc_util.h" #include "chrome/browser/ash/drive/drive_integration_service.h" #include "chrome/browser/ash/file_manager/path_util.h" @@ -126,8 +127,12 @@ private: void OnFilePathChanged(const base::FilePath& file_path, bool error) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - content::GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, base::BindOnce(callback_, file_path, error)); + // In tests `OnFilePathChanged()` events are sometimes propagated before + // `OnFileMoved()` events. Delay propagation of `OnFilePathChanged()` + // events to give `OnFileMoved()` events time to propagate. + content::GetUIThreadTaskRunner({})->PostDelayedTask( + FROM_HERE, base::BindOnce(callback_, file_path, error), + base::Milliseconds(1)); } SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc index e5b2974..b43e663 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc +++ b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc
@@ -786,11 +786,9 @@ persisted_holding_space_items); } -// TODO(crbug.com/1315122): Fix flakes and re-enable. // Verifies that when a file backing a holding space item is moved, the holding // space item is updated in place and persistence storage is updated. -TEST_F(HoldingSpaceKeyedServiceTest, - DISABLED_UpdatePersistentStorageAfterMove) { +TEST_F(HoldingSpaceKeyedServiceTest, UpdatePersistentStorageAfterMove) { // Create a file system mount point. std::unique_ptr<ScopedTestMountPoint> downloads_mount = ScopedTestMountPoint::CreateAndMountDownloads(GetProfile()); @@ -912,12 +910,11 @@ } } -// TODO(crbug.com/1170667): Fix flakes and re-enable. // Tests that holding space item's image representation gets updated when the // backing file is changed using move operation. Furthermore, verifies that // conflicts caused by moving a holding space item file to another path present // in the holding space get resolved. -TEST_F(HoldingSpaceKeyedServiceTest, DISABLED_UpdateItemsOverwrittenByMove) { +TEST_F(HoldingSpaceKeyedServiceTest, UpdateItemsOverwrittenByMove) { // Create a file system mount point. std::unique_ptr<ScopedTestMountPoint> downloads_mount = ScopedTestMountPoint::CreateAndMountDownloads(GetProfile());
diff --git a/chrome/browser/ui/page_info/chrome_page_info_delegate.cc b/chrome/browser/ui/page_info/chrome_page_info_delegate.cc index 18706b7..1fe1e918 100644 --- a/chrome/browser/ui/page_info/chrome_page_info_delegate.cc +++ b/chrome/browser/ui/page_info/chrome_page_info_delegate.cc
@@ -32,8 +32,11 @@ #include "components/security_interstitials/content/stateful_ssl_host_state_delegate.h" #include "components/subresource_filter/content/browser/subresource_filter_content_settings_manager.h" #include "components/subresource_filter/content/browser/subresource_filter_profile_context.h" +#include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_features.h" +#include "url/origin.h" #if BUILDFLAG(FULL_SAFE_BROWSING) #include "chrome/browser/safe_browsing/chrome_password_protection_service.h" @@ -151,14 +154,14 @@ } #endif -permissions::PermissionResult ChromePageInfoDelegate::GetPermissionStatus( - ContentSettingsType type, - const GURL& site_url) { - // TODO(raymes): Use GetPermissionStatus() to retrieve information - // about *all* permissions once it has default behaviour implemented for - // ContentSettingTypes that aren't permissions. - return PermissionManagerFactory::GetForProfile(GetProfile()) - ->GetPermissionStatusForDisplayOnSettingsUI(type, site_url); +permissions::PermissionResult ChromePageInfoDelegate::GetPermissionResult( + blink::PermissionType permission, + const url::Origin& origin) { + content::PermissionResult permission_result = + GetProfile() + ->GetPermissionController() + ->GetPermissionResultForOriginWithoutContext(permission, origin); + return permissions::PermissionUtil::ToPermissionResult(permission_result); } #if !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/ui/page_info/chrome_page_info_delegate.h b/chrome/browser/ui/page_info/chrome_page_info_delegate.h index 5e719b7..349bf17 100644 --- a/chrome/browser/ui/page_info/chrome_page_info_delegate.h +++ b/chrome/browser/ui/page_info/chrome_page_info_delegate.h
@@ -48,9 +48,9 @@ void OnUserActionOnPasswordUi(safe_browsing::WarningAction action) override; std::u16string GetWarningDetailText() override; #endif - permissions::PermissionResult GetPermissionStatus( - ContentSettingsType type, - const GURL& site_url) override; + permissions::PermissionResult GetPermissionResult( + blink::PermissionType permission, + const url::Origin& origin) override; #if !BUILDFLAG(IS_ANDROID) bool CreateInfoBarDelegate() override;
diff --git a/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.cc b/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.cc index 9cfc9ab7..53bc206 100644 --- a/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.cc +++ b/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.cc
@@ -20,6 +20,8 @@ #include "components/permissions/permissions_client.h" #include "components/prefs/pref_service.h" #include "components/strings/grit/components_strings.h" +#include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "content/public/browser/web_contents.h" #include "net/base/url_util.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" @@ -206,10 +208,14 @@ } #endif -permissions::PermissionResult ChromePageInfoUiDelegate::GetPermissionStatus( - ContentSettingsType type) { - return PermissionManagerFactory::GetForProfile(GetProfile()) - ->GetPermissionStatusForDisplayOnSettingsUI(type, site_url_); +permissions::PermissionResult ChromePageInfoUiDelegate::GetPermissionResult( + blink::PermissionType permission) { + content::PermissionResult permission_result = + GetProfile() + ->GetPermissionController() + ->GetPermissionResultForOriginWithoutContext( + permission, url::Origin::Create(site_url_)); + return permissions::PermissionUtil::ToPermissionResult(permission_result); } absl::optional<permissions::PermissionResult>
diff --git a/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h b/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h index af8e733b..8d0c2ec3 100644 --- a/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h +++ b/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h
@@ -68,8 +68,8 @@ bool IsBlockAutoPlayEnabled() override; bool IsMultipleTabsOpen() override; #endif // !BUILDFLAG(IS_ANDROID) - permissions::PermissionResult GetPermissionStatus( - ContentSettingsType type) override; + permissions::PermissionResult GetPermissionResult( + blink::PermissionType permission) override; absl::optional<permissions::PermissionResult> GetEmbargoResult( ContentSettingsType type) override;
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc index 6afe1fc..efbc3c6e 100644 --- a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc +++ b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
@@ -9,6 +9,7 @@ #include "base/test/scoped_mock_time_message_loop_task_runner.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_tabstrip.h" @@ -17,8 +18,10 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/live_caption/pref_names.h" #include "components/live_caption/views/caption_bubble.h" #include "components/live_caption/views/caption_bubble_controller_views.h" +#include "components/prefs/pref_service.h" #include "content/public/browser/browser_accessibility_state.h" #include "content/public/test/browser_test.h" #include "media/mojo/mojom/speech_recognition_service.mojom.h" @@ -50,7 +53,8 @@ CaptionBubbleControllerViews* GetController() { if (!controller_) - controller_ = std::make_unique<CaptionBubbleControllerViews>(); + controller_ = std::make_unique<CaptionBubbleControllerViews>( + browser()->profile()->GetPrefs()); return controller_.get(); } @@ -101,6 +105,16 @@ : nullptr; } + views::Button* GetPinButton() { + return controller_ ? controller_->caption_bubble_->pin_button_.get() + : nullptr; + } + + views::Button* GetUnpinButton() { + return controller_ ? controller_->caption_bubble_->unpin_button_.get() + : nullptr; + } + views::View* GetErrorMessage() { return controller_ ? controller_->caption_bubble_->generic_error_message_.get() @@ -862,6 +876,8 @@ IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, ExpandsAndCollapses) { int line_height = 24; + EXPECT_FALSE(browser()->profile()->GetPrefs()->GetBoolean( + prefs::kLiveCaptionBubbleExpanded)); OnPartialTranscription("Seahorses are monogamous"); EXPECT_TRUE(GetExpandButton()->GetVisible()); @@ -872,6 +888,8 @@ EXPECT_TRUE(GetCollapseButton()->GetVisible()); EXPECT_FALSE(GetExpandButton()->GetVisible()); EXPECT_EQ(7 * line_height, GetLabel()->GetBoundsInScreen().height()); + EXPECT_TRUE(browser()->profile()->GetPrefs()->GetBoolean( + prefs::kLiveCaptionBubbleExpanded)); // Switch media. The bubble should remain expanded. auto media_1 = CaptionBubbleContextBrowser::Create( @@ -899,6 +917,29 @@ EXPECT_EQ(line_height, GetLabel()->GetBoundsInScreen().height()); } +IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, PinAndUnpin) { + base::ScopedMockTimeMessageLoopTaskRunner test_task_runner; + SetTickClockForTesting(test_task_runner->GetMockTickClock()); + EXPECT_FALSE(browser()->profile()->GetPrefs()->GetBoolean( + prefs::kLiveCaptionBubblePinned)); + + OnPartialTranscription( + "Sea otters have the densest fur of any mammal at about 1 million hairs " + "per square inch."); + EXPECT_TRUE(GetPinButton()->GetVisible()); + EXPECT_FALSE(GetUnpinButton()->GetVisible()); + + ClickButton(GetPinButton()); + EXPECT_FALSE(GetPinButton()->GetVisible()); + EXPECT_TRUE(GetUnpinButton()->GetVisible()); + EXPECT_TRUE(browser()->profile()->GetPrefs()->GetBoolean( + prefs::kLiveCaptionBubblePinned)); + + ASSERT_TRUE(GetBubble()->GetInactivityTimerForTesting()->IsRunning()); + test_task_runner->FastForwardBy(base::Seconds(15)); + EXPECT_TRUE(IsWidgetVisible()); +} + IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, NonAsciiCharacter) { OnPartialTranscription("犬は最高です"); EXPECT_EQ("犬は最高です", GetLabelText());
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc index ada56943..cf7743c 100644 --- a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc +++ b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
@@ -500,43 +500,41 @@ } void DownloadBubbleRowView::UpdateButtons() { - if (download::IsDownloadBubbleV2Enabled(browser_->profile())) { - resume_action_->SetVisible(false); - pause_action_->SetVisible(false); - open_when_complete_action_->SetVisible(false); - cancel_action_->SetVisible(false); - show_in_folder_action_->SetVisible(false); - open_when_complete_action_->SetVisible(false); - for (const auto& action : ui_info_.quick_actions) { - views::ImageButton* action_button = - GetActionButtonForCommand(action.command); - action_button->SetImageModel(views::Button::STATE_NORMAL, - ui::ImageModel::FromVectorIcon( - *(action.icon), ui::kColorIcon, + resume_action_->SetVisible(false); + pause_action_->SetVisible(false); + open_when_complete_action_->SetVisible(false); + cancel_action_->SetVisible(false); + show_in_folder_action_->SetVisible(false); + open_when_complete_action_->SetVisible(false); + for (const auto& action : ui_info_.quick_actions) { + views::ImageButton* action_button = + GetActionButtonForCommand(action.command); + action_button->SetImageModel( + views::Button::STATE_NORMAL, + ui::ImageModel::FromVectorIcon(*(action.icon), ui::kColorIcon, GetLayoutConstant(DOWNLOAD_ICON_SIZE))); - action_button->SetAccessibleName(action.hover_text); - action_button->SetTooltipText(action.hover_text); - action_button->SetVisible(true); - } - } else { - cancel_button_->SetVisible(ui_info_.primary_button_command == - DownloadCommands::CANCEL); - discard_button_->SetVisible(ui_info_.primary_button_command == - DownloadCommands::DISCARD); - keep_button_->SetVisible(ui_info_.primary_button_command == - DownloadCommands::KEEP); - scan_button_->SetVisible(ui_info_.primary_button_command == - DownloadCommands::DEEP_SCAN); - open_now_button_->SetVisible(ui_info_.primary_button_command == - DownloadCommands::BYPASS_DEEP_SCANNING); - resume_button_->SetVisible(ui_info_.primary_button_command == - DownloadCommands::RESUME); - review_button_->SetVisible(ui_info_.primary_button_command == - DownloadCommands::REVIEW); - retry_button_->SetVisible(ui_info_.primary_button_command == - DownloadCommands::RETRY); + action_button->SetAccessibleName(action.hover_text); + action_button->SetTooltipText(action.hover_text); + action_button->SetVisible(true); } + cancel_button_->SetVisible(ui_info_.primary_button_command == + DownloadCommands::CANCEL); + discard_button_->SetVisible(ui_info_.primary_button_command == + DownloadCommands::DISCARD); + keep_button_->SetVisible(ui_info_.primary_button_command == + DownloadCommands::KEEP); + scan_button_->SetVisible(ui_info_.primary_button_command == + DownloadCommands::DEEP_SCAN); + open_now_button_->SetVisible(ui_info_.primary_button_command == + DownloadCommands::BYPASS_DEEP_SCANNING); + resume_button_->SetVisible(ui_info_.primary_button_command == + DownloadCommands::RESUME); + review_button_->SetVisible(ui_info_.primary_button_command == + DownloadCommands::REVIEW); + retry_button_->SetVisible(ui_info_.primary_button_command == + DownloadCommands::RETRY); + subpage_icon_->SetVisible(ui_info_.has_subpage); subpage_icon_->SetBorder(views::CreateEmptyBorder( gfx::Insets(ui_info_.has_subpage ? kDownloadSubpageIconMargin : 0)));
diff --git a/chrome/browser/ui/views/frame/webui_tab_strip_interactive_uitest.cc b/chrome/browser/ui/views/frame/webui_tab_strip_interactive_uitest.cc index 66aa6342..1bd4401 100644 --- a/chrome/browser/ui/views/frame/webui_tab_strip_interactive_uitest.cc +++ b/chrome/browser/ui/views/frame/webui_tab_strip_interactive_uitest.cc
@@ -2,13 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/callback_forward.h" #include "base/strings/utf_string_conversions.h" -#include "base/test/bind.h" #include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" -#include "chrome/browser/ui/browser_element_identifiers.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/frame/browser_view.h" @@ -20,18 +17,8 @@ #include "chrome/browser/ui/views/toolbar/toolbar_view.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" -#include "chrome/test/interaction/interaction_test_util_browser.h" -#include "chrome/test/interaction/webui_interaction_test_util.h" #include "content/public/test/browser_test.h" -#include "ui/aura/client/drag_drop_client.h" -#include "ui/base/dragdrop/drag_drop_types.h" -#include "ui/base/interaction/element_tracker.h" -#include "ui/base/interaction/expect_call_in_scope.h" -#include "ui/base/interaction/interaction_sequence.h" -#include "ui/base/page_transition_types.h" #include "ui/base/pointer/touch_ui_controller.h" -#include "ui/base/test/ui_controls.h" -#include "ui/gfx/geometry/point.h" #include "ui/views/controls/webview/webview.h" #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -201,258 +188,4 @@ EXPECT_TRUE(immersive_mode_controller->IsRevealed()); } -// Regression test for crbug.com/1286203. -// -// The original bug was a UAF that happened when a tab closed itself (e.g. via -// javascript) during a drag from the WebUI tabstrip; not all references to the -// tab were properly cleaned up. -// -// There is already a proposed regression test for this bug using existing -// technology; see: -// https://chromium-review.googlesource.com/c/chromium/src/+/3588859 -// -// This is a proof-of-concept for regression testing using InteractionSequence, -// which demonstrates that: -// - tests can be written without arbitrary (and often flaky) delays -// - tests can be end-to-end interacting with both native and WebUI code -// - tests can be written to reproduce very specific test cases -// -// This framework can be used to handle many similar types of bugs, for both -// WebUI and Views elements. These tests, while more verbose, can be made very -// specific and are declarative and event-driven. This particular test performs -// the following steps: -// 1. opens a second tab in the browser -// 2. clicks the tab counter button to open the WebUI tabstrip -// 3. drags the second tab out of the WebUI tabstrip -// 4. without finishing the drag, closes the tab via script -// 5. verifies the tab actually closed -// 6. completes the drag -// -// This sequence of events would crash without the associated bugfix. More -// detail is provided in the actual test sequence. -// TODO(crbug.com/1352040): Fix consistent failures. -#if BUILDFLAG(IS_LINUX) && \ - (defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \ - defined(THREAD_SANITIZER)) -#define MAYBE_CloseTabDuringDrag DISABLED_CloseTabDuringDrag -#else -#define MAYBE_CloseTabDuringDrag CloseTabDuringDrag -#endif -IN_PROC_BROWSER_TEST_F(WebUITabStripInteractiveTest, MAYBE_CloseTabDuringDrag) { - // Add a second tab and set up an object to instrument that tab. - ASSERT_TRUE(AddTabAtIndex(-1, GURL("about:blank"), ui::PAGE_TRANSITION_LINK)); - DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kSecondTabElementId); - std::unique_ptr<WebUIInteractionTestUtil> second_tab = - WebUIInteractionTestUtil::ForExistingTabInBrowser(browser(), - kSecondTabElementId, 1); - - // The WebUI for the tabstrip will be instrumented only after it is guaranteed - // to have been created. - DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kWebUiTabStripElementId); - std::unique_ptr<WebUIInteractionTestUtil> tab_strip; - - // This is the DeepQuery path to the second tab element in the WebUI tabstrip. - // If the structure of the WebUI page changes greatly, it may need to be - // modified to reflect a new page structure. - const WebUIInteractionTestUtil::DeepQuery kSecondTabQuery{ - "tabstrip-tab-list", "tabstrip-tab + tabstrip-tab"}; - - // Some custom events used to advance the test sequence. - DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(kTabPopulatedCustomEvent); - DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(kMouseDragCompleteCustomEvent); - DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(kMouseUpCustomEvent); - - // This is just a convenience function for sending custom events so this code - // doesn't have to be duplicated in a bunch of places. - auto send_custom_event = [&](ui::CustomElementEventType event_type) { - auto* const target = - ui::ElementTracker::GetElementTracker()->GetUniqueElement( - kWebUiTabStripElementId, browser()->window()->GetElementContext()); - ASSERT_NE(nullptr, target); - ui::ElementTracker::GetFrameworkDelegate()->NotifyCustomEvent(target, - event_type); - }; - - // Performs a drag by sending mouse events. - // - // Moves the cursor to `start` and begins a drag to `end` in screen - // coordinates (but does not release the mouse button). When the mouse reaches - // `end`, an event is sent. - // - // This can probably be turned into a common utility method for testing things - // that happen in the middle of a drag. - auto perform_drag = [&](gfx::Point start, gfx::Point end) { - ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone( - start.x(), start.y(), base::BindLambdaForTesting([&]() { - ASSERT_TRUE(ui_controls::SendMouseEventsNotifyWhenDone( - ui_controls::LEFT, ui_controls::DOWN, - base::BindLambdaForTesting([&]() { - ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone( - end.x(), end.y(), base::BindLambdaForTesting([&]() { - send_custom_event(kMouseDragCompleteCustomEvent); - }))); - }))); - }))); - }; - - // These are needed to determine the sequence didn't fail. They're boilerplate - // and will probably be exchanged in the future for a smarter version of - // InteractionSequence::RunSynchronouslyForTesting(). - UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed); - UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted); - - // This object contains the sequence of expected stets in the test. - auto sequence = - ui::InteractionSequence::Builder() - .SetContext(browser()->window()->GetElementContext()) - .SetCompletedCallback(completed.Get()) - .SetAbortedCallback(aborted.Get()) - - // Wait until the second tab has fully loaded. This is advisable since - // later the destruction of the tab needs to be observed. - .AddStep(ui::InteractionSequence::StepBuilder() - .SetType(ui::InteractionSequence::StepType::kShown) - .SetElementID(kSecondTabElementId) - .Build()) - - // Click the tab counter button to display the WebUI tabstrip and - // make sure the tabstrip appears. - .AddStep( - ui::InteractionSequence::StepBuilder() - .SetType(ui::InteractionSequence::StepType::kShown) - .SetElementID(kTabCounterButtonElementId) - .SetStartCallback(base::BindLambdaForTesting( - [&](ui::InteractionSequence*, - ui::TrackedElement* element) { - const auto test_util = CreateInteractionTestUtil(); - test_util->PressButton(element); - - // The WebUI tabstrip can be created dynamically, so - // wait until the button is pressed and the browser is - // re-laid-out to bind the associated WebUI. - auto* const browser_view = - BrowserView::GetBrowserViewForBrowser(browser()); - browser_view->GetWidget()->LayoutRootViewIfNecessary(); - auto* const web_view = browser_view->webui_tab_strip() - ->web_view_for_testing(); - tab_strip = WebUIInteractionTestUtil::ForNonTabWebView( - web_view, kWebUiTabStripElementId); - })) - .Build()) - - // Wait for the WebUI tabstrip to become fully loaded, and then wait - // for the tab data to load and render. - .AddStep( - ui::InteractionSequence::StepBuilder() - .SetType(ui::InteractionSequence::StepType::kShown) - .SetElementID(kWebUiTabStripElementId) - .SetStartCallback(base::BindLambdaForTesting( - [&](ui::InteractionSequence*, - ui::TrackedElement* element) { - // At this point the new tab has been fully loaded and - // its onLoad() called. - EXPECT_EQ(2, browser()->tab_strip_model()->count()); - - // It takes a while for tab data to be filled out in the - // tabstrip. Before it is fully loaded the tabs have - // zero visible size, so wait until they are the - // expected size. - WebUIInteractionTestUtil::StateChange change; - change.event = kTabPopulatedCustomEvent; - change.where = kSecondTabQuery; - change.type = WebUIInteractionTestUtil::StateChange:: - Type::kExistsAndConditionTrue; - change.test_function = - "el => (el.getBoundingClientRect().width > 0)"; - tab_strip->SendEventOnStateChange(std::move(change)); - })) - .Build()) - - // Now that the tab is properly rendered, drag it out of the tabstrip. - .AddStep(ui::InteractionSequence::StepBuilder() - .SetType(ui::InteractionSequence::StepType::kCustomEvent, - kTabPopulatedCustomEvent) - .SetElementID(kWebUiTabStripElementId) - .SetStartCallback(base::BindLambdaForTesting( - [&](ui::InteractionSequence*, - ui::TrackedElement* element) { - // Starting point of drag is the center of the - // second tab in the WebUI tabstrip. - const gfx::Point start = - tab_strip - ->GetElementBoundsInScreen(kSecondTabQuery) - .CenterPoint(); - - // Endpoint is center of the main webcontents, so - // guaranteed to be outside the tabstrip. - const gfx::Point end = browser() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetContainerBounds() - .CenterPoint(); - - // Perform but do not complete the drag. - perform_drag(start, end); - })) - .Build()) - - // Wait for the drag to finish and close the tab without releasing the - // mouse and actually ending the drag. - .AddStep(ui::InteractionSequence::StepBuilder() - .SetType(ui::InteractionSequence::StepType::kCustomEvent, - kMouseDragCompleteCustomEvent) - .SetElementID(kWebUiTabStripElementId) - .SetStartCallback(base::BindLambdaForTesting( - [&](ui::InteractionSequence*, - ui::TrackedElement* element) { - // For WebUI tab drag, the tab isn't actually - // removed from the tabstrip until the drag - // completes. - EXPECT_EQ(2, - browser()->tab_strip_model()->count()); - - // Close the new tab. - second_tab->Execute("() => window.close()"); - })) - .Build()) - - // Wait for the dragged tab to be closed, verify it is closed, and - // release the mouse to finish the drag. - // - // SetTransitionOnlyOnEvent(true) means the test will fail if the tab - // goes away before this step is queued; it will only succeed if the - // tab disappears specifically in response to the previous step. - .AddStep( - ui::InteractionSequence::StepBuilder() - .SetType(ui::InteractionSequence::StepType::kHidden) - .SetElementID(kSecondTabElementId) - .SetTransitionOnlyOnEvent(true) - .SetStartCallback(base::BindLambdaForTesting( - [&](ui::InteractionSequence*, - ui::TrackedElement* element) { - // The tab should now be removed from the tabstrip - // because it was closed; the drag has not yet - // finished. - EXPECT_EQ(1, browser()->tab_strip_model()->count()); - - // Complete the drag by releasing the mouse. - EXPECT_TRUE(ui_controls::SendMouseEventsNotifyWhenDone( - ui_controls::LEFT, ui_controls::UP, - base::BindLambdaForTesting([&]() { - send_custom_event(kMouseUpCustomEvent); - }))); - })) - .Build()) - - // Wait for the mouse-up action to complete before ending the sequence - // so the browser is in a known input state for the next test. - .AddStep(ui::InteractionSequence::StepBuilder() - .SetType(ui::InteractionSequence::StepType::kCustomEvent, - kMouseUpCustomEvent) - .SetElementID(kWebUiTabStripElementId)) - .Build(); - - EXPECT_CALL_IN_SCOPE(completed, Run, sequence->RunSynchronouslyForTesting()); -} - #endif // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.cc b/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.cc index 5428a7a..810b83e 100644 --- a/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.cc +++ b/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.cc
@@ -15,6 +15,7 @@ #include "chrome/grit/generated_resources.h" #include "components/content_settings/browser/ui/cookie_controls_controller.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/web_contents.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/gfx/geometry/size.h"
diff --git a/chrome/browser/ui/views/safe_browsing/OWNERS b/chrome/browser/ui/views/safe_browsing/OWNERS index 70e4b68..5225674 100644 --- a/chrome/browser/ui/views/safe_browsing/OWNERS +++ b/chrome/browser/ui/views/safe_browsing/OWNERS
@@ -1,3 +1 @@ -drubery@chromium.org -nparker@chromium.org -vakh@chromium.org +file://components/safe_browsing/OWNERS
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_constants.h b/chrome/browser/ui/views/side_panel/read_anything/read_anything_constants.h index 8da26fc3..d7425f1d 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_constants.h +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_constants.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_UI_VIEWS_SIDE_PANEL_READ_ANYTHING_READ_ANYTHING_CONSTANTS_H_ #define CHROME_BROWSER_UI_VIEWS_SIDE_PANEL_READ_ANYTHING_READ_ANYTHING_CONSTANTS_H_ +#include "third_party/skia/include/core/SkColor.h" + // Various constants used throughout the Read Anything feature. namespace { @@ -15,6 +17,7 @@ const int kButtonPadding = 8; const int kSmallIconSize = 18; const int kLargeIconSize = 20; +const int kColorsIconSize = 24; const char kReadAnythingDefaultFontName[] = "Standard font"; @@ -26,6 +29,11 @@ const double kReadAnythingMinimumFontScale = 0.2; const double kReadAnythingMaximumFontScale = 5.0; +// Custom feature colors. +constexpr SkColor kReadAnythingDarkBackground = SkColorSetRGB(0x33, 0x36, 0x39); +constexpr SkColor kReadAnythingYellowForeground = + SkColorSetRGB(0x4E, 0x3F, 0x6C); + } // namespace #endif // CHROME_BROWSER_UI_VIEWS_SIDE_PANEL_READ_ANYTHING_READ_ANYTHING_CONSTANTS_H_
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.cc index d71e4ca..b19df309 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.cc
@@ -29,6 +29,10 @@ DistillAXTree(); } +/////////////////////////////////////////////////////////////////////////////// +// ReadAnythingFontCombobox::Delegate: +/////////////////////////////////////////////////////////////////////////////// + void ReadAnythingController::OnFontChoiceChanged(int new_choice) { model_->SetSelectedFontByIndex(new_choice); @@ -38,9 +42,13 @@ } ui::ComboboxModel* ReadAnythingController::GetFontComboboxModel() { - return static_cast<ui::ComboboxModel*>(model_->GetFontModel()); + return model_->GetFontModel(); } +/////////////////////////////////////////////////////////////////////////////// +// ReadAnythingToolbarView::Delegate: +/////////////////////////////////////////////////////////////////////////////// + void ReadAnythingController::OnFontSizeChanged(bool increase) { if (increase) { model_->IncreaseTextSize(); @@ -52,6 +60,20 @@ prefs::kAccessibilityReadAnythingFontScale, model_->GetFontScale()); } +void ReadAnythingController::OnColorsChanged(int new_index) { + model_->SetSelectedColorsByIndex(new_index); + + // TODO(crbug.com/1266555): Save color choice to prefs here. +} + +ui::ComboboxModel* ReadAnythingController::GetColorsModel() { + return model_->GetColorsModel(); +} + +/////////////////////////////////////////////////////////////////////////////// +// ReadAnythingPageHandler::Delegate: +/////////////////////////////////////////////////////////////////////////////// + void ReadAnythingController::OnUIReady() { ui_ready_ = true; DistillAXTree(); @@ -61,6 +83,10 @@ ui_ready_ = false; } +/////////////////////////////////////////////////////////////////////////////// +// TabStripModelObserver: +/////////////////////////////////////////////////////////////////////////////// + void ReadAnythingController::OnTabStripModelChanged( TabStripModel* tab_strip_model, const TabStripModelChange& change, @@ -79,6 +105,10 @@ browser_ = nullptr; } +/////////////////////////////////////////////////////////////////////////////// +// content::WebContentsObserver: +/////////////////////////////////////////////////////////////////////////////// + void ReadAnythingController::DidStopLoading() { DistillAXTree(); } @@ -87,6 +117,8 @@ active_contents_ = nullptr; } +/////////////////////////////////////////////////////////////////////////////// + void ReadAnythingController::DistillAXTree() { DCHECK(browser_); if (!active_ || !ui_ready_)
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.h b/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.h index 99392ff..9585e0b5 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.h +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.h
@@ -52,13 +52,15 @@ private: friend class ReadAnythingControllerTest; - // ReadAnythingToolbarView::Delegate: - void OnFontSizeChanged(bool increase) override; - // ReadAnythingFontCombobox::Delegate: void OnFontChoiceChanged(int new_choice) override; ui::ComboboxModel* GetFontComboboxModel() override; + // ReadAnythingToolbarView::Delegate: + void OnFontSizeChanged(bool increase) override; + void OnColorsChanged(int new_index) override; + ui::ComboboxModel* GetColorsModel() override; + // ReadAnythingPageHandler::Delegate: void OnUIReady() override; void OnUIDestroyed() override;
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_coordinator.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_coordinator.cc index e4cc294..54fd25f 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_coordinator.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_coordinator.cc
@@ -43,6 +43,8 @@ prefs_font_scale = browser->profile()->GetPrefs()->GetDouble( prefs::kAccessibilityReadAnythingFontScale); + // TODO(crbug.com/1266555): Add initial color values fetched from Prefs. + model_->Init( /* font name = */ prefs_font_name, /* font scale = */ prefs_font_scale);
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc index f0d6533..d1317d4 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc
@@ -8,17 +8,24 @@ #include <utility> #include "base/check.h" -#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/views/side_panel/read_anything/read_anything_constants.h" +#include "chrome/grit/component_extension_resources.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/base/models/image_model.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/color_palette.h" +#include "ui/gfx/image/image_skia.h" +#include "ui/gfx/image/image_skia_operations.h" using read_anything::mojom::ReadAnythingTheme; ReadAnythingModel::ReadAnythingModel() : font_name_(kReadAnythingDefaultFontName), font_scale_(kReadAnythingDefaultFontScale), - font_model_(std::make_unique<ReadAnythingFontModel>()) {} + font_model_(std::make_unique<ReadAnythingFontModel>()), + colors_model_(std::make_unique<ReadAnythingColorsModel>()) {} ReadAnythingModel::~ReadAnythingModel() = default; @@ -31,6 +38,8 @@ } font_scale_ = font_scale; + foreground_color_ = SkColors::kBlack.toSkColor(); + background_color_ = SkColors::kWhite.toSkColor(); } void ReadAnythingModel::AddObserver(Observer* obs) { @@ -52,6 +61,17 @@ NotifyThemeChanged(); } +void ReadAnythingModel::SetSelectedColorsByIndex(size_t new_index) { + // Check that the index is valid. + DCHECK(colors_model_->IsValidColorsIndex(new_index)); + + auto& new_colors = colors_model_->GetColorsAt(new_index); + foreground_color_ = new_colors.foreground; + background_color_ = new_colors.background; + + NotifyThemeChanged(); +} + void ReadAnythingModel::SetDistilledAXTree( ui::AXTreeUpdate snapshot, std::vector<ui::AXNodeID> content_node_ids) { @@ -87,10 +107,15 @@ void ReadAnythingModel::NotifyThemeChanged() { for (Observer& obs : observers_) { obs.OnThemeChanged(ReadAnythingTheme::New( - font_name_, kReadAnythingDefaultFontSize * font_scale_)); + font_name_, kReadAnythingDefaultFontSize * font_scale_, + foreground_color_, background_color_)); } } +/////////////////////////////////////////////////////////////////////////////// +// ReadAnythingFontModel +/////////////////////////////////////////////////////////////////////////////// + ReadAnythingFontModel::ReadAnythingFontModel() { font_choices_.emplace_back(u"Standard font"); font_choices_.emplace_back(u"Sans-serif"); @@ -155,3 +180,70 @@ } ReadAnythingFontModel::~ReadAnythingFontModel() = default; + +/////////////////////////////////////////////////////////////////////////////// +// ReadAnythingColorsModel +/////////////////////////////////////////////////////////////////////////////// + +ReadAnythingColorsModel::ReadAnythingColorsModel() { + // Define the possible sets of colors available to the user. + // TODO (crbug.com/1266555): Define default colors from system theme. + ColorInfo kDefaultColors = {u"Default", IDS_READ_ANYTHING_DEFAULT_PNG, + SkColors::kBlack.toSkColor(), + SkColors::kWhite.toSkColor()}; + + ColorInfo kLightColors = {u"Light", IDS_READ_ANYTHING_LIGHT_PNG, + gfx::kGoogleGrey900, gfx::kGoogleGrey050}; + + ColorInfo kDarkColors = {u"Dark", IDS_READ_ANYTHING_DARK_PNG, + gfx::kGoogleGrey200, kReadAnythingDarkBackground}; + + ColorInfo kYellowColors = {u"Yellow", IDS_READ_ANYTHING_YELLOW_PNG, + kReadAnythingYellowForeground, + gfx::kGoogleYellow200}; + + colors_choices_.emplace_back(kDefaultColors); + colors_choices_.emplace_back(kLightColors); + colors_choices_.emplace_back(kDarkColors); + colors_choices_.emplace_back(kYellowColors); + colors_choices_.shrink_to_fit(); +} +bool ReadAnythingColorsModel::IsValidColorsIndex(size_t index) { + return index < GetItemCount(); +} + +ReadAnythingColorsModel::ColorInfo& ReadAnythingColorsModel::GetColorsAt( + size_t index) { + return colors_choices_[index]; +} + +absl::optional<size_t> ReadAnythingColorsModel::GetDefaultIndex() const { + return default_index_; +} + +size_t ReadAnythingColorsModel::GetItemCount() const { + return colors_choices_.size(); +} + +ui::ImageModel ReadAnythingColorsModel::GetIconAt(size_t index) const { + const gfx::ImageSkia* icon_skia_asset = + ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( + colors_choices_[index].icon_asset); + DCHECK(icon_skia_asset); + + return ui::ImageModel::FromImageSkia( + gfx::ImageSkiaOperations::CreateResizedImage( + *icon_skia_asset, skia::ImageOperations::ResizeMethod::RESIZE_GOOD, + gfx::Size(kColorsIconSize, kColorsIconSize))); +} + +std::u16string ReadAnythingColorsModel::GetItemAt(size_t index) const { + // Only display the icon choice in the toolbar, so suppress name here. + return u""; +} + +std::u16string ReadAnythingColorsModel::GetDropDownTextAt(size_t index) const { + return colors_choices_[index].name; +} + +ReadAnythingColorsModel::~ReadAnythingColorsModel() = default;
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.h b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.h index add6e27..97b2696 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.h +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.h
@@ -12,6 +12,7 @@ #include "base/observer_list.h" #include "base/observer_list_types.h" #include "chrome/common/accessibility/read_anything.mojom.h" +#include "third_party/skia/include/core/SkColor.h" #include "ui/accessibility/ax_node_id_forward.h" #include "ui/accessibility/ax_tree_update.h" #include "ui/base/models/combobox_model.h" @@ -52,6 +53,54 @@ }; /////////////////////////////////////////////////////////////////////////////// +// ReadAnythingColorsModel +// +// A class that stores the data for the colors combobox. +// This class is owned by the ReadAnythingModel and has the same lifetime as +// the browser. +// +class ReadAnythingColorsModel : public ui::ComboboxModel { + public: + ReadAnythingColorsModel(); + ReadAnythingColorsModel(const ReadAnythingColorsModel&) = delete; + ReadAnythingColorsModel& operator=(const ReadAnythingColorsModel&) = delete; + ~ReadAnythingColorsModel() override; + + // Simple struct to hold the various colors to keep code cleaner. + struct ColorInfo { + // The name of the colors, e.g. Default, Light, Dark. + std::u16string name; + + // The resources value/identifier for the icon image asset. + int icon_asset; + + // The foreground color, used for text and icon hints. + SkColor foreground; + + // The background color, used for text background. + SkColor background; + }; + + bool IsValidColorsIndex(size_t index); + ColorInfo& GetColorsAt(size_t index); + + protected: + // ui::Combobox implementation: + absl::optional<size_t> GetDefaultIndex() const override; + size_t GetItemCount() const override; + ui::ImageModel GetIconAt(size_t index) const override; + std::u16string GetItemAt(size_t index) const override; + std::u16string GetDropDownTextAt(size_t index) const override; + + private: + // Individual combobox choices for colors presented in front-end. + std::vector<ColorInfo> colors_choices_; + + // Default index for drop down, either zero or populated from prefs. + size_t default_index_ = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// // ReadAnythingModel // // A class that stores data for the Read Anything feature. @@ -85,9 +134,11 @@ void SetSelectedFontByIndex(size_t new_index); void DecreaseTextSize(); void IncreaseTextSize(); + void SetSelectedColorsByIndex(size_t new_index); ReadAnythingFontModel* GetFontModel() { return font_model_.get(); } double GetFontScale() { return font_scale_; } + ReadAnythingColorsModel* GetColorsModel() { return colors_model_.get(); } private: void NotifyAXTreeDistilled(); @@ -97,6 +148,8 @@ // Members of read_anything::mojom::ReadAnythingTheme: std::string font_name_; + SkColor foreground_color_; + SkColor background_color_; // A scale multiplier for font size (internal use only, not shown to user). float font_scale_; @@ -108,6 +161,7 @@ base::ObserverList<Observer> observers_; const std::unique_ptr<ReadAnythingFontModel> font_model_; + const std::unique_ptr<ReadAnythingColorsModel> colors_model_; }; #endif // CHROME_BROWSER_UI_VIEWS_SIDE_PANEL_READ_ANYTHING_READ_ANYTHING_MODEL_H_
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model_unittest.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model_unittest.cc index d3de682..c8f85ec2 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model_unittest.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model_unittest.cc
@@ -126,6 +126,14 @@ EXPECT_NEAR(model_->GetFontScale(), 1.2, 0.01); } +TEST_F(ReadAnythingModelTest, NotificationsOnSetSelectedColorsIndex) { + model_->AddObserver(&model_observer_1_); + + EXPECT_CALL(model_observer_1_, OnThemeChanged(_)).Times(1); + + model_->SetSelectedColorsByIndex(2); +} + TEST_F(ReadAnythingModelTest, MinimumFontScaleIsEnforced) { std::string font_name; model_->Init(font_name, 0.3);
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.cc index 3638e98d..250d702c 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.cc
@@ -20,6 +20,7 @@ #include "ui/gfx/paint_vector_icon.h" #include "ui/views/background.h" #include "ui/views/controls/button/image_button_factory.h" +#include "ui/views/controls/combobox/combobox.h" #include "ui/views/controls/highlight_path_generator.h" #include "ui/views/controls/separator.h" #include "ui/views/layout/box_layout.h" @@ -42,7 +43,8 @@ SetLayoutManager(std::move(layout)); - // Create a font selection combobox for the toolbar. + // Create a font selection combobox for the toolbar. The font combobox uses + // a custom MenuModel, so we have a separate View for it for convenience. auto combobox = std::make_unique<ReadAnythingFontCombobox>(font_combobox_delegate); @@ -63,12 +65,23 @@ l10n_util::GetStringUTF16( IDS_READ_ANYTHING_INCREASE_FONT_SIZE_BUTTON_LABEL)); + // Create theme selection combobox. + auto colors_combobox = std::make_unique<views::Combobox>(); + colors_combobox->SetModel(delegate_->GetColorsModel()); + colors_combobox->SetTooltipTextAndAccessibleName( + l10n_util::GetStringUTF16(IDS_READ_ANYTHING_COLORS_COMBOBOX_LABEL)); + colors_combobox->SetSizeToLargestLabel(true); + colors_combobox->SetCallback( + base::BindRepeating(&ReadAnythingToolbarView::ChangeColorsCallback, + weak_pointer_factory_.GetWeakPtr())); + // Add all views as children. font_combobox_ = AddChildView(std::move(combobox)); AddChildView(Separator()); decrease_text_size_button_ = AddChildView(std::move(decrease_size_button)); increase_text_size_button_ = AddChildView(std::move(increase_size_button)); AddChildView(Separator()); + colors_combobox_ = AddChildView(std::move(colors_combobox)); } void ReadAnythingToolbarView::DecreaseFontSizeCallback() { @@ -81,6 +94,12 @@ delegate_->OnFontSizeChanged(/* increase = */ true); } +void ReadAnythingToolbarView::ChangeColorsCallback() { + if (delegate_) + delegate_->OnColorsChanged( + colors_combobox_->GetSelectedIndex().value_or(0)); +} + void ReadAnythingToolbarView::OnCoordinatorDestroyed() { // When the coordinator that created |this| is destroyed, clean up pointers. coordinator_ = nullptr;
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.h b/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.h index 1238329..c01f769 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.h +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view.h
@@ -27,6 +27,8 @@ class Delegate { public: virtual void OnFontSizeChanged(bool increase) = 0; + virtual void OnColorsChanged(int new_index) = 0; + virtual ui::ComboboxModel* GetColorsModel() = 0; }; ReadAnythingToolbarView( @@ -45,6 +47,7 @@ void DecreaseFontSizeCallback(); void IncreaseFontSizeCallback(); + void ChangeColorsCallback(); // views::View: void GetAccessibleNodeData(ui::AXNodeData* node_data) override; @@ -54,6 +57,8 @@ raw_ptr<views::Combobox> font_combobox_; raw_ptr<ReadAnythingButtonView> decrease_text_size_button_; raw_ptr<ReadAnythingButtonView> increase_text_size_button_; + raw_ptr<views::Combobox> colors_combobox_; + raw_ptr<ReadAnythingToolbarView::Delegate> delegate_; raw_ptr<ReadAnythingCoordinator> coordinator_;
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view_browsertest.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view_browsertest.cc index a7ce10d..22e4bf4 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view_browsertest.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_toolbar_view_browsertest.cc
@@ -17,6 +17,8 @@ : public ReadAnythingToolbarView::Delegate { public: MOCK_METHOD(void, OnFontSizeChanged, (bool increase), (override)); + MOCK_METHOD(void, OnColorsChanged, (int new_index), (override)); + MOCK_METHOD(ui::ComboboxModel*, GetColorsModel, (), (override)); }; class MockReadAnythingFontComboboxDelegate @@ -65,6 +67,8 @@ void IncreaseFontSizeCallback() { toolbar_view_->IncreaseFontSizeCallback(); } + void ChangeColorsCallback() { toolbar_view_->ChangeColorsCallback(); } + protected: MockReadAnythingToolbarViewDelegate toolbar_delegate_; MockReadAnythingFontComboboxDelegate font_combobox_delegate_; @@ -87,3 +91,9 @@ IncreaseFontSizeCallback(); } + +IN_PROC_BROWSER_TEST_F(ReadAnythingToolbarViewTest, ChangeColorsCallback) { + EXPECT_CALL(toolbar_delegate_, OnColorsChanged(0)).Times(1); + + ChangeColorsCallback(); +}
diff --git a/chrome/browser/ui/views/translate/partial_translate_bubble_view.cc b/chrome/browser/ui/views/translate/partial_translate_bubble_view.cc index 7138187..f8390d8 100644 --- a/chrome/browser/ui/views/translate/partial_translate_bubble_view.cc +++ b/chrome/browser/ui/views/translate/partial_translate_bubble_view.cc
@@ -433,6 +433,11 @@ tabbed_pane_->GetTabAt(1)->SetTitleText(target_language_name); model_->Translate(); tabbed_pane_->SelectTabAt(1); + + // Update max width of text selection label to match width of bubble, which + // changes with the lengths of the languages displayed in the tabbed pane. + partial_text_label_->SizeToFit( + tab_view_top_row_->GetPreferredSize().width()); SwitchView(PartialTranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE); if (from_source_language_view) { translate::ReportPartialTranslateBubbleUiAction( @@ -495,54 +500,18 @@ auto inner_view = std::make_unique<views::View>(); inner_view->SetLayoutManager(std::make_unique<views::FlexLayout>()) ->SetOrientation(views::LayoutOrientation::kHorizontal); - auto* horizontal_view = view->AddChildView(std::move(inner_view)); - - auto partial_text_row = std::make_unique<views::View>(); - partial_text_row->SetLayoutManager(std::make_unique<views::FlexLayout>()); - auto partial_text_label = std::make_unique<views::Label>( - text_selection_, views::style::CONTEXT_DIALOG_BODY_TEXT, - views::style::STYLE_PRIMARY); - const int vertical_spacing = - provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL); - partial_text_label->SetLineHeight(vertical_spacing * 5); - partial_text_label->SetHorizontalAlignment( - gfx::HorizontalAlignment::ALIGN_LEFT); - partial_text_label->SetProperty( - views::kFlexBehaviorKey, - views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero, - views::MaximumFlexSizeRule::kUnbounded)); - partial_text_label->SetProperty(views::kMarginsKey, - gfx::Insets::TLBR(0, 0, vertical_spacing, 0)); - partial_text_row->AddChildView(std::move(partial_text_label)); - view->AddChildView(std::move(partial_text_row)); - - // Button to trigger full page translation. - auto button_row = std::make_unique<views::BoxLayoutView>(); - button_row->SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kEnd); - auto full_page_button = std::make_unique<views::MdTextButton>( - base::BindRepeating(&PartialTranslateBubbleView::TranslateFullPage, - base::Unretained(this)), - l10n_util::GetStringUTF16( - IDS_PARTIAL_TRANSLATE_BUBBLE_TRANSLATE_FULL_PAGE)); - full_page_button->SetID(BUTTON_ID_FULL_PAGE_TRANSLATE); - button_row->AddChildView(std::move(full_page_button)); - button_row->SetProperty( - views::kMarginsKey, - gfx::Insets::TLBR(0, 0, 0, - provider->GetDistanceMetric( - views::DISTANCE_RELATED_CONTROL_HORIZONTAL))); - view->AddChildView(std::move(button_row)); + tab_view_top_row_ = view->AddChildView(std::move(inner_view)); views::View* icon = nullptr; if (!UseGoogleTranslateBranding()) { - icon = horizontal_view->AddChildView(CreateTranslateIcon()); + icon = tab_view_top_row_->AddChildView(CreateTranslateIcon()); } // Tabbed pane for language selection. Can't use unique_ptr because // tabs have to be added after the tabbed_pane is added to the parent, // when we release ownership of the unique_ptr. auto tabbed_pane = std::make_unique<views::TabbedPane>(); - tabbed_pane_ = horizontal_view->AddChildView(std::move(tabbed_pane)); + tabbed_pane_ = tab_view_top_row_->AddChildView(std::move(tabbed_pane)); // NOTE: Panes must be added after |tabbed_pane| has been added to its // parent. @@ -559,9 +528,10 @@ tabbed_pane_->set_listener(this); auto* padding_view = - horizontal_view->AddChildView(std::make_unique<views::View>()); - auto* options_menu = horizontal_view->AddChildView(CreateOptionsMenuButton()); - horizontal_view->AddChildView(CreateCloseButton()); + tab_view_top_row_->AddChildView(std::make_unique<views::View>()); + auto* options_menu = + tab_view_top_row_->AddChildView(CreateOptionsMenuButton()); + tab_view_top_row_->AddChildView(CreateCloseButton()); if (icon) { icon->SetProperty( @@ -585,6 +555,39 @@ gfx::Insets::VH(0, provider->GetDistanceMetric( views::DISTANCE_RELATED_BUTTON_HORIZONTAL))); + // Text selection. + auto partial_text_label = std::make_unique<views::Label>( + text_selection_, views::style::CONTEXT_DIALOG_BODY_TEXT, + views::style::STYLE_PRIMARY); + partial_text_label->SetMultiLine(true); + partial_text_label->SizeToFit(tab_view_top_row_->GetPreferredSize().width()); + + const int vertical_spacing = + provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL); + const int horizontal_spacing = + provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL); + partial_text_label->SetHorizontalAlignment( + gfx::HorizontalAlignment::ALIGN_LEFT); + partial_text_label->SetProperty( + views::kMarginsKey, + gfx::Insets::TLBR(vertical_spacing, 0, vertical_spacing, + horizontal_spacing)); + partial_text_label_ = view->AddChildView(std::move(partial_text_label)); + + // Button to trigger full page translation. + auto button_row = std::make_unique<views::BoxLayoutView>(); + button_row->SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kEnd); + auto full_page_button = std::make_unique<views::MdTextButton>( + base::BindRepeating(&PartialTranslateBubbleView::TranslateFullPage, + base::Unretained(this)), + l10n_util::GetStringUTF16( + IDS_PARTIAL_TRANSLATE_BUBBLE_TRANSLATE_FULL_PAGE)); + full_page_button->SetID(BUTTON_ID_FULL_PAGE_TRANSLATE); + button_row->AddChildView(std::move(full_page_button)); + button_row->SetProperty(views::kMarginsKey, + gfx::Insets::TLBR(0, 0, 0, horizontal_spacing)); + view->AddChildView(std::move(button_row)); + return view; } @@ -774,16 +777,18 @@ std::unique_ptr<views::Button> advanced_reset_button, std::unique_ptr<views::Button> advanced_done_button) { const ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); - auto view = std::make_unique<AdvancedViewContainer>(); - auto* layout = view->SetLayoutManager(std::make_unique<views::BoxLayout>()); - layout->set_between_child_spacing( - provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL)); - - std::unique_ptr<views::ImageView> language_icon = CreateTranslateIcon(); const int vertical_spacing = provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL); + const int horizontal_spacing = + provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL); + + auto view = std::make_unique<AdvancedViewContainer>(); + auto* layout = view->SetLayoutManager(std::make_unique<views::BoxLayout>()); + layout->set_between_child_spacing(horizontal_spacing); + + std::unique_ptr<views::ImageView> language_icon = CreateTranslateIcon(); if (!UseGoogleTranslateBranding()) { - // If the bottom branding isn't showing, display the leading translate + // If the bottom branding isn't showing, display the leading Translate // icon otherwise it's not obvious what the bubble is about. This should // only happen on non-Chrome-branded builds. auto* icon_view = @@ -794,6 +799,10 @@ gfx::Insets::VH(vertical_spacing, 0)); } auto* form_view = view->AddChildView(std::make_unique<views::View>()); + // Stretch |form_view| to fit the rest of bubble's width. Note that because no + // other view has flex set, the flex argument here can be any positive + // integer. + layout->SetFlexForView(form_view, 1); form_view->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kVertical, gfx::Insets(), vertical_spacing)); @@ -801,37 +810,43 @@ language_title_label->SetProperty( views::kMarginsKey, gfx::Insets::TLBR(vertical_spacing, 0, vertical_spacing, - provider->GetDistanceMetric( - views::DISTANCE_RELATED_CONTROL_HORIZONTAL) * - 4)); + horizontal_spacing * 4)); language_title_label->SetProperty(views::kCrossAxisAlignmentKey, views::LayoutAlignment::kStart); auto* title_row = form_view->AddChildView(std::make_unique<views::View>()); title_row->SetLayoutManager(std::make_unique<views::FlexLayout>()); - title_row->AddChildView(std::move(language_title_label)); + auto* title_label = title_row->AddChildView(std::move(language_title_label)); + auto* padding_view = title_row->AddChildView(std::make_unique<views::View>()); title_row->AddChildView(CreateCloseButton()) ->SetProperty(views::kCrossAxisAlignmentKey, views::LayoutAlignment::kStart); + // Set flex specifications for |title_row| views. + title_label->SetProperty( + views::kFlexBehaviorKey, + views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum, + views::MaximumFlexSizeRule::kPreferred)); + // |padding_view| is unbounded so that the close button stays right aligned + // when the bubble expands. + padding_view->SetProperty( + views::kFlexBehaviorKey, + views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero, + views::MaximumFlexSizeRule::kUnbounded) + .WithOrder(2)); form_view->AddChildView(std::move(combobox)) - ->SetProperty( - views::kMarginsKey, - gfx::Insets::TLBR(0, 0, 0, - provider->GetDistanceMetric( - views::DISTANCE_RELATED_CONTROL_HORIZONTAL))); + ->SetProperty(views::kMarginsKey, + gfx::Insets::TLBR(0, 0, 0, horizontal_spacing)); auto button_row = std::make_unique<views::BoxLayoutView>(); button_row->SetProperty(views::kMarginsKey, gfx::Insets::TLBR(2 * vertical_spacing, 0, 0, 0)); + button_row->SetProperty( + views::kMarginsKey, + gfx::Insets::TLBR(2 * vertical_spacing, 0, 0, horizontal_spacing)); button_row->SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kEnd); button_row->SetBetweenChildSpacing( provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL)); - button_row->SetProperty( - views::kMarginsKey, - gfx::Insets::TLBR(0, 0, 0, - provider->GetDistanceMetric( - views::DISTANCE_RELATED_CONTROL_HORIZONTAL))); button_row->AddChildView(std::move(advanced_reset_button)); button_row->AddChildView(std::move(advanced_done_button)); form_view->AddChildView(std::move(button_row));
diff --git a/chrome/browser/ui/views/translate/partial_translate_bubble_view.h b/chrome/browser/ui/views/translate/partial_translate_bubble_view.h index 20ab7b6..65f31c28 100644 --- a/chrome/browser/ui/views/translate/partial_translate_bubble_view.h +++ b/chrome/browser/ui/views/translate/partial_translate_bubble_view.h
@@ -227,6 +227,8 @@ raw_ptr<views::Combobox> target_language_combobox_ = nullptr; raw_ptr<views::TabbedPane> tabbed_pane_ = nullptr; + raw_ptr<views::View> tab_view_top_row_ = nullptr; + raw_ptr<views::Label> partial_text_label_ = nullptr; raw_ptr<views::LabelButton> advanced_reset_button_source_ = nullptr; raw_ptr<views::LabelButton> advanced_reset_button_target_ = nullptr;
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc index 1597648..3ee0eb4c 100644 --- a/chrome/browser/ui/views/translate/translate_bubble_view.cc +++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -875,16 +875,18 @@ std::unique_ptr<views::Button> advanced_done_button, std::unique_ptr<views::Checkbox> advanced_always_translate_checkbox) { const ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); - auto view = std::make_unique<AdvancedViewContainer>(); - auto* layout = view->SetLayoutManager(std::make_unique<views::BoxLayout>()); - layout->set_between_child_spacing( - provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL)); - - std::unique_ptr<views::ImageView> language_icon = CreateTranslateIcon(); const int vertical_spacing = provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL); + const int horizontal_spacing = + provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL); + + auto view = std::make_unique<AdvancedViewContainer>(); + auto* layout = view->SetLayoutManager(std::make_unique<views::BoxLayout>()); + layout->set_between_child_spacing(horizontal_spacing); + + std::unique_ptr<views::ImageView> language_icon = CreateTranslateIcon(); if (!UseGoogleTranslateBranding()) { - // If the bottom branding isn't showing, display the leading translate + // If the bottom branding isn't showing, display the leading Translate // icon otherwise it's not obvious what the bubble is about. This should // only happen on non-Chrome-branded builds. auto* icon_view = @@ -895,7 +897,9 @@ gfx::Insets::VH(vertical_spacing, 0)); } auto* form_view = view->AddChildView(std::make_unique<views::View>()); - // Stretch `form_view` to fit the rest of bubble's width. + // Stretch |form_view| to fit the rest of bubble's width. Note that because no + // other view has flex set, the flex argument here can be any positive + // integer. layout->SetFlexForView(form_view, 1); form_view->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kVertical, gfx::Insets(), @@ -904,44 +908,49 @@ language_title_label->SetProperty( views::kMarginsKey, gfx::Insets::TLBR(vertical_spacing, 0, vertical_spacing, - provider->GetDistanceMetric( - views::DISTANCE_RELATED_CONTROL_HORIZONTAL) * - 4)); + horizontal_spacing * 4)); language_title_label->SetProperty(views::kCrossAxisAlignmentKey, views::LayoutAlignment::kStart); auto* title_row = form_view->AddChildView(std::make_unique<views::View>()); title_row->SetLayoutManager(std::make_unique<views::FlexLayout>()); - title_row->AddChildView(std::move(language_title_label)); + auto* title_label = title_row->AddChildView(std::move(language_title_label)); + auto* padding_view = title_row->AddChildView(std::make_unique<views::View>()); title_row->AddChildView(CreateCloseButton()) ->SetProperty(views::kCrossAxisAlignmentKey, views::LayoutAlignment::kStart); + // Set flex specifications for |title_row| views. + title_label->SetProperty( + views::kFlexBehaviorKey, + views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum, + views::MaximumFlexSizeRule::kPreferred)); + // |padding_view| is unbounded so that the close button stays right aligned + // when the bubble expands. + padding_view->SetProperty( + views::kFlexBehaviorKey, + views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero, + views::MaximumFlexSizeRule::kUnbounded) + .WithOrder(2)); form_view->AddChildView(std::move(combobox)) - ->SetProperty( - views::kMarginsKey, - gfx::Insets::TLBR(0, 0, 0, - provider->GetDistanceMetric( - views::DISTANCE_RELATED_CONTROL_HORIZONTAL))); + ->SetProperty(views::kMarginsKey, + gfx::Insets::TLBR(0, 0, 0, horizontal_spacing)); auto button_row = std::make_unique<views::BoxLayoutView>(); if (advanced_always_translate_checkbox) { advanced_always_translate_checkbox_ = form_view->AddChildView(std::move(advanced_always_translate_checkbox)); - button_row->SetProperty(views::kMarginsKey, - gfx::Insets::TLBR(vertical_spacing, 0, 0, 0)); + button_row->SetProperty( + views::kMarginsKey, + gfx::Insets::TLBR(vertical_spacing, 0, 0, horizontal_spacing)); } else { - button_row->SetProperty(views::kMarginsKey, - gfx::Insets::TLBR(2 * vertical_spacing, 0, 0, 0)); + button_row->SetProperty( + views::kMarginsKey, + gfx::Insets::TLBR(2 * vertical_spacing, 0, 0, horizontal_spacing)); } button_row->SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kEnd); button_row->SetBetweenChildSpacing( provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL)); - button_row->SetProperty( - views::kMarginsKey, - gfx::Insets::TLBR(0, 0, 0, - provider->GetDistanceMetric( - views::DISTANCE_RELATED_CONTROL_HORIZONTAL))); button_row->AddChildView(std::move(advanced_reset_button)); button_row->AddChildView(std::move(advanced_done_button)); form_view->AddChildView(std::move(button_row));
diff --git a/chrome/browser/ui/webui/favicon_source_unittest.cc b/chrome/browser/ui/webui/favicon_source_unittest.cc index e876c54..64fadb2 100644 --- a/chrome/browser/ui/webui/favicon_source_unittest.cc +++ b/chrome/browser/ui/webui/favicon_source_unittest.cc
@@ -48,8 +48,6 @@ } // namespace -void Noop(scoped_refptr<base::RefCountedMemory>) {} - class MockHistoryUiFaviconRequestHandler : public favicon::HistoryUiFaviconRequestHandler { public: @@ -178,14 +176,14 @@ SetDarkMode(true); EXPECT_CALL(*source(), LoadIconBytes(_, IDR_DEFAULT_FAVICON_DARK)); source()->StartDataRequest(GURL(kDummyPrefix), test_web_contents_getter_, - base::BindOnce(&Noop)); + base::DoNothing()); } TEST_F(FaviconSourceTestWithLegacyFormat, LightDefault) { SetDarkMode(false); EXPECT_CALL(*source(), LoadIconBytes(_, IDR_DEFAULT_FAVICON)); source()->StartDataRequest(GURL(kDummyPrefix), test_web_contents_getter_, - base::BindOnce(&Noop)); + base::DoNothing()); } TEST_F(FaviconSourceTestWithLegacyFormat, @@ -199,7 +197,7 @@ source()->StartDataRequest( GURL(base::StrCat({kDummyPrefix, "size/16@1x/https://www.google.com"})), - test_web_contents_getter_, base::BindOnce(&Noop)); + test_web_contents_getter_, base::DoNothing()); } TEST_F(FaviconSourceTestWithLegacyFormat, @@ -232,7 +230,7 @@ base::HistogramTester tester; source()->StartDataRequest( GURL(base::StrCat({kDummyPrefix, "size/16@1x/https://www.google.com"})), - test_web_contents_getter_, base::BindOnce(&Noop)); + test_web_contents_getter_, base::DoNothing()); std::unique_ptr<base::HistogramSamples> samples( tester.GetHistogramSamplesSinceCreation( "Extensions.FaviconResourceUsed")); @@ -244,14 +242,14 @@ SetDarkMode(true); EXPECT_CALL(*source(), LoadIconBytes(_, IDR_DEFAULT_FAVICON_DARK)); source()->StartDataRequest(GURL(kDummyPrefix), test_web_contents_getter_, - base::BindOnce(&Noop)); + base::DoNothing()); } TEST_F(FaviconSourceTestWithFavicon2Format, LightDefault) { SetDarkMode(false); EXPECT_CALL(*source(), LoadIconBytes(_, IDR_DEFAULT_FAVICON)); source()->StartDataRequest(GURL(kDummyPrefix), test_web_contents_getter_, - base::BindOnce(&Noop)); + base::DoNothing()); } TEST_F(FaviconSourceTestWithFavicon2Format, @@ -268,7 +266,7 @@ {kDummyPrefix, "?size=16&scale_factor=1x&pageUrl=https%3A%2F%2Fwww.google." "com&allowGoogleServerFallback=0"})), - test_web_contents_getter_, base::BindOnce(&Noop)); + test_web_contents_getter_, base::DoNothing()); } TEST_F(FaviconSourceTestWithFavicon2Format, @@ -285,7 +283,7 @@ {kDummyPrefix, "?size=16&scale_factor=1x&pageUrl=https%3A%2F%2Fwww.google." "com&allowGoogleServerFallback=1"})), - test_web_contents_getter_, base::BindOnce(&Noop)); + test_web_contents_getter_, base::DoNothing()); } TEST_F( @@ -303,7 +301,7 @@ {kDummyPrefix, "?size=16&scale_factor=1x&pageUrl=https%3A%2F%2Fwww.google." "com&allowGoogleServerFallback=1"})), - test_web_contents_getter_, base::BindOnce(&Noop)); + test_web_contents_getter_, base::DoNothing()); } TEST_F(FaviconSourceTestWithFavicon2Format, @@ -317,5 +315,5 @@ // 100x scale factor runs into the max cap. source()->StartDataRequest( GURL(base::StrCat({kDummyPrefix, "size/16@100x/https://www.google.com"})), - test_web_contents_getter_, base::BindOnce(&Noop)); + test_web_contents_getter_, base::DoNothing()); }
diff --git a/chrome/browser/ui/webui/reset_password/OWNERS b/chrome/browser/ui/webui/reset_password/OWNERS index 6a739ea7..929be25 100644 --- a/chrome/browser/ui/webui/reset_password/OWNERS +++ b/chrome/browser/ui/webui/reset_password/OWNERS
@@ -1,6 +1,4 @@ per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS -drubery@chromium.org -nparker@chromium.org -vakh@chromium.org +file://components/safe_browsing/OWNERS
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index 9202fc2..9931520 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -1287,6 +1287,11 @@ autofill::payments::GetVirtualCardEnrollmentSupportUrl() .spec()))); + html_source->AddBoolean( + "virtualCardMetadataEnabled", + base::FeatureList::IsEnabled( + autofill::features::kAutofillEnableVirtualCardMetadata)); + html_source->AddLocalizedStrings(kLocalizedStrings); }
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc index 5775a96..ce1991c 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -60,6 +60,7 @@ #include "components/permissions/permission_decision_auto_blocker.h" #include "components/permissions/permission_uma_util.h" #include "components/permissions/test/object_permission_context_base_mock_permission_observer.h" +#include "components/permissions/test/permission_test_util.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" #include "components/services/app_service/public/cpp/app_types.h" #include "components/services/app_service/public/cpp/app_update.h" @@ -183,10 +184,7 @@ public: ContentSettingSourceSetter(TestingProfile* profile, ContentSettingsType content_type) - : prefs_(profile->GetTestingPrefService()), - host_content_settings_map_( - HostContentSettingsMapFactory::GetForProfile(profile)), - content_type_(content_type) {} + : prefs_(profile->GetTestingPrefService()), content_type_(content_type) {} ContentSettingSourceSetter(const ContentSettingSourceSetter&) = delete; ContentSettingSourceSetter& operator=(const ContentSettingSourceSetter&) = delete; @@ -209,7 +207,6 @@ private: raw_ptr<sync_preferences::TestingPrefServiceSyncable> prefs_; - raw_ptr<HostContentSettingsMap> host_content_settings_map_; ContentSettingsType content_type_; }; @@ -251,7 +248,11 @@ mock_privacy_sandbox_service_ = static_cast<MockPrivacySandboxService*>( PrivacySandboxServiceFactory::GetInstance()->SetTestingFactoryAndUse( profile(), base::BindRepeating(&BuildMockPrivacySandboxService))); - handler_ = std::make_unique<SiteSettingsHandler>(profile_.get()); + + profile()->SetPermissionControllerDelegate( + permissions::GetPermissionControllerDelegate(profile())); + + handler_ = std::make_unique<SiteSettingsHandler>(profile()); handler()->set_web_ui(web_ui()); handler()->AllowJavascript(); // AllowJavascript() adds a callback to create leveldb_env::ChromiumEnv
diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/browser/ui/webui/settings/site_settings_helper.cc index eab4779..af1fdcf 100644 --- a/chrome/browser/ui/webui/settings/site_settings_helper.cc +++ b/chrome/browser/ui/webui/settings/site_settings_helper.cc
@@ -23,7 +23,6 @@ #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/hid/hid_chooser_context.h" #include "chrome/browser/hid/hid_chooser_context_factory.h" -#include "chrome/browser/permissions/permission_manager_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/serial/serial_chooser_context.h" #include "chrome/browser/serial/serial_chooser_context_factory.h" @@ -40,7 +39,6 @@ #include "components/permissions/contexts/bluetooth_chooser_context.h" #include "components/permissions/object_permission_context_base.h" #include "components/permissions/permission_decision_auto_blocker.h" -#include "components/permissions/permission_manager.h" #include "components/permissions/permission_result.h" #include "components/permissions/permission_util.h" #include "components/permissions/permissions_client.h" @@ -49,11 +47,14 @@ #include "components/subresource_filter/content/browser/subresource_filter_profile_context.h" #include "components/subresource_filter/core/browser/subresource_filter_features.h" #include "components/url_formatter/url_formatter.h" +#include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "content/public/common/url_utils.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/constants.h" +#include "third_party/blink/public/common/permissions/permission_utils.h" #include "url/origin.h" namespace site_settings { @@ -733,9 +734,14 @@ if (permissions::PermissionDecisionAutoBlocker::IsEnabledForContentSetting( content_type)) { if (permissions::PermissionUtil::IsPermission(content_type)) { + content::PermissionResult permission_result = + profile->GetPermissionController() + ->GetPermissionResultForOriginWithoutContext( + permissions::PermissionUtil:: + ContentSettingTypeToPermissionType(content_type), + url::Origin::Create(origin)); result = - PermissionManagerFactory::GetForProfile(profile) - ->GetPermissionStatusForDisplayOnSettingsUI(content_type, origin); + permissions::PermissionUtil::ToPermissionResult(permission_result); } else { permissions::PermissionDecisionAutoBlocker* auto_blocker = permissions::PermissionsClient::Get()
diff --git a/chrome/browser/ui/webui/settings/site_settings_helper_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_helper_unittest.cc index 68f6e5f..e856371 100644 --- a/chrome/browser/ui/webui/settings/site_settings_helper_unittest.cc +++ b/chrome/browser/ui/webui/settings/site_settings_helper_unittest.cc
@@ -26,6 +26,7 @@ #include "components/permissions/object_permission_context_base.h" #include "components/permissions/permission_decision_auto_blocker.h" #include "components/permissions/permissions_client.h" +#include "components/permissions/test/permission_test_util.h" #include "components/prefs/pref_service.h" #include "content/public/test/browser_task_environment.h" #include "extensions/browser/extension_registry.h" @@ -416,6 +417,8 @@ // default, user-set pattern, user-set origin setting, extension, and policy. TEST_F(SiteSettingsHelperTest, ContentSettingSource) { TestingProfile profile; + profile.SetPermissionControllerDelegate( + permissions::GetPermissionControllerDelegate(&profile)); HostContentSettingsMap* map = HostContentSettingsMapFactory::GetForProfile(&profile);
diff --git a/chrome/browser/vr/ui_host/vr_ui_host_impl.cc b/chrome/browser/vr/ui_host/vr_ui_host_impl.cc index 2c842dc..365ba93 100644 --- a/chrome/browser/vr/ui_host/vr_ui_host_impl.cc +++ b/chrome/browser/vr/ui_host/vr_ui_host_impl.cc
@@ -9,7 +9,6 @@ #include "build/build_config.h" #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" -#include "chrome/browser/permissions/permission_manager_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" @@ -17,13 +16,13 @@ #include "chrome/browser/vr/vr_tab_helper.h" #include "chrome/browser/vr/win/vr_browser_renderer_thread_win.h" #include "components/content_settings/browser/page_specific_content_settings.h" -#include "components/permissions/permission_manager.h" -#include "components/permissions/permission_result.h" #include "content/public/browser/device_service.h" #include "content/public/browser/navigation_entry.h" +#include "content/public/browser/permission_controller.h" #include "content/public/browser/xr_runtime_manager.h" #include "device/base/features.h" #include "device/vr/public/mojom/vr_service.mojom.h" +#include "third_party/blink/public/common/permissions/permission_utils.h" #include "ui/base/l10n/l10n_util.h" namespace vr { @@ -352,33 +351,28 @@ potential_capturing_ = g_default_capturing_state; DCHECK(web_contents_); - permissions::PermissionManager* permission_manager = - PermissionManagerFactory::GetForProfile( - Profile::FromBrowserContext(web_contents_->GetBrowserContext())); + content::PermissionController* permission_controller = + web_contents_->GetBrowserContext()->GetPermissionController(); potential_capturing_.audio_capture_enabled = - permission_manager - ->GetPermissionStatusForCurrentDocument( - ContentSettingsType::MEDIASTREAM_MIC, - web_contents_->GetPrimaryMainFrame()) - .content_setting == CONTENT_SETTING_ALLOW; + permission_controller->GetPermissionStatusForCurrentDocument( + blink::PermissionType::AUDIO_CAPTURE, + web_contents_->GetPrimaryMainFrame()) == + blink::mojom::PermissionStatus::GRANTED; potential_capturing_.video_capture_enabled = - permission_manager - ->GetPermissionStatusForCurrentDocument( - ContentSettingsType::MEDIASTREAM_CAMERA, - web_contents_->GetPrimaryMainFrame()) - .content_setting == CONTENT_SETTING_ALLOW; + permission_controller->GetPermissionStatusForCurrentDocument( + blink::PermissionType::VIDEO_CAPTURE, + web_contents_->GetPrimaryMainFrame()) == + blink::mojom::PermissionStatus::GRANTED; potential_capturing_.location_access_enabled = - permission_manager - ->GetPermissionStatusForCurrentDocument( - ContentSettingsType::GEOLOCATION, - web_contents_->GetPrimaryMainFrame()) - .content_setting == CONTENT_SETTING_ALLOW; + permission_controller->GetPermissionStatusForCurrentDocument( + blink::PermissionType::GEOLOCATION, + web_contents_->GetPrimaryMainFrame()) == + blink::mojom::PermissionStatus::GRANTED; potential_capturing_.midi_connected = - permission_manager - ->GetPermissionStatusForCurrentDocument( - ContentSettingsType::MIDI_SYSEX, - web_contents_->GetPrimaryMainFrame()) - .content_setting == CONTENT_SETTING_ALLOW; + permission_controller->GetPermissionStatusForCurrentDocument( + blink::PermissionType::MIDI_SYSEX, + web_contents_->GetPrimaryMainFrame()) == + blink::mojom::PermissionStatus::GRANTED; indicators_shown_start_time_ = base::Time::Now(); indicators_visible_ = false;
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index bf3803f..2edfc19d 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1660219080-5c2d21bf4dd331c9b4e976e9165d27d27759ab52.profdata +chrome-linux-main-1660240770-a632af6c039f2ad4413e996af2f98bfc7f9434f2.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index c1f08ae3..1a3409c 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1660193600-2b7fa3816328527a7e00a736424cbd7cbf96c851.profdata +chrome-mac-main-1660240770-77ae20bf4e2aad589798cef67e057a2c4c231c49.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 64c1c351..b63ff69 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1660219080-817777645bb5a96bb8c86e7fa2a9003a46078df2.profdata +chrome-win32-main-1660229884-9bd506015e7ee89f769e0301f1c300238928a0c9.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index cf6749fe..661bf81 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1660229884-63764646f5a984f02a3c0edd8fa1017e1d45b5cf.profdata +chrome-win64-main-1660240770-0f7eb5b3d8c1500481b67b9d706ad42b10d14b1e.profdata
diff --git a/chrome/common/accessibility/read_anything.mojom b/chrome/common/accessibility/read_anything.mojom index 76b7fb0..1876292 100644 --- a/chrome/common/accessibility/read_anything.mojom +++ b/chrome/common/accessibility/read_anything.mojom
@@ -5,6 +5,7 @@ // A module for a prototype of the Read Anything feature. module read_anything.mojom; +import "skia/public/mojom/skcolor.mojom"; import "ui/accessibility/mojom/ax_tree_update.mojom"; // Used to represent the current user choices for the Read Anything visual @@ -15,6 +16,10 @@ // The px value of the user's font size. float font_size; + + // The various colors of the user's chosen theme. + skia.mojom.SkColor foreground_color; + skia.mojom.SkColor background_color; }; // Used by the WebUI page to bootstrap bidirectional communication.
diff --git a/chrome/common/safe_browsing/OWNERS b/chrome/common/safe_browsing/OWNERS index 89d2255..dcfaa52 100644 --- a/chrome/common/safe_browsing/OWNERS +++ b/chrome/common/safe_browsing/OWNERS
@@ -1,10 +1,4 @@ -drubery@chromium.org -nparker@chromium.org -vakh@chromium.org - -# This is for the common case of adding or renaming files. If you're doing -# structural changes, use usual OWNERS rules. -per-file BUILD.gn=* +file://components/safe_browsing/OWNERS per-file *_messages*.h=set noparent per-file *_messages*.h=file://ipc/SECURITY_OWNERS
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.cc b/chrome/renderer/accessibility/read_anything_app_controller.cc index dd0ed1c..ed197399 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller.cc +++ b/chrome/renderer/accessibility/read_anything_app_controller.cc
@@ -203,6 +203,8 @@ void ReadAnythingAppController::OnThemeChanged(ReadAnythingThemePtr new_theme) { font_name_ = new_theme->font_name; font_size_ = new_theme->font_size; + foreground_color_ = new_theme->foreground_color; + background_color_ = new_theme->background_color; // TODO(abigailbklein): Use v8::Function rather than javascript. If possible, // replace this function call with firing an event. @@ -217,6 +219,10 @@ .SetProperty("contentNodeIds", &ReadAnythingAppController::ContentNodeIds) .SetProperty("fontName", &ReadAnythingAppController::FontName) .SetProperty("fontSize", &ReadAnythingAppController::FontSize) + .SetProperty("foregroundColor", + &ReadAnythingAppController::ForegroundColor) + .SetProperty("backgroundColor", + &ReadAnythingAppController::BackgroundColor) .SetMethod("getChildren", &ReadAnythingAppController::GetChildren) .SetMethod("getHeadingLevel", &ReadAnythingAppController::GetHeadingLevel) .SetMethod("getTextContent", &ReadAnythingAppController::GetTextContent) @@ -244,6 +250,14 @@ return font_size_; } +SkColor ReadAnythingAppController::ForegroundColor() { + return foreground_color_; +} + +SkColor ReadAnythingAppController::BackgroundColor() { + return background_color_; +} + std::vector<ui::AXNodeID> ReadAnythingAppController::GetChildren( ui::AXNodeID ax_node_id) { std::vector<ui::AXNodeID> child_ids; @@ -318,8 +332,11 @@ } void ReadAnythingAppController::SetThemeForTesting(const std::string& font_name, - float font_size) { - OnThemeChanged(ReadAnythingTheme::New(font_name, font_size)); + float font_size, + SkColor foreground_color, + SkColor background_color) { + OnThemeChanged(ReadAnythingTheme::New(font_name, font_size, foreground_color, + background_color)); } void ReadAnythingAppController::SetContentForTesting(
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.h b/chrome/renderer/accessibility/read_anything_app_controller.h index a9dc29f..9e2e452 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller.h +++ b/chrome/renderer/accessibility/read_anything_app_controller.h
@@ -13,6 +13,7 @@ #include "gin/wrappable.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" +#include "third_party/skia/include/core/SkColor.h" #include "ui/accessibility/ax_node_id_forward.h" #include "ui/accessibility/ax_tree_update_forward.h" @@ -73,6 +74,8 @@ std::vector<ui::AXNodeID> ContentNodeIds(); std::string FontName(); float FontSize(); + SkColor ForegroundColor(); + SkColor BackgroundColor(); std::vector<ui::AXNodeID> GetChildren(ui::AXNodeID ax_node_id); uint32_t GetHeadingLevel(ui::AXNodeID ax_node_id); std::string GetTextContent(ui::AXNodeID ax_node_id); @@ -102,7 +105,10 @@ // }; void SetContentForTesting(v8::Local<v8::Value> v8_snapshot_lite, std::vector<ui::AXNodeID> content_node_ids); - void SetThemeForTesting(const std::string& font_name, float font_size); + void SetThemeForTesting(const std::string& font_name, + float font_size, + SkColor foreground_color, + SkColor background_color); ui::AXNode* GetAXNode(ui::AXNodeID ax_node_id); @@ -116,6 +122,8 @@ std::vector<ui::AXNodeID> content_node_ids_; std::string font_name_; float font_size_; + SkColor foreground_color_; + SkColor background_color_; }; #endif // CHROME_RENDERER_ACCESSIBILITY_READ_ANYTHING_APP_CONTROLLER_H_
diff --git a/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc index 9d4a93f2..a74b356d 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc +++ b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc
@@ -34,8 +34,12 @@ basic_snapshot_.nodes[3].id = 4; } - void SetThemeForTesting(const std::string& font_name, float font_size) { - controller_->SetThemeForTesting(font_name, font_size); + void SetThemeForTesting(const std::string& font_name, + float font_size, + SkColor foreground_color, + SkColor background_color) { + controller_->SetThemeForTesting(font_name, font_size, foreground_color, + background_color); } void OnAXTreeDistilled(const ui::AXTreeUpdate& snapshot, const std::vector<ui::AXNodeID>& content_node_ids) { @@ -50,6 +54,10 @@ float FontSize() { return controller_->FontSize(); } + SkColor ForegroundColor() { return controller_->ForegroundColor(); } + + SkColor BackgroundColor() { return controller_->BackgroundColor(); } + std::vector<ui::AXNodeID> GetChildren(ui::AXNodeID ax_node_id) { return controller_->GetChildren(ax_node_id); } @@ -93,9 +101,13 @@ TEST_F(ReadAnythingAppControllerTest, Theme) { std::string font_name = "Roboto"; float font_size = 18.0; - SetThemeForTesting(font_name, font_size); + SkColor foreground = SkColorSetRGB(0x33, 0x36, 0x39); + SkColor background = SkColorSetRGB(0xFD, 0xE2, 0x93); + SetThemeForTesting(font_name, font_size, foreground, background); EXPECT_EQ(font_name, FontName()); EXPECT_EQ(font_size, FontSize()); + EXPECT_EQ(foreground, ForegroundColor()); + EXPECT_EQ(background, BackgroundColor()); } TEST_F(ReadAnythingAppControllerTest, ContentNodeIds) {
diff --git a/chrome/renderer/cart/commerce_hint_agent.cc b/chrome/renderer/cart/commerce_hint_agent.cc index 99dc734..c006dce3 100644 --- a/chrome/renderer/cart/commerce_hint_agent.cc +++ b/chrome/renderer/cart/commerce_hint_agent.cc
@@ -809,10 +809,12 @@ javascript_request_ = new JavaScriptRequest(weak_factory_.GetWeakPtr()); } main_frame->RequestExecuteScript( - ISOLATED_WORLD_ID_CHROME_INTERNAL, base::make_span(&source, 1), false, - blink::WebLocalFrame::kAsynchronous, javascript_request_, + ISOLATED_WORLD_ID_CHROME_INTERNAL, base::make_span(&source, 1), + blink::mojom::UserActivationOption::kDoNotActivate, + blink::mojom::EvaluationTiming::kAsynchronous, + blink::mojom::LoadEventBlockingOption::kDoNotBlock, javascript_request_, blink::BackForwardCacheAware::kAllow, - blink::WebLocalFrame::PromiseBehavior::kAwait); + blink::mojom::PromiseResultOption::kAwait); } CommerceHintAgent::JavaScriptRequest::JavaScriptRequest(
diff --git a/chrome/renderer/safe_browsing/OWNERS b/chrome/renderer/safe_browsing/OWNERS index 70e4b68..5225674 100644 --- a/chrome/renderer/safe_browsing/OWNERS +++ b/chrome/renderer/safe_browsing/OWNERS
@@ -1,3 +1 @@ -drubery@chromium.org -nparker@chromium.org -vakh@chromium.org +file://components/safe_browsing/OWNERS
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index dfcafe6..86d187f 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -299,7 +299,6 @@ "//net:test_support", "//ppapi/buildflags", "//printing/buildflags", - "//services/cert_verifier:test_support", "//services/data_decoder/public/cpp:test_support", "//services/device/public/cpp:test_support", "//services/device/public/cpp/geolocation", @@ -5508,9 +5507,12 @@ ] if (!is_android) { - # The test is disabled for Android. The respective functionality is currently not being used on - # Android. We should enable this test when Android becomes supported. - sources += [ "../browser/policy/messaging_layer/util/reporting_server_connector_unittest.cc" ] + sources += [ + # The test is disabled for Android. The respective functionality is currently not being used on + # Android. We should enable this test when Android becomes supported. + "../browser/performance_manager/metrics/metrics_provider_unittest.cc", + "../browser/policy/messaging_layer/util/reporting_server_connector_unittest.cc", + ] } if (enable_feed_v2) { @@ -6536,6 +6538,8 @@ "../browser/performance_manager/test_support/page_discarding_utils.h", "../browser/performance_manager/test_support/site_data_utils.cc", "../browser/performance_manager/test_support/site_data_utils.h", + "../browser/performance_manager/user_tuning/fake_frame_throttling_delegate.cc", + "../browser/performance_manager/user_tuning/fake_frame_throttling_delegate.h", "../browser/platform_util_unittest.cc", "../browser/policy/policy_path_parser_unittest.cc", "../browser/policy/serial_allow_usb_devices_for_urls_policy_handler_unittest.cc", @@ -9320,6 +9324,7 @@ "//components/javascript_dialogs", "//components/keep_alive_registry", "//components/live_caption", + "//components/live_caption:constants", "//components/media_message_center", "//components/media_router/browser:test_support", "//components/metrics:content",
diff --git a/chrome/test/chromedriver/BUILD.gn b/chrome/test/chromedriver/BUILD.gn index 68fe940..eaa7ad9 100644 --- a/chrome/test/chromedriver/BUILD.gn +++ b/chrome/test/chromedriver/BUILD.gn
@@ -59,6 +59,24 @@ args += rebase_path(ts_files, root_build_dir) } +action("embed_bidimapper_in_cpp") { + script = "embed_bidimapper_in_cpp.py" + + js_files = [ "//third_party/bidimapper/mapper.js" ] + + inputs = [ "cpp_source.py" ] + js_files + + outputs = [ + "$target_gen_dir/bidimapper/bidimapper.cc", + "$target_gen_dir/bidimapper/bidimapper.h", + ] + args = [ + "--directory", + rebase_path("$target_gen_dir/bidimapper", root_build_dir), + ] + args += rebase_path(js_files, root_build_dir) +} + action("embed_user_data_dir_in_cpp") { script = "embed_user_data_dir_in_cpp.py" @@ -86,6 +104,8 @@ "chrome/adb.h", "chrome/adb_impl.cc", "chrome/adb_impl.h", + "chrome/bidi_tracker.cc", + "chrome/bidi_tracker.h", "chrome/browser_info.cc", "chrome/browser_info.h", "chrome/cast_tracker.cc", @@ -196,9 +216,11 @@ # Also compile the generated files. sources += get_target_outputs(":embed_js_in_cpp") sources += get_target_outputs(":embed_mobile_devices_in_cpp") + sources += get_target_outputs(":embed_bidimapper_in_cpp") sources += get_target_outputs(":embed_user_data_dir_in_cpp") deps = [ + ":embed_bidimapper_in_cpp", ":embed_js_in_cpp", ":embed_mobile_devices_in_cpp", ":embed_user_data_dir_in_cpp",
diff --git a/chrome/test/chromedriver/chrome/bidi_tracker.cc b/chrome/test/chromedriver/chrome/bidi_tracker.cc new file mode 100644 index 0000000..d293cd1 --- /dev/null +++ b/chrome/test/chromedriver/chrome/bidi_tracker.cc
@@ -0,0 +1,54 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/test/chromedriver/chrome/bidi_tracker.h" + +#include <stddef.h> + +#include <utility> + +#include "base/logging.h" +#include "base/values.h" +#include "chrome/test/chromedriver/chrome/devtools_client.h" +#include "chrome/test/chromedriver/chrome/status.h" + +BidiTracker::BidiTracker() = default; + +BidiTracker::~BidiTracker() = default; + +bool BidiTracker::ListensToConnections() const { + return false; +} + +Status BidiTracker::OnEvent(DevToolsClient* client, + const std::string& method, + const base::DictionaryValue& params) { + if (method != "Runtime.bindingCalled") { + return Status(kOk); + } + + const base::Value* nameVal = params.FindKey("name"); + if (nameVal == nullptr) { + return Status(kUnknownError, "Runtime.bindingCalled missing 'name'"); + } + std::string name = nameVal->GetString(); + if (name != "sendBidiResponse") { + // We are not interested in this function call + return Status(kOk); + } + + const base::Value* payloadVal = params.FindKey("payload"); + if (payloadVal == nullptr) { + return Status(kUnknownError, "Runtime.bindingCalled missing 'payload'"); + } + + std::string payload = payloadVal->GetString(); + send_bidi_response_.Run(payload); + + return Status(kOk); +} + +void BidiTracker::SetBidiCallback(SendTextFunc on_bidi_message) { + send_bidi_response_ = std::move(on_bidi_message); +}
diff --git a/chrome/test/chromedriver/chrome/bidi_tracker.h b/chrome/test/chromedriver/chrome/bidi_tracker.h new file mode 100644 index 0000000..a84d8e9 --- /dev/null +++ b/chrome/test/chromedriver/chrome/bidi_tracker.h
@@ -0,0 +1,44 @@ +// Copyright (c) 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_TEST_CHROMEDRIVER_CHROME_BIDI_TRACKER_H_ +#define CHROME_TEST_CHROMEDRIVER_CHROME_BIDI_TRACKER_H_ + +#include <map> +#include <string> + +#include "base/callback.h" +#include "chrome/test/chromedriver/chrome/devtools_event_listener.h" + +namespace base { +class DictionaryValue; +} + +class DevToolsClient; +class Status; +typedef base::RepeatingCallback<void(const std::string&)> SendTextFunc; + +// Tracks the state of the DOM and BiDi messages coming from the browser +class BidiTracker : public DevToolsEventListener { + public: + BidiTracker(); + + BidiTracker(const BidiTracker&) = delete; + BidiTracker& operator=(const BidiTracker&) = delete; + + ~BidiTracker() override; + + // Overridden from DevToolsEventListener: + bool ListensToConnections() const override; + Status OnEvent(DevToolsClient* client, + const std::string& method, + const base::DictionaryValue& params) override; + + void SetBidiCallback(SendTextFunc on_bidi_message); + + private: + SendTextFunc send_bidi_response_; +}; + +#endif // CHROME_TEST_CHROMEDRIVER_CHROME_BIDI_TRACKER_H_
diff --git a/chrome/test/chromedriver/chrome/chrome_impl.cc b/chrome/test/chromedriver/chrome/chrome_impl.cc index 31a797c3..d8dd0767 100644 --- a/chrome/test/chromedriver/chrome/chrome_impl.cc +++ b/chrome/test/chromedriver/chrome/chrome_impl.cc
@@ -792,6 +792,10 @@ return status; } +DevToolsClient* ChromeImpl::Client() const { + return devtools_websocket_client_.get(); +} + ChromeImpl::ChromeImpl(std::unique_ptr<DevToolsHttpClient> http_client, std::unique_ptr<DevToolsClient> websocket_client, std::vector<std::unique_ptr<DevToolsEventListener>>
diff --git a/chrome/test/chromedriver/chrome/chrome_impl.h b/chrome/test/chromedriver/chrome/chrome_impl.h index 1403f07..47d276a 100644 --- a/chrome/test/chromedriver/chrome/chrome_impl.h +++ b/chrome/test/chromedriver/chrome/chrome_impl.h
@@ -59,6 +59,7 @@ bool HasTouchScreen() const override; std::string page_load_strategy() const override; Status Quit() override; + DevToolsClient* Client() const; protected: ChromeImpl(std::unique_ptr<DevToolsHttpClient> http_client,
diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl.cc b/chrome/test/chromedriver/chrome/devtools_client_impl.cc index faa3c81..4bf3c89 100644 --- a/chrome/test/chromedriver/chrome/devtools_client_impl.cc +++ b/chrome/test/chromedriver/chrome/devtools_client_impl.cc
@@ -422,7 +422,7 @@ // but return timeout status if primary timeout has expired // This supports cases when loading state is updated by a different client Timeout funcinterval = Timeout(base::Milliseconds(500), &timeout); - Status status = ProcessNextMessage(-1, false, funcinterval); + Status status = ProcessNextMessage(-1, false, funcinterval, this); if (status.code() == kTimeout) { if (timeout.IsExpired()) { // Build status message based on timeout parameter, not funcinterval @@ -524,7 +524,7 @@ // Use a long default timeout if user has not requested one. Status status = ProcessNextMessage( command_id, true, - timeout != nullptr ? *timeout : Timeout(base::Minutes(10))); + timeout != nullptr ? *timeout : Timeout(base::Minutes(10)), this); if (status.IsError()) { if (response_info->state == kReceived) response_info_map_.erase(command_id); @@ -561,7 +561,8 @@ Status DevToolsClientImpl::ProcessNextMessage(int expected_id, bool log_timeout, - const Timeout& timeout) { + const Timeout& timeout, + DevToolsClientImpl* caller) { ScopedIncrementer increment_stack_count(&stack_count_); DCHECK(IsConnected()); @@ -591,7 +592,7 @@ return Status(kTargetDetached); if (parent_ != nullptr) - return parent_->ProcessNextMessage(-1, log_timeout, timeout); + return parent_->ProcessNextMessage(-1, log_timeout, timeout, caller); std::string message; switch (socket_->ReceiveNextMessage(&message, timeout)) { @@ -615,11 +616,12 @@ break; } - return HandleMessage(expected_id, message); + return HandleMessage(expected_id, message, caller); } Status DevToolsClientImpl::HandleMessage(int expected_id, - const std::string& message) { + const std::string& message, + DevToolsClientImpl* caller) { std::string session_id; internal::InspectorMessageType type; internal::InspectorEvent event; @@ -643,10 +645,46 @@ } WebViewImplHolder client_holder(client->owner_); if (type == internal::kEventMessageType) { - return client->ProcessEvent(event); + Status status = client->ProcessEvent(event); + if (caller == client || this == client) { + // In either case we are in the root. + // 'this == client' means that the error has happened in the browser + // session. Any errors happening here are global and most likely will lead + // to the session termination. Forward them to the caller! + // 'caller == client' means that the message must be routed to the + // same client that invoked the current root. Sending the errors + // to the caller is the proper behavior in this case as well. + return status; + } else { + // We support active event consumption meaning that the whole session + // makes progress independently from the active WebDriver Classic target. + // This is needed for timely delivery of bidi events to the user. + // If something wrong happens in the different target the corresponding + // WebView must update its state accordingly to notify the user + // about the issue on the next HTTP request. + return Status{kOk}; + } } CHECK_EQ(type, internal::kCommandResponseMessageType); - return client->ProcessCommandResponse(response); + Status status = client->ProcessCommandResponse(response); + if (caller == client || this == client) { + // In either case we are in the root. + // 'this == client' means that the error has happened in the browser + // session. Any errors happening here are global and most likely will lead + // to the session termination. Forward them to the caller! + // 'caller == client' means that the message must be routed to the + // same client that invoked the current root. Sending the errors + // to the caller is the proper behavior in this case as well. + return status; + } else { + // We support active event consumption meaning that the whole session + // makes progress independently from the active WebDriver Classic target. + // This is needed for timely delivery of bidi events to the user. + // If something wrong happens in the different target the corresponding + // WebView must update its state accordingly to notify the user + // about the issue on the next HTTP request. + return Status{kOk}; + } } Status DevToolsClientImpl::ProcessEvent(const internal::InspectorEvent& event) {
diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl.h b/chrome/test/chromedriver/chrome/devtools_client_impl.h index ecc9431..f2eb3d9 100644 --- a/chrome/test/chromedriver/chrome/devtools_client_impl.h +++ b/chrome/test/chromedriver/chrome/devtools_client_impl.h
@@ -188,8 +188,11 @@ const Timeout* timeout); Status ProcessNextMessage(int expected_id, bool log_timeout, - const Timeout& timeout); - Status HandleMessage(int expected_id, const std::string& message); + const Timeout& timeout, + DevToolsClientImpl* caller); + Status HandleMessage(int expected_id, + const std::string& message, + DevToolsClientImpl* caller); Status ProcessEvent(const internal::InspectorEvent& event); Status ProcessCommandResponse( const internal::InspectorCommandResponse& response); @@ -228,6 +231,7 @@ int stack_count_; bool is_remote_end_configured_; bool is_main_page_; + base::WeakPtrFactory<DevToolsClientImpl> weak_ptr_factory_{this}; }; namespace internal {
diff --git a/chrome/test/chromedriver/chrome/stub_web_view.cc b/chrome/test/chromedriver/chrome/stub_web_view.cc index f121289..c82ee98 100644 --- a/chrome/test/chromedriver/chrome/stub_web_view.cc +++ b/chrome/test/chromedriver/chrome/stub_web_view.cc
@@ -28,6 +28,11 @@ return Status(kOk); } +Status StubWebView::HandleEventsUntil(const ConditionalFunc& conditional_func, + const Timeout& timeout) { + return Status{kOk}; +} + Status StubWebView::HandleReceivedEvents() { return Status(kOk); }
diff --git a/chrome/test/chromedriver/chrome/stub_web_view.h b/chrome/test/chromedriver/chrome/stub_web_view.h index 95500112..9d3744e 100644 --- a/chrome/test/chromedriver/chrome/stub_web_view.h +++ b/chrome/test/chromedriver/chrome/stub_web_view.h
@@ -20,6 +20,8 @@ std::string GetId() override; bool WasCrashed() override; Status ConnectIfNecessary() override; + Status HandleEventsUntil(const ConditionalFunc& conditional_func, + const Timeout& timeout) override; Status HandleReceivedEvents() override; Status GetUrl(std::string* url) override; Status Load(const std::string& url, const Timeout* timeout) override;
diff --git a/chrome/test/chromedriver/chrome/web_view.h b/chrome/test/chromedriver/chrome/web_view.h index 42a0cae..87024dd 100644 --- a/chrome/test/chromedriver/chrome/web_view.h +++ b/chrome/test/chromedriver/chrome/web_view.h
@@ -9,6 +9,7 @@ #include <string> #include <vector> +#include "base/callback_forward.h" #include "base/values.h" namespace base { @@ -31,7 +32,10 @@ class WebView { public: - virtual ~WebView() {} + typedef base::RepeatingCallback<Status(bool* is_condition_met)> + ConditionalFunc; + + virtual ~WebView() = default; virtual bool IsServiceWorker() const = 0; @@ -44,6 +48,14 @@ // Make DevToolsCient connect to DevTools if it is disconnected. virtual Status ConnectIfNecessary() = 0; + // Handles events until the given function reports the condition is met + // and there are no more received events to handle. If the given + // function ever returns an error, returns immediately with the error. + // If the condition is not met within |timeout|, kTimeout status + // is returned eventually. If |timeout| is 0, this function will not block. + virtual Status HandleEventsUntil(const ConditionalFunc& conditional_func, + const Timeout& timeout) = 0; + // Handles events that have been received but not yet handled. virtual Status HandleReceivedEvents() = 0;
diff --git a/chrome/test/chromedriver/chrome/web_view_impl.cc b/chrome/test/chromedriver/chrome/web_view_impl.cc index d87652c3..0c6c71f1 100644 --- a/chrome/test/chromedriver/chrome/web_view_impl.cc +++ b/chrome/test/chromedriver/chrome/web_view_impl.cc
@@ -442,6 +442,11 @@ ->AttachTo(static_cast<DevToolsClientImpl*>(parent)); } +Status WebViewImpl::HandleEventsUntil(const ConditionalFunc& conditional_func, + const Timeout& timeout) { + return client_->HandleEventsUntil(conditional_func, timeout); +} + Status WebViewImpl::HandleReceivedEvents() { return client_->HandleReceivedEvents(); }
diff --git a/chrome/test/chromedriver/chrome/web_view_impl.h b/chrome/test/chromedriver/chrome/web_view_impl.h index ac21a312..61661f5 100644 --- a/chrome/test/chromedriver/chrome/web_view_impl.h +++ b/chrome/test/chromedriver/chrome/web_view_impl.h
@@ -57,6 +57,8 @@ bool WasCrashed() override; Status ConnectIfNecessary() override; Status AttachTo(DevToolsClient* parent); + Status HandleEventsUntil(const ConditionalFunc& conditional_func, + const Timeout& timeout) override; Status HandleReceivedEvents() override; Status GetUrl(std::string* url) override; Status Load(const std::string& url, const Timeout* timeout) override;
diff --git a/chrome/test/chromedriver/client/chromedriver.py b/chrome/test/chromedriver/client/chromedriver.py index d2af048..6c92488 100644 --- a/chrome/test/chromedriver/client/chromedriver.py +++ b/chrome/test/chromedriver/client/chromedriver.py
@@ -13,63 +13,13 @@ from webelement import WebElement from webshadowroot import WebShadowRoot from websocket_connection import WebSocketConnection +from exceptions import * ELEMENT_KEY_W3C = "element-6066-11e4-a52e-4f735466cecf" ELEMENT_KEY = "ELEMENT" SHADOW_KEY = "shadow-6066-11e4-a52e-4f735466cecf" MAX_RETRY_COUNT = 5 -class ChromeDriverException(Exception): - pass -class NoSuchElement(ChromeDriverException): - pass -class NoSuchFrame(ChromeDriverException): - pass -class UnknownCommand(ChromeDriverException): - pass -class StaleElementReference(ChromeDriverException): - pass -class ElementNotVisible(ChromeDriverException): - pass -class InvalidElementState(ChromeDriverException): - pass -class UnknownError(ChromeDriverException): - pass -class JavaScriptError(ChromeDriverException): - pass -class XPathLookupError(ChromeDriverException): - pass -class Timeout(ChromeDriverException): - pass -class NoSuchWindow(ChromeDriverException): - pass -class InvalidCookieDomain(ChromeDriverException): - pass -class ScriptTimeout(ChromeDriverException): - pass -class InvalidSelector(ChromeDriverException): - pass -class SessionNotCreated(ChromeDriverException): - pass -class InvalidSessionId(ChromeDriverException): - pass -class UnexpectedAlertOpen(ChromeDriverException): - pass -class NoSuchAlert(ChromeDriverException): - pass -class NoSuchCookie(ChromeDriverException): - pass -class InvalidArgument(ChromeDriverException): - pass -class ElementNotInteractable(ChromeDriverException): - pass -class UnsupportedOperation(ChromeDriverException): - pass -class NoSuchShadowRoot(ChromeDriverException): - pass -class DetachedShadowRoot(ChromeDriverException): - pass - def _ExceptionForLegacyResponse(response): exception_class_map = { 6: InvalidSessionId, @@ -788,4 +738,9 @@ params = {'vendorId': vendorId} return self.ExecuteCommand(Command.GET_CAST_SINKS, params) + def __enter__(self): + return self + + def __exit__(self, *args): + self.Quit()
diff --git a/chrome/test/chromedriver/client/exceptions.py b/chrome/test/chromedriver/client/exceptions.py new file mode 100644 index 0000000..c275d88 --- /dev/null +++ b/chrome/test/chromedriver/client/exceptions.py
@@ -0,0 +1,60 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +class ChromeDriverException(Exception): + pass +class NoSuchElement(ChromeDriverException): + pass +class NoSuchFrame(ChromeDriverException): + pass +class UnknownCommand(ChromeDriverException): + pass +class StaleElementReference(ChromeDriverException): + pass +class ElementNotVisible(ChromeDriverException): + pass +class InvalidElementState(ChromeDriverException): + pass +class UnknownError(ChromeDriverException): + pass +class JavaScriptError(ChromeDriverException): + pass +class XPathLookupError(ChromeDriverException): + pass +class Timeout(ChromeDriverException): + pass +class NoSuchWindow(ChromeDriverException): + pass +class InvalidCookieDomain(ChromeDriverException): + pass +class ScriptTimeout(ChromeDriverException): + pass +class InvalidSelector(ChromeDriverException): + pass +class SessionNotCreated(ChromeDriverException): + pass +class InvalidSessionId(ChromeDriverException): + pass +class UnexpectedAlertOpen(ChromeDriverException): + pass +class NoSuchAlert(ChromeDriverException): + pass +class NoSuchCookie(ChromeDriverException): + pass +class InvalidArgument(ChromeDriverException): + pass +class ElementNotInteractable(ChromeDriverException): + pass +class UnsupportedOperation(ChromeDriverException): + pass +class NoSuchShadowRoot(ChromeDriverException): + pass +class DetachedShadowRoot(ChromeDriverException): + pass +class WebSocketException(ChromeDriverException): + pass +class WebSocketConnectionClosedException(WebSocketException): + pass +class WebSocketTimeoutException(WebSocketException): + pass \ No newline at end of file
diff --git a/chrome/test/chromedriver/client/websocket_connection.py b/chrome/test/chromedriver/client/websocket_connection.py index 8db4369..87ff1517 100644 --- a/chrome/test/chromedriver/client/websocket_connection.py +++ b/chrome/test/chromedriver/client/websocket_connection.py
@@ -2,9 +2,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import json import os import sys -import json +import time from command_executor import CommandExecutor _THIS_DIR = os.path.abspath(os.path.dirname(__file__)) @@ -17,6 +18,11 @@ 'websocket-client')) import websocket +from websocket import WebSocketConnectionClosedException as InternalWebSocketConnectionClosedException +from websocket import WebSocketTimeoutException as InternalWebSocketTimeoutException +from exceptions import WebSocketConnectionClosedException +from exceptions import WebSocketTimeoutException + class WebSocketCommands: CREATE_WEBSOCKET = \ '/session/:sessionId' @@ -27,19 +33,57 @@ def __init__(self, server_url, session_id): self._server_url = server_url.replace('http', 'ws') self._session_id = session_id - self._command_id = -1 + self._command_id = 0 cmd_params = {'sessionId': session_id} path = CommandExecutor.CreatePath( WebSocketCommands.CREATE_WEBSOCKET, cmd_params) self._websocket = websocket.create_connection(self._server_url + path) + self._responses = {} def SendCommand(self, cmd_params): + self._command_id = self._command_id + 1 cmd_params['id'] = self._command_id - self._command_id -= 1 - self._websocket.send(json.dumps(cmd_params)) + try: + self._websocket.send(json.dumps(cmd_params)) + except InternalWebSocketTimeoutException: + raise WebSocketTimeoutException() + return self._command_id - def ReadMessage(self): - return self._websocket.recv() + def WaitForResponse(self, command_id): + if command_id in self._responses: + msg = self._responses[command_id] + del self._responses[command_id] + return msg + + start = time.monotonic() + timeout = self.GetTimeout() + + try: + while True: + msg = json.loads(self._websocket.recv()) + if 'id' in msg: + if msg['id'] == command_id: + return msg + elif msg['id'] >= 0: + self._responses[msg['id']] = msg + if start + timeout <= time.monotonic(): + raise TimeoutError() + except InternalWebSocketConnectionClosedException: + raise WebSocketConnectionClosedException() + except InternalWebSocketTimeoutException: + raise WebSocketTimeoutException() def Close(self): self._websocket.close(); + + def __enter__(self): + return self + + def __exit__(self, *args): + self.Close() + + def GetTimeout(self): + return self._websocket.gettimeout() + + def SetTimeout(self, timeout_seconds): + self._websocket.settimeout(timeout_seconds)
diff --git a/chrome/test/chromedriver/commands.cc b/chrome/test/chromedriver/commands.cc index 12b91bad..c0844c8 100644 --- a/chrome/test/chromedriver/commands.cc +++ b/chrome/test/chromedriver/commands.cc
@@ -202,6 +202,7 @@ void ExecuteSessionCommandOnSessionThread( const char* command_name, + const std::string& session_id, const SessionCommand& command, bool w3c_standard_command, bool return_ok_without_session, @@ -217,7 +218,7 @@ base::BindOnce( callback_on_cmd, Status(return_ok_without_session ? kOk : kInvalidSessionId), - std::unique_ptr<base::Value>(), std::string(), kW3CDefault)); + std::unique_ptr<base::Value>(), session_id, kW3CDefault)); return; } @@ -317,6 +318,7 @@ session->id, session->w3c_compliant)); if (session->quit) { + session->CloseAllConnections(); SetThreadLocalSession(std::unique_ptr<Session>()); delete session; cmd_task_runner->PostTask(FROM_HERE, terminate_on_cmd); @@ -342,8 +344,8 @@ iter->second->thread()->task_runner()->PostTask( FROM_HERE, base::BindOnce( - &ExecuteSessionCommandOnSessionThread, command_name, command, - w3c_standard_command, return_ok_without_session, + &ExecuteSessionCommandOnSessionThread, command_name, session_id, + command, w3c_standard_command, return_ok_without_session, base::DictionaryValue::From( base::Value::ToUniquePtrValue(params.Clone())), base::ThreadTaskRunnerHandle::Get(), callback,
diff --git a/chrome/test/chromedriver/embed_bidimapper_in_cpp.py b/chrome/test/chromedriver/embed_bidimapper_in_cpp.py new file mode 100755 index 0000000..0b0a1a4 --- /dev/null +++ b/chrome/test/chromedriver/embed_bidimapper_in_cpp.py
@@ -0,0 +1,43 @@ +#!/usr/bin/env python +# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Embeds standalone JavaScript snippets in C++ code. + +Each argument to the script must be a file containing an associated JavaScript +function (e.g., evaluate_script.js should contain an evaluateScript function). +This is called the exported function of the script. The entire script will be +put into a C-style string in the form of an anonymous function which invokes +the exported function when called. +""" + +import optparse +import os +import sys + +import cpp_source + + +def main(): + parser = optparse.OptionParser() + parser.add_option( + '', '--directory', type='string', default='.', + help='Path to directory where the cc/h js file should be created') + options, args = parser.parse_args() + + global_string_map = {} + for js_file in args: + base_name = os.path.basename(js_file)[:-3].title().replace('_', '') + func_name = base_name[0].lower() + base_name[1:] + script_name = 'k%sScript' % base_name + with open(js_file, 'r') as f: + contents = f.read() + global_string_map[script_name] = contents + + cpp_source.WriteSource('bidimapper', 'chrome/test/chromedriver/bidimapper', + options.directory, global_string_map) + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/chrome/test/chromedriver/server/chromedriver_server.cc b/chrome/test/chromedriver/server/chromedriver_server.cc index 848b2ad5..cd4fae86 100644 --- a/chrome/test/chromedriver/server/chromedriver_server.cc +++ b/chrome/test/chromedriver/server/chromedriver_server.cc
@@ -336,8 +336,8 @@ "add readable timestamps to log", "enable-chrome-logs", "show logs from the browser (overrides other logging options)", -// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch -// of lacros-chrome is complete. + // TODO(crbug.com/1052397): Revisit the macro expression once build flag + // switch of lacros-chrome is complete. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) "disable-dev-shm-usage", "do not use /dev/shm "
diff --git a/chrome/test/chromedriver/server/http_handler.cc b/chrome/test/chromedriver/server/http_handler.cc index 31426db..b68cc8e0 100644 --- a/chrome/test/chromedriver/server/http_handler.cc +++ b/chrome/test/chromedriver/server/http_handler.cc
@@ -11,6 +11,7 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/callback_forward.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/logging.h" // For CHECK macros. @@ -66,13 +67,82 @@ return kW3CDefault; } -net::HttpServerResponseInfo createWebSocketRejectResponse( +net::HttpServerResponseInfo CreateWebSocketRejectResponse( net::HttpStatusCode code, const std::string& msg) { net::HttpServerResponseInfo response(code); response.AddHeader("X-WebSocket-Reject-Reason", msg); return response; } + +void SendWebSocketResponseOnCmdThread( + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + HttpServer* http_server, + int connection_id, + const std::string& data) { + io_task_runner->PostTask( + FROM_HERE, + base::BindOnce(&HttpServer::SendOverWebSocket, + base::Unretained(http_server), connection_id, data)); +} + +void SendWebSocketResponseOnSessionThread( + scoped_refptr<base::SingleThreadTaskRunner> cmd_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + HttpServer* http_server, + int connection_id, + const std::string& data) { + cmd_task_runner->PostTask( + FROM_HERE, + base::BindOnce(&SendWebSocketResponseOnCmdThread, io_task_runner, + base::Unretained(http_server), connection_id, data)); +} + +void CloseWebSocketOnCmdThread( + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + HttpServer* http_server, + int connection_id) { + io_task_runner->PostTask( + FROM_HERE, base::BindOnce(&HttpServer::Close, + base::Unretained(http_server), connection_id)); +} + +void CloseWebSocketOnSessionThread( + scoped_refptr<base::SingleThreadTaskRunner> cmd_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + HttpServer* http_server, + int connection_id) { + cmd_task_runner->PostTask( + FROM_HERE, base::BindOnce(&CloseWebSocketOnCmdThread, io_task_runner, + base::Unretained(http_server), connection_id)); +} + +void AddBidiConnectionOnSessionThread(int connection_id, + SendTextFunc send_response, + CloseFunc close_connection) { + Session* session = GetThreadLocalSession(); + // session == nullptr is a valid case: ExecuteQuit has already been handled + // in the session thread but the following + // TerminateSessionThreadOnCommandThread has not yet been executed (the latter + // destroys the session thread) The connection has already been accepted by + // the CMD thread but soon it will be closed. We don't need to do anything. + if (session != nullptr) { + session->AddBidiConnection(connection_id, std::move(send_response), + std::move(close_connection)); + } +} + +void RemoveBidiConnectionOnSessionThread(int connection_id) { + Session* session = GetThreadLocalSession(); + // session == nullptr is a valid case: ExecuteQuit has already been handled + // in the session thread but the following + // TerminateSessionThreadOnCommandThread has not yet been executed (the latter + // destroys the session thread) + if (session != nullptr) { + session->RemoveBidiConnection(connection_id); + } +} + } // namespace // WrapperURLLoaderFactory subclasses mojom::URLLoaderFactory as non-mojo, cross @@ -152,6 +222,7 @@ int adb_port) : quit_func_(quit_func), io_task_runner_(io_task_runner), + cmd_task_runner_(cmd_task_runner), url_base_(url_base), received_shutdown_(false) { #if BUILDFLAG(IS_MAC) @@ -1398,20 +1469,143 @@ } else { session_connection_map_[session_id] = connection_id; connection_session_map_[connection_id] = session_id; - io_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&HttpServer::AcceptWebSocket, - base::Unretained(http_server), connection_id, info)); + + auto thread_it = session_thread_map_.find(session_id); + // check first that the session thread is still alive + if (thread_it != session_thread_map_.end()) { + auto send_response_from_seq = base::BindRepeating( + &SendWebSocketResponseOnSessionThread, cmd_task_runner_, + io_task_runner_, base::Unretained(http_server), connection_id); + + auto close_from_seq = base::BindRepeating( + &CloseWebSocketOnSessionThread, cmd_task_runner_, io_task_runner_, + base::Unretained(http_server), connection_id); + + thread_it->second->thread()->task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&AddBidiConnectionOnSessionThread, connection_id, + std::move(send_response_from_seq), + std::move(close_from_seq))); + + io_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&HttpServer::AcceptWebSocket, + base::Unretained(http_server), connection_id, info)); + } else { + std::string err_msg = "session not found session_id=" + session_id; + VLOG(0) << "HttpHandler WebSocketRequest error " << err_msg; + SendWebSocketRejectResponse(http_server, connection_id, + net::HTTP_BAD_REQUEST, err_msg); + } } } +void HttpHandler::OnWebSocketMessage(HttpServer* http_server, + int connection_id, + const std::string& data) { + base::RepeatingCallback<void(const Status&)> send_error = base::BindRepeating( + [](HttpServer* http_server, int connection_id, const std::string& data, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + const Status& status) { + base::Value::Dict msg_dict; + msg_dict.Set("message", status.message()); + msg_dict.Set("error", StatusCodeToString(status.code())); + absl::optional<base::Value> value = + base::JSONReader::Read(data, base::JSON_PARSE_CHROMIUM_EXTENSIONS); + if (value && value->is_dict()) { + absl::optional<int> msg_id = value->GetDict().FindInt("id"); + if (msg_id) { + msg_dict.Set("id", *msg_id); + } else { + LOG(WARNING) << "BiDi command has no id"; + } + } else { + LOG(WARNING) << "BiDi command is not a JSON map"; + } + std::string error_message; + if (base::JSONWriter::Write(msg_dict, &error_message)) { + io_task_runner->PostTask( + FROM_HERE, base::BindOnce(&HttpServer::SendOverWebSocket, + base::Unretained(http_server), + connection_id, error_message)); + } else { + LOG(WARNING) << "unable to serialize BiDi error message"; + } + }, + http_server, connection_id, data, io_task_runner_); + + auto it = connection_session_map_.find(connection_id); + if (it == connection_session_map_.end()) { + // Session was terminated but the connection is not yet closed + send_error.Run(Status{kNoSuchFrame, "session not found"}); + return; + } + + std::string session_id = it->second; + + base::DictionaryValue params; + params.Set("bidiCommand", std::make_unique<base::Value>(data)); + + auto callback = base::BindRepeating( + [](base::RepeatingCallback<void(const Status&)> send_error, + const Status& status, std::unique_ptr<base::Value>, + const std::string& session_id, bool) { + if (status.IsOk()) { + return; + } + switch (status.code()) { + case kInvalidSessionId: { + // ExecuteSessionCommandOnSessionThread can return this error status + send_error.Run(Status{ + kNoSuchFrame, "session not found session_id=" + session_id}); + break; + } + default: { + send_error.Run(status); + break; + } + } + }, + send_error); + auto cmd = WrapToCommand("ExecuteBidiCommand", + base::BindRepeating(&ExecuteBidiCommand)); + cmd.Run(params, session_id, std::move(callback)); +} + +void HttpHandler::OnWebSocketResponseOnCmdThread(HttpServer* http_server, + int connection_id, + const std::string& data) { + io_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&HttpServer::SendOverWebSocket, + base::Unretained(http_server), connection_id, data)); +} + +void HttpHandler::OnWebSocketResponseOnSessionThread(HttpServer* http_server, + int connection_id, + const std::string& data) { + cmd_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&HttpHandler::OnWebSocketResponseOnCmdThread, WeakPtr(), + base::Unretained(http_server), connection_id, data)); +} + void HttpHandler::OnClose(HttpServer* http_server, int connection_id) { auto it = connection_session_map_.find(connection_id); if (it == connection_session_map_.end()) { return; } - session_connection_map_[it->second] = -1; + std::string session_id = it->second; + session_connection_map_[session_id] = -1; connection_session_map_.erase(it); + + auto thread_it = session_thread_map_.find(session_id); + // check first that the session thread is still alive + if (thread_it != session_thread_map_.end()) { + thread_it->second->thread()->task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&RemoveBidiConnectionOnSessionThread, connection_id)); + } } void HttpHandler::SendWebSocketRejectResponse(HttpServer* http_server, @@ -1422,7 +1616,7 @@ FROM_HERE, base::BindOnce(&HttpServer::SendResponse, base::Unretained(http_server), connection_id, - createWebSocketRejectResponse(net::HTTP_BAD_REQUEST, msg), + CreateWebSocketRejectResponse(net::HTTP_BAD_REQUEST, msg), TRAFFIC_ANNOTATION_FOR_TESTS)); }
diff --git a/chrome/test/chromedriver/server/http_handler.h b/chrome/test/chromedriver/server/http_handler.h index fa7aa05..9b18d0b 100644 --- a/chrome/test/chromedriver/server/http_handler.h +++ b/chrome/test/chromedriver/server/http_handler.h
@@ -135,6 +135,18 @@ int connection_id, const net::HttpServerRequestInfo& info); + void OnWebSocketMessage(HttpServer* http_server, + int connection_id, + const std::string& data); + + void OnWebSocketResponseOnCmdThread(HttpServer* http_server, + int connection_id, + const std::string& data); + + void OnWebSocketResponseOnSessionThread(HttpServer* http_server, + int connection_id, + const std::string& data); + void OnClose(HttpServer* http_server, int connection_id); void SendWebSocketRejectResponse(HttpServer* http_server, @@ -145,6 +157,7 @@ base::ThreadChecker thread_checker_; base::RepeatingClosure quit_func_; scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> cmd_task_runner_; std::string url_base_; bool received_shutdown_; scoped_refptr<URLRequestContextGetter> context_getter_;
diff --git a/chrome/test/chromedriver/server/http_server.cc b/chrome/test/chromedriver/server/http_server.cc index deb8d9a7..999aeaf6 100644 --- a/chrome/test/chromedriver/server/http_server.cc +++ b/chrome/test/chromedriver/server/http_server.cc
@@ -232,12 +232,9 @@ } void HttpServer::OnWebSocketMessage(int connection_id, std::string data) { - // TODO: Make use of WebSocket data - VLOG(0) << "HttpServer::OnWebSocketMessage received: " << data; - // https://crbug.com/chromedriver/3974 - // Response "not supported" to avoid WebSocket tests timeout. - server_->SendOverWebSocket(connection_id, "not supported", - TRAFFIC_ANNOTATION_FOR_TESTS); + cmd_runner_->PostTask( + FROM_HERE, base::BindOnce(&HttpHandler::OnWebSocketMessage, handler_, + this, connection_id, data)); } void HttpServer::OnClose(int connection_id) { @@ -246,6 +243,14 @@ base::BindOnce(&HttpHandler::OnClose, handler_, this, connection_id)); } +void HttpServer::Close(int connection_id) { + server_->Close(connection_id); +} + +void HttpServer::SendOverWebSocket(int connection_id, const std::string& data) { + server_->SendOverWebSocket(connection_id, data, TRAFFIC_ANNOTATION_FOR_TESTS); +} + void HttpServer::AcceptWebSocket(int connection_id, const net::HttpServerRequestInfo& request) { server_->AcceptWebSocket(connection_id, request,
diff --git a/chrome/test/chromedriver/server/http_server.h b/chrome/test/chromedriver/server/http_server.h index 01afb1d..1f9541a 100644 --- a/chrome/test/chromedriver/server/http_server.h +++ b/chrome/test/chromedriver/server/http_server.h
@@ -44,9 +44,13 @@ void OnClose(int connection_id) override; + void Close(int connection_id); + void AcceptWebSocket(int connection_id, const net::HttpServerRequestInfo& request); + void SendOverWebSocket(int connection_id, const std::string& data); + void SendResponse(int connection_id, const net::HttpServerResponseInfo& response, const net::NetworkTrafficAnnotationTag& traffic_annotation);
diff --git a/chrome/test/chromedriver/session.cc b/chrome/test/chromedriver/session.cc index d9a1cae..93346fa 100644 --- a/chrome/test/chromedriver/session.cc +++ b/chrome/test/chromedriver/session.cc
@@ -7,7 +7,9 @@ #include <list> #include <utility> +#include "base/json/json_reader.h" #include "base/lazy_instance.h" +#include "base/logging.h" #include "base/threading/thread_local.h" #include "base/values.h" #include "chrome/test/chromedriver/chrome/chrome.h" @@ -51,10 +53,24 @@ InputCancelListEntry::~InputCancelListEntry() = default; +BidiConnection::BidiConnection(int connection_id, + SendTextFunc send_response, + CloseFunc close_connection) + : connection_id(connection_id), + send_response(std::move(send_response)), + close_connection(std::move(close_connection)) {} + +BidiConnection::BidiConnection(BidiConnection&& other) = default; + +BidiConnection::~BidiConnection() = default; + +BidiConnection& BidiConnection::operator=(BidiConnection&& other) = default; + // The default timeout values came from W3C spec. const base::TimeDelta Session::kDefaultImplicitWaitTimeout = base::Seconds(0); const base::TimeDelta Session::kDefaultPageLoadTimeout = base::Seconds(300); const base::TimeDelta Session::kDefaultScriptTimeout = base::Seconds(30); +const int kBidiQueueCapacity = 20; Session::Session(const std::string& id) : id(id), @@ -142,6 +158,85 @@ } } +void Session::OnBidiResponse(const std::string& payload) { + if (payload == "{\"launched\":true}") { + // TODO(chromedriver:4180): Prohibit any user command handling before we + // receive the "launched" event from the BiDiMapper. + return; + } + + // If there is no active bidi connections the events will be accumulated. + bidi_response_queue_.push(payload); + for (; bidi_response_queue_.size() > kBidiQueueCapacity; + bidi_response_queue_.pop()) { + LOG(WARNING) << "BiDi response queue overflow, dropping the message: " + << bidi_response_queue_.front(); + } + ProcessBidiResponseQueue(); +} + +void Session::AddBidiConnection(int connection_id, + SendTextFunc send_response, + CloseFunc close_connection) { + bidi_connections_.emplace_back(connection_id, std::move(send_response), + std::move(close_connection)); + ProcessBidiResponseQueue(); +} + +void Session::RemoveBidiConnection(int connection_id) { + // Reallistically we will not have many connections, therefore linear search + // is optimal. + auto it = std::find_if(bidi_connections_.begin(), bidi_connections_.end(), + [connection_id](const auto& conn) { + return conn.connection_id == connection_id; + }); + if (it != bidi_connections_.end()) { + bidi_connections_.erase(it); + } +} + +void Session::ProcessBidiResponseQueue() { + if (bidi_connections_.empty() || bidi_response_queue_.empty()) { + return; + } + // Only single websocket connection is supported now. + DCHECK(bidi_connections_.size() == 1); + for (; !bidi_response_queue_.empty(); bidi_response_queue_.pop()) { + // TODO(chromedriver:4179): In the future we will support multiple + // connections. The payload will have to be parsed and routed to the + // appropriate connection. The events will have to be delivered to all + // connections. + for (const BidiConnection& conn : bidi_connections_) { + // If the callback fails (asynchronously) because the connection was + // broken we simply ignore this fact as the message cannot be delivered + // over that connection anyway. + std::string response = bidi_response_queue_.front(); + conn.send_response.Run(response); + absl::optional<base::Value> responseParsed = base::JSONReader::Read( + response, base::JSON_PARSE_CHROMIUM_EXTENSIONS); + if (responseParsed && responseParsed->is_dict()) { + absl::optional<int> response_id = + responseParsed->GetDict().FindInt("id"); + if (response_id && *response_id == awaited_bidi_response_id) { + VLOG(0) << "awaited response is received!"; + awaited_bidi_response_id = -1; + // No "id" means that we are dealing with an event + } + } else { + LOG(WARNING) << "BiDi response is not a map"; + } + } + } +} + +void Session::CloseAllConnections() { + for (BidiConnection& conn : bidi_connections_) { + // If the callback fails (asynchronously) because the connection was + // terminated we simply ignore this - it is already closed. + conn.close_connection.Run(); + } +} + Session* GetThreadLocalSession() { return lazy_tls_session.Pointer()->Get(); }
diff --git a/chrome/test/chromedriver/session.h b/chrome/test/chromedriver/session.h index 7a4bd6b..1a6f78e 100644 --- a/chrome/test/chromedriver/session.h +++ b/chrome/test/chromedriver/session.h
@@ -7,9 +7,11 @@ #include <list> #include <memory> +#include <queue> #include <string> #include <vector> +#include "base/callback.h" #include "base/memory/raw_ptr.h" #include "base/time/time.h" #include "base/values.h" @@ -64,6 +66,23 @@ std::unique_ptr<KeyEvent> key_event; }; +typedef base::RepeatingCallback<void(const std::string& /*payload*/)> + SendTextFunc; + +typedef base::RepeatingCallback<void()> CloseFunc; + +struct BidiConnection { + BidiConnection(int connection_id, + SendTextFunc send_response, + CloseFunc close_connection); + BidiConnection(BidiConnection&& other); + ~BidiConnection(); + BidiConnection& operator=(BidiConnection&& other); + int connection_id; + SendTextFunc send_response; + CloseFunc close_connection; +}; + struct Session { static const base::TimeDelta kDefaultImplicitWaitTimeout; static const base::TimeDelta kDefaultPageLoadTimeout; @@ -83,11 +102,19 @@ std::string GetCurrentFrameId() const; std::vector<WebDriverLog*> GetAllLogs() const; + void OnBidiResponse(const std::string& payload); + void AddBidiConnection(int connection_id, + SendTextFunc send_response, + CloseFunc close_connection); + void RemoveBidiConnection(int connection_id); + void CloseAllConnections(); + const std::string id; bool w3c_compliant; bool webSocketUrl = false; bool quit; bool detach; + int awaited_bidi_response_id = -1; std::unique_ptr<Chrome> chrome; std::string window; int sticky_modifiers; @@ -135,6 +162,19 @@ private: void SwitchFrameInternal(bool for_top_frame); + void ProcessBidiResponseQueue(); + + // TODO: for the moment being we support single connection per client + // In the future (2022Q4) we will probably support multiple bidi connections. + // In order to do that we can try either of the following approaches: + // * Create a separate CDP session per connection + // * Give some connection identifying context to the BiDiMapper. + // The context will travel between the BiDiMapper and ChromeDriver. + // * Store an internal map between CDP command id and connection. + std::vector<BidiConnection> bidi_connections_; + // If there is no active connections the messages from Chrome are accumulated + // in this queue until a connection is created or the queue overflows. + std::queue<std::string> bidi_response_queue_; }; Session* GetThreadLocalSession();
diff --git a/chrome/test/chromedriver/session_commands.cc b/chrome/test/chromedriver/session_commands.cc index d0784a2..2e84853 100644 --- a/chrome/test/chromedriver/session_commands.cc +++ b/chrome/test/chromedriver/session_commands.cc
@@ -6,11 +6,14 @@ #include <list> #include <memory> +#include <thread> #include <utility> #include "base/bind.h" #include "base/callback.h" #include "base/files/file_util.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" #include "base/logging.h" // For CHECK macros. #include "base/memory/ref_counted.h" #include "base/strings/string_util.h" @@ -22,12 +25,16 @@ #include "base/time/time.h" #include "base/values.h" #include "chrome/test/chromedriver/basic_types.h" +#include "chrome/test/chromedriver/bidimapper/bidimapper.h" #include "chrome/test/chromedriver/capabilities.h" +#include "chrome/test/chromedriver/chrome/bidi_tracker.h" #include "chrome/test/chromedriver/chrome/browser_info.h" #include "chrome/test/chromedriver/chrome/chrome.h" #include "chrome/test/chromedriver/chrome/chrome_android_impl.h" #include "chrome/test/chromedriver/chrome/chrome_desktop_impl.h" +#include "chrome/test/chromedriver/chrome/chrome_impl.h" #include "chrome/test/chromedriver/chrome/device_manager.h" +#include "chrome/test/chromedriver/chrome/devtools_client_impl.h" #include "chrome/test/chromedriver/chrome/devtools_event_listener.h" #include "chrome/test/chromedriver/chrome/geoposition.h" #include "chrome/test/chromedriver/chrome/javascript_dialog_manager.h" @@ -254,7 +261,7 @@ } Status CheckSessionCreated(Session* session) { - WebView* web_view = NULL; + WebView* web_view = nullptr; Status status = session->GetTargetWindow(&web_view); if (status.IsError()) return Status(kSessionNotCreated, status); @@ -307,11 +314,17 @@ // |session| will own the |CommandListener|s. session->command_listeners.swap(command_listeners); + BidiTracker* bidi_tracker = new BidiTracker(); + bidi_tracker->SetBidiCallback( + base::BindRepeating(&Session::OnBidiResponse, base::Unretained(session))); + devtools_event_listeners.emplace_back(bidi_tracker); + status = LaunchChrome(bound_params.url_loader_factory, bound_params.socket_factory, bound_params.device_manager, capabilities, std::move(devtools_event_listeners), &session->chrome, session->w3c_compliant); + if (status.IsError()) return status; @@ -341,7 +354,77 @@ } else { *value = base::Value::ToUniquePtrValue(session->capabilities->Clone()); } - return CheckSessionCreated(session); + + status = CheckSessionCreated(session); + if (status.IsError()) + return status; + + if (session->webSocketUrl) { + WebView* web_view = nullptr; + Status status = session->GetTargetWindow(&web_view); + if (status.IsError()) + return status; + ChromeImpl* chrome = static_cast<ChromeImpl*>(session->chrome.get()); + DevToolsClient* client = chrome->Client(); + + { + base::Value body(base::Value::Type::DICTIONARY); + body.SetStringKey("bindingName", "cdp"); + body.SetStringKey("targetId", session->window); + client->SendCommandAndIgnoreResponse( + "Target.exposeDevToolsProtocol", + base::Value::AsDictionaryValue(body)); + } + + { + std::unique_ptr<base::Value> result; + base::Value body(base::Value::Type::DICTIONARY); + body.SetStringKey("name", "sendBidiResponse"); + web_view->SendCommandAndGetResult( + "Runtime.addBinding", base::Value::AsDictionaryValue(body), &result); + } + + status = EvaluateScriptAndIgnoreResult(session, kMapperScript); + if (status.IsError()) + return status; + + { + std::unique_ptr<base::Value> result; + base::Value body(base::Value::Type::DICTIONARY); + std::string window_id; + if (!base::JSONWriter::Write(session->window, &window_id)) { + return Status(kUnknownError, + "cannot serialize be window id: " + session->window); + } + body.SetStringKey("expression", + "window.setSelfTargetId(" + window_id + ")"); + status = web_view->SendCommandAndGetResult( + "Runtime.evaluate", base::Value::AsDictionaryValue(body), &result); + if (status.IsError()) + return status; + } + + { + // Create a new tab because the default one is occupied by the BiDiMapper + std::string web_view_id; + status = session->chrome->NewWindow( + session->window, Chrome::WindowType::kTab, &web_view_id); + + if (status.IsError()) + return status; + + std::string handle = WebViewIdToWindowHandle(web_view_id); + + std::unique_ptr<base::Value> result; + base::Value body(base::Value::Type::DICTIONARY); + body.GetDict().Set("handle", handle); + + status = ExecuteSwitchToWindow( + session, base::Value::AsDictionaryValue(body), &result); + } + } + + return status; } } // namespace @@ -627,7 +710,7 @@ Status status = InitSessionHelper(bound_params, session, params, value); if (status.IsError()) { session->quit = true; - if (session->chrome != NULL) + if (session->chrome != nullptr) session->chrome->Quit(); } else if (session->webSocketUrl) { bound_params.cmd_task_runner->PostTask( @@ -658,7 +741,7 @@ Status ExecuteGetCurrentWindowHandle(Session* session, const base::DictionaryValue& params, std::unique_ptr<base::Value>* value) { - WebView* web_view = NULL; + WebView* web_view = nullptr; Status status = session->GetTargetWindow(&web_view); if (status.IsError()) return status; @@ -679,9 +762,12 @@ if (status.IsError()) return status; bool is_last_web_view = web_view_ids.size() == 1u; + if (session->webSocketUrl) { + is_last_web_view = web_view_ids.size() <= 2u; + } web_view_ids.clear(); - WebView* web_view = NULL; + WebView* web_view = nullptr; status = session->GetTargetWindow(&web_view); if (status.IsError()) return status; @@ -725,16 +811,16 @@ if (status.IsError()) return status; - if (!is_last_web_view) { - status = ExecuteGetWindowHandles(session, base::DictionaryValue(), value); - if (status.IsError()) - return status; - } else { + if (is_last_web_view) { // If there is only one window left, call quit as well. session->quit = true; status = session->chrome->Quit(); if (status.IsOk()) *value = std::make_unique<base::Value>(base::Value::Type::LIST); + } else { + status = ExecuteGetWindowHandles(session, base::DictionaryValue(), value); + if (status.IsError()) + return status; } return status; @@ -748,6 +834,20 @@ session->w3c_compliant); if (status.IsError()) return status; + + if (session->webSocketUrl) { + std::string mapper_view_id; + // TODO(chromedriver:4181): How do we know for sure that the first page is + // the mapper? + status = session->chrome->GetWebViewIdForFirstTab(&mapper_view_id, + session->w3c_compliant); + auto it = + std::find(web_view_ids.begin(), web_view_ids.end(), mapper_view_id); + if (it != web_view_ids.end()) { + web_view_ids.erase(it); + } + } + std::unique_ptr<base::Value> window_ids( new base::Value(base::Value::Type::LIST)); for (std::list<std::string>::const_iterator it = web_view_ids.begin(); @@ -977,7 +1077,7 @@ Status ExecuteIsLoading(Session* session, const base::DictionaryValue& params, std::unique_ptr<base::Value>* value) { - WebView* web_view = NULL; + WebView* web_view = nullptr; Status status = session->GetTargetWindow(&web_view); if (status.IsError()) return status; @@ -1330,3 +1430,106 @@ value); return Status(kOk); } + +// Run a BiDi command +Status ExecuteBidiCommand(Session* session, + const base::DictionaryValue& params, + std::unique_ptr<base::Value>* value) { + // session == nullptr is a valid case: ExecuteQuit has already been handled + // in the session thread but the following + // TerminateSessionThreadOnCommandThread has not yet been executed (the later + // destroys the session thread) The connection has already been accepted by + // the CMD thread but soon it will be closed. We don't need to do anything. + if (session == nullptr) { + return Status{kNoSuchFrame, "session not found"}; + } + std::string data; + params.GetString("bidiCommand", &data); + + std::string web_view_id; + Status status = session->chrome->GetWebViewIdForFirstTab( + &web_view_id, session->w3c_compliant); + if (status.IsError()) { + return status; + } + WebView* web_view = nullptr; + status = session->chrome->GetWebViewById(web_view_id, &web_view); + if (status.IsError()) { + return status; + } + + absl::optional<base::Value> dataParsed = + base::JSONReader::Read(data, base::JSON_PARSE_CHROMIUM_EXTENSIONS); + + if (!dataParsed) { + return Status(kUnknownError, "cannot parse the BiDi command: " + data); + } + + if (!dataParsed->is_dict()) { + return Status(kUnknownError, + "a JSON map is expected as a BiDi command: " + data); + } + + absl::optional<int> cmd_id = dataParsed->GetDict().FindInt("id"); + if (!cmd_id) { + return Status(kUnknownError, "BiDi command is missing 'id' field: " + data); + } + + std::string* method = dataParsed->GetDict().FindString("method"); + if (!method) { + return Status(kUnknownError, + "BiDi command is missing 'method' field: " + data); + } + + std::string msg; + if (!base::JSONWriter::Write(data, &msg)) { + return Status(kUnknownError, "cannot serialize be BiDi command: " + data); + } + std::string expression = "onBidiMessage(" + msg + ")"; + + if (*method == "browsingContext.close") { + // Closing of the context is handled in a blocking way. + // This simplifies us closing the browser if the last tab was closed. + session->awaited_bidi_response_id = *cmd_id; + status = web_view->EvaluateScript(std::string(), expression, false, value); + base::RepeatingCallback<Status(bool*)> bidi_response_is_received = + base::BindRepeating( + [](Session* session, int cmd_id, bool* condition_is_met) { + *condition_is_met = session->awaited_bidi_response_id != cmd_id; + return Status{kOk}; + }, + base::Unretained(session), *cmd_id); + if (status.IsError()) { + return status; + } + + // The timeout is the same as in ChromeImpl::CloseTarget + status = web_view->HandleEventsUntil(std::move(bidi_response_is_received), + Timeout(base::Seconds(20))); + if (status.code() == kTimeout) { + // It looks like something is going wrong with the BiDiMapper. + // Terminating the session... + session->quit = true; + status = session->chrome->Quit(); + return Status(kUnknownError, "failed to close window in 20 seconds"); + } + if (status.IsError()) + return status; + + std::list<std::string> web_view_ids; + status = + session->chrome->GetWebViewIds(&web_view_ids, session->w3c_compliant); + if (status.IsError()) + return status; + + bool is_last_web_view = web_view_ids.size() <= 1u; + if (is_last_web_view) { + session->quit = true; + status = session->chrome->Quit(); + } + } else { + status = web_view->EvaluateScript(std::string(), expression, false, value); + } + + return status; +}
diff --git a/chrome/test/chromedriver/session_commands.h b/chrome/test/chromedriver/session_commands.h index 4ff91b5..eae7841 100644 --- a/chrome/test/chromedriver/session_commands.h +++ b/chrome/test/chromedriver/session_commands.h
@@ -174,6 +174,11 @@ const base::DictionaryValue& params, std::unique_ptr<base::Value>* value); +// Run a BiDi command +Status ExecuteBidiCommand(Session* session, + const base::DictionaryValue& params, + std::unique_ptr<base::Value>* value); + namespace internal { Status ConfigureHeadlessSession(Session* session, const Capabilities& capabilities);
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index c17d68d..f17cf4b2 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -562,9 +562,10 @@ self.assertEqual(driver.capabilities['webSocketUrl'], self.composeWebSocketUrl(_CHROMEDRIVER_SERVER_URL, driver.GetSessionId())) + websocket = websocket_connection.WebSocketConnection( _CHROMEDRIVER_SERVER_URL, driver.GetSessionId()) - self.assertNotEqual(None, websocket) + self.assertIsNotNone(websocket) def testWebSocketUrlInvalid(self): self.assertRaises(chromedriver.InvalidArgument, @@ -578,15 +579,6 @@ self.assertRaises(Exception, websocket_connection.WebSocketConnection, _CHROMEDRIVER_SERVER_URL, driver.GetSessionId()) - def testWebSocketCommandReturnsNotSupported(self): - driver = self.CreateDriver(web_socket_url=True) - websocket = websocket_connection.WebSocketConnection( - _CHROMEDRIVER_SERVER_URL, driver.GetSessionId()) - - websocket.SendCommand({"SOME": "COMMAND"}) - message = websocket.ReadMessage() - self.assertEqual("not supported", message) - def testWebSocketInvalidSessionId(self): driver = self.CreateDriver(web_socket_url=True) self.assertRaises(Exception, websocket_connection.WebSocketConnection, @@ -5314,6 +5306,143 @@ self.assertRaises(chromedriver.InvalidArgument, self._driver.PrintPDF, {'pageRanges': ['x-y']}) +class BidiTest(ChromeDriverBaseTestWithWebServer): + + def setUp(self): + self._driver = self.CreateDriver(web_socket_url = True) + + def createWebSocketConnection(self, driver = None): + if driver is None: + driver = self._driver + conn = driver.CreateWebSocketConnection() + conn.SetTimeout(5 * 60) # 5 minutes + return conn + + def testCreateContext(self): + conn = self.createWebSocketConnection() + + old_handles = self._driver.GetWindowHandles() + self.assertEqual(1, len(old_handles)) + self.assertNotEqual("BiDi Mapper", self._driver.GetTitle()) + + cmd_id = conn.SendCommand({ + 'method': 'browsingContext.create', + 'params': { + 'type': 'tab' + } + }) + conn.WaitForResponse(cmd_id) + new_handles = self._driver.GetWindowHandles() + diff = set(new_handles) - set(old_handles) + self.assertEqual(1, len(diff)) + + def testGetBrowsingContextTree(self): + conn = self.createWebSocketConnection() + + cmd_id = conn.SendCommand({ + 'method': 'browsingContext.getTree', + 'params': { + } + }) + resp = conn.WaitForResponse(cmd_id) + contexts = resp['result']['contexts'] + self.assertEqual(1, len(contexts)) + + def testMapperIsNotDisplacedByNavigation(self): + self._http_server.SetDataForPath('/page.html', + bytes('<html><title>Regular Page</title></body></html>', 'utf-8')) + + conn = self.createWebSocketConnection() + old_handles = self._driver.GetWindowHandles() + + self._driver.Load(self._http_server.GetUrl() + '/page.html') + self.assertEqual("Regular Page", self._driver.GetTitle()) + + cmd_id = conn.SendCommand({ + 'method': 'browsingContext.create', + 'params': { + 'type': 'tab' + } + }) + conn.WaitForResponse(cmd_id) + new_handles = self._driver.GetWindowHandles() + diff = set(new_handles) - set(old_handles) + self.assertEqual(1, len(diff)) + + def testBrowserQuitsWhenLastPageIsClosed(self): + conn = self.createWebSocketConnection() + + handles = self._driver.GetWindowHandles() + self.assertEqual(1, len(handles)) + self._driver.CloseWindow() + + with self.assertRaises(chromedriver.WebSocketConnectionClosedException): + # BiDi messages cannot have negative "id". + # Wait indefinitely until time out. + conn.WaitForResponse(-1) + + def testCloseOneOfManyPages(self): + conn = self.createWebSocketConnection() + + cmd_id = conn.SendCommand({ + 'method': 'browsingContext.create', + 'params': { + 'type': 'tab' + } + }) + conn.WaitForResponse(cmd_id) + + handles = self._driver.GetWindowHandles() + self.assertEqual(2, len(handles)) + self._driver.CloseWindow() + + cmd_id = conn.SendCommand({ + 'method': 'browsingContext.getTree', + 'params': { + } + }) + resp = conn.WaitForResponse(cmd_id) + contexts = resp['result']['contexts'] + self.assertEqual(1, len(contexts)) + + def testBrowserQuitsWhenLastBrowsingContextIsClosed(self): + conn = self.createWebSocketConnection() + + cmd_id = conn.SendCommand({ + 'method': 'browsingContext.getTree', + 'params': { + } + }) + resp = conn.WaitForResponse(cmd_id) + contexts = resp['result']['contexts'] + + cmd_id = conn.SendCommand({ + 'method': 'browsingContext.close', + 'params': { + 'context': contexts[0]['context'] + } + }) + conn.WaitForResponse(cmd_id) + + with self.assertRaises(chromedriver.WebSocketConnectionClosedException): + # BiDi messages cannot have negative "id". + # Wait indefinitely until time out. + conn.WaitForResponse(-1) + + + # TODO(nechaev): Test over tab switching by different means. + +class ClassiTest(ChromeDriverBaseTestWithWebServer): + + def testAfterLastPage(self): + driver = self.CreateDriver(web_socket_url = False) + + handles = driver.GetWindowHandles() + self.assertEqual(1, len(handles)) + driver.CloseWindow() + + + class SupportIPv4AndIPv6(ChromeDriverBaseTest): def testSupportIPv4AndIPv6(self): has_ipv4 = False
diff --git a/chrome/test/chromedriver/test/run_py_tests.pydeps b/chrome/test/chromedriver/test/run_py_tests.pydeps index ae77f00..3703cfb9 100644 --- a/chrome/test/chromedriver/test/run_py_tests.pydeps +++ b/chrome/test/chromedriver/test/run_py_tests.pydeps
@@ -82,6 +82,7 @@ ../chrome_paths.py ../client/chromedriver.py ../client/command_executor.py +../client/exceptions.py ../client/webelement.py ../client/webshadowroot.py ../client/websocket_connection.py
diff --git a/chrome/test/data/webui/cr_elements/cr_radio_group_test.ts b/chrome/test/data/webui/cr_elements/cr_radio_group_test.ts index 7ff9a331..4efde5ef 100644 --- a/chrome/test/data/webui/cr_elements/cr_radio_group_test.ts +++ b/chrome/test/data/webui/cr_elements/cr_radio_group_test.ts
@@ -3,11 +3,11 @@ // found in the LICENSE file. // clang-format off -import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; import {CrRadioButtonElement} from 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; -import {CrRadioGroupElement} from 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import {CrRadioGroupElement} from 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import {pressAndReleaseKeyOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
diff --git a/chrome/test/data/webui/mojo/mojo_file_system_access_browsertest.cc b/chrome/test/data/webui/mojo/mojo_file_system_access_browsertest.cc index 19d37e2..a257330 100644 --- a/chrome/test/data/webui/mojo/mojo_file_system_access_browsertest.cc +++ b/chrome/test/data/webui/mojo/mojo_file_system_access_browsertest.cc
@@ -9,7 +9,6 @@ #include "base/test/bind.h" #include "base/threading/sequenced_task_runner_handle.h" #include "chrome/browser/bad_message.h" -#include "chrome/browser/chrome_browser_interface_binders.h" #include "chrome/browser/chrome_content_browser_client.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -25,6 +24,7 @@ #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui_controller_factory.h" +#include "content/public/browser/web_ui_controller_interface_binder.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/common/content_client.h" #include "content/public/common/extra_mojo_js_features.mojom.h" @@ -196,7 +196,7 @@ mojo::BinderMapWithContext<content::RenderFrameHost*>* map) override { ChromeContentBrowserClient::RegisterBrowserInterfaceBindersForFrame( render_frame_host, map); - chrome::internal::RegisterWebUIControllerInterfaceBinder< + content::RegisterWebUIControllerInterfaceBinder< ::test::mojom::MojoFileSystemAccessTest, MojoFileSystemAccessUI>(map); } };
diff --git a/chrome/test/data/webui/mojo/mojo_web_ui_controller_browsertest.cc b/chrome/test/data/webui/mojo/mojo_web_ui_controller_browsertest.cc index cda29a5..1ef35bdd 100644 --- a/chrome/test/data/webui/mojo/mojo_web_ui_controller_browsertest.cc +++ b/chrome/test/data/webui/mojo/mojo_web_ui_controller_browsertest.cc
@@ -21,6 +21,7 @@ #include "content/public/browser/render_process_host_observer.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui_controller_factory.h" +#include "content/public/browser/web_ui_controller_interface_binder.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/common/content_client.h" #include "content/public/common/url_constants.h" @@ -187,10 +188,10 @@ mojo::BinderMapWithContext<content::RenderFrameHost*>* map) override { ChromeContentBrowserClient::RegisterBrowserInterfaceBindersForFrame( render_frame_host, map); - chrome::internal::RegisterWebUIControllerInterfaceBinder< - ::test::mojom::Bar, FooBarUI>(map); - chrome::internal::RegisterWebUIControllerInterfaceBinder< - ::test::mojom::Foo, FooUI, FooBarUI>(map); + content::RegisterWebUIControllerInterfaceBinder<::test::mojom::Bar, + FooBarUI>(map); + content::RegisterWebUIControllerInterfaceBinder<::test::mojom::Foo, FooUI, + FooBarUI>(map); } };
diff --git a/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.ts b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.ts index f7c8d14bc..8bd8696a 100644 --- a/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.ts +++ b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.ts
@@ -163,6 +163,7 @@ isLocal: true, summaryLabel: card + ' ' + '****' + cardNumber.substr(-4), + summarySublabel: 'Jane Doe', }, }; }
diff --git a/chrome/test/data/webui/settings/payments_section_test.ts b/chrome/test/data/webui/settings/payments_section_test.ts index 035c1387..d69422101b 100644 --- a/chrome/test/data/webui/settings/payments_section_test.ts +++ b/chrome/test/data/webui/settings/payments_section_test.ts
@@ -43,6 +43,7 @@ loadTimeData.overrideValues({ migrationEnabled: true, virtualCardEnrollmentEnabled: true, + virtualCardMetadataEnabled: true, }); }); @@ -207,7 +208,7 @@ assertEquals( creditCard.metadata!.summaryLabel, rowShadowRoot.querySelector<HTMLElement>( - '#creditCardLabel')!.textContent!.trim()); + '#summaryLabel')!.textContent!.trim()); assertEquals( creditCard.expirationMonth + '/' + creditCard.expirationYear, rowShadowRoot.querySelector<HTMLElement>( @@ -305,6 +306,77 @@ assertFalse(!!outlinkButton); }); + test('verifyCreditCardSummarySublabelWhenSublabelIsValid', function() { + const creditCard = createCreditCardEntry(); + creditCard.metadata!.isLocal = false; + creditCard.metadata!.isVirtualCardEnrollmentEligible = false; + creditCard.metadata!.isVirtualCardEnrolled = false; + const section = + createPaymentsSection([creditCard], /*upiIds=*/[], /*prefValues=*/ {}); + + const creditCardList = section.$.paymentsList; + assertTrue(!!creditCardList); + assertEquals(1, getLocalAndServerCreditCardListItems().length); + assertFalse(getCardRowShadowRoot(section.$.paymentsList) + .querySelector<HTMLElement>('#summarySublabel')!.hidden); + }); + + test('verifyCreditCardSummarySublabelWhenSublabelIsInvalid', function() { + const creditCard = createCreditCardEntry(); + creditCard.metadata!.isLocal = false; + creditCard.metadata!.isVirtualCardEnrollmentEligible = false; + creditCard.metadata!.isVirtualCardEnrolled = false; + creditCard.metadata!.summarySublabel = ''; + const section = + createPaymentsSection([creditCard], /*upiIds=*/[], /*prefValues=*/ {}); + + const creditCardList = section.$.paymentsList; + assertTrue(!!creditCardList); + assertEquals(1, getLocalAndServerCreditCardListItems().length); + assertTrue(getCardRowShadowRoot(section.$.paymentsList) + .querySelector<HTMLElement>('#summarySublabel')!.hidden); + }); + + test('verifyCreditCardSummarySublabelWhenVirtualCardAvailable', function() { + const creditCard = createCreditCardEntry(); + creditCard.metadata!.isLocal = false; + creditCard.metadata!.isVirtualCardEnrollmentEligible = true; + creditCard.metadata!.isVirtualCardEnrolled = false; + const section = + createPaymentsSection([creditCard], /*upiIds=*/[], /*prefValues=*/ {}); + + const creditCardList = section.$.paymentsList; + assertTrue(!!creditCardList); + assertEquals(1, getLocalAndServerCreditCardListItems().length); + assertFalse(getCardRowShadowRoot(section.$.paymentsList) + .querySelector<HTMLElement>('#summarySublabel')!.hidden); + assertEquals( + 'Virtual card available', + getCardRowShadowRoot(section.$.paymentsList) + .querySelector<HTMLElement>( + '#summarySublabel')!.textContent!.trim()); + }); + + test('verifyCreditCardSummarySublabelWhenVirtualCardTurnedOn', function() { + const creditCard = createCreditCardEntry(); + creditCard.metadata!.isLocal = false; + creditCard.metadata!.isVirtualCardEnrollmentEligible = false; + creditCard.metadata!.isVirtualCardEnrolled = true; + const section = + createPaymentsSection([creditCard], /*upiIds=*/[], /*prefValues=*/ {}); + + const creditCardList = section.$.paymentsList; + assertTrue(!!creditCardList); + assertEquals(1, getLocalAndServerCreditCardListItems().length); + assertFalse(getCardRowShadowRoot(section.$.paymentsList) + .querySelector<HTMLElement>('#summarySublabel')!.hidden); + assertEquals( + 'Virtual card turned on', + getCardRowShadowRoot(section.$.paymentsList) + .querySelector<HTMLElement>( + '#summarySublabel')!.textContent!.trim()); + }); + test('verifyAddVsEditCreditCardTitle', function() { const newCreditCard = createEmptyCreditCardEntry(); const newCreditCardDialog = createCreditCardDialog(newCreditCard);
diff --git a/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts b/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts index 658b5c5..34ac1ad 100644 --- a/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts +++ b/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts
@@ -20,7 +20,7 @@ document.body.innerHTML = ''; readAnythingApp = document.createElement('read-anything-app'); document.body.appendChild(readAnythingApp); - chrome.readAnything.setThemeForTesting('default', 18.0); + chrome.readAnything.setThemeForTesting('default', 18.0, 0, 0); }); function assertFontName(fontFamily: string) { @@ -40,33 +40,50 @@ } test('updateTheme fontName', () => { - chrome.readAnything.setThemeForTesting('Standard font', 18.0); + chrome.readAnything.setThemeForTesting('Standard font', 18.0, 0, 0); assertFontName('"Standard font"'); - chrome.readAnything.setThemeForTesting('Sans-serif', 18.0); + chrome.readAnything.setThemeForTesting('Sans-serif', 18.0, 0, 0); assertFontName('sans-serif'); - chrome.readAnything.setThemeForTesting('Serif', 18.0); + chrome.readAnything.setThemeForTesting('Serif', 18.0, 0, 0); assertFontName('serif'); - chrome.readAnything.setThemeForTesting('Avenir', 18.0); + chrome.readAnything.setThemeForTesting('Avenir', 18.0, 0, 0); assertFontName('avenir'); - chrome.readAnything.setThemeForTesting('Comic Neue', 18.0); + chrome.readAnything.setThemeForTesting('Comic Neue', 18.0, 0, 0); assertFontName('"Comic Neue"'); - chrome.readAnything.setThemeForTesting('Comic Sans MS', 18.0); + chrome.readAnything.setThemeForTesting('Comic Sans MS', 18.0, 0, 0); assertFontName('"Comic Sans MS"'); - chrome.readAnything.setThemeForTesting('Poppins', 18.0); + chrome.readAnything.setThemeForTesting('Poppins', 18.0, 0, 0); assertFontName('poppins'); }); test('updateTheme fontSize', () => { - chrome.readAnything.setThemeForTesting('Standard font', 27.0); + chrome.readAnything.setThemeForTesting('Standard font', 27.0, 0, 0); assertFontSize('27px'); }); + test('updateTheme foregroundColor', () => { + chrome.readAnything.setThemeForTesting( + 'f', 1, /* SkColorSetRGB(0x33, 0x36, 0x39) = */ 4281546297, 0); + const container = readAnythingApp.shadowRoot!.getElementById('container'); + assertEquals( + /* #333639 = */ 'rgb(51, 54, 57)', getComputedStyle(container!).color); + }); + + test('updateTheme backgroundColor', () => { + chrome.readAnything.setThemeForTesting( + 'f', 1, 0, /* SkColorSetRGB(0xFD, 0xE2, 0x93) = */ 4294828691); + const container = readAnythingApp.shadowRoot!.getElementById('container'); + assertEquals( + /* #FDE293 = */ 'rgb(253, 226, 147)', + getComputedStyle(container!).backgroundColor); + }); + test('updateContent paragraph', () => { // root id=1 // ++paragraph id=2
diff --git a/chrome/test/media_router/media_router_integration_browsertest.cc b/chrome/test/media_router/media_router_integration_browsertest.cc index 6a1bfe5..6be2e31 100644 --- a/chrome/test/media_router/media_router_integration_browsertest.cc +++ b/chrome/test/media_router/media_router_integration_browsertest.cc
@@ -234,19 +234,17 @@ // Read the test result, the test result set by javascript is a // JSON string with the following format: // {"passed": "<true/false>", "errorMessage": "<error_message>"} - std::unique_ptr<base::Value> value = base::JSONReader::ReadDeprecated( - result, base::JSON_ALLOW_TRAILING_COMMAS); + absl::optional<base::Value> value = + base::JSONReader::Read(result, base::JSON_ALLOW_TRAILING_COMMAS); // Convert to dictionary. - base::DictionaryValue* dict_value = nullptr; - ASSERT_TRUE(value->GetAsDictionary(&dict_value)); + base::Value::Dict* dict_value = value->GetIfDict(); + ASSERT_TRUE(dict_value); // Extract the fields. - std::string error_message; - ASSERT_TRUE(dict_value->GetString("errorMessage", &error_message)); - - ASSERT_THAT(dict_value->FindBoolKey("passed"), Optional(true)) - << error_message; + const std::string* error_message = dict_value->FindString("errorMessage"); + ASSERT_TRUE(error_message); + ASSERT_THAT(dict_value->FindBool("passed"), Optional(true)) << error_message; } void MediaRouterIntegrationBrowserTest::StartSessionAndAssertNotFoundError() {
diff --git a/chrome/updater/app/app_install.cc b/chrome/updater/app/app_install.cc index 3f764f0..c202ae4 100644 --- a/chrome/updater/app/app_install.cc +++ b/chrome/updater/app/app_install.cc
@@ -184,14 +184,18 @@ // It's possible that a previous updater existed but is nonresponsive. In // this case, clear the active version in global prefs so that the system can // recover. - base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()}) - ->PostTaskAndReply(FROM_HERE, - base::BindOnce( - [](UpdaterScope scope) { - CreateGlobalPrefs(scope)->SetActiveVersion(""); - }, - updater_scope()), - base::BindOnce(&AppInstall::WakeCandidate, this)); + base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::WithBaseSyncPrimitives()}) + ->PostTaskAndReply( + FROM_HERE, + base::BindOnce( + [](UpdaterScope scope) { + scoped_refptr<GlobalPrefs> prefs = CreateGlobalPrefs(scope); + prefs->SetActiveVersion(""); + PrefsCommitPendingWrites(prefs->GetPrefService()); + }, + updater_scope()), + base::BindOnce(&AppInstall::WakeCandidate, this)); } void AppInstall::WakeCandidate() {
diff --git a/chrome/updater/unittest_util_unittest.cc b/chrome/updater/unittest_util_unittest.cc index 56d93e1..c4679f12 100644 --- a/chrome/updater/unittest_util_unittest.cc +++ b/chrome/updater/unittest_util_unittest.cc
@@ -26,7 +26,9 @@ TEST(UnitTestUtil, Processes) { // Test the state of the process for the unit test process itself. base::FilePath::StringType unit_test = GetUnitTestExecutableName(); - EXPECT_TRUE(IsProcessRunning(unit_test)); + // TODO(crbug.com/1352190) - remove process name insertion after the flakiness + // of the test is resolved. + EXPECT_TRUE(IsProcessRunning(unit_test)) << unit_test; EXPECT_FALSE(WaitForProcessesToExit(unit_test, base::Milliseconds(1))); #if BUILDFLAG(IS_WIN)
diff --git a/chrome/utility/safe_browsing/OWNERS b/chrome/utility/safe_browsing/OWNERS index 70e4b68..5225674 100644 --- a/chrome/utility/safe_browsing/OWNERS +++ b/chrome/utility/safe_browsing/OWNERS
@@ -1,3 +1 @@ -drubery@chromium.org -nparker@chromium.org -vakh@chromium.org +file://components/safe_browsing/OWNERS
diff --git a/chromecast/browser/cast_permission_manager.cc b/chromecast/browser/cast_permission_manager.cc index 8dc88916..1703f4c 100644 --- a/chromecast/browser/cast_permission_manager.cc +++ b/chromecast/browser/cast_permission_manager.cc
@@ -174,6 +174,17 @@ return GetPermissionStatusInternal(permission, requesting_origin); } +content::PermissionResult +CastPermissionManager::GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) { + blink::mojom::PermissionStatus status = + GetPermissionStatus(permission, origin.GetURL(), origin.GetURL()); + + return content::PermissionResult( + status, content::PermissionStatusSource::UNSPECIFIED); +} + blink::mojom::PermissionStatus CastPermissionManager::GetPermissionStatusForCurrentDocument( blink::PermissionType permission,
diff --git a/chromecast/browser/cast_permission_manager.h b/chromecast/browser/cast_permission_manager.h index 7fac9e2..be32fcf4 100644 --- a/chromecast/browser/cast_permission_manager.h +++ b/chromecast/browser/cast_permission_manager.h
@@ -7,6 +7,7 @@ #include "base/callback_forward.h" #include "content/public/browser/permission_controller_delegate.h" +#include "content/public/browser/permission_result.h" #include "third_party/blink/public/common/permissions/permission_utils.h" #include "url/gurl.h" @@ -56,6 +57,9 @@ blink::PermissionType permission, const GURL& requesting_origin, const GURL& embedding_origin) override; + content::PermissionResult GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) override; blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument( blink::PermissionType permission, content::RenderFrameHost* render_frame_host) override;
diff --git a/chromeos/ash/components/network/cellular_inhibitor.cc b/chromeos/ash/components/network/cellular_inhibitor.cc index 0bb89dd..1b302d5 100644 --- a/chromeos/ash/components/network/cellular_inhibitor.cc +++ b/chromeos/ash/components/network/cellular_inhibitor.cc
@@ -355,33 +355,33 @@ return stream; } -} // namespace ash - std::ostream& operator<<( std::ostream& stream, - const ash::CellularInhibitor::InhibitReason& inhibit_reason) { + const CellularInhibitor::InhibitReason& inhibit_reason) { switch (inhibit_reason) { - case ash::CellularInhibitor::InhibitReason::kInstallingProfile: + case CellularInhibitor::InhibitReason::kInstallingProfile: stream << "[Installing profile]"; break; - case ash::CellularInhibitor::InhibitReason::kRenamingProfile: + case CellularInhibitor::InhibitReason::kRenamingProfile: stream << "[Renaming profile]"; break; - case ash::CellularInhibitor::InhibitReason::kRemovingProfile: + case CellularInhibitor::InhibitReason::kRemovingProfile: stream << "[Removing profile]"; break; - case ash::CellularInhibitor::InhibitReason::kConnectingToProfile: + case CellularInhibitor::InhibitReason::kConnectingToProfile: stream << "[Connecting to profile]"; break; - case ash::CellularInhibitor::InhibitReason::kRefreshingProfileList: + case CellularInhibitor::InhibitReason::kRefreshingProfileList: stream << "[Refreshing profile list]"; break; - case ash::CellularInhibitor::InhibitReason::kResettingEuiccMemory: + case CellularInhibitor::InhibitReason::kResettingEuiccMemory: stream << "[Resetting EUICC memory]"; break; - case ash::CellularInhibitor::InhibitReason::kDisablingProfile: + case CellularInhibitor::InhibitReason::kDisablingProfile: stream << "[Disabling profile]"; break; } return stream; } + +} // namespace ash
diff --git a/chromeos/ash/components/network/cellular_inhibitor.h b/chromeos/ash/components/network/cellular_inhibitor.h index c2d57ab..4af01624 100644 --- a/chromeos/ash/components/network/cellular_inhibitor.h +++ b/chromeos/ash/components/network/cellular_inhibitor.h
@@ -76,6 +76,8 @@ kResettingEuiccMemory, kDisablingProfile, }; + friend std::ostream& operator<<(std::ostream& stream, + const InhibitReason& state); // Callback which returns InhibitLock on inhibit success or nullptr on // failure. @@ -197,12 +199,16 @@ base::WeakPtrFactory<CellularInhibitor> weak_ptr_factory_{this}; }; -} // namespace ash +std::ostream& COMPONENT_EXPORT(CHROMEOS_NETWORK) operator<<( + std::ostream& stream, + const ash::CellularInhibitor::State& state); -std::ostream& operator<<( +std::ostream& COMPONENT_EXPORT(CHROMEOS_NETWORK) operator<<( std::ostream& stream, const ash::CellularInhibitor::InhibitReason& inhibit_reason); +} // namespace ash + // TODO(https://crbug.com/1164001): remove when the migration is finished. namespace chromeos { using ::ash::CellularInhibitor;
diff --git a/chromeos/ash/components/network/network_state.cc b/chromeos/ash/components/network/network_state.cc index 9fd4cc5..793fbe4c 100644 --- a/chromeos/ash/components/network/network_state.cc +++ b/chromeos/ash/components/network/network_state.cc
@@ -667,7 +667,7 @@ shill_portal_state_); if (shill_portal_state_ != PortalState::kOnline) { NET_LOG(EVENT) << "Shill captive portal state for: " << NetworkId(this) - << " = " << static_cast<int>(shill_portal_state_) + << " = " << shill_portal_state_ << " ,status_code=" << status_code; base::UmaHistogramSparse("CaptivePortal.NetworkStateStatusCode", std::abs(status_code)); @@ -687,4 +687,29 @@ vpn_provider_->type = type; } +std::ostream& operator<<(std::ostream& stream, + const NetworkState::PortalState& portal_state) { + switch (portal_state) { + case NetworkState::PortalState::kUnknown: + stream << "Unknown"; + break; + case NetworkState::PortalState::kOnline: + stream << "Online"; + break; + case NetworkState::PortalState::kPortalSuspected: + stream << "PortalSuspected"; + break; + case NetworkState::PortalState::kPortal: + stream << "Portal"; + break; + case NetworkState::PortalState::kProxyAuthRequired: + stream << "ProxyAuthRequired"; + break; + case NetworkState::PortalState::kNoInternet: + stream << "NoInternet"; + break; + } + return stream; +} + } // namespace ash
diff --git a/chromeos/ash/components/network/network_state.h b/chromeos/ash/components/network/network_state.h index 5a82d1e..b511d84d 100644 --- a/chromeos/ash/components/network/network_state.h +++ b/chromeos/ash/components/network/network_state.h
@@ -6,6 +6,7 @@ #define CHROMEOS_ASH_COMPONENTS_NETWORK_NETWORK_STATE_H_ #include <stdint.h> +#include <sstream> #include <memory> #include <string> @@ -69,6 +70,8 @@ kNoInternet, kMaxValue = kNoInternet // For UMA_HISTOGRAM_ENUMERATION }; + friend std::ostream& operator<<(std::ostream& stream, + const PortalState& portal_state); // ManagedState overrides // If you change this method, update GetProperties too. @@ -383,6 +386,10 @@ bool connect_requested_ = false; }; +std::ostream& COMPONENT_EXPORT(CHROMEOS_NETWORK) operator<<( + std::ostream& stream, + const NetworkState::PortalState& portal_state); + } // namespace ash // TODO(https://crbug.com/1164001): remove when the migration is finished.
diff --git a/chromeos/ash/components/network/network_state_handler.cc b/chromeos/ash/components/network/network_state_handler.cc index 15dd9197..60c246a3 100644 --- a/chromeos/ash/components/network/network_state_handler.cc +++ b/chromeos/ash/components/network/network_state_handler.cc
@@ -567,6 +567,8 @@ NetworkState* network = GetModifiableNetworkState(service_path); if (!network) return; + NET_LOG(USER) << "Setting Chrome PortalState for " + << NetworkPathId(service_path) << " = " << portal_state; auto prev_portal_state = network->GetPortalState(); network->set_chrome_portal_state(portal_state); if (prev_portal_state == network->GetPortalState()) @@ -2075,6 +2077,8 @@ default_network->proxy_config() != default_network_proxy_config_)) { default_network_portal_state_ = default_network->GetPortalState(); default_network_proxy_config_ = default_network->proxy_config().Clone(); + NET_LOG(EVENT) << "NOTIFY: PortalStateChanged: " + << default_network_portal_state_; for (auto& observer : observers_) { observer.PortalStateChanged(default_network, default_network_portal_state_); @@ -2084,6 +2088,7 @@ !default_network_proxy_config_.is_none())) { default_network_portal_state_ = NetworkState::PortalState::kUnknown; default_network_proxy_config_ = base::Value(); + NET_LOG(EVENT) << "NOTIFY: PortalStateChanged: Unknown (no network)"; for (auto& observer : observers_) observer.PortalStateChanged(nullptr, NetworkState::PortalState::kUnknown); }
diff --git a/chromeos/ash/components/network/network_state_handler_unittest.cc b/chromeos/ash/components/network/network_state_handler_unittest.cc index be0ba79..fb9de76f 100644 --- a/chromeos/ash/components/network/network_state_handler_unittest.cc +++ b/chromeos/ash/components/network/network_state_handler_unittest.cc
@@ -144,7 +144,7 @@ NetworkState::PortalState portal_state) override { default_network_portal_state_ = portal_state; ++portal_state_change_count_; - VLOG(1) << "PortalStateChanged: " << static_cast<int>(portal_state); + VLOG(1) << "PortalStateChanged: " << portal_state; } void NetworkConnectionStateChanged(const NetworkState* network) override {
diff --git a/chromeos/components/cdm_factory_daemon/BUILD.gn b/chromeos/components/cdm_factory_daemon/BUILD.gn index e5c5c65..34dcc0d4 100644 --- a/chromeos/components/cdm_factory_daemon/BUILD.gn +++ b/chromeos/components/cdm_factory_daemon/BUILD.gn
@@ -52,6 +52,10 @@ "chromeos_cdm_factory.h", "content_decryption_module_adapter.cc", "content_decryption_module_adapter.h", + "remote_cdm_context.cc", + "remote_cdm_context.h", + "stable_cdm_context_impl.cc", + "stable_cdm_context_impl.h", ] public_deps = [ "//chromeos/components/cdm_factory_daemon/mojom", @@ -59,6 +63,7 @@ ] deps = [ "//base", + "//media/mojo/mojom/stable:stable_video_decoder", "//mojo/public/cpp/bindings", ] defines = [ "IS_CDM_FACTORY_DAEMON_IMPL" ]
diff --git a/chromeos/components/cdm_factory_daemon/chromeos_cdm_context.h b/chromeos/components/cdm_factory_daemon/chromeos_cdm_context.h index 75e2420..f297248 100644 --- a/chromeos/components/cdm_factory_daemon/chromeos_cdm_context.h +++ b/chromeos/components/cdm_factory_daemon/chromeos_cdm_context.h
@@ -55,6 +55,11 @@ // Returns true if this is coming from a CDM in ARC. virtual bool UsingArcCdm() const = 0; + // Returns true if this is coming from a remote CDM in another process or + // operating system. This is used to determine if certain processing has + // already been done on the data such as transcryption. + virtual bool IsRemoteCdm() const = 0; + protected: virtual ~ChromeOsCdmContext() = default; };
diff --git a/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.cc b/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.cc index 05ed5c7..146cd49 100644 --- a/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.cc +++ b/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.cc
@@ -146,6 +146,7 @@ return std::make_unique<SingletonCdmContextRef>(this); } bool UsingArcCdm() const override { return true; } + bool IsRemoteCdm() const override { return true; } // media::CdmContext implementation. ChromeOsCdmContext* GetChromeOsCdmContext() override { return this; }
diff --git a/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.cc b/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.cc index 73198a9..1d5e76e 100644 --- a/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.cc +++ b/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.cc
@@ -259,6 +259,10 @@ return false; } +bool ContentDecryptionModuleAdapter::IsRemoteCdm() const { + return false; +} + void ContentDecryptionModuleAdapter::OnSessionMessage( const std::string& session_id, media::CdmMessageType message_type,
diff --git a/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.h b/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.h index 83e3534..edb1e0c 100644 --- a/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.h +++ b/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.h
@@ -108,6 +108,7 @@ void GetScreenResolutions(GetScreenResolutionsCB callback) override; std::unique_ptr<media::CdmContextRef> GetCdmContextRef() override; bool UsingArcCdm() const override; + bool IsRemoteCdm() const override; // cdm::mojom::ContentDecryptionModuleClient: void OnSessionMessage(const std::string& session_id,
diff --git a/chromeos/components/cdm_factory_daemon/remote_cdm_context.cc b/chromeos/components/cdm_factory_daemon/remote_cdm_context.cc new file mode 100644 index 0000000..ae4ddad --- /dev/null +++ b/chromeos/components/cdm_factory_daemon/remote_cdm_context.cc
@@ -0,0 +1,127 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/components/cdm_factory_daemon/remote_cdm_context.h" + +#include "base/callback.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "base/threading/thread_checker.h" +#include "media/cdm/cdm_context_ref_impl.h" + +namespace chromeos { + +namespace { +class RemoteCdmContextRef final : public media::CdmContextRef { + public: + explicit RemoteCdmContextRef(scoped_refptr<RemoteCdmContext> cdm_context) + : cdm_context_(std::move(cdm_context)) {} + + RemoteCdmContextRef(const RemoteCdmContextRef&) = delete; + RemoteCdmContextRef& operator=(const RemoteCdmContextRef&) = delete; + + ~RemoteCdmContextRef() final = default; + + // CdmContextRef: + media::CdmContext* GetCdmContext() final { return cdm_context_.get(); } + + private: + scoped_refptr<RemoteCdmContext> cdm_context_; +}; +} // namespace + +RemoteCdmContext::RemoteCdmContext( + mojo::PendingRemote<media::stable::mojom::StableCdmContext> + stable_cdm_context) + : stable_cdm_context_(std::move(stable_cdm_context)), + mojo_task_runner_(base::SequencedTaskRunnerHandle::Get()) {} + +std::unique_ptr<media::CallbackRegistration> RemoteCdmContext::RegisterEventCB( + EventCB event_cb) { + auto registration = event_callbacks_.Register(std::move(event_cb)); + mojo_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&RemoteCdmContext::RegisterForRemoteCallbacks, + weak_ptr_factory_.GetWeakPtr())); + return registration; +} + +RemoteCdmContext::~RemoteCdmContext() {} + +void RemoteCdmContext::RegisterForRemoteCallbacks() { + if (!event_callback_receiver_.is_bound()) { + stable_cdm_context_->RegisterEventCallback( + event_callback_receiver_.BindNewPipeAndPassRemote()); + } +} + +ChromeOsCdmContext* RemoteCdmContext::GetChromeOsCdmContext() { + return this; +} + +void RemoteCdmContext::GetHwKeyData(const media::DecryptConfig* decrypt_config, + const std::vector<uint8_t>& hw_identifier, + GetHwKeyDataCB callback) { + // Clone the |decrypt_config| in case the pointer becomes invalid when we are + // re-posting the task. + GetHwKeyDataInternal(decrypt_config->Clone(), hw_identifier, + std::move(callback)); +} + +void RemoteCdmContext::GetHwKeyDataInternal( + std::unique_ptr<media::DecryptConfig> decrypt_config, + const std::vector<uint8_t>& hw_identifier, + GetHwKeyDataCB callback) { + // This can get called from decoder threads, so we may need to repost the + // task. + if (!mojo_task_runner_->RunsTasksInCurrentSequence()) { + mojo_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&RemoteCdmContext::GetHwKeyDataInternal, + weak_ptr_factory_.GetWeakPtr(), + std::move(decrypt_config), hw_identifier, + std::move(callback))); + return; + } + stable_cdm_context_->GetHwKeyData(std::move(decrypt_config), hw_identifier, + std::move(callback)); +} + +void RemoteCdmContext::GetHwConfigData(GetHwConfigDataCB callback) { + stable_cdm_context_->GetHwConfigData(std::move(callback)); +} + +void RemoteCdmContext::GetScreenResolutions(GetScreenResolutionsCB callback) { + stable_cdm_context_->GetScreenResolutions(std::move(callback)); +} + +std::unique_ptr<media::CdmContextRef> RemoteCdmContext::GetCdmContextRef() { + return std::make_unique<RemoteCdmContextRef>(base::WrapRefCounted(this)); +} + +bool RemoteCdmContext::UsingArcCdm() const { + return false; +} + +bool RemoteCdmContext::IsRemoteCdm() const { + return true; +} + +void RemoteCdmContext::EventCallback(media::CdmContext::Event event) { + event_callbacks_.Notify(std::move(event)); +} + +void RemoteCdmContext::DeleteOnCorrectThread() const { + if (!mojo_task_runner_->RunsTasksInCurrentSequence()) { + // When DeleteSoon returns false, |this| will be leaked, which is okay. + mojo_task_runner_->DeleteSoon(FROM_HERE, this); + } else { + delete this; + } +} + +// static +void RemoteCdmContextTraits::Destruct( + const RemoteCdmContext* remote_cdm_context) { + remote_cdm_context->DeleteOnCorrectThread(); +} + +} // namespace chromeos
diff --git a/chromeos/components/cdm_factory_daemon/remote_cdm_context.h b/chromeos/components/cdm_factory_daemon/remote_cdm_context.h new file mode 100644 index 0000000..fb634c1 --- /dev/null +++ b/chromeos/components/cdm_factory_daemon/remote_cdm_context.h
@@ -0,0 +1,96 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_REMOTE_CDM_CONTEXT_H_ +#define CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_REMOTE_CDM_CONTEXT_H_ + +#include <memory> + +#include "base/component_export.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/task/sequenced_task_runner.h" +#include "chromeos/components/cdm_factory_daemon/chromeos_cdm_context.h" +#include "media/base/callback_registry.h" +#include "media/base/cdm_context.h" +#include "media/mojo/mojom/stable/stable_video_decoder.mojom.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/remote.h" + +namespace chromeos { + +struct RemoteCdmContextTraits; + +// Provides the implementation that runs in out of process video decoding that +// proxies the media::CdmContext calls back through a mojom::StableCdmContext +// IPC connection. +class COMPONENT_EXPORT(CDM_FACTORY_DAEMON) RemoteCdmContext + : public media::CdmContext, + public ChromeOsCdmContext, + public media::stable::mojom::CdmContextEventCallback, + public base::RefCountedThreadSafe<RemoteCdmContext, + RemoteCdmContextTraits> { + public: + explicit RemoteCdmContext( + mojo::PendingRemote<media::stable::mojom::StableCdmContext> + stable_cdm_context); + + RemoteCdmContext(const RemoteCdmContext&) = delete; + RemoteCdmContext& operator=(const RemoteCdmContext&) = delete; + + // media::CdmContext: + std::unique_ptr<media::CallbackRegistration> RegisterEventCB( + EventCB event_cb) override; + ChromeOsCdmContext* GetChromeOsCdmContext() override; + + // chromeos::ChromeOsCdmContext: + void GetHwKeyData(const media::DecryptConfig* decrypt_config, + const std::vector<uint8_t>& hw_identifier, + GetHwKeyDataCB callback) override; + void GetHwConfigData(GetHwConfigDataCB callback) override; + void GetScreenResolutions(GetScreenResolutionsCB callback) override; + std::unique_ptr<media::CdmContextRef> GetCdmContextRef() override; + bool UsingArcCdm() const override; + bool IsRemoteCdm() const override; + + // media::stable::mojom::CdmContextEventCallback: + void EventCallback(media::CdmContext::Event event) override; + + // Deletes |this| on the correct thread. + void DeleteOnCorrectThread() const; + + private: + // For DeleteSoon() in DeleteOnCorrectThread(). + friend class base::DeleteHelper<RemoteCdmContext>; + + ~RemoteCdmContext() override; + + void RegisterForRemoteCallbacks(); + + void GetHwKeyDataInternal( + std::unique_ptr<media::DecryptConfig> decrypt_config, + const std::vector<uint8_t>& hw_identifier, + GetHwKeyDataCB callback); + + mojo::Remote<media::stable::mojom::StableCdmContext> stable_cdm_context_; + + scoped_refptr<base::SequencedTaskRunner> mojo_task_runner_; + + mojo::Receiver<media::stable::mojom::CdmContextEventCallback> + event_callback_receiver_{this}; + + media::CallbackRegistry<EventCB::RunType> event_callbacks_; + + // WeakPtrFactory to use for callbacks. + base::WeakPtrFactory<RemoteCdmContext> weak_ptr_factory_{this}; +}; + +struct COMPONENT_EXPORT(CDM_FACTORY_DAEMON) RemoteCdmContextTraits { + // Destroys |remote_cdm_context| on the correct thread. + static void Destruct(const RemoteCdmContext* remote_cdm_context); +}; + +} // namespace chromeos + +#endif // CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_REMOTE_CDM_CONTEXT_H_
diff --git a/chromeos/components/cdm_factory_daemon/stable_cdm_context_impl.cc b/chromeos/components/cdm_factory_daemon/stable_cdm_context_impl.cc new file mode 100644 index 0000000..311afc5 --- /dev/null +++ b/chromeos/components/cdm_factory_daemon/stable_cdm_context_impl.cc
@@ -0,0 +1,55 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/components/cdm_factory_daemon/stable_cdm_context_impl.h" + +#include "base/callback.h" +#include "chromeos/components/cdm_factory_daemon/chromeos_cdm_context.h" +#include "chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.h" + +namespace chromeos { + +StableCdmContextImpl::StableCdmContextImpl(media::CdmContext* cdm_context) + : cdm_context_(cdm_context) { + DCHECK(cdm_context_); + DCHECK(cdm_context_->GetChromeOsCdmContext()); + cdm_context_ref_ = cdm_context_->GetChromeOsCdmContext()->GetCdmContextRef(); +} + +StableCdmContextImpl::~StableCdmContextImpl() {} + +void StableCdmContextImpl::GetHwKeyData( + std::unique_ptr<media::DecryptConfig> decrypt_config, + const std::vector<uint8_t>& hw_identifier, + GetHwKeyDataCallback callback) { + cdm_context_->GetChromeOsCdmContext()->GetHwKeyData( + decrypt_config.get(), hw_identifier, std::move(callback)); +} + +void StableCdmContextImpl::RegisterEventCallback( + mojo::PendingRemote<media::stable::mojom::CdmContextEventCallback> + callback) { + remote_event_callbacks_.Add(std::move(callback)); + if (!callback_registration_) { + callback_registration_ = cdm_context_->RegisterEventCB( + base::BindRepeating(&StableCdmContextImpl::CdmEventCallback, + weak_ptr_factory_.GetWeakPtr())); + } +} + +void StableCdmContextImpl::GetHwConfigData(GetHwConfigDataCallback callback) { + ChromeOsCdmFactory::GetHwConfigData(std::move(callback)); +} + +void StableCdmContextImpl::GetScreenResolutions( + GetScreenResolutionsCallback callback) { + ChromeOsCdmFactory::GetScreenResolutions(std::move(callback)); +} + +void StableCdmContextImpl::CdmEventCallback(media::CdmContext::Event event) { + for (auto& cb : remote_event_callbacks_) + cb->EventCallback(event); +} + +} // namespace chromeos
diff --git a/chromeos/components/cdm_factory_daemon/stable_cdm_context_impl.h b/chromeos/components/cdm_factory_daemon/stable_cdm_context_impl.h new file mode 100644 index 0000000..50fd6a8 --- /dev/null +++ b/chromeos/components/cdm_factory_daemon/stable_cdm_context_impl.h
@@ -0,0 +1,61 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_STABLE_CDM_CONTEXT_IMPL_H_ +#define CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_STABLE_CDM_CONTEXT_IMPL_H_ + +#include <memory> + +#include "base/component_export.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "media/base/callback_registry.h" +#include "media/base/cdm_context.h" +#include "media/mojo/mojom/stable/stable_video_decoder.mojom.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/remote_set.h" + +namespace chromeos { + +// Provides the receiving implementation for the CdmContext Mojo interface +// used with out of process video decoding. This will run in the GPU process and +// is used by the OOPVideoDecoder. The remote end of it will run in the video +// decoder utility process launched from ash-chrome. +class COMPONENT_EXPORT(CDM_FACTORY_DAEMON) StableCdmContextImpl + : public media::stable::mojom::StableCdmContext { + public: + explicit StableCdmContextImpl(media::CdmContext* cdm_context); + + StableCdmContextImpl(const StableCdmContextImpl&) = delete; + StableCdmContextImpl& operator=(const StableCdmContextImpl&) = delete; + + ~StableCdmContextImpl() override; + + // media::stable::mojom::StableCdmContext: + void GetHwKeyData(std::unique_ptr<media::DecryptConfig> decrypt_config, + const std::vector<uint8_t>& hw_identifier, + GetHwKeyDataCallback callback) override; + void RegisterEventCallback( + mojo::PendingRemote<media::stable::mojom::CdmContextEventCallback> + callback) override; + void GetHwConfigData(GetHwConfigDataCallback callback) override; + void GetScreenResolutions(GetScreenResolutionsCallback callback) override; + + private: + // Receives callbacks from the |cdm_context_| after we register with it. + void CdmEventCallback(media::CdmContext::Event event); + + const raw_ptr<media::CdmContext> cdm_context_; + std::unique_ptr<media::CdmContextRef> cdm_context_ref_; + std::unique_ptr<media::CallbackRegistration> callback_registration_; + mojo::RemoteSet<media::stable::mojom::CdmContextEventCallback> + remote_event_callbacks_; + + // WeakPtrFactory to use for callbacks. + base::WeakPtrFactory<StableCdmContextImpl> weak_ptr_factory_{this}; +}; + +} // namespace chromeos + +#endif // CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_STABLE_CDM_CONTEXT_IMPL_H_
diff --git a/chromeos/tast_control.gni b/chromeos/tast_control.gni index 138fe19..79f55a0 100644 --- a/chromeos/tast_control.gni +++ b/chromeos/tast_control.gni
@@ -265,6 +265,10 @@ # https://crbug.com/1350880 "arc.PIPRoundedCornersUnderlay", + + # http://b/242172965 + "crostini.SSHFSMount.buster_stable", + "crostini.SSHFSMount.bullseye_stable", ] # To create filters to be used on specific builders add them like this:
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 18e22473..d7af9e7 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -187,6 +187,8 @@ "form_parsing/field_candidates.h", "form_parsing/form_field.cc", "form_parsing/form_field.h", + "form_parsing/iban_field.cc", + "form_parsing/iban_field.h", "form_parsing/merchant_promo_code_field.cc", "form_parsing/merchant_promo_code_field.h", "form_parsing/name_field.cc", @@ -819,6 +821,7 @@ "form_parsing/credit_card_field_unittest.cc", "form_parsing/field_candidates_unittest.cc", "form_parsing/form_field_unittest.cc", + "form_parsing/iban_field_unittest.cc", "form_parsing/merchant_promo_code_field_unittest.cc", "form_parsing/name_field_unittest.cc", "form_parsing/parsing_test_utils.cc",
diff --git a/components/autofill/core/browser/autofill_field.cc b/components/autofill/core/browser/autofill_field.cc index 757a5bae..abc1795 100644 --- a/components/autofill/core/browser/autofill_field.cc +++ b/components/autofill/core/browser/autofill_field.cc
@@ -204,8 +204,14 @@ (heuristic_type() == ADDRESS_HOME_STREET_NAME || heuristic_type() == ADDRESS_HOME_HOUSE_NUMBER)); + // For merchant promo code fields the heuristic predictions get precedence + // over the server predictions. believe_server = - believe_server && !(heuristic_type() == MERCHANT_PROMO_CODE); + believe_server && (heuristic_type() != MERCHANT_PROMO_CODE); + + // For international bank account number (IBAN) fields the heuristic + // predictions get precedence over the server predictions. + believe_server = believe_server && (heuristic_type() != IBAN_VALUE); if (believe_server) return AutofillType(server_type());
diff --git a/components/autofill/core/browser/autofill_regex_constants.h b/components/autofill/core/browser/autofill_regex_constants.h index c560393..73a92dc9 100644 --- a/components/autofill/core/browser/autofill_regex_constants.h +++ b/components/autofill/core/browser/autofill_regex_constants.h
@@ -581,12 +581,17 @@ u"yesbankltd" u")$"; -// Used to match field data that might be an International Bank Account Number. +// Used to match the HTML name and label for International Bank Account Number +// (IBAN). +inline constexpr char16_t kIBANRe[] = + u"(\\biban(\\b|_)|international bank account number)"; + +// Used to match field value that might be an International Bank Account Number. // TODO(crbug.com/977377): The regex doesn't match IBANs for Saint Lucia (LC), // Kazakhstan (KZ) and Romania (RO). Consider replace the regex with something // like "(?:IT|SM)\d{2}[A-Z]\d{22}|CY\d{2}[A-Z]\d{23}...". For reference: // - https://www.swift.com/resource/iban-registry-pdf -inline constexpr char16_t kInternationalBankAccountNumberRe[] = +inline constexpr char16_t kInternationalBankAccountNumberValueRe[] = u"^[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{4}[0-9]{7}([a-zA-Z0-9]?){0,16}$"; // Matches all 3 and 4 digit numbers.
diff --git a/components/autofill/core/browser/autofill_type.cc b/components/autofill/core/browser/autofill_type.cc index 03b60e7..9153d9a 100644 --- a/components/autofill/core/browser/autofill_type.cc +++ b/components/autofill/core/browser/autofill_type.cc
@@ -201,6 +201,9 @@ case HTML_TYPE_MERCHANT_PROMO_CODE: return FieldTypeGroup::kNoGroup; + case HTML_TYPE_IBAN: + return FieldTypeGroup::kNoGroup; + case HTML_TYPE_UNSPECIFIED: case HTML_TYPE_UNRECOGNIZED: return FieldTypeGroup::kNoGroup; @@ -374,6 +377,7 @@ case HTML_TYPE_TRANSACTION_CURRENCY: case HTML_TYPE_ONE_TIME_CODE: case HTML_TYPE_MERCHANT_PROMO_CODE: + case HTML_TYPE_IBAN: return UNKNOWN_TYPE; case HTML_TYPE_UNRECOGNIZED:
diff --git a/components/autofill/core/browser/data_model/credit_card.cc b/components/autofill/core/browser/data_model/credit_card.cc index 2df69bc..94d167f7 100644 --- a/components/autofill/core/browser/data_model/credit_card.cc +++ b/components/autofill/core/browser/data_model/credit_card.cc
@@ -866,9 +866,7 @@ SetExpirationYear(num); } -const std::pair<std::u16string, std::u16string> CreditCard::LabelPieces() - const { - std::u16string label; +std::pair<std::u16string, std::u16string> CreditCard::LabelPieces() const { if (number().empty()) { // No CC number, if valid nickname is present, return nickname only. // Otherwise, return cardholder name only. @@ -878,22 +876,16 @@ return std::make_pair(name_on_card_, std::u16string()); } - std::u16string obfuscated_cc_number = - CardIdentifierStringForAutofillDisplay(); - // No expiration date set. - if (!expiration_month_ || !expiration_year_) - return std::make_pair(obfuscated_cc_number, std::u16string()); - - std::u16string formatted_date = ExpirationDateForDisplay(); - - std::u16string separator = - l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR); - return std::make_pair(obfuscated_cc_number, separator + formatted_date); + return std::make_pair(CardIdentifierStringForAutofillDisplay(), + name_on_card_); } -const std::u16string CreditCard::Label() const { +std::u16string CreditCard::Label() const { std::pair<std::u16string, std::u16string> pieces = LabelPieces(); - return pieces.first + pieces.second; + if (pieces.first.empty() || pieces.second.empty()) + return pieces.first + pieces.second; + + return pieces.first + u", " + pieces.second; } std::u16string CreditCard::LastFourDigits() const {
diff --git a/components/autofill/core/browser/data_model/credit_card.h b/components/autofill/core/browser/data_model/credit_card.h index eeb9dab..cb8daaf 100644 --- a/components/autofill/core/browser/data_model/credit_card.h +++ b/components/autofill/core/browser/data_model/credit_card.h
@@ -275,11 +275,11 @@ // Various display functions. - // Card preview summary, for example: "Nickname/Network - ****1234", - // ", 01/2020". - const std::pair<std::u16string, std::u16string> LabelPieces() const; + // Card preview summary, for example: "Nickname/Network - ****1234 John + // Smith". + std::pair<std::u16string, std::u16string> LabelPieces() const; // Like LabelPieces, but appends the two pieces together. - const std::u16string Label() const; + std::u16string Label() const; // The last four digits of the card number (or possibly less if there aren't // enough characters). std::u16string LastFourDigits() const;
diff --git a/components/autofill/core/browser/data_model/credit_card_unittest.cc b/components/autofill/core/browser/data_model/credit_card_unittest.cc index ebfcc92..3e704144 100644 --- a/components/autofill/core/browser/data_model/credit_card_unittest.cc +++ b/components/autofill/core/browser/data_model/credit_card_unittest.cc
@@ -103,81 +103,57 @@ // Tests credit card summary string generation. This test simulates a variety // of different possible summary strings. Variations occur based on the // existence of credit card number, month, and year fields. -TEST(CreditCardTest, PreviewSummaryAndNetworkAndLastFourDigitsStrings) { +TEST(CreditCardTest, LabelSummary) { std::u16string valid_nickname = u"My Visa Card"; // Case 0: empty credit card. CreditCard credit_card0(base::GenerateGUID(), "https://www.example.com/"); - std::u16string summary0 = credit_card0.Label(); - EXPECT_EQ(std::u16string(), summary0); - std::u16string obfuscated0 = credit_card0.NetworkAndLastFourDigits(); - EXPECT_EQ(ASCIIToUTF16(std::string("Card")), obfuscated0); + EXPECT_EQ(std::u16string(), credit_card0.Label()); // Case 00: Empty credit card with empty strings. CreditCard credit_card00(base::GenerateGUID(), "https://www.example.com/"); test::SetCreditCardInfo(&credit_card00, "John Dillinger", "", "", "", ""); - std::u16string summary00 = credit_card00.Label(); - EXPECT_EQ(std::u16string(u"John Dillinger"), summary00); - std::u16string obfuscated00 = credit_card00.NetworkAndLastFourDigits(); - EXPECT_EQ(ASCIIToUTF16(std::string("Card")), obfuscated00); + EXPECT_EQ(std::u16string(u"John Dillinger"), credit_card00.Label()); // Case 1: No credit card number. CreditCard credit_card1(base::GenerateGUID(), "https://www.example.com/"); test::SetCreditCardInfo(&credit_card1, "John Dillinger", "", "01", "2010", "1"); - std::u16string summary1 = credit_card1.Label(); - EXPECT_EQ(std::u16string(u"John Dillinger"), summary1); - std::u16string obfuscated1 = credit_card1.NetworkAndLastFourDigits(); - EXPECT_EQ(ASCIIToUTF16(std::string("Card")), obfuscated1); + EXPECT_EQ(std::u16string(u"John Dillinger"), credit_card1.Label()); // Case 1.1: No credit card number, but has nickname. CreditCard credit_card11(base::GenerateGUID(), "https://www.example.com/"); test::SetCreditCardInfo(&credit_card11, "John Dillinger", "", "01", "2010", "1"); credit_card11.SetNickname(valid_nickname); - std::u16string summary11 = credit_card11.Label(); - EXPECT_EQ(valid_nickname, summary11); - std::u16string obfuscated11 = credit_card11.NetworkAndLastFourDigits(); - EXPECT_EQ(ASCIIToUTF16(std::string("Card")), obfuscated11); + EXPECT_EQ(valid_nickname, credit_card11.Label()); // Case 2: No month. CreditCard credit_card2(base::GenerateGUID(), "https://www.example.com/"); test::SetCreditCardInfo(&credit_card2, "John Dillinger", "5105 1051 0510 5100", "", "2010", "1"); - std::u16string summary2 = credit_card2.Label(); EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") + - test::ObfuscatedCardDigitsAsUTF8("5100")), - summary2); - std::u16string obfuscated2 = credit_card2.NetworkAndLastFourDigits(); - EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") + - test::ObfuscatedCardDigitsAsUTF8("5100")), - obfuscated2); + test::ObfuscatedCardDigitsAsUTF8("5100") + + ", John Dillinger"), + credit_card2.Label()); // Case 3: No year. CreditCard credit_card3(base::GenerateGUID(), "https://www.example.com/"); test::SetCreditCardInfo(&credit_card3, "John Dillinger", "5105 1051 0510 5100", "01", "", "1"); - std::u16string summary3 = credit_card3.Label(); EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") + - test::ObfuscatedCardDigitsAsUTF8("5100")), - summary3); - std::u16string obfuscated3 = credit_card3.NetworkAndLastFourDigits(); - EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") + - test::ObfuscatedCardDigitsAsUTF8("5100")), - obfuscated3); + test::ObfuscatedCardDigitsAsUTF8("5100") + + ", John Dillinger"), + credit_card3.Label()); // Case 4: Have everything except nickname. CreditCard credit_card4(base::GenerateGUID(), "https://www.example.com/"); test::SetCreditCardInfo(&credit_card4, "John Dillinger", "5105 1051 0510 5100", "01", "2010", "1"); - std::u16string summary4 = credit_card4.Label(); EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") + - test::ObfuscatedCardDigitsAsUTF8("5100") + ", 01/2010"), - summary4); - std::u16string obfuscated4 = credit_card4.NetworkAndLastFourDigits(); - EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") + - test::ObfuscatedCardDigitsAsUTF8("5100")), - obfuscated4); + test::ObfuscatedCardDigitsAsUTF8("5100") + + ", John Dillinger"), + credit_card4.Label()); // Case 5: Very long credit card CreditCard credit_card5(base::GenerateGUID(), "https://www.example.com/"); @@ -185,26 +161,94 @@ &credit_card5, "John Dillinger", "0123456789 0123456789 0123456789 5105 1051 0510 5100", "01", "2010", "1"); - std::u16string summary5 = credit_card5.Label(); EXPECT_EQ(UTF8ToUTF16(std::string("Card ") + - test::ObfuscatedCardDigitsAsUTF8("5100") + ", 01/2010"), - summary5); - std::u16string obfuscated5 = credit_card5.NetworkAndLastFourDigits(); - EXPECT_EQ(UTF8ToUTF16(std::string("Card ") + - test::ObfuscatedCardDigitsAsUTF8("5100")), - obfuscated5); + test::ObfuscatedCardDigitsAsUTF8("5100") + + ", John Dillinger"), + credit_card5.Label()); // Case 6: Have everything including nickname. CreditCard credit_card6(base::GenerateGUID(), "https://www.example.com/"); test::SetCreditCardInfo(&credit_card6, "John Dillinger", "5105 1051 0510 5100", "01", "2010", "1"); credit_card6.SetNickname(valid_nickname); - std::u16string summary6 = credit_card6.Label(); EXPECT_EQ( - valid_nickname + - UTF8ToUTF16(std::string(" ") + - test::ObfuscatedCardDigitsAsUTF8("5100") + ", 01/2010"), - summary6); + valid_nickname + UTF8ToUTF16(std::string(" ") + + test::ObfuscatedCardDigitsAsUTF8("5100") + + ", John Dillinger"), + credit_card6.Label()); +} + +TEST(CreditCardTest, NetworkAndLastFourDigits) { + std::u16string valid_nickname = u"My Visa Card"; + + // Case 0: empty credit card. + CreditCard credit_card0(base::GenerateGUID(), "https://www.example.com/"); + EXPECT_EQ(ASCIIToUTF16(std::string("Card")), + credit_card0.NetworkAndLastFourDigits()); + + // Case 00: Empty credit card with empty strings. + CreditCard credit_card00(base::GenerateGUID(), "https://www.example.com/"); + test::SetCreditCardInfo(&credit_card00, "John Dillinger", "", "", "", ""); + EXPECT_EQ(ASCIIToUTF16(std::string("Card")), + credit_card00.NetworkAndLastFourDigits()); + + // Case 1: No credit card number. + CreditCard credit_card1(base::GenerateGUID(), "https://www.example.com/"); + test::SetCreditCardInfo(&credit_card1, "John Dillinger", "", "01", "2010", + "1"); + EXPECT_EQ(ASCIIToUTF16(std::string("Card")), + credit_card1.NetworkAndLastFourDigits()); + + // Case 1.1: No credit card number, but has nickname. + CreditCard credit_card11(base::GenerateGUID(), "https://www.example.com/"); + test::SetCreditCardInfo(&credit_card11, "John Dillinger", "", "01", "2010", + "1"); + credit_card11.SetNickname(valid_nickname); + EXPECT_EQ(ASCIIToUTF16(std::string("Card")), + credit_card11.NetworkAndLastFourDigits()); + + // Case 2: No month. + CreditCard credit_card2(base::GenerateGUID(), "https://www.example.com/"); + test::SetCreditCardInfo(&credit_card2, "John Dillinger", + "5105 1051 0510 5100", "", "2010", "1"); + EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") + + test::ObfuscatedCardDigitsAsUTF8("5100")), + credit_card2.NetworkAndLastFourDigits()); + + // Case 3: No year. + CreditCard credit_card3(base::GenerateGUID(), "https://www.example.com/"); + test::SetCreditCardInfo(&credit_card3, "John Dillinger", + "5105 1051 0510 5100", "01", "", "1"); + EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") + + test::ObfuscatedCardDigitsAsUTF8("5100")), + credit_card3.NetworkAndLastFourDigits()); + + // Case 4: Have everything except nickname. + CreditCard credit_card4(base::GenerateGUID(), "https://www.example.com/"); + test::SetCreditCardInfo(&credit_card4, "John Dillinger", + "5105 1051 0510 5100", "01", "2010", "1"); + EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") + + test::ObfuscatedCardDigitsAsUTF8("5100")), + credit_card4.NetworkAndLastFourDigits()); + + // Case 5: Very long credit card + CreditCard credit_card5(base::GenerateGUID(), "https://www.example.com/"); + test::SetCreditCardInfo( + &credit_card5, "John Dillinger", + "0123456789 0123456789 0123456789 5105 1051 0510 5100", "01", "2010", + "1"); + EXPECT_EQ(UTF8ToUTF16(std::string("Card ") + + test::ObfuscatedCardDigitsAsUTF8("5100")), + credit_card5.NetworkAndLastFourDigits()); + + // Case 6: Have everything including nickname. + CreditCard credit_card6(base::GenerateGUID(), "https://www.example.com/"); + test::SetCreditCardInfo(&credit_card6, "John Dillinger", + "5105 1051 0510 5100", "01", "2010", "1"); + credit_card6.SetNickname(valid_nickname); + EXPECT_EQ(UTF8ToUTF16(std::string("Mastercard ") + + test::ObfuscatedCardDigitsAsUTF8("5100")), + credit_card6.NetworkAndLastFourDigits()); } TEST(CreditCardTest, NicknameAndLastFourDigitsStrings) {
diff --git a/components/autofill/core/browser/field_types.cc b/components/autofill/core/browser/field_types.cc index 20ee50f8e..537ba0a 100644 --- a/components/autofill/core/browser/field_types.cc +++ b/components/autofill/core/browser/field_types.cc
@@ -101,9 +101,8 @@ case UPI_VPA: return base::FeatureList::IsEnabled(features::kAutofillSaveAndFillVPA); - // TODO(crbug/1335549) to return true when the flag is enabled. case IBAN_VALUE: - return false; + return base::FeatureList::IsEnabled(features::kAutofillParseIBANFields); case COMPANY_NAME: return true; @@ -425,6 +424,8 @@ return "HTML_TYPE_ONE_TIME_CODE"; case HTML_TYPE_MERCHANT_PROMO_CODE: return "HTML_TYPE_MERCHANT_PROMO_CODE"; + case HTML_TYPE_IBAN: + return "HTML_TYPE_IBAN"; case HTML_TYPE_UNRECOGNIZED: return "HTML_TYPE_UNRECOGNIZED"; }
diff --git a/components/autofill/core/browser/field_types.h b/components/autofill/core/browser/field_types.h index 496ab51..16ff815 100644 --- a/components/autofill/core/browser/field_types.h +++ b/components/autofill/core/browser/field_types.h
@@ -239,7 +239,9 @@ PHONE_HOME_NUMBER_PREFIX = 123, PHONE_HOME_NUMBER_SUFFIX = 124, - // IBAN data. + // International Bank Account Number (IBAN) details are usually entered on + // banking and merchant websites used to make international transactions. + // See https://en.wikipedia.org/wiki/International_Bank_Account_Number. IBAN_VALUE = 125, // No new types can be added without a corresponding change to the Autofill // server.
diff --git a/components/autofill/core/browser/form_parsing/form_field.cc b/components/autofill/core/browser/form_parsing/form_field.cc index 1dbf810..e2ed3af3 100644 --- a/components/autofill/core/browser/form_parsing/form_field.cc +++ b/components/autofill/core/browser/form_parsing/form_field.cc
@@ -26,6 +26,7 @@ #include "components/autofill/core/browser/form_parsing/birthdate_field.h" #include "components/autofill/core/browser/form_parsing/credit_card_field.h" #include "components/autofill/core/browser/form_parsing/email_field.h" +#include "components/autofill/core/browser/form_parsing/iban_field.h" #include "components/autofill/core/browser/form_parsing/merchant_promo_code_field.h" #include "components/autofill/core/browser/form_parsing/name_field.h" #include "components/autofill/core/browser/form_parsing/phone_field.h" @@ -191,6 +192,12 @@ field_candidates, page_language, pattern_source, log_manager); } + + // IBAN pass. + if (base::FeatureList::IsEnabled(features::kAutofillParseIBANFields)) { + ParseFormFieldsPass(IBANField::Parse, processed_fields, field_candidates, + page_language, pattern_source, log_manager); + } } // static @@ -501,7 +508,7 @@ // static bool FormField::IsSingleFieldParseableType(ServerFieldType field_type) { - return field_type == MERCHANT_PROMO_CODE; + return field_type == MERCHANT_PROMO_CODE || field_type == IBAN_VALUE; } // static
diff --git a/components/autofill/core/browser/form_parsing/form_field.h b/components/autofill/core/browser/form_parsing/form_field.h index 0404742..6cd50974 100644 --- a/components/autofill/core/browser/form_parsing/form_field.h +++ b/components/autofill/core/browser/form_parsing/form_field.h
@@ -93,13 +93,14 @@ // Initial values assigned to FieldCandidates by their corresponding parsers. // There's an implicit precedence determined by the values assigned here. // Email is currently the most important followed by Phone, Travel, Address, - // Birthdate, Credit Card, Price, Name, Merchant promo code, and Search. + // Birthdate, Credit Card, IBAN, Price, Name, Merchant promo code, and Search. static constexpr float kBaseEmailParserScore = 1.4f; static constexpr float kBasePhoneParserScore = 1.3f; static constexpr float kBaseTravelParserScore = 1.2f; static constexpr float kBaseAddressParserScore = 1.1f; static constexpr float kBaseBirthdateParserScore = 1.05f; static constexpr float kBaseCreditCardParserScore = 1.0f; + static constexpr float kBaseIBANParserScore = 0.975f; static constexpr float kBasePriceParserScore = 0.95f; static constexpr float kBaseNameParserScore = 0.9f; static constexpr float kBaseMerchantPromoCodeParserScore = 0.85f;
diff --git a/components/autofill/core/browser/form_parsing/form_field_unittest.cc b/components/autofill/core/browser/form_parsing/form_field_unittest.cc index 5292514..f6d7f86 100644 --- a/components/autofill/core/browser/form_parsing/form_field_unittest.cc +++ b/components/autofill/core/browser/form_parsing/form_field_unittest.cc
@@ -211,7 +211,7 @@ } // Test that `ParseSingleFieldForms` parses single field promo codes. -TEST_P(FormFieldTest, ParseSingleFieldFormsPromoCode) { +TEST_P(FormFieldTest, ParseFormFieldsForSingleFieldPromoCode) { base::test::ScopedFeatureList scoped_feature; scoped_feature.InitAndEnableFeature( features::kAutofillParseMerchantPromoCodeFields); @@ -229,6 +229,24 @@ TestClassificationExpectations(); } +// Test that `ParseSingleFieldForms` parses single field IBAN. +TEST_P(FormFieldTest, ParseSingleFieldFormsIban) { + base::test::ScopedFeatureList scoped_feature; + scoped_feature.InitAndEnableFeature(features::kAutofillParseIBANFields); + + // Parse single field IBAN. + AddTextFormFieldData("", "IBAN", IBAN_VALUE); + EXPECT_EQ(1, ParseSingleFieldForms()); + TestClassificationExpectations(); + + // Don't parse other fields. + // UNKNOWN_TYPE is used as the expected type, which prevents it from being + // part of the expectations in `TestClassificationExpectations()`. + AddTextFormFieldData("", "Address line 1", UNKNOWN_TYPE); + EXPECT_EQ(1, ParseSingleFieldForms()); + TestClassificationExpectations(); +} + struct ParseInAnyOrderTestcase { // An nxn matrix, describing that field i is matched by parser j. std::vector<std::vector<bool>> field_matches_parser;
diff --git a/components/autofill/core/browser/form_parsing/iban_field.cc b/components/autofill/core/browser/form_parsing/iban_field.cc new file mode 100644 index 0000000..4526a33 --- /dev/null +++ b/components/autofill/core/browser/form_parsing/iban_field.cc
@@ -0,0 +1,42 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/form_parsing/iban_field.h" + +#include "components/autofill/core/browser/autofill_field.h" +#include "components/autofill/core/browser/autofill_regex_constants.h" +#include "components/autofill/core/browser/form_parsing/autofill_scanner.h" +#include "components/autofill/core/common/autofill_payments_features.h" + +namespace autofill { + +// static +std::unique_ptr<FormField> IBANField::Parse(AutofillScanner* scanner, + const LanguageCode& page_language, + PatternSource pattern_source, + LogManager* log_manager) { + if (!base::FeatureList::IsEnabled(features::kAutofillParseIBANFields)) + return nullptr; + + AutofillField* field; + base::span<const MatchPatternRef> iban_patterns = + GetMatchPatterns(IBAN_VALUE, page_language, pattern_source); + + if (ParseFieldSpecifics(scanner, kIBANRe, + kDefaultMatchParamsWith<MatchFieldType::kNumber, + MatchFieldType::kTextArea>, + iban_patterns, &field, {log_manager, "kIBANRe"})) { + return std::make_unique<IBANField>(field); + } + + return nullptr; +} + +IBANField::IBANField(const AutofillField* field) : field_(field) {} + +void IBANField::AddClassifications(FieldCandidatesMap& field_candidates) const { + AddClassification(field_, IBAN_VALUE, kBaseIBANParserScore, field_candidates); +} + +} // namespace autofill
diff --git a/components/autofill/core/browser/form_parsing/iban_field.h b/components/autofill/core/browser/form_parsing/iban_field.h new file mode 100644 index 0000000..d8b4339 --- /dev/null +++ b/components/autofill/core/browser/form_parsing/iban_field.h
@@ -0,0 +1,42 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_PARSING_IBAN_FIELD_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_PARSING_IBAN_FIELD_H_ + +#include <memory> + +#include "base/memory/raw_ptr.h" +#include "components/autofill/core/browser/form_parsing/form_field.h" +#include "components/autofill/core/common/language_code.h" + +namespace autofill { + +class AutofillField; +class AutofillScanner; +class LogManager; + +// A form field that accepts International Bank Account Number (IBAN). +class IBANField : public FormField { + public: + static std::unique_ptr<FormField> Parse(AutofillScanner* scanner, + const LanguageCode& page_language, + PatternSource pattern_source, + LogManager* log_manager); + + explicit IBANField(const AutofillField* field); + + IBANField(const IBANField&) = delete; + IBANField& operator=(const IBANField&) = delete; + + protected: + void AddClassifications(FieldCandidatesMap& field_candidates) const override; + + private: + raw_ptr<const AutofillField> field_; +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_PARSING_IBAN_FIELD_H_
diff --git a/components/autofill/core/browser/form_parsing/iban_field_unittest.cc b/components/autofill/core/browser/form_parsing/iban_field_unittest.cc new file mode 100644 index 0000000..f5a39d1 --- /dev/null +++ b/components/autofill/core/browser/form_parsing/iban_field_unittest.cc
@@ -0,0 +1,68 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/form_parsing/iban_field.h" + +#include "base/test/scoped_feature_list.h" +#include "components/autofill/core/browser/form_parsing/parsing_test_utils.h" +#include "components/autofill/core/common/autofill_payments_features.h" + +namespace autofill { + +class IBANFieldTest + : public FormFieldTestBase, + public testing::TestWithParam<PatternProviderFeatureState> { + public: + IBANFieldTest() : FormFieldTestBase(GetParam()) {} + IBANFieldTest(const IBANFieldTest&) = delete; + IBANFieldTest& operator=(const IBANFieldTest&) = delete; + + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillParseIBANFields); + } + + protected: + std::unique_ptr<FormField> Parse( + AutofillScanner* scanner, + const LanguageCode& page_language = LanguageCode("en")) override { + return IBANField::Parse(scanner, page_language, GetActivePatternSource(), + /*log_manager=*/nullptr); + } + + base::test::ScopedFeatureList scoped_feature_list_; +}; + +INSTANTIATE_TEST_SUITE_P( + IBANFieldTest, + IBANFieldTest, + ::testing::ValuesIn(PatternProviderFeatureState::All())); + +// Match IBAN +TEST_P(IBANFieldTest, ParseIban) { + AddTextFormFieldData("iban-field", "Enter account number", IBAN_VALUE); + + ClassifyAndVerify(ParseResult::PARSED); +} + +TEST_P(IBANFieldTest, ParseIbanBanks) { + AddTextFormFieldData("accountNumber", "IBAN*", IBAN_VALUE); + + ClassifyAndVerify(ParseResult::PARSED); +} + +TEST_P(IBANFieldTest, ParseNonIban) { + AddTextFormFieldData("other-field", "Field for Account Number", UNKNOWN_TYPE); + + ClassifyAndVerify(ParseResult::NOT_PARSED); +} + +TEST_P(IBANFieldTest, ParseIbanFlagOff) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(features::kAutofillParseIBANFields); + AddTextFormFieldData("iban-field", "Enter IBAN here", IBAN_VALUE); + + ClassifyAndVerify(ParseResult::NOT_PARSED); +} +} // namespace autofill
diff --git a/components/autofill/core/browser/form_parsing/resources/legacy_regex_patterns.json b/components/autofill/core/browser/form_parsing/resources/legacy_regex_patterns.json index a4217b5a..d03eae03 100644 --- a/components/autofill/core/browser/form_parsing/resources/legacy_regex_patterns.json +++ b/components/autofill/core/browser/form_parsing/resources/legacy_regex_patterns.json
@@ -3315,5 +3315,17 @@ "match_field_input_types": [0] } ] + }, + "IBAN_VALUE": { + "en": [ + { + "pattern_identifier": "en_iban_preserving", + "positive_pattern": "(\\biban(\\b|_)|international bank account number)", + "positive_score": 0.975, + "negative_pattern": null, + "match_field_attributes": [0, 1], + "match_field_input_types": [0] + } + ] } }
diff --git a/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.cc b/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.cc index 38c9829..7773dfb 100644 --- a/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.cc +++ b/components/autofill/core/browser/form_processing/autocomplete_attribute_processing_util.cc
@@ -156,6 +156,7 @@ {"company", HTML_TYPE_ORGANIZATION}, {"first-name", HTML_TYPE_GIVEN_NAME}, {"gift-code", HTML_TYPE_MERCHANT_PROMO_CODE}, + {"iban", HTML_TYPE_IBAN}, {"locality", HTML_TYPE_ADDRESS_LEVEL2}, {"promo-code", HTML_TYPE_MERCHANT_PROMO_CODE}, {"promotional-code", HTML_TYPE_MERCHANT_PROMO_CODE},
diff --git a/components/autofill/core/browser/validation.cc b/components/autofill/core/browser/validation.cc index 2e9eae6..d81a9b46 100644 --- a/components/autofill/core/browser/validation.cc +++ b/components/autofill/core/browser/validation.cc
@@ -350,7 +350,7 @@ bool IsInternationalBankAccountNumber(const std::u16string& value) { std::u16string no_spaces; base::RemoveChars(value, u" ", &no_spaces); - return MatchesRegex<kInternationalBankAccountNumberRe>(no_spaces); + return MatchesRegex<kInternationalBankAccountNumberValueRe>(no_spaces); } bool IsPlausibleCreditCardCVCNumber(const std::u16string& value) {
diff --git a/components/autofill/core/common/html_field_types.h b/components/autofill/core/common/html_field_types.h index c3a7c31..0cfcdfe2 100644 --- a/components/autofill/core/common/html_field_types.h +++ b/components/autofill/core/common/html_field_types.h
@@ -91,6 +91,9 @@ // Promo code for merchant sites. HTML_TYPE_MERCHANT_PROMO_CODE, + // International Bank Account Number (IBAN) for banking and merchant sites. + HTML_TYPE_IBAN, + // Non-standard autocomplete types. HTML_TYPE_UNRECOGNIZED, };
diff --git a/components/browser_ui/site_settings/android/website_preference_bridge.cc b/components/browser_ui/site_settings/android/website_preference_bridge.cc index 40c23141..90f97ba 100644 --- a/components/browser_ui/site_settings/android/website_preference_bridge.cc +++ b/components/browser_ui/site_settings/android/website_preference_bridge.cc
@@ -39,6 +39,7 @@ #include "content/public/browser/android/browser_context_handle.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/permission_controller.h" #include "content/public/browser/storage_partition.h" #include "services/network/public/mojom/cookie_manager.mojom.h" #include "storage/browser/quota/quota_manager.h" @@ -194,20 +195,39 @@ ContentSettingsType content_type, jstring origin, jstring embedder) { - GURL url(ConvertJavaStringToUTF8(env, origin)); + GURL requesting_origin(ConvertJavaStringToUTF8(env, origin)); std::string embedder_str = ConvertJavaStringToUTF8(env, embedder); - GURL embedder_url; + GURL embedding_origin; // TODO(raymes): This check to see if '*' is the embedder is a hack that fixes // crbug.com/738377. In general querying the settings for patterns is broken // and needs to be fixed. See crbug.com/738757. if (embedder_str == "*") - embedder_url = url; + embedding_origin = requesting_origin; else - embedder_url = GURL(embedder_str); - return permissions::PermissionsClient::Get() - ->GetPermissionManager(unwrap(jbrowser_context_handle)) - ->GetPermissionStatusDeprecated(content_type, url, embedder_url) - .content_setting; + embedding_origin = GURL(embedder_str); + + // If `content_type` is permission, then we need to apply a set of + // verifications before reading its value in `HostContentSettingsMap`. + if (permissions::PermissionUtil::IsPermission(content_type)) { + BrowserContext* browser_context = unwrap(jbrowser_context_handle); + content::PermissionController* permission_controller = + browser_context->GetPermissionController(); + blink::mojom::PermissionStatus status = + permission_controller->GetPermissionStatusForOriginWithoutContext( + permissions::PermissionUtil::ContentSettingTypeToPermissionType( + content_type), + url::Origin::Create(requesting_origin), + url::Origin::Create(embedding_origin)); + return permissions::PermissionUtil::PermissionStatusToContentSetting( + status); + } else { + // If `content_type` is not permission, then we can directly read its value + // from `HostContentSettingsMap`. + HostContentSettingsMap* host_content_settings_map = + GetHostContentSettingsMap(jbrowser_context_handle); + return host_content_settings_map->GetContentSetting( + requesting_origin, embedding_origin, content_type); + } } void SetPermissionSettingForOrigin(
diff --git a/components/content_settings/android/cookie_controls_bridge.cc b/components/content_settings/android/cookie_controls_bridge.cc index f1808bc2..a3cb1119 100644 --- a/components/content_settings/android/cookie_controls_bridge.cc +++ b/components/content_settings/android/cookie_controls_bridge.cc
@@ -11,6 +11,7 @@ #include "components/permissions/permissions_client.h" #include "content/public/browser/android/browser_context_handle.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/web_contents.h" namespace content_settings {
diff --git a/components/content_settings/browser/page_specific_content_settings.cc b/components/content_settings/browser/page_specific_content_settings.cc index fe1ef5b..123175b 100644 --- a/components/content_settings/browser/page_specific_content_settings.cc +++ b/components/content_settings/browser/page_specific_content_settings.cc
@@ -34,12 +34,15 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/cookie_access_details.h" #include "content/public/browser/navigation_handle.h" +#include "content/public/browser/navigation_handle_user_data.h" #include "content/public/browser/page.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" #include "content/public/common/content_constants.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" @@ -59,39 +62,113 @@ !navigation_handle->IsPrerenderedPageActivation(); } +// Keeps track of cookie and service worker access during a navigation. +// These types of access can happen for the current page or for a new +// navigation (think cookies sent in the HTTP request or service worker +// being run to serve a fetch request). A navigation might fail to +// commit in which case we have to handle it as if it had never +// occurred. So we cache all cookies and service worker accesses that +// happen during a navigation and only apply the changes if the +// navigation commits. +class InflightNavigationContentSettings + : public content::NavigationHandleUserData< + InflightNavigationContentSettings> { + public: + ~InflightNavigationContentSettings() override; + std::vector<content::CookieAccessDetails> cookie_accesses; + std::vector<std::pair<GURL, content::AllowServiceWorkerResult>> + service_worker_accesses; + + private: + explicit InflightNavigationContentSettings( + content::NavigationHandle& navigation_handle); + friend class content::NavigationHandleUserData< + InflightNavigationContentSettings>; + NAVIGATION_HANDLE_USER_DATA_KEY_DECL(); +}; + +// This class attaches to WebContents to listen to events and route them to +// appropriate PageSpecificContentSettings, store navigation related events +// until the navigation finishes and then transferring the +// navigation-associated state to the newly-created page. +class WebContentsHandler + : public content::WebContentsObserver, + public content::WebContentsUserData<WebContentsHandler> { + public: + using Delegate = PageSpecificContentSettings::Delegate; + using SiteDataObserver = PageSpecificContentSettings::SiteDataObserver; + + explicit WebContentsHandler(content::WebContents* web_contents, + std::unique_ptr<Delegate> delegate); + ~WebContentsHandler() override; + // Adds the given |SiteDataObserver|. The |observer| is notified when a + // locale shared object, like for example a cookie, is accessed. + void AddSiteDataObserver(SiteDataObserver* observer); + + // Removes the given |SiteDataObserver|. + void RemoveSiteDataObserver(SiteDataObserver* observer); + + // Notifies all registered |SiteDataObserver|s. + void NotifySiteDataObservers(); + + Delegate* delegate() { return delegate_.get(); } + + private: + friend class content::WebContentsUserData<WebContentsHandler>; + + // Applies all stored events for the given navigation to the current main + // document. + void TransferNavigationContentSettingsToCommittedDocument( + const InflightNavigationContentSettings& navigation_settings, + content::RenderFrameHost* rfh); + + // content::WebContentsObserver overrides. + void ReadyToCommitNavigation( + content::NavigationHandle* navigation_handle) override; + void DidFinishNavigation( + content::NavigationHandle* navigation_handle) override; + void OnCookiesAccessed(content::NavigationHandle* navigation, + const content::CookieAccessDetails& details) override; + void OnCookiesAccessed(content::RenderFrameHost* rfh, + const content::CookieAccessDetails& details) override; + // Called when a specific Service Worker scope was accessed. + // If access was blocked due to the user's content settings, + // |blocked_by_policy_javascript| or/and |blocked_by_policy_cookie| + // should be true, and this function should invoke OnContentBlocked for + // JavaScript or/and cookies respectively. + void OnServiceWorkerAccessed( + content::NavigationHandle* navigation, + const GURL& scope, + content::AllowServiceWorkerResult allowed) override; + void OnServiceWorkerAccessed( + content::RenderFrameHost* frame, + const GURL& scope, + content::AllowServiceWorkerResult allowed) override; + + std::unique_ptr<Delegate> delegate_; + + raw_ptr<HostContentSettingsMap> map_; + + // All currently registered |SiteDataObserver|s. + base::ObserverList<SiteDataObserver>::Unchecked observer_list_; + + WEB_CONTENTS_USER_DATA_KEY_DECL(); +}; + } // namespace using StorageType = mojom::ContentSettingsManager::StorageType; -PageSpecificContentSettings::SiteDataObserver::SiteDataObserver( - content::WebContents* web_contents) - : web_contents_(web_contents) { - // Make sure the handler was attached to the WebContents as some UT might skip - // this. - auto* handler = - PageSpecificContentSettings::WebContentsHandler::FromWebContents( - web_contents_); - if (handler) - handler->AddSiteDataObserver(this); -} +InflightNavigationContentSettings::InflightNavigationContentSettings( + content::NavigationHandle&) {} -PageSpecificContentSettings::SiteDataObserver::~SiteDataObserver() { - if (!web_contents_) - return; - auto* handler = - PageSpecificContentSettings::WebContentsHandler::FromWebContents( - web_contents_); - if (handler) - handler->RemoveSiteDataObserver(this); -} +InflightNavigationContentSettings::~InflightNavigationContentSettings() = + default; -void PageSpecificContentSettings::SiteDataObserver::WebContentsDestroyed() { - web_contents_ = nullptr; -} +NAVIGATION_HANDLE_USER_DATA_KEY_IMPL(InflightNavigationContentSettings); -PageSpecificContentSettings::WebContentsHandler::WebContentsHandler( - content::WebContents* web_contents, - std::unique_ptr<Delegate> delegate) +WebContentsHandler::WebContentsHandler(content::WebContents* web_contents, + std::unique_ptr<Delegate> delegate) : WebContentsObserver(web_contents), content::WebContentsUserData<WebContentsHandler>(*web_contents), delegate_(std::move(delegate)), @@ -99,18 +176,17 @@ DCHECK( !PageSpecificContentSettings::GetForPage(web_contents->GetPrimaryPage())); content::PageUserData<PageSpecificContentSettings>::CreateForPage( - web_contents->GetPrimaryPage(), *this, delegate_.get()); + web_contents->GetPrimaryPage(), delegate_.get()); } -PageSpecificContentSettings::WebContentsHandler::~WebContentsHandler() { +WebContentsHandler::~WebContentsHandler() { for (SiteDataObserver& observer : observer_list_) observer.WebContentsDestroyed(); } -void PageSpecificContentSettings::WebContentsHandler:: - TransferNavigationContentSettingsToCommittedDocument( - const InflightNavigationContentSettings& navigation_settings, - content::RenderFrameHost* rfh) { +void WebContentsHandler::TransferNavigationContentSettingsToCommittedDocument( + const InflightNavigationContentSettings& navigation_settings, + content::RenderFrameHost* rfh) { for (const auto& cookie_access : navigation_settings.cookie_accesses) { OnCookiesAccessed(rfh, cookie_access); } @@ -121,7 +197,7 @@ } } -void PageSpecificContentSettings::WebContentsHandler::OnCookiesAccessed( +void WebContentsHandler::OnCookiesAccessed( content::NavigationHandle* navigation, const content::CookieAccessDetails& details) { if (WillNavigationCreateNewPageSpecificContentSettingsOnCommit(navigation)) { @@ -138,7 +214,7 @@ OnCookiesAccessed(navigation->GetParentFrame()->GetMainFrame(), details); } -void PageSpecificContentSettings::WebContentsHandler::OnCookiesAccessed( +void WebContentsHandler::OnCookiesAccessed( content::RenderFrameHost* rfh, const content::CookieAccessDetails& details) { auto* pscs = PageSpecificContentSettings::GetForPage(rfh->GetPage()); @@ -146,7 +222,7 @@ pscs->OnCookiesAccessed(details); } -void PageSpecificContentSettings::WebContentsHandler::OnServiceWorkerAccessed( +void WebContentsHandler::OnServiceWorkerAccessed( content::NavigationHandle* navigation, const GURL& scope, content::AllowServiceWorkerResult allowed) { @@ -168,7 +244,7 @@ allowed); } -void PageSpecificContentSettings::WebContentsHandler::OnServiceWorkerAccessed( +void WebContentsHandler::OnServiceWorkerAccessed( content::RenderFrameHost* frame, const GURL& scope, content::AllowServiceWorkerResult allowed) { @@ -177,7 +253,7 @@ pscs->OnServiceWorkerAccessed(scope, allowed); } -void PageSpecificContentSettings::WebContentsHandler::ReadyToCommitNavigation( +void WebContentsHandler::ReadyToCommitNavigation( content::NavigationHandle* navigation_handle) { content::RenderFrameHost* rfh = navigation_handle->GetRenderFrameHost(); @@ -200,7 +276,7 @@ agent->SendRendererContentSettingRules(std::move(rules)); } -void PageSpecificContentSettings::WebContentsHandler::DidFinishNavigation( +void WebContentsHandler::DidFinishNavigation( content::NavigationHandle* navigation_handle) { if (!navigation_handle->HasCommitted()) return; @@ -208,8 +284,7 @@ if (WillNavigationCreateNewPageSpecificContentSettingsOnCommit( navigation_handle)) { content::PageUserData<PageSpecificContentSettings>::CreateForPage( - navigation_handle->GetRenderFrameHost()->GetPage(), *this, - delegate_.get()); + navigation_handle->GetRenderFrameHost()->GetPage(), delegate_.get()); InflightNavigationContentSettings* inflight_settings = content::NavigationHandleUserData<InflightNavigationContentSettings>:: GetForNavigationHandle(*navigation_handle); @@ -232,56 +307,60 @@ delegate_->UpdateLocationBar(); } -void PageSpecificContentSettings::WebContentsHandler::AddSiteDataObserver( - SiteDataObserver* observer) { +void WebContentsHandler::AddSiteDataObserver(SiteDataObserver* observer) { observer_list_.AddObserver(observer); } -void PageSpecificContentSettings::WebContentsHandler::RemoveSiteDataObserver( - SiteDataObserver* observer) { +void WebContentsHandler::RemoveSiteDataObserver(SiteDataObserver* observer) { observer_list_.RemoveObserver(observer); } -void PageSpecificContentSettings::WebContentsHandler:: - NotifySiteDataObservers() { +void WebContentsHandler::NotifySiteDataObservers() { for (SiteDataObserver& observer : observer_list_) observer.OnSiteDataAccessed(); } -PageSpecificContentSettings::InflightNavigationContentSettings:: - InflightNavigationContentSettings(content::NavigationHandle&) {} +WEB_CONTENTS_USER_DATA_KEY_IMPL(WebContentsHandler); -PageSpecificContentSettings::InflightNavigationContentSettings:: - ~InflightNavigationContentSettings() = default; +PageSpecificContentSettings::SiteDataObserver::SiteDataObserver( + content::WebContents* web_contents) + : web_contents_(web_contents) { + // Make sure the handler was attached to the WebContents as some UT might skip + // this. + auto* handler = WebContentsHandler::FromWebContents(web_contents_); + if (handler) + handler->AddSiteDataObserver(this); +} -NAVIGATION_HANDLE_USER_DATA_KEY_IMPL( - PageSpecificContentSettings::InflightNavigationContentSettings); +PageSpecificContentSettings::SiteDataObserver::~SiteDataObserver() { + if (!web_contents_) + return; + auto* handler = WebContentsHandler::FromWebContents(web_contents_); + if (handler) + handler->RemoveSiteDataObserver(this); +} -WEB_CONTENTS_USER_DATA_KEY_IMPL( - PageSpecificContentSettings::WebContentsHandler); +void PageSpecificContentSettings::SiteDataObserver::WebContentsDestroyed() { + web_contents_ = nullptr; +} PageSpecificContentSettings::PendingUpdates::PendingUpdates() = default; PageSpecificContentSettings::PendingUpdates::~PendingUpdates() = default; -PageSpecificContentSettings::PageSpecificContentSettings( - content::Page& page, - PageSpecificContentSettings::WebContentsHandler& handler, - Delegate* delegate) +PageSpecificContentSettings::PageSpecificContentSettings(content::Page& page, + Delegate* delegate) : content::PageUserData<PageSpecificContentSettings>(page), - handler_(handler), delegate_(delegate), map_(delegate_->GetSettingsMap()), - allowed_local_shared_objects_( - handler_.web_contents()->GetBrowserContext(), - /*ignore_empty_localstorage=*/true, - delegate_->GetAdditionalFileSystemTypes(), - delegate_->GetIsDeletionDisabledCallback()), - blocked_local_shared_objects_( - handler_.web_contents()->GetBrowserContext(), - /*ignore_empty_localstorage=*/false, - delegate_->GetAdditionalFileSystemTypes(), - delegate_->GetIsDeletionDisabledCallback()), + allowed_local_shared_objects_(GetWebContents()->GetBrowserContext(), + /*ignore_empty_localstorage=*/true, + delegate_->GetAdditionalFileSystemTypes(), + delegate_->GetIsDeletionDisabledCallback()), + blocked_local_shared_objects_(GetWebContents()->GetBrowserContext(), + /*ignore_empty_localstorage=*/false, + delegate_->GetAdditionalFileSystemTypes(), + delegate_->GetIsDeletionDisabledCallback()), microphone_camera_state_(MICROPHONE_CAMERA_NOT_ACCESSED) { observation_.Observe(map_.get()); if (page.GetMainDocument().GetLifecycleState() == @@ -296,8 +375,7 @@ void PageSpecificContentSettings::CreateForWebContents( content::WebContents* web_contents, std::unique_ptr<Delegate> delegate) { - PageSpecificContentSettings::WebContentsHandler::CreateForWebContents( - web_contents, std::move(delegate)); + WebContentsHandler::CreateForWebContents(web_contents, std::move(delegate)); } // static @@ -305,8 +383,7 @@ content::WebContents* web_contents) { PageSpecificContentSettings::DeleteForPage(web_contents->GetPrimaryPage()); - web_contents->RemoveUserData( - PageSpecificContentSettings::WebContentsHandler::UserDataKey()); + web_contents->RemoveUserData(WebContentsHandler::UserDataKey()); } // static @@ -330,9 +407,7 @@ PageSpecificContentSettings::Delegate* PageSpecificContentSettings::GetDelegateForWebContents( content::WebContents* web_contents) { - auto* handler = - PageSpecificContentSettings::WebContentsHandler::FromWebContents( - web_contents); + auto* handler = WebContentsHandler::FromWebContents(web_contents); return handler ? handler->delegate() : nullptr; } @@ -393,8 +468,7 @@ content::WebContentsObserver* PageSpecificContentSettings::GetWebContentsObserverForTest( content::WebContents* web_contents) { - return PageSpecificContentSettings::WebContentsHandler::FromWebContents( - web_contents); + return WebContentsHandler::FromWebContents(web_contents); } bool PageSpecificContentSettings::IsContentBlocked( @@ -917,7 +991,8 @@ } if (updates_queued_during_prerender_->site_data_accessed) { - handler_.NotifySiteDataObservers(); + WebContentsHandler::FromWebContents(GetWebContents()) + ->NotifySiteDataObservers(); } updates_queued_during_prerender_.reset(); @@ -930,7 +1005,8 @@ updates_queued_during_prerender_->site_data_accessed = true; return; } - handler_.NotifySiteDataObservers(); + WebContentsHandler::FromWebContents(GetWebContents()) + ->NotifySiteDataObservers(); } void PageSpecificContentSettings::MaybeUpdateLocationBar() { @@ -941,6 +1017,10 @@ delegate_->UpdateLocationBar(); } +content::WebContents* PageSpecificContentSettings::GetWebContents() const { + return content::WebContents::FromRenderFrameHost(&page().GetMainDocument()); +} + PAGE_USER_DATA_KEY_IMPL(PageSpecificContentSettings); } // namespace content_settings
diff --git a/components/content_settings/browser/page_specific_content_settings.h b/components/content_settings/browser/page_specific_content_settings.h index 186bd34..e2f2a864 100644 --- a/components/content_settings/browser/page_specific_content_settings.h +++ b/components/content_settings/browser/page_specific_content_settings.h
@@ -29,18 +29,16 @@ #include "components/content_settings/core/common/content_settings_types.h" #include "components/privacy_sandbox/canonical_topic.h" #include "content/public/browser/allow_service_worker_result.h" -#include "content/public/browser/navigation_handle_user_data.h" #include "content/public/browser/page_user_data.h" #include "content/public/browser/render_frame_host.h" -#include "content/public/browser/web_contents_observer.h" -#include "content/public/browser/web_contents_user_data.h" namespace blink { class StorageKey; } // namespace blink namespace content { -class NavigationHandle; +class WebContents; +class WebContentsObserver; } namespace url { @@ -380,101 +378,13 @@ // Returns the topics that were accessed by this page. std::vector<privacy_sandbox::CanonicalTopic> GetAccessedTopics() const; + // Runs any queued updates in |updates_queued_during_prerender_|, should be + // called after the page activates. + void OnPrerenderingPageActivation(); + private: friend class content::PageUserData<PageSpecificContentSettings>; - // Keeps track of cookie and service worker access during a navigation. - // These types of access can happen for the current page or for a new - // navigation (think cookies sent in the HTTP request or service worker - // being run to serve a fetch request). A navigation might fail to - // commit in which case we have to handle it as if it had never - // occurred. So we cache all cookies and service worker accesses that - // happen during a navigation and only apply the changes if the - // navigation commits. - class InflightNavigationContentSettings - : public content::NavigationHandleUserData< - InflightNavigationContentSettings> { - public: - ~InflightNavigationContentSettings() override; - std::vector<content::CookieAccessDetails> cookie_accesses; - std::vector<std::pair<GURL, content::AllowServiceWorkerResult>> - service_worker_accesses; - - private: - explicit InflightNavigationContentSettings( - content::NavigationHandle& navigation_handle); - friend class content::NavigationHandleUserData< - InflightNavigationContentSettings>; - NAVIGATION_HANDLE_USER_DATA_KEY_DECL(); - }; - - // This class attaches to WebContents to listen to events and route them to - // appropriate PageSpecificContentSettings, store navigation related events - // until the navigation finishes and then transferring the - // navigation-associated state to the newly-created page. - class WebContentsHandler - : public content::WebContentsObserver, - public content::WebContentsUserData<WebContentsHandler> { - public: - explicit WebContentsHandler(content::WebContents* web_contents, - std::unique_ptr<Delegate> delegate); - ~WebContentsHandler() override; - // Adds the given |SiteDataObserver|. The |observer| is notified when a - // locale shared object, like for example a cookie, is accessed. - void AddSiteDataObserver(SiteDataObserver* observer); - - // Removes the given |SiteDataObserver|. - void RemoveSiteDataObserver(SiteDataObserver* observer); - - // Notifies all registered |SiteDataObserver|s. - void NotifySiteDataObservers(); - - Delegate* delegate() { return delegate_.get(); } - - private: - friend class content::WebContentsUserData<WebContentsHandler>; - - // Applies all stored events for the given navigation to the current main - // document. - void TransferNavigationContentSettingsToCommittedDocument( - const InflightNavigationContentSettings& navigation_settings, - content::RenderFrameHost* rfh); - - // content::WebContentsObserver overrides. - void ReadyToCommitNavigation( - content::NavigationHandle* navigation_handle) override; - void DidFinishNavigation( - content::NavigationHandle* navigation_handle) override; - void OnCookiesAccessed( - content::NavigationHandle* navigation, - const content::CookieAccessDetails& details) override; - void OnCookiesAccessed( - content::RenderFrameHost* rfh, - const content::CookieAccessDetails& details) override; - // Called when a specific Service Worker scope was accessed. - // If access was blocked due to the user's content settings, - // |blocked_by_policy_javascript| or/and |blocked_by_policy_cookie| - // should be true, and this function should invoke OnContentBlocked for - // JavaScript or/and cookies respectively. - void OnServiceWorkerAccessed( - content::NavigationHandle* navigation, - const GURL& scope, - content::AllowServiceWorkerResult allowed) override; - void OnServiceWorkerAccessed( - content::RenderFrameHost* frame, - const GURL& scope, - content::AllowServiceWorkerResult allowed) override; - - std::unique_ptr<Delegate> delegate_; - - raw_ptr<HostContentSettingsMap> map_; - - // All currently registered |SiteDataObserver|s. - base::ObserverList<SiteDataObserver>::Unchecked observer_list_; - - WEB_CONTENTS_USER_DATA_KEY_DECL(); - }; - struct PendingUpdates { PendingUpdates(); ~PendingUpdates(); @@ -483,10 +393,7 @@ bool site_data_accessed = false; }; - explicit PageSpecificContentSettings( - content::Page& page, - PageSpecificContentSettings::WebContentsHandler& handler, - Delegate* delegate); + explicit PageSpecificContentSettings(content::Page& page, Delegate* delegate); // content_settings::Observer implementation. void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern, @@ -498,7 +405,6 @@ bool IsPagePrerendering() const; bool IsEmbeddedPage() const; - void OnPrerenderingPageActivation(); // Delays the call of the delegate method if the page is currently // prerendering until the page is activated; directly calls the method @@ -536,7 +442,7 @@ // the page is currently prerendering or is embedded. void MaybeUpdateLocationBar(); - WebContentsHandler& handler_; + content::WebContents* GetWebContents() const; raw_ptr<Delegate> delegate_;
diff --git a/components/content_settings/core/browser/cookie_settings.cc b/components/content_settings/core/browser/cookie_settings.cc index d08d6f5c..0acb2f8 100644 --- a/components/content_settings/core/browser/cookie_settings.cc +++ b/components/content_settings/core/browser/cookie_settings.cc
@@ -18,6 +18,7 @@ #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" #include "extensions/buildflags/buildflags.h" +#include "net/base/features.h" #include "net/cookies/cookie_util.h" #include "net/cookies/site_for_cookies.h" #include "url/gurl.h"
diff --git a/components/content_settings/core/common/cookie_settings_base.cc b/components/content_settings/core/common/cookie_settings_base.cc index 5e46cf3b..064481bc 100644 --- a/components/content_settings/core/common/cookie_settings_base.cc +++ b/components/content_settings/core/common/cookie_settings_base.cc
@@ -21,6 +21,14 @@ namespace content_settings { +CookieSettingsBase::CookieSettingsBase() + : storage_access_api_enabled_( + base::FeatureList::IsEnabled(net::features::kStorageAccessAPI)), + storage_access_api_grants_unpartitioned_storage_( + net::features::kStorageAccessAPIGrantsUnpartitionedStorage.Get()), + is_storage_partitioned_(base::FeatureList::IsEnabled( + net::features::kThirdPartyStoragePartitioning)) {} + // static bool CookieSettingsBase::IsThirdPartyRequest( const GURL& url, @@ -134,18 +142,31 @@ return net::CookieAccessSemantics::UNKNOWN; } -// static bool CookieSettingsBase::ShouldConsiderStorageAccessGrants( - QueryReason query_reason) { + QueryReason query_reason) const { + return CookieSettingsBase::ShouldConsiderStorageAccessGrantsInternal( + query_reason, storage_access_api_enabled_, + storage_access_api_grants_unpartitioned_storage_, + is_storage_partitioned_); +} + +// static +bool CookieSettingsBase::ShouldConsiderStorageAccessGrantsInternal( + QueryReason query_reason, + bool storage_access_api_enabled, + bool storage_access_api_grants_unpartitioned_storage, + bool is_storage_partitioned) { switch (query_reason) { case QueryReason::kSetting: return false; case QueryReason::kPrivacySandbox: return false; case QueryReason::kSiteStorage: - return base::FeatureList::IsEnabled(net::features::kStorageAccessAPI); + return storage_access_api_enabled && + (storage_access_api_grants_unpartitioned_storage || + is_storage_partitioned); case QueryReason::kCookies: - return base::FeatureList::IsEnabled(net::features::kStorageAccessAPI); + return storage_access_api_enabled; } }
diff --git a/components/content_settings/core/common/cookie_settings_base.h b/components/content_settings/core/common/cookie_settings_base.h index e75715f..deb6d61 100644 --- a/components/content_settings/core/common/cookie_settings_base.h +++ b/components/content_settings/core/common/cookie_settings_base.h
@@ -66,7 +66,7 @@ // |top_frame_origin|. This is done inconsistently and needs to be fixed. class CookieSettingsBase { public: - CookieSettingsBase() = default; + CookieSettingsBase(); CookieSettingsBase(const CookieSettingsBase&) = delete; CookieSettingsBase& operator=(const CookieSettingsBase&) = delete; @@ -205,7 +205,15 @@ // access. static bool IsValidSettingForLegacyAccess(ContentSetting setting); - static bool ShouldConsiderStorageAccessGrants(QueryReason query_reason); + // Returns true iff the query should consider Storage Access API permission + // grants. + bool ShouldConsiderStorageAccessGrants(QueryReason query_reason) const; + // Static version of the above, exposed for testing. + static bool ShouldConsiderStorageAccessGrantsInternal( + QueryReason query_reason, + bool storage_access_api_enabled, + bool storage_access_api_grants_unpartitioned_storage, + bool is_storage_partitioned); protected: // Returns true iff the request is considered third-party. @@ -225,6 +233,10 @@ bool is_third_party_request, content_settings::SettingSource* source, QueryReason query_reason) const = 0; + + bool storage_access_api_enabled_; + bool storage_access_api_grants_unpartitioned_storage_; + bool is_storage_partitioned_; }; } // namespace content_settings
diff --git a/components/content_settings/core/common/cookie_settings_base_unittest.cc b/components/content_settings/core/common/cookie_settings_base_unittest.cc index 20d35ef..e71d08de 100644 --- a/components/content_settings/core/common/cookie_settings_base_unittest.cc +++ b/components/content_settings/core/common/cookie_settings_base_unittest.cc
@@ -36,6 +36,10 @@ std::string(), false); } +std::string BoolToString(bool b) { + return b ? "true" : "false"; +} + class CallbackCookieSettings : public CookieSettingsBase { public: explicit CallbackCookieSettings(GetSettingCallback callback) @@ -225,14 +229,33 @@ } class CookieSettingsBaseStorageAccessAPITest - : public testing::TestWithParam<bool> { + : public testing::TestWithParam<std::tuple<bool, bool, bool>> { public: CookieSettingsBaseStorageAccessAPITest() { - features_.InitWithFeatureState(net::features::kStorageAccessAPI, - IsStorageAccessAPIEnabled()); + std::vector<base::test::ScopedFeatureList::FeatureAndParams> enabled; + std::vector<base::Feature> disabled; + if (IsStorageAccessAPIEnabled()) { + enabled.push_back({net::features::kStorageAccessAPI, + {{"storage-access-api-grants-unpartitioned-storage", + BoolToString(IsStorageGrantedByPermission())}}}); + } else { + disabled.push_back(net::features::kStorageAccessAPI); + } + features_.InitWithFeaturesAndParameters(enabled, disabled); } - bool IsStorageAccessAPIEnabled() const { return GetParam(); } + bool IsStorageAccessAPIEnabled() const { return std::get<0>(GetParam()); } + bool PermissionGrantsUnpartitionedStorage() const { + return std::get<1>(GetParam()); + } + bool IsStoragePartitioned() const { return std::get<2>(GetParam()); } + + bool IsStorageGrantedByPermission() const { + // Storage access should only be granted if the permission grants + // unpartitioned storage, or if storage is partitioned. + return IsStorageAccessAPIEnabled() && + (PermissionGrantsUnpartitionedStorage() || IsStoragePartitioned()); + } private: base::test::ScopedFeatureList features_; @@ -240,22 +263,30 @@ TEST_P(CookieSettingsBaseStorageAccessAPITest, ShouldConsiderStorageAccessGrants) { - EXPECT_FALSE(CookieSettingsBase::ShouldConsiderStorageAccessGrants( - QueryReason::kSetting)); - EXPECT_FALSE(CookieSettingsBase::ShouldConsiderStorageAccessGrants( - QueryReason::kPrivacySandbox)); + EXPECT_FALSE(CookieSettingsBase::ShouldConsiderStorageAccessGrantsInternal( + QueryReason::kSetting, IsStorageAccessAPIEnabled(), + PermissionGrantsUnpartitionedStorage(), IsStoragePartitioned())); - EXPECT_EQ(CookieSettingsBase::ShouldConsiderStorageAccessGrants( - QueryReason::kSiteStorage), - IsStorageAccessAPIEnabled()); - EXPECT_EQ(CookieSettingsBase::ShouldConsiderStorageAccessGrants( - QueryReason::kCookies), + EXPECT_FALSE(CookieSettingsBase::ShouldConsiderStorageAccessGrantsInternal( + QueryReason::kPrivacySandbox, IsStorageAccessAPIEnabled(), + PermissionGrantsUnpartitionedStorage(), IsStoragePartitioned())); + + EXPECT_EQ(CookieSettingsBase::ShouldConsiderStorageAccessGrantsInternal( + QueryReason::kSiteStorage, IsStorageAccessAPIEnabled(), + PermissionGrantsUnpartitionedStorage(), IsStoragePartitioned()), + IsStorageGrantedByPermission()); + + EXPECT_EQ(CookieSettingsBase::ShouldConsiderStorageAccessGrantsInternal( + QueryReason::kCookies, IsStorageAccessAPIEnabled(), + PermissionGrantsUnpartitionedStorage(), IsStoragePartitioned()), IsStorageAccessAPIEnabled()); } INSTANTIATE_TEST_SUITE_P(/* no prefix */, CookieSettingsBaseStorageAccessAPITest, - testing::Bool()); + testing::Combine(testing::Bool(), + testing::Bool(), + testing::Bool())); } // namespace } // namespace content_settings
diff --git a/components/exo/shared_memory.cc b/components/exo/shared_memory.cc index f158bf1..2993e0b8 100644 --- a/components/exo/shared_memory.cc +++ b/components/exo/shared_memory.cc
@@ -42,7 +42,7 @@ std::unique_ptr<Buffer> SharedMemory::CreateBuffer(const gfx::Size& size, gfx::BufferFormat format, unsigned offset, - int stride) { + uint32_t stride) { TRACE_EVENT2("exo", "SharedMemory::CreateBuffer", "size", size.ToString(), "format", static_cast<int>(format)); @@ -52,10 +52,8 @@ return nullptr; } - if (!base::IsValueInRangeForNumericType<size_t>(stride) || - gfx::RowSizeForBufferFormat(size.width(), format, 0) > - static_cast<size_t>(stride) || - static_cast<size_t>(stride) & 3) { + if (gfx::RowSizeForBufferFormat(size.width(), format, 0) > stride || + stride & 3) { DLOG(WARNING) << "Failed to create shm buffer. Unsupported stride " << stride; return nullptr;
diff --git a/components/exo/shared_memory.h b/components/exo/shared_memory.h index 8222fa7..47fa7356 100644 --- a/components/exo/shared_memory.h +++ b/components/exo/shared_memory.h
@@ -34,7 +34,7 @@ std::unique_ptr<Buffer> CreateBuffer(const gfx::Size& size, gfx::BufferFormat format, unsigned offset, - int stride); + uint32_t stride); size_t GetSize() const; bool Resize(const size_t new_size);
diff --git a/components/exo/text_input.cc b/components/exo/text_input.cc index bae361a..f2dccff 100644 --- a/components/exo/text_input.cc +++ b/components/exo/text_input.cc
@@ -255,7 +255,7 @@ return gfx::Rect(); } -bool TextInput::GetCompositionCharacterBounds(uint32_t index, +bool TextInput::GetCompositionCharacterBounds(size_t index, gfx::Rect* rect) const { return false; }
diff --git a/components/exo/text_input.h b/components/exo/text_input.h index 2610b8fa..eb19f262 100644 --- a/components/exo/text_input.h +++ b/components/exo/text_input.h
@@ -182,7 +182,7 @@ bool CanComposeInline() const override; gfx::Rect GetCaretBounds() const override; gfx::Rect GetSelectionBoundingBox() const override; - bool GetCompositionCharacterBounds(uint32_t index, + bool GetCompositionCharacterBounds(size_t index, gfx::Rect* rect) const override; bool HasCompositionText() const override; ui::TextInputClient::FocusReason GetFocusReason() const override;
diff --git a/components/favicon/content/content_favicon_driver.cc b/components/favicon/content/content_favicon_driver.cc index f185a4f..13025e8 100644 --- a/components/favicon/content/content_favicon_driver.cc +++ b/components/favicon/content/content_favicon_driver.cc
@@ -96,15 +96,15 @@ } int ContentFaviconDriver::DownloadImage(const GURL& url, - int preferred_size, + int max_image_size, ImageDownloadCallback callback) { bool bypass_cache = (bypass_cache_page_url_ == GetActiveURL()); bypass_cache_page_url_ = GURL(); - const gfx::Size preferred_size_constraints(preferred_size, preferred_size); - return web_contents()->DownloadImage(url, true, preferred_size_constraints, - /*max_image_size = */ 0, bypass_cache, - std::move(callback)); + const gfx::Size preferred_size(max_image_size, max_image_size); + return web_contents()->DownloadImage(url, true, preferred_size, + /*max_bitmap_size=*/max_image_size, + bypass_cache, std::move(callback)); } void ContentFaviconDriver::DownloadManifest(const GURL& url,
diff --git a/components/favicon/content/content_favicon_driver.h b/components/favicon/content/content_favicon_driver.h index 6cf0a23..000ac24 100644 --- a/components/favicon/content/content_favicon_driver.h +++ b/components/favicon/content/content_favicon_driver.h
@@ -74,7 +74,7 @@ // FaviconHandler::Delegate implementation. int DownloadImage(const GURL& url, - int preferred_size, + int max_image_size, ImageDownloadCallback callback) override; void DownloadManifest(const GURL& url, ManifestDownloadCallback callback) override;
diff --git a/components/favicon/core/favicon_handler.cc b/components/favicon/core/favicon_handler.cc index 2bea93f..56f54be5 100644 --- a/components/favicon/core/favicon_handler.cc +++ b/components/favicon/core/favicon_handler.cc
@@ -22,7 +22,6 @@ #include "components/favicon_base/favicon_util.h" #include "components/favicon_base/select_favicon_frames.h" #include "skia/ext/image_operations.h" -#include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_util.h" @@ -714,8 +713,9 @@ image_download_request_.Reset( base::BindOnce(&FaviconHandler::OnDidDownloadFavicon, base::Unretained(this), icon_type)); - // The maximal icon size is passed in to set the preferred size for vector - // images. See FaviconHandler::Delegate::DownloadImage() for more info. + // A max bitmap size is specified to avoid receiving huge bitmaps in + // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() + // for more details about the max bitmap size. const int download_id = delegate_->DownloadImage( image_url, GetMaximalIconSize(handler_type_, !manifest_url_.is_empty()), image_download_request_.callback());
diff --git a/components/favicon/core/favicon_handler.h b/components/favicon/core/favicon_handler.h index 7e2dc5f..2be71b2 100644 --- a/components/favicon/core/favicon_handler.h +++ b/components/favicon/core/favicon_handler.h
@@ -93,14 +93,12 @@ // is called with the results. Returns the unique id of the download // request, which will also be passed to the callback. In case of error, 0 // is returned and no callback will be called. - // For vector images, |preferred_size| will serve as a viewport into which - // the image will be rendered. This would usually be the dimensions of the - // rectangle where the bitmap will be rendered. If |preferred_size| is - // empty, any existing intrinsic dimensions of the image will be used. All - // images are downloaded (without filtering by size), and all filtering is - // handled by the utility functions inside select_favicon_frames.cc. + // Bitmaps with pixel sizes larger than |max_bitmap_size| are filtered out + // from the bitmap results. If there are no bitmap results <= + // |max_bitmap_size|, the smallest bitmap is resized to |max_bitmap_size| + // and is the only result. A |max_bitmap_size| of 0 means unlimited. virtual int DownloadImage(const GURL& url, - int preferred_size, + int max_image_size, ImageDownloadCallback callback) = 0; // Downloads a WebManifest and returns the favicons listed there.
diff --git a/components/favicon/core/favicon_handler_unittest.cc b/components/favicon/core/favicon_handler_unittest.cc index 5736a55..7530efa 100644 --- a/components/favicon/core/favicon_handler_unittest.cc +++ b/components/favicon/core/favicon_handler_unittest.cc
@@ -134,12 +134,21 @@ // Implementation of FaviconHalder::Delegate's DownloadImage(). If a given // URL is not known (i.e. not previously added via Add()), it produces 404s. int DownloadImage(const GURL& url, - int preferred_size, + int max_image_size, FaviconHandler::Delegate::ImageDownloadCallback callback) { downloads_->push_back(url); Response response = responses_[url]; DCHECK_EQ(response.bitmaps.size(), response.original_bitmap_sizes.size()); + // Apply maximum image size. + for (size_t i = 0; i < response.bitmaps.size(); ++i) { + if (response.bitmaps[i].width() > max_image_size || + response.bitmaps[i].height() > max_image_size) { + response.bitmaps[i] = skia::ImageOperations::Resize( + response.bitmaps[i], skia::ImageOperations::RESIZE_LANCZOS3, + max_image_size, max_image_size); + } + } int download_id = next_download_id_++; base::OnceClosure bound_callback = base::BindOnce( @@ -290,9 +299,9 @@ } int DownloadImage(const GURL& url, - int preferred_size, + int max_image_size, ImageDownloadCallback callback) override { - return fake_image_downloader_.DownloadImage(url, preferred_size, + return fake_image_downloader_.DownloadImage(url, max_image_size, std::move(callback)); } @@ -1718,7 +1727,7 @@ EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL2)); } -TEST_F(FaviconHandlerTest, TestFaviconNotScaledButSelectedCorrectly) { +TEST_F(FaviconHandlerTest, TestFaviconWasScaledAfterDownload) { const int kMaximalSize = FaviconHandler::GetMaximalIconSize( FaviconDriverObserver::NON_TOUCH_LARGEST, /*candidates_from_web_manifest=*/false); @@ -1735,10 +1744,10 @@ SK_ColorBLUE); // Verify the best bitmap was selected (although smaller than |kIconURL2|) - // and that it was downloaded without any scaling. + // and that it was scaled down to |kMaximalSize|. EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL1, _, - ImageSizeIs(kOriginalSize1, kOriginalSize1))); + ImageSizeIs(kMaximalSize, kMaximalSize))); RunHandlerWithCandidates( FaviconDriverObserver::NON_TOUCH_LARGEST,
diff --git a/components/favicon/ios/web_favicon_driver.h b/components/favicon/ios/web_favicon_driver.h index 9657294..84bbb2a 100644 --- a/components/favicon/ios/web_favicon_driver.h +++ b/components/favicon/ios/web_favicon_driver.h
@@ -41,7 +41,7 @@ // FaviconHandler::Delegate implementation. int DownloadImage(const GURL& url, - int preferred_size, + int max_image_size, ImageDownloadCallback callback) override; void DownloadManifest(const GURL& url, ManifestDownloadCallback callback) override;
diff --git a/components/favicon/ios/web_favicon_driver.mm b/components/favicon/ios/web_favicon_driver.mm index 150c776..00ca6e83 100644 --- a/components/favicon/ios/web_favicon_driver.mm +++ b/components/favicon/ios/web_favicon_driver.mm
@@ -48,7 +48,7 @@ } int WebFaviconDriver::DownloadImage(const GURL& url, - int preferred_size, + int max_image_size, ImageDownloadCallback callback) { static int downloaded_image_count = 0; int local_download_id = ++downloaded_image_count; @@ -65,10 +65,7 @@ std::vector<SkBitmap> frames; std::vector<gfx::Size> sizes; if (data) { - // From FaviconHandler::ScheduleImageDownload, the preferred_size - // contains the maximal size while the max_image_size is set to 0 to - // allow all files to be downloaded by the blink renderer. - frames = skia::ImageDataToSkBitmapsWithMaxSize(data, preferred_size); + frames = skia::ImageDataToSkBitmapsWithMaxSize(data, max_image_size); for (const auto& frame : frames) { sizes.push_back(gfx::Size(frame.width(), frame.height())); }
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc index 86bdbf7..5afb07f2 100644 --- a/components/history/core/browser/history_backend.cc +++ b/components/history/core/browser/history_backend.cc
@@ -1775,7 +1775,7 @@ if (!db_) return base::Time::Min(); const auto clusters = - GetMostRecentClusters(base::Time::Min(), base::Time::Max(), 1); + GetMostRecentClusters(base::Time::Min(), base::Time::Max(), 1, false); return clusters.empty() ? base::Time::Min() : clusters[0] .GetMostRecentVisit() @@ -1796,26 +1796,30 @@ std::vector<Cluster> HistoryBackend::GetMostRecentClusters( base::Time inclusive_min_time, base::Time exclusive_max_time, - int max_clusters) { + int max_clusters, + bool include_keywords) { TRACE_EVENT0("browser", "HistoryBackend::GetMostRecentClusters"); if (!db_) return {}; const auto cluster_ids = db_->GetMostRecentClusterIds( inclusive_min_time, exclusive_max_time, max_clusters); std::vector<Cluster> clusters; - base::ranges::transform( - cluster_ids, std::back_inserter(clusters), - [&](const auto& cluster_id) { return GetCluster(cluster_id); }); + base::ranges::transform(cluster_ids, std::back_inserter(clusters), + [&](const auto& cluster_id) { + return GetCluster(cluster_id, include_keywords); + }); return clusters; } -Cluster HistoryBackend::GetCluster(int64_t cluster_id) { +Cluster HistoryBackend::GetCluster(int64_t cluster_id, bool include_keywords) { TRACE_EVENT0("browser", "HistoryBackend::GetCluster"); if (!db_) return {}; Cluster cluster = db_->GetCluster(cluster_id); cluster.visits = ToClusterVisits(db_->GetVisitIdsInCluster(cluster_id)); + if (include_keywords) + cluster.keyword_to_data_map = db_->GetClusterKeywords(cluster_id); return cluster; }
diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h index 68e61b6..c0c9920ea 100644 --- a/components/history/core/browser/history_backend.h +++ b/components/history/core/browser/history_backend.h
@@ -484,10 +484,12 @@ std::vector<Cluster> GetMostRecentClusters(base::Time inclusive_min_time, base::Time exclusive_max_time, - int max_clusters); + int max_clusters, + bool include_keywords = true); - // Get a `Cluster`. - Cluster GetCluster(int64_t cluster_id); + // Get a `Cluster`. `keyword_to_data_map` isn't always useful, and it requires + // an extra SQL execution. It's only populated If `include_keywords` is true. + Cluster GetCluster(int64_t cluster_id, bool include_keywords = true); // Finds the 1st visit in the redirect chain containing `visit`. // Unlike `GetRedirectsToSpecificVisit()`, this only considers actual
diff --git a/components/history/core/browser/history_backend_unittest.cc b/components/history/core/browser/history_backend_unittest.cc index 7923bc0b..ba81500f 100644 --- a/components/history/core/browser/history_backend_unittest.cc +++ b/components/history/core/browser/history_backend_unittest.cc
@@ -3870,17 +3870,50 @@ // returned. ClusterVisit visit_3; visit_3.annotated_visit.visit_row.visit_id = 3; - backend_->db_->AddClusters( - {{0, {visit_1, visit_2, visit_3}, {}, false, u"label"}}); - const auto cluster = backend_->GetCluster(1); + ClusterKeywordData keyword_data_1 = { + ClusterKeywordData::ClusterKeywordType::kEntityAlias, + .4, + {"entity1", "entity2"}}; + ClusterKeywordData keyword_data_2 = { + ClusterKeywordData::ClusterKeywordType::kEntityCategory, .6, {}}; + + backend_->db_->AddClusters( + {{0, + {visit_1, visit_2, visit_3}, + {{u"keyword1", keyword_data_1}, {u"keyword2", keyword_data_2}}, + false, + u"label"}}); + + auto cluster = backend_->GetCluster(1, true); VerifyCluster(cluster, {1, {2, 1}}); EXPECT_EQ(cluster.cluster_id, 1); EXPECT_EQ(cluster.label, u"label"); EXPECT_EQ(cluster.visits[1].url_for_display, u"url_for_display"); + EXPECT_EQ(cluster.keyword_to_data_map.size(), 2u); + EXPECT_EQ(cluster.keyword_to_data_map[u"keyword1"].type, + ClusterKeywordData::ClusterKeywordType::kEntityAlias); + EXPECT_EQ(cluster.keyword_to_data_map[u"keyword1"].score, .4f); + // Only the 1st keyword entity should be preserved. + EXPECT_THAT(cluster.keyword_to_data_map[u"keyword1"].entity_collections, + UnorderedElementsAre("entity1")); + EXPECT_EQ(cluster.keyword_to_data_map[u"keyword2"].type, + ClusterKeywordData::ClusterKeywordType::kEntityCategory); + EXPECT_EQ(cluster.keyword_to_data_map[u"keyword2"].score, .6f); + EXPECT_TRUE( + cluster.keyword_to_data_map[u"keyword2"].entity_collections.empty()); + + // Verify keywords are not returned, but other info is, when the + // `include_keywords` param is false. + cluster = backend_->GetCluster(1, false); + VerifyCluster(cluster, {1, {2, 1}}); + EXPECT_EQ(cluster.cluster_id, 1); + EXPECT_EQ(cluster.label, u"label"); + EXPECT_EQ(cluster.visits[1].url_for_display, u"url_for_display"); + EXPECT_TRUE(cluster.keyword_to_data_map.empty()); // Verify non-existent clusters aren't returned. - VerifyCluster(backend_->GetCluster(2), {0}); + VerifyCluster(backend_->GetCluster(2, true), {0}); } TEST_F(HistoryBackendTest, GetRedirectChainStart) {
diff --git a/components/history/core/browser/history_service.cc b/components/history/core/browser/history_service.cc index 9680c91..930e844 100644 --- a/components/history/core/browser/history_service.cc +++ b/components/history/core/browser/history_service.cc
@@ -317,7 +317,8 @@ return tracker->PostTaskAndReplyWithResult( backend_task_runner_.get(), FROM_HERE, base::BindOnce(&HistoryBackend::GetMostRecentClusters, history_backend_, - inclusive_min_time, exclusive_max_time, max_clusters), + inclusive_min_time, exclusive_max_time, max_clusters, + /*include_keywords=*/true), std::move(callback)); }
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h index 658e50d..b1fd3c9 100644 --- a/components/history/core/browser/history_types.h +++ b/components/history/core/browser/history_types.h
@@ -991,7 +991,6 @@ std::vector<ClusterVisit> visits; // A map of keywords to additional data. - // TODO(manukh): Persist to db. base::flat_map<std::u16string, ClusterKeywordData> keyword_to_data_map; // Whether the cluster should be shown prominently on UI surfaces.
diff --git a/components/history/core/browser/visit_annotations_database.cc b/components/history/core/browser/visit_annotations_database.cc index ff77a11..e267eb5c 100644 --- a/components/history/core/browser/visit_annotations_database.cc +++ b/components/history/core/browser/visit_annotations_database.cc
@@ -200,6 +200,17 @@ if (!CreateClustersAndVisitsTableAndIndex()) return false; + // Represents the one-to-many relationship of `Cluster`s and + // `ClusterKeywordData`s. + if (!GetDB().Execute("CREATE TABLE IF NOT EXISTS cluster_keywords(" + "cluster_id INTEGER NOT NULL," + "keyword VARCHAR NOT NULL," + "type INTEGER NOT NULL," + "score NUMERIC NOT NULL," + "collections VARCHAR NOT NULL)")) { + return false; + } + return true; } @@ -417,6 +428,11 @@ "(cluster_id,visit_id,score,engagement_score,url_for_deduping," "normalized_url,url_for_display)" "VALUES(?,?,?,?,?,?,?)")); + sql::Statement cluster_keywords_statement( + GetDB().GetCachedStatement(SQL_FROM_HERE, + "INSERT INTO cluster_keywords" + "(cluster_id,keyword,type,score,collections)" + "VALUES(?,?,?,?,?)")); for (const auto& cluster : clusters) { if (cluster.visits.empty()) @@ -456,6 +472,23 @@ << "cluster_id = " << cluster_id << ", visit_id = " << visit_id; } }); + + // Insert each keyword into 'cluster_keywords'. + for (const auto& [keyword, keyword_data] : cluster.keyword_to_data_map) { + cluster_keywords_statement.Reset(true); + cluster_keywords_statement.BindInt64(0, cluster_id); + cluster_keywords_statement.BindString16(1, keyword); + cluster_keywords_statement.BindInt(2, keyword_data.type); + cluster_keywords_statement.BindDouble(3, keyword_data.score); + cluster_keywords_statement.BindString( + 4, keyword_data.entity_collections.empty() + ? "" + : keyword_data.entity_collections[0]); + if (!cluster_keywords_statement.Run()) { + DVLOG(0) << "Failed to execute 'cluster_keywords' insert statement: " + << "cluster_id = " << cluster_id << ", keyword = " << keyword; + } + } } } @@ -572,6 +605,27 @@ return 0; } +base::flat_map<std::u16string, ClusterKeywordData> +VisitAnnotationsDatabase::GetClusterKeywords(int64_t cluster_id) { + DCHECK_GT(cluster_id, 0); + sql::Statement statement( + GetDB().GetCachedStatement(SQL_FROM_HERE, + "SELECT keyword,type,score,collections " + "FROM cluster_keywords " + "WHERE cluster_id=?")); + statement.BindInt64(0, cluster_id); + + base::flat_map<std::u16string, ClusterKeywordData> keyword_data; + while (statement.Step()) { + keyword_data[statement.ColumnString16(0)] = { + static_cast<ClusterKeywordData::ClusterKeywordType>( + statement.ColumnInt(1)), + static_cast<float>(statement.ColumnDouble(2)), + DeserializeFromStringColumn(statement.ColumnString(3))}; + } + return keyword_data; +} + void VisitAnnotationsDatabase::DeleteClusters( const std::vector<int64_t>& cluster_ids) { if (cluster_ids.empty()) @@ -583,6 +637,9 @@ sql::Statement clusters_and_visits_statement(GetDB().GetCachedStatement( SQL_FROM_HERE, "DELETE FROM clusters_and_visits WHERE cluster_id=?")); + sql::Statement cluster_keywords_statement(GetDB().GetCachedStatement( + SQL_FROM_HERE, "DELETE FROM cluster_keywords WHERE cluster_id=?")); + for (auto cluster_id : cluster_ids) { clusters_statement.Reset(true); clusters_statement.BindInt64(0, cluster_id); @@ -597,6 +654,13 @@ DVLOG(0) << "Failed to execute clusters_and_visits delete statement: " << "cluster_id = " << cluster_id; } + + cluster_keywords_statement.Reset(true); + cluster_keywords_statement.BindInt64(0, cluster_id); + if (!cluster_keywords_statement.Run()) { + DVLOG(0) << "Failed to execute cluster_keywords delete statement: " + << "cluster_id = " << cluster_id; + } } }
diff --git a/components/history/core/browser/visit_annotations_database.h b/components/history/core/browser/visit_annotations_database.h index 8a1a6464..471755c6 100644 --- a/components/history/core/browser/visit_annotations_database.h +++ b/components/history/core/browser/visit_annotations_database.h
@@ -76,7 +76,8 @@ // entries for any `Cluster` that it failed to add. void AddClusters(const std::vector<Cluster>& clusters); - // Get a `Cluster`. + // Get a `Cluster`. Does not include the cluster's `visits` or + // `keyword_to_data_map`. Cluster GetCluster(int64_t cluster_id); // Get the most recent clusters within the constraints. The most recent visit @@ -95,6 +96,10 @@ // is not in a cluster.` int64_t GetClusterIdContainingVisit(VisitID visit_id); + // Return the keyword data associated with `cluster_id`. + base::flat_map<std::u16string, ClusterKeywordData> GetClusterKeywords( + int64_t cluster_id); + // Delete `Cluster`s from the table. void DeleteClusters(const std::vector<int64_t>& cluster_ids);
diff --git a/components/history/core/browser/visit_annotations_database_unittest.cc b/components/history/core/browser/visit_annotations_database_unittest.cc index a629ea7..0c50330 100644 --- a/components/history/core/browser/visit_annotations_database_unittest.cc +++ b/components/history/core/browser/visit_annotations_database_unittest.cc
@@ -216,7 +216,8 @@ EXPECT_EQ(final.alternative_title, "New alternative title"); } -TEST_F(VisitAnnotationsDatabaseTest, AddClusters_GetCluster_GetClusterVisit) { +TEST_F(VisitAnnotationsDatabaseTest, + AddClusters_GetCluster_GetClusterVisit_GetClusterKeywords) { // Test `AddClusters()`. // Cluster without visits shouldn't be added. @@ -353,7 +354,10 @@ AddContextAnnotationsForVisit(1, {}); AddContentAnnotationsForVisit(2, {}); AddContextAnnotationsForVisit(2, {}); - AddCluster({1, 2}); + auto cluster = CreateCluster({1, 2}); + cluster.keyword_to_data_map[u"keyword1"]; + cluster.keyword_to_data_map[u"keyword2"]; + AddClusters({cluster}); VisitContentAnnotations got_content_annotations; VisitContextAnnotations got_context_annotations; @@ -362,10 +366,11 @@ EXPECT_TRUE(GetContextAnnotationsForVisit(1, &got_context_annotations)); EXPECT_TRUE(GetContentAnnotationsForVisit(2, &got_content_annotations)); EXPECT_TRUE(GetContextAnnotationsForVisit(2, &got_context_annotations)); + EXPECT_EQ(GetCluster(1).cluster_id, 1); EXPECT_THAT(GetVisitIdsInCluster(1), UnorderedElementsAre(1, 2)); EXPECT_EQ(GetClusterIdContainingVisit(1), 1); EXPECT_EQ(GetClusterIdContainingVisit(2), 1); - EXPECT_EQ(GetCluster(1).cluster_id, 1); + EXPECT_EQ(GetClusterKeywords(1).size(), 2u); // Delete 1 visit. Make sure the tables are updated, but the cluster remains. DeleteAnnotationsForVisit(1); @@ -373,10 +378,11 @@ EXPECT_FALSE(GetContextAnnotationsForVisit(1, &got_context_annotations)); EXPECT_TRUE(GetContentAnnotationsForVisit(2, &got_content_annotations)); EXPECT_TRUE(GetContextAnnotationsForVisit(2, &got_context_annotations)); + EXPECT_EQ(GetCluster(1).cluster_id, 1); EXPECT_THAT(GetVisitIdsInCluster(1), UnorderedElementsAre(2)); EXPECT_EQ(GetClusterIdContainingVisit(1), 0); EXPECT_EQ(GetClusterIdContainingVisit(2), 1); - EXPECT_EQ(GetCluster(1).cluster_id, 1); + EXPECT_EQ(GetClusterKeywords(1).size(), 2u); // Delete the 2nd visit. Make sure the cluster is removed. DeleteAnnotationsForVisit(2); @@ -384,31 +390,56 @@ EXPECT_FALSE(GetContextAnnotationsForVisit(1, &got_context_annotations)); EXPECT_FALSE(GetContentAnnotationsForVisit(2, &got_content_annotations)); EXPECT_FALSE(GetContextAnnotationsForVisit(2, &got_context_annotations)); + EXPECT_EQ(GetCluster(1).cluster_id, 0); EXPECT_TRUE(GetVisitIdsInCluster(1).empty()); EXPECT_EQ(GetClusterIdContainingVisit(1), 0); EXPECT_EQ(GetClusterIdContainingVisit(2), 0); - EXPECT_EQ(GetCluster(1).cluster_id, 0); + EXPECT_EQ(GetClusterKeywords(1).size(), 0u); } TEST_F(VisitAnnotationsDatabaseTest, AddClusters_DeleteClusters) { AddClusters(CreateClusters({{3, 2, 5}, {3, 2, 5}, {6}})); + auto cluster_with_keyword_data = CreateCluster({10}); + cluster_with_keyword_data.keyword_to_data_map[u"keyword1"]; + cluster_with_keyword_data.keyword_to_data_map[u"keyword2"]; + AddClusters({cluster_with_keyword_data}); + + EXPECT_EQ(GetCluster(1).cluster_id, 1); + EXPECT_EQ(GetCluster(2).cluster_id, 2); + EXPECT_EQ(GetCluster(3).cluster_id, 3); + EXPECT_EQ(GetCluster(4).cluster_id, 4); EXPECT_THAT(GetVisitIdsInCluster(1), ElementsAre(5, 3, 2)); EXPECT_THAT(GetVisitIdsInCluster(2), ElementsAre(5, 3, 2)); EXPECT_THAT(GetVisitIdsInCluster(3), ElementsAre(6)); + EXPECT_THAT(GetVisitIdsInCluster(4), ElementsAre(10)); + EXPECT_EQ(GetClusterKeywords(4).size(), 2u); DeleteClusters({}); + EXPECT_EQ(GetCluster(1).cluster_id, 1); + EXPECT_EQ(GetCluster(2).cluster_id, 2); + EXPECT_EQ(GetCluster(3).cluster_id, 3); + EXPECT_EQ(GetCluster(4).cluster_id, 4); EXPECT_THAT(GetVisitIdsInCluster(1), ElementsAre(5, 3, 2)); EXPECT_THAT(GetVisitIdsInCluster(2), ElementsAre(5, 3, 2)); EXPECT_THAT(GetVisitIdsInCluster(3), ElementsAre(6)); + EXPECT_THAT(GetVisitIdsInCluster(4), ElementsAre(10)); + EXPECT_EQ(GetClusterKeywords(4).size(), 2u); - DeleteClusters({1, 3, 4}); + DeleteClusters({1, 3, 4, 5}); + EXPECT_EQ(GetCluster(1).cluster_id, 0); + EXPECT_EQ(GetCluster(2).cluster_id, 2); + EXPECT_EQ(GetCluster(3).cluster_id, 0); + EXPECT_EQ(GetCluster(4).cluster_id, 0); + EXPECT_EQ(GetCluster(5).cluster_id, 0); EXPECT_THAT(GetVisitIdsInCluster(1), ElementsAre()); EXPECT_THAT(GetVisitIdsInCluster(2), ElementsAre(5, 3, 2)); EXPECT_THAT(GetVisitIdsInCluster(3), ElementsAre()); EXPECT_THAT(GetVisitIdsInCluster(4), ElementsAre()); + EXPECT_THAT(GetVisitIdsInCluster(5), ElementsAre()); + EXPECT_TRUE(GetClusterKeywords(4).empty()); } } // namespace history
diff --git a/components/live_caption/caption_bubble_controller.h b/components/live_caption/caption_bubble_controller.h index f39d1ff..84ccb7e 100644 --- a/components/live_caption/caption_bubble_controller.h +++ b/components/live_caption/caption_bubble_controller.h
@@ -13,6 +13,8 @@ #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/native_theme/caption_style.h" +class PrefService; + namespace content { class BrowserContext; } @@ -37,7 +39,8 @@ CaptionBubbleController(const CaptionBubbleController&) = delete; CaptionBubbleController& operator=(const CaptionBubbleController&) = delete; - static std::unique_ptr<CaptionBubbleController> Create(); + static std::unique_ptr<CaptionBubbleController> Create( + PrefService* profile_prefs); // Called when a transcription is received from the service. Returns whether // the transcription result was set on the caption bubble successfully.
diff --git a/components/live_caption/live_caption_controller.cc b/components/live_caption/live_caption_controller.cc index f6be626..f4c4fc7 100644 --- a/components/live_caption/live_caption_controller.cc +++ b/components/live_caption/live_caption_controller.cc
@@ -57,6 +57,12 @@ void LiveCaptionController::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { registry->RegisterBooleanPref( + prefs::kLiveCaptionBubbleExpanded, false, + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); + registry->RegisterBooleanPref( + prefs::kLiveCaptionBubblePinned, false, + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); + registry->RegisterBooleanPref( prefs::kLiveCaptionEnabled, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); @@ -183,7 +189,7 @@ is_ui_constructed_ = true; - caption_bubble_controller_ = CaptionBubbleController::Create(); + caption_bubble_controller_ = CaptionBubbleController::Create(profile_prefs_); caption_bubble_controller_->UpdateCaptionStyle(caption_style_); // Observe native theme changes for caption style updates.
diff --git a/components/live_caption/pref_names.cc b/components/live_caption/pref_names.cc index ce280928..de77b02 100644 --- a/components/live_caption/pref_names.cc +++ b/components/live_caption/pref_names.cc
@@ -18,6 +18,14 @@ namespace prefs { #if !defined(ANDROID) +// Whether the Live Caption bubble is expanded. +const char kLiveCaptionBubbleExpanded[] = + "accessibility.captions.live_caption_bubble_expanded"; + +// Whether the Live Caption bubble is pinned. +const char kLiveCaptionBubblePinned[] = + "accessibility.captions.live_caption_bubble_pinned"; + // Whether the Live Caption feature is enabled. const char kLiveCaptionEnabled[] = "accessibility.captions.live_caption_enabled";
diff --git a/components/live_caption/pref_names.h b/components/live_caption/pref_names.h index 1596c8e..c8dbde3 100644 --- a/components/live_caption/pref_names.h +++ b/components/live_caption/pref_names.h
@@ -20,6 +20,8 @@ // Live Caption is not available on Android, so exclude these unneeded // kLiveCaption* prefs. #if !defined(ANDROID) +extern const char kLiveCaptionBubbleExpanded[]; +extern const char kLiveCaptionBubblePinned[]; extern const char kLiveCaptionEnabled[]; extern const char kLiveCaptionLanguageCode[]; extern const char kLiveCaptionMediaFoundationRendererErrorSilenced[];
diff --git a/components/live_caption/views/caption_bubble.cc b/components/live_caption/views/caption_bubble.cc index fe55750..6e914b40 100644 --- a/components/live_caption/views/caption_bubble.cc +++ b/components/live_caption/views/caption_bubble.cc
@@ -18,6 +18,8 @@ #include "base/timer/timer.h" #include "build/build_config.h" #include "components/live_caption/caption_bubble_context.h" +#include "components/live_caption/pref_names.h" +#include "components/prefs/pref_service.h" #include "components/strings/grit/components_strings.h" #include "components/vector_icons/vector_icons.h" #include "third_party/re2/src/re2/re2.h" @@ -402,8 +404,13 @@ }; #endif -CaptionBubble::CaptionBubble(base::OnceClosure destroyed_callback) - : destroyed_callback_(std::move(destroyed_callback)), +CaptionBubble::CaptionBubble(PrefService* profile_prefs, + base::OnceClosure destroyed_callback) + : profile_prefs_(profile_prefs), + destroyed_callback_(std::move(destroyed_callback)), + is_expanded_( + profile_prefs_->GetBoolean(prefs::kLiveCaptionBubbleExpanded)), + is_pinned_(profile_prefs_->GetBoolean(prefs::kLiveCaptionBubblePinned)), tick_clock_(base::DefaultTickClock::GetInstance()) { // Bubbles that use transparent colors should not paint their ClientViews to a // layer as doing so could result in visual artifacts. @@ -696,6 +703,7 @@ void CaptionBubble::ExpandOrCollapseButtonPressed() { is_expanded_ = !is_expanded_; + profile_prefs_->SetBoolean(prefs::kLiveCaptionBubbleExpanded, is_expanded_); base::UmaHistogramBoolean("Accessibility.LiveCaption.ExpandBubble", is_expanded_); @@ -708,6 +716,7 @@ void CaptionBubble::PinOrUnpinButtonPressed() { is_pinned_ = !is_pinned_; + profile_prefs_->SetBoolean(prefs::kLiveCaptionBubblePinned, is_pinned_); base::UmaHistogramBoolean("Accessibility.LiveCaption.PinBubble", is_pinned_); SwapButtons(unpin_button_, pin_button_, is_pinned_);
diff --git a/components/live_caption/views/caption_bubble.h b/components/live_caption/views/caption_bubble.h index 6479597aa..6b045a1 100644 --- a/components/live_caption/views/caption_bubble.h +++ b/components/live_caption/views/caption_bubble.h
@@ -13,6 +13,7 @@ #include "base/memory/raw_ptr.h" #include "build/buildflag.h" #include "components/live_caption/views/caption_bubble_model.h" +#include "components/prefs/pref_service.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/gfx/font_list.h" #include "ui/native_theme/caption_style.h" @@ -67,7 +68,8 @@ class CaptionBubble : public views::BubbleDialogDelegateView { public: METADATA_HEADER(CaptionBubble); - explicit CaptionBubble(base::OnceClosure destroyed_callback); + CaptionBubble(PrefService* profile_prefs, + base::OnceClosure destroyed_callback); CaptionBubble(const CaptionBubble&) = delete; CaptionBubble& operator=(const CaptionBubble&) = delete; ~CaptionBubble() override; @@ -211,16 +213,17 @@ absl::optional<ui::CaptionStyle> caption_style_; raw_ptr<CaptionBubbleModel> model_ = nullptr; + raw_ptr<PrefService> profile_prefs_; OnErrorClickedCallback error_clicked_callback_; OnDoNotShowAgainClickedCallback error_silenced_callback_; base::ScopedClosureRunner destroyed_callback_; // Whether the caption bubble is expanded to show more lines of text. - bool is_expanded_ = false; + bool is_expanded_; // Whether the caption bubble is pinned or if it should hide on inactivity. - bool is_pinned_ = false; + bool is_pinned_; bool has_been_shown_ = false;
diff --git a/components/live_caption/views/caption_bubble_controller_views.cc b/components/live_caption/views/caption_bubble_controller_views.cc index ee2f8e3..9fdf63e 100644 --- a/components/live_caption/views/caption_bubble_controller_views.cc +++ b/components/live_caption/views/caption_bubble_controller_views.cc
@@ -12,16 +12,20 @@ #include "components/live_caption/live_caption_controller.h" #include "components/live_caption/views/caption_bubble.h" #include "components/live_caption/views/caption_bubble_model.h" +#include "components/prefs/pref_service.h" namespace captions { // Static -std::unique_ptr<CaptionBubbleController> CaptionBubbleController::Create() { - return std::make_unique<CaptionBubbleControllerViews>(); +std::unique_ptr<CaptionBubbleController> CaptionBubbleController::Create( + PrefService* profile_prefs) { + return std::make_unique<CaptionBubbleControllerViews>(profile_prefs); } -CaptionBubbleControllerViews::CaptionBubbleControllerViews() { +CaptionBubbleControllerViews::CaptionBubbleControllerViews( + PrefService* profile_prefs) { caption_bubble_ = new CaptionBubble( + profile_prefs, base::BindOnce(&CaptionBubbleControllerViews::OnCaptionBubbleDestroyed, base::Unretained(this))); caption_widget_ =
diff --git a/components/live_caption/views/caption_bubble_controller_views.h b/components/live_caption/views/caption_bubble_controller_views.h index 6a18fa0..4ab6784 100644 --- a/components/live_caption/views/caption_bubble_controller_views.h +++ b/components/live_caption/views/caption_bubble_controller_views.h
@@ -12,6 +12,7 @@ #include "base/memory/raw_ptr.h" #include "components/live_caption/caption_bubble_controller.h" #include "components/live_caption/views/caption_bubble.h" +#include "components/prefs/pref_service.h" #include "media/mojo/mojom/speech_recognition.mojom.h" namespace views { @@ -30,7 +31,7 @@ // class CaptionBubbleControllerViews : public CaptionBubbleController { public: - explicit CaptionBubbleControllerViews(); + explicit CaptionBubbleControllerViews(PrefService* profile_prefs); ~CaptionBubbleControllerViews() override; CaptionBubbleControllerViews(const CaptionBubbleControllerViews&) = delete; CaptionBubbleControllerViews& operator=(const CaptionBubbleControllerViews&) =
diff --git a/components/page_info/page_info.cc b/components/page_info/page_info.cc index 93cada1..295235ff 100644 --- a/components/page_info/page_info.cc +++ b/components/page_info/page_info.cc
@@ -1076,8 +1076,10 @@ CONTENT_SETTING_DEFAULT, permissions::PermissionStatusSource::UNSPECIFIED); if (permissions::PermissionUtil::IsPermission(permission_info.type)) { - permission_result = - delegate_->GetPermissionStatus(permission_info.type, site_url_); + permission_result = delegate_->GetPermissionResult( + permissions::PermissionUtil::ContentSettingTypeToPermissionType( + permission_info.type), + url::Origin::Create(site_url_)); } else if (permission_info.type == ContentSettingsType::FEDERATED_IDENTITY_API) { absl::optional<permissions::PermissionResult> embargo_result =
diff --git a/components/page_info/page_info_delegate.h b/components/page_info/page_info_delegate.h index ee85dc55..f5ecdd27 100644 --- a/components/page_info/page_info_delegate.h +++ b/components/page_info/page_info_delegate.h
@@ -17,6 +17,10 @@ #include "components/safe_browsing/core/browser/password_protection/metrics_util.h" #include "components/security_state/core/security_state.h" +namespace blink { +enum class PermissionType; +} + namespace permissions { class ObjectPermissionContextBase; class PermissionDecisionAutoBlocker; @@ -30,6 +34,10 @@ class Event; } // namespace ui +namespace url { +class Origin; +} + class HostContentSettingsMap; class StatefulSSLHostStateDelegate; @@ -54,9 +62,9 @@ #endif // Get permission status for the permission associated with ContentSetting of // type |type|. - virtual permissions::PermissionResult GetPermissionStatus( - ContentSettingsType type, - const GURL& site_url) = 0; + virtual permissions::PermissionResult GetPermissionResult( + blink::PermissionType permission, + const url::Origin& origin) = 0; #if !BUILDFLAG(IS_ANDROID) // Creates an infobars::ContentInfoBarManager and an InfoBarDelegate using it, // if possible. Returns true if an InfoBarDelegate was created, false
diff --git a/components/page_info/page_info_ui.cc b/components/page_info/page_info_ui.cc index 6a8d5db..4859faca 100644 --- a/components/page_info/page_info_ui.cc +++ b/components/page_info/page_info_ui.cc
@@ -762,7 +762,10 @@ CONTENT_SETTING_DEFAULT, permissions::PermissionStatusSource::UNSPECIFIED); if (permissions::PermissionUtil::IsPermission(permission.type)) { - permission_result = delegate->GetPermissionStatus(permission.type); + blink::PermissionType permission_type = + permissions::PermissionUtil::ContentSettingTypeToPermissionType( + permission.type); + permission_result = delegate->GetPermissionResult(permission_type); } else if (permission.type == ContentSettingsType::FEDERATED_IDENTITY_API) { absl::optional<permissions::PermissionResult> embargo_result = delegate->GetEmbargoResult(permission.type);
diff --git a/components/page_info/page_info_ui_delegate.h b/components/page_info/page_info_ui_delegate.h index 641db35..bcad2092 100644 --- a/components/page_info/page_info_ui_delegate.h +++ b/components/page_info/page_info_ui_delegate.h
@@ -10,6 +10,10 @@ #include "components/permissions/permission_result.h" #include "third_party/abseil-cpp/absl/types/optional.h" +namespace blink { +enum class PermissionType; +} + class PageInfoUiDelegate { public: virtual ~PageInfoUiDelegate() = default; @@ -17,8 +21,8 @@ virtual bool IsBlockAutoPlayEnabled() = 0; virtual bool IsMultipleTabsOpen() = 0; #endif - virtual permissions::PermissionResult GetPermissionStatus( - ContentSettingsType type) = 0; + virtual permissions::PermissionResult GetPermissionResult( + blink::PermissionType permission) = 0; virtual absl::optional<permissions::PermissionResult> GetEmbargoResult( ContentSettingsType type) = 0; };
diff --git a/components/payments/content/installable_payment_app_crawler.cc b/components/payments/content/installable_payment_app_crawler.cc index 841e434..0797946 100644 --- a/components/payments/content/installable_payment_app_crawler.cc +++ b/components/payments/content/installable_payment_app_crawler.cc
@@ -21,6 +21,7 @@ #include "content/public/browser/manifest_icon_downloader.h" #include "content/public/browser/payment_app_provider_util.h" #include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" @@ -185,10 +186,11 @@ continue; } - if (permission_controller->GetPermissionStatusForOriginWithoutContext( - blink::PermissionType::PAYMENT_HANDLER, - url::Origin::Create(web_app_manifest_url)) != - blink::mojom::PermissionStatus::GRANTED) { + if (permission_controller + ->GetPermissionResultForOriginWithoutContext( + blink::PermissionType::PAYMENT_HANDLER, + url::Origin::Create(web_app_manifest_url)) + .status != blink::mojom::PermissionStatus::GRANTED) { // Do not download the web app manifest if it is blocked. continue; }
diff --git a/components/performance_manager/BUILD.gn b/components/performance_manager/BUILD.gn index 2d58f6cb..da482ff 100644 --- a/components/performance_manager/BUILD.gn +++ b/components/performance_manager/BUILD.gn
@@ -97,7 +97,6 @@ "graph/worker_node_impl_describer.h", "graph_features.cc", "metrics/metrics_collector.cc", - "metrics/metrics_provider.cc", "owned_objects.h", "performance_manager.cc", "performance_manager_feature_observer_client.cc", @@ -139,7 +138,6 @@ "public/graph/worker_node.h", "public/metrics/background_metrics_reporter.h", "public/metrics/metrics_collector.h", - "public/metrics/metrics_provider.h", "public/performance_manager.h", "public/performance_manager_main_thread_mechanism.h", "public/performance_manager_main_thread_observer.h", @@ -285,7 +283,6 @@ "graph/worker_node_impl_unittest.cc", "graph_features_unittest.cc", "metrics/metrics_collector_unittest.cc", - "metrics/metrics_provider_unittest.cc", "owned_objects_unittest.cc", "performance_manager_impl_unittest.cc", "performance_manager_registry_impl_unittest.cc",
diff --git a/components/performance_manager/metrics/metrics_provider.cc b/components/performance_manager/metrics/metrics_provider.cc deleted file mode 100644 index b39f80c..0000000 --- a/components/performance_manager/metrics/metrics_provider.cc +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2022 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/performance_manager/public/metrics/metrics_provider.h" - -#include "base/metrics/histogram_functions.h" -#include "components/performance_manager/public/user_tuning/prefs.h" -#include "components/prefs/pref_service.h" - -namespace performance_manager { - -MetricsProvider::MetricsProvider(PrefService* local_state) - : local_state_(local_state) { - pref_change_registrar_.Init(local_state_); - pref_change_registrar_.Add( - performance_manager::user_tuning::prefs::kHighEfficiencyModeEnabled, - base::BindRepeating(&MetricsProvider::OnEfficiencyModeChanged, - base::Unretained(this))); - pref_change_registrar_.Add( - performance_manager::user_tuning::prefs::kBatterySaverModeEnabled, - base::BindRepeating(&MetricsProvider::OnEfficiencyModeChanged, - base::Unretained(this))); - - current_mode_ = ComputeCurrentMode(); -} - -MetricsProvider::~MetricsProvider() = default; - -void MetricsProvider::ProvideCurrentSessionData( - metrics::ChromeUserMetricsExtension* uma_proto) { - base::UmaHistogramEnumeration("PerformanceManager.UserTuning.EfficiencyMode", - current_mode_); - - // Set `current_mode_` to represent the state of the modes as they are now, so - // that this mode is what is adequately reported at the next report, unless it - // changes in the meantime. - current_mode_ = ComputeCurrentMode(); -} - -void MetricsProvider::OnEfficiencyModeChanged() { - EfficiencyMode new_mode = ComputeCurrentMode(); - - // If the mode changes between UMA reports, mark it as Mixed for this - // interval. - if (current_mode_ != new_mode) { - current_mode_ = EfficiencyMode::kMixed; - } -} - -MetricsProvider::EfficiencyMode MetricsProvider::ComputeCurrentMode() const { - bool high_efficiency_enabled = local_state_->GetBoolean( - performance_manager::user_tuning::prefs::kHighEfficiencyModeEnabled); - bool battery_saver_enabled = local_state_->GetBoolean( - performance_manager::user_tuning::prefs::kBatterySaverModeEnabled); - - if (high_efficiency_enabled && battery_saver_enabled) { - return EfficiencyMode::kBoth; - } - - if (high_efficiency_enabled) { - return EfficiencyMode::kHighEfficiency; - } - - if (battery_saver_enabled) { - return EfficiencyMode::kBatterySaver; - } - - return EfficiencyMode::kNormal; -} - -} // namespace performance_manager \ No newline at end of file
diff --git a/components/performance_manager/public/metrics/metrics_provider.h b/components/performance_manager/public/metrics/metrics_provider.h deleted file mode 100644 index d940b9f..0000000 --- a/components/performance_manager/public/metrics/metrics_provider.h +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright 2022 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_METRICS_METRICS_PROVIDER_H_ -#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_METRICS_METRICS_PROVIDER_H_ - -#include "base/memory/raw_ptr.h" -#include "components/metrics/metrics_provider.h" - -#include "components/prefs/pref_change_registrar.h" - -class PrefService; - -namespace performance_manager { - -// A metrics provider to add some performance manager related metrics to the UMA -// protos on each upload. -class MetricsProvider : public metrics::MetricsProvider { - public: - enum class EfficiencyMode { - // No efficiency mode for the entire upload window - kNormal = 0, - // In high efficiency mode for the entire upload window - kHighEfficiency = 1, - // In battery saver mode for the entire upload window - kBatterySaver = 2, - // Both modes enabled for the entire upload window - kBoth = 3, - // The modes were changed during the upload window - kMixed = 4, - // Max value, used in UMA histograms macros - kMaxValue = kMixed - }; - - explicit MetricsProvider(PrefService* local_state); - ~MetricsProvider() override; - - // metrics::MetricsProvider: - // This is only called from UMA code but is public for testing. - void ProvideCurrentSessionData( - metrics::ChromeUserMetricsExtension* uma_proto) override; - - private: - void OnEfficiencyModeChanged(); - EfficiencyMode ComputeCurrentMode() const; - - PrefChangeRegistrar pref_change_registrar_; - const raw_ptr<PrefService> local_state_; - EfficiencyMode current_mode_ = EfficiencyMode::kNormal; -}; - -} // namespace performance_manager - -#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_METRICS_METRICS_PROVIDER_H_
diff --git a/components/permissions/contexts/geolocation_permission_context_unittest.cc b/components/permissions/contexts/geolocation_permission_context_unittest.cc index 309c4aea5..8f3c281e 100644 --- a/components/permissions/contexts/geolocation_permission_context_unittest.cc +++ b/components/permissions/contexts/geolocation_permission_context_unittest.cc
@@ -49,6 +49,7 @@ #include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/test/mock_render_process_host.h" @@ -240,8 +241,9 @@ const GURL& requesting_origin) { return browser_context() ->GetPermissionController() - ->GetPermissionStatusForOriginWithoutContext( - permission, url::Origin::Create(requesting_origin)); + ->GetPermissionResultForOriginWithoutContext( + permission, url::Origin::Create(requesting_origin)) + .status; } void GeolocationPermissionContextTests::PermissionResponse(
diff --git a/components/permissions/permission_manager.cc b/components/permissions/permission_manager.cc index 96d7af03..04d25e1 100644 --- a/components/permissions/permission_manager.cc +++ b/components/permissions/permission_manager.cc
@@ -28,6 +28,8 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "third_party/blink/public/common/permissions/permission_utils.h" +#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" +#include "url/origin.h" using blink::PermissionType; using blink::mojom::PermissionStatus; @@ -35,60 +37,11 @@ namespace permissions { namespace { -// Represents the possible methods of delegating permissions from main frames -// to child frames. -enum class PermissionDelegationMode { - // Permissions from the main frame are delegated to child frames. - // This is the default delegation mode for permissions. If a main frame was - // granted a permission that is delegated, its child frames will inherit that - // permission if allowed by the permissions policy. - kDelegated, - // Permissions from the main frame are not delegated to child frames. - // An undelegated permission will only be granted to a child frame if the - // child frame's origin was previously granted access to the permission when - // in a main frame. - kUndelegated, - // Permission access is a function of both the requesting and embedding - // origins. - kDoubleKeyed, -}; - -// Helper methods to convert ContentSetting to PermissionStatus and vice versa. -PermissionStatus ContentSettingToPermissionStatus(ContentSetting setting) { - switch (setting) { - case CONTENT_SETTING_ALLOW: - return PermissionStatus::GRANTED; - case CONTENT_SETTING_BLOCK: - return PermissionStatus::DENIED; - case CONTENT_SETTING_ASK: - return PermissionStatus::ASK; - case CONTENT_SETTING_SESSION_ONLY: - case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT: - case CONTENT_SETTING_DEFAULT: - case CONTENT_SETTING_NUM_SETTINGS: - break; - } - - NOTREACHED(); - return PermissionStatus::DENIED; -} - -PermissionDelegationMode GetPermissionDelegationMode( - ContentSettingsType permission) { - // TODO(crbug.com/987654): Generalize this to other "background permissions", - // that is, permissions that can be used by a service worker. This includes - // durable storage, background sync, etc. - if (permission == ContentSettingsType::NOTIFICATIONS) - return PermissionDelegationMode::kUndelegated; - if (permission == ContentSettingsType::STORAGE_ACCESS) - return PermissionDelegationMode::kDoubleKeyed; - return PermissionDelegationMode::kDelegated; -} - void SubscriptionCallbackWrapper( base::OnceCallback<void(PermissionStatus)> callback, ContentSetting content_setting) { - std::move(callback).Run(ContentSettingToPermissionStatus(content_setting)); + std::move(callback).Run( + PermissionUtil::ContentSettingToPermissionStatus(content_setting)); } void PermissionStatusVectorCallbackWrapper( @@ -97,7 +50,7 @@ std::vector<PermissionStatus> permission_statuses; std::transform(content_settings.begin(), content_settings.end(), back_inserter(permission_statuses), - ContentSettingToPermissionStatus); + PermissionUtil::ContentSettingToPermissionStatus); std::move(callback).Run(permission_statuses); } @@ -107,7 +60,7 @@ content::WebContents::FromRenderFrameHost(render_frame_host); DCHECK(web_contents); - if (PermissionsClient::Get()->DoOriginsMatchNewTabPage( + if (PermissionsClient::Get()->DoURLsMatchNewTabPage( requesting_origin, web_contents->GetLastCommittedURL().DeprecatedGetOriginAsURL())) { return web_contents->GetLastCommittedURL().DeprecatedGetOriginAsURL(); @@ -116,36 +69,6 @@ render_frame_host->GetMainFrame()); } } - -// If an iframed document/worker inherits a different StoragePartition from its -// embedder than it would use if it were a main frame, we should block -// undelegated permissions. Because permissions are scoped to BrowserContext -// instead of StoragePartition, without this check the aforementioned iframe -// would be given undelegated permissions if the user had granted its origin -// access when it was loaded as a main frame. -bool IsPermissionBlockedInPartition( - ContentSettingsType permission, - const GURL& requesting_origin, - content::RenderProcessHost* render_process_host) { - DCHECK(render_process_host); - switch (GetPermissionDelegationMode(permission)) { - case PermissionDelegationMode::kDelegated: - return false; - case PermissionDelegationMode::kDoubleKeyed: - return false; - case PermissionDelegationMode::kUndelegated: - // TODO(crbug.com/1312218): This will create |requesting_origin|'s home - // StoragePartition if it doesn't already exist. Given how - // StoragePartitions are used today, this shouldn't actually be a - // problem, but ideally we'd compare StoragePartitionConfigs. - content::StoragePartition* requesting_home_partition = - render_process_host->GetBrowserContext()->GetStoragePartitionForUrl( - requesting_origin); - return requesting_home_partition != - render_process_host->GetStoragePartition(); - } -} - } // anonymous namespace class PermissionManager::PendingRequest { @@ -250,59 +173,6 @@ DCHECK(subscriptions_.IsEmpty()); } -GURL PermissionManager::GetCanonicalOrigin(ContentSettingsType permission, - const GURL& requesting_origin, - const GURL& embedding_origin) const { - absl::optional<GURL> override_origin = - PermissionsClient::Get()->OverrideCanonicalOrigin(requesting_origin, - embedding_origin); - if (override_origin) - return override_origin.value(); - - switch (GetPermissionDelegationMode(permission)) { - case PermissionDelegationMode::kDelegated: - return embedding_origin; - case PermissionDelegationMode::kDoubleKeyed: - case PermissionDelegationMode::kUndelegated: - return requesting_origin; - } -} - -PermissionResult PermissionManager::GetPermissionStatusDeprecated( - ContentSettingsType permission, - const GURL& requesting_origin, - const GURL& embedding_origin) { - DCHECK_EQ(requesting_origin, embedding_origin); - - return GetPermissionStatusHelper(permission, - /*render_process_host=*/nullptr, - /*render_frame_host=*/nullptr, - requesting_origin, embedding_origin); -} - -PermissionResult PermissionManager::GetPermissionStatusForDisplayOnSettingsUI( - ContentSettingsType permission, - const GURL& origin) { - return GetPermissionStatusHelper(permission, - /*render_process_host=*/nullptr, - /*render_frame_host=*/nullptr, origin, - origin); -} - -PermissionResult PermissionManager::GetPermissionStatusForCurrentDocument( - ContentSettingsType permission, - content::RenderFrameHost* render_frame_host) { - const GURL requesting_origin = - PermissionUtil::GetLastCommittedOriginAsURL(render_frame_host); - const GURL embedding_origin = - GetEmbeddingOrigin(render_frame_host, requesting_origin); - - return GetPermissionStatusHelper(permission, - /*render_process_host=*/nullptr, - render_frame_host, requesting_origin, - embedding_origin); -} - void PermissionManager::Shutdown() { is_shutting_down_ = true; @@ -357,13 +227,13 @@ const GURL& embedding_origin) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ContentSettingsType type = - PermissionUtil::PermissionTypeToContentSetting(permission); + PermissionUtil::PermissionTypeToContentSettingType(permission); PermissionContextBase* context = GetPermissionContext(type); if (!context) return; - context->ResetPermission( - GetCanonicalOrigin(type, requesting_origin, embedding_origin), - embedding_origin.DeprecatedGetOriginAsURL()); + context->ResetPermission(PermissionUtil::GetCanonicalOrigin( + type, requesting_origin, embedding_origin), + embedding_origin.DeprecatedGetOriginAsURL()); } void PermissionManager::RequestPermissionsFromCurrentDocument( @@ -377,7 +247,7 @@ std::vector<ContentSettingsType> permissions; std::transform(permissions_types.begin(), permissions_types.end(), back_inserter(permissions), - PermissionUtil::PermissionTypeToContentSetting); + PermissionUtil::PermissionTypeToContentSettingType); base::OnceCallback<void(const std::vector<ContentSetting>&)> callback = base::BindOnce(&PermissionStatusVectorCallbackWrapper, @@ -402,13 +272,13 @@ for (size_t i = 0; i < permissions.size(); ++i) { const ContentSettingsType permission = permissions[i]; - const GURL canonical_requesting_origin = - GetCanonicalOrigin(permission, requesting_origin, embedding_origin); + const GURL canonical_requesting_origin = PermissionUtil::GetCanonicalOrigin( + permission, requesting_origin, embedding_origin); auto response_callback = std::make_unique<PermissionResponseCallback>(this, request_local_id, i); - if (IsPermissionBlockedInPartition(permission, requesting_origin, - render_frame_host->GetProcess())) { + if (PermissionUtil::IsPermissionBlockedInPartition( + permission, requesting_origin, render_frame_host->GetProcess())) { response_callback->OnPermissionsRequestResponseStatus( CONTENT_SETTING_BLOCK); continue; @@ -440,31 +310,53 @@ // TODO(benwells): split this into two functions, GetPermissionStatus and // GetPermissionStatusForPermissionsAPI. DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - PermissionResult result = GetPermissionStatusHelper( - PermissionUtil::PermissionTypeToContentSetting(permission), + PermissionResult result = GetPermissionStatusInternal( + PermissionUtil::PermissionTypeToContentSettingType(permission), /*render_process_host=*/nullptr, /*render_frame_host=*/nullptr, requesting_origin, embedding_origin); - return ContentSettingToPermissionStatus(result.content_setting); + return PermissionUtil::ContentSettingToPermissionStatus( + result.content_setting); +} + +content::PermissionResult +PermissionManager::GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + PermissionResult result = GetPermissionStatusInternal( + PermissionUtil::PermissionTypeToContentSettingType(permission), + /*render_process_host=*/nullptr, + /*render_frame_host=*/nullptr, origin.GetURL(), origin.GetURL()); + + return PermissionUtil::ToContentPermissionResult(result); } PermissionStatus PermissionManager::GetPermissionStatusForCurrentDocument( PermissionType permission, content::RenderFrameHost* render_frame_host) { + return GetPermissionResultForCurrentDocument(permission, render_frame_host) + .status; +} + +content::PermissionResult +PermissionManager::GetPermissionResultForCurrentDocument( + blink::PermissionType permission, + content::RenderFrameHost* render_frame_host) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ContentSettingsType type = - PermissionUtil::PermissionTypeToContentSetting(permission); + PermissionUtil::PermissionTypeToContentSettingType(permission); const GURL requesting_origin = PermissionUtil::GetLastCommittedOriginAsURL(render_frame_host); const GURL embedding_origin = GetEmbeddingOrigin(render_frame_host, requesting_origin); - PermissionResult result = GetPermissionStatusHelper( + PermissionResult result = GetPermissionStatusInternal( type, /*render_process_host=*/nullptr, render_frame_host, requesting_origin, embedding_origin); - return ContentSettingToPermissionStatus(result.content_setting); + return PermissionUtil::ToContentPermissionResult(result); } PermissionStatus PermissionManager::GetPermissionStatusForWorker( @@ -473,19 +365,20 @@ const GURL& worker_origin) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ContentSettingsType type = - PermissionUtil::PermissionTypeToContentSetting(permission); - PermissionResult result = GetPermissionStatusHelper( + PermissionUtil::PermissionTypeToContentSettingType(permission); + PermissionResult result = GetPermissionStatusInternal( type, render_process_host, /*render_frame_host=*/nullptr, worker_origin, worker_origin); - return ContentSettingToPermissionStatus(result.content_setting); + return PermissionUtil::ContentSettingToPermissionStatus( + result.content_setting); } bool PermissionManager::IsPermissionOverridableByDevTools( PermissionType permission, const absl::optional<url::Origin>& origin) { ContentSettingsType type = - PermissionUtil::PermissionTypeToContentSettingSafe(permission); + PermissionUtil::PermissionTypeToContentSettingTypeSafe(permission); PermissionContextBase* context = GetPermissionContext(type); if (!context || context->IsPermissionKillSwitchOn()) @@ -508,7 +401,7 @@ return SubscriptionId(); ContentSettingsType content_type = - PermissionUtil::PermissionTypeToContentSetting(permission); + PermissionUtil::PermissionTypeToContentSettingType(permission); auto& type_count = subscription_type_counts_[content_type]; if (type_count == 0) { PermissionContextBase* context = GetPermissionContext(content_type); @@ -528,10 +421,10 @@ subscription->render_frame_id = render_frame_host->GetRoutingID(); subscription->render_process_id = render_frame_host->GetProcess()->GetID(); subscription->current_value = - GetPermissionStatusHelper(content_type, - /*render_process_host=*/nullptr, - render_frame_host, requesting_origin, - embedding_origin) + GetPermissionStatusInternal(content_type, + /*render_process_host=*/nullptr, + render_frame_host, requesting_origin, + embedding_origin) .content_setting; } else { @@ -540,15 +433,15 @@ subscription->render_process_id = render_process_host ? render_process_host->GetID() : -1; subscription->current_value = - GetPermissionStatusHelper(content_type, render_process_host, - /*render_frame_host=*/nullptr, - requesting_origin, embedding_origin) + GetPermissionStatusInternal(content_type, render_process_host, + /*render_frame_host=*/nullptr, + requesting_origin, embedding_origin) .content_setting; } subscription->permission = content_type; - subscription->requesting_origin = - GetCanonicalOrigin(content_type, requesting_origin, embedding_origin); + subscription->requesting_origin = PermissionUtil::GetCanonicalOrigin( + content_type, requesting_origin, embedding_origin); subscription->callback = base::BindRepeating(&SubscriptionCallbackWrapper, std::move(callback)); @@ -635,9 +528,9 @@ subscription->render_process_id); ContentSetting new_value = - GetPermissionStatusHelper(subscription->permission, rph, rfh, - subscription->requesting_origin, - embedding_origin) + GetPermissionStatusInternal(subscription->permission, rph, rfh, + subscription->requesting_origin, + embedding_origin) .content_setting; if (subscription->current_value == new_value) @@ -654,7 +547,7 @@ std::move(callback).Run(); } -PermissionResult PermissionManager::GetPermissionStatusHelper( +PermissionResult PermissionManager::GetPermissionStatusInternal( ContentSettingsType permission, content::RenderProcessHost* render_process_host, content::RenderFrameHost* render_frame_host, @@ -665,14 +558,14 @@ // TODO(crbug.com/1307044): Move this to PermissionContextBase. content::RenderProcessHost* rph = render_frame_host ? render_frame_host->GetProcess() : render_process_host; - if (rph && - IsPermissionBlockedInPartition(permission, requesting_origin, rph)) { + if (rph && PermissionUtil::IsPermissionBlockedInPartition( + permission, requesting_origin, rph)) { return PermissionResult(CONTENT_SETTING_BLOCK, PermissionStatusSource::UNSPECIFIED); } - GURL canonical_requesting_origin = - GetCanonicalOrigin(permission, requesting_origin, embedding_origin); + GURL canonical_requesting_origin = PermissionUtil::GetCanonicalOrigin( + permission, requesting_origin, embedding_origin); auto status = GetPermissionOverrideForDevTools( url::Origin::Create(canonical_requesting_origin), permission); if (status != CONTENT_SETTING_DEFAULT) @@ -711,7 +604,7 @@ ContentSettingsTypeOverrides result; for (const auto& item : overrides) { ContentSettingsType content_setting = - PermissionUtil::PermissionTypeToContentSettingSafe(item.first); + PermissionUtil::PermissionTypeToContentSettingTypeSafe(item.first); if (content_setting != ContentSettingsType::DEFAULT) result[content_setting] = PermissionUtil::PermissionStatusToContentSetting(item.second);
diff --git a/components/permissions/permission_manager.h b/components/permissions/permission_manager.h index bace981..ed0b5ba 100644 --- a/components/permissions/permission_manager.h +++ b/components/permissions/permission_manager.h
@@ -19,6 +19,7 @@ #include "components/permissions/permission_request_id.h" #include "components/permissions/permission_util.h" #include "content/public/browser/permission_controller_delegate.h" +#include "content/public/browser/permission_result.h" #include "url/origin.h" namespace blink { @@ -55,42 +56,6 @@ ~PermissionManager() override; - // Converts from |url|'s actual origin to the "canonical origin" that should - // be used for the purpose of requesting/storing permissions. For example, the - // origin of the local NTP gets mapped to the Google base URL instead. With - // Permission Delegation it will transform the requesting origin into - // the embedding origin because all permission checks happen on the top level - // origin. - // - // All the public methods below, such as RequestPermission or - // GetPermissionStatus, take the actual origin and do the canonicalization - // internally. You only need to call this directly if you do something else - // with the origin, such as display it in the UI. - GURL GetCanonicalOrigin(ContentSettingsType permission, - const GURL& requesting_origin, - const GURL& embedding_origin) const; - - // This method is deprecated. Use `GetPermissionStatusForCurrentDocument` - // instead or `GetPermissionStatusForDisplayOnSettingsUI`. - PermissionResult GetPermissionStatusDeprecated(ContentSettingsType permission, - const GURL& requesting_origin, - const GURL& embedding_origin); - - // Returns the permission status for a given `permission` and displayed, - // top-level `origin`. This should be used only for displaying on the - // browser's native UI (PageInfo, Settings, etc.). This method does not take - // context specific restrictions (e.g. permission policy) into consideration. - PermissionResult GetPermissionStatusForDisplayOnSettingsUI( - ContentSettingsType permission, - const GURL& origin); - - // Returns the status for the given `permission` on behalf of the last - // committed document in `render_frame_host`, also performing additional - // checks such as Permission Policy. - PermissionResult GetPermissionStatusForCurrentDocument( - ContentSettingsType permission, - content::RenderFrameHost* render_frame_host); - // KeyedService implementation. void Shutdown() override; @@ -154,9 +119,15 @@ blink::PermissionType permission, const GURL& requesting_origin, const GURL& embedding_origin) override; + content::PermissionResult GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) override; blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument( blink::PermissionType permission, content::RenderFrameHost* render_frame_host) override; + content::PermissionResult GetPermissionResultForCurrentDocument( + blink::PermissionType permission, + content::RenderFrameHost* render_frame_host) override; blink::mojom::PermissionStatus GetPermissionStatusForWorker( blink::PermissionType permission, content::RenderProcessHost* render_process_host, @@ -192,7 +163,7 @@ // Only one of |render_process_host| and |render_frame_host| should be set, // or neither. RenderProcessHost will be inferred from |render_frame_host|. - PermissionResult GetPermissionStatusHelper( + PermissionResult GetPermissionStatusInternal( ContentSettingsType permission, content::RenderProcessHost* render_process_host, content::RenderFrameHost* render_frame_host,
diff --git a/components/permissions/permission_manager_unittest.cc b/components/permissions/permission_manager_unittest.cc index a4e3f51..a277dff9 100644 --- a/components/permissions/permission_manager_unittest.cc +++ b/components/permissions/permission_manager_unittest.cc
@@ -17,10 +17,12 @@ #include "components/permissions/permission_context_base.h" #include "components/permissions/permission_request_manager.h" #include "components/permissions/permission_result.h" +#include "components/permissions/permission_util.h" #include "components/permissions/test/mock_permission_prompt_factory.h" #include "components/permissions/test/permission_test_util.h" #include "components/permissions/test/test_permissions_client.h" #include "content/public/browser/content_browser_client.h" +#include "content/public/browser/permission_result.h" #include "content/public/common/content_client.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/mock_render_process_host.h" @@ -82,8 +84,8 @@ auto GetDefaultProtectedMediaIdentifierContentSetting() { return base::android::BuildInfo::GetInstance()->sdk_int() >= base::android::SDK_VERSION_MARSHMALLOW - ? CONTENT_SETTING_ALLOW - : CONTENT_SETTING_ASK; + ? PermissionStatus::GRANTED + : PermissionStatus::ASK; } #endif // BUILDFLAG(IS_ANDROID) @@ -113,31 +115,41 @@ } void CheckPermissionStatus(PermissionType type, PermissionStatus expected) { - EXPECT_EQ(expected, GetPermissionManager()->GetPermissionStatus( - type, url_.DeprecatedGetOriginAsURL(), - url_.DeprecatedGetOriginAsURL())); + EXPECT_EQ(expected, GetPermissionManager() + ->GetPermissionResultForOriginWithoutContext( + type, url::Origin::Create(url_)) + .status); } - void CheckPermissionResult(ContentSettingsType type, - ContentSetting expected_status, - PermissionStatusSource expected_status_source) { - PermissionResult result = - GetPermissionManager()->GetPermissionStatusDeprecated( - type, url_.DeprecatedGetOriginAsURL(), - url_.DeprecatedGetOriginAsURL()); - EXPECT_EQ(expected_status, result.content_setting); + void CheckPermissionResult( + PermissionType type, + PermissionStatus expected_status, + content::PermissionStatusSource expected_status_source) { + content::PermissionResult result = + GetPermissionManager()->GetPermissionResultForOriginWithoutContext( + type, url::Origin::Create(url_)); + EXPECT_EQ(expected_status, result.status); EXPECT_EQ(expected_status_source, result.source); } - void SetPermission(ContentSettingsType type, ContentSetting value) { - SetPermission(url_, type, value); + void SetPermission(PermissionType type, PermissionStatus value) { + SetPermission(url_, url_, type, value); } void SetPermission(const GURL& origin, - ContentSettingsType type, - ContentSetting value) { - GetHostContentSettingsMap()->SetContentSettingDefaultScope(origin, origin, - type, value); + PermissionType type, + PermissionStatus value) { + SetPermission(origin, origin, type, value); + } + + void SetPermission(const GURL& requesting_origin, + const GURL& embedding_origin, + PermissionType type, + PermissionStatus value) { + GetHostContentSettingsMap()->SetContentSettingDefaultScope( + requesting_origin, embedding_origin, + permissions::PermissionUtil::PermissionTypeToContentSettingType(type), + permissions::PermissionUtil::PermissionStatusToContentSetting(value)); } void RequestPermissionFromCurrentDocument(PermissionType type, @@ -181,6 +193,13 @@ permission, render_frame_host); } + content::PermissionResult GetPermissionResultForCurrentDocument( + PermissionType permission, + content::RenderFrameHost* render_frame_host) { + return GetPermissionManager()->GetPermissionResultForCurrentDocument( + permission, render_frame_host); + } + PermissionStatus GetPermissionStatusForWorker( PermissionType permission, content::RenderProcessHost* render_process_host, @@ -324,66 +343,66 @@ } TEST_F(PermissionManagerTest, GetPermissionStatusAfterSet) { - SetPermission(ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED); CheckPermissionStatus(PermissionType::GEOLOCATION, PermissionStatus::GRANTED); - SetPermission(ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_ALLOW); + SetPermission(PermissionType::NOTIFICATIONS, PermissionStatus::GRANTED); CheckPermissionStatus(PermissionType::NOTIFICATIONS, PermissionStatus::GRANTED); - SetPermission(ContentSettingsType::MIDI_SYSEX, CONTENT_SETTING_ALLOW); + SetPermission(PermissionType::MIDI_SYSEX, PermissionStatus::GRANTED); CheckPermissionStatus(PermissionType::MIDI_SYSEX, PermissionStatus::GRANTED); #if BUILDFLAG(IS_ANDROID) - SetPermission(ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER, - CONTENT_SETTING_ALLOW); + SetPermission(PermissionType::PROTECTED_MEDIA_IDENTIFIER, + PermissionStatus::GRANTED); CheckPermissionStatus(PermissionType::PROTECTED_MEDIA_IDENTIFIER, PermissionStatus::GRANTED); - SetPermission(ContentSettingsType::WINDOW_PLACEMENT, CONTENT_SETTING_ALLOW); + SetPermission(PermissionType::WINDOW_PLACEMENT, PermissionStatus::GRANTED); CheckPermissionStatus(PermissionType::WINDOW_PLACEMENT, PermissionStatus::DENIED); #else - SetPermission(ContentSettingsType::WINDOW_PLACEMENT, CONTENT_SETTING_ALLOW); + SetPermission(PermissionType::WINDOW_PLACEMENT, PermissionStatus::GRANTED); CheckPermissionStatus(PermissionType::WINDOW_PLACEMENT, PermissionStatus::GRANTED); #endif } TEST_F(PermissionManagerTest, CheckPermissionResultDefault) { - CheckPermissionResult(ContentSettingsType::MIDI_SYSEX, CONTENT_SETTING_ASK, - PermissionStatusSource::UNSPECIFIED); - CheckPermissionResult(ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_ASK, - PermissionStatusSource::UNSPECIFIED); - CheckPermissionResult(ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ASK, - PermissionStatusSource::UNSPECIFIED); + CheckPermissionResult(PermissionType::MIDI_SYSEX, PermissionStatus::ASK, + content::PermissionStatusSource::UNSPECIFIED); + CheckPermissionResult(PermissionType::NOTIFICATIONS, PermissionStatus::ASK, + content::PermissionStatusSource::UNSPECIFIED); + CheckPermissionResult(PermissionType::GEOLOCATION, PermissionStatus::ASK, + content::PermissionStatusSource::UNSPECIFIED); #if BUILDFLAG(IS_ANDROID) - CheckPermissionResult(ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER, + CheckPermissionResult(PermissionType::PROTECTED_MEDIA_IDENTIFIER, GetDefaultProtectedMediaIdentifierContentSetting(), - PermissionStatusSource::UNSPECIFIED); + content::PermissionStatusSource::UNSPECIFIED); #endif } TEST_F(PermissionManagerTest, CheckPermissionResultAfterSet) { - SetPermission(ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW); - CheckPermissionResult(ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW, - PermissionStatusSource::UNSPECIFIED); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED); + CheckPermissionResult(PermissionType::GEOLOCATION, PermissionStatus::GRANTED, + content::PermissionStatusSource::UNSPECIFIED); - SetPermission(ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_ALLOW); - CheckPermissionResult(ContentSettingsType::NOTIFICATIONS, - CONTENT_SETTING_ALLOW, - PermissionStatusSource::UNSPECIFIED); + SetPermission(PermissionType::NOTIFICATIONS, PermissionStatus::GRANTED); + CheckPermissionResult(PermissionType::NOTIFICATIONS, + PermissionStatus::GRANTED, + content::PermissionStatusSource::UNSPECIFIED); - SetPermission(ContentSettingsType::MIDI_SYSEX, CONTENT_SETTING_ALLOW); - CheckPermissionResult(ContentSettingsType::MIDI_SYSEX, CONTENT_SETTING_ALLOW, - PermissionStatusSource::UNSPECIFIED); + SetPermission(PermissionType::MIDI_SYSEX, PermissionStatus::GRANTED); + CheckPermissionResult(PermissionType::MIDI_SYSEX, PermissionStatus::GRANTED, + content::PermissionStatusSource::UNSPECIFIED); #if BUILDFLAG(IS_ANDROID) - SetPermission(ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER, - CONTENT_SETTING_ALLOW); - CheckPermissionResult(ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER, - CONTENT_SETTING_ALLOW, - PermissionStatusSource::UNSPECIFIED); + SetPermission(PermissionType::PROTECTED_MEDIA_IDENTIFIER, + PermissionStatus::GRANTED); + CheckPermissionResult(PermissionType::PROTECTED_MEDIA_IDENTIFIER, + PermissionStatus::GRANTED, + content::PermissionStatusSource::UNSPECIFIED); #endif } @@ -431,8 +450,7 @@ base::BindRepeating(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED); EXPECT_TRUE(callback_called()); EXPECT_EQ(PermissionStatus::GRANTED, callback_result()); @@ -448,8 +466,8 @@ base::BindRepeating(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), GURL(), ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_ALLOW); + SetPermission(url(), GURL(), PermissionType::NOTIFICATIONS, + PermissionStatus::GRANTED); EXPECT_FALSE(callback_called()); @@ -466,8 +484,8 @@ UnsubscribePermissionStatusChange(subscription_id); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW); + SetPermission(url(), url(), PermissionType::GEOLOCATION, + PermissionStatus::GRANTED); EXPECT_FALSE(callback_called()); } @@ -489,8 +507,8 @@ UnsubscribePermissionStatusChange(subscription_id); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW); + SetPermission(url(), url(), PermissionType::GEOLOCATION, + PermissionStatus::GRANTED); EXPECT_EQ(callback_count(), 1); } @@ -503,9 +521,8 @@ base::BindRepeating(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - other_url(), url(), ContentSettingsType::GEOLOCATION, - CONTENT_SETTING_ALLOW); + SetPermission(other_url(), url(), PermissionType::GEOLOCATION, + PermissionStatus::GRANTED); EXPECT_FALSE(callback_called()); @@ -520,9 +537,8 @@ base::BindRepeating(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), other_url(), ContentSettingsType::STORAGE_ACCESS, - CONTENT_SETTING_ALLOW); + SetPermission(url(), other_url(), PermissionType::STORAGE_ACCESS_GRANT, + PermissionStatus::GRANTED); EXPECT_FALSE(callback_called()); @@ -547,8 +563,8 @@ } TEST_F(PermissionManagerTest, ClearSettingsNotifies) { - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW); + SetPermission(url(), url(), PermissionType::GEOLOCATION, + PermissionStatus::GRANTED); content::PermissionControllerDelegate::SubscriptionId subscription_id = SubscribePermissionStatusChange( @@ -574,8 +590,7 @@ base::BindRepeating(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_BLOCK); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::DENIED); EXPECT_TRUE(callback_called()); EXPECT_EQ(PermissionStatus::DENIED, callback_result()); @@ -584,8 +599,7 @@ } TEST_F(PermissionManagerTest, ChangeWithoutPermissionChangeDoesNotNotify) { - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED); content::PermissionControllerDelegate::SubscriptionId subscription_id = SubscribePermissionStatusChange( @@ -594,8 +608,8 @@ base::BindRepeating(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW); + SetPermission(url(), url(), PermissionType::GEOLOCATION, + PermissionStatus::GRANTED); EXPECT_FALSE(callback_called()); @@ -603,8 +617,8 @@ } TEST_F(PermissionManagerTest, ChangesBackAndForth) { - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ASK); + SetPermission(url(), url(), PermissionType::GEOLOCATION, + PermissionStatus::ASK); content::PermissionControllerDelegate::SubscriptionId subscription_id = SubscribePermissionStatusChange( @@ -613,16 +627,15 @@ base::BindRepeating(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW); + SetPermission(url(), url(), PermissionType::GEOLOCATION, + PermissionStatus::GRANTED); EXPECT_TRUE(callback_called()); EXPECT_EQ(PermissionStatus::GRANTED, callback_result()); Reset(); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ASK); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::ASK); EXPECT_TRUE(callback_called()); EXPECT_EQ(PermissionStatus::ASK, callback_result()); @@ -631,8 +644,7 @@ } TEST_F(PermissionManagerTest, ChangesBackAndForthWorker) { - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ASK); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::ASK); content::PermissionControllerDelegate::SubscriptionId subscription_id = SubscribePermissionStatusChange( @@ -641,16 +653,14 @@ base::BindRepeating(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED); EXPECT_TRUE(callback_called()); EXPECT_EQ(PermissionStatus::GRANTED, callback_result()); Reset(); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ASK); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::ASK); EXPECT_TRUE(callback_called()); EXPECT_EQ(PermissionStatus::ASK, callback_result()); @@ -667,8 +677,7 @@ base::Unretained(this))); CheckPermissionStatus(PermissionType::GEOLOCATION, PermissionStatus::ASK); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED); CheckPermissionStatus(PermissionType::GEOLOCATION, PermissionStatus::GRANTED); EXPECT_FALSE(callback_called()); @@ -702,22 +711,20 @@ GURL insecure_frame("http://www.example.com/geolocation"); NavigateAndCommit(insecure_frame); - PermissionResult result = - GetPermissionManager()->GetPermissionStatusForCurrentDocument( - ContentSettingsType::GEOLOCATION, - web_contents()->GetPrimaryMainFrame()); + content::PermissionResult result = GetPermissionResultForCurrentDocument( + PermissionType::GEOLOCATION, web_contents()->GetPrimaryMainFrame()); - EXPECT_EQ(CONTENT_SETTING_BLOCK, result.content_setting); - EXPECT_EQ(PermissionStatusSource::INSECURE_ORIGIN, result.source); + EXPECT_EQ(PermissionStatus::DENIED, result.status); + EXPECT_EQ(content::PermissionStatusSource::INSECURE_ORIGIN, result.source); GURL secure_frame("https://www.example.com/geolocation"); NavigateAndCommit(secure_frame); - result = GetPermissionManager()->GetPermissionStatusForCurrentDocument( - ContentSettingsType::GEOLOCATION, web_contents()->GetPrimaryMainFrame()); + result = GetPermissionResultForCurrentDocument( + PermissionType::GEOLOCATION, web_contents()->GetPrimaryMainFrame()); - EXPECT_EQ(CONTENT_SETTING_ASK, result.content_setting); - EXPECT_EQ(PermissionStatusSource::UNSPECIFIED, result.source); + EXPECT_EQ(PermissionStatus::ASK, result.status); + EXPECT_EQ(content::PermissionStatusSource::UNSPECIFIED, result.source); } TEST_F(PermissionManagerTest, InsecureOriginIsNotOverridable) { @@ -766,7 +773,7 @@ TEST_F(PermissionManagerTest, ResetPermission) { #if BUILDFLAG(IS_ANDROID) CheckPermissionStatus(PermissionType::NOTIFICATIONS, PermissionStatus::ASK); - SetPermission(ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_ALLOW); + SetPermission(PermissionType::NOTIFICATIONS, PermissionStatus::GRANTED); CheckPermissionStatus(PermissionType::NOTIFICATIONS, PermissionStatus::GRANTED); @@ -886,8 +893,7 @@ PermissionType::GEOLOCATION, child)); // Allow access for the top level origin. - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED); // The child's permission should still be block and no callback should be run. EXPECT_EQ(PermissionStatus::DENIED, GetPermissionStatusForCurrentDocument( @@ -911,8 +917,7 @@ // Blocking access to the parent should trigger the callback to be run for the // child also. - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_BLOCK); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::DENIED); EXPECT_TRUE(callback_called()); EXPECT_EQ(PermissionStatus::DENIED, callback_result()); @@ -935,8 +940,7 @@ base::Unretained(this))); EXPECT_EQ(callback_count(), 0); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED); EXPECT_EQ(callback_count(), 1); EXPECT_EQ(PermissionStatus::GRANTED, callback_result()); @@ -944,10 +948,8 @@ UnsubscribePermissionStatusChange(subscription_id); // ensure no callbacks are received when unsubscribed. - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_BLOCK); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::DENIED); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED); EXPECT_EQ(callback_count(), 1); @@ -959,8 +961,7 @@ base::Unretained(this))); EXPECT_EQ(callback_count(), 1); - GetHostContentSettingsMap()->SetContentSettingDefaultScope( - url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_BLOCK); + SetPermission(PermissionType::GEOLOCATION, PermissionStatus::DENIED); EXPECT_EQ(callback_count(), 2); EXPECT_EQ(PermissionStatus::DENIED, callback_result()); @@ -973,13 +974,13 @@ GURL embedding("https://embedding.example.com"); EXPECT_EQ(embedding, - GetPermissionManager()->GetCanonicalOrigin( + permissions::PermissionUtil::GetCanonicalOrigin( ContentSettingsType::COOKIES, requesting, embedding)); EXPECT_EQ(requesting, - GetPermissionManager()->GetCanonicalOrigin( + permissions::PermissionUtil::GetCanonicalOrigin( ContentSettingsType::NOTIFICATIONS, requesting, embedding)); EXPECT_EQ(requesting, - GetPermissionManager()->GetCanonicalOrigin( + permissions::PermissionUtil::GetCanonicalOrigin( ContentSettingsType::STORAGE_ACCESS, requesting, embedding)); } @@ -989,18 +990,18 @@ const GURL kPartitionedOrigin("https://partitioned.com"); ScopedPartitionedOriginBrowserClient browser_client(kPartitionedOrigin); - SetPermission(kOrigin, ContentSettingsType::GEOLOCATION, - ContentSetting::CONTENT_SETTING_ALLOW); + SetPermission(kOrigin, PermissionType::GEOLOCATION, + PermissionStatus::GRANTED); - SetPermission(kOrigin2, ContentSettingsType::GEOLOCATION, - ContentSetting::CONTENT_SETTING_BLOCK); - SetPermission(kOrigin2, ContentSettingsType::NOTIFICATIONS, - ContentSetting::CONTENT_SETTING_ALLOW); + SetPermission(kOrigin2, PermissionType::GEOLOCATION, + PermissionStatus::DENIED); + SetPermission(kOrigin2, PermissionType::NOTIFICATIONS, + PermissionStatus::GRANTED); - SetPermission(kPartitionedOrigin, ContentSettingsType::GEOLOCATION, - ContentSetting::CONTENT_SETTING_BLOCK); - SetPermission(kPartitionedOrigin, ContentSettingsType::NOTIFICATIONS, - ContentSetting::CONTENT_SETTING_ALLOW); + SetPermission(kPartitionedOrigin, PermissionType::GEOLOCATION, + PermissionStatus::DENIED); + SetPermission(kPartitionedOrigin, PermissionType::NOTIFICATIONS, + PermissionStatus::GRANTED); NavigateAndCommit(kOrigin); content::RenderFrameHost* parent = main_rfh();
diff --git a/components/permissions/permission_util.cc b/components/permissions/permission_util.cc index f13780e9..5f1e5ad 100644 --- a/components/permissions/permission_util.cc +++ b/components/permissions/permission_util.cc
@@ -10,7 +10,12 @@ #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "components/permissions/features.h" +#include "components/permissions/permission_result.h" +#include "components/permissions/permissions_client.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/permission_result.h" #include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "third_party/blink/public/common/permissions/permission_utils.h" #include "third_party/blink/public/common/web_preferences/web_preferences.h" @@ -21,6 +26,38 @@ namespace permissions { +namespace { +// Represents the possible methods of delegating permissions from main frames +// to child frames. +enum class PermissionDelegationMode { + // Permissions from the main frame are delegated to child frames. + // This is the default delegation mode for permissions. If a main frame was + // granted a permission that is delegated, its child frames will inherit that + // permission if allowed by the permissions policy. + kDelegated, + // Permissions from the main frame are not delegated to child frames. + // An undelegated permission will only be granted to a child frame if the + // child frame's origin was previously granted access to the permission when + // in a main frame. + kUndelegated, + // Permission access is a function of both the requesting and embedding + // origins. + kDoubleKeyed, +}; + +PermissionDelegationMode GetPermissionDelegationMode( + ContentSettingsType permission) { + // TODO(crbug.com/987654): Generalize this to other "background permissions", + // that is, permissions that can be used by a service worker. This includes + // durable storage, background sync, etc. + if (permission == ContentSettingsType::NOTIFICATIONS) + return PermissionDelegationMode::kUndelegated; + if (permission == ContentSettingsType::STORAGE_ACCESS) + return PermissionDelegationMode::kDoubleKeyed; + return PermissionDelegationMode::kDelegated; +} +} // namespace + // The returned strings must match any Field Trial configs for the Permissions // kill switch e.g. Permissions.Action.Geolocation etc.. std::string PermissionUtil::GetPermissionString( @@ -264,7 +301,7 @@ return render_frame_host->GetLastCommittedOrigin().GetURL(); } -ContentSettingsType PermissionUtil::PermissionTypeToContentSettingSafe( +ContentSettingsType PermissionUtil::PermissionTypeToContentSettingTypeSafe( PermissionType permission) { switch (permission) { case PermissionType::MIDI: @@ -332,16 +369,79 @@ return ContentSettingsType::DEFAULT; } -ContentSettingsType PermissionUtil::PermissionTypeToContentSetting( +ContentSettingsType PermissionUtil::PermissionTypeToContentSettingType( PermissionType permission) { ContentSettingsType content_setting = - PermissionTypeToContentSettingSafe(permission); + PermissionTypeToContentSettingTypeSafe(permission); DCHECK_NE(content_setting, ContentSettingsType::DEFAULT) << "Unknown content setting for permission " << static_cast<int>(permission); return content_setting; } +PermissionType PermissionUtil::ContentSettingTypeToPermissionType( + ContentSettingsType permission) { + switch (permission) { + case ContentSettingsType::GEOLOCATION: + return PermissionType::GEOLOCATION; + case ContentSettingsType::NOTIFICATIONS: + return PermissionType::NOTIFICATIONS; + case ContentSettingsType::MIDI: + return PermissionType::MIDI; + case ContentSettingsType::MIDI_SYSEX: + return PermissionType::MIDI_SYSEX; + case ContentSettingsType::DURABLE_STORAGE: + return PermissionType::DURABLE_STORAGE; + case ContentSettingsType::MEDIASTREAM_CAMERA: + return PermissionType::VIDEO_CAPTURE; + case ContentSettingsType::MEDIASTREAM_MIC: + return PermissionType::AUDIO_CAPTURE; + case ContentSettingsType::BACKGROUND_SYNC: + return PermissionType::BACKGROUND_SYNC; +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) + case ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER: + return PermissionType::PROTECTED_MEDIA_IDENTIFIER; +#endif + case ContentSettingsType::SENSORS: + return PermissionType::SENSORS; + case ContentSettingsType::ACCESSIBILITY_EVENTS: + return PermissionType::ACCESSIBILITY_EVENTS; + case ContentSettingsType::CLIPBOARD_READ_WRITE: + return PermissionType::CLIPBOARD_READ_WRITE; + case ContentSettingsType::PAYMENT_HANDLER: + return PermissionType::PAYMENT_HANDLER; + case ContentSettingsType::BACKGROUND_FETCH: + return PermissionType::BACKGROUND_FETCH; + case ContentSettingsType::PERIODIC_BACKGROUND_SYNC: + return PermissionType::PERIODIC_BACKGROUND_SYNC; + case ContentSettingsType::WAKE_LOCK_SCREEN: + return PermissionType::WAKE_LOCK_SCREEN; + case ContentSettingsType::WAKE_LOCK_SYSTEM: + return PermissionType::WAKE_LOCK_SYSTEM; + case ContentSettingsType::NFC: + return PermissionType::NFC; + case ContentSettingsType::VR: + return PermissionType::VR; + case ContentSettingsType::AR: + return PermissionType::AR; + case ContentSettingsType::STORAGE_ACCESS: + return PermissionType::STORAGE_ACCESS_GRANT; + case ContentSettingsType::CAMERA_PAN_TILT_ZOOM: + return PermissionType::CAMERA_PAN_TILT_ZOOM; + case ContentSettingsType::WINDOW_PLACEMENT: + return PermissionType::WINDOW_PLACEMENT; + case ContentSettingsType::LOCAL_FONTS: + return PermissionType::LOCAL_FONTS; + case ContentSettingsType::IDLE_DETECTION: + return PermissionType::IDLE_DETECTION; + case ContentSettingsType::DISPLAY_CAPTURE: + return PermissionType::DISPLAY_CAPTURE; + default: + NOTREACHED(); + return PermissionType::NUM; + } +} + ContentSetting PermissionUtil::PermissionStatusToContentSetting( blink::mojom::PermissionStatus status) { switch (status) { @@ -358,4 +458,83 @@ return CONTENT_SETTING_DEFAULT; } +blink::mojom::PermissionStatus PermissionUtil::ContentSettingToPermissionStatus( + ContentSetting setting) { + switch (setting) { + case CONTENT_SETTING_ALLOW: + return blink::mojom::PermissionStatus::GRANTED; + case CONTENT_SETTING_BLOCK: + return blink::mojom::PermissionStatus::DENIED; + case CONTENT_SETTING_ASK: + return blink::mojom::PermissionStatus::ASK; + case CONTENT_SETTING_SESSION_ONLY: + case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT: + case CONTENT_SETTING_DEFAULT: + case CONTENT_SETTING_NUM_SETTINGS: + break; + } + + NOTREACHED(); + return blink::mojom::PermissionStatus::DENIED; +} + +content::PermissionResult PermissionUtil::ToContentPermissionResult( + PermissionResult result) { + content::PermissionStatusSource source = + (content::PermissionStatusSource)result.source; + blink::mojom::PermissionStatus status = + ContentSettingToPermissionStatus(result.content_setting); + + return content::PermissionResult(status, source); +} + +PermissionResult PermissionUtil::ToPermissionResult( + content::PermissionResult result) { + PermissionStatusSource source = (PermissionStatusSource)result.source; + ContentSetting setting = PermissionStatusToContentSetting(result.status); + + return PermissionResult(setting, source); +} + +bool PermissionUtil::IsPermissionBlockedInPartition( + ContentSettingsType permission, + const GURL& requesting_origin, + content::RenderProcessHost* render_process_host) { + DCHECK(render_process_host); + switch (GetPermissionDelegationMode(permission)) { + case PermissionDelegationMode::kDelegated: + return false; + case PermissionDelegationMode::kDoubleKeyed: + return false; + case PermissionDelegationMode::kUndelegated: + // TODO(crbug.com/1312218): This will create |requesting_origin|'s home + // StoragePartition if it doesn't already exist. Given how + // StoragePartitions are used today, this shouldn't actually be a + // problem, but ideally we'd compare StoragePartitionConfigs. + content::StoragePartition* requesting_home_partition = + render_process_host->GetBrowserContext()->GetStoragePartitionForUrl( + requesting_origin); + return requesting_home_partition != + render_process_host->GetStoragePartition(); + } +} + +GURL PermissionUtil::GetCanonicalOrigin(ContentSettingsType permission, + const GURL& requesting_origin, + const GURL& embedding_origin) { + absl::optional<GURL> override_origin = + PermissionsClient::Get()->OverrideCanonicalOrigin(requesting_origin, + embedding_origin); + if (override_origin) + return override_origin.value(); + + switch (GetPermissionDelegationMode(permission)) { + case PermissionDelegationMode::kDelegated: + return embedding_origin; + case PermissionDelegationMode::kDoubleKeyed: + case PermissionDelegationMode::kUndelegated: + return requesting_origin; + } +} + } // namespace permissions
diff --git a/components/permissions/permission_util.h b/components/permissions/permission_util.h index 4a44362..c4f73498 100644 --- a/components/permissions/permission_util.h +++ b/components/permissions/permission_util.h
@@ -19,11 +19,14 @@ namespace content { class RenderFrameHost; +class RenderProcessHost; +struct PermissionResult; } // namespace content class GURL; namespace permissions { +struct PermissionResult; // This enum backs a UMA histogram, so it must be treated as append-only. enum class PermissionAction { @@ -79,19 +82,59 @@ static GURL GetLastCommittedOriginAsURL( content::RenderFrameHost* render_frame_host); - // Helper method to convert PermissionType to ContentSettingType. - // If PermissionType is not supported or found, returns + // Helper method to convert `PermissionType` to `ContentSettingType`. + // If `PermissionType` is not supported or found, returns // ContentSettingsType::DEFAULT. - static ContentSettingsType PermissionTypeToContentSettingSafe( + static ContentSettingsType PermissionTypeToContentSettingTypeSafe( blink::PermissionType permission); - // Helper method to convert PermissionType to ContentSettingType. - static ContentSettingsType PermissionTypeToContentSetting( + // Helper method to convert `PermissionType` to `ContentSettingType`. + static ContentSettingsType PermissionTypeToContentSettingType( blink::PermissionType permission); + // Helper method to convert `ContentSettingType` to `PermissionType`. + static blink::PermissionType ContentSettingTypeToPermissionType( + ContentSettingsType permission); + // Helper method to convert PermissionStatus to ContentSetting. static ContentSetting PermissionStatusToContentSetting( blink::mojom::PermissionStatus status); + + // Helper methods to convert ContentSetting to PermissionStatus and vice + // versa. + static blink::mojom::PermissionStatus ContentSettingToPermissionStatus( + ContentSetting setting); + + static content::PermissionResult ToContentPermissionResult( + PermissionResult result); + + static PermissionResult ToPermissionResult(content::PermissionResult result); + + // If an iframed document/worker inherits a different StoragePartition from + // its embedder than it would use if it were a main frame, we should block + // undelegated permissions. Because permissions are scoped to BrowserContext + // instead of StoragePartition, without this check the aforementioned iframe + // would be given undelegated permissions if the user had granted its origin + // access when it was loaded as a main frame. + static bool IsPermissionBlockedInPartition( + ContentSettingsType permission, + const GURL& requesting_origin, + content::RenderProcessHost* render_process_host); + + // Converts from |url|'s actual origin to the "canonical origin" that should + // be used for the purpose of requesting/storing permissions. For example, the + // origin of the local NTP gets mapped to the Google base URL instead. With + // Permission Delegation it will transform the requesting origin into + // the embedding origin because all permission checks happen on the top level + // origin. + // + // All the public methods below, such as RequestPermission or + // GetPermissionStatus, take the actual origin and do the canonicalization + // internally. You only need to call this directly if you do something else + // with the origin, such as display it in the UI. + static GURL GetCanonicalOrigin(ContentSettingsType permission, + const GURL& requesting_origin, + const GURL& embedding_origin); }; } // namespace permissions
diff --git a/components/permissions/permissions_client.cc b/components/permissions/permissions_client.cc index f7273857..24b10f0 100644 --- a/components/permissions/permissions_client.cc +++ b/components/permissions/permissions_client.cc
@@ -115,8 +115,8 @@ return absl::nullopt; } -bool PermissionsClient::DoOriginsMatchNewTabPage(const GURL& requesting_origin, - const GURL& embedding_origin) { +bool PermissionsClient::DoURLsMatchNewTabPage(const GURL& requesting_origin, + const GURL& embedding_origin) { return false; }
diff --git a/components/permissions/permissions_client.h b/components/permissions/permissions_client.h index 3cd33e2..d8d8792 100644 --- a/components/permissions/permissions_client.h +++ b/components/permissions/permissions_client.h
@@ -44,7 +44,6 @@ class ObjectPermissionContextBase; class PermissionActionsHistory; class PermissionDecisionAutoBlocker; -class PermissionManager; class PermissionPromptAndroid; // Interface to be implemented by permissions embedder to access embedder @@ -88,11 +87,6 @@ virtual PermissionDecisionAutoBlocker* GetPermissionDecisionAutoBlocker( content::BrowserContext* browser_context) = 0; - // Retrieves the PermissionManager for this context. The returned - // pointer has the same lifetime as |browser_context|. - virtual PermissionManager* GetPermissionManager( - content::BrowserContext* browser_context) = 0; - // Gets the ObjectPermissionContextBase for the given type and context, which // must be a // *_CHOOSER_DATA value. May return null if the context does not exist. @@ -196,8 +190,8 @@ // Checks if `requesting_origin` and `embedding_origin` are the new tab page // origins. - virtual bool DoOriginsMatchNewTabPage(const GURL& requesting_origin, - const GURL& embedding_origin); + virtual bool DoURLsMatchNewTabPage(const GURL& requesting_origin, + const GURL& embedding_origin); #if BUILDFLAG(IS_ANDROID) // Returns whether the given origin matches the default search engine (DSE)
diff --git a/components/permissions/test/test_permissions_client.cc b/components/permissions/test/test_permissions_client.cc index 03ba8f79f..024e8990 100644 --- a/components/permissions/test/test_permissions_client.cc +++ b/components/permissions/test/test_permissions_client.cc
@@ -61,11 +61,6 @@ return &autoblocker_; } -PermissionManager* TestPermissionsClient::GetPermissionManager( - content::BrowserContext* browser_context) { - return nullptr; -} - ObjectPermissionContextBase* TestPermissionsClient::GetChooserContext( content::BrowserContext* browser_context, ContentSettingsType type) {
diff --git a/components/permissions/test/test_permissions_client.h b/components/permissions/test/test_permissions_client.h index 88d8517..2ae0877a 100644 --- a/components/permissions/test/test_permissions_client.h +++ b/components/permissions/test/test_permissions_client.h
@@ -31,8 +31,6 @@ content::BrowserContext* browser_context) override; PermissionDecisionAutoBlocker* GetPermissionDecisionAutoBlocker( content::BrowserContext* browser_context) override; - PermissionManager* GetPermissionManager( - content::BrowserContext* browser_context) override; ObjectPermissionContextBase* GetChooserContext( content::BrowserContext* browser_context, ContentSettingsType type) override;
diff --git a/components/policy/core/common/policy_service_impl.cc b/components/policy/core/common/policy_service_impl.cc index 13ab61ce..83f04b9 100644 --- a/components/policy/core/common/policy_service_impl.cc +++ b/components/policy/core/common/policy_service_impl.cc
@@ -95,7 +95,7 @@ } bool IsUserCloudMergingAllowed(const PolicyMap& policies) { -#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_IOS) +#if BUILDFLAG(IS_CHROMEOS) return false; #else const base::Value* cloud_user_policy_merge_value =
diff --git a/components/policy/proto/chrome_device_policy.proto b/components/policy/proto/chrome_device_policy.proto index 9902d37..a8a01cf 100644 --- a/components/policy/proto/chrome_device_policy.proto +++ b/components/policy/proto/chrome_device_policy.proto
@@ -910,14 +910,16 @@ // every time a user authenticates via SAML during login. If false, cookies // are transferred during each user's first login only. optional bool transfer_saml_cookies = 1; +} +message SAMLUsernameProto { // If this policy is not configured or set to a blank string, users will have // to manually enter their username on SAML IdP page during online // authentication on the sign-in screen and the lock screen. // Otherwise, this string is expected to contain a url parameter name which - // should be used on IdP web page as $|autofill_saml_username|=[user's email] - // to autofill the username. - optional string url_parameter_to_autofill_saml_username = 2; + // should be used on IdP's login page with user's email as a value to autofill + // the username. + optional string url_parameter_to_autofill_saml_username = 1; } message RebootOnShutdownProto { @@ -1864,4 +1866,5 @@ optional BooleanPolicyProto device_run_automatic_cleanup_on_login = 133; optional EncryptedReportingPipelineConfigurationProto device_encrypted_reporting_pipeline_enabled = 134; + optional SAMLUsernameProto saml_username = 135; }
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index c06185b7..ecb21b21 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -10564,7 +10564,7 @@ 'type': 'main', 'schema': { 'type': 'boolean' }, 'supported_on': ['chrome.*:92-', 'android:97-'], - 'future_on': ['fuchsia'], + 'future_on': ['fuchsia', 'ios'], 'features': { 'dynamic_refresh': True, 'per_profile': True, @@ -33060,7 +33060,7 @@ 'DeviceKeylockerForStorageEncryptionEnabled': 'keylocker_for_storage_encryption_enabled.enabled', 'DeviceRunAutomaticCleanupOnLogin': 'device_run_automatic_cleanup_on_login.value', 'DeviceEncryptedReportingPipelineEnabled': 'device_reporting.encrypted_reporting_pipeline_enabled', - 'DeviceAutofillSAMLUsername': 'saml_settings.url_parameter_to_autofill_saml_username' + 'DeviceAutofillSAMLUsername': 'saml_username.url_parameter_to_autofill_saml_username' }, 'policy_atomic_group_definitions': [ {
diff --git a/components/power_bookmarks/core/power_bookmark_service.cc b/components/power_bookmarks/core/power_bookmark_service.cc index 7b9b35a..3b733b5 100644 --- a/components/power_bookmarks/core/power_bookmark_service.cc +++ b/components/power_bookmarks/core/power_bookmark_service.cc
@@ -4,6 +4,8 @@ #include "components/power_bookmarks/core/power_bookmark_service.h" +#include <algorithm> + namespace power_bookmarks { PowerBookmarkService::PowerBookmarkService() = default;
diff --git a/components/resources/protobufs/OWNERS b/components/resources/protobufs/OWNERS index f93bbac4..11e138a1 100644 --- a/components/resources/protobufs/OWNERS +++ b/components/resources/protobufs/OWNERS
@@ -1,4 +1,3 @@ -drubery@chromium.org +file://components/safe_browsing/OWNERS + meacer@chromium.org -nparker@chromium.org -vakh@chromium.org
diff --git a/components/safe_browsing/README.md b/components/safe_browsing/README.md index 844bfdf..94e96ef 100644 --- a/components/safe_browsing/README.md +++ b/components/safe_browsing/README.md
@@ -7,8 +7,7 @@ * core/: shared code that does not depend on either {src/content, src/ios} or {./content, ./ios} * browser/: Browser process code - * common/: Code shared by the browser and the renderer (on platforms other than - iOS) + * common/: Code shared by the browser and the renderer * content/: non-iOS code layered above core/ that integrates with the Content API * browser/: Browser process code * common/: Code shared by the browser and the renderer
diff --git a/components/sync/protocol/autofill_wallet_usage_specifics.proto b/components/sync/protocol/autofill_wallet_usage_specifics.proto index 66ab481d..d705567 100644 --- a/components/sync/protocol/autofill_wallet_usage_specifics.proto +++ b/components/sync/protocol/autofill_wallet_usage_specifics.proto
@@ -30,7 +30,7 @@ // specific Autofill wallet data model. These timestamps are collected when a // user selects an option in a Autofill suggestion dropdown and the client // records the time. - repeated int64 retrieval_time_unix_epoch_micros = 3; + repeated int64 retrieval_time_unix_epoch_micros = 3 [packed = true]; message VirtualCardUsageData { // The instrument id of the actual card that the virtual card is related to.
diff --git a/components/viz/common/quads/render_pass_io.cc b/components/viz/common/quads/render_pass_io.cc index 8cd18e09..f8388592 100644 --- a/components/viz/common/quads/render_pass_io.cc +++ b/components/viz/common/quads/render_pass_io.cc
@@ -385,8 +385,8 @@ base::Value::List steps; for (size_t i = 0; i < gradient_mask.step_count(); ++i) { base::Value::Dict step_dict; - step_dict.Set("percent", - static_cast<double>(gradient_mask.steps()[i].percent)); + step_dict.Set("fraction", + static_cast<double>(gradient_mask.steps()[i].fraction)); step_dict.Set("alpha", static_cast<int>(gradient_mask.steps()[i].alpha)); steps.Append(std::move(step_dict)); } @@ -411,12 +411,12 @@ if (!step) return false; - absl::optional<double> percent = step->FindDouble("percent"); + absl::optional<double> fraction = step->FindDouble("fraction"); absl::optional<int> alpha = step->FindInt("alpha"); - if (!percent || !alpha) + if (!fraction || !alpha) return false; - gradient_mask.AddStep(*percent, *alpha); + gradient_mask.AddStep(*fraction, *alpha); } *out = gradient_mask;
diff --git a/components/viz/common/quads/render_pass_io_unittest.cc b/components/viz/common/quads/render_pass_io_unittest.cc index 1f7e8b8a..340b6eca 100644 --- a/components/viz/common/quads/render_pass_io_unittest.cc +++ b/components/viz/common/quads/render_pass_io_unittest.cc
@@ -127,7 +127,7 @@ transform.MakeIdentity(); gfx::LinearGradient gradient_mask(40); gradient_mask.AddStep(/*percent=*/0, /*alpha=*/0); - gradient_mask.AddStep(100, 255); + gradient_mask.AddStep(1, 255); sqs1->SetAll( transform, gfx::Rect(0, 0, 640, 480), gfx::Rect(10, 10, 600, 400), gfx::MaskFilterInfo(gfx::RRectF(gfx::RectF(2.f, 3.f, 4.f, 5.f), 1.5f), @@ -173,7 +173,7 @@ EXPECT_EQ(2u, sqs1->mask_filter_info.gradient_mask()->step_count()); EXPECT_EQ(gfx::LinearGradient::Step({0, 0}), sqs1->mask_filter_info.gradient_mask()->steps()[0]); - EXPECT_EQ(gfx::LinearGradient::Step({100, 255}), + EXPECT_EQ(gfx::LinearGradient::Step({1, 255}), sqs1->mask_filter_info.gradient_mask()->steps()[1]); EXPECT_EQ(gfx::RectF(2.f, 3.f, 4.f, 5.f), sqs1->mask_filter_info.bounds()); EXPECT_EQ(gfx::Rect(5, 20, 1000, 200), sqs1->clip_rect);
diff --git a/components/viz/common/resources/resource_format_utils.cc b/components/viz/common/resources/resource_format_utils.cc index f31da5e..0962122 100644 --- a/components/viz/common/resources/resource_format_utils.cc +++ b/components/viz/common/resources/resource_format_utils.cc
@@ -542,7 +542,6 @@ bool GLSupportsFormat(ResourceFormat format) { switch (format) { case BGR_565: - case BGRX_8888: case YVU_420: case YUV_420_BIPLANAR: case P010:
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc index 4a3aea7c..51d9222 100644 --- a/components/viz/service/display/renderer_pixeltest.cc +++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -4579,8 +4579,8 @@ gfx::RRectF rounded_corner_bounds(gfx::RectF(pass_rect), kCornerRadius); gfx::LinearGradient gradient_mask(330); gradient_mask.AddStep(/*percent=*/0, /*alpha=*/0); - gradient_mask.AddStep(50, 255); - gradient_mask.AddStep(100, 255); + gradient_mask.AddStep(.5, 255); + gradient_mask.AddStep(1, 255); SharedQuadState* pass_shared_state = CreateTestSharedQuadState( gfx::Transform(), pass_rect, root_pass.get(), gfx::MaskFilterInfo(rounded_corner_bounds, gradient_mask)); @@ -4626,7 +4626,7 @@ blue_rrect.Offset(blue_offset_from_target); gfx::LinearGradient blue_gradient(0); blue_gradient.AddStep(/*percent=*/0, /*alpha=*/255); - blue_gradient.AddStep(100, 0); + blue_gradient.AddStep(1, 0); gfx::Transform quad_to_target_transform; quad_to_target_transform.Translate(blue_offset_from_target); @@ -4648,8 +4648,8 @@ gfx::RRectF rounded_corner_bounds(gfx::RectF(pass_rect), kCornerRadius); gfx::LinearGradient gradient_mask(-30); gradient_mask.AddStep(/*percent=*/0, /*alpha=*/0); - gradient_mask.AddStep(50, 255); - gradient_mask.AddStep(100, 255); + gradient_mask.AddStep(.5, 255); + gradient_mask.AddStep(1, 255); SharedQuadState* pass_shared_state = CreateTestSharedQuadState( gfx::Transform(), pass_rect, root_pass.get(), gfx::MaskFilterInfo(rounded_corner_bounds, gradient_mask));
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index 02ae6e938..01ed5054 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -1292,7 +1292,7 @@ size_t i = 0; for (; i < gradient_mask->step_count(); ++i) { - positions[i] = gradient_mask->steps()[i].percent / 100.f; + positions[i] = gradient_mask->steps()[i].fraction; gradient_colors[i] = MaskColor(gradient_mask->steps()[i].alpha); }
diff --git a/components/viz/test/test_gpu_memory_buffer_manager.cc b/components/viz/test/test_gpu_memory_buffer_manager.cc index 20626b7..ce49bce 100644 --- a/components/viz/test/test_gpu_memory_buffer_manager.cc +++ b/components/viz/test/test_gpu_memory_buffer_manager.cc
@@ -75,7 +75,7 @@ handle.type = gfx::SHARED_MEMORY_BUFFER; handle.region = region_.Duplicate(); handle.offset = base::checked_cast<uint32_t>(offset_); - handle.stride = base::checked_cast<int32_t>(stride_); + handle.stride = base::checked_cast<uint32_t>(stride_); return handle; } void OnMemoryDump(
diff --git a/components/viz/test/test_image_factory.cc b/components/viz/test/test_image_factory.cc index 663dd18..8302da7a 100644 --- a/components/viz/test/test_image_factory.cc +++ b/components/viz/test/test_image_factory.cc
@@ -26,7 +26,7 @@ DCHECK_EQ(handle.type, gfx::SHARED_MEMORY_BUFFER); auto image = base::MakeRefCounted<gl::GLImageSharedMemory>(size); if (!image->Initialize(handle.region, handle.id, format, handle.offset, - base::checked_cast<size_t>(handle.stride))) + handle.stride)) return nullptr; return image;
diff --git a/components/webapps/browser/installable/installable_manager.cc b/components/webapps/browser/installable/installable_manager.cc index c85ce7a..8af8c3d6 100644 --- a/components/webapps/browser/installable/installable_manager.cc +++ b/components/webapps/browser/installable/installable_manager.cc
@@ -922,12 +922,14 @@ ? kMinimumScreenshotSizeInPx : std::max(url->image.sizes[0].width(), url->image.sizes[0].height()); - // Passing in kMaximumScreenshotSizeInPx ensures that screenshots above that - // size are filtered out by the blink image_downloader implementation. - // Thus, we no longer need them to be resized in OnScreenshotFetched(). + // Do not pass in a maximum icon size so that screenshots larger than + // kMaximumScreenshotSizeInPx are not downscaled to the maximum size by + // `ManifestIconDownloader::Download`. Screenshots with size larger than + // kMaximumScreenshotSizeInPx get filtered out by OnScreenshotFetched. bool can_download = content::ManifestIconDownloader::Download( GetWebContents(), url->image.src, ideal_size_in_px, - kMinimumScreenshotSizeInPx, kMaximumScreenshotSizeInPx, + kMinimumScreenshotSizeInPx, + /*maximum_icon_size_in_px=*/0, base::BindOnce(&InstallableManager::OnScreenshotFetched, weak_factory_.GetWeakPtr(), url->image.src), /*square_only=*/false); @@ -969,7 +971,12 @@ auto iter = downloaded_screenshots_.find(url->image.src); if (iter == downloaded_screenshots_.end()) continue; + auto screenshot = iter->second; + if (screenshot.dimensions().width() > kMaximumScreenshotSizeInPx || + screenshot.dimensions().height() > kMaximumScreenshotSizeInPx) { + continue; + } // Screenshots must have the same aspect ratio. Cross-multiplying // dimensions checks portrait vs landscape mode (1:2 vs 2:1 for instance).
diff --git a/components/webrtc/media_stream_devices_controller.cc b/components/webrtc/media_stream_devices_controller.cc index 13bbeaa..71eb2ed 100644 --- a/components/webrtc/media_stream_devices_controller.cc +++ b/components/webrtc/media_stream_devices_controller.cc
@@ -10,11 +10,10 @@ #include "base/bind.h" #include "build/build_config.h" -#include "components/permissions/permission_manager.h" -#include "components/permissions/permission_result.h" -#include "components/permissions/permissions_client.h" +#include "components/permissions/permission_util.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_widget_host_view.h" @@ -36,15 +35,15 @@ namespace { -// Returns true if the given ContentSettingsType is being requested in +// Returns true if the given PermissionType is being requested in // |request|. -bool ContentTypeIsRequested(ContentSettingsType type, - const content::MediaStreamRequest& request) { - if (type == ContentSettingsType::MEDIASTREAM_MIC) +bool PermissionIsRequested(blink::PermissionType permission, + const content::MediaStreamRequest& request) { + if (permission == blink::PermissionType::AUDIO_CAPTURE) return request.audio_type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE; - if (type == ContentSettingsType::MEDIASTREAM_CAMERA) + if (permission == blink::PermissionType::VIDEO_CAPTURE) return request.video_type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE; @@ -93,42 +92,39 @@ std::vector<blink::PermissionType> permission_types; - permissions::PermissionManager* permission_manager = - permissions::PermissionsClient::Get()->GetPermissionManager( - web_contents->GetBrowserContext()); + content::PermissionController* permission_controller = + web_contents->GetBrowserContext()->GetPermissionController(); if (controller->ShouldRequestAudio()) { - permissions::PermissionResult permission_status = - permission_manager->GetPermissionStatusForCurrentDocument( - ContentSettingsType::MEDIASTREAM_MIC, rfh); - if (permission_status.content_setting == CONTENT_SETTING_BLOCK) { + content::PermissionResult permission_status = + permission_controller->GetPermissionResultForCurrentDocument( + blink::PermissionType::AUDIO_CAPTURE, rfh); + if (permission_status.status == blink::mojom::PermissionStatus::DENIED) { controller->denial_reason_ = blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED; - controller->RunCallback( - permission_status.source == - permissions::PermissionStatusSource::FEATURE_POLICY); + controller->RunCallback(permission_status.source == + content::PermissionStatusSource::FEATURE_POLICY); return; } permission_types.push_back(blink::PermissionType::AUDIO_CAPTURE); } if (controller->ShouldRequestVideo()) { - permissions::PermissionResult permission_status = - permission_manager->GetPermissionStatusForCurrentDocument( - ContentSettingsType::MEDIASTREAM_CAMERA, rfh); - if (permission_status.content_setting == CONTENT_SETTING_BLOCK) { + content::PermissionResult permission_status = + permission_controller->GetPermissionResultForCurrentDocument( + blink::PermissionType::VIDEO_CAPTURE, rfh); + if (permission_status.status == blink::mojom::PermissionStatus::DENIED) { controller->denial_reason_ = blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED; - controller->RunCallback( - permission_status.source == - permissions::PermissionStatusSource::FEATURE_POLICY); + controller->RunCallback(permission_status.source == + content::PermissionStatusSource::FEATURE_POLICY); return; } permission_types.push_back(blink::PermissionType::VIDEO_CAPTURE); bool has_pan_tilt_zoom_camera = controller->HasAvailableDevices( - ContentSettingsType::CAMERA_PAN_TILT_ZOOM, + blink::PermissionType::CAMERA_PAN_TILT_ZOOM, request.requested_video_device_id); // Request CAMERA_PAN_TILT_ZOOM only if the website requested the @@ -136,9 +132,9 @@ // available. if (request.request_pan_tilt_zoom_permission && has_pan_tilt_zoom_camera) { permission_status = - permission_manager->GetPermissionStatusForCurrentDocument( - ContentSettingsType::CAMERA_PAN_TILT_ZOOM, rfh); - if (permission_status.content_setting == CONTENT_SETTING_BLOCK) { + permission_controller->GetPermissionResultForCurrentDocument( + blink::PermissionType::CAMERA_PAN_TILT_ZOOM, rfh); + if (permission_status.status == blink::mojom::PermissionStatus::DENIED) { controller->denial_reason_ = blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED; controller->RunCallback(/*blocked_by_permissions_policy=*/false); @@ -188,9 +184,9 @@ enumerator_ = &owned_enumerator_; denial_reason_ = blink::mojom::MediaStreamRequestResult::OK; - audio_setting_ = GetContentSetting(ContentSettingsType::MEDIASTREAM_MIC, + audio_setting_ = GetContentSetting(blink::PermissionType::AUDIO_CAPTURE, request, &denial_reason_); - video_setting_ = GetContentSetting(ContentSettingsType::MEDIASTREAM_CAMERA, + video_setting_ = GetContentSetting(blink::PermissionType::VIDEO_CAPTURE, request, &denial_reason_); } @@ -342,37 +338,37 @@ } ContentSetting MediaStreamDevicesController::GetContentSetting( - ContentSettingsType content_type, + blink::PermissionType permission, const content::MediaStreamRequest& request, blink::mojom::MediaStreamRequestResult* denial_reason) const { - DCHECK(content_type == ContentSettingsType::MEDIASTREAM_MIC || - content_type == ContentSettingsType::MEDIASTREAM_CAMERA); + DCHECK(permission == blink::PermissionType::AUDIO_CAPTURE || + permission == blink::PermissionType::VIDEO_CAPTURE); DCHECK(!request_.security_origin.is_empty()); DCHECK(network::IsUrlPotentiallyTrustworthy(request_.security_origin) || request_.request_type == blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY); - if (!ContentTypeIsRequested(content_type, request)) { + if (!PermissionIsRequested(permission, request)) { // No denial reason set as it will have been previously set. return CONTENT_SETTING_DEFAULT; } std::string device_id; - if (content_type == ContentSettingsType::MEDIASTREAM_MIC) + if (permission == blink::PermissionType::AUDIO_CAPTURE) device_id = request.requested_audio_device_id; else device_id = request.requested_video_device_id; - if (!HasAvailableDevices(content_type, device_id)) { + if (!HasAvailableDevices(permission, device_id)) { *denial_reason = blink::mojom::MediaStreamRequestResult::NO_HARDWARE; return CONTENT_SETTING_BLOCK; } - if (!IsUserAcceptAllowed(content_type)) { + if (!IsUserAcceptAllowed(permission)) { *denial_reason = blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED; return CONTENT_SETTING_BLOCK; } // Don't request if the kill switch is on. if (PermissionIsBlockedForReason( - content_type, permissions::PermissionStatusSource::KILL_SWITCH)) { + permission, content::PermissionStatusSource::KILL_SWITCH)) { *denial_reason = blink::mojom::MediaStreamRequestResult::KILL_SWITCH_ON; return CONTENT_SETTING_BLOCK; } @@ -381,13 +377,27 @@ } bool MediaStreamDevicesController::IsUserAcceptAllowed( - ContentSettingsType content_type) const { + blink::PermissionType permission) const { #if BUILDFLAG(IS_ANDROID) ui::WindowAndroid* window_android = web_contents_->GetNativeView()->GetWindowAndroid(); if (!window_android) return false; + ContentSettingsType content_type; + + switch (permission) { + case blink::PermissionType::AUDIO_CAPTURE: + content_type = ContentSettingsType::MEDIASTREAM_MIC; + break; + case blink::PermissionType::VIDEO_CAPTURE: + content_type = ContentSettingsType::MEDIASTREAM_CAMERA; + break; + default: + NOTREACHED(); + return false; + } + std::vector<std::string> required_android_permissions; permissions::AppendRequiredAndroidPermissionsForContentSetting( content_type, &required_android_permissions); @@ -408,21 +418,22 @@ } bool MediaStreamDevicesController::PermissionIsBlockedForReason( - ContentSettingsType content_type, - permissions::PermissionStatusSource reason) const { - // TODO(raymes): This function wouldn't be needed if - // PermissionManager::RequestPermissions returned a denial reason. + blink::PermissionType permission, + content::PermissionStatusSource reason) const { content::RenderFrameHost* rfh = content::RenderFrameHost::FromID( request_.render_process_id, request_.render_frame_id); if (rfh->GetLastCommittedOrigin().GetURL() != request_.security_origin) { return false; } - permissions::PermissionResult result = - permissions::PermissionsClient::Get() - ->GetPermissionManager(web_contents_->GetBrowserContext()) - ->GetPermissionStatusForCurrentDocument(content_type, rfh); + + // TODO(raymes): This function wouldn't be needed if + // PermissionManager::RequestPermissions returned a denial reason. + content::PermissionResult result = + web_contents_->GetBrowserContext() + ->GetPermissionController() + ->GetPermissionResultForCurrentDocument(permission, rfh); if (result.source == reason) { - DCHECK_EQ(CONTENT_SETTING_BLOCK, result.content_setting); + DCHECK_EQ(blink::mojom::PermissionStatus::DENIED, result.status); return true; } return false; @@ -452,8 +463,8 @@ blocked_by_permissions_policy &= audio_setting_ == CONTENT_SETTING_BLOCK && PermissionIsBlockedForReason( - ContentSettingsType::MEDIASTREAM_MIC, - permissions::PermissionStatusSource::FEATURE_POLICY); + blink::PermissionType::AUDIO_CAPTURE, + content::PermissionStatusSource::FEATURE_POLICY); } if (need_video) { @@ -461,8 +472,8 @@ blocked_by_permissions_policy &= video_setting_ == CONTENT_SETTING_BLOCK && PermissionIsBlockedForReason( - ContentSettingsType::MEDIASTREAM_CAMERA, - permissions::PermissionStatusSource::FEATURE_POLICY); + blink::PermissionType::VIDEO_CAPTURE, + content::PermissionStatusSource::FEATURE_POLICY); } for (ContentSetting response : responses) { @@ -478,13 +489,13 @@ } bool MediaStreamDevicesController::HasAvailableDevices( - ContentSettingsType content_type, + blink::PermissionType permission, const std::string& device_id) const { const MediaStreamDevices* devices = nullptr; - if (content_type == ContentSettingsType::MEDIASTREAM_MIC) { + if (permission == blink::PermissionType::AUDIO_CAPTURE) { devices = &enumerator_->GetAudioCaptureDevices(); - } else if (content_type == ContentSettingsType::MEDIASTREAM_CAMERA || - content_type == ContentSettingsType::CAMERA_PAN_TILT_ZOOM) { + } else if (permission == blink::PermissionType::VIDEO_CAPTURE || + permission == blink::PermissionType::CAMERA_PAN_TILT_ZOOM) { devices = &enumerator_->GetVideoCaptureDevices(); } else { NOTREACHED(); @@ -500,7 +511,7 @@ // If there are no particular device requirements, all devices will do. if (device_id.empty() && - content_type != ContentSettingsType::CAMERA_PAN_TILT_ZOOM) { + permission != blink::PermissionType::CAMERA_PAN_TILT_ZOOM) { return true; } @@ -509,7 +520,7 @@ if (!device_id.empty() && device.id != device_id) { continue; } - if (content_type == ContentSettingsType::CAMERA_PAN_TILT_ZOOM && + if (permission == blink::PermissionType::CAMERA_PAN_TILT_ZOOM && !device.video_control_support.pan && !device.video_control_support.tilt && !device.video_control_support.zoom) {
diff --git a/components/webrtc/media_stream_devices_controller.h b/components/webrtc/media_stream_devices_controller.h index 1787b41..da70bfb 100644 --- a/components/webrtc/media_stream_devices_controller.h +++ b/components/webrtc/media_stream_devices_controller.h
@@ -18,11 +18,12 @@ #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" -namespace permissions { -enum class PermissionStatusSource; +namespace blink { +enum class PermissionType; } namespace content { +enum class PermissionStatusSource; class WebContents; } @@ -81,25 +82,25 @@ // Runs |callback_| with the current audio/video permission settings. void RunCallback(bool blocked_by_permissions_policy); - // Returns the content settings for the given content type and request. + // Returns the content settings for the given permission type and request. ContentSetting GetContentSetting( - ContentSettingsType content_type, + blink::PermissionType permission, const content::MediaStreamRequest& request, blink::mojom::MediaStreamRequestResult* denial_reason) const; // Returns true if clicking allow on the dialog should give access to the // requested devices. - bool IsUserAcceptAllowed(ContentSettingsType content_type) const; + bool IsUserAcceptAllowed(blink::PermissionType permission) const; bool PermissionIsBlockedForReason( - ContentSettingsType content_type, - permissions::PermissionStatusSource reason) const; + blink::PermissionType permission, + content::PermissionStatusSource reason) const; // Called when a permission prompt is answered through the PermissionManager. void PromptAnsweredGroupedRequest( const std::vector<blink::mojom::PermissionStatus>& permissions_status); - bool HasAvailableDevices(ContentSettingsType content_type, + bool HasAvailableDevices(blink::PermissionType permission, const std::string& device_id) const; // The current state of the audio/video content settings which may be updated
diff --git a/content/browser/accessibility/accessibility_ipc_error_browsertest.cc b/content/browser/accessibility/accessibility_ipc_error_browsertest.cc index 63d8a4a..6e78961 100644 --- a/content/browser/accessibility/accessibility_ipc_error_browsertest.cc +++ b/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
@@ -14,6 +14,7 @@ #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" #include "content/shell/browser/shell.h" +#include "ui/accessibility/ax_common.h" #include "ui/accessibility/ax_node.h" #include "ui/accessibility/ax_tree.h" @@ -42,7 +43,9 @@ }; // Failed on Android x86 in crbug.com/1123641. -#if BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_X86) +// Do not test on AX_FAIL_FAST_BUILDS, where the BAD IPC will simply assert. +#if (BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_X86)) || \ + defined(AX_FAIL_FAST_BUILD) #define MAYBE_ResetBrowserAccessibilityManager \ DISABLED_ResetBrowserAccessibilityManager #else @@ -142,7 +145,8 @@ EXPECT_EQ(ax::mojom::Role::kButton, button->GetRole()); } -#if BUILDFLAG(IS_LINUX) +// Do not test on AX_FAIL_FAST_BUILDS, where the BAD IPC will simply assert. +#if BUILDFLAG(IS_LINUX) && !defined(AX_FAIL_FAST_BUILD) #define MAYBE_MultipleBadAccessibilityIPCsKillsRenderer \ MultipleBadAccessibilityIPCsKillsRenderer #else
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc index f8cac33..d2d270c 100644 --- a/content/browser/accessibility/browser_accessibility_manager.cc +++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -13,7 +13,6 @@ #include "base/auto_reset.h" #include "base/containers/adapters.h" -#include "base/debug/crash_logging.h" #include "base/logging.h" #include "base/metrics/user_metrics.h" #include "base/no_destructor.h" @@ -229,32 +228,12 @@ ParentConnectionChanged(parent); } -bool BrowserAccessibilityManager::Unserialize( - const ui::AXTreeUpdate& tree_update) { - if (ax_tree()->Unserialize(tree_update)) - return true; - - LOG(ERROR) << ax_tree()->error(); - LOG(ERROR) << tree_update.ToString(); - - static auto* const ax_tree_error = base::debug::AllocateCrashKeyString( - "ax_tree_error", base::debug::CrashKeySize::Size256); - static auto* const ax_tree_update = base::debug::AllocateCrashKeyString( - "ax_tree_update", base::debug::CrashKeySize::Size256); - // Temporarily log some additional crash keys so we can try to - // figure out why we're getting bad accessibility trees here. - // http://crbug.com/765490, https://crbug.com/1094848. - // Be sure to re-enable BrowserAccessibilityManagerTest.TestFatalError - // when done (or delete it if no longer needed). - base::debug::SetCrashKeyString(ax_tree_error, ax_tree()->error()); - base::debug::SetCrashKeyString(ax_tree_update, tree_update.ToString()); - return false; -} - void BrowserAccessibilityManager::Initialize( const ui::AXTreeUpdate& initial_tree) { - if (!Unserialize(initial_tree)) - LOG(FATAL) << ax_tree()->error(); + if (!ax_tree()->Unserialize(initial_tree)) { + LOG(FATAL) << "No recovery is possible if the initial tree is broken: " + << ax_tree()->error(); + } } // A flag for use in tests to ensure events aren't suppressed or delayed. @@ -552,7 +531,7 @@ // Process all changes to the accessibility tree first. for (const ui::AXTreeUpdate& tree_update : *tree_updates) { - if (!Unserialize(tree_update)) { + if (!ax_tree()->Unserialize(tree_update)) { // This is a fatal error, but if there is a delegate, it will handle the // error result and recover by re-creating the manager. After a max // threshold number of errors is reached, it will crash the browser.
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h index 6e4bed1..bc6e77f 100644 --- a/content/browser/accessibility/browser_accessibility_manager.h +++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -324,8 +324,7 @@ // Called when the renderer process has notified us of tree changes. Returns // false in fatal-error conditions, in which case the caller should destroy // the manager. - [[nodiscard]] virtual bool OnAccessibilityEvents( - const AXEventNotificationDetails& details); + virtual bool OnAccessibilityEvents(const AXEventNotificationDetails& details); // Allows derived classes to do event pre-processing virtual void BeforeAccessibilityEvents(); @@ -684,10 +683,6 @@ #endif // DCHECK_IS_ON() private: - // Helper that calls AXTree::Unserialize(). On failure it populates crash data - // with error information. - bool Unserialize(const ui::AXTreeUpdate& tree_update); - void BuildAXTreeHitTestCacheInternal( const BrowserAccessibility* node, std::vector<const BrowserAccessibility*>* storage);
diff --git a/content/browser/accessibility/browser_accessibility_manager_unittest.cc b/content/browser/accessibility/browser_accessibility_manager_unittest.cc index 5cbc46a..aa408d5 100644 --- a/content/browser/accessibility/browser_accessibility_manager_unittest.cc +++ b/content/browser/accessibility/browser_accessibility_manager_unittest.cc
@@ -80,8 +80,7 @@ std::make_unique<TestBrowserAccessibilityDelegate>(); } -// Temporarily disabled due to bug http://crbug.com/765490 -TEST_F(BrowserAccessibilityManagerTest, DISABLED_TestFatalError) { +TEST_F(BrowserAccessibilityManagerTest, TestErrorOnCreateIsFatal) { // Test that BrowserAccessibilityManager raises a fatal error // (which will crash the renderer) if the same id is used in // two places in the tree. @@ -93,42 +92,52 @@ root.child_ids.push_back(2); std::unique_ptr<BrowserAccessibilityManager> manager; - ASSERT_FALSE(test_browser_accessibility_delegate_->got_fatal_error()); - manager.reset(BrowserAccessibilityManager::Create( - MakeAXTreeUpdate(root), test_browser_accessibility_delegate_.get())); - ASSERT_TRUE(test_browser_accessibility_delegate_->got_fatal_error()); + EXPECT_DEATH_IF_SUPPORTED( + manager.reset(BrowserAccessibilityManager::Create( + MakeAXTreeUpdate(root), test_browser_accessibility_delegate_.get())), + "Node 1 has duplicate child id 2"); +} - ui::AXNodeData root2; - root2.id = 1; - root2.role = ax::mojom::Role::kRootWebArea; - root2.child_ids.push_back(2); - root2.child_ids.push_back(3); +TEST_F(BrowserAccessibilityManagerTest, TestErrorOnUpdate) { + ui::AXNodeData root; + root.id = 1; + root.role = ax::mojom::Role::kRootWebArea; - ui::AXNodeData child1; - child1.id = 2; - child1.child_ids.push_back(4); - child1.child_ids.push_back(5); + ui::AXNodeData node2; + node2.id = 2; + root.child_ids.push_back(2); - ui::AXNodeData child2; - child2.id = 3; - child2.child_ids.push_back(6); - child2.child_ids.push_back(5); // Duplicate + ui::AXNodeData node3; + node3.id = 3; + root.child_ids.push_back(3); - ui::AXNodeData grandchild4; - grandchild4.id = 4; + ui::AXNodeData node4; + node4.id = 4; + node3.child_ids.push_back(4); - ui::AXNodeData grandchild5; - grandchild5.id = 5; + ui::AXNodeData node5; + node5.id = 5; + root.child_ids.push_back(5); - ui::AXNodeData grandchild6; - grandchild6.id = 6; + std::unique_ptr<BrowserAccessibilityManager> manager( + BrowserAccessibilityManager::Create( + MakeAXTreeUpdate(root, node2, node3, node4, node5), + test_browser_accessibility_delegate_.get())); - test_browser_accessibility_delegate_->reset_got_fatal_error(); - manager.reset(BrowserAccessibilityManager::Create( - MakeAXTreeUpdate(root2, child1, child2, grandchild4, grandchild5, - grandchild6), - test_browser_accessibility_delegate_.get())); - ASSERT_TRUE(test_browser_accessibility_delegate_->got_fatal_error()); + // node4 has two child ids now. + node4.child_ids.push_back(5); + node4.child_ids.push_back(5); + ui::AXTreeUpdate update = MakeAXTreeUpdate(node4, node5); + AXEventNotificationDetails events; + events.updates = {update}; + +#if defined(AX_FAIL_FAST_BUILD) + // Update errors are fatal in AX_FAIL_FAST_BUILD builds. + EXPECT_DEATH_IF_SUPPORTED(manager->OnAccessibilityEvents(events), + "Node 4 has duplicate child id 5"); +#else + ASSERT_FALSE(manager->OnAccessibilityEvents(events)); +#endif } // This test depends on hypertext, which is only used on
diff --git a/content/browser/accessibility/test_browser_accessibility_delegate.cc b/content/browser/accessibility/test_browser_accessibility_delegate.cc index 6c8b894..583993c 100644 --- a/content/browser/accessibility/test_browser_accessibility_delegate.cc +++ b/content/browser/accessibility/test_browser_accessibility_delegate.cc
@@ -7,9 +7,7 @@ namespace content { TestBrowserAccessibilityDelegate::TestBrowserAccessibilityDelegate() - : is_root_frame_(true), - accelerated_widget_(gfx::kNullAcceleratedWidget), - got_fatal_error_(false) {} + : is_root_frame_(true), accelerated_widget_(gfx::kNullAcceleratedWidget) {} void TestBrowserAccessibilityDelegate::AccessibilityPerformAction( const ui::AXActionData& data) {} @@ -28,9 +26,7 @@ return 1.0f; } -void TestBrowserAccessibilityDelegate::AccessibilityFatalError() { - got_fatal_error_ = true; -} +void TestBrowserAccessibilityDelegate::AccessibilityFatalError() {} gfx::AcceleratedWidget TestBrowserAccessibilityDelegate::AccessibilityGetAcceleratedWidget() { @@ -68,12 +64,4 @@ return nullptr; } -bool TestBrowserAccessibilityDelegate::got_fatal_error() const { - return got_fatal_error_; -} - -void TestBrowserAccessibilityDelegate::reset_got_fatal_error() { - got_fatal_error_ = false; -} - } // namespace content
diff --git a/content/browser/accessibility/test_browser_accessibility_delegate.h b/content/browser/accessibility/test_browser_accessibility_delegate.h index a63cc452..1b7c189 100644 --- a/content/browser/accessibility/test_browser_accessibility_delegate.h +++ b/content/browser/accessibility/test_browser_accessibility_delegate.h
@@ -33,14 +33,8 @@ int hit_node_id)> opt_callback) override; WebContentsAccessibility* AccessibilityGetWebContentsAccessibility() override; - bool got_fatal_error() const; - void reset_got_fatal_error(); - bool is_root_frame_; gfx::AcceleratedWidget accelerated_widget_; - - private: - bool got_fatal_error_; }; } // namespace content
diff --git a/content/browser/android/content_feature_list.cc b/content/browser/android/content_feature_list.cc index d2531979b..9a53afd 100644 --- a/content/browser/android/content_feature_list.cc +++ b/content/browser/android/content_feature_list.cc
@@ -30,6 +30,7 @@ &features::kFedCm, &features::kOnDemandAccessibilityEvents, &features::kProcessSharingWithStrictSiteInstances, + &features::kReduceGpuPriorityOnBackground, &features::kRequestDesktopSiteAdditions, &features::kRequestDesktopSiteExceptions, &features::kTouchDragAndContextMenu,
diff --git a/content/browser/attribution_reporting/attribution_src_browsertest.cc b/content/browser/attribution_reporting/attribution_src_browsertest.cc index 73d94f3..42733483 100644 --- a/content/browser/attribution_reporting/attribution_src_browsertest.cc +++ b/content/browser/attribution_reporting/attribution_src_browsertest.cc
@@ -5,6 +5,7 @@ #include <memory> #include <utility> +#include "base/containers/contains.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" #include "base/strings/strcat.h" @@ -802,6 +803,41 @@ "event-source, trigger"); } +// Regression test for crbug.com/1345955. +IN_PROC_BROWSER_TEST_F(AttributionSrcBrowserTest, + UntrustworthyUrl_DoesNotSetEligibleHeader) { + auto http_server = std::make_unique<net::EmbeddedTestServer>(); + net::test_server::RegisterDefaultHandlers(http_server.get()); + + auto response1 = std::make_unique<net::test_server::ControllableHttpResponse>( + http_server.get(), "/register_source1"); + auto response2 = std::make_unique<net::test_server::ControllableHttpResponse>( + http_server.get(), "/register_source2"); + ASSERT_TRUE(http_server->Start()); + + GURL page_url = + https_server()->GetURL("b.test", "/page_with_impression_creator.html"); + ASSERT_TRUE(NavigateToURL(web_contents(), page_url)); + + GURL register_url1 = http_server->GetURL("d.test", "/register_source1"); + ASSERT_TRUE(ExecJs(web_contents(), JsReplace(R"( + createAndClickAttributionSrcAnchor({url: $1, attributionsrc: '', target: '_blank'});)", + register_url1))); + + response1->WaitForRequest(); + ASSERT_FALSE(base::Contains(response1->http_request()->headers, + "Attribution-Reporting-Eligible")); + + GURL register_url2 = http_server->GetURL("d.test", "/register_source2"); + ASSERT_TRUE(ExecJs(web_contents(), JsReplace(R"( + window.open($1, '_blank', 'attributionsrc=');)", + register_url2))); + + response2->WaitForRequest(); + ASSERT_FALSE(base::Contains(response2->http_request()->headers, + "Attribution-Reporting-Eligible")); +} + IN_PROC_BROWSER_TEST_F(AttributionSrcBrowserTest, ReferrerPolicy_RespectsDocument) { // Create a separate server as we cannot register a `ControllableHttpResponse`
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc index e7b8168..d0d6020 100644 --- a/content/browser/devtools/devtools_instrumentation.cc +++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -228,9 +228,6 @@ case FederatedAuthRequestResult::kErrorFetchingIdTokenInvalidResponse: { return FederatedAuthRequestIssueReasonEnum::IdTokenInvalidResponse; } - case FederatedAuthRequestResult::kErrorFetchingIdTokenInvalidRequest: { - return FederatedAuthRequestIssueReasonEnum::IdTokenInvalidRequest; - } case FederatedAuthRequestResult::kErrorCanceled: { return FederatedAuthRequestIssueReasonEnum::Canceled; }
diff --git a/content/browser/first_party_sets/first_party_set_parser.cc b/content/browser/first_party_sets/first_party_set_parser.cc index 610b587..4b5a110a 100644 --- a/content/browser/first_party_sets/first_party_set_parser.cc +++ b/content/browser/first_party_sets/first_party_set_parser.cc
@@ -4,6 +4,7 @@ #include "content/browser/first_party_sets/first_party_set_parser.h" +#include <cstdint> #include <string> #include <utility> #include <vector> @@ -81,6 +82,7 @@ // returns an appropriate FirstPartySetParser::ParseError. base::expected<FirstPartySetParser::SingleSet, FirstPartySetParser::ParseError> ParseSet(const base::Value& value, + bool keep_indices, base::flat_set<net::SchemefulSite>& elements) { if (!value.is_dict()) return base::unexpected(FirstPartySetParser::ParseError::kInvalidType); @@ -112,8 +114,10 @@ std::vector<std::pair<net::SchemefulSite, net::FirstPartySetEntry>> sites; sites.emplace_back( *canonical_owner, - net::FirstPartySetEntry(*canonical_owner, net::SiteType::kPrimary)); + net::FirstPartySetEntry(*canonical_owner, net::SiteType::kPrimary, + absl::nullopt)); // Add each member to our mapping (assuming the member is a string). + uint32_t index = 0; for (const auto& item : maybe_members_list->GetListDeprecated()) { // Members may not be a member of another set, and may not be an owner of // another set. @@ -140,7 +144,12 @@ sites.emplace_back( *member, - net::FirstPartySetEntry(*canonical_owner, net::SiteType::kAssociated)); + net::FirstPartySetEntry( + *canonical_owner, net::SiteType::kAssociated, + keep_indices + ? absl::make_optional(net::FirstPartySetEntry::SiteIndex(index)) + : absl::nullopt)); + ++index; } for (const std::pair<net::SchemefulSite, net::FirstPartySetEntry>& @@ -168,7 +177,7 @@ for (int i = 0; i < static_cast<int>(policy_sets->size()); i++) { base::expected<FirstPartySetParser::SingleSet, FirstPartySetParser::ParseError> - parsed = ParseSet((*policy_sets)[i], elements); + parsed = ParseSet((*policy_sets)[i], /*keep_indices=*/false, elements); if (!parsed.has_value()) { return base::unexpected( FirstPartySetParser::PolicyParsingError{parsed.error(), set_type, i}); @@ -229,9 +238,9 @@ continue; } if (!owner_set.contains(maybe_owner)) { - map.emplace_back( - *maybe_owner, - net::FirstPartySetEntry(*maybe_owner, net::SiteType::kPrimary)); + map.emplace_back(*maybe_owner, net::FirstPartySetEntry( + *maybe_owner, net::SiteType::kPrimary, + absl::nullopt)); } // Check disjointness. Note that we are relying on the JSON Parser to // eliminate the possibility of a site being used as a key more than once, @@ -242,9 +251,12 @@ } owner_set.insert(*maybe_owner); member_set.insert(*maybe_member); - map.emplace_back(std::move(*maybe_member), - net::FirstPartySetEntry(std::move(*maybe_owner), - net::SiteType::kAssociated)); + // TODO(https://crbug.com/1219656): preserve ordering information when + // persisting set info. + map.emplace_back( + std::move(*maybe_member), + net::FirstPartySetEntry(std::move(*maybe_owner), + net::SiteType::kAssociated, absl::nullopt)); } return map; } @@ -286,7 +298,7 @@ return {}; base::expected<FirstPartySetParser::SingleSet, FirstPartySetParser::ParseError> - parsed = ParseSet(*maybe_value, elements); + parsed = ParseSet(*maybe_value, /*keep_indices=*/true, elements); if (!parsed.has_value()) { if (parsed.error() == FirstPartySetParser::ParseError::kInvalidOrigin) { // Ignore sets that include an invalid domain (which might have been
diff --git a/content/browser/first_party_sets/first_party_set_parser_unittest.cc b/content/browser/first_party_sets/first_party_set_parser_unittest.cc index 1d65699..91441cd6 100644 --- a/content/browser/first_party_sets/first_party_set_parser_unittest.cc +++ b/content/browser/first_party_sets/first_party_set_parser_unittest.cc
@@ -68,11 +68,11 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://aaaa.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST(FirstPartySetParser, RejectsMissingOwner) { @@ -116,19 +116,19 @@ Pair(SerializesTo("https://example2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example2.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example2.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://aaaa.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST(FirstPartySetParser, RejectsOwnerWithoutRegisteredDomain) { @@ -180,19 +180,19 @@ Pair(SerializesTo("https://example2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example2.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example2.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member3.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST(FirstPartySetParser, RejectsMemberWithoutRegisteredDomain) { @@ -211,11 +211,11 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://aaaa.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST(FirstPartySetParser, TruncatesSubdomain_Member) { @@ -227,11 +227,11 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://aaaa.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST(FirstPartySetParser, AcceptsMultipleSets) { @@ -247,19 +247,19 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://foo.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST(FirstPartySetParser, AcceptsMultipleSetsWithWhitespace) { @@ -277,19 +277,19 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://foo.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST(FirstPartySetParser, RejectsInvalidSets_InvalidOwner) { @@ -315,11 +315,11 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST(FirstPartySetParser, Rejects_SameOwner) { @@ -362,19 +362,20 @@ {{net::SchemefulSite(GURL("https://member1.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example1.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://example1.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example1.test")), - net::SiteType::kPrimary)}})); + net::SiteType::kPrimary, absl::nullopt)}})); } TEST(FirstPartySetParser, SerializeFirstPartySetsWithOpaqueOrigin) { - EXPECT_EQ(R"({"https://member1.test":"null"})", - FirstPartySetParser::SerializeFirstPartySets( - {{net::SchemefulSite(GURL("https://member1.test")), - net::FirstPartySetEntry(net::SchemefulSite(GURL("")), - net::SiteType::kPrimary)}})); + EXPECT_EQ( + R"({"https://member1.test":"null"})", + FirstPartySetParser::SerializeFirstPartySets( + {{net::SchemefulSite(GURL("https://member1.test")), + net::FirstPartySetEntry(net::SchemefulSite(GURL("")), + net::SiteType::kPrimary, absl::nullopt)}})); } TEST(FirstPartySetParser, SerializeFirstPartySetsEmptySet) { @@ -394,23 +395,23 @@ Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example1.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, absl::nullopt)), Pair(SerializesTo("https://member3.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example1.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, absl::nullopt)), Pair(SerializesTo("https://example1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example1.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example2.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, absl::nullopt)), Pair(SerializesTo("https://example2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example2.test")), - net::SiteType::kPrimary)))); + net::SiteType::kPrimary, absl::nullopt)))); } TEST(FirstPartySetParser, DeserializeFirstPartySetsEmptySet) { @@ -430,11 +431,11 @@ Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example2.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, absl::nullopt)), Pair(SerializesTo("https://example2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example2.test")), - net::SiteType::kPrimary)))); + net::SiteType::kPrimary, absl::nullopt)))); } // Singleton set is ignored. @@ -449,11 +450,11 @@ Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example2.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, absl::nullopt)), Pair(SerializesTo("https://example2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example2.test")), - net::SiteType::kPrimary)))); + net::SiteType::kPrimary, absl::nullopt)))); } class FirstPartySetParserInvalidContentTest @@ -506,7 +507,8 @@ R"({"https://member1.test":"https://example1.test", "https://example1.test":"https://example2.test"})"))); -TEST(ParseSetsFromEnterprisePolicyTest, Accepts_MissingSetLists) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, + Accepts_MissingSetLists) { base::Value policy_value = base::JSONReader::Read(R"( { } @@ -518,7 +520,7 @@ FirstPartySetParser::ParsedPolicySetLists({}, {})); } -TEST(ParseSetsFromEnterprisePolicyTest, Accepts_EmptyLists) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, Accepts_EmptyLists) { base::Value policy_value = base::JSONReader::Read(R"( { "replacements": [], @@ -532,7 +534,8 @@ FirstPartySetParser::ParsedPolicySetLists({}, {})); } -TEST(ParseSetsFromEnterprisePolicyTest, InvalidTypeError_MissingOwner) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, + InvalidTypeError_MissingOwner) { base::Value policy_value = base::JSONReader::Read(R"( { "replacements": [ @@ -552,7 +555,8 @@ FirstPartySetParser::PolicySetType::kReplacement, 0})); } -TEST(ParseSetsFromEnterprisePolicyTest, InvalidTypeError_MissingMembers) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, + InvalidTypeError_MissingMembers) { base::Value policy_value = base::JSONReader::Read(R"( { "replacements": [ @@ -572,7 +576,8 @@ FirstPartySetParser::PolicySetType::kReplacement, 0})); } -TEST(ParseSetsFromEnterprisePolicyTest, InvalidTypeError_WrongOwnerType) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, + InvalidTypeError_WrongOwnerType) { base::Value policy_value = base::JSONReader::Read(R"( { "replacements": [ @@ -593,7 +598,7 @@ FirstPartySetParser::PolicySetType::kReplacement, 0})); } -TEST(ParseSetsFromEnterprisePolicyTest, +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, InvalidTypeError_WrongMembersFieldType) { base::Value policy_value = base::JSONReader::Read(R"( { @@ -615,7 +620,8 @@ FirstPartySetParser::PolicySetType::kReplacement, 0})); } -TEST(ParseSetsFromEnterprisePolicyTest, InvalidTypeError_WrongMemberType) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, + InvalidTypeError_WrongMemberType) { base::Value policy_value = base::JSONReader::Read(R"( { "replacements": [ @@ -637,7 +643,8 @@ FirstPartySetParser::PolicySetType::kReplacement, 0})); } -TEST(ParseSetsFromEnterprisePolicyTest, InvalidOriginError_OwnerOpaque) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, + InvalidOriginError_OwnerOpaque) { base::Value policy_value = base::JSONReader::Read(R"( { "replacements": [ @@ -658,7 +665,8 @@ FirstPartySetParser::PolicySetType::kReplacement, 0})); } -TEST(ParseSetsFromEnterprisePolicyTest, InvalidOriginError_MemberOpaque) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, + InvalidOriginError_MemberOpaque) { base::Value policy_value = base::JSONReader::Read(R"( { "replacements": [ @@ -679,7 +687,8 @@ FirstPartySetParser::PolicySetType::kReplacement, 0})); } -TEST(ParseSetsFromEnterprisePolicyTest, InvalidOriginError_OwnerNonHttps) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, + InvalidOriginError_OwnerNonHttps) { base::Value policy_value = base::JSONReader::Read(R"( { "replacements": [ @@ -700,7 +709,8 @@ FirstPartySetParser::PolicySetType::kReplacement, 0})); } -TEST(ParseSetsFromEnterprisePolicyTest, InvalidOriginError_MemberNonHttps) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, + InvalidOriginError_MemberNonHttps) { base::Value policy_value = base::JSONReader::Read(R"( { "replacements": [ @@ -721,7 +731,7 @@ FirstPartySetParser::PolicySetType::kReplacement, 0})); } -TEST(ParseSetsFromEnterprisePolicyTest, +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, InvalidOriginError_OwnerNonRegisteredDomain) { base::Value policy_value = base::JSONReader::Read(R"( { @@ -743,7 +753,7 @@ FirstPartySetParser::PolicySetType::kReplacement, 0})); } -TEST(ParseSetsFromEnterprisePolicyTest, +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, InvalidOriginError_MemberNonRegisteredDomain) { base::Value policy_value = base::JSONReader::Read(R"( { @@ -765,7 +775,8 @@ FirstPartySetParser::PolicySetType::kReplacement, 0})); } -TEST(ParseSetsFromEnterprisePolicyTest, SingletonSetError_EmptyMembers) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, + SingletonSetError_EmptyMembers) { base::Value policy_value = base::JSONReader::Read(R"( { "replacements": [ @@ -786,7 +797,7 @@ FirstPartySetParser::PolicySetType::kReplacement, 0})); } -TEST(ParseSetsFromEnterprisePolicyTest, +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, RepeatedDomainError_WithinReplacements) { base::Value policy_value = base::JSONReader::Read(R"( { @@ -808,7 +819,8 @@ FirstPartySetParser::PolicySetType::kReplacement, 0})); } -TEST(ParseSetsFromEnterprisePolicyTest, NonDisjointError_WithinReplacements) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, + NonDisjointError_WithinReplacements) { base::Value policy_value = base::JSONReader::Read(R"( { "replacements": [ @@ -833,7 +845,8 @@ FirstPartySetParser::PolicySetType::kReplacement, 1})); } -TEST(ParseSetsFromEnterprisePolicyTest, NonDisjointError_WithinAdditions) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, + NonDisjointError_WithinAdditions) { base::Value policy_value = base::JSONReader::Read(R"( { "replacements": [], @@ -858,7 +871,8 @@ FirstPartySetParser::PolicySetType::kAddition, 1})); } -TEST(ParseSetsFromEnterprisePolicyTest, NonDisjointError_AcrossBothLists) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, + NonDisjointError_AcrossBothLists) { base::Value policy_value = base::JSONReader::Read(R"( { "replacements": [ @@ -884,7 +898,8 @@ FirstPartySetParser::PolicySetType::kAddition, 0})); } -TEST(ParseSetsFromEnterprisePolicyTest, SuccessfulMapping_SameList) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, + SuccessfulMapping_SameList) { net::SchemefulSite owner1(GURL("https://owner1.test")); net::SchemefulSite member1(GURL("https://member1.test")); net::SchemefulSite owner2(GURL("https://owner2.test")); @@ -910,21 +925,24 @@ .value(), FirstPartySetParser::ParsedPolicySetLists( {FirstPartySetParser::SetsMap({ - {owner1, - net::FirstPartySetEntry(owner1, net::SiteType::kPrimary)}, + {owner1, net::FirstPartySetEntry(owner1, net::SiteType::kPrimary, + absl::nullopt)}, {member1, - net::FirstPartySetEntry(owner1, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(owner1, net::SiteType::kAssociated, + absl::nullopt)}, }), FirstPartySetParser::SetsMap({ - {owner2, - net::FirstPartySetEntry(owner2, net::SiteType::kPrimary)}, + {owner2, net::FirstPartySetEntry(owner2, net::SiteType::kPrimary, + absl::nullopt)}, {member2, - net::FirstPartySetEntry(owner2, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(owner2, net::SiteType::kAssociated, + absl::nullopt)}, })}, {})); } -TEST(ParseSetsFromEnterprisePolicyTest, SuccessfulMapping_CrossList) { +TEST(FirstPartySets_ParseSetsFromEnterprisePolicyTest, + SuccessfulMapping_CrossList) { net::SchemefulSite owner1(GURL("https://owner1.test")); net::SchemefulSite member1(GURL("https://member1.test")); net::SchemefulSite owner2(GURL("https://owner2.test")); @@ -958,22 +976,24 @@ .value(), FirstPartySetParser::ParsedPolicySetLists( {FirstPartySetParser::SetsMap({ - {owner1, - net::FirstPartySetEntry(owner1, net::SiteType::kPrimary)}, + {owner1, net::FirstPartySetEntry(owner1, net::SiteType::kPrimary, + absl::nullopt)}, {member1, - net::FirstPartySetEntry(owner1, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(owner1, net::SiteType::kAssociated, + absl::nullopt)}, }), FirstPartySetParser::SetsMap({ - {owner2, - net::FirstPartySetEntry(owner2, net::SiteType::kPrimary)}, + {owner2, net::FirstPartySetEntry(owner2, net::SiteType::kPrimary, + absl::nullopt)}, {member2, - net::FirstPartySetEntry(owner2, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(owner2, net::SiteType::kAssociated, + absl::nullopt)}, })}, {FirstPartySetParser::SetsMap({ - {owner3, - net::FirstPartySetEntry(owner3, net::SiteType::kPrimary)}, - {member3, - net::FirstPartySetEntry(owner3, net::SiteType::kAssociated)}, + {owner3, net::FirstPartySetEntry(owner3, net::SiteType::kPrimary, + absl::nullopt)}, + {member3, net::FirstPartySetEntry( + owner3, net::SiteType::kAssociated, absl::nullopt)}, })})); }
diff --git a/content/browser/first_party_sets/first_party_sets_handler_impl.cc b/content/browser/first_party_sets/first_party_sets_handler_impl.cc index c4e3ee2..b150d77d 100644 --- a/content/browser/first_party_sets/first_party_sets_handler_impl.cc +++ b/content/browser/first_party_sets/first_party_sets_handler_impl.cc
@@ -149,9 +149,10 @@ for (const auto& child_site_and_entry : addition_sets[child_set_idx]) { bool inserted = normalized - .emplace(child_site_and_entry.first, - net::FirstPartySetEntry(rep_primary, - net::SiteType::kAssociated)) + .emplace( + child_site_and_entry.first, + net::FirstPartySetEntry( + rep_primary, net::SiteType::kAssociated, absl::nullopt)) .second; DCHECK(inserted); } @@ -305,7 +306,8 @@ member, net::FirstPartySetEntry(entry->second.primary(), member == entry->second.primary() ? net::SiteType::kPrimary - : net::SiteType::kAssociated)); + : net::SiteType::kAssociated, + absl::nullopt)); } if (member == set_entry.primary()) continue;
diff --git a/content/browser/first_party_sets/first_party_sets_handler_impl_unittest.cc b/content/browser/first_party_sets/first_party_sets_handler_impl_unittest.cc index 9c09a6c..af509bd 100644 --- a/content/browser/first_party_sets/first_party_sets_handler_impl_unittest.cc +++ b/content/browser/first_party_sets/first_party_sets_handler_impl_unittest.cc
@@ -49,32 +49,37 @@ for (const auto& [owner, members] : owners_to_members) { net::SchemefulSite owner_site((GURL(owner))); result.insert(std::make_pair( - owner_site, - net::FirstPartySetEntry(owner_site, net::SiteType::kPrimary))); + owner_site, net::FirstPartySetEntry(owner_site, net::SiteType::kPrimary, + absl::nullopt))); + uint32_t index = 0; for (const std::string& member : members) { net::SchemefulSite member_site((GURL(member))); result.insert(std::make_pair( - member_site, - net::FirstPartySetEntry(owner_site, net::SiteType::kAssociated))); + member_site, net::FirstPartySetEntry( + owner_site, net::SiteType::kAssociated, index))); + ++index; } } return result; } // Parses `input` as a collection of primaries and their associated sites, and -// appends the results to `output`. +// appends the results to `output`. Does not preserve indices (so it is only +// suitable for creating enterprise policy sets). void ParseAndAppend( const base::flat_map<std::string, std::vector<std::string>>& input, std::vector<SingleSet>& output) { for (auto& [owner, members] : input) { std::vector<std::pair<net::SchemefulSite, net::FirstPartySetEntry>> sites; net::SchemefulSite owner_site((GURL(owner))); - sites.emplace_back(owner_site, net::FirstPartySetEntry( - owner_site, net::SiteType::kPrimary)); + sites.emplace_back( + owner_site, net::FirstPartySetEntry(owner_site, net::SiteType::kPrimary, + absl::nullopt)); for (const std::string& member : members) { sites.emplace_back( GURL(member), - net::FirstPartySetEntry(owner_site, net::SiteType::kAssociated)); + net::FirstPartySetEntry(owner_site, net::SiteType::kAssociated, + absl::nullopt)); } output.emplace_back(sites); } @@ -109,13 +114,13 @@ FirstPartySetsHandlerImpl::FlattenedSets old_sets = { {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://member1.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://member3.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}}; + net::SiteType::kAssociated, 1)}}; // Consistency check the reviewer-friendly format matches the input. ASSERT_THAT(ParseSetsFromStream( R"({"owner": "https://example.test", "members": )" @@ -125,19 +130,19 @@ FirstPartySetsHandlerImpl::FlattenedSets current_sets = { {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://member1.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://member3.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 1)}, {net::SchemefulSite(GURL("https://foo.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://member2.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, }; // Consistency check the reviewer-friendly format matches the input. ASSERT_THAT( @@ -159,19 +164,19 @@ FirstPartySetsHandlerImpl::FlattenedSets old_sets = { {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://member1.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://member3.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 1)}, {net::SchemefulSite(GURL("https://foo.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://member2.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}}; + net::SiteType::kAssociated, 0)}}; // Consistency check the reviewer-friendly format matches the input. ASSERT_THAT( ParseSetsFromStream(R"({"owner": "https://example.test", "members": )" @@ -182,10 +187,10 @@ FirstPartySetsHandlerImpl::FlattenedSets current_sets = { {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://member1.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}}; + net::SiteType::kAssociated, 0)}}; // Consistency check the reviewer-friendly format matches the input. ASSERT_THAT(ParseSetsFromStream(R"({"owner": "https://example.test", )" R"("members": ["https://member1.test"]})"), @@ -205,19 +210,19 @@ FirstPartySetsHandlerImpl::FlattenedSets old_sets = { {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://member1.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://foo.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://member2.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://member3.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}}; + net::SiteType::kAssociated, 1)}}; // Consistency check the reviewer-friendly format matches the input. ASSERT_THAT(ParseSetsFromStream( R"({"owner": "https://example.test", "members": )" @@ -229,19 +234,19 @@ FirstPartySetsHandlerImpl::FlattenedSets current_sets = { {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://member1.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://member3.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 1)}, {net::SchemefulSite(GURL("https://foo.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://member2.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}}; + net::SiteType::kAssociated, 0)}}; // Consistency check the reviewer-friendly format matches the input. ASSERT_THAT( ParseSetsFromStream(R"({"owner": "https://example.test", "members": )" @@ -260,13 +265,13 @@ FirstPartySetsHandlerImpl::FlattenedSets old_sets = { {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://foo.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://bar.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}}; + net::SiteType::kAssociated, 1)}}; // Consistency check the reviewer-friendly format matches the input. ASSERT_THAT( ParseSetsFromStream(R"({"owner": "https://example.test", "members": )" @@ -276,10 +281,10 @@ FirstPartySetsHandlerImpl::FlattenedSets current_sets = { {net::SchemefulSite(GURL("https://foo.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://bar.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}}; + net::SiteType::kAssociated, 0)}}; // Consistency check the reviewer-friendly format matches the input. ASSERT_THAT(ParseSetsFromStream(R"( {"owner": "https://foo.test", "members": ["https://bar.test"]})"), @@ -302,10 +307,10 @@ FirstPartySetsHandlerImpl::FlattenedSets old_sets = { {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://foo.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}}; + net::SiteType::kAssociated, 0)}}; // Consistency check the reviewer-friendly format matches the input. ASSERT_THAT( ParseSetsFromStream(R"({"owner": "https://example.test", "members": )" @@ -315,10 +320,10 @@ FirstPartySetsHandlerImpl::FlattenedSets current_sets = { {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://foo.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)}}; + net::SiteType::kPrimary, absl::nullopt)}}; // Consistency check the reviewer-friendly format matches the input. ASSERT_THAT( ParseSetsFromStream( @@ -340,10 +345,10 @@ FirstPartySetsHandlerImpl::FlattenedSets current_sets = { {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://member1.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}}; + net::SiteType::kAssociated, 0)}}; // Consistency check the reviewer-friendly format matches the input. ASSERT_THAT(ParseSetsFromStream(R"({"owner": "https://example.test", )" R"("members": ["https://member1.test"]})"), @@ -360,10 +365,10 @@ FirstPartySetsHandlerImpl::FlattenedSets old_sets = { {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://member1.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}}; + net::SiteType::kAssociated, 0)}}; // Consistency check the reviewer-friendly format matches the input. ASSERT_THAT(ParseSetsFromStream(R"({"owner": "https://example.test", )" R"("members": ["https://member1.test"]})"), @@ -379,10 +384,10 @@ FirstPartySetsHandlerImpl::PolicyCustomization current_policy = { {net::SchemefulSite(GURL("https://foo.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)}}, + net::SiteType::kPrimary, absl::nullopt)}}, {net::SchemefulSite(GURL("https://member2.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, }; // "https://example.test" and "https://member2.test" joined FPSs via @@ -398,10 +403,10 @@ FirstPartySetsHandlerImpl::FlattenedSets sets = { {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://member1.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}}; + net::SiteType::kAssociated, 0)}}; // Consistency check the reviewer-friendly format matches the input. ASSERT_THAT(ParseSetsFromStream(R"({"owner": "https://example.test",)" R"("members": ["https://member1.test"]})"), @@ -411,10 +416,10 @@ FirstPartySetsHandlerImpl::PolicyCustomization old_policy = { {net::SchemefulSite(GURL("https://foo.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)}}, + net::SiteType::kPrimary, absl::nullopt)}}, {net::SchemefulSite(GURL("https://member1.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, {net::SchemefulSite(GURL("https://example.test")), absl::nullopt}, }; @@ -422,13 +427,13 @@ FirstPartySetsHandlerImpl::PolicyCustomization current_policy = { {net::SchemefulSite(GURL("https://foo.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)}}, + net::SiteType::kPrimary, absl::nullopt)}}, {net::SchemefulSite(GURL("https://member1.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, {net::SchemefulSite(GURL("https://example.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, }; // We don't clear site data upon joining, so the computed diff should be @@ -443,23 +448,23 @@ FirstPartySetsHandlerImpl::PolicyCustomization old_policy = { {net::SchemefulSite(GURL("https://foo.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)}}, + net::SiteType::kPrimary, absl::nullopt)}}, {net::SchemefulSite(GURL("https://member1.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, {net::SchemefulSite(GURL("https://member2.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, }; // "https://member2.test" left FPSs via enterprise policy. FirstPartySetsHandlerImpl::PolicyCustomization current_policy = { {net::SchemefulSite(GURL("https://foo.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)}}, + net::SiteType::kPrimary, absl::nullopt)}}, {net::SchemefulSite(GURL("https://member1.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, }; EXPECT_THAT( @@ -473,26 +478,26 @@ {net::SchemefulSite(GURL("https://example.test")), {net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}}, + net::SiteType::kPrimary, absl::nullopt)}}, {net::SchemefulSite(GURL("https://member1.test")), {net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, {net::SchemefulSite(GURL("https://member2.test")), {net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, }; FirstPartySetsHandlerImpl::PolicyCustomization current_policy = { {net::SchemefulSite(GURL("https://member1.test")), {net::FirstPartySetEntry( net::SchemefulSite(GURL("https://member1.test")), - net::SiteType::kPrimary)}}, + net::SiteType::kPrimary, absl::nullopt)}}, {net::SchemefulSite(GURL("https://member2.test")), {net::FirstPartySetEntry( net::SchemefulSite(GURL("https://member1.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, }; // Expected diff: "https://example.test" left FPSs, "https://member1.test" and @@ -512,31 +517,31 @@ FirstPartySetsHandlerImpl::PolicyCustomization old_policy = { {net::SchemefulSite(GURL("https://foo.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)}}, + net::SiteType::kPrimary, absl::nullopt)}}, {net::SchemefulSite(GURL("https://member1.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, {net::SchemefulSite(GURL("https://bar.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://bar.test")), - net::SiteType::kPrimary)}}, + net::SiteType::kPrimary, absl::nullopt)}}, {net::SchemefulSite(GURL("https://member2.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://bar.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, }; FirstPartySetsHandlerImpl::PolicyCustomization current_policy = { {net::SchemefulSite(GURL("https://foo.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)}}, + net::SiteType::kPrimary, absl::nullopt)}}, {net::SchemefulSite(GURL("https://member2.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, {net::SchemefulSite(GURL("https://bar.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://bar.test")), - net::SiteType::kPrimary)}}, + net::SiteType::kPrimary, absl::nullopt)}}, {net::SchemefulSite(GURL("https://member1.test")), {net::FirstPartySetEntry(net::SchemefulSite(GURL("https://bar.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, }; EXPECT_THAT( @@ -668,11 +673,11 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST_F(FirstPartySetsHandlerImplEnabledTest, @@ -685,34 +690,51 @@ FirstPartySetsHandlerImpl::GetInstance()->SetPublicFirstPartySets( WritePublicSetsFile(input)); - auto expected_sets = UnorderedElementsAre( - Pair(SerializesTo("https://example.test"), - net::FirstPartySetEntry( - net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), - Pair(SerializesTo("https://member1.test"), - net::FirstPartySetEntry( - net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), - Pair(SerializesTo("https://foo.test"), - net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)), - Pair(SerializesTo("https://member2.test"), - net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated))); - // Persisted sets are expected to be loaded with the provided path. FirstPartySetsHandlerImpl::GetInstance()->Init( scoped_dir_.GetPath(), /*flag_value=*/"https://example.test,https://member1.test"); - EXPECT_THAT(GetSetsAndWait(), expected_sets); + EXPECT_THAT(GetSetsAndWait(), + UnorderedElementsAre( + Pair(SerializesTo("https://example.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://example.test")), + net::SiteType::kPrimary, absl::nullopt)), + Pair(SerializesTo("https://member1.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://example.test")), + net::SiteType::kAssociated, 0)), + Pair(SerializesTo("https://foo.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://foo.test")), + net::SiteType::kPrimary, absl::nullopt)), + Pair(SerializesTo("https://member2.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://foo.test")), + net::SiteType::kAssociated, 0)))); env().RunUntilIdle(); std::string got; ASSERT_TRUE(base::ReadFileToString(persisted_sets_path_, &got)); EXPECT_THAT(FirstPartySetParser::DeserializeFirstPartySets(got), - expected_sets); + UnorderedElementsAre( + Pair(SerializesTo("https://example.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://example.test")), + net::SiteType::kPrimary, absl::nullopt)), + Pair(SerializesTo("https://member1.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://example.test")), + net::SiteType::kAssociated, absl::nullopt)), + Pair(SerializesTo("https://foo.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://foo.test")), + net::SiteType::kPrimary, absl::nullopt)), + Pair(SerializesTo("https://member2.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://foo.test")), + net::SiteType::kAssociated, absl::nullopt)))); } TEST_F(FirstPartySetsHandlerImplEnabledTest, Successful_PersistedSetsEmpty) { @@ -726,34 +748,51 @@ FirstPartySetsHandlerImpl::GetInstance()->SetPublicFirstPartySets( WritePublicSetsFile(input)); - auto expected_sets = UnorderedElementsAre( - Pair(SerializesTo("https://example.test"), - net::FirstPartySetEntry( - net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), - Pair(SerializesTo("https://member1.test"), - net::FirstPartySetEntry( - net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), - Pair(SerializesTo("https://foo.test"), - net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)), - Pair(SerializesTo("https://member2.test"), - net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated))); - // Persisted sets are expected to be loaded with the provided path. FirstPartySetsHandlerImpl::GetInstance()->Init( scoped_dir_.GetPath(), /*flag_value=*/"https://example.test,https://member1.test"); - EXPECT_THAT(GetSetsAndWait(), expected_sets); + EXPECT_THAT(GetSetsAndWait(), + UnorderedElementsAre( + Pair(SerializesTo("https://example.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://example.test")), + net::SiteType::kPrimary, absl::nullopt)), + Pair(SerializesTo("https://member1.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://example.test")), + net::SiteType::kAssociated, 0)), + Pair(SerializesTo("https://foo.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://foo.test")), + net::SiteType::kPrimary, absl::nullopt)), + Pair(SerializesTo("https://member2.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://foo.test")), + net::SiteType::kAssociated, 0)))); env().RunUntilIdle(); std::string got; ASSERT_TRUE(base::ReadFileToString(persisted_sets_path_, &got)); EXPECT_THAT(FirstPartySetParser::DeserializeFirstPartySets(got), - expected_sets); + UnorderedElementsAre( + Pair(SerializesTo("https://example.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://example.test")), + net::SiteType::kPrimary, absl::nullopt)), + Pair(SerializesTo("https://member1.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://example.test")), + net::SiteType::kAssociated, absl::nullopt)), + Pair(SerializesTo("https://foo.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://foo.test")), + net::SiteType::kPrimary, absl::nullopt)), + Pair(SerializesTo("https://member2.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://foo.test")), + net::SiteType::kAssociated, absl::nullopt)))); } TEST_F(FirstPartySetsHandlerImplEnabledTest, @@ -768,33 +807,48 @@ FirstPartySetsHandlerImpl::GetInstance()->SetPublicFirstPartySets( WritePublicSetsFile(input)); - auto expected_sets = UnorderedElementsAre( - Pair(SerializesTo("https://example.test"), - net::FirstPartySetEntry( - net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), - Pair(SerializesTo("https://member.test"), - net::FirstPartySetEntry( - net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated))); - // Persisted sets are expected to be loaded with the provided path. FirstPartySetsHandlerImpl::GetInstance()->Init(scoped_dir_.GetPath(), /*flag_value=*/""); - EXPECT_THAT(GetSetsAndWait(), expected_sets); + EXPECT_THAT(GetSetsAndWait(), + UnorderedElementsAre( + Pair(SerializesTo("https://example.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://example.test")), + net::SiteType::kPrimary, absl::nullopt)), + Pair(SerializesTo("https://member.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://example.test")), + net::SiteType::kAssociated, 0)))); env().RunUntilIdle(); std::string got; ASSERT_TRUE(base::ReadFileToString(persisted_sets_path_, &got)); EXPECT_THAT(FirstPartySetParser::DeserializeFirstPartySets(got), - expected_sets); + UnorderedElementsAre( + Pair(SerializesTo("https://example.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://example.test")), + net::SiteType::kPrimary, absl::nullopt)), + Pair(SerializesTo("https://member.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://example.test")), + net::SiteType::kAssociated, absl::nullopt)))); EXPECT_THAT( FirstPartySetsHandlerImpl::GetInstance()->GetSets( base::BindLambdaForTesting( [](FirstPartySetsHandlerImpl::FlattenedSets) { FAIL(); })), - testing::Optional(expected_sets)); + testing::Optional(UnorderedElementsAre( + Pair(SerializesTo("https://example.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://example.test")), + net::SiteType::kPrimary, absl::nullopt)), + Pair(SerializesTo("https://member.test"), + net::FirstPartySetEntry( + net::SchemefulSite(GURL("https://example.test")), + net::SiteType::kAssociated, 0))))); } TEST_F(FirstPartySetsHandlerImplEnabledTest, @@ -824,11 +878,11 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); EXPECT_THAT( FirstPartySetsHandlerImpl::GetInstance()->GetSets( @@ -838,11 +892,11 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated))))); + net::SiteType::kAssociated, 0))))); } class FirstPartySetsHandlerGetCustomizationForPolicyTest @@ -945,23 +999,23 @@ Pair(SerializesTo("https://owner1.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner2.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://member1.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://member1.test")), - net::SiteType::kPrimary))), + net::SiteType::kPrimary, absl::nullopt))), Pair(SerializesTo("https://owner3.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://member1.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://member2.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner2.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://owner2.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner2.test")), - net::SiteType::kPrimary))))); + net::SiteType::kPrimary, absl::nullopt))))); } TEST(FirstPartySetsProfilePolicyCustomizations, EmptyPolicySetLists) { @@ -987,11 +1041,11 @@ Pair(SerializesTo("https://member2.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner2.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://owner2.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner2.test")), - net::SiteType::kPrimary))))); + net::SiteType::kPrimary, absl::nullopt))))); } // The common member between the policy and existing set is removed from its @@ -1012,11 +1066,11 @@ Pair(SerializesTo("https://member1b.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner2.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://owner2.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner2.test")), - net::SiteType::kPrimary))))); + net::SiteType::kPrimary, absl::nullopt))))); } // The common owner between the policy and existing set is removed and its @@ -1037,11 +1091,11 @@ Pair(SerializesTo("https://member2.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner1.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://owner1.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner1.test")), - net::SiteType::kPrimary))), + net::SiteType::kPrimary, absl::nullopt))), Pair(SerializesTo("https://member1a.test"), absl::nullopt), Pair(SerializesTo("https://member1b.test"), absl::nullopt))); } @@ -1063,11 +1117,11 @@ Pair(SerializesTo("https://member1.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner3.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://owner3.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner3.test")), - net::SiteType::kPrimary))), + net::SiteType::kPrimary, absl::nullopt))), Pair(SerializesTo("https://owner1.test"), absl::nullopt))); } @@ -1088,11 +1142,11 @@ Pair(SerializesTo("https://member2.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner2.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://owner2.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner2.test")), - net::SiteType::kPrimary))))); + net::SiteType::kPrimary, absl::nullopt))))); } // The owner of a policy set is also a member in an existing set. @@ -1113,19 +1167,19 @@ Pair(SerializesTo("https://owner1.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://member2.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://member2a.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://member2.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://member2b.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://member2.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://member2.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://member2.test")), - net::SiteType::kPrimary))))); + net::SiteType::kPrimary, absl::nullopt))))); } // The owner of a policy set is also an owner of an existing set. @@ -1146,19 +1200,19 @@ Pair(SerializesTo("https://member2.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner1.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://member1.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner1.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://member3.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner1.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://owner1.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner1.test")), - net::SiteType::kPrimary))))); + net::SiteType::kPrimary, absl::nullopt))))); } TEST(FirstPartySetsProfilePolicyCustomizations, @@ -1183,44 +1237,53 @@ FirstPartySetParser::ParsedPolicySetLists( /*replacement_list=*/{}, { - SingleSet( - {{owner0, net::FirstPartySetEntry( - owner0, net::SiteType::kPrimary)}, - {member0, net::FirstPartySetEntry( - owner0, net::SiteType::kAssociated)}}), - SingleSet( - {{owner1, net::FirstPartySetEntry( - owner1, net::SiteType::kPrimary)}, - {member1, net::FirstPartySetEntry( - owner1, net::SiteType::kAssociated)}}), - SingleSet( - {{owner2, net::FirstPartySetEntry( - owner2, net::SiteType::kPrimary)}, - {member2, net::FirstPartySetEntry( - owner2, net::SiteType::kAssociated)}}), - SingleSet( - {{owner42, net::FirstPartySetEntry( - owner42, net::SiteType::kPrimary)}, - {member42, net::FirstPartySetEntry( - owner42, net::SiteType::kAssociated)}}), + SingleSet({{owner0, net::FirstPartySetEntry( + owner0, net::SiteType::kPrimary, + absl::nullopt)}, + {member0, net::FirstPartySetEntry( + owner0, net::SiteType::kAssociated, + absl::nullopt)}}), + SingleSet({{owner1, net::FirstPartySetEntry( + owner1, net::SiteType::kPrimary, + absl::nullopt)}, + {member1, net::FirstPartySetEntry( + owner1, net::SiteType::kAssociated, + absl::nullopt)}}), + SingleSet({{owner2, net::FirstPartySetEntry( + owner2, net::SiteType::kPrimary, + absl::nullopt)}, + {member2, net::FirstPartySetEntry( + owner2, net::SiteType::kAssociated, + absl::nullopt)}}), + SingleSet({{owner42, net::FirstPartySetEntry( + owner42, net::SiteType::kPrimary, + absl::nullopt)}, + {member42, net::FirstPartySetEntry( + owner42, net::SiteType::kAssociated, + absl::nullopt)}}), })), UnorderedElementsAre( - Pair(member0, absl::make_optional(net::FirstPartySetEntry( - owner0, net::SiteType::kAssociated))), - Pair(member1, absl::make_optional(net::FirstPartySetEntry( - owner1, net::SiteType::kAssociated))), - Pair(member2, absl::make_optional(net::FirstPartySetEntry( - owner1, net::SiteType::kAssociated))), - Pair(member42, absl::make_optional(net::FirstPartySetEntry( - owner42, net::SiteType::kAssociated))), + Pair(member0, + absl::make_optional(net::FirstPartySetEntry( + owner0, net::SiteType::kAssociated, absl::nullopt))), + Pair(member1, + absl::make_optional(net::FirstPartySetEntry( + owner1, net::SiteType::kAssociated, absl::nullopt))), + Pair(member2, + absl::make_optional(net::FirstPartySetEntry( + owner1, net::SiteType::kAssociated, absl::nullopt))), + Pair(member42, + absl::make_optional(net::FirstPartySetEntry( + owner42, net::SiteType::kAssociated, absl::nullopt))), Pair(owner0, absl::make_optional(net::FirstPartySetEntry( - owner0, net::SiteType::kPrimary))), + owner0, net::SiteType::kPrimary, absl::nullopt))), Pair(owner1, absl::make_optional(net::FirstPartySetEntry( - owner1, net::SiteType::kPrimary))), + owner1, net::SiteType::kPrimary, absl::nullopt))), Pair(owner2, absl::make_optional(net::FirstPartySetEntry( - owner1, net::SiteType::kAssociated))), - Pair(owner42, absl::make_optional(net::FirstPartySetEntry( - owner42, net::SiteType::kPrimary))))); + owner1, net::SiteType::kAssociated, absl::nullopt))), + Pair(owner42, + absl::make_optional(net::FirstPartySetEntry( + owner42, net::SiteType::kPrimary, absl::nullopt))))); } TEST(FirstPartySetsProfilePolicyCustomizations, @@ -1245,44 +1308,53 @@ FirstPartySetParser::ParsedPolicySetLists( /*replacement_list=*/{}, { - SingleSet( - {{owner0, net::FirstPartySetEntry( - owner0, net::SiteType::kPrimary)}, - {member0, net::FirstPartySetEntry( - owner0, net::SiteType::kAssociated)}}), - SingleSet( - {{owner2, net::FirstPartySetEntry( - owner2, net::SiteType::kPrimary)}, - {member2, net::FirstPartySetEntry( - owner2, net::SiteType::kAssociated)}}), - SingleSet( - {{owner1, net::FirstPartySetEntry( - owner1, net::SiteType::kPrimary)}, - {member1, net::FirstPartySetEntry( - owner1, net::SiteType::kAssociated)}}), - SingleSet( - {{owner42, net::FirstPartySetEntry( - owner42, net::SiteType::kPrimary)}, - {member42, net::FirstPartySetEntry( - owner42, net::SiteType::kAssociated)}}), + SingleSet({{owner0, net::FirstPartySetEntry( + owner0, net::SiteType::kPrimary, + absl::nullopt)}, + {member0, net::FirstPartySetEntry( + owner0, net::SiteType::kAssociated, + absl::nullopt)}}), + SingleSet({{owner2, net::FirstPartySetEntry( + owner2, net::SiteType::kPrimary, + absl::nullopt)}, + {member2, net::FirstPartySetEntry( + owner2, net::SiteType::kAssociated, + absl::nullopt)}}), + SingleSet({{owner1, net::FirstPartySetEntry( + owner1, net::SiteType::kPrimary, + absl::nullopt)}, + {member1, net::FirstPartySetEntry( + owner1, net::SiteType::kAssociated, + absl::nullopt)}}), + SingleSet({{owner42, net::FirstPartySetEntry( + owner42, net::SiteType::kPrimary, + absl::nullopt)}, + {member42, net::FirstPartySetEntry( + owner42, net::SiteType::kAssociated, + absl::nullopt)}}), })), UnorderedElementsAre( - Pair(member0, absl::make_optional(net::FirstPartySetEntry( - owner0, net::SiteType::kAssociated))), - Pair(member1, absl::make_optional(net::FirstPartySetEntry( - owner2, net::SiteType::kAssociated))), - Pair(member2, absl::make_optional(net::FirstPartySetEntry( - owner2, net::SiteType::kAssociated))), - Pair(member42, absl::make_optional(net::FirstPartySetEntry( - owner42, net::SiteType::kAssociated))), + Pair(member0, + absl::make_optional(net::FirstPartySetEntry( + owner0, net::SiteType::kAssociated, absl::nullopt))), + Pair(member1, + absl::make_optional(net::FirstPartySetEntry( + owner2, net::SiteType::kAssociated, absl::nullopt))), + Pair(member2, + absl::make_optional(net::FirstPartySetEntry( + owner2, net::SiteType::kAssociated, absl::nullopt))), + Pair(member42, + absl::make_optional(net::FirstPartySetEntry( + owner42, net::SiteType::kAssociated, absl::nullopt))), Pair(owner0, absl::make_optional(net::FirstPartySetEntry( - owner0, net::SiteType::kPrimary))), + owner0, net::SiteType::kPrimary, absl::nullopt))), Pair(owner1, absl::make_optional(net::FirstPartySetEntry( - owner2, net::SiteType::kAssociated))), + owner2, net::SiteType::kAssociated, absl::nullopt))), Pair(owner2, absl::make_optional(net::FirstPartySetEntry( - owner2, net::SiteType::kPrimary))), - Pair(owner42, absl::make_optional(net::FirstPartySetEntry( - owner42, net::SiteType::kPrimary))))); + owner2, net::SiteType::kPrimary, absl::nullopt))), + Pair(owner42, + absl::make_optional(net::FirstPartySetEntry( + owner42, net::SiteType::kPrimary, absl::nullopt))))); } // Existing set overlaps with both replacement and addition set. @@ -1303,22 +1375,22 @@ Pair(SerializesTo("https://member1.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner0.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://owner0.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner0.test")), - net::SiteType::kPrimary))), + net::SiteType::kPrimary, absl::nullopt))), Pair(SerializesTo("https://new-member1.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner1.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://member2.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner1.test")), - net::SiteType::kAssociated))), + net::SiteType::kAssociated, absl::nullopt))), Pair(SerializesTo("https://owner1.test"), Optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://owner1.test")), - net::SiteType::kPrimary))))); + net::SiteType::kPrimary, absl::nullopt))))); } } // namespace content
diff --git a/content/browser/first_party_sets/first_party_sets_loader.cc b/content/browser/first_party_sets/first_party_sets_loader.cc index be17bddb..825048c 100644 --- a/content/browser/first_party_sets/first_party_sets_loader.cc +++ b/content/browser/first_party_sets/first_party_sets_loader.cc
@@ -42,14 +42,20 @@ const net::SchemefulSite& owner = *maybe_owner; std::vector<std::pair<net::SchemefulSite, net::FirstPartySetEntry>> sites( - {{owner, net::FirstPartySetEntry(owner, net::SiteType::kPrimary)}}); + {{owner, net::FirstPartySetEntry(owner, net::SiteType::kPrimary, + absl::nullopt)}}); + base::flat_set<net::SchemefulSite> associated_sites; for (auto it = origins.begin() + 1; it != origins.end(); ++it) { const absl::optional<net::SchemefulSite> maybe_member = content::FirstPartySetParser::CanonicalizeRegisteredDomain( *it, true /* emit_errors */); - if (maybe_member.has_value() && maybe_member != owner) + if (maybe_member.has_value() && maybe_member != owner && + !base::Contains(associated_sites, *maybe_member)) { sites.emplace_back(*maybe_member, net::FirstPartySetEntry( - owner, net::SiteType::kAssociated)); + owner, net::SiteType::kAssociated, + associated_sites.size())); + associated_sites.insert(*maybe_member); + } } if (sites.size() < 2) {
diff --git a/content/browser/first_party_sets/first_party_sets_loader_unittest.cc b/content/browser/first_party_sets/first_party_sets_loader_unittest.cc index 5a7b85f..ca23bbed 100644 --- a/content/browser/first_party_sets/first_party_sets_loader_unittest.cc +++ b/content/browser/first_party_sets/first_party_sets_loader_unittest.cc
@@ -98,11 +98,11 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://aaaa.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST_F(FirstPartySetsLoaderTest, AcceptsMultipleSets) { @@ -121,19 +121,19 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://foo.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST_F(FirstPartySetsLoaderTest, SetComponentSets_Idempotent) { @@ -156,19 +156,19 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://foo.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST_F(FirstPartySetsLoaderTest, OwnerIsOnlyMember) { @@ -263,11 +263,11 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST_F(FirstPartySetsLoaderTest, @@ -282,11 +282,11 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST_F(FirstPartySetsLoaderTest, SetsManuallySpecified_Valid_MultipleMembers) { @@ -300,15 +300,15 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 1)))); } TEST_F(FirstPartySetsLoaderTest, @@ -331,11 +331,11 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST_F(FirstPartySetsLoaderTest, SetsManuallySpecified_Valid_RepeatedMember) { @@ -351,15 +351,15 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 1)))); } TEST_F(FirstPartySetsLoaderTest, SetsManuallySpecified_DeduplicatesOwnerOwner) { @@ -375,23 +375,23 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 1)), Pair(SerializesTo("https://bar.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://bar.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member4.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://bar.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST_F(FirstPartySetsLoaderTest, @@ -408,23 +408,23 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://member3.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 1)), Pair(SerializesTo("https://bar.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://bar.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://bar.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST_F(FirstPartySetsLoaderTest, @@ -440,23 +440,23 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member3.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://foo.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 1)))); } TEST_F(FirstPartySetsLoaderTest, @@ -473,31 +473,31 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 1)), Pair(SerializesTo("https://foo.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member3.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 1)), Pair(SerializesTo("https://bar.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://bar.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member4.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://bar.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST_F(FirstPartySetsLoaderTest, @@ -516,11 +516,11 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } } // namespace content
diff --git a/content/browser/first_party_sets/test/first_party_set_parser_map_fuzzer.cc b/content/browser/first_party_sets/test/first_party_set_parser_map_fuzzer.cc index 08598d8..516e2c21 100644 --- a/content/browser/first_party_sets/test/first_party_set_parser_map_fuzzer.cc +++ b/content/browser/first_party_sets/test/first_party_set_parser_map_fuzzer.cc
@@ -11,6 +11,7 @@ #include "net/base/schemeful_site.h" #include "net/cookies/first_party_set_entry.h" #include "testing/libfuzzer/proto/lpm_interface.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace content { @@ -32,11 +33,16 @@ for (const firstpartysets::proto::SitePair& item : sets.items()) { auto member_or_owner = GetSchemefulSite(item.member_or_owner()); auto owner = GetSchemefulSite(item.owner()); - map.emplace( - std::move(member_or_owner), - net::FirstPartySetEntry(owner, member_or_owner == owner - ? net::SiteType::kPrimary - : net::SiteType::kAssociated)); + net::SiteType site_type = member_or_owner == owner + ? net::SiteType::kPrimary + : net::SiteType::kAssociated; + absl::optional<net::FirstPartySetEntry::SiteIndex> site_index = + site_type == net::SiteType::kPrimary + ? absl::nullopt + : absl::make_optional( + net::FirstPartySetEntry::SiteIndex(map.size())); + map.emplace(member_or_owner, + net::FirstPartySetEntry(owner, site_type, site_index)); } return map; }
diff --git a/content/browser/media/session/media_session_impl.cc b/content/browser/media/session/media_session_impl.cc index 6c7be7d..2096290 100644 --- a/content/browser/media/session/media_session_impl.cc +++ b/content/browser/media/session/media_session_impl.cc
@@ -7,12 +7,10 @@ #include <algorithm> #include <memory> #include <utility> -#include <vector> #include "base/bind.h" #include "base/containers/contains.h" #include "base/cxx17_backports.h" -#include "base/numerics/safe_conversions.h" #include "base/ranges/algorithm.h" #include "base/strings/string_util.h" #include "base/time/time.h" @@ -41,9 +39,7 @@ #include "services/media_session/public/mojom/audio_focus.mojom.h" #include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h" #include "third_party/blink/public/strings/grit/blink_strings.h" -#include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/favicon_size.h" -#include "ui/gfx/image/image_util.h" #if BUILDFLAG(IS_ANDROID) #include "content/browser/media/session/media_session_android.h" @@ -869,25 +865,17 @@ const GURL& image_url, const std::vector<SkBitmap>& bitmaps, const std::vector<gfx::Size>& sizes) { - DCHECK_EQ(bitmaps.size(), sizes.size()); - - std::vector<SkBitmap> filtered_images; - std::vector<gfx::Size> filtered_bitmap_sizes; - gfx::FilterAndResizeImagesForMaximalSize( - bitmaps, base::checked_cast<uint32_t>(desired_size_px), filtered_images, - filtered_bitmap_sizes); - DCHECK_EQ(filtered_images.size(), filtered_bitmap_sizes.size()); - + DCHECK(bitmaps.size() == sizes.size()); SkBitmap image; double best_image_score = 0.0; - // Rank |filtered_bitmap_sizes| and |filtered_images| using MediaImageManager. - for (size_t i = 0; i < filtered_images.size(); i++) { + // Rank |sizes| and |bitmaps| using MediaImageManager. + for (size_t i = 0; i < bitmaps.size(); i++) { double image_score = media_session::MediaImageManager::GetImageSizeScore( - minimum_size_px, desired_size_px, filtered_bitmap_sizes.at(i)); + minimum_size_px, desired_size_px, sizes.at(i)); if (image_score > best_image_score) - image = filtered_images.at(i); + image = bitmaps.at(i); } // If the image is the wrong color type then we should convert it. @@ -1334,7 +1322,7 @@ const gfx::Size preferred_size(desired_size_px, desired_size_px); web_contents()->DownloadImage( image.src, false /* is_favicon */, preferred_size, - /*max_bitmap_size=*/0, false /* bypass_cache */, + desired_size_px /* max_bitmap_size */, false /* bypass_cache */, base::BindOnce(&MediaSessionImpl::OnImageDownloadComplete, base::Unretained(this), mojo::WrapCallbackWithDefaultInvokeIfNotRun(
diff --git a/content/browser/notifications/platform_notification_context_impl.cc b/content/browser/notifications/platform_notification_context_impl.cc index 61ac1d77..fdd7485 100644 --- a/content/browser/notifications/platform_notification_context_impl.cc +++ b/content/browser/notifications/platform_notification_context_impl.cc
@@ -24,6 +24,7 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_database_data.h" #include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "content/public/browser/platform_notification_service.h" #include "content/public/common/content_client.h" #include "content/public/common/content_features.h" @@ -365,8 +366,11 @@ // Erase all valid origins so we're left with invalid ones. base::EraseIf(origins, [controller](const GURL& origin) { - auto permission = controller->GetPermissionStatusForOriginWithoutContext( - blink::PermissionType::NOTIFICATIONS, url::Origin::Create(origin)); + auto permission = controller + ->GetPermissionResultForOriginWithoutContext( + blink::PermissionType::NOTIFICATIONS, + url::Origin::Create(origin)) + .status; return permission == blink::mojom::PermissionStatus::GRANTED; });
diff --git a/content/browser/notifications/platform_notification_context_unittest.cc b/content/browser/notifications/platform_notification_context_unittest.cc index d080f61..c71967e 100644 --- a/content/browser/notifications/platform_notification_context_unittest.cc +++ b/content/browser/notifications/platform_notification_context_unittest.cc
@@ -19,6 +19,7 @@ #include "content/browser/service_worker/embedded_worker_test_helper.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/public/browser/notification_database_data.h" +#include "content/public/browser/permission_result.h" #include "content/public/common/content_client.h" #include "content/public/common/content_features.h" #include "content/public/test/browser_task_environment.h" @@ -210,10 +211,11 @@ void SetPermissionStatus(const GURL& origin, blink::mojom::PermissionStatus permission_status) { - ON_CALL(*permission_manager_, - GetPermissionStatus(blink::PermissionType::NOTIFICATIONS, origin, - origin)) - .WillByDefault(Return(permission_status)); + ON_CALL(*permission_manager_, GetPermissionResultForOriginWithoutContext( + blink::PermissionType::NOTIFICATIONS, + url::Origin::Create(origin))) + .WillByDefault(Return(content::PermissionResult( + permission_status, PermissionStatusSource::UNSPECIFIED))); } // Returns the file path to the leveldb database for |context|.
diff --git a/content/browser/payments/installed_payment_apps_finder_impl.cc b/content/browser/payments/installed_payment_apps_finder_impl.cc index 656ee65..05c2abf9 100644 --- a/content/browser/payments/installed_payment_apps_finder_impl.cc +++ b/content/browser/payments/installed_payment_apps_finder_impl.cc
@@ -14,6 +14,7 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "third_party/blink/public/common/permissions/permission_utils.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" @@ -78,10 +79,11 @@ PaymentApps permitted_apps; for (auto& app : apps) { GURL origin = app.second->scope.DeprecatedGetOriginAsURL(); - if (permission_controller->GetPermissionStatusForOriginWithoutContext( - blink::PermissionType::PAYMENT_HANDLER, - url::Origin::Create(origin)) == - blink::mojom::PermissionStatus::GRANTED) { + if (permission_controller + ->GetPermissionResultForOriginWithoutContext( + blink::PermissionType::PAYMENT_HANDLER, + url::Origin::Create(origin)) + .status == blink::mojom::PermissionStatus::GRANTED) { permitted_apps[app.first] = std::move(app.second); } }
diff --git a/content/browser/payments/payment_app_provider_impl_unittest.cc b/content/browser/payments/payment_app_provider_impl_unittest.cc index 281b16ec..48ee071 100644 --- a/content/browser/payments/payment_app_provider_impl_unittest.cc +++ b/content/browser/payments/payment_app_provider_impl_unittest.cc
@@ -73,10 +73,11 @@ std::unique_ptr<MockPermissionManager> mock_permission_manager( new testing::NiceMock<MockPermissionManager>()); ON_CALL(*mock_permission_manager, - GetPermissionStatus(blink::PermissionType::PAYMENT_HANDLER, - testing::_, testing::_)) - .WillByDefault( - testing::Return(blink::mojom::PermissionStatus::GRANTED)); + GetPermissionResultForOriginWithoutContext( + blink::PermissionType::PAYMENT_HANDLER, testing::_)) + .WillByDefault(testing::Return( + PermissionResult(blink::mojom::PermissionStatus::GRANTED, + PermissionStatusSource::UNSPECIFIED))); static_cast<TestBrowserContext*>(browser_context()) ->SetPermissionControllerDelegate(std::move(mock_permission_manager));
diff --git a/content/browser/permissions/permission_controller_impl.cc b/content/browser/permissions/permission_controller_impl.cc index 4f292be8..d8c23c0 100644 --- a/content/browser/permissions/permission_controller_impl.cc +++ b/content/browser/permissions/permission_controller_impl.cc
@@ -11,13 +11,12 @@ #include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/permission_controller_delegate.h" +#include "content/public/browser/permission_result.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "third_party/blink/public/common/permissions/permission_utils.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" -class GURL; - namespace content { namespace { @@ -167,9 +166,9 @@ url::Origin::Create(subscription.requesting_origin)); } - return DeprecatedGetPermissionStatus(subscription.permission, - subscription.requesting_origin, - subscription.embedding_origin); + return GetPermissionStatusInternal(subscription.permission, + subscription.requesting_origin, + subscription.embedding_origin); } PermissionControllerImpl::SubscriptionsStatusMap @@ -335,7 +334,7 @@ } blink::mojom::PermissionStatus -PermissionControllerImpl::DeprecatedGetPermissionStatus( +PermissionControllerImpl::GetPermissionStatusInternal( PermissionType permission, const GURL& requesting_origin, const GURL& embedding_origin) { @@ -349,6 +348,7 @@ browser_context_->GetPermissionControllerDelegate(); if (!delegate) return blink::mojom::PermissionStatus::DENIED; + return delegate->GetPermissionStatus(permission, requesting_origin, embedding_origin); } @@ -389,12 +389,52 @@ render_frame_host); } +PermissionResult +PermissionControllerImpl::GetPermissionResultForCurrentDocument( + PermissionType permission, + RenderFrameHost* render_frame_host) { + absl::optional<blink::mojom::PermissionStatus> status = + devtools_permission_overrides_.Get( + render_frame_host->GetLastCommittedOrigin(), permission); + if (status) + return PermissionResult(*status, PermissionStatusSource::UNSPECIFIED); + + PermissionControllerDelegate* delegate = + browser_context_->GetPermissionControllerDelegate(); + if (!delegate) + return PermissionResult(blink::mojom::PermissionStatus::DENIED, + PermissionStatusSource::UNSPECIFIED); + + return delegate->GetPermissionResultForCurrentDocument(permission, + render_frame_host); +} + +PermissionResult +PermissionControllerImpl::GetPermissionResultForOriginWithoutContext( + PermissionType permission, + const url::Origin& origin) { + absl::optional<blink::mojom::PermissionStatus> status = + devtools_permission_overrides_.Get(origin, permission); + if (status) + return PermissionResult(*status, PermissionStatusSource::UNSPECIFIED); + + PermissionControllerDelegate* delegate = + browser_context_->GetPermissionControllerDelegate(); + if (!delegate) + return PermissionResult(blink::mojom::PermissionStatus::DENIED, + PermissionStatusSource::UNSPECIFIED); + + return delegate->GetPermissionResultForOriginWithoutContext(permission, + origin); +} + blink::mojom::PermissionStatus PermissionControllerImpl::GetPermissionStatusForOriginWithoutContext( PermissionType permission, - const url::Origin& origin) { - return DeprecatedGetPermissionStatus(permission, origin.GetURL(), - origin.GetURL()); + const url::Origin& requesting_origin, + const url::Origin& embedding_origin) { + return GetPermissionStatusInternal(permission, requesting_origin.GetURL(), + embedding_origin.GetURL()); } void PermissionControllerImpl::ResetPermission(PermissionType permission,
diff --git a/content/browser/permissions/permission_controller_impl.h b/content/browser/permissions/permission_controller_impl.h index 613867c..b332fca 100644 --- a/content/browser/permissions/permission_controller_impl.h +++ b/content/browser/permissions/permission_controller_impl.h
@@ -23,6 +23,7 @@ class PermissionControllerImplTest; class RenderProcessHost; class PermissionServiceImpl; +struct PermissionResult; using blink::PermissionType; @@ -76,7 +77,7 @@ friend class PermissionControllerImplTest; friend class PermissionServiceImpl; - blink::mojom::PermissionStatus DeprecatedGetPermissionStatus( + blink::mojom::PermissionStatus GetPermissionStatusInternal( PermissionType permission, const GURL& requesting_origin, const GURL& embedding_origin); @@ -89,9 +90,16 @@ blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument( PermissionType permission, RenderFrameHost* render_frame_host) override; - blink::mojom::PermissionStatus GetPermissionStatusForOriginWithoutContext( + PermissionResult GetPermissionResultForCurrentDocument( + PermissionType permission, + RenderFrameHost* render_frame_host) override; + PermissionResult GetPermissionResultForOriginWithoutContext( PermissionType permission, const url::Origin& origin) override; + blink::mojom::PermissionStatus GetPermissionStatusForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& requesting_origin, + const url::Origin& embedding_origin) override; void RequestPermissionFromCurrentDocument( PermissionType permission, RenderFrameHost* render_frame_host,
diff --git a/content/browser/permissions/permission_service_impl.cc b/content/browser/permissions/permission_service_impl.cc index d2b12f7..956ce9b 100644 --- a/content/browser/permissions/permission_service_impl.cc +++ b/content/browser/permissions/permission_service_impl.cc
@@ -15,6 +15,7 @@ #include "content/browser/bad_message.h" #include "content/browser/permissions/permission_controller_impl.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/permission_result.h" #include "content/public/browser/render_frame_host.h" #include "third_party/blink/public/common/permissions/permission_utils.h" #include "third_party/blink/public/mojom/permissions/permission.mojom-shared.h" @@ -211,7 +212,8 @@ DCHECK(context_->GetEmbeddingOrigin().is_empty()); return browser_context->GetPermissionController() - ->GetPermissionStatusForOriginWithoutContext(type, origin_); + ->GetPermissionResultForOriginWithoutContext(type, origin_) + .status; } void PermissionServiceImpl::ResetPermissionStatus(blink::PermissionType type) {
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index e44c788..5e45adfa 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1386,7 +1386,7 @@ } bool RenderWidgetHostViewAura::GetCompositionCharacterBounds( - uint32_t index, + size_t index, gfx::Rect* rect) const { DCHECK(rect);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index eba15e73..f406646 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -223,7 +223,7 @@ bool CanComposeInline() const override; gfx::Rect GetCaretBounds() const override; gfx::Rect GetSelectionBoundingBox() const override; - bool GetCompositionCharacterBounds(uint32_t index, + bool GetCompositionCharacterBounds(size_t index, gfx::Rect* rect) const override; bool HasCompositionText() const override; ui::TextInputClient::FocusReason GetFocusReason() const override;
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index 9606e4c..d2275a3 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -101,6 +101,7 @@ #include "content/public/browser/login_delegate.h" #include "content/public/browser/network_service_instance.h" #include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "content/public/browser/service_process_host.h" #include "content/public/browser/session_storage_usage_info.h" #include "content/public/browser/shared_cors_origin_access_list.h" @@ -2037,10 +2038,10 @@ std::vector<url::Origin> origins_out; for (auto& origin : origins) { - bool allowed = - permission_controller->GetPermissionStatusForOriginWithoutContext( - blink::PermissionType::BACKGROUND_SYNC, origin) == - blink::mojom::PermissionStatus::GRANTED; + bool allowed = permission_controller + ->GetPermissionResultForOriginWithoutContext( + blink::PermissionType::BACKGROUND_SYNC, origin) + .status == blink::mojom::PermissionStatus::GRANTED; if (allowed) origins_out.push_back(origin); } @@ -2054,11 +2055,12 @@ DCHECK(initialized_); PermissionController* permission_controller = browser_context_->GetPermissionController(); - std::move(callback).Run( - permission_controller->GetPermissionStatusForOriginWithoutContext( - blink::PermissionType::BACKGROUND_SYNC, - url::Origin::Create(origin)) == - blink::mojom::PermissionStatus::GRANTED); + std::move(callback).Run(permission_controller + ->GetPermissionResultForOriginWithoutContext( + blink::PermissionType::BACKGROUND_SYNC, + url::Origin::Create(origin)) + .status == + blink::mojom::PermissionStatus::GRANTED); } void StoragePartitionImpl::OnClearSiteData(
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc index e7ccd06..4d57232 100644 --- a/content/browser/web_contents/web_contents_android.cc +++ b/content/browser/web_contents/web_contents_android.cc
@@ -20,8 +20,6 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/metrics/user_metrics.h" -#include "base/numerics/safe_conversions.h" -#include "base/task/thread_pool.h" #include "base/threading/scoped_blocking_call.h" #include "content/browser/android/java/gin_java_bridge_dispatcher_host.h" #include "content/browser/media/media_web_contents_observer.h" @@ -37,9 +35,7 @@ #include "content/public/browser/render_widget_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_switches.h" -#include "skia/ext/image_operations.h" #include "third_party/blink/public/mojom/input/input_handler.mojom-blink.h" -#include "third_party/skia/include/core/SkBitmap.h" #include "ui/accessibility/ax_assistant_structure.h" #include "ui/accessibility/ax_node_data.h" #include "ui/accessibility/ax_tree_update.h" @@ -49,7 +45,6 @@ #include "ui/gfx/android/java_bitmap.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" -#include "ui/gfx/image/image_util.h" #include "url/android/gurl_android.h" #include "url/gurl.h" @@ -726,19 +721,13 @@ jint max_bitmap_size, jboolean bypass_cache, const base::android::JavaParamRef<jobject>& jcallback) { - ScopedJavaGlobalRef<jobject> j_callback; - j_callback.Reset(env, jcallback); - // The max_image_size of 0 being passed to web_contents_->DownloadImage() - // ensures that all images are fetched by the renderer before being - // resized/filtered out in WebContentsAndroid::OnFinishDownloadImage() - // using the max_bitmap_size in a separate threadpool. const gfx::Size preferred_size; return web_contents_->DownloadImage( *url::GURLAndroid::ToNativeGURL(env, jurl), is_fav_icon, preferred_size, - /*max_image_size=*/0, bypass_cache, + max_bitmap_size, bypass_cache, base::BindOnce(&WebContentsAndroid::OnFinishDownloadImage, - weak_factory_.GetWeakPtr(), j_callback, - base::checked_cast<uint32_t>(max_bitmap_size))); + weak_factory_.GetWeakPtr(), obj_, + ScopedJavaGlobalRef<jobject>(env, jcallback))); } void WebContentsAndroid::SetHasPersistentVideo(JNIEnv* env, jboolean value) { @@ -782,45 +771,13 @@ } void WebContentsAndroid::OnFinishDownloadImage( - const base::android::ScopedJavaGlobalRef<jobject>& callback, - uint32_t max_image_size, - int id, - int http_status_code, - const GURL& url, - const std::vector<SkBitmap>& bitmaps, - const std::vector<gfx::Size>& sizes) { - std::vector<SkBitmap> filtered_images; - std::vector<gfx::Size> filtered_bitmap_sizes; - - base::ThreadPool::PostTaskAndReply( - FROM_HERE, {base::TaskPriority::USER_VISIBLE}, - base::BindOnce(&WebContentsAndroid::FilterOrResizeReceivedImages, - weak_factory_.GetWeakPtr(), bitmaps, max_image_size, - std::ref(filtered_images), - std::ref(filtered_bitmap_sizes)), - base::BindOnce(&WebContentsAndroid::ConvertToJavaBitmap, - weak_factory_.GetWeakPtr(), obj_, callback, id, - http_status_code, url, filtered_images, - filtered_bitmap_sizes)); -} - -void WebContentsAndroid::FilterOrResizeReceivedImages( - const std::vector<SkBitmap>& bitmaps, - uint32_t max_image_size, - std::vector<SkBitmap>& filtered_images, - std::vector<gfx::Size>& filtered_bitmap_sizes) { - gfx::FilterAndResizeImagesForMaximalSize( - bitmaps, max_image_size, filtered_images, filtered_bitmap_sizes); -} - -void WebContentsAndroid::ConvertToJavaBitmap( const JavaRef<jobject>& obj, const JavaRef<jobject>& callback, int id, int http_status_code, const GURL& url, - const std::vector<SkBitmap>& filtered_images, - const std::vector<gfx::Size>& filtered_bitmap_sizes) { + const std::vector<SkBitmap>& bitmaps, + const std::vector<gfx::Size>& sizes) { JNIEnv* env = base::android::AttachCurrentThread(); ScopedJavaLocalRef<jobject> jbitmaps = Java_WebContentsImpl_createBitmapList(env); @@ -828,15 +785,14 @@ Java_WebContentsImpl_createSizeList(env); ScopedJavaLocalRef<jobject> jurl = url::GURLAndroid::FromNativeGURL(env, url); - DCHECK_EQ(filtered_images.size(), filtered_bitmap_sizes.size()); - for (const SkBitmap& bitmap : filtered_images) { - // WARNING: converting to java bitmaps results in duplicate memory + for (const SkBitmap& bitmap : bitmaps) { + // WARNING: convering to java bitmaps results in duplicate memory // allocations, which increases the chance of OOMs if DownloadImage() is // misused. ScopedJavaLocalRef<jobject> jbitmap = gfx::ConvertToJavaBitmap(bitmap); Java_WebContentsImpl_addToBitmapList(env, jbitmaps, jbitmap); } - for (const gfx::Size& size : filtered_bitmap_sizes) { + for (const gfx::Size& size : sizes) { Java_WebContentsImpl_createSizeAndAddToList(env, jsizes, size.width(), size.height()); }
diff --git a/content/browser/web_contents/web_contents_android.h b/content/browser/web_contents/web_contents_android.h index f28c0d19..2b278693 100644 --- a/content/browser/web_contents/web_contents_android.h +++ b/content/browser/web_contents/web_contents_android.h
@@ -215,26 +215,13 @@ void RemoveDestructionObserver(DestructionObserver* observer); private: - void OnFinishDownloadImage( - const base::android::ScopedJavaGlobalRef<jobject>& jcallback, - uint32_t max_image_size, - int id, - int http_status_code, - const GURL& url, - const std::vector<SkBitmap>& bitmaps, - const std::vector<gfx::Size>& sizes); - void FilterOrResizeReceivedImages( - const std::vector<SkBitmap>& bitmaps, - uint32_t max_image_size, - std::vector<SkBitmap>& filtered_images, - std::vector<gfx::Size>& filtered_bitmap_sizes); - void ConvertToJavaBitmap(const base::android::JavaRef<jobject>& obj, - const base::android::JavaRef<jobject>& callback, - int id, - int http_status_code, - const GURL& url, - const std::vector<SkBitmap>& filtered_images, - const std::vector<gfx::Size>& filtered_bitmap_sizes); + void OnFinishDownloadImage(const base::android::JavaRef<jobject>& obj, + const base::android::JavaRef<jobject>& callback, + int id, + int http_status_code, + const GURL& url, + const std::vector<SkBitmap>& bitmaps, + const std::vector<gfx::Size>& sizes); void SelectAroundCaretAck(blink::mojom::SelectAroundCaretResultPtr result); // Walks over the AXTreeUpdate and creates a light weight snapshot. void AXTreeSnapshotCallback(
diff --git a/content/browser/webid/fedcm_metrics.h b/content/browser/webid/fedcm_metrics.h index 6352cae..1390216d 100644 --- a/content/browser/webid/fedcm_metrics.h +++ b/content/browser/webid/fedcm_metrics.h
@@ -38,7 +38,7 @@ kIdTokenHttpNotFound, kIdTokenNoResponse, kIdTokenInvalidResponse, - kIdTokenInvalidRequest, + kIdTokenInvalidRequest, // obsolete kClientMetadataMissingPrivacyPolicyUrl, // obsolete kThirdPartyCookiesBlocked, kDisabledInSettings,
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc index 9978e42..f083a85 100644 --- a/content/browser/webid/federated_auth_request_impl.cc +++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -35,6 +35,8 @@ #include "url/url_constants.h" using blink::mojom::FederatedAuthRequestResult; +using blink::mojom::IdentityProvider; +using blink::mojom::IdentityProviderPtr; using blink::mojom::LogoutRpsStatus; using blink::mojom::RequestTokenStatus; using FederatedApiPermissionStatus = @@ -158,9 +160,6 @@ case FederatedAuthRequestResult::kErrorFetchingIdTokenInvalidResponse: { return "Provider's token is invalid."; } - case FederatedAuthRequestResult::kErrorFetchingIdTokenInvalidRequest: { - return "The id token fetching request is invalid."; - } case FederatedAuthRequestResult::kErrorCanceled: { return "The request has been aborted."; } @@ -210,7 +209,6 @@ case FederatedAuthRequestResult::kErrorFetchingIdTokenHttpNotFound: case FederatedAuthRequestResult::kErrorFetchingIdTokenNoResponse: case FederatedAuthRequestResult::kErrorFetchingIdTokenInvalidResponse: - case FederatedAuthRequestResult::kErrorFetchingIdTokenInvalidRequest: case FederatedAuthRequestResult::kError: { return RequestTokenStatus::kError; } @@ -292,11 +290,10 @@ sharing_permission_context, std::move(receiver)); } -void FederatedAuthRequestImpl::RequestToken(const GURL& provider, - const std::string& client_id, - const std::string& nonce, - bool prefer_auto_sign_in, - RequestTokenCallback callback) { +void FederatedAuthRequestImpl::RequestToken( + IdentityProviderPtr identity_provider_ptr, + bool prefer_auto_sign_in, + RequestTokenCallback callback) { if (HasPendingRequest()) { fedcm_metrics_->RecordRequestTokenStatus(TokenStatus::kTooManyRequests); std::move(callback).Run(RequestTokenStatus::kErrorTooManyRequests, ""); @@ -304,20 +301,20 @@ } auth_request_callback_ = std::move(callback); - provider_ = provider; // Generate a random int for the FedCM call, to be used by the UKM events. std::random_device dev; std::mt19937 rng(dev()); std::uniform_int_distribution<std::mt19937::result_type> uniform_dist( 1, 1 << 30); + // TODO(crbug.com/1307709): Handle FedCmMetrics for multiple IDPs. fedcm_metrics_ = std::make_unique<FedCmMetrics>( - provider_, render_frame_host().GetPageUkmSourceId(), uniform_dist(rng)); - client_id_ = client_id; - nonce_ = nonce; + identity_provider_ptr->config_url, + render_frame_host().GetPageUkmSourceId(), uniform_dist(rng)); prefer_auto_sign_in_ = prefer_auto_sign_in && IsFedCmAutoSigninEnabled(); start_time_ = base::TimeTicks::Now(); - network_manager_ = CreateNetworkManager(provider); + // TODO(crbug.com/1307709): Handle network managers for multiple IDPs. + network_manager_ = CreateNetworkManager(identity_provider_ptr->config_url); if (!network_manager_) { fedcm_metrics_->RecordRequestTokenStatus(TokenStatus::kNoNetworkManager); // TODO(yigu): this is due to provider url being non-secure. We should @@ -365,7 +362,7 @@ request_dialog_controller_ = CreateDialogController(); - FetchManifest(); + FetchManifest(std::move(identity_provider_ptr)); } void FederatedAuthRequestImpl::CancelTokenRequest() { @@ -442,19 +439,25 @@ return auth_request_callback_ || logout_callback_; } -GURL FederatedAuthRequestImpl::ResolveManifestUrl(const std::string& endpoint) { +GURL FederatedAuthRequestImpl::ResolveManifestUrl( + const IdentityProvider& identity_provider, + const std::string& endpoint) { if (endpoint.empty()) return GURL(); - GURL manifest_url = - provider_.Resolve(IdpNetworkRequestManager::kManifestFilePath); + GURL manifest_url = identity_provider.config_url.Resolve( + IdpNetworkRequestManager::kManifestFilePath); return manifest_url.Resolve(endpoint); } -bool FederatedAuthRequestImpl::IsEndpointUrlValid(const GURL& endpoint_url) { - return url::Origin::Create(provider_).IsSameOriginWith(endpoint_url); +bool FederatedAuthRequestImpl::IsEndpointUrlValid( + const IdentityProvider& identity_provider, + const GURL& endpoint_url) { + return url::Origin::Create(identity_provider.config_url) + .IsSameOriginWith(endpoint_url); } -void FederatedAuthRequestImpl::FetchManifest() { +void FederatedAuthRequestImpl::FetchManifest( + IdentityProviderPtr identity_provider_ptr) { absl::optional<int> icon_ideal_size = absl::nullopt; absl::optional<int> icon_minimum_size = absl::nullopt; if (request_dialog_controller_) { @@ -464,10 +467,10 @@ IdpNetworkRequestManager::FetchManifestCallback manifest_callback = base::BindOnce(&FederatedAuthRequestImpl::OnManifestFetched, - weak_ptr_factory_.GetWeakPtr()); + weak_ptr_factory_.GetWeakPtr(), *identity_provider_ptr); IdpNetworkRequestManager::FetchManifestListCallback manifest_list_callback = base::BindOnce(&FederatedAuthRequestImpl::OnManifestListFetched, - weak_ptr_factory_.GetWeakPtr()); + weak_ptr_factory_.GetWeakPtr(), *identity_provider_ptr); if (IsFedCmManifestValidationEnabled()) { network_manager_->FetchManifestList(std::move(manifest_list_callback)); @@ -485,6 +488,7 @@ } void FederatedAuthRequestImpl::OnManifestListFetched( + const IdentityProvider& identity_provider, IdpNetworkRequestManager::FetchStatus status, const std::set<GURL>& urls) { switch (status) { @@ -514,10 +518,6 @@ /*should_delay_callback=*/true); return; } - case IdpNetworkRequestManager::FetchStatus::kInvalidRequestError: { - NOTREACHED(); - return; - } case IdpNetworkRequestManager::FetchStatus::kSuccess: { // Intentional fall-through. } @@ -545,7 +545,7 @@ // "https://foo.idp.example/fedcm.json" // ] // } - bool provider_url_is_valid = (urls.count(provider_) != 0); + bool provider_url_is_valid = (urls.count(identity_provider.config_url) != 0); if (!provider_url_is_valid) { fedcm_metrics_->RecordRequestTokenStatus( @@ -557,10 +557,11 @@ manifest_list_checked_ = true; if (idp_metadata_) - OnManifestReady(*idp_metadata_); + OnManifestReady(identity_provider, *idp_metadata_); } void FederatedAuthRequestImpl::OnManifestFetched( + const IdentityProvider& identity_provider, IdpNetworkRequestManager::FetchStatus status, IdpNetworkRequestManager::Endpoints endpoints, IdentityProviderMetadata idp_metadata) { @@ -589,28 +590,28 @@ /*should_delay_callback=*/true); return; } - case IdpNetworkRequestManager::FetchStatus::kInvalidRequestError: { - NOTREACHED(); - return; - } case IdpNetworkRequestManager::FetchStatus::kSuccess: { // Intentional fall-through. } } - endpoints_.token = ResolveManifestUrl(endpoints.token); - endpoints_.accounts = ResolveManifestUrl(endpoints.accounts); - endpoints_.client_metadata = ResolveManifestUrl(endpoints.client_metadata); + endpoints_.token = ResolveManifestUrl(identity_provider, endpoints.token); + endpoints_.accounts = + ResolveManifestUrl(identity_provider, endpoints.accounts); + endpoints_.client_metadata = + ResolveManifestUrl(identity_provider, endpoints.client_metadata); idp_metadata_ = idp_metadata; if (manifest_list_checked_) - OnManifestReady(idp_metadata); + OnManifestReady(identity_provider, idp_metadata); } void FederatedAuthRequestImpl::OnManifestReady( + const IdentityProvider& identity_provider, IdentityProviderMetadata idp_metadata) { - bool is_token_valid = IsEndpointUrlValid(endpoints_.token); - bool is_accounts_valid = IsEndpointUrlValid(endpoints_.accounts); + bool is_token_valid = IsEndpointUrlValid(identity_provider, endpoints_.token); + bool is_accounts_valid = + IsEndpointUrlValid(identity_provider, endpoints_.accounts); if (!is_token_valid || !is_accounts_valid) { std::string message = "Manifest is missing or has an invalid URL for the following " @@ -630,22 +631,24 @@ /*should_delay_callback=*/true); return; } - if (IsEndpointUrlValid(endpoints_.client_metadata)) { + if (IsEndpointUrlValid(identity_provider, endpoints_.client_metadata)) { network_manager_->FetchClientMetadata( - endpoints_.client_metadata, client_id_, + endpoints_.client_metadata, identity_provider.client_id, base::BindOnce( &FederatedAuthRequestImpl::OnClientMetadataResponseReceived, - weak_ptr_factory_.GetWeakPtr(), std::move(idp_metadata))); + weak_ptr_factory_.GetWeakPtr(), identity_provider, + std::move(idp_metadata))); } else { network_manager_->SendAccountsRequest( - endpoints_.accounts, client_id_, + endpoints_.accounts, identity_provider.client_id, base::BindOnce(&FederatedAuthRequestImpl::OnAccountsResponseReceived, - weak_ptr_factory_.GetWeakPtr(), + weak_ptr_factory_.GetWeakPtr(), identity_provider, std::move(idp_metadata))); } } void FederatedAuthRequestImpl::OnClientMetadataResponseReceived( + const IdentityProvider& identity_provider, IdentityProviderMetadata idp_metadata, IdpNetworkRequestManager::FetchStatus status, IdpNetworkRequestManager::ClientMetadata data) { @@ -653,12 +656,14 @@ // console logs. client_metadata_ = data; network_manager_->SendAccountsRequest( - endpoints_.accounts, client_id_, + endpoints_.accounts, identity_provider.client_id, base::BindOnce(&FederatedAuthRequestImpl::OnAccountsResponseReceived, - weak_ptr_factory_.GetWeakPtr(), std::move(idp_metadata))); + weak_ptr_factory_.GetWeakPtr(), identity_provider, + std::move(idp_metadata))); } void FederatedAuthRequestImpl::OnAccountsResponseReceived( + const IdentityProvider& identity_provider, IdentityProviderMetadata idp_metadata, IdpNetworkRequestManager::FetchStatus status, IdpNetworkRequestManager::AccountList accounts) { @@ -705,7 +710,7 @@ WebContents* rp_web_contents = WebContents::FromRenderFrameHost(&render_frame_host()); - ComputeLoginStateAndReorderAccounts(accounts); + ComputeLoginStateAndReorderAccounts(identity_provider, accounts); bool screen_reader_is_on = rp_web_contents->GetAccessibilityMode().has_mode( @@ -726,21 +731,19 @@ start_time_); request_dialog_controller_->ShowAccountsDialog( - rp_web_contents, provider_, accounts, idp_metadata, data, - is_auto_sign_in ? SignInMode::kAuto : SignInMode::kExplicit, + rp_web_contents, identity_provider.config_url, accounts, idp_metadata, + data, is_auto_sign_in ? SignInMode::kAuto : SignInMode::kExplicit, base::BindOnce(&FederatedAuthRequestImpl::OnAccountSelected, - weak_ptr_factory_.GetWeakPtr()), + weak_ptr_factory_.GetWeakPtr(), identity_provider), base::BindOnce(&FederatedAuthRequestImpl::OnDialogDismissed, weak_ptr_factory_.GetWeakPtr())); return; } - case IdpNetworkRequestManager::FetchStatus::kInvalidRequestError: { - NOTREACHED(); - } } } void FederatedAuthRequestImpl::ComputeLoginStateAndReorderAccounts( + const IdentityProvider& identity_provider, IdpNetworkRequestManager::AccountList& accounts) { // Populate the accounts login state. for (auto& account : accounts) { @@ -748,7 +751,8 @@ bool idp_claimed_sign_in = account.login_state == LoginState::kSignIn; bool browser_observed_sign_in = sharing_permission_delegate_->HasSharingPermission( - origin(), url::Origin::Create(provider_), account.id); + origin(), url::Origin::Create(identity_provider.config_url), + account.id); if (idp_claimed_sign_in == browser_observed_sign_in) { fedcm_metrics_->RecordSignInStateMatchStatus( @@ -784,8 +788,10 @@ }); } -void FederatedAuthRequestImpl::OnAccountSelected(const std::string& account_id, - bool is_sign_in) { +void FederatedAuthRequestImpl::OnAccountSelected( + const IdentityProvider& identity_provider, + const std::string& account_id, + bool is_sign_in) { DCHECK(!account_id.empty()); // Check if the user has disabled the FedCM API after the FedCM UI is @@ -813,10 +819,11 @@ network_manager_->SendTokenRequest( endpoints_.token, account_id_, - ComputeUrlEncodedTokenPostData(client_id_, nonce_, account_id, + ComputeUrlEncodedTokenPostData(identity_provider.client_id, + identity_provider.nonce, account_id, is_sign_in), base::BindOnce(&FederatedAuthRequestImpl::OnTokenResponseReceived, - weak_ptr_factory_.GetWeakPtr())); + weak_ptr_factory_.GetWeakPtr(), identity_provider)); } void FederatedAuthRequestImpl::OnDialogDismissed( @@ -854,6 +861,7 @@ } void FederatedAuthRequestImpl::OnTokenResponseReceived( + const IdentityProvider& identity_provider, IdpNetworkRequestManager::FetchStatus status, const std::string& id_token) { if (!auth_request_callback_) @@ -867,18 +875,20 @@ base::TimeDelta fetch_time = token_response_time_ - select_account_time_; if (ShouldCompleteRequestImmediately() || fetch_time >= token_request_delay_) { - CompleteTokenRequest(status, id_token); + CompleteTokenRequest(identity_provider, status, id_token); return; } base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::BindOnce(&FederatedAuthRequestImpl::CompleteTokenRequest, - weak_ptr_factory_.GetWeakPtr(), status, id_token), + weak_ptr_factory_.GetWeakPtr(), identity_provider, status, + id_token), token_request_delay_ - fetch_time); } void FederatedAuthRequestImpl::CompleteTokenRequest( + const IdentityProvider& identity_provider, IdpNetworkRequestManager::FetchStatus status, const std::string& token) { DCHECK(!start_time_.is_null()); @@ -898,14 +908,6 @@ /*should_delay_callback=*/true); return; } - case IdpNetworkRequestManager::FetchStatus::kInvalidRequestError: { - fedcm_metrics_->RecordRequestTokenStatus( - TokenStatus::kIdTokenInvalidRequest); - CompleteRequest( - FederatedAuthRequestResult::kErrorFetchingIdTokenInvalidRequest, "", - /*should_delay_callback=*/true); - return; - } case IdpNetworkRequestManager::FetchStatus::kInvalidResponseError: { fedcm_metrics_->RecordRequestTokenStatus( TokenStatus::kIdTokenInvalidResponse); @@ -929,10 +931,12 @@ // https://crbug.com/1199088 CHECK(!account_id_.empty()); sharing_permission_delegate_->GrantSharingPermission( - origin(), url::Origin::Create(provider_), account_id_); + origin(), url::Origin::Create(identity_provider.config_url), + account_id_); active_session_permission_delegate_->GrantActiveSession( - origin(), url::Origin::Create(provider_), account_id_); + origin(), url::Origin::Create(identity_provider.config_url), + account_id_); fedcm_metrics_->RecordTokenResponseAndTurnaroundTime( token_response_time_ - select_account_time_,
diff --git a/content/browser/webid/federated_auth_request_impl.h b/content/browser/webid/federated_auth_request_impl.h index 97b2f9c1..ea80961 100644 --- a/content/browser/webid/federated_auth_request_impl.h +++ b/content/browser/webid/federated_auth_request_impl.h
@@ -56,9 +56,7 @@ ~FederatedAuthRequestImpl() override; // blink::mojom::FederatedAuthRequest: - void RequestToken(const GURL& provider, - const std::string& client_id, - const std::string& nonce, + void RequestToken(blink::mojom::IdentityProviderPtr identity_provider_ptr, bool prefer_auto_sign_in, RequestTokenCallback) override; void CancelTokenRequest() override; @@ -85,34 +83,52 @@ mojo::PendingReceiver<blink::mojom::FederatedAuthRequest>); bool HasPendingRequest() const; - GURL ResolveManifestUrl(const std::string& url); + GURL ResolveManifestUrl( + const blink::mojom::IdentityProvider& identity_provider, + const std::string& url); // Checks validity of the passed-in endpoint URL origin. - bool IsEndpointUrlValid(const GURL& endpoint_url); + bool IsEndpointUrlValid( + const blink::mojom::IdentityProvider& identity_provider, + const GURL& endpoint_url); - void FetchManifest(); - void OnManifestListFetched(IdpNetworkRequestManager::FetchStatus status, - const std::set<GURL>& urls); - void OnManifestFetched(IdpNetworkRequestManager::FetchStatus status, - IdpNetworkRequestManager::Endpoints, - IdentityProviderMetadata idp_metadata); - void OnManifestReady(IdentityProviderMetadata idp_metadata); + void FetchManifest(blink::mojom::IdentityProviderPtr identity_provider_ptr); + void OnManifestListFetched( + const blink::mojom::IdentityProvider& identity_provider, + IdpNetworkRequestManager::FetchStatus status, + const std::set<GURL>& urls); + void OnManifestFetched( + const blink::mojom::IdentityProvider& identity_provider, + IdpNetworkRequestManager::FetchStatus status, + IdpNetworkRequestManager::Endpoints, + IdentityProviderMetadata idp_metadata); + void OnManifestReady(const blink::mojom::IdentityProvider& identity_provider, + IdentityProviderMetadata idp_metadata); void OnClientMetadataResponseReceived( + const blink::mojom::IdentityProvider& identity_provider, IdentityProviderMetadata idp_metadata, IdpNetworkRequestManager::FetchStatus status, IdpNetworkRequestManager::ClientMetadata data); void OnAccountsResponseReceived( + const blink::mojom::IdentityProvider& identity_provider, IdentityProviderMetadata idp_metadata, IdpNetworkRequestManager::FetchStatus status, IdpNetworkRequestManager::AccountList accounts); - void OnAccountSelected(const std::string& account_id, bool is_sign_in); + void OnAccountSelected( + const blink::mojom::IdentityProvider& identity_provider, + const std::string& account_id, + bool is_sign_in); void OnDialogDismissed( IdentityRequestDialogController::DismissReason dismiss_reason); - void CompleteTokenRequest(IdpNetworkRequestManager::FetchStatus status, - const std::string& token); - void OnTokenResponseReceived(IdpNetworkRequestManager::FetchStatus status, - const std::string& token); + void CompleteTokenRequest( + const blink::mojom::IdentityProvider& identity_provider, + IdpNetworkRequestManager::FetchStatus status, + const std::string& token); + void OnTokenResponseReceived( + const blink::mojom::IdentityProvider& identity_provider, + IdpNetworkRequestManager::FetchStatus status, + const std::string& token); void DispatchOneLogout(); void OnLogoutCompleted(); void CompleteRequest(blink::mojom::FederatedAuthRequestResult, @@ -146,6 +162,7 @@ // reorders accounts so that those that are considered returning users are // before users that are not returning. void ComputeLoginStateAndReorderAccounts( + const blink::mojom::IdentityProvider& identity_provider, IdpNetworkRequestManager::AccountList& accounts); std::unique_ptr<IdpNetworkRequestManager> network_manager_; @@ -159,19 +176,6 @@ // RequestToken() method, so all metrics must be recorded after that. std::unique_ptr<FedCmMetrics> fedcm_metrics_; - // Parameters of auth request. - GURL provider_; - - // The federated auth request parameters provided by RP. Note that these - // parameters will uniquely identify the users so they should only be passed - // to IDP after user permission has been granted. - // - // TODO(majidvp): Implement a mechanism (e.g., a getter) that checks the - // request permission is granted before providing access to this parameter - // this way we avoid accidentally sharing these values. - std::string client_id_; - std::string nonce_; - bool prefer_auto_sign_in_; // Fetched from the IDP FedCM manifest configuration.
diff --git a/content/browser/webid/federated_auth_request_impl_unittest.cc b/content/browser/webid/federated_auth_request_impl_unittest.cc index f965526..f1d892d 100644 --- a/content/browser/webid/federated_auth_request_impl_unittest.cc +++ b/content/browser/webid/federated_auth_request_impl_unittest.cc
@@ -686,7 +686,10 @@ const std::string& nonce, bool prefer_auto_sign_in, bool wait_for_callback) { - request_remote_->RequestToken(provider, client_id, nonce, + blink::mojom::IdentityProviderPtr identity_provider = + blink::mojom::IdentityProvider::New(provider, client_id, nonce); + + request_remote_->RequestToken(std::move(identity_provider), prefer_auto_sign_in, auth_helper_.callback()); if (wait_for_callback) @@ -868,8 +871,10 @@ } void ComputeLoginStateAndReorderAccounts( + const blink::mojom::IdentityProvider& identity_provider, IdpNetworkRequestManager::AccountList& accounts) { - federated_auth_request_impl_->ComputeLoginStateAndReorderAccounts(accounts); + federated_auth_request_impl_->ComputeLoginStateAndReorderAccounts( + identity_provider, accounts); } protected: @@ -2018,7 +2023,10 @@ kConfigurationValid); AccountList multiple_accounts = kMultipleAccounts; - ComputeLoginStateAndReorderAccounts(multiple_accounts); + blink::mojom::IdentityProviderPtr identity_provider = + blink::mojom::IdentityProvider::New(GURL(kProviderUrlFull), kClientId, + kNonce); + ComputeLoginStateAndReorderAccounts(*identity_provider, multiple_accounts); // Check the account order using the account ids. ASSERT_EQ(multiple_accounts.size(), 3u);
diff --git a/content/browser/webid/idp_network_request_manager.cc b/content/browser/webid/idp_network_request_manager.cc index 18c82a41..0841ba4 100644 --- a/content/browser/webid/idp_network_request_manager.cc +++ b/content/browser/webid/idp_network_request_manager.cc
@@ -631,11 +631,6 @@ const std::string& account, const std::string& url_encoded_post_data, TokenRequestCallback callback) { - if (url_encoded_post_data.empty()) { - std::move(callback).Run(FetchStatus::kInvalidRequestError, std::string()); - return; - } - std::unique_ptr<network::SimpleURLLoader> url_loader = CreateCredentialedUrlLoader(token_url, /* send_referrer= */ true,
diff --git a/content/browser/webid/idp_network_request_manager.h b/content/browser/webid/idp_network_request_manager.h index 3b61f29..ab50ba8 100644 --- a/content/browser/webid/idp_network_request_manager.h +++ b/content/browser/webid/idp_network_request_manager.h
@@ -67,7 +67,6 @@ kHttpNotFoundError, kNoResponseError, kInvalidResponseError, - kInvalidRequestError, }; enum class LogoutResponse {
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index af20f26..ea54b3c 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -219,6 +219,8 @@ {wf::EnableDocumentPolicy, features::kDocumentPolicy}, {wf::EnableDocumentPolicyNegotiation, features::kDocumentPolicyNegotiation}, {wf::EnableFedCm, features::kFedCm, kSetOnlyIfOverridden}, + {wf::EnableFedCmMultipleIdentityProviders, + features::kFedCmMultipleIdentityProviders, kDefault}, {wf::EnableFencedFrames, features::kPrivacySandboxAdsAPIsOverride, kSetOnlyIfOverridden}, {wf::EnableSharedStorageAPI, features::kPrivacySandboxAdsAPIsOverride,
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 40b7166..b2f7ce1 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -147,6 +147,7 @@ "//build/android:build_java", "//components/download/public/common:public_java", "//components/payments/mojom:mojom_java", + "//content/public/common:common_java", "//content/public/common:trust_tokens_mojo_bindings_java", "//device/bluetooth:java", "//device/gamepad:java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java index cb531379..1748f358 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java
@@ -44,6 +44,7 @@ import org.chromium.content_public.browser.ChildProcessImportance; import org.chromium.content_public.browser.ContentFeatureList; import org.chromium.content_public.browser.UiThreadTaskTraits; +import org.chromium.content_public.common.ContentFeatures; import org.chromium.content_public.common.ContentSwitches; import java.io.IOException; @@ -78,6 +79,12 @@ // To be conservative, only delay removing binding in the initial second of the process. private static final int TIMEOUT_FOR_DELAY_BINDING_REMOVE_MS = 1000; + // Delay after app is background before reducing process priority. + private static final int REDUCE_PRIORITY_ON_BACKGROUND_DELAY_MS = 9 * 1000; + + private static final Runnable sDelayedBackgroundTask = + ChildProcessLauncherHelperImpl::onSentToBackgroundOnLauncherThreadAfterDelay; + // Flag to check if ServiceGroupImportance should be enabled after native is initialized. private static boolean sCheckedServiceGroupImportance; @@ -102,12 +109,16 @@ private static ChildConnectionAllocator.ConnectionFactory sSandboxedServiceFactoryForTesting; private static int sSandboxedServicesCountForTesting = -1; private static String sSandboxedServicesNameForTesting; + private static boolean sSkipDelayForReducePriorityOnBackgroundForTesting; private static BindingManager sBindingManager; // Whether the main application is currently brought to the foreground. private static boolean sApplicationInForegroundOnUiThread; + // Set on UI thread only, but null-checked on launcher thread as well. + private static ApplicationStatus.ApplicationStateListener sAppStateListener; + // TODO(boliu): These are only set for sandboxed renderer processes. Generalize them for // all types of processes. private final ChildProcessRanking mRanking; @@ -116,6 +127,9 @@ // Whether the created process should be sandboxed. private final boolean mSandboxed; + // Remove strong binding when app is in background. + private final boolean mReducePriorityOnBackground; + // The type of process as determined by the command line. private final String mProcessType; @@ -188,6 +202,10 @@ if (mSandboxed) { ChildProcessConnectionMetrics.getInstance().addConnection(connection); } + if (mReducePriorityOnBackground + && !ApplicationStatus.hasVisibleActivities()) { + reducePriorityOnBackgroundOnLauncherThread(); + } } // Tell native launch result (whether getPid is 0). @@ -342,6 +360,8 @@ private @ChildProcessImportance int mEffectiveImportance = ChildProcessImportance.MODERATE; private boolean mVisible; + private boolean mDroppedStrongBingingDueToBackgrounding; + // Protects fields below that are accessed on client thread as well. private final Object mLock = new Object(); private int mReverseRankWhenConnectionLost; @@ -378,9 +398,12 @@ commandLine[commandLine.length - 1] = TRACE_EARLY_JAVA_IN_CHILD_SWITCH; } boolean sandboxed = true; + boolean reducePriorityOnBackground = false; if (!ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) { if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) { sandboxed = false; + reducePriorityOnBackground = ContentFeatureList.isEnabled( + ContentFeatures.REDUCE_GPU_PRIORITY_ON_BACKGROUND); } else { // We only support sandboxed utility processes now. assert ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType); @@ -397,7 +420,8 @@ : null; ChildProcessLauncherHelperImpl helper = new ChildProcessLauncherHelperImpl(nativePointer, - commandLine, filesToBeMapped, sandboxed, canUseWarmUpConnection, binderCallback); + commandLine, filesToBeMapped, sandboxed, reducePriorityOnBackground, + canUseWarmUpConnection, binderCallback); helper.start(); if (sandboxed && !sCheckedServiceGroupImportance) { @@ -459,39 +483,57 @@ ChildProcessConnectionMetrics.getInstance().setBindingManager(sBindingManager); } }); - - sApplicationInForegroundOnUiThread = ApplicationStatus.getStateForApplication() - == ApplicationState.HAS_RUNNING_ACTIVITIES - || ApplicationStatus.getStateForApplication() - == ApplicationState.HAS_PAUSED_ACTIVITIES; - - ApplicationStatus.registerApplicationStateListener(newState -> { - switch (newState) { - case ApplicationState.UNKNOWN: - break; - case ApplicationState.HAS_RUNNING_ACTIVITIES: - case ApplicationState.HAS_PAUSED_ACTIVITIES: - if (!sApplicationInForegroundOnUiThread) onBroughtToForeground(); - break; - default: - if (sApplicationInForegroundOnUiThread) onSentToBackground(); - break; - } - }); } private static void onSentToBackground() { assert ThreadUtils.runningOnUiThread(); sApplicationInForegroundOnUiThread = false; + int delay = sSkipDelayForReducePriorityOnBackgroundForTesting + ? 0 + : REDUCE_PRIORITY_ON_BACKGROUND_DELAY_MS; + LauncherThread.postDelayed(sDelayedBackgroundTask, delay); LauncherThread.post(() -> { if (sBindingManager != null) sBindingManager.onSentToBackground(); }); } + private static void onSentToBackgroundOnLauncherThreadAfterDelay() { + assert LauncherThread.runningOnLauncherThread(); + for (ChildProcessLauncherHelperImpl helper : sLauncherByPid.values()) { + if (!helper.mReducePriorityOnBackground) continue; + helper.reducePriorityOnBackgroundOnLauncherThread(); + } + } + + private void reducePriorityOnBackgroundOnLauncherThread() { + assert LauncherThread.runningOnLauncherThread(); + if (mDroppedStrongBingingDueToBackgrounding) return; + ChildProcessConnection connection = mLauncher.getConnection(); + if (!connection.isConnected()) return; + if (connection.isStrongBindingBound()) { + connection.removeStrongBinding(); + mDroppedStrongBingingDueToBackgrounding = true; + } + } + + private void raisePriorityOnForegroundOnLauncherThread() { + assert LauncherThread.runningOnLauncherThread(); + if (!mDroppedStrongBingingDueToBackgrounding) return; + ChildProcessConnection connection = mLauncher.getConnection(); + if (!connection.isConnected()) return; + connection.addStrongBinding(); + mDroppedStrongBingingDueToBackgrounding = false; + } + private static void onBroughtToForeground() { assert ThreadUtils.runningOnUiThread(); sApplicationInForegroundOnUiThread = true; + LauncherThread.removeCallbacks(sDelayedBackgroundTask); LauncherThread.post(() -> { + for (ChildProcessLauncherHelperImpl helper : sLauncherByPid.values()) { + if (!helper.mReducePriorityOnBackground) continue; + helper.raisePriorityOnForegroundOnLauncherThread(); + } if (sBindingManager != null) sBindingManager.onBroughtToForeground(); }); } @@ -506,6 +548,11 @@ } @VisibleForTesting + public static void setSkipDelayForReducePriorityOnBackgroundForTesting() { + sSkipDelayForReducePriorityOnBackgroundForTesting = true; + } + + @VisibleForTesting static ChildConnectionAllocator getConnectionAllocator(Context context, boolean sandboxed) { assert LauncherThread.runningOnLauncherThread(); boolean bindToCaller = ChildProcessCreationParamsImpl.getBindToCallerCheck(); @@ -577,12 +624,14 @@ } private ChildProcessLauncherHelperImpl(long nativePointer, String[] commandLine, - FileDescriptorInfo[] filesToBeMapped, boolean sandboxed, boolean canUseWarmUpConnection, + FileDescriptorInfo[] filesToBeMapped, boolean sandboxed, + boolean reducePriorityOnBackground, boolean canUseWarmUpConnection, IBinder binderCallback) { assert LauncherThread.runningOnLauncherThread(); mNativeChildProcessLauncherHelper = nativePointer; mSandboxed = sandboxed; + mReducePriorityOnBackground = reducePriorityOnBackground; mCanUseWarmUpConnection = canUseWarmUpConnection; ChildConnectionAllocator connectionAllocator = getConnectionAllocator(ContextUtils.getApplicationContext(), sandboxed); @@ -602,6 +651,27 @@ // -2 means not applicable. mReverseRankWhenConnectionLost = -2; } + + if (!ApplicationStatus.isInitialized()) return; + if (sAppStateListener != null) return; + PostTask.postTask(UiThreadTaskTraits.BEST_EFFORT, () -> { + if (sAppStateListener != null) return; + sApplicationInForegroundOnUiThread = ApplicationStatus.hasVisibleActivities(); + sAppStateListener = newState -> { + switch (newState) { + case ApplicationState.UNKNOWN: + break; + case ApplicationState.HAS_RUNNING_ACTIVITIES: + case ApplicationState.HAS_PAUSED_ACTIVITIES: + if (!sApplicationInForegroundOnUiThread) onBroughtToForeground(); + break; + default: + if (sApplicationInForegroundOnUiThread) onSentToBackground(); + break; + } + }; + ApplicationStatus.registerApplicationStateListener(sAppStateListener); + }); } private void start() { @@ -822,10 +892,12 @@ @VisibleForTesting public static ChildProcessLauncherHelperImpl createAndStartForTesting(String[] commandLine, - FileDescriptorInfo[] filesToBeMapped, boolean sandboxed, boolean canUseWarmUpConnection, + FileDescriptorInfo[] filesToBeMapped, boolean sandboxed, + boolean reducePriorityOnBackground, boolean canUseWarmUpConnection, IBinder binderCallback, boolean doSetupConnection) { - ChildProcessLauncherHelperImpl launcherHelper = new ChildProcessLauncherHelperImpl(0L, - commandLine, filesToBeMapped, sandboxed, canUseWarmUpConnection, binderCallback); + ChildProcessLauncherHelperImpl launcherHelper = + new ChildProcessLauncherHelperImpl(0L, commandLine, filesToBeMapped, sandboxed, + reducePriorityOnBackground, canUseWarmUpConnection, binderCallback); launcherHelper.mLauncher.start(doSetupConnection, true /* queueIfNoFreeConnection */); return launcherHelper; }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherHelperTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherHelperTest.java index df482a63..cc94122 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherHelperTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherHelperTest.java
@@ -21,9 +21,12 @@ import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.ActivityState; +import org.chromium.base.ApplicationStatus; import org.chromium.base.BaseSwitches; import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.LibraryProcessType; @@ -39,6 +42,8 @@ import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_shell_apk.ChildProcessLauncherTestHelperService; import org.chromium.content_shell_apk.ChildProcessLauncherTestUtils; +import org.chromium.content_shell_apk.ContentShellActivity; +import org.chromium.content_shell_apk.ContentShellActivityTestRule; import java.util.concurrent.Callable; @@ -59,6 +64,9 @@ private static final int BLOCK_UNTIL_CONNECTED = 1; private static final int BLOCK_UNTIL_SETUP = 2; + @Rule + public ContentShellActivityTestRule mActivityTestRule = new ContentShellActivityTestRule(); + @Before public void setUp() { LibraryLoader.getInstance().ensureInitialized(); @@ -321,9 +329,9 @@ Assert.assertEquals(1, getConnectedServicesCount()); // And subsequent process launches should work. - ChildProcessLauncherHelperImpl launcher = - startChildProcess(BLOCK_UNTIL_SETUP, true /* doSetupConnection */, - false /* sandboxed */, true /* canUseWarmUpConnection */); + ChildProcessLauncherHelperImpl launcher = startChildProcess(BLOCK_UNTIL_SETUP, + true /* doSetupConnection */, false /* sandboxed */, + false /* reducePriorityOnBackground */, true /* canUseWarmUpConnection */); Assert.assertEquals(1, getConnectedServicesCount()); Assert.assertEquals(0, getConnectedSandboxedServicesCount()); Assert.assertNotNull(ChildProcessLauncherTestUtils.getConnection(launcher)); @@ -352,14 +360,65 @@ waitForConnectedSandboxedServicesCount(0); } + @Test + @MediumTest + @Feature({"ProcessManagement"}) + public void testReducePriorityOnBackground() { + ChildProcessLauncherHelperImpl.setSkipDelayForReducePriorityOnBackgroundForTesting(); + + final ContentShellActivity activity = + mActivityTestRule.launchContentShellWithUrl("about:blank"); + mActivityTestRule.waitForActiveShellToBeDoneLoading(); + Assert.assertTrue(ApplicationStatus.hasVisibleActivities()); + + ChildProcessLauncherHelperImpl launcher = startChildProcess(BLOCK_UNTIL_SETUP, + true /* doSetupConnection */, false /* sandboxed */, + true /* reducePriorityOnBackground */, true /* canUseWarmUpConnection */); + final ChildProcessConnection connection = + ChildProcessLauncherTestUtils.getConnection(launcher); + + Assert.assertTrue(ChildProcessLauncherTestUtils.runOnLauncherAndGetResult( + () -> connection.isStrongBindingBound())); + + TestThreadUtils.runOnUiThreadBlocking( + () -> ApplicationStatus.onStateChangeForTesting(activity, ActivityState.STOPPED)); + Assert.assertFalse(ApplicationStatus.hasVisibleActivities()); + Assert.assertFalse(ChildProcessLauncherTestUtils.runOnLauncherAndGetResult( + () -> connection.isStrongBindingBound())); + } + + @Test + @MediumTest + @Feature({"ProcessManagement"}) + public void testLaunchWithReducedPriorityOnBackground() { + ChildProcessLauncherHelperImpl.setSkipDelayForReducePriorityOnBackgroundForTesting(); + + final ContentShellActivity activity = + mActivityTestRule.launchContentShellWithUrl("about:blank"); + mActivityTestRule.waitForActiveShellToBeDoneLoading(); + TestThreadUtils.runOnUiThreadBlocking( + () -> ApplicationStatus.onStateChangeForTesting(activity, ActivityState.STOPPED)); + Assert.assertFalse(ApplicationStatus.hasVisibleActivities()); + + ChildProcessLauncherHelperImpl launcher = startChildProcess(BLOCK_UNTIL_SETUP, + true /* doSetupConnection */, false /* sandboxed */, + true /* reducePriorityOnBackground */, true /* canUseWarmUpConnection */); + final ChildProcessConnection connection = + ChildProcessLauncherTestUtils.getConnection(launcher); + + Assert.assertFalse(ChildProcessLauncherTestUtils.runOnLauncherAndGetResult( + () -> connection.isStrongBindingBound())); + } + private static ChildProcessLauncherHelperImpl startSandboxedChildProcess( int blockingPolicy, final boolean doSetupConnection) { return startChildProcess(blockingPolicy, doSetupConnection, true /* sandboxed */, - true /* canUseWarmUpConnection */); + false /* reducePriorityOnBackground */, true /* canUseWarmUpConnection */); } private static ChildProcessLauncherHelperImpl startChildProcess(int blockingPolicy, - final boolean doSetupConnection, boolean sandboxed, boolean canUseWarmUpConnection) { + final boolean doSetupConnection, boolean sandboxed, boolean reducePriorityOnBackground, + boolean canUseWarmUpConnection) { assert doSetupConnection || blockingPolicy != BLOCK_UNTIL_SETUP; ChildProcessLauncherHelperImpl launcher = ChildProcessLauncherTestUtils.runOnLauncherAndGetResult( @@ -368,8 +427,8 @@ public ChildProcessLauncherHelperImpl call() { return ChildProcessLauncherHelperImpl.createAndStartForTesting( sProcessWaitArguments, new FileDescriptorInfo[0], sandboxed, - canUseWarmUpConnection, null /* binderCallback */, - doSetupConnection); + reducePriorityOnBackground, canUseWarmUpConnection, + null /* binderCallback */, doSetupConnection); } }); if (blockingPolicy != DONT_BLOCK) {
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index ea154d8f..a16cd52 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -283,6 +283,8 @@ "permission_controller.h", "permission_controller_delegate.cc", "permission_controller_delegate.h", + "permission_result.cc", + "permission_result.h", "picture_in_picture_window_controller.h", "platform_notification_context.h", "platform_notification_service.h", @@ -424,6 +426,8 @@ "web_ui_controller.cc", "web_ui_controller.h", "web_ui_controller_factory.h", + "web_ui_controller_interface_binder.cc", + "web_ui_controller_interface_binder.h", "web_ui_data_source.h", "web_ui_message_handler.h", "web_ui_url_loader_factory.h",
diff --git a/content/public/browser/permission_controller.h b/content/public/browser/permission_controller.h index 87b8785..f147bc4 100644 --- a/content/public/browser/permission_controller.h +++ b/content/public/browser/permission_controller.h
@@ -8,6 +8,7 @@ #include "base/supports_user_data.h" #include "base/types/id_type.h" #include "content/common/content_export.h" +#include "content/public/browser/permission_result.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" class GURL; @@ -53,11 +54,26 @@ blink::PermissionType permission, RenderFrameHost* render_frame_host) = 0; + // The method does the same as `GetPermissionStatusForCurrentDocument` but + // additionally returns a source or reason for the permission status. + virtual PermissionResult GetPermissionResultForCurrentDocument( + blink::PermissionType permission, + RenderFrameHost* render_frame_host) = 0; + // Returns the permission status for a given origin. Use this API only if // there is no document and it is not a ServiceWorker. + virtual PermissionResult GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) = 0; + + // The method does the same as `GetPermissionResultForOriginWithoutContext` + // but it can be used for `PermissionType` that are keyed on a combination of + // requesting and embedding origins, e.g., Notifications. virtual blink::mojom::PermissionStatus - GetPermissionStatusForOriginWithoutContext(blink::PermissionType permission, - const url::Origin& origin) = 0; + GetPermissionStatusForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& requesting_origin, + const url::Origin& embedding_origin) = 0; // Requests the permission from the current document in the given // RenderFrameHost. This API takes into account the lifecycle state of a given
diff --git a/content/public/browser/permission_controller_delegate.cc b/content/public/browser/permission_controller_delegate.cc index 0cd97b19..2a0c82e 100644 --- a/content/public/browser/permission_controller_delegate.cc +++ b/content/public/browser/permission_controller_delegate.cc
@@ -3,6 +3,8 @@ // found in the LICENSE file. #include "content/public/browser/permission_controller_delegate.h" +#include "content/public/browser/permission_result.h" +#include "content/public/browser/render_frame_host.h" namespace content { @@ -12,4 +14,12 @@ return true; } +PermissionResult +PermissionControllerDelegate::GetPermissionResultForCurrentDocument( + blink::PermissionType permission, + RenderFrameHost* render_frame_host) { + return PermissionResult(blink::mojom::PermissionStatus::DENIED, + PermissionStatusSource::UNSPECIFIED); +} + } // namespace content
diff --git a/content/public/browser/permission_controller_delegate.h b/content/public/browser/permission_controller_delegate.h index e91b4557..cf92ec9 100644 --- a/content/public/browser/permission_controller_delegate.h +++ b/content/public/browser/permission_controller_delegate.h
@@ -8,6 +8,7 @@ #include "base/types/id_type.h" #include "content/common/content_export.h" #include "content/public/browser/devtools_permission_overrides.h" +#include "content/public/browser/permission_result.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" class GURL; @@ -75,6 +76,10 @@ const GURL& requesting_origin, const GURL& embedding_origin) = 0; + virtual PermissionResult GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) = 0; + // Returns the permission status for the current document in the given // RenderFrameHost. Use this over `GetPermissionStatus` whenever possible as // this API takes into account the lifecycle state of a given document (i.e. @@ -84,6 +89,12 @@ blink::PermissionType permission, RenderFrameHost* render_frame_host) = 0; + // The method does the same as `GetPermissionStatusForCurrentDocument` but + // additionally returns a source or reason for the permission status. + virtual PermissionResult GetPermissionResultForCurrentDocument( + blink::PermissionType permission, + RenderFrameHost* render_frame_host); + // Returns the status of the given `permission` for a worker on // `worker_origin` running in `render_process_host`, also performing // additional checks such as Permission Policy. Use this over
diff --git a/content/public/browser/permission_result.cc b/content/public/browser/permission_result.cc new file mode 100644 index 0000000..6ff6d807 --- /dev/null +++ b/content/public/browser/permission_result.cc
@@ -0,0 +1,16 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/public/browser/permission_result.h" + +namespace content { + +PermissionResult::PermissionResult( + blink::mojom::PermissionStatus permission_status, + PermissionStatusSource permission_status_source) + : status(permission_status), source(permission_status_source) {} + +PermissionResult::~PermissionResult() = default; + +} // namespace content
diff --git a/content/public/browser/permission_result.h b/content/public/browser/permission_result.h new file mode 100644 index 0000000..b26428f --- /dev/null +++ b/content/public/browser/permission_result.h
@@ -0,0 +1,62 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_PUBLIC_BROWSER_PERMISSION_RESULT_H_ +#define CONTENT_PUBLIC_BROWSER_PERMISSION_RESULT_H_ + +#include "content/common/content_export.h" +#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" + +namespace content { + +// Identifies the source or reason for a permission status being returned. +enum class PermissionStatusSource { + // The reason for the status is not specified. + UNSPECIFIED, + + // The status is the result of being blocked by the permissions kill switch. + KILL_SWITCH, + + // The status is the result of being blocked due to the user dismissing a + // permission prompt multiple times. + MULTIPLE_DISMISSALS, + + // The status is the result of being blocked due to the user ignoring a + // permission prompt multiple times. + MULTIPLE_IGNORES, + + // This origin is insecure, thus its access to some permissions has been + // restricted, such as camera, microphone, etc. + INSECURE_ORIGIN, + + // The feature has been blocked in the requesting frame by permissions policy. + FEATURE_POLICY, + + // The virtual URL and the loaded URL are for different origins. The loaded + // URL is the one actually in the renderer, but the virtual URL is the one + // seen by the user. This may be very confusing for a user to see in a + // permissions request. + VIRTUAL_URL_DIFFERENT_ORIGIN, + + // The status is the result of a permission being requested inside a portal. + // Permissions are currently always denied inside a portal. + PORTAL, + + // The status is the result of a permission being requested inside a fenced + // frame. Permissions are currently always denied inside a fenced frame. + FENCED_FRAME, +}; + +struct CONTENT_EXPORT PermissionResult { + PermissionResult(blink::mojom::PermissionStatus status, + PermissionStatusSource source); + ~PermissionResult(); + + blink::mojom::PermissionStatus status; + PermissionStatusSource source; +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_PERMISSION_RESULT_H_
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h index 2ee2f2a..c12e9514 100644 --- a/content/public/browser/web_contents.h +++ b/content/public/browser/web_contents.h
@@ -1096,8 +1096,8 @@ // be called with the bitmaps received from the renderer. // If |is_favicon| is true, the cookies are not sent and not accepted during // download. - // Bitmaps with pixel sizes larger than |max_bitmap_size| are filtered out - // from the bitmap results. + // If there are no bitmap results <= |max_bitmap_size|, the smallest bitmap + // is resized to |max_bitmap_size| and is the only result. // A |max_bitmap_size| of 0 means unlimited. // For vector images, |preferred_size| will serve as a viewport into which // the image will be rendered. This would usually be the dimensions of the
diff --git a/content/public/browser/web_ui_controller_interface_binder.cc b/content/public/browser/web_ui_controller_interface_binder.cc new file mode 100644 index 0000000..b46089f --- /dev/null +++ b/content/public/browser/web_ui_controller_interface_binder.cc
@@ -0,0 +1,17 @@ +// 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/public/browser/web_ui_controller_interface_binder.h" + +#include "content/browser/bad_message.h" + +namespace content::internal { + +void ReceivedInvalidWebUIControllerMessage(RenderFrameHost* rfh) { + ReceivedBadMessage( + rfh->GetProcess(), + bad_message::BadMessageReason::RFH_INVALID_WEB_UI_CONTROLLER); +} + +} // namespace content::internal
diff --git a/content/public/browser/web_ui_controller_interface_binder.h b/content/public/browser/web_ui_controller_interface_binder.h new file mode 100644 index 0000000..e517f9f --- /dev/null +++ b/content/public/browser/web_ui_controller_interface_binder.h
@@ -0,0 +1,96 @@ +// 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_PUBLIC_BROWSER_WEB_UI_CONTROLLER_INTERFACE_BINDER_H_ +#define CONTENT_PUBLIC_BROWSER_WEB_UI_CONTROLLER_INTERFACE_BINDER_H_ + +#include "content/common/content_export.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_controller.h" +#include "mojo/public/cpp/bindings/binder_map.h" + +namespace content { +namespace internal { + +template <typename Interface, int N, typename... Subclasses> +struct BinderHelper; + +template <typename Interface, typename WebUIControllerSubclass> +bool SafeDownCastAndBindInterface(WebUI* web_ui, + mojo::PendingReceiver<Interface>& receiver) { + // Performs a safe downcast to the concrete WebUIController subclass. + WebUIControllerSubclass* concrete_controller = + web_ui ? web_ui->GetController()->GetAs<WebUIControllerSubclass>() + : nullptr; + + if (!concrete_controller) + return false; + + // Fails to compile if |Subclass| does not implement the appropriate overload + // for |Interface|. + concrete_controller->BindInterface(std::move(receiver)); + return true; +} + +template <typename Interface, int N, typename Subclass, typename... Subclasses> +struct BinderHelper<Interface, N, std::tuple<Subclass, Subclasses...>> { + static bool BindInterface(WebUI* web_ui, + mojo::PendingReceiver<Interface> receiver) { + // Try a different subclass if the current one is not the right + // WebUIController for the current WebUI page, and only fail if none of the + // passed subclasses match. + if (!SafeDownCastAndBindInterface<Interface, Subclass>(web_ui, receiver)) { + return BinderHelper<Interface, N - 1, std::tuple<Subclasses...>>:: + BindInterface(web_ui, std::move(receiver)); + } + return true; + } +}; + +template <typename Interface, typename Subclass, typename... Subclasses> +struct BinderHelper<Interface, 0, std::tuple<Subclass, Subclasses...>> { + static bool BindInterface(WebUI* web_ui, + mojo::PendingReceiver<Interface> receiver) { + return SafeDownCastAndBindInterface<Interface, Subclass>(web_ui, receiver); + } +}; + +void CONTENT_EXPORT ReceivedInvalidWebUIControllerMessage(RenderFrameHost* rfh); + +} // namespace internal + +// Registers a binder in |map| that binds |Interface| iff the RenderFrameHost +// has a WebUIController among type |WebUIControllerSubclasses|. +template <typename Interface, typename... WebUIControllerSubclasses> +void RegisterWebUIControllerInterfaceBinder( + mojo::BinderMapWithContext<RenderFrameHost*>* map) { + DCHECK(!map->Contains<Interface>()) + << "A binder for " << Interface::Name_ << " has already been registered."; + map->Add<Interface>(base::BindRepeating( + [](RenderFrameHost* host, mojo::PendingReceiver<Interface> receiver) { + // This is expected to be called only for outermost main frames. + if (host->GetParentOrOuterDocument()) { + internal::ReceivedInvalidWebUIControllerMessage(host); + return; + } + + const int size = sizeof...(WebUIControllerSubclasses); + bool is_bound = + internal::BinderHelper<Interface, size - 1, + std::tuple<WebUIControllerSubclasses...>>:: + BindInterface(host->GetWebUI(), std::move(receiver)); + + // This is expected to be called only for the right WebUI pages matching + // the same WebUI associated to the RenderFrameHost. + if (!is_bound) { + internal::ReceivedInvalidWebUIControllerMessage(host); + return; + } + })); +} + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_WEB_UI_CONTROLLER_INTERFACE_BINDER_H_
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 80661db1..fd51e0c6 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -352,6 +352,11 @@ const base::Feature kFedCmManifestValidation{"FedCmManifestValidation", base::FEATURE_ENABLED_BY_DEFAULT}; +// Enables usage of the FedCM API with multiple identity providers at the same +// time. +const base::Feature kFedCmMultipleIdentityProviders{ + "FedCmMultipleIdentityProviders", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables usage of First Party Sets to determine cookie availability. constexpr base::Feature kFirstPartySets{"FirstPartySets", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -1199,6 +1204,11 @@ "BackgroundMediaRendererHasModerateBinding", base::FEATURE_DISABLED_BY_DEFAULT}; +// Reduce the priority of GPU process when in background so it is more likely +// to be killed first if the OS needs more memory. +const base::Feature kReduceGpuPriorityOnBackground{ + "ReduceGpuPriorityOnBackground", base::FEATURE_DISABLED_BY_DEFAULT}; + // Allows the use of an experimental feature to drop any AccessibilityEvents // that are not relevant to currently enabled accessibility services. const base::Feature kOnDemandAccessibilityEvents{
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 080db50..a436c7c 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -92,6 +92,7 @@ CONTENT_EXPORT extern const char kFedCmIdpSignoutFieldTrialParamName[]; CONTENT_EXPORT extern const char kFedCmIframeSupportFieldTrialParamName[]; CONTENT_EXPORT extern const base::Feature kFedCmManifestValidation; +CONTENT_EXPORT extern const base::Feature kFedCmMultipleIdentityProviders; CONTENT_EXPORT extern const base::Feature kFirstPartySets; CONTENT_EXPORT extern const base::FeatureParam<bool> kFirstPartySetsIsDogfooder; CONTENT_EXPORT extern const base::Feature kFontManagerEarlyInit; @@ -312,6 +313,7 @@ CONTENT_EXPORT extern const base::Feature kAccessibilityPageZoom; CONTENT_EXPORT extern const base::Feature kBackgroundMediaRendererHasModerateBinding; +CONTENT_EXPORT extern const base::Feature kReduceGpuPriorityOnBackground; CONTENT_EXPORT extern const base::Feature kOnDemandAccessibilityEvents; CONTENT_EXPORT extern const base::Feature kRequestDesktopSiteAdditions; CONTENT_EXPORT extern const base::Feature kRequestDesktopSiteExceptions;
diff --git a/content/public/test/DEPS b/content/public/test/DEPS index 166beac..4d049c846 100644 --- a/content/public/test/DEPS +++ b/content/public/test/DEPS
@@ -31,6 +31,7 @@ "+components/viz/test", "+device/vr/public/mojom", "+services/audio", + "+services/cert_verifier", "+services/metrics/public/cpp", "+services/network", "+services/service_manager",
diff --git a/content/public/test/OWNERS b/content/public/test/OWNERS index 9f2054f..d7c2aa8 100644 --- a/content/public/test/OWNERS +++ b/content/public/test/OWNERS
@@ -22,6 +22,9 @@ # Network Service per-file network_service_test_helper.*=file://services/network/OWNERS +# Cert Verifier Service +per-file test_cert_verifier_service_factory.*=file://services/cert_verifier/OWNERS + # DevTools-specific changes per-file *devtools*=file://content/browser/devtools/OWNERS
diff --git a/content/public/test/mock_permission_controller.h b/content/public/test/mock_permission_controller.h index 0a8b14a..b940ff58 100644 --- a/content/public/test/mock_permission_controller.h +++ b/content/public/test/mock_permission_controller.h
@@ -6,6 +6,7 @@ #define CONTENT_PUBLIC_TEST_MOCK_PERMISSION_CONTROLLER_H_ #include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "testing/gmock/include/gmock/gmock.h" namespace blink { @@ -38,10 +39,17 @@ GetPermissionStatusForCurrentDocument, blink::mojom::PermissionStatus(blink::PermissionType permission, RenderFrameHost* render_frame_host)); - MOCK_METHOD2( + MOCK_METHOD2(GetPermissionResultForCurrentDocument, + content::PermissionResult(blink::PermissionType permission, + RenderFrameHost* render_frame_host)); + MOCK_METHOD2(GetPermissionResultForOriginWithoutContext, + content::PermissionResult(blink::PermissionType permission, + const url::Origin& requesting_origin)); + MOCK_METHOD3( GetPermissionStatusForOriginWithoutContext, blink::mojom::PermissionStatus(blink::PermissionType permission, - const url::Origin& requesting_origin)); + const url::Origin& requesting_origin, + const url::Origin& embedding_origin)); void RequestPermissionFromCurrentDocument( blink::PermissionType permission, RenderFrameHost* render_frame_host,
diff --git a/content/public/test/mock_permission_manager.h b/content/public/test/mock_permission_manager.h index f36cb43..2d178c4 100644 --- a/content/public/test/mock_permission_manager.h +++ b/content/public/test/mock_permission_manager.h
@@ -6,8 +6,10 @@ #define CONTENT_PUBLIC_TEST_MOCK_PERMISSION_MANAGER_H_ #include "content/public/browser/permission_controller_delegate.h" +#include "content/public/browser/permission_result.h" #include "testing/gmock/include/gmock/gmock.h" #include "url/gurl.h" +#include "url/origin.h" namespace blink { enum class PermissionType; @@ -30,6 +32,9 @@ blink::mojom::PermissionStatus(blink::PermissionType permission, const GURL& requesting_origin, const GURL& embedding_origin)); + MOCK_METHOD2(GetPermissionResultForOriginWithoutContext, + content::PermissionResult(blink::PermissionType permission, + const url::Origin& origin)); MOCK_METHOD2(GetPermissionStatusForCurrentDocument, blink::mojom::PermissionStatus( blink::PermissionType permission,
diff --git a/services/cert_verifier/test_cert_verifier_service_factory.cc b/content/public/test/test_cert_verifier_service_factory.cc similarity index 64% rename from services/cert_verifier/test_cert_verifier_service_factory.cc rename to content/public/test/test_cert_verifier_service_factory.cc index 139d98f..3cece9b 100644 --- a/services/cert_verifier/test_cert_verifier_service_factory.cc +++ b/content/public/test/test_cert_verifier_service_factory.cc
@@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "services/cert_verifier/test_cert_verifier_service_factory.h" +#include "content/public/test/test_cert_verifier_service_factory.h" #include <memory> #include <type_traits> #include "base/memory/scoped_refptr.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" #include "net/net_buildflags.h" #include "services/cert_verifier/cert_verifier_service.h" #include "services/cert_verifier/cert_verifier_service_factory.h" @@ -72,8 +74,37 @@ } void TestCertVerifierServiceFactoryImpl::InitDelegate() { - delegate_ = std::make_unique<CertVerifierServiceFactoryImpl>( - delegate_remote_.BindNewPipeAndPassReceiver()); + delegate_ = base::MakeRefCounted<DelegateOwner>( +#if BUILDFLAG(IS_CHROMEOS) + // In-process CertVerifierService in Ash and Lacros should run on the IO + // thread because it interacts with IO-bound NSS and ChromeOS user slots. + // See for example InitializeNSSForChromeOSUser() or + // CertDbInitializerIOImpl. + content::GetIOThreadTaskRunner({}) +#else + base::SequencedTaskRunnerHandle::Get() +#endif + ); + delegate_->Init(delegate_remote_.BindNewPipeAndPassReceiver()); +} + +TestCertVerifierServiceFactoryImpl::DelegateOwner::DelegateOwner( + scoped_refptr<base::SequencedTaskRunner> task_runner) + : base::RefCountedDeleteOnSequence<DelegateOwner>(std::move(task_runner)) {} + +TestCertVerifierServiceFactoryImpl::DelegateOwner::~DelegateOwner() = default; + +void TestCertVerifierServiceFactoryImpl::DelegateOwner::Init( + mojo::PendingReceiver<cert_verifier::mojom::CertVerifierServiceFactory> + receiver) { + if (!owning_task_runner()->RunsTasksInCurrentSequence()) { + owning_task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&DelegateOwner::Init, this, std::move(receiver))); + return; + } + delegate_ = + std::make_unique<CertVerifierServiceFactoryImpl>(std::move(receiver)); } } // namespace cert_verifier
diff --git a/services/cert_verifier/test_cert_verifier_service_factory.h b/content/public/test/test_cert_verifier_service_factory.h similarity index 75% rename from services/cert_verifier/test_cert_verifier_service_factory.h rename to content/public/test/test_cert_verifier_service_factory.h index 6ff8a30..bed5b36e 100644 --- a/services/cert_verifier/test_cert_verifier_service_factory.h +++ b/content/public/test/test_cert_verifier_service_factory.h
@@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SERVICES_CERT_VERIFIER_TEST_CERT_VERIFIER_SERVICE_FACTORY_H_ -#define SERVICES_CERT_VERIFIER_TEST_CERT_VERIFIER_SERVICE_FACTORY_H_ +#ifndef CONTENT_PUBLIC_TEST_TEST_CERT_VERIFIER_SERVICE_FACTORY_H_ +#define CONTENT_PUBLIC_TEST_TEST_CERT_VERIFIER_SERVICE_FACTORY_H_ #include <memory> #include "base/containers/circular_deque.h" +#include "base/memory/ref_counted.h" +#include "base/memory/ref_counted_delete_on_sequence.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver_set.h" @@ -63,14 +65,32 @@ } private: + class DelegateOwner : public base::RefCountedDeleteOnSequence<DelegateOwner> { + public: + explicit DelegateOwner( + scoped_refptr<base::SequencedTaskRunner> owning_task_runner); + + void Init( + mojo::PendingReceiver<cert_verifier::mojom::CertVerifierServiceFactory> + receiver); + + private: + friend class base::RefCountedDeleteOnSequence<DelegateOwner>; + friend class base::DeleteHelper<DelegateOwner>; + + ~DelegateOwner(); + + std::unique_ptr<CertVerifierServiceFactoryImpl> delegate_; + }; + void InitDelegate(); mojo::Remote<mojom::CertVerifierServiceFactory> delegate_remote_; - std::unique_ptr<CertVerifierServiceFactoryImpl> delegate_; + scoped_refptr<DelegateOwner> delegate_; base::circular_deque<GetNewCertVerifierParams> captured_params_; }; } // namespace cert_verifier -#endif // SERVICES_CERT_VERIFIER_TEST_CERT_VERIFIER_SERVICE_FACTORY_H_ +#endif // CONTENT_PUBLIC_TEST_TEST_CERT_VERIFIER_SERVICE_FACTORY_H_
diff --git a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestUtils.java b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestUtils.java index 3481221..0ee095fa 100644 --- a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestUtils.java +++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestUtils.java
@@ -59,8 +59,9 @@ @Override public ChildProcessLauncherHelperImpl call() { return ChildProcessLauncherHelperImpl.createAndStartForTesting(commandLine, - filesToBeMapped, sandboxed, true /* canUseWarmUpConnection */, - null /* binderCallback */, doSetupConnection); + filesToBeMapped, sandboxed, false /* reducePriorityOnBackground */, + true /* canUseWarmUpConnection */, null /* binderCallback */, + doSetupConnection); } }); }
diff --git a/content/shell/browser/shell_permission_manager.cc b/content/shell/browser/shell_permission_manager.cc index 0b62b1b2..4d5ba47 100644 --- a/content/shell/browser/shell_permission_manager.cc +++ b/content/shell/browser/shell_permission_manager.cc
@@ -154,6 +154,16 @@ : blink::mojom::PermissionStatus::DENIED; } +PermissionResult +ShellPermissionManager::GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) { + blink::mojom::PermissionStatus status = + GetPermissionStatus(permission, origin.GetURL(), origin.GetURL()); + + return PermissionResult(status, content::PermissionStatusSource::UNSPECIFIED); +} + blink::mojom::PermissionStatus ShellPermissionManager::GetPermissionStatusForCurrentDocument( PermissionType permission,
diff --git a/content/shell/browser/shell_permission_manager.h b/content/shell/browser/shell_permission_manager.h index cf6d8ab..70210564 100644 --- a/content/shell/browser/shell_permission_manager.h +++ b/content/shell/browser/shell_permission_manager.h
@@ -7,6 +7,7 @@ #include "base/callback_forward.h" #include "content/public/browser/permission_controller_delegate.h" +#include "content/public/browser/permission_result.h" namespace blink { enum class PermissionType; @@ -53,6 +54,9 @@ blink::PermissionType permission, const GURL& requesting_origin, const GURL& embedding_origin) override; + PermissionResult GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) override; blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument( blink::PermissionType permission, content::RenderFrameHost* render_frame_host) override;
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 240f5ad8..b12c3e12 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -290,6 +290,8 @@ "../public/test/test_aggregation_service.h", "../public/test/test_browser_context.cc", "../public/test/test_browser_context.h", + "../public/test/test_cert_verifier_service_factory.cc", + "../public/test/test_cert_verifier_service_factory.h", "../public/test/test_content_client_initializer.cc", "../public/test/test_content_client_initializer.h", "../public/test/test_devtools_protocol_client.cc", @@ -539,6 +541,7 @@ "//net:test_support", "//services/audio", "//services/audio/public/mojom", + "//services/cert_verifier:lib", "//services/data_decoder/public/cpp:test_support", "//services/data_decoder/public/mojom", "//services/device/public/mojom",
diff --git a/content/web_test/browser/web_test_permission_manager.cc b/content/web_test/browser/web_test_permission_manager.cc index 348bcd4..da00838 100644 --- a/content/web_test/browser/web_test_permission_manager.cc +++ b/content/web_test/browser/web_test_permission_manager.cc
@@ -168,6 +168,16 @@ return it->second; } +PermissionResult +WebTestPermissionManager::GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) { + blink::mojom::PermissionStatus status = + GetPermissionStatus(permission, origin.GetURL(), origin.GetURL()); + + return PermissionResult(status, content::PermissionStatusSource::UNSPECIFIED); +} + blink::mojom::PermissionStatus WebTestPermissionManager::GetPermissionStatusForCurrentDocument( blink::PermissionType permission,
diff --git a/content/web_test/browser/web_test_permission_manager.h b/content/web_test/browser/web_test_permission_manager.h index 998ab38b1..c9f1cbd 100644 --- a/content/web_test/browser/web_test_permission_manager.h +++ b/content/web_test/browser/web_test_permission_manager.h
@@ -11,6 +11,7 @@ #include "base/containers/id_map.h" #include "base/synchronization/lock.h" #include "content/public/browser/permission_controller_delegate.h" +#include "content/public/browser/permission_result.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "third_party/blink/public/mojom/permissions/permission.mojom.h" #include "third_party/blink/public/mojom/permissions/permission_automation.mojom.h" @@ -63,6 +64,9 @@ blink::PermissionType permission, const GURL& requesting_origin, const GURL& embedding_origin) override; + PermissionResult GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) override; blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument( blink::PermissionType permission, content::RenderFrameHost* render_frame_host) override;
diff --git a/content/web_test/renderer/text_input_controller.cc b/content/web_test/renderer/text_input_controller.cc index 51a7b49..cc0e6769 100644 --- a/content/web_test/renderer/text_input_controller.cc +++ b/content/web_test/renderer/text_input_controller.cc
@@ -57,8 +57,8 @@ bool HasMarkedText(); std::vector<int> MarkedRange(); std::vector<int> SelectedRange(); - std::vector<int> FirstRectForCharacterRange(unsigned location, - unsigned length); + std::vector<int> FirstRectForCharacterRange(uint32_t location, + uint32_t length); void SetComposition(const std::string& text); void SetCompositionWithReplacementRange(const std::string& text, int replacement_start, @@ -186,8 +186,8 @@ } std::vector<int> TextInputControllerBindings::FirstRectForCharacterRange( - unsigned location, - unsigned length) { + uint32_t location, + uint32_t length) { return controller_ ? controller_->FirstRectForCharacterRange(location, length) : std::vector<int>(); } @@ -363,8 +363,8 @@ } std::vector<int> TextInputController::FirstRectForCharacterRange( - unsigned location, - unsigned length) { + uint32_t location, + uint32_t length) { gfx::Rect rect; if (!view()->FocusedFrame() || !view()->FocusedFrame()->FirstRectForCharacterRange(location, length,
diff --git a/content/web_test/renderer/text_input_controller.h b/content/web_test/renderer/text_input_controller.h index b6ab1dd..9fbb5f37 100644 --- a/content/web_test/renderer/text_input_controller.h +++ b/content/web_test/renderer/text_input_controller.h
@@ -48,8 +48,8 @@ bool HasMarkedText(); std::vector<int> MarkedRange(); std::vector<int> SelectedRange(); - std::vector<int> FirstRectForCharacterRange(unsigned location, - unsigned length); + std::vector<int> FirstRectForCharacterRange(uint32_t location, + uint32_t length); void SetComposition(const std::string& text, int replacement_range_start, int replacement_range_end);
diff --git a/device/bluetooth/floss/floss_socket_manager.cc b/device/bluetooth/floss/floss_socket_manager.cc index dcf46f1..2e98597 100644 --- a/device/bluetooth/floss/floss_socket_manager.cc +++ b/device/bluetooth/floss/floss_socket_manager.cc
@@ -127,6 +127,26 @@ absl::optional<FlossSocketManager::FlossListeningSocket>* socket); template <> +void FlossDBusClient::WriteDBusParam( + dbus::MessageWriter* writer, + const FlossSocketManager::FlossListeningSocket& socket) { + dbus::MessageWriter array(nullptr); + dbus::MessageWriter dict(nullptr); + + writer->OpenArray("{sv}", &array); + + WriteDictEntry(&array, kListeningPropId, socket.id); + WriteDictEntry(&array, kListeningPropSockType, socket.type); + WriteDictEntry(&array, kListeningPropFlags, socket.flags); + WriteDictEntry(&array, kListeningPropPsm, socket.psm); + WriteDictEntry(&array, kListeningPropChannel, socket.channel); + WriteDictEntry(&array, kListeningPropName, socket.name); + WriteDictEntry(&array, kListeningPropUuid, socket.uuid); + + writer->CloseContainer(&array); +} + +template <> bool FlossDBusClient::ReadDBusParam(dbus::MessageReader* reader, FlossSocketManager::FlossSocket* socket) { dbus::MessageReader array(nullptr);
diff --git a/device/bluetooth/floss/floss_socket_manager.h b/device/bluetooth/floss/floss_socket_manager.h index 1c7f762..f680633 100644 --- a/device/bluetooth/floss/floss_socket_manager.h +++ b/device/bluetooth/floss/floss_socket_manager.h
@@ -58,7 +58,7 @@ // Represents a listening socket. struct FlossListeningSocket { - SocketId id; + SocketId id = FlossSocketManager::kInvalidSocketId; SocketType type; int flags; absl::optional<int> psm; @@ -69,11 +69,13 @@ FlossListeningSocket(); FlossListeningSocket(const FlossListeningSocket&); ~FlossListeningSocket(); + + bool is_valid() const { return id != FlossSocketManager::kInvalidSocketId; } }; // Represents a connecting socket (either incoming or outgoing). struct FlossSocket { - SocketId id; + SocketId id = FlossSocketManager::kInvalidSocketId; FlossDeviceId remote_device; SocketType type; int flags;
diff --git a/device/bluetooth/floss/floss_socket_manager_unittest.cc b/device/bluetooth/floss/floss_socket_manager_unittest.cc index b0ec631..9806aaa 100644 --- a/device/bluetooth/floss/floss_socket_manager_unittest.cc +++ b/device/bluetooth/floss/floss_socket_manager_unittest.cc
@@ -83,6 +83,30 @@ sockmgr_->Init(bus_.get(), kSocketManagerInterface, adapter_path_.value()); } + void SetupListeningSocket() { + // First listen on something. This will push the socket callbacks into a + // map. + EXPECT_CALL( + *sockmgr_proxy_.get(), + DoCallMethodWithErrorResponse( + HasMemberOf(socket_manager::kListenUsingRfcommWithServiceRecord), _, + _)) + .WillOnce( + Invoke(this, &FlossSocketManagerTest::HandleReturnSocketResult)); + + sockmgr_->ListenUsingRfcomm( + "Foo", device::BluetoothUUID("F00D"), Security::kSecure, + base::BindOnce(&FlossSocketManagerTest::SockStatusCb, + weak_ptr_factory_.GetWeakPtr()), + base::BindRepeating(&FlossSocketManagerTest::SockConnectionStateChanged, + weak_ptr_factory_.GetWeakPtr()), + base::BindRepeating(&FlossSocketManagerTest::SockConnectionAccepted, + weak_ptr_factory_.GetWeakPtr())); + + // We should call accept here but that state is tracked on the daemon side. + // Opting not to simply because we have it mocked away... + } + void HandleRegisterCallback( ::dbus::MethodCall* method_call, int timeout_ms, @@ -114,10 +138,22 @@ std::move(*cb).Run(response.get(), nullptr); } + void HandleReturnSuccess(::dbus::MethodCall* method_call, + int timeout_ms, + ::dbus::ObjectProxy::ResponseOrErrorCallback* cb) { + auto response = ::dbus::Response::CreateEmpty(); + ::dbus::MessageWriter msg(response.get()); + + BtifStatus status = BtifStatus::kSuccess; + FlossDBusClient::WriteAllDBusParams(&msg, status); + + std::move(*cb).Run(response.get(), nullptr); + } + void SendOutgoingConnectionResult( FlossSocketManager::SocketId id, BtifStatus status, - absl::optional<FlossSocketManager::FlossSocket> socket, + const absl::optional<FlossSocketManager::FlossSocket>& socket, dbus::ExportedObject::ResponseSender response) { dbus::MethodCall method_call(socket_manager::kCallbackInterface, socket_manager::kOnOutgoingConnectionResult); @@ -128,6 +164,43 @@ sockmgr_->OnOutgoingConnectionResult(&method_call, std::move(response)); } + void SendIncomingSocketReady( + const FlossSocketManager::FlossListeningSocket& server_socket, + BtifStatus status, + dbus::ExportedObject::ResponseSender response) { + dbus::MethodCall method_call(socket_manager::kCallbackInterface, + socket_manager::kOnIncomingSocketReady); + method_call.SetSerial(serial_++); + dbus::MessageWriter writer(&method_call); + FlossDBusClient::WriteAllDBusParams(&writer, server_socket, status); + + sockmgr_->OnIncomingSocketReady(&method_call, std::move(response)); + } + + void SendIncomingSocketClosed(FlossSocketManager::SocketId id, + BtifStatus status, + dbus::ExportedObject::ResponseSender response) { + dbus::MethodCall method_call(socket_manager::kCallbackInterface, + socket_manager::kOnIncomingSocketReady); + method_call.SetSerial(serial_++); + dbus::MessageWriter writer(&method_call); + FlossDBusClient::WriteAllDBusParams(&writer, id, status); + + sockmgr_->OnIncomingSocketClosed(&method_call, std::move(response)); + } + + void SendIncomingConnection(FlossSocketManager::SocketId id, + const FlossSocketManager::FlossSocket& socket, + dbus::ExportedObject::ResponseSender response) { + dbus::MethodCall method_call(socket_manager::kCallbackInterface, + socket_manager::kOnIncomingSocketReady); + method_call.SetSerial(serial_++); + dbus::MessageWriter writer(&method_call); + FlossDBusClient::WriteAllDBusParams(&writer, id, socket); + + sockmgr_->OnHandleIncomingConnection(&method_call, std::move(response)); + } + void SockStatusCb(DBusResult<BtifStatus> result) { if (!result.has_value()) { last_status_ = BtifStatus::kFail; @@ -140,11 +213,13 @@ FlossSocketManager::ServerSocketState state, FlossSocketManager::FlossListeningSocket socket, BtifStatus status) { - // No-op + last_state_ = state; + last_server_socket_ = socket; + last_status_ = status; } void SockConnectionAccepted(FlossSocketManager::FlossSocket&& socket) { - // No -op + last_incoming_socket_ = std::move(socket); } void ExpectNormalResponse(std::unique_ptr<dbus::Response> response) { @@ -155,7 +230,11 @@ int adapter_index_ = 2; int serial_ = 1; dbus::ObjectPath adapter_path_; + + FlossSocketManager::ServerSocketState last_state_; + FlossSocketManager::FlossListeningSocket last_server_socket_; BtifStatus last_status_; + FlossSocketManager::FlossSocket last_incoming_socket_; uint32_t callback_id_ctr_ = 1; uint64_t socket_id_ctr_ = 1; @@ -338,4 +417,129 @@ } } +// Really basic calls to accept and close +TEST_F(FlossSocketManagerTest, AcceptAndCloseConnection) { + Init(); + + EXPECT_CALL( + *sockmgr_proxy_.get(), + DoCallMethodWithErrorResponse(HasMemberOf(socket_manager::kAccept), _, _)) + .WillOnce(Invoke(this, &FlossSocketManagerTest::HandleReturnSuccess)); + + last_status_ = BtifStatus::kNotReady; + sockmgr_->Accept(socket_id_ctr_, 42, + base::BindOnce(&FlossSocketManagerTest::SockStatusCb, + weak_ptr_factory_.GetWeakPtr())); + EXPECT_EQ(BtifStatus::kSuccess, last_status_); + + EXPECT_CALL( + *sockmgr_proxy_.get(), + DoCallMethodWithErrorResponse(HasMemberOf(socket_manager::kClose), _, _)) + .WillOnce(Invoke(this, &FlossSocketManagerTest::HandleReturnSuccess)); + + last_status_ = BtifStatus::kNotReady; + sockmgr_->Close(socket_id_ctr_, + base::BindOnce(&FlossSocketManagerTest::SockStatusCb, + weak_ptr_factory_.GetWeakPtr())); + EXPECT_EQ(BtifStatus::kSuccess, last_status_); +} + +// Handle state changes from calling accept and close. +TEST_F(FlossSocketManagerTest, IncomingStateChanges) { + Init(); + SetupListeningSocket(); + + // With a bad id, callbacks will never be dispatched. + FlossSocketManager::FlossListeningSocket bad_socket; + bad_socket.id = 123456789; + + // Good id is the last socket ctr we used. + FlossSocketManager::FlossListeningSocket good_socket; + good_socket.id = socket_id_ctr_ - 1; + good_socket.name = "Foo"; + good_socket.uuid = device::BluetoothUUID("F00D"); + + // Empty out the last seen status and socket. + last_status_ = BtifStatus::kNotReady; + last_server_socket_ = FlossSocketManager::FlossListeningSocket(); + last_state_ = FlossSocketManager::ServerSocketState::kClosed; + + EXPECT_FALSE(last_server_socket_.is_valid()); + // Send an invalid update. Should result in no callbacks being called. + SendIncomingSocketReady( + bad_socket, BtifStatus::kSuccess, + base::BindOnce(&FlossSocketManagerTest::ExpectNormalResponse, + weak_ptr_factory_.GetWeakPtr())); + EXPECT_EQ(BtifStatus::kNotReady, last_status_); + EXPECT_FALSE(last_server_socket_.is_valid()); + + // Send a successful ready to a valid socket. + SendIncomingSocketReady( + good_socket, BtifStatus::kSuccess, + base::BindOnce(&FlossSocketManagerTest::ExpectNormalResponse, + weak_ptr_factory_.GetWeakPtr())); + EXPECT_EQ(BtifStatus::kSuccess, last_status_); + EXPECT_EQ(last_state_, FlossSocketManager::ServerSocketState::kReady); + EXPECT_TRUE(last_server_socket_.is_valid()); + + // Empty out the last seen status and socket. + last_status_ = BtifStatus::kNotReady; + last_server_socket_ = FlossSocketManager::FlossListeningSocket(); + + // Send an invalid update. Should result in no callbacks being called. + SendIncomingSocketClosed( + bad_socket.id, BtifStatus::kSuccess, + base::BindOnce(&FlossSocketManagerTest::ExpectNormalResponse, + weak_ptr_factory_.GetWeakPtr())); + EXPECT_EQ(BtifStatus::kNotReady, last_status_); + EXPECT_FALSE(last_server_socket_.is_valid()); + + // Send a successful close to a valid socket. + SendIncomingSocketClosed( + good_socket.id, BtifStatus::kSuccess, + base::BindOnce(&FlossSocketManagerTest::ExpectNormalResponse, + weak_ptr_factory_.GetWeakPtr())); + EXPECT_EQ(BtifStatus::kSuccess, last_status_); + EXPECT_EQ(last_server_socket_.id, good_socket.id); + EXPECT_EQ(last_state_, FlossSocketManager::ServerSocketState::kClosed); + + // Try sending a ready to the same socket and nothing should happen. + last_status_ = BtifStatus::kNotReady; + SendIncomingSocketReady( + good_socket, BtifStatus::kSuccess, + base::BindOnce(&FlossSocketManagerTest::ExpectNormalResponse, + weak_ptr_factory_.GetWeakPtr())); + EXPECT_EQ(BtifStatus::kNotReady, last_status_); +} + +// Handle incoming socket connections. +TEST_F(FlossSocketManagerTest, IncomingConnections) { + Init(); + SetupListeningSocket(); + + // With a bad id, callbacks will never be dispatched. + FlossSocketManager::FlossSocket bad_socket; + bad_socket.id = 123456789; + + // Good id is the last socket ctr we used. + FlossSocketManager::FlossSocket good_socket; + good_socket.id = socket_id_ctr_ - 1; + + last_incoming_socket_ = FlossSocketManager::FlossSocket(); + EXPECT_FALSE(last_incoming_socket_.is_valid()); + + SendIncomingConnection( + bad_socket.id, bad_socket, + base::BindOnce(&FlossSocketManagerTest::ExpectNormalResponse, + weak_ptr_factory_.GetWeakPtr())); + EXPECT_FALSE(last_incoming_socket_.is_valid()); + + SendIncomingConnection( + good_socket.id, good_socket, + base::BindOnce(&FlossSocketManagerTest::ExpectNormalResponse, + weak_ptr_factory_.GetWeakPtr())); + EXPECT_TRUE(last_incoming_socket_.is_valid()); + EXPECT_EQ(last_incoming_socket_.id, good_socket.id); +} + } // namespace floss
diff --git a/extensions/browser/api/execute_code_function.cc b/extensions/browser/api/execute_code_function.cc index 765028b..27e7386 100644 --- a/extensions/browser/api/execute_code_function.cc +++ b/extensions/browser/api/execute_code_function.cc
@@ -134,10 +134,13 @@ sources.push_back(mojom::JSSource::New(code_string, script_url_)); // tabs.executeScript does not support waiting for promises (only // scripting.executeScript does). - constexpr bool kWaitForPromises = false; injection = mojom::CodeInjection::NewJs(mojom::JSInjection::New( - std::move(sources), mojom::ExecutionWorld::kIsolated, wants_result, - user_gesture(), kWaitForPromises)); + std::move(sources), mojom::ExecutionWorld::kIsolated, + wants_result ? blink::mojom::WantResultOption::kWantResult + : blink::mojom::WantResultOption::kNoResult, + user_gesture() ? blink::mojom::UserActivationOption::kActivate + : blink::mojom::UserActivationOption::kDoNotActivate, + blink::mojom::PromiseResultOption::kDoNotWait)); } executor->ExecuteScript(
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc index 147e9fa..cfa38f1 100644 --- a/extensions/browser/extension_prefs.cc +++ b/extensions/browser/extension_prefs.cc
@@ -725,14 +725,18 @@ return true; } +const base::Value* ExtensionPrefs::GetPrefAsValue( + const std::string& extension_id, + base::StringPiece pref_key) const { + const base::DictionaryValue* ext = GetExtensionPref(extension_id); + return ext ? ext->FindDictPath(pref_key) : nullptr; +} + bool ExtensionPrefs::ReadPrefAsDictionary( const std::string& extension_id, base::StringPiece pref_key, const base::DictionaryValue** out_value) const { - const base::DictionaryValue* ext = GetExtensionPref(extension_id); - if (!ext) - return false; - const base::Value* out = ext->FindDictPath(pref_key); + const base::Value* out = GetPrefAsValue(extension_id, pref_key); if (!out) return false; if (out_value) @@ -741,6 +745,13 @@ return true; } +const base::Value::Dict* ExtensionPrefs::ReadPrefAsDict( + const std::string& extension_id, + base::StringPiece pref_key) const { + const base::Value* out = GetPrefAsValue(extension_id, pref_key); + return out ? &out->GetDict() : nullptr; +} + bool ExtensionPrefs::HasPrefForExtension( const std::string& extension_id) const { return GetExtensionPref(extension_id) != NULL;
diff --git a/extensions/browser/extension_prefs.h b/extensions/browser/extension_prefs.h index 1fd512f..e98d4e5 100644 --- a/extensions/browser/extension_prefs.h +++ b/extensions/browser/extension_prefs.h
@@ -350,10 +350,14 @@ base::StringPiece pref_key, const base::ListValue** out_value) const; + // DEPRECATED: prefer ReadPrefAsDict() instead. bool ReadPrefAsDictionary(const std::string& extension_id, base::StringPiece pref_key, const base::DictionaryValue** out_value) const; + const base::Value::Dict* ReadPrefAsDict(const std::string& extension_id, + base::StringPiece pref_key) const; + // Interprets the list pref, |pref_key| in |extension_id|'s preferences, as a // URLPatternSet. The |valid_schemes| specify how to parse the URLPatterns. bool ReadPrefAsURLPatternSet(const std::string& extension_id, @@ -848,6 +852,11 @@ // doesn't exist. const base::DictionaryValue* GetExtensionPref(const std::string& id) const; + // Returns an immutable base::Value for extension |id|'s prefs, or nullptr if + // it doesn't exist. + const base::Value* GetPrefAsValue(const std::string& extension_id, + base::StringPiece pref_key) const; + // Modifies the extensions disable reasons to add a new reason, remove an // existing reason, or clear all reasons. Notifies observers if the set of // DisableReasons has changed.
diff --git a/extensions/common/mojom/code_injection.mojom b/extensions/common/mojom/code_injection.mojom index b2c0d3ba1..375c14e 100644 --- a/extensions/common/mojom/code_injection.mojom +++ b/extensions/common/mojom/code_injection.mojom
@@ -6,6 +6,7 @@ import "extensions/common/mojom/css_origin.mojom"; import "extensions/common/mojom/execution_world.mojom"; +import "third_party/blink/public/mojom/script/script_evaluation_params.mojom"; import "url/mojom/url.mojom"; // A single JS source to execute in the renderer. @@ -37,15 +38,15 @@ // Whether the caller is interested in the result value. Manifest-declared // content scripts and executeScript() calls without a response callback - // are examples of when this will be false. - bool wants_result; + // are examples of when this will be `kNoResult`. + blink.mojom.WantResultOption wants_result; - // Whether the code to be executed should be associated with a user gesture. - bool user_gesture; + // Whether the code to be executed with synthesized user activation. + blink.mojom.UserActivationOption user_gesture; - // If true and a script evaluates to a promise, causes the injection to - // wait for the promise to resolve and pass back the result. - bool wait_for_promise; + // For scripts that evaluate to promises, whether to wait for the resolution + // of the resulting promises. + blink.mojom.PromiseResultOption wait_for_promise; }; // A struct representing a collection of CSS code to insert in the renderer.
diff --git a/extensions/renderer/api/automation/automation_internal_custom_bindings.cc b/extensions/renderer/api/automation/automation_internal_custom_bindings.cc index 06771c3..67a717ed 100644 --- a/extensions/renderer/api/automation/automation_internal_custom_bindings.cc +++ b/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
@@ -2455,7 +2455,8 @@ ui::AXTreeID tree_id = event_bundle.tree_id; AutomationAXTreeWrapper* tree_wrapper; auto iter = tree_id_to_tree_wrapper_map_.find(tree_id); - if (iter == tree_id_to_tree_wrapper_map_.end()) { + bool is_new_tree = iter == tree_id_to_tree_wrapper_map_.end(); + if (is_new_tree) { tree_wrapper = new AutomationAXTreeWrapper(tree_id, this); tree_id_to_tree_wrapper_map_.insert( std::make_pair(tree_id, base::WrapUnique(tree_wrapper))); @@ -2473,6 +2474,16 @@ return; } + // Send an initial event to ensure the js-side objects get created for new + // trees. + if (is_new_tree) { + ui::AXEvent initial_event; + initial_event.id = -1; + initial_event.event_from = ax::mojom::EventFrom::kNone; + initial_event.event_type = ax::mojom::Event::kNone; + SendAutomationEvent(tree_id, gfx::Point(), initial_event); + } + // After handling events in js, if the client did not add any event listeners, // shut things down. TreeEventListenersChanged(tree_wrapper); @@ -2615,11 +2626,12 @@ api::automation::ToString(automation_event_type); // These events get used internally to trigger other behaviors in js. - ax::mojom::Event ax_event = event.event_type; - bool fire_event = ax_event == ax::mojom::Event::kNone || - ax_event == ax::mojom::Event::kHitTestResult || - ax_event == ax::mojom::Event::kMediaStartedPlaying || - ax_event == ax::mojom::Event::kMediaStoppedPlaying; + bool fire_event = + automation_event_type == api::automation::EVENT_TYPE_NONE || + automation_event_type == api::automation::EVENT_TYPE_HITTESTRESULT || + automation_event_type == + api::automation::EVENT_TYPE_MEDIASTARTEDPLAYING || + automation_event_type == api::automation::EVENT_TYPE_MEDIASTOPPEDPLAYING; // If we don't explicitly recognize the event type, require a valid, unignored // node target. @@ -2629,8 +2641,10 @@ return; while (node && tree_wrapper && !fire_event) { - if (tree_wrapper->HasEventListener(automation_event_type, node)) + if (tree_wrapper->HasEventListener(automation_event_type, node)) { fire_event = true; + break; + } node = GetParent(node, &tree_wrapper); } @@ -2669,6 +2683,9 @@ args.Append(std::move(event_params)); bindings_system_->DispatchEventInContext( "automationInternal.onAccessibilityEvent", args, nullptr, context()); + + if (!notify_event_for_testing_.is_null()) + notify_event_for_testing_.Run(automation_event_type); } void AutomationInternalCustomBindings::MaybeSendFocusAndBlur(
diff --git a/extensions/renderer/api/automation/automation_internal_custom_bindings.h b/extensions/renderer/api/automation/automation_internal_custom_bindings.h index 826dbd9..86e5795 100644 --- a/extensions/renderer/api/automation/automation_internal_custom_bindings.h +++ b/extensions/renderer/api/automation/automation_internal_custom_bindings.h
@@ -308,6 +308,9 @@ // Keeps track of all trees with event listeners. std::set<ui::AXTreeID> trees_with_event_listeners_; + base::RepeatingCallback<void(api::automation::EventType)> + notify_event_for_testing_; + base::WeakPtrFactory<AutomationInternalCustomBindings> weak_ptr_factory_{ this}; };
diff --git a/extensions/renderer/api/automation/automation_internal_custom_bindings_unittests.cc b/extensions/renderer/api/automation/automation_internal_custom_bindings_unittests.cc index 422138a..12b5ce5 100644 --- a/extensions/renderer/api/automation/automation_internal_custom_bindings_unittests.cc +++ b/extensions/renderer/api/automation/automation_internal_custom_bindings_unittests.cc
@@ -4,6 +4,7 @@ #include "extensions/renderer/api/automation/automation_internal_custom_bindings.h" +#include "base/test/bind.h" #include "extensions/common/constants.h" #include "extensions/common/extension_builder.h" #include "extensions/common/extension_messages.h" @@ -82,6 +83,12 @@ return automation_internal_bindings_->GetRootsOfChildTree(node); } + void AddAutomationEventCallback( + base::RepeatingCallback<void(api::automation::EventType)> callback) { + automation_internal_bindings_->notify_event_for_testing_ = + std::move(callback); + } + private: AutomationInternalCustomBindings* automation_internal_bindings_ = nullptr; }; @@ -639,4 +646,103 @@ EXPECT_EQ(3, child_roots[1]->id()); } +TEST_F(AutomationInternalCustomBindingsTest, FireEventsWithListeners) { + // A simple tree. + ExtensionMsg_AccessibilityEventBundleParams bundle; + bundle.updates.emplace_back(); + auto& tree_update = bundle.updates.back(); + tree_update.has_tree_data = true; + tree_update.root_id = 1; + auto& tree_data = tree_update.tree_data; + tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID(); + bundle.tree_id = tree_data.tree_id; + tree_update.nodes.emplace_back(); + auto& node_data1 = tree_update.nodes.back(); + node_data1.id = 1; + node_data1.role = ax::mojom::Role::kRootWebArea; + node_data1.child_ids.push_back(2); + node_data1.relative_bounds.bounds = gfx::RectF(100, 100, 100, 100); + tree_update.nodes.emplace_back(); + auto& node_data2 = tree_update.nodes.back(); + node_data2.id = 2; + node_data2.role = ax::mojom::Role::kButton; + node_data2.relative_bounds.bounds = gfx::RectF(0, 0, 200, 200); + + // Add a hook for events from automation. + std::vector<api::automation::EventType> events; + AddAutomationEventCallback(base::BindLambdaForTesting( + [&](api::automation::EventType event) { events.push_back(event); })); + + SendOnAccessibilityEvents(bundle, true /* active profile */); + + // We aren't listening for any events yet, but we should still get one that + // gets fired on initial tree creation. + ASSERT_EQ(1U, events.size()); + EXPECT_EQ(api::automation::EVENT_TYPE_NONE, events[0]); + events.clear(); + + // Remove the root node data and don't update tree data. + tree_update.nodes.erase(tree_update.nodes.begin()); + tree_update.has_tree_data = false; + + // Trigger a role change. + tree_update.nodes[0].role = ax::mojom::Role::kSwitch; + SendOnAccessibilityEvents(bundle, true /* active profile */); + + // There should be no events since there are no listeners and this isn't the + // initial tree. + ASSERT_TRUE(events.empty()); + + // Add a role change listener and do trigger the role change again. + auto* wrapper = GetTreeIDToTreeMap()[tree_data.tree_id].get(); + auto* tree = wrapper->tree(); + // The button is id 2. + wrapper->EventListenerAdded(api::automation::EVENT_TYPE_ROLECHANGED, + tree->GetFromId(2)); + tree_update.nodes[0].role = ax::mojom::Role::kButton; + SendOnAccessibilityEvents(bundle, true /* active profile */); + + // We should now have exactly one event. + ASSERT_EQ(1U, events.size()); + EXPECT_EQ(api::automation::EVENT_TYPE_ROLECHANGED, events[0]); + events.clear(); + + // Now, remove the listener and do the same as above. + wrapper->EventListenerRemoved(api::automation::EVENT_TYPE_ROLECHANGED, + tree->GetFromId(2)); + // We have to add another listener to ensure we don't shut down (no event + // listeners means this renderer closes). + wrapper->EventListenerAdded(api::automation::EVENT_TYPE_LOADCOMPLETE, + tree->GetFromId(1)); + tree_update.nodes[0].role = ax::mojom::Role::kSwitch; + SendOnAccessibilityEvents(bundle, true /* active profile */); + + // We should have no events. + ASSERT_TRUE(events.empty()); + + // Finally, let's fire a non-generated event on the button, but add the + // listener on the root. This will test both non-generated events and + // respecting event listeners on ancestors of the target. + + // First, fire the event without the click listener. + tree_update.nodes.clear(); + bundle.events.emplace_back(); + auto& event = bundle.events.back(); + event.event_type = ax::mojom::Event::kClicked; + event.id = 2; + SendOnAccessibilityEvents(bundle, true /* active profile */); + + // No event. + ASSERT_TRUE(events.empty()); + + // Now, add the click listener to the root, and fire the click event on the + // button. + wrapper->EventListenerAdded(api::automation::EVENT_TYPE_CLICKED, + tree->GetFromId(1)); + SendOnAccessibilityEvents(bundle, true /* active profile */); + + ASSERT_EQ(1U, events.size()); + EXPECT_EQ(api::automation::EVENT_TYPE_CLICKED, events[0]); +} + } // namespace extensions
diff --git a/extensions/renderer/programmatic_script_injector.cc b/extensions/renderer/programmatic_script_injector.cc index fa5d86a..37c6b12 100644 --- a/extensions/renderer/programmatic_script_injector.cc +++ b/extensions/renderer/programmatic_script_injector.cc
@@ -39,7 +39,8 @@ return mojom::InjectionType::kProgrammaticScript; } -bool ProgrammaticScriptInjector::IsUserGesture() const { +blink::mojom::UserActivationOption ProgrammaticScriptInjector::IsUserGesture() + const { DCHECK(params_->injection->is_js()); return params_->injection->get_js()->user_gesture; } @@ -60,12 +61,14 @@ return params_->injection->get_css()->operation; } -bool ProgrammaticScriptInjector::ExpectsResults() const { +blink::mojom::WantResultOption ProgrammaticScriptInjector::ExpectsResults() + const { DCHECK(params_->injection->is_js()); return params_->injection->get_js()->wants_result; } -bool ProgrammaticScriptInjector::ShouldWaitForPromise() const { +blink::mojom::PromiseResultOption +ProgrammaticScriptInjector::ShouldWaitForPromise() const { DCHECK(params_->injection->is_js()); return params_->injection->get_js()->wait_for_promise; }
diff --git a/extensions/renderer/programmatic_script_injector.h b/extensions/renderer/programmatic_script_injector.h index 761c8b62..cda5691 100644 --- a/extensions/renderer/programmatic_script_injector.h +++ b/extensions/renderer/programmatic_script_injector.h
@@ -34,12 +34,12 @@ private: // ScriptInjector implementation. mojom::InjectionType script_type() const override; - bool IsUserGesture() const override; + blink::mojom::UserActivationOption IsUserGesture() const override; mojom::ExecutionWorld GetExecutionWorld() const override; mojom::CSSOrigin GetCssOrigin() const override; mojom::CSSInjection::Operation GetCSSInjectionOperation() const override; - bool ExpectsResults() const override; - bool ShouldWaitForPromise() const override; + blink::mojom::WantResultOption ExpectsResults() const override; + blink::mojom::PromiseResultOption ShouldWaitForPromise() const override; bool ShouldInjectJs( mojom::RunLocation run_location, const std::set<std::string>& executing_scripts) const override;
diff --git a/extensions/renderer/script_injection.cc b/extensions/renderer/script_injection.cc index 621e25e..19c8ff67 100644 --- a/extensions/renderer/script_injection.cc +++ b/extensions/renderer/script_injection.cc
@@ -327,7 +327,6 @@ std::vector<blink::WebScriptSource> sources = injector_->GetJsSources( run_location_, executing_scripts, num_injected_js_scripts); DCHECK(!sources.empty()); - bool is_user_gesture = injector_->IsUserGesture(); std::unique_ptr<blink::WebScriptExecutionCallback> callback( new TimedScriptInjectionCallback(weak_ptr_factory_.GetWeakPtr())); @@ -345,29 +344,29 @@ injector_->script_type() == mojom::InjectionType::kContentScript && (run_location_ == mojom::RunLocation::kDocumentEnd || run_location_ == mojom::RunLocation::kDocumentIdle); - blink::WebLocalFrame::ScriptExecutionType execution_option = + blink::mojom::EvaluationTiming execution_option = should_execute_asynchronously - ? blink::WebLocalFrame::kAsynchronousBlockingOnload - : blink::WebLocalFrame::kSynchronous; + ? blink::mojom::EvaluationTiming::kAsynchronous + : blink::mojom::EvaluationTiming::kSynchronous; - mojom::ExecutionWorld execution_world = injector_->GetExecutionWorld(); int32_t world_id = blink::kMainDOMWorldId; - if (execution_world == mojom::ExecutionWorld::kIsolated) { - world_id = GetIsolatedWorldIdForInstance(injection_host_.get()); - if (injection_host_->id().type == mojom::HostID::HostType::kExtensions && - log_activity_) { - DOMActivityLogger::AttachToWorld(world_id, injection_host_->id().id); - } - } else { - DCHECK_EQ(mojom::ExecutionWorld::kMain, execution_world); + switch (injector_->GetExecutionWorld()) { + case mojom::ExecutionWorld::kIsolated: + world_id = GetIsolatedWorldIdForInstance(injection_host_.get()); + if (injection_host_->id().type == mojom::HostID::HostType::kExtensions && + log_activity_) { + DOMActivityLogger::AttachToWorld(world_id, injection_host_->id().id); + } + break; + case mojom::ExecutionWorld::kMain: + world_id = blink::kMainDOMWorldId; + break; } - auto promise_behavior = - injector_->ShouldWaitForPromise() - ? blink::WebLocalFrame::PromiseBehavior::kAwait - : blink::WebLocalFrame::PromiseBehavior::kDontWait; render_frame_->GetWebFrame()->RequestExecuteScript( - world_id, sources, is_user_gesture, execution_option, callback.release(), - blink::BackForwardCacheAware::kPossiblyDisallow, promise_behavior); + world_id, sources, injector_->IsUserGesture(), execution_option, + blink::mojom::LoadEventBlockingOption::kBlock, callback.release(), + blink::BackForwardCacheAware::kPossiblyDisallow, + injector_->ShouldWaitForPromise()); } void ScriptInjection::OnJsInjectionCompleted( @@ -396,8 +395,8 @@ } } - bool expects_results = injector_->ExpectsResults(); - if (expects_results) { + if (injector_->ExpectsResults() == + blink::mojom::WantResultOption::kWantResult) { if (!results.empty() && !results.back().IsEmpty()) { // Right now, we only support returning single results (per frame). // It's safe to always use the main world context when converting
diff --git a/extensions/renderer/script_injector.h b/extensions/renderer/script_injector.h index e7c6d85..8abefe47 100644 --- a/extensions/renderer/script_injector.h +++ b/extensions/renderer/script_injector.h
@@ -50,8 +50,8 @@ // Returns the script type of this particular injection. virtual mojom::InjectionType script_type() const = 0; - // Returns true if the script is running inside a user gesture. - virtual bool IsUserGesture() const = 0; + // Returns the associated `UserActivationOption` for script evaluation. + virtual blink::mojom::UserActivationOption IsUserGesture() const = 0; // Returns the world in which to execute the javascript code. virtual mojom::ExecutionWorld GetExecutionWorld() const = 0; @@ -63,11 +63,11 @@ // performed. virtual mojom::CSSInjection::Operation GetCSSInjectionOperation() const = 0; - // Returns true if the script expects results. - virtual bool ExpectsResults() const = 0; + // Returns the associated `WantResultOption` for script evaluation. + virtual blink::mojom::WantResultOption ExpectsResults() const = 0; - // Whether to wait for a promise result to resolve. - virtual bool ShouldWaitForPromise() const = 0; + // Returns the associated `PromiseResultOption` for script evaluation. + virtual blink::mojom::PromiseResultOption ShouldWaitForPromise() const = 0; // Returns true if the script should inject JS source at the given // |run_location|.
diff --git a/extensions/renderer/user_script_injector.cc b/extensions/renderer/user_script_injector.cc index 4d0648d..1ef39cc 100644 --- a/extensions/renderer/user_script_injector.cc +++ b/extensions/renderer/user_script_injector.cc
@@ -138,20 +138,21 @@ return mojom::InjectionType::kContentScript; } -bool UserScriptInjector::IsUserGesture() const { - return false; +blink::mojom::UserActivationOption UserScriptInjector::IsUserGesture() const { + return blink::mojom::UserActivationOption::kDoNotActivate; } mojom::ExecutionWorld UserScriptInjector::GetExecutionWorld() const { return script_->execution_world(); } -bool UserScriptInjector::ExpectsResults() const { - return false; +blink::mojom::WantResultOption UserScriptInjector::ExpectsResults() const { + return blink::mojom::WantResultOption::kNoResult; } -bool UserScriptInjector::ShouldWaitForPromise() const { - return false; +blink::mojom::PromiseResultOption UserScriptInjector::ShouldWaitForPromise() + const { + return blink::mojom::PromiseResultOption::kDoNotWait; } mojom::CSSOrigin UserScriptInjector::GetCssOrigin() const {
diff --git a/extensions/renderer/user_script_injector.h b/extensions/renderer/user_script_injector.h index 5509e5b7..dd7fdebc6 100644 --- a/extensions/renderer/user_script_injector.h +++ b/extensions/renderer/user_script_injector.h
@@ -45,12 +45,12 @@ // ScriptInjector implementation. mojom::InjectionType script_type() const override; - bool IsUserGesture() const override; + blink::mojom::UserActivationOption IsUserGesture() const override; mojom::ExecutionWorld GetExecutionWorld() const override; mojom::CSSOrigin GetCssOrigin() const override; mojom::CSSInjection::Operation GetCSSInjectionOperation() const override; - bool ExpectsResults() const override; - bool ShouldWaitForPromise() const override; + blink::mojom::WantResultOption ExpectsResults() const override; + blink::mojom::PromiseResultOption ShouldWaitForPromise() const override; bool ShouldInjectJs( mojom::RunLocation run_location, const std::set<std::string>& executing_scripts) const override;
diff --git a/fuchsia_web/webengine/browser/web_engine_permission_delegate.cc b/fuchsia_web/webengine/browser/web_engine_permission_delegate.cc index 2c9bb37..6bc15db3 100644 --- a/fuchsia_web/webengine/browser/web_engine_permission_delegate.cc +++ b/fuchsia_web/webengine/browser/web_engine_permission_delegate.cc
@@ -70,7 +70,7 @@ for (const auto& permission : permissions) { permission_strings.push_back( permissions::PermissionUtil::GetPermissionString( - permissions::PermissionUtil::PermissionTypeToContentSetting( + permissions::PermissionUtil::PermissionTypeToContentSettingType( permission))); } @@ -99,6 +99,17 @@ return blink::mojom::PermissionStatus::DENIED; } +content::PermissionResult +WebEnginePermissionDelegate::GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) { + blink::mojom::PermissionStatus status = + GetPermissionStatus(permission, origin.GetURL(), origin.GetURL()); + + return content::PermissionResult( + status, content::PermissionStatusSource::UNSPECIFIED); +} + blink::mojom::PermissionStatus WebEnginePermissionDelegate::GetPermissionStatusForCurrentDocument( blink::PermissionType permission,
diff --git a/fuchsia_web/webengine/browser/web_engine_permission_delegate.h b/fuchsia_web/webengine/browser/web_engine_permission_delegate.h index 7c034b3..639f11d0 100644 --- a/fuchsia_web/webengine/browser/web_engine_permission_delegate.h +++ b/fuchsia_web/webengine/browser/web_engine_permission_delegate.h
@@ -6,6 +6,7 @@ #define FUCHSIA_WEB_WEBENGINE_BROWSER_WEB_ENGINE_PERMISSION_DELEGATE_H_ #include "content/public/browser/permission_controller_delegate.h" +#include "content/public/browser/permission_result.h" namespace blink { enum class PermissionType; @@ -53,6 +54,9 @@ blink::PermissionType permission, const GURL& requesting_origin, const GURL& embedding_origin) override; + content::PermissionResult GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) override; blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument( blink::PermissionType permission, content::RenderFrameHost* render_frame_host) override;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc index ff99584..4724174 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -2846,8 +2846,7 @@ TRACE_EVENT_NESTABLE_ASYNC_END0( "cc", "GLES2DecoderPassthroughImpl::DescheduleUntilFinished", TRACE_ID_LOCAL(this)); - deschedule_until_finished_fences_.erase( - deschedule_until_finished_fences_.begin()); + deschedule_until_finished_fences_.pop_front(); client()->OnRescheduleAfterFinished(); }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h index 6d48a0d..668711f 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -9,11 +9,11 @@ #include <algorithm> #include <memory> -#include <set> -#include <unordered_map> #include <vector> #include "base/containers/circular_deque.h" +#include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "gpu/command_buffer/common/debug_marker_manager.h" @@ -141,7 +141,7 @@ // Mapping of client buffer IDs that are mapped to the shared memory used to // back the mapping so that it can be flushed when the buffer is unmapped - std::unordered_map<GLuint, MappedBuffer> mapped_buffer_map; + base::flat_map<GLuint, MappedBuffer> mapped_buffer_map; }; class GPU_GLES2_EXPORT GLES2DecoderPassthroughImpl @@ -655,7 +655,7 @@ std::vector<TexturePendingBinding> textures_pending_binding_; // State tracking of currently bound buffers - std::unordered_map<GLenum, GLuint> bound_buffers_; + base::flat_map<GLenum, GLuint> bound_buffers_; // Lazy tracking of the bound element array buffer when changing VAOs. bool bound_element_array_buffer_dirty_; @@ -663,7 +663,7 @@ struct QueryInfo { GLenum type = GL_NONE; }; - std::unordered_map<GLuint, QueryInfo> query_info_map_; + base::flat_map<GLuint, QueryInfo> query_info_map_; // All queries that are waiting for their results to be ready struct PendingQuery { @@ -711,7 +711,7 @@ base::TimeTicks command_processing_start_time; base::TimeDelta active_time; }; - std::unordered_map<GLenum, ActiveQuery> active_queries_; + base::flat_map<GLenum, ActiveQuery> active_queries_; // Pending async ReadPixels calls struct PendingReadPixels { @@ -757,7 +757,7 @@ BufferShadowUpdateMap buffer_shadow_updates_; // Error state - std::set<GLenum> errors_; + base::flat_set<GLenum> errors_; // Checks if an error has been generated since the last call to // CheckErrorCallbackState @@ -879,7 +879,8 @@ // After a second fence is inserted, both the GpuChannelMessageQueue and // CommandExecutor are descheduled. Once the first fence has completed, both // get rescheduled. - std::vector<std::unique_ptr<gl::GLFence>> deschedule_until_finished_fences_; + base::circular_deque<std::unique_ptr<gl::GLFence>> + deschedule_until_finished_fences_; GLuint linking_program_service_id_ = 0u;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc index d962cbb..3f404a8c8 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
@@ -4647,8 +4647,7 @@ DCHECK_EQ(2u, deschedule_until_finished_fences_.size()); if (deschedule_until_finished_fences_[0]->HasCompleted()) { - deschedule_until_finished_fences_.erase( - deschedule_until_finished_fences_.begin()); + deschedule_until_finished_fences_.pop_front(); return error::kNoError; }
diff --git a/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc index 2487a39..84a6495 100644 --- a/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc
@@ -41,9 +41,6 @@ return estimated_size; } -using ScopedResetAndRestoreUnpackState = - GLTextureImageBackingHelper::ScopedResetAndRestoreUnpackState; - using ScopedRestoreTexture = GLTextureImageBackingHelper::ScopedRestoreTexture; class AngleVulkanImageBacking : public ClearTrackingSharedImageBacking,
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing.cc b/gpu/command_buffer/service/shared_image/egl_image_backing.cc index b14dde0..83555476 100644 --- a/gpu/command_buffer/service/shared_image/egl_image_backing.cc +++ b/gpu/command_buffer/service/shared_image/egl_image_backing.cc
@@ -186,7 +186,6 @@ size_t estimated_size, const GLCommonImageBackingFactory::FormatInfo format_info, const GpuDriverBugWorkarounds& workarounds, - const GLTextureImageBackingHelper::UnpackStateAttribs& attribs, bool use_passthrough, base::span<const uint8_t> pixel_data) : ClearTrackingSharedImageBacking(mailbox, @@ -199,7 +198,6 @@ estimated_size, true /*is_thread_safe*/), format_info_(format_info), - gl_unpack_attribs_(attribs), use_passthrough_(use_passthrough) { created_on_context_ = gl::g_current_gl_context; // On some GPUs (NVidia) keeping reference to egl image itself is not enough, @@ -405,21 +403,20 @@ if (!pixel_data.empty()) { GLTextureImageBackingHelper::ScopedResetAndRestoreUnpackState - scoped_unpack_state(api, gl_unpack_attribs_, - true /* uploading_data */); + scoped_unpack_state(/*uploading_data=*/true); api->glTexSubImage2DFn(target, 0, 0, 0, size().width(), size().height(), format_info_.adjusted_format, format_info_.gl_type, pixel_data.data()); } } else if (format_info_.is_compressed) { GLTextureImageBackingHelper::ScopedResetAndRestoreUnpackState - scoped_unpack_state(api, gl_unpack_attribs_, !pixel_data.empty()); + scoped_unpack_state(!pixel_data.empty()); api->glCompressedTexImage2DFn( target, 0, format_info_.image_internal_format, size().width(), size().height(), 0, pixel_data.size(), pixel_data.data()); } else { GLTextureImageBackingHelper::ScopedResetAndRestoreUnpackState - scoped_unpack_state(api, gl_unpack_attribs_, !pixel_data.empty()); + scoped_unpack_state(!pixel_data.empty()); api->glTexImage2DFn(target, 0, format_info_.image_internal_format, size().width(), size().height(), 0,
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing.h b/gpu/command_buffer/service/shared_image/egl_image_backing.h index e2d2902..b4b82ba 100644 --- a/gpu/command_buffer/service/shared_image/egl_image_backing.h +++ b/gpu/command_buffer/service/shared_image/egl_image_backing.h
@@ -36,20 +36,18 @@ // group. This is achieved by using locks and fences for proper synchronization. class EGLImageBacking : public ClearTrackingSharedImageBacking { public: - EGLImageBacking( - const Mailbox& mailbox, - viz::ResourceFormat format, - const gfx::Size& size, - const gfx::ColorSpace& color_space, - GrSurfaceOrigin surface_origin, - SkAlphaType alpha_type, - uint32_t usage, - size_t estimated_size, - const GLCommonImageBackingFactory::FormatInfo format_into, - const GpuDriverBugWorkarounds& workarounds, - const GLTextureImageBackingHelper::UnpackStateAttribs& attribs, - bool use_passthrough, - base::span<const uint8_t> pixel_data); + EGLImageBacking(const Mailbox& mailbox, + viz::ResourceFormat format, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + GrSurfaceOrigin surface_origin, + SkAlphaType alpha_type, + uint32_t usage, + size_t estimated_size, + const GLCommonImageBackingFactory::FormatInfo format_into, + const GpuDriverBugWorkarounds& workarounds, + bool use_passthrough, + base::span<const uint8_t> pixel_data); EGLImageBacking(const EGLImageBacking&) = delete; EGLImageBacking& operator=(const EGLImageBacking&) = delete; @@ -122,7 +120,6 @@ base::flat_set<const GLRepresentationShared*> active_readers_ GUARDED_BY(lock_); - const GLTextureImageBackingHelper::UnpackStateAttribs gl_unpack_attribs_; const bool use_passthrough_; };
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc index c269777..d2c0020e 100644 --- a/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc
@@ -137,8 +137,7 @@ return std::make_unique<EGLImageBacking>( mailbox, format, size, color_space, surface_origin, alpha_type, usage, - estimated_size, format_info, workarounds_, attribs_, use_passthrough_, - pixel_data); + estimated_size, format_info, workarounds_, use_passthrough_, pixel_data); } } // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.cc index 606ff3f..56fe64e1 100644 --- a/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.cc
@@ -38,13 +38,6 @@ max_texture_size_ = std::min(max_texture_size_, INT_MAX - 1); texture_usage_angle_ = feature_info->feature_flags().angle_texture_usage; - attribs_.es3_capable = feature_info->IsES3Capable(); - attribs_.desktop_gl = !feature_info->gl_version_info().is_es; - // Can't use the value from feature_info, as we unconditionally enable this - // extension, and assume it can't be used if PBOs are not used (which isn't - // true for Skia used directly against GL). - attribs_.supports_unpack_subimage = - gl::g_current_gl_driver->ext.b_GL_EXT_unpack_subimage; bool enable_texture_storage = feature_info->feature_flags().ext_texture_storage; const gles2::Validators* validators = feature_info->validators();
diff --git a/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.h b/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.h index 2273649..039ae48c 100644 --- a/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.h +++ b/gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.h
@@ -79,7 +79,6 @@ FormatInfo format_info_[viz::RESOURCE_FORMAT_MAX + 1]; int32_t max_texture_size_ = 0; bool texture_usage_angle_ = false; - GLTextureImageBackingHelper::UnpackStateAttribs attribs_; GpuDriverBugWorkarounds workarounds_; WebGPUAdapterName use_webgpu_adapter_ = WebGPUAdapterName::kDefault;
diff --git a/gpu/command_buffer/service/shared_image/gl_image_backing.cc b/gpu/command_buffer/service/shared_image/gl_image_backing.cc index fa4ae16..2b8605b 100644 --- a/gpu/command_buffer/service/shared_image/gl_image_backing.cc +++ b/gpu/command_buffer/service/shared_image/gl_image_backing.cc
@@ -37,8 +37,6 @@ return estimated_size; } -using UnpackStateAttribs = GLTextureImageBackingHelper::UnpackStateAttribs; - using ScopedResetAndRestoreUnpackState = GLTextureImageBackingHelper::ScopedResetAndRestoreUnpackState; @@ -317,11 +315,10 @@ // one param. InitializeGLTextureParams params; params.target = texture_target; - UnpackStateAttribs attribs; auto shared_image = std::make_unique<GLImageBacking>( std::move(image), mailbox, format, size, color_space, surface_origin, - alpha_type, usage, params, attribs, true); + alpha_type, usage, params, true); shared_image->passthrough_texture_ = std::move(wrapped_gl_texture); shared_image->gl_texture_retained_for_legacy_mailbox_ = true; @@ -340,7 +337,6 @@ SkAlphaType alpha_type, uint32_t usage, const InitializeGLTextureParams& params, - const UnpackStateAttribs& attribs, bool is_passthrough) : SharedImageBacking(mailbox, format, @@ -353,7 +349,6 @@ false /* is_thread_safe */), image_(image), gl_params_(params), - gl_unpack_attribs_(attribs), is_passthrough_(is_passthrough), cleared_rect_(params.is_cleared ? gfx::Rect(size) : gfx::Rect()), weak_factory_(this) { @@ -789,9 +784,8 @@ } new_state = gles2::Texture::BOUND; } else { - ScopedResetAndRestoreUnpackState scoped_unpack_state(api, - gl_unpack_attribs_, - /*upload=*/true); + ScopedResetAndRestoreUnpackState scoped_unpack_state( + /*uploading_data=*/true); if (!image_->CopyTexImage(target)) { LOG(ERROR) << "Failed to copy GLImage to target"; return false; @@ -825,7 +819,7 @@ ScopedRestoreTexture scoped_restore(api, target); api->glBindTextureFn(target, GetGLServiceId()); ScopedResetAndRestoreUnpackState scoped_unpack_state( - api, gl_unpack_attribs_, true /* uploading_data */); + /*uploading_data=*/true); api->glTexSubImage2DFn(target, 0, 0, 0, size().width(), size().height(), format, type, data); ReleaseGLTexture(true /* have_context */);
diff --git a/gpu/command_buffer/service/shared_image/gl_image_backing.h b/gpu/command_buffer/service/shared_image/gl_image_backing.h index 9e01970..d179099 100644 --- a/gpu/command_buffer/service/shared_image/gl_image_backing.h +++ b/gpu/command_buffer/service/shared_image/gl_image_backing.h
@@ -187,7 +187,6 @@ SkAlphaType alpha_type, uint32_t usage, const GLTextureImageBackingHelper::InitializeGLTextureParams& params, - const GLTextureImageBackingHelper::UnpackStateAttribs& attribs, bool is_passthrough); GLImageBacking(const GLImageBacking& other) = delete; GLImageBacking& operator=(const GLImageBacking& other) = delete; @@ -257,7 +256,6 @@ bool gl_texture_retained_for_legacy_mailbox_ = false; const GLTextureImageBackingHelper::InitializeGLTextureParams gl_params_; - const GLTextureImageBackingHelper::UnpackStateAttribs gl_unpack_attribs_; const bool is_passthrough_; // This is the cleared rect used by ClearedRect and SetClearedRect when
diff --git a/gpu/command_buffer/service/shared_image/gl_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/gl_image_backing_factory.cc index 544fceb9..ce485b2 100644 --- a/gpu/command_buffer/service/shared_image/gl_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/gl_image_backing_factory.cc
@@ -210,7 +210,7 @@ for_framebuffer_attachment && texture_usage_angle_; return std::make_unique<GLImageBacking>( image, mailbox, plane_format, plane_size, color_space, surface_origin, - alpha_type, usage, params, attribs_, use_passthrough_); + alpha_type, usage, params, use_passthrough_); } scoped_refptr<gl::GLImage> GLImageBackingFactory::MakeGLImage( @@ -224,8 +224,6 @@ if (handle.type == gfx::SHARED_MEMORY_BUFFER) { if (plane != gfx::BufferPlane::DEFAULT) return nullptr; - if (!base::IsValueInRangeForNumericType<size_t>(handle.stride)) - return nullptr; auto image = base::MakeRefCounted<gl::GLImageSharedMemory>(size); if (color_space.IsValid()) image->SetColorSpace(color_space); @@ -371,7 +369,7 @@ DCHECK(!format_info.swizzle); auto result = std::make_unique<GLImageBacking>( image, mailbox, format, size, color_space, surface_origin, alpha_type, - usage, params, attribs_, use_passthrough_); + usage, params, use_passthrough_); if (!pixel_data.empty()) { gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); result->InitializePixels(format_info.adjusted_format, format_info.gl_type,
diff --git a/gpu/command_buffer/service/shared_image/gl_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/gl_image_backing_factory_unittest.cc index 5b0d4292..cce492b 100644 --- a/gpu/command_buffer/service/shared_image/gl_image_backing_factory_unittest.cc +++ b/gpu/command_buffer/service/shared_image/gl_image_backing_factory_unittest.cc
@@ -767,7 +767,7 @@ handle.region = base::UnsafeSharedMemoryRegion::Create(shm_size); ASSERT_TRUE(handle.region.IsValid()); handle.offset = 0; - handle.stride = static_cast<int32_t>( + handle.stride = static_cast<uint32_t>( gfx::RowSizeForBufferFormat(size.width(), format, 0)); auto backing = backing_factory_shmem_->CreateSharedImage(
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc index 623232d..a809737 100644 --- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc
@@ -217,22 +217,20 @@ if (!pixel_data.empty()) { ScopedResetAndRestoreUnpackState scoped_unpack_state( - api, attribs_, true /* uploading_data */); + /*uploading_data=*/true); gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); api->glTexSubImage2DFn(target, 0, 0, 0, size.width(), size.height(), format_info.adjusted_format, format_info.gl_type, pixel_data.data()); } } else if (format_info.is_compressed) { - ScopedResetAndRestoreUnpackState scoped_unpack_state(api, attribs_, - !pixel_data.empty()); + ScopedResetAndRestoreUnpackState scoped_unpack_state(!pixel_data.empty()); gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); api->glCompressedTexImage2DFn(target, 0, format_info.image_internal_format, size.width(), size.height(), 0, pixel_data.size(), pixel_data.data()); } else { - ScopedResetAndRestoreUnpackState scoped_unpack_state(api, attribs_, - !pixel_data.empty()); + ScopedResetAndRestoreUnpackState scoped_unpack_state(!pixel_data.empty()); gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); api->glTexImage2DFn(target, 0, format_info.image_internal_format, size.width(), size.height(), 0,
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.cc b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.cc index e3746c5..0844fce 100644 --- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.cc +++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.cc
@@ -10,16 +10,18 @@ #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/shared_context_state.h" #include "gpu/command_buffer/service/shared_image/shared_image_factory.h" +#include "ui/gl/gl_context.h" #include "ui/gl/gl_gl_api_implementation.h" +#include "ui/gl/gl_version_info.h" namespace gpu { GLTextureImageBackingHelper::ScopedResetAndRestoreUnpackState:: - ScopedResetAndRestoreUnpackState(gl::GLApi* api, - const UnpackStateAttribs& attribs, - bool uploading_data) - : api_(api) { - if (attribs.es3_capable) { + ScopedResetAndRestoreUnpackState(bool uploading_data) + : api_(gl::g_current_gl_context) { + const auto* version_info = gl::g_current_gl_version; + + if (version_info->is_es3_capable) { // Need to unbind any GL_PIXEL_UNPACK_BUFFER for the nullptr in // glTexImage2D to mean "no pixels" (as opposed to offset 0 in the // buffer). @@ -32,7 +34,8 @@ if (unpack_alignment_ != 4) api_->glPixelStoreiFn(GL_UNPACK_ALIGNMENT, 4); - if (attribs.es3_capable || attribs.supports_unpack_subimage) { + if (version_info->is_es3_capable || + gl::g_current_gl_driver->ext.b_GL_EXT_unpack_subimage) { api_->glGetIntegervFn(GL_UNPACK_ROW_LENGTH, &unpack_row_length_); if (unpack_row_length_) api_->glPixelStoreiFn(GL_UNPACK_ROW_LENGTH, 0); @@ -44,7 +47,7 @@ api_->glPixelStoreiFn(GL_UNPACK_SKIP_PIXELS, 0); } - if (attribs.es3_capable) { + if (version_info->is_es3_capable) { api_->glGetIntegervFn(GL_UNPACK_SKIP_IMAGES, &unpack_skip_images_); if (unpack_skip_images_) api_->glPixelStoreiFn(GL_UNPACK_SKIP_IMAGES, 0); @@ -53,13 +56,13 @@ api_->glPixelStoreiFn(GL_UNPACK_IMAGE_HEIGHT, 0); } - if (attribs.desktop_gl) { - api->glGetBooleanvFn(GL_UNPACK_SWAP_BYTES, &unpack_swap_bytes_); + if (!version_info->is_es) { + api_->glGetBooleanvFn(GL_UNPACK_SWAP_BYTES, &unpack_swap_bytes_); if (unpack_swap_bytes_) - api->glPixelStoreiFn(GL_UNPACK_SWAP_BYTES, GL_FALSE); - api->glGetBooleanvFn(GL_UNPACK_LSB_FIRST, &unpack_lsb_first_); + api_->glPixelStoreiFn(GL_UNPACK_SWAP_BYTES, GL_FALSE); + api_->glGetBooleanvFn(GL_UNPACK_LSB_FIRST, &unpack_lsb_first_); if (unpack_lsb_first_) - api->glPixelStoreiFn(GL_UNPACK_LSB_FIRST, GL_FALSE); + api_->glPixelStoreiFn(GL_UNPACK_LSB_FIRST, GL_FALSE); } } }
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.h b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.h index 4498aec..36e08ae 100644 --- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.h +++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_helper.h
@@ -27,19 +27,10 @@ bool has_immutable_storage = false; }; - // Attributes needed to know what state to restore for GL upload and copy. - struct UnpackStateAttribs { - bool es3_capable = false; - bool desktop_gl = false; - bool supports_unpack_subimage = false; - }; - // Object used to restore state around GL upload and copy. class ScopedResetAndRestoreUnpackState { public: - ScopedResetAndRestoreUnpackState(gl::GLApi* api, - const UnpackStateAttribs& attribs, - bool uploading_data); + explicit ScopedResetAndRestoreUnpackState(bool uploading_data); ScopedResetAndRestoreUnpackState(const ScopedResetAndRestoreUnpackState&) = delete;
diff --git a/gpu/command_buffer/service/shared_memory_region_wrapper.cc b/gpu/command_buffer/service/shared_memory_region_wrapper.cc index 85644fbf..20e3c64 100644 --- a/gpu/command_buffer/service/shared_memory_region_wrapper.cc +++ b/gpu/command_buffer/service/shared_memory_region_wrapper.cc
@@ -17,11 +17,11 @@ // Validate that |stride| will work for pixels with |size| and |format|. bool ValidateStride(const gfx::Size size, viz::ResourceFormat format, - int32_t stride) { + uint32_t stride) { if (!base::IsValueInRangeForNumericType<size_t>(stride)) return false; - int32_t min_width_in_bytes = 0; + uint32_t min_width_in_bytes = 0; if (!viz::ResourceSizes::MaybeWidthInBytes(size.width(), format, &min_width_in_bytes)) { return false;
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.cc b/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.cc index 7b48187..e0c025d9 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.cc +++ b/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.cc
@@ -30,7 +30,7 @@ base::UnsafeSharedMemoryRegion shared_memory_region, base::WritableSharedMemoryMapping shared_memory_mapping, size_t offset, - int stride) + uint32_t stride) : GpuMemoryBufferImpl(id, size, format, std::move(callback)), shared_memory_region_(std::move(shared_memory_region)), shared_memory_mapping_(std::move(shared_memory_mapping)), @@ -89,7 +89,7 @@ handle.type = gfx::SHARED_MEMORY_BUFFER; handle.id = id; handle.offset = 0; - handle.stride = static_cast<int32_t>( + handle.stride = static_cast<uint32_t>( gfx::RowSizeForBufferFormat(size.width(), format, 0)); handle.region = std::move(shared_memory_region); return handle; @@ -114,19 +114,18 @@ size_t min_buffer_size = 0; if (gfx::NumberOfPlanesForLinearBufferFormat(format) == 1) { - if (static_cast<size_t>(handle.stride) < minimum_stride) + if (handle.stride < minimum_stride) return nullptr; - base::CheckedNumeric<size_t> checked_min_buffer_size = - base::MakeCheckedNum(handle.stride) * - (base::MakeCheckedNum(size.height()) - 1) + - minimum_stride; + base::CheckedNumeric<size_t> checked_min_buffer_size = handle.stride; + checked_min_buffer_size *= size.height() - 1; + checked_min_buffer_size += minimum_stride; if (!checked_min_buffer_size.AssignIfValid(&min_buffer_size)) return nullptr; } else { // Custom layout (i.e. non-standard stride) is not allowed for multi-plane // formats. - if (static_cast<size_t>(handle.stride) != minimum_stride) + if (handle.stride != minimum_stride) return nullptr; if (!gfx::BufferSizeForBufferFormatChecked(size, format,
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h b/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h index 31a7d46..add325e 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h +++ b/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h
@@ -85,12 +85,12 @@ base::UnsafeSharedMemoryRegion shared_memory_region, base::WritableSharedMemoryMapping shared_memory_mapping, size_t offset, - int stride); + uint32_t stride); base::UnsafeSharedMemoryRegion shared_memory_region_; base::WritableSharedMemoryMapping shared_memory_mapping_; size_t offset_; - int stride_; + uint32_t stride_; }; } // namespace gpu
diff --git a/gpu/ipc/service/dcomp_texture_win.cc b/gpu/ipc/service/dcomp_texture_win.cc index cbe350c..515916a 100644 --- a/gpu/ipc/service/dcomp_texture_win.cc +++ b/gpu/ipc/service/dcomp_texture_win.cc
@@ -45,7 +45,6 @@ using InitializeGLTextureParams = GLTextureImageBackingHelper::InitializeGLTextureParams; -using UnpackStateAttribs = GLTextureImageBackingHelper::UnpackStateAttribs; } // namespace @@ -170,11 +169,10 @@ params.is_cleared = true; params.is_rgb_emulation = false; params.framebuffer_attachment_angle = false; - UnpackStateAttribs attribs; auto shared_image = std::make_unique<GLImageBacking>( this, mailbox, viz::BGRA_8888, GetSize(), gfx::ColorSpace::CreateSRGB(), kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, - /*usage=*/SHARED_IMAGE_USAGE_DISPLAY, params, attribs, + /*usage=*/SHARED_IMAGE_USAGE_DISPLAY, params, /*use_passthrough=*/true); channel_->shared_image_stub()->factory()->RegisterBacking(
diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc index 6030d8e..166b8ac 100644 --- a/gpu/ipc/service/gpu_channel.cc +++ b/gpu/ipc/service/gpu_channel.cc
@@ -1066,8 +1066,6 @@ case gfx::SHARED_MEMORY_BUFFER: { if (plane != gfx::BufferPlane::DEFAULT) return nullptr; - if (!base::IsValueInRangeForNumericType<size_t>(handle.stride)) - return nullptr; auto image = base::MakeRefCounted<gl::GLImageSharedMemory>(size); if (!image->Initialize(handle.region, handle.id, format, handle.offset, handle.stride)) {
diff --git a/headless/lib/browser/headless_permission_manager.cc b/headless/lib/browser/headless_permission_manager.cc index e5c0ecd..c4616db 100644 --- a/headless/lib/browser/headless_permission_manager.cc +++ b/headless/lib/browser/headless_permission_manager.cc
@@ -7,7 +7,9 @@ #include "base/callback.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" #include "third_party/blink/public/common/permissions/permission_utils.h" +#include "url/gurl.h" namespace headless { @@ -74,6 +76,17 @@ return blink::mojom::PermissionStatus::ASK; } +content::PermissionResult +HeadlessPermissionManager::GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) { + blink::mojom::PermissionStatus status = + GetPermissionStatus(permission, origin.GetURL(), origin.GetURL()); + + return content::PermissionResult( + status, content::PermissionStatusSource::UNSPECIFIED); +} + blink::mojom::PermissionStatus HeadlessPermissionManager::GetPermissionStatusForCurrentDocument( blink::PermissionType permission,
diff --git a/headless/lib/browser/headless_permission_manager.h b/headless/lib/browser/headless_permission_manager.h index ed91c294..f5f1045 100644 --- a/headless/lib/browser/headless_permission_manager.h +++ b/headless/lib/browser/headless_permission_manager.h
@@ -15,6 +15,7 @@ namespace content { class BrowserContext; +struct PermissionResult; } namespace headless { @@ -59,6 +60,9 @@ blink::PermissionType permission, const GURL& requesting_origin, const GURL& embedding_origin) override; + content::PermissionResult GetPermissionResultForOriginWithoutContext( + blink::PermissionType permission, + const url::Origin& origin) override; blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument( blink::PermissionType permission, content::RenderFrameHost* render_frame_host) override;
diff --git a/ios/chrome/browser/autofill/form_structure_browsertest.mm b/ios/chrome/browser/autofill/form_structure_browsertest.mm index c8eaccd..8b739f3 100644 --- a/ios/chrome/browser/autofill/form_structure_browsertest.mm +++ b/ios/chrome/browser/autofill/form_structure_browsertest.mm
@@ -198,7 +198,9 @@ // TODO(crbug.com/1190334): Remove once launched. autofill::features::kAutofillParseMerchantPromoCodeFields, // TODO(crbug.com/1113970): Remove once launched. - features::kAutofillSectionUponRedundantNameInfo}, + features::kAutofillSectionUponRedundantNameInfo, + // TODO(crbug.com/1335549): Remove once launched. + autofill::features::kAutofillParseIBANFields}, // Disabled {}); }
diff --git a/ios/chrome/browser/link_to_text/BUILD.gn b/ios/chrome/browser/link_to_text/BUILD.gn index 9c4b5dd..e3881faf 100644 --- a/ios/chrome/browser/link_to_text/BUILD.gn +++ b/ios/chrome/browser/link_to_text/BUILD.gn
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//ios/web/public/js_messaging/compile_ts.gni") import("//ios/web/public/js_messaging/optimize_js.gni") source_set("link_to_text") { @@ -68,13 +69,23 @@ ] } -optimize_js("link_to_text_js") { - visibility = [ ":link_to_text" ] - - primary_script = "resources/link_to_text.js" +compile_ts("compile_link_to_text_js") { + allow_js = true sources = [ + "//ios/web/public/js_messaging/resources/gcrweb.ts", "//third_party/text-fragments-polyfill/src/src/fragment-generation-utils.js", "//third_party/text-fragments-polyfill/src/src/text-fragment-utils.js", - "resources/link_to_text.js", + "resources/link_to_text.ts", ] } + +optimize_js("link_to_text_js") { + visibility = [ ":link_to_text" ] + _script = filter_include(get_target_outputs(":compile_link_to_text_js"), + [ "*link_to_text.js" ]) + primary_script = _script[0] + + sources = _script + + deps = [ ":compile_link_to_text_js" ] +}
diff --git a/ios/chrome/browser/link_to_text/resources/link_to_text.js b/ios/chrome/browser/link_to_text/resources/link_to_text.js deleted file mode 100644 index 2585b5ee..0000000 --- a/ios/chrome/browser/link_to_text/resources/link_to_text.js +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import * as utils from '//third_party/text-fragments-polyfill/src/src/fragment-generation-utils.js'; - -/** - * @fileoverview Interface used for Chrome to use link-to-text link generation - * the utility functions from the text-fragments-polyfill library. - */ - -__gCrWeb['linkToText'] = {}; - -/** - * Attempts to generate a link with text fragments for the current - * page's selection. - */ -__gCrWeb.linkToText.getLinkToText = - function() { - const selection = window.getSelection(); - const selectedText = `"${selection.toString()}"`; - const selectionRect = {x: 0, y: 0, width: 0, height: 0}; - - if (selection.rangeCount) { - // Get the selection range's first client rect. - const domRect = selection.getRangeAt(0).getClientRects()[0]; - selectionRect.x = domRect.x; - selectionRect.y = domRect.y; - selectionRect.width = domRect.width; - selectionRect.height = domRect.height; - } - - const canonicalLinkNode = document.querySelector('link[rel=\'canonical\']'); - - const response = utils.generateFragment(selection); - return { - status: response.status, - fragment: response.fragment, - selectedText: selectedText, - selectionRect: selectionRect, - canonicalUrl: canonicalLinkNode && canonicalLinkNode.getAttribute('href') - }; -} - -/** - * Checks if the range is suitable to attempt link generation; the feature - * should be disabled if this does not return true. - */ -__gCrWeb.linkToText.checkPreconditions = function() { - return utils.isValidRangeForFragmentGeneration( - window.getSelection().getRangeAt(0)); -}
diff --git a/ios/chrome/browser/link_to_text/resources/link_to_text.ts b/ios/chrome/browser/link_to_text/resources/link_to_text.ts new file mode 100644 index 0000000..2b10d13 --- /dev/null +++ b/ios/chrome/browser/link_to_text/resources/link_to_text.ts
@@ -0,0 +1,46 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js'; +import * as utils from '//third_party/text-fragments-polyfill/src/src/fragment-generation-utils.js'; + +/** + * @fileoverview Interface used for Chrome to use link-to-text link generation + * the utility functions from the text-fragments-polyfill library. + */ + +/** + * Attempts to generate a link with text fragments for the current + * page's selection. + */ +function getLinkToText() { + const selection = window.getSelection(); + let selectionRect = {x: 0, y: 0, width: 0, height: 0}; + + if (selection && selection.rangeCount) { + // Get the selection range's first client rect. + const domRect = selection.getRangeAt(0).getClientRects()[0]; + if (domRect) { + selectionRect.x = domRect.x; + selectionRect.y = domRect.y; + selectionRect.width = domRect.width; + selectionRect.height = domRect.height; + } + } + + const selectedText = `"${selection?.toString()}"`; + const canonicalLinkNode = document.querySelector('link[rel=\'canonical\']'); + + const response = utils.generateFragment(selection as Selection); + return { + status: response.status, + fragment: response.fragment, + selectedText: selectedText, + selectionRect: selectionRect, + canonicalUrl: canonicalLinkNode + && canonicalLinkNode.getAttribute('href') + }; +} + +gCrWeb.linkToText = { getLinkToText };
diff --git a/ios/chrome/browser/signin/authentication_service.mm b/ios/chrome/browser/signin/authentication_service.mm index 68a26fd..947278a 100644 --- a/ios/chrome/browser/signin/authentication_service.mm +++ b/ios/chrome/browser/signin/authentication_service.mm
@@ -321,49 +321,13 @@ return account_manager_service_->GetIdentityWithGaiaID(authenticated_gaia_id); } +// TODO(crbug.com/1351423): Remove asynchronous callback from SignIn function, +// since this is no longer used by existing callers. void AuthenticationService::SignIn(ChromeIdentity* identity, signin_ui::CompletionCallback completion) { - base::WeakPtr<AuthenticationService> weak_ptr = GetWeakPtr(); - ProceduralBlock signin_callback = ^() { - bool has_primary_identity = false; - AuthenticationService* strong_ptr = weak_ptr.get(); - if (strong_ptr) { - strong_ptr->SignInInternal(identity); - has_primary_identity = - strong_ptr->HasPrimaryIdentity(signin::ConsentLevel::kSignin); - } - if (completion) { - completion(has_primary_identity); - } - }; - - if (base::FeatureList::IsEnabled(signin::kEnableUnicornAccountSupport)) { - ios::ChromeIdentityService* identity_service = - ios::GetChromeBrowserProvider().GetChromeIdentityService(); - identity_service->IsSubjectToParentalControls( - identity, ^(ios::ChromeIdentityCapabilityResult result) { - AuthenticationService* strong_ptr = weak_ptr.get(); - if (strong_ptr) { - strong_ptr->OnIsSubjectToParentalControlsResult(result, - signin_callback); - } - }); - return; - } - - // When supervised user account are not enabled, sign in the account by - // default. - signin_callback(); -} - -void AuthenticationService::OnIsSubjectToParentalControlsResult( - ios::ChromeIdentityCapabilityResult result, - ProceduralBlock completion) { - // Clears browsing data for supervised users before sign-in operation. - if (result == ios::ChromeIdentityCapabilityResult::kTrue) { - delegate_->ClearBrowsingData(completion); - } else if (completion) { - completion(); + SignInInternal(identity); + if (completion) { + completion(HasPrimaryIdentity(signin::ConsentLevel::kSignin)); } } @@ -484,10 +448,6 @@ // GetPrimaryAccountMutator() returns nullptr on ChromeOS only. DCHECK(account_mutator); - // Retrieve primary identity before clearing in the account mutator. - ChromeIdentity* primary_identity = - GetPrimaryIdentity(signin::ConsentLevel::kSignin); - account_mutator->ClearPrimaryAccount( signout_source, signin_metrics::SignoutDelete::kIgnoreMetric); crash_keys::SetCurrentlySignedIn(false); @@ -497,18 +457,6 @@ // started at least once. if (force_clear_browsing_data || (is_managed && is_first_setup_complete)) { delegate_->ClearBrowsingData(completion); - } else if (base::FeatureList::IsEnabled( - signin::kEnableUnicornAccountSupport)) { - ios::ChromeIdentityService* identity_service = - ios::GetChromeBrowserProvider().GetChromeIdentityService(); - base::WeakPtr<AuthenticationService> weak_ptr = GetWeakPtr(); - identity_service->IsSubjectToParentalControls( - primary_identity, ^(ios::ChromeIdentityCapabilityResult result) { - AuthenticationService* strong_ptr = weak_ptr.get(); - if (strong_ptr) { - strong_ptr->OnIsSubjectToParentalControlsResult(result, completion); - } - }); } else if (completion) { base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(completion));
diff --git a/ios/chrome/browser/signin/authentication_service_unittest.mm b/ios/chrome/browser/signin/authentication_service_unittest.mm index 9436b994..8d2592f 100644 --- a/ios/chrome/browser/signin/authentication_service_unittest.mm +++ b/ios/chrome/browser/signin/authentication_service_unittest.mm
@@ -790,59 +790,3 @@ EXPECT_OCMOCK_VERIFY(observer_delegate); } - -// Tests that a supervised user has all local data cleared on sign-in when -// there was a previous account on the device. -TEST_F(AuthenticationServiceTest, SupervisedAccountSwitch) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature( - signin::kEnableUnicornAccountSupport); - - SetExpectationsForSignIn(); - identity_service()->SetCapabilities( - identity(1), @{ - @(kIsSubjectToParentalControlsCapabilityName) : - @(static_cast<int>(ios::ChromeIdentityCapabilityResult::kTrue)) - }); - - authentication_service()->SignIn(identity(0), nil); - EXPECT_TRUE(authentication_service()->HasPrimaryIdentity( - signin::ConsentLevel::kSignin)); - ON_CALL(*mock_sync_service()->GetMockUserSettings(), IsFirstSetupComplete()) - .WillByDefault(Return(true)); - - authentication_service()->SignOut(signin_metrics::ABORT_SIGNIN, - /*force_clear_browsing_data=*/false, nil); - - EXPECT_EQ(ClearBrowsingDataCount(), 0); - - // Clears browsing data when signed-in as a child. - authentication_service()->SignIn(identity(1), nil); - EXPECT_EQ(ClearBrowsingDataCount(), 1); -} - -// Tests that supervised user's local data is correctly cleared when signing -// out. -TEST_F(AuthenticationServiceTest, SupervisedAccountSignOut) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature( - signin::kEnableUnicornAccountSupport); - - SetExpectationsForSignIn(); - identity_service()->SetCapabilities( - identity(0), @{ - @(kIsSubjectToParentalControlsCapabilityName) : - @(static_cast<int>(ios::ChromeIdentityCapabilityResult::kTrue)) - }); - - authentication_service()->SignIn(identity(0), nil); - EXPECT_TRUE(authentication_service()->HasPrimaryIdentity( - signin::ConsentLevel::kSignin)); - ON_CALL(*mock_sync_service()->GetMockUserSettings(), IsFirstSetupComplete()) - .WillByDefault(Return(true)); - EXPECT_EQ(ClearBrowsingDataCount(), 1); - - authentication_service()->SignOut(signin_metrics::ABORT_SIGNIN, - /*force_clear_browsing_data=*/false, nil); - EXPECT_EQ(ClearBrowsingDataCount(), 2); -}
diff --git a/ios/chrome/browser/ui/authentication/BUILD.gn b/ios/chrome/browser/ui/authentication/BUILD.gn index 648ee0a..f6376dc 100644 --- a/ios/chrome/browser/ui/authentication/BUILD.gn +++ b/ios/chrome/browser/ui/authentication/BUILD.gn
@@ -33,6 +33,7 @@ "//components/infobars/core", "//components/policy/core/common", "//components/prefs", + "//components/signin/ios/browser", "//components/signin/public/identity_manager", "//components/signin/public/identity_manager/objc", "//components/strings",
diff --git a/ios/chrome/browser/ui/authentication/authentication_flow.mm b/ios/chrome/browser/ui/authentication/authentication_flow.mm index b487fe54..d8f4567 100644 --- a/ios/chrome/browser/ui/authentication/authentication_flow.mm +++ b/ios/chrome/browser/ui/authentication/authentication_flow.mm
@@ -8,6 +8,7 @@ #include "base/check_op.h" #import "base/ios/block_types.h" #include "base/notreached.h" +#import "components/signin/ios/browser/features.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/main/browser.h" #include "ios/chrome/browser/policy/cloud/user_policy_switch.h" @@ -302,17 +303,25 @@ case CHECK_MERGE_CASE: DCHECK_EQ(SHOULD_CLEAR_DATA_USER_CHOICE, self.localDataClearingStrategy); if (_postSignInAction == POST_SIGNIN_ACTION_COMMIT_SYNC) { - if (([_performer shouldHandleMergeCaseForIdentity:_identityToSignIn - browserState:browserState])) { - [_performer promptMergeCaseForIdentity:_identityToSignIn - browser:_browser - viewController:_presentingViewController]; - return; + if (base::FeatureList::IsEnabled( + signin::kEnableUnicornAccountSupport)) { + ios::ChromeIdentityService* identity_service = + ios::GetChromeBrowserProvider().GetChromeIdentityService(); + __weak AuthenticationFlow* weakSelf = self; + identity_service->IsSubjectToParentalControls( + _identityToSignIn, ^(ios::ChromeIdentityCapabilityResult result) { + if (result == ios::ChromeIdentityCapabilityResult::kTrue) { + weakSelf.localDataClearingStrategy = + SHOULD_CLEAR_DATA_CLEAR_DATA; + [weakSelf continueSignin]; + return; + } + [weakSelf checkMergeCaseForUnsupervisedAccounts]; + }); } else { - // If the user is not prompted to choose a data clearing strategy, - // Chrome defaults to merging the account data. - self.localDataClearingStrategy = SHOULD_CLEAR_DATA_MERGE_DATA; + [self checkMergeCaseForUnsupervisedAccounts]; } + return; } [self continueSignin]; return; @@ -382,6 +391,21 @@ NOTREACHED(); } +- (void)checkMergeCaseForUnsupervisedAccounts { + if (([_performer + shouldHandleMergeCaseForIdentity:_identityToSignIn + browserState:_browser->GetBrowserState()])) { + [_performer promptMergeCaseForIdentity:_identityToSignIn + browser:_browser + viewController:_presentingViewController]; + } else { + // If the user is not prompted to choose a data clearing strategy, + // Chrome defaults to merging the account data. + self.localDataClearingStrategy = SHOULD_CLEAR_DATA_MERGE_DATA; + [self continueSignin]; + } +} + - (void)checkSigninSteps { ChromeIdentity* currentIdentity = AuthenticationServiceFactory::GetForBrowserState(
diff --git a/ios/chrome/browser/ui/authentication/signin/BUILD.gn b/ios/chrome/browser/ui/authentication/signin/BUILD.gn index 745bdca..ba60a8e 100644 --- a/ios/chrome/browser/ui/authentication/signin/BUILD.gn +++ b/ios/chrome/browser/ui/authentication/signin/BUILD.gn
@@ -122,6 +122,8 @@ "//base", "//base/test:test_support", "//components/policy:policy_code_generate", + "//components/signin/internal/identity_manager", + "//components/signin/ios/browser:features", "//components/signin/public/base", "//components/strings:components_strings_grit", "//ios/chrome/app/strings", @@ -131,11 +133,13 @@ "//ios/chrome/browser/policy:policy_util", "//ios/chrome/browser/ui/authentication:eg_test_support+eg2", "//ios/chrome/browser/ui/authentication/views:views_constants", + "//ios/chrome/browser/ui/bookmarks:eg_test_support+eg2", "//ios/chrome/browser/ui/content_suggestions:feature_flags", "//ios/chrome/browser/ui/recent_tabs:recent_tabs_ui_constants", "//ios/chrome/browser/ui/settings:constants", "//ios/chrome/browser/ui/settings/google_services:constants", "//ios/chrome/test/earl_grey:eg_test_support+eg2", + "//ios/public/provider/chrome/browser/signin", "//ios/public/provider/chrome/browser/signin:constants", "//ios/public/provider/chrome/browser/signin:fake_chrome_identity", "//ios/testing/earl_grey:eg_test_support+eg2",
diff --git a/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm b/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm index 3d11dd5..30fe624 100644 --- a/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm +++ b/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm
@@ -7,6 +7,8 @@ #include "base/strings/sys_string_conversions.h" #import "base/test/ios/wait_util.h" #include "components/policy/policy_constants.h" +#import "components/signin/internal/identity_manager/account_capabilities_constants.h" +#import "components/signin/ios/browser/features.h" #include "components/signin/public/base/signin_metrics.h" #include "components/strings/grit/components_strings.h" #import "ios/chrome/browser/metrics/metrics_app_interface.h" @@ -18,6 +20,8 @@ #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui_test_util.h" #import "ios/chrome/browser/ui/authentication/signin_matchers.h" #import "ios/chrome/browser/ui/authentication/views/views_constants.h" +#import "ios/chrome/browser/ui/bookmarks/bookmark_earl_grey.h" +#import "ios/chrome/browser/ui/bookmarks/bookmark_earl_grey_ui.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_feature.h" #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_constants.h" #import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_constants.h" @@ -27,6 +31,8 @@ #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" #import "ios/chrome/test/earl_grey/chrome_matchers.h" #import "ios/chrome/test/earl_grey/chrome_test_case.h" +#import "ios/chrome/test/earl_grey/web_http_server_chrome_test_case.h" +#import "ios/public/provider/chrome/browser/signin/chrome_identity_service.h" #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h" #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity_interaction_manager_constants.h" #import "ios/testing/earl_grey/earl_grey_test.h" @@ -74,6 +80,21 @@ NSString* const kPassphrase = @"hello"; +// Timeout in seconds to wait for asynchronous sync operations. +const NSTimeInterval kSyncOperationTimeout = 5.0; + +// Sets parental control capability for the given identity. +void SetParentalControlsCapabilityForIdentity(FakeChromeIdentity* identity) { + // The identity must exist in the test storage to be able to set capabilities + // through the fake identity service. + [SigninEarlGrey addFakeIdentity:identity]; + + NSDictionary* capabilities = @{ + @(kIsSubjectToParentalControlsCapabilityName) : [NSNumber + numberWithInt:(int)ios::ChromeIdentityCapabilityResult::kTrue], + }; + [SigninEarlGrey setCapabilities:capabilities forIdentity:identity]; +} // Closes the sign-in import data dialog and choose either to combine the data // or keep the data separate. void CloseImportDataDialog(id<GREYMatcher> choiceButtonMatcher) { @@ -148,22 +169,31 @@ // Sign-in interaction tests that work both with Unified Consent enabled or // disabled. -@interface SigninCoordinatorTestCase : ChromeTestCase +@interface SigninCoordinatorTestCase : WebHttpServerChromeTestCase @end @implementation SigninCoordinatorTestCase +- (AppLaunchConfiguration)appConfigurationForTestCase { + AppLaunchConfiguration config = [super appConfigurationForTestCase]; + config.features_enabled.push_back(signin::kEnableUnicornAccountSupport); + return config; +} + - (void)setUp { [super setUp]; // Remove closed tab history to make sure the sign-in promo is always visible // in recent tabs. [ChromeEarlGrey clearBrowsingHistory]; + [ChromeEarlGrey waitForBookmarksToFinishLoading]; + [ChromeEarlGrey clearBookmarks]; GREYAssertNil([MetricsAppInterface setupHistogramTester], @"Failed to set up histogram tester."); } - (void)tearDown { [super tearDown]; + [BookmarkEarlGrey clearBookmarksPositionCache]; GREYAssertNil([MetricsAppInterface releaseHistogramTester], @"Cannot reset histogram tester."); } @@ -181,6 +211,64 @@ ExpectSyncConsentHistogram(signin_metrics::SigninAccountType::kRegular); } +// Tests that opening the sign-in screen from the Settings and signing in works +// correctly when there is a supervised user identity on the device. +- (void)testSignInSupervisedUser { + // Set up a fake supervised identity. + FakeChromeIdentity* fakeIdentity = [FakeChromeIdentity fakeIdentity1]; + SetParentalControlsCapabilityForIdentity(fakeIdentity); + + [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; + + [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity]; +} + +// Tests that signing out a supervised user account with the keep local data +// option is honored. +- (void)testSignOutWithKeepDataForSupervisedUser { + // Sign in with a fake supervised identity. + FakeChromeIdentity* fakeSupervisedIdentity = + [FakeChromeIdentity fakeIdentity1]; + SetParentalControlsCapabilityForIdentity(fakeSupervisedIdentity); + [SigninEarlGreyUI signinWithFakeIdentity:fakeSupervisedIdentity]; + + // Add a bookmark after sync is initialized. + [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; + [ChromeEarlGrey waitForBookmarksToFinishLoading]; + [BookmarkEarlGrey setupStandardBookmarks]; + + // Sign out from the supervised account with option to keep local data. + [SigninEarlGreyUI + signOutWithConfirmationChoice:SignOutConfirmationChoiceKeepData]; + + // Verify bookmarks are available. + [BookmarkEarlGreyUI openBookmarks]; + [BookmarkEarlGreyUI verifyEmptyBackgroundIsAbsent]; +} + +// Tests that signing out a supervised user account with the clear local data +// option is honored. +- (void)testSignOutWithClearDataForSupervisedUser { + // Sign in with a fake supervised identity. + FakeChromeIdentity* fakeSupervisedIdentity = + [FakeChromeIdentity fakeIdentity1]; + SetParentalControlsCapabilityForIdentity(fakeSupervisedIdentity); + [SigninEarlGreyUI signinWithFakeIdentity:fakeSupervisedIdentity]; + + // Add a bookmark after sync is initialized. + [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; + [ChromeEarlGrey waitForBookmarksToFinishLoading]; + [BookmarkEarlGrey setupStandardBookmarks]; + + // Sign out from the supervised account with option to clear local data. + [SigninEarlGreyUI + signOutWithConfirmationChoice:SignOutConfirmationChoiceClearData]; + + // Verify bookmarks are cleared. + [BookmarkEarlGreyUI openBookmarks]; + [BookmarkEarlGreyUI verifyEmptyBackgroundAppears]; +} + // Tests signing in with one account, switching sync account to a second and // choosing to keep the browsing data separate during the switch. // Flaky, crbug.com/1279995.
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 ccb641e5..73a08f3c 100644 --- a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm +++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
@@ -713,14 +713,8 @@ [NSString stringWithFormat:@"%i", 2])]; // Test the same thing after opening a tab from the tab grid. - // TODO(crbug.com/933953) For an unknown reason synchronization doesn't work - // well with tapping on the tabgrid button, and instead triggers the long - // press gesture recognizer. Disable this here so the test can be re-enabled. - { - ScopedSynchronizationDisabler disabler; - [[EarlGrey selectElementWithMatcher:chrome_test_util::ShowTabsButton()] - performAction:grey_longPressWithDuration(0.05)]; - } + [ChromeEarlGreyUI openTabGrid]; + [[EarlGrey selectElementWithMatcher:chrome_test_util::TabGridNewTabButton()] performAction:grey_tap()]; [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()]
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm index 1b0abcc6..bb163a4 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
@@ -1063,18 +1063,7 @@ // Requests feeds here if the correct flags and prefs are enabled. if ([self shouldFeedBeVisible]) { - FeedModelConfiguration* discoverFeedConfiguration = - [FeedModelConfiguration discoverFeedModelConfiguration]; - self.discoverFeedService->CreateFeedModel(discoverFeedConfiguration); - if ([self isFollowingFeedAvailable]) { - FeedModelConfiguration* followingFeedConfiguration = - [FeedModelConfiguration - followingModelConfigurationWithSortType: - (FollowingFeedSortType)self.prefService->GetInteger( - prefs::kNTPFollowingFeedSortType)]; - self.discoverFeedService->CreateFeedModel(followingFeedConfiguration); - switch (self.selectedFeed) { case FeedTypeDiscover: self.feedViewController = [self discoverFeed]; @@ -1108,6 +1097,10 @@ return nil; } + FeedModelConfiguration* discoverFeedConfiguration = + [FeedModelConfiguration discoverFeedModelConfiguration]; + self.discoverFeedService->CreateFeedModel(discoverFeedConfiguration); + UIViewController* discoverFeed = self.discoverFeedService->NewDiscoverFeedViewControllerWithConfiguration( [self feedViewControllerConfiguration]); @@ -1120,6 +1113,12 @@ return nil; } + FeedModelConfiguration* followingFeedConfiguration = [FeedModelConfiguration + followingModelConfigurationWithSortType: + (FollowingFeedSortType)self.prefService->GetInteger( + prefs::kNTPFollowingFeedSortType)]; + self.discoverFeedService->CreateFeedModel(followingFeedConfiguration); + UIViewController* followingFeed = self.discoverFeedService->NewFollowingFeedViewControllerWithConfiguration( [self feedViewControllerConfiguration]);
diff --git a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn index 794b2b0e..57a33e7 100644 --- a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
@@ -146,6 +146,7 @@ "resources:omnibox_suggestion_answer_icon_dark_color", "resources:omnibox_suggestion_icon_color", "resources:omnibox_suggestion_icon_dark_color", + "resources:omnibox_suggestion_row_highlight_color", "//base", "//components/omnibox/common", "//ios/chrome/app/strings:ios_strings_grit", @@ -162,6 +163,7 @@ "//ios/chrome/browser/ui/toolbar/public", "//ios/chrome/browser/ui/util", "//ios/chrome/common/ui/colors", + "//ios/chrome/common/ui/elements:elements", "//ios/chrome/common/ui/util", "//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser/branded_images:branded_images_api",
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_view.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_view.h index 1112300..84cf737 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_view.h +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_view.h
@@ -21,6 +21,8 @@ @property(nonatomic, weak) id<ImageRetriever> imageRetriever; // Used for testing to check whether this view is displaying anything. @property(nonatomic, readonly) UIImage* mainImage; +// Same as UIImageView. +@property(nonatomic, getter=isHighlighted) BOOL highlighted; - (void)prepareForReuse;
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_view.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_view.mm index b9d59fa..bec2d669 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_view.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_icon_view.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/ui/omnibox/popup/omnibox_icon_view.h" #import "ios/chrome/browser/net/crurl.h" +#import "ios/chrome/browser/ui/omnibox/omnibox_ui_features.h" #import "ios/chrome/browser/ui/omnibox/popup/favicon_retriever.h" #import "ios/chrome/browser/ui/omnibox/popup/image_retriever.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_icon.h" @@ -20,6 +21,8 @@ @property(nonatomic, strong) UIImageView* mainImageView; @property(nonatomic, strong) UIImageView* overlayImageView; +@property(nonatomic, strong) id<OmniboxIcon> omniboxIcon; + @end @implementation OmniboxIconView @@ -95,6 +98,8 @@ } - (void)setOmniboxIcon:(id<OmniboxIcon>)omniboxIcon { + _omniboxIcon = omniboxIcon; + // Setup the view layout the first time the cell is setup. if (self.subviews.count == 0) { [self setupLayout]; @@ -150,4 +155,16 @@ return self.mainImageView.image; } +- (void)setHighlighted:(BOOL)highlighted { + _highlighted = highlighted; + self.backgroundImageView.highlighted = highlighted; + self.mainImageView.highlighted = highlighted; + self.overlayImageView.highlighted = highlighted; + + if (IsOmniboxActionsEnabled()) { + self.mainImageView.tintColor = + highlighted ? UIColor.whiteColor : self.omniboxIcon.iconImageTintColor; + } +} + @end
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm index f630353..d3994e46 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm
@@ -15,6 +15,7 @@ #import "ios/chrome/browser/ui/util/named_guide.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" +#import "ios/chrome/common/ui/elements/gradient_view.h" #import "ios/chrome/common/ui/util/pointer_interaction_util.h" #include "ios/chrome/grit/ios_strings.h" #include "ios/chrome/grit/ios_theme_resources.h" @@ -29,6 +30,7 @@ const CGFloat kTextTopMargin = 6; const CGFloat kTrailingButtonSize = 24; const CGFloat kTrailingButtonTrailingMargin = 14; +const CGFloat kTopGradientColorOpacity = 0.85; NSString* const kOmniboxPopupRowSwitchTabAccessibilityIdentifier = @"OmniboxPopupRowSwitchTabAccessibilityIdentifier"; @@ -74,9 +76,19 @@ if (self) { _incognito = NO; - self.selectedBackgroundView = [[UIView alloc] initWithFrame:CGRectZero]; - self.selectedBackgroundView.backgroundColor = - [UIColor colorNamed:kTableViewRowHighlightColor]; + if (IsOmniboxActionsEnabled()) { + self.selectedBackgroundView = [[GradientView alloc] + initWithTopColor: + [[UIColor colorNamed:@"omnibox_suggestion_row_highlight_color"] + colorWithAlphaComponent:kTopGradientColorOpacity] + bottomColor: + [UIColor + colorNamed:@"omnibox_suggestion_row_highlight_color"]]; + } else { + self.selectedBackgroundView = [[UIView alloc] initWithFrame:CGRectZero]; + self.selectedBackgroundView.backgroundColor = + [UIColor colorNamed:kTableViewRowHighlightColor]; + } _textTruncatingLabel = [[FadeTruncatingLabel alloc] initWithFrame:CGRectZero]; @@ -157,6 +169,25 @@ } } +#pragma mark - UITableViewCell + +- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { + [super setHighlighted:highlighted animated:animated]; + + if (!IsOmniboxActionsEnabled()) { + return; + } + + UIColor* textColor = highlighted ? [UIColor whiteColor] : nil; + self.textTruncatingLabel.textColor = textColor; + self.detailTruncatingLabel.textColor = textColor; + self.detailAnswerLabel.textColor = textColor; + + self.leadingIconView.highlighted = highlighted; + self.trailingButton.tintColor = + highlighted ? [UIColor whiteColor] : [UIColor colorNamed:kBlueColor]; +} + #pragma mark - Property setter/getters - (void)setImageRetriever:(id<ImageRetriever>)imageRetriever {
diff --git a/ios/chrome/browser/ui/omnibox/popup/resources/BUILD.gn b/ios/chrome/browser/ui/omnibox/popup/resources/BUILD.gn index 08f18d87..4f454036 100644 --- a/ios/chrome/browser/ui/omnibox/popup/resources/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/popup/resources/BUILD.gn
@@ -31,6 +31,10 @@ sources = [ "omnibox_suggestion_icon_dark_color.colorset/Contents.json" ] } +colorset("omnibox_suggestion_row_highlight_color") { + sources = [ "omnibox_suggestion_row_highlight_color.colorset/Contents.json" ] +} + imageset("omnibox_popup_tab_match") { sources = [ "omnibox_popup_tab_match.imageset/Contents.json",
diff --git a/ios/chrome/browser/ui/omnibox/popup/resources/omnibox_suggestion_row_highlight_color.colorset/Contents.json b/ios/chrome/browser/ui/omnibox/popup/resources/omnibox_suggestion_row_highlight_color.colorset/Contents.json new file mode 100644 index 0000000..e36b0c4 --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/popup/resources/omnibox_suggestion_row_highlight_color.colorset/Contents.json
@@ -0,0 +1,20 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "colors" : [ + { + "idiom" : "universal", + "color" : { + "color-space" : "srgb", + "components" : { + "red" : "0x1A", + "alpha" : "1.000", + "blue" : "0xE8", + "green" : "0x73" + } + } + } + ] +}
diff --git a/ios/chrome/test/data/policy/policy_test_cases.json b/ios/chrome/test/data/policy/policy_test_cases.json index 72f0165..c03799d 100644 --- a/ios/chrome/test/data/policy/policy_test_cases.json +++ b/ios/chrome/test/data/policy/policy_test_cases.json
@@ -212,6 +212,9 @@ "CloudPolicyOverridesPlatformPolicy": { "reason_for_missing_test": "This policy has no pref as it is only directly read by the policy system." }, + "CloudUserPolicyMerge": { + "reason_for_missing_test": "This policy has no pref as it is only directly read by the policy system." + }, "CloudUserPolicyOverridesCloudMachinePolicy": { "reason_for_missing_test": "This policy has no pref as it is only directly read by the policy system." },
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h index a86df20..19b706a 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h +++ b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h
@@ -114,6 +114,9 @@ // Opens a new incognito tab via the tools menu. - (void)openNewIncognitoTab; +// Opens the tab grid. +- (void)openTabGrid; + // Opens and clear browsing data from history. - (void)openAndClearBrowsingDataFromHistory;
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm index 4ad15a6..09e3f271 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm
@@ -11,6 +11,7 @@ #include "ios/chrome/grit/ios_strings.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" #import "ios/chrome/test/earl_grey/chrome_matchers.h" +#import "ios/chrome/test/scoped_eg_synchronization_disabler.h" #import "ios/testing/earl_grey/earl_grey_test.h" #include "ui/base/l10n/l10n_util.h" @@ -363,6 +364,15 @@ [self waitForAppToIdle]; } +- (void)openTabGrid { + // TODO(crbug.com/933953) For an unknown reason synchronization doesn't work + // well with tapping on the tabgrid button, and instead triggers the long + // press gesture recognizer. Disable this here so the test can be re-enabled. + ScopedSynchronizationDisabler disabler; + [[EarlGrey selectElementWithMatcher:chrome_test_util::ShowTabsButton()] + performAction:grey_longPressWithDuration(0.05)]; +} + - (void)reload { // On iPhone Reload button is a part of tools menu, so open it. if (IsAppCompactWidth()) {
diff --git a/ipc/ipc_message.cc b/ipc/ipc_message.cc index a27afc7..510d80a 100644 --- a/ipc/ipc_message.cc +++ b/ipc/ipc_message.cc
@@ -70,7 +70,7 @@ Init(); } -Message::Message(const char* data, int data_len) +Message::Message(const char* data, size_t data_len) : base::Pickle(data, data_len) { Init(); }
diff --git a/ipc/ipc_message.h b/ipc/ipc_message.h index 8302cee2..b15bc20 100644 --- a/ipc/ipc_message.h +++ b/ipc/ipc_message.h
@@ -66,7 +66,7 @@ // Initializes a message from a const block of data. The data is not copied; // instead the data is merely referenced by this message. Only const methods // should be used on the message when initialized this way. - Message(const char* data, int data_len); + Message(const char* data, size_t data_len); Message(const Message& other); Message& operator=(const Message& other); @@ -111,7 +111,7 @@ if (unblock) { header()->flags |= UNBLOCK_BIT; } else { - header()->flags &= ~UNBLOCK_BIT; + header()->flags &= static_cast<uint32_t>(~UNBLOCK_BIT); } }
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h index 3462b855..77efa8c 100644 --- a/ipc/ipc_message_utils.h +++ b/ipc/ipc_message_utils.h
@@ -191,7 +191,9 @@ template <> struct ParamTraits<unsigned int> { typedef unsigned int param_type; - static void Write(base::Pickle* m, const param_type& p) { m->WriteInt(p); } + static void Write(base::Pickle* m, const param_type& p) { + m->WriteInt(static_cast<int>(p)); + } static bool Read(const base::Pickle* m, base::PickleIterator* iter, param_type* r) { @@ -260,7 +262,9 @@ template <> struct ParamTraits<unsigned long long> { typedef unsigned long long param_type; - static void Write(base::Pickle* m, const param_type& p) { m->WriteInt64(p); } + static void Write(base::Pickle* m, const param_type& p) { + m->WriteInt64(static_cast<int64_t>(p)); + } static bool Read(const base::Pickle* m, base::PickleIterator* iter, param_type* r) {
diff --git a/media/gpu/chromeos/BUILD.gn b/media/gpu/chromeos/BUILD.gn index 84c78a1..455435b 100644 --- a/media/gpu/chromeos/BUILD.gn +++ b/media/gpu/chromeos/BUILD.gn
@@ -18,6 +18,7 @@ defines = [ "MEDIA_GPU_IMPLEMENTATION" ] sources = [ "image_processor_factory.cc", + "oop_video_decoder.cc", "video_decoder_pipeline.cc", ] @@ -30,6 +31,7 @@ "//media/gpu:buildflags", "//media/gpu:command_buffer_helper", "//media/gpu:common", + "//media/mojo/common:common", ] if (use_vaapi) { @@ -42,6 +44,11 @@ if (use_v4l2_codec) { deps += [ "//media/gpu/v4l2" ] } + + if (is_chromeos) { + deps += + [ "//chromeos/components/cdm_factory_daemon:cdm_factory_daemon_gpu" ] + } } # This target can be depended by targets in //media/gpu/{v4l2,vaapi}. @@ -66,7 +73,6 @@ "libyuv_image_processor_backend.h", "mailbox_video_frame_converter.cc", "mailbox_video_frame_converter.h", - "oop_video_decoder.cc", "oop_video_decoder.h", "platform_video_frame_pool.cc", "platform_video_frame_pool.h", @@ -100,7 +106,6 @@ "//media/gpu:command_buffer_helper", "//media/gpu:common", "//media/gpu:video_frame_mapper_common", - "//media/mojo/common:common", "//third_party/libyuv", "//ui/gfx:buffer_types", "//ui/gfx:memory_buffer", @@ -109,7 +114,7 @@ "//ui/gfx/linux:gbm", "//ui/gl", ] - if (is_chromeos_ash) { + if (is_chromeos) { sources += [ "decoder_buffer_transcryptor.cc", "decoder_buffer_transcryptor.h", @@ -156,7 +161,7 @@ ] } -if (is_chromeos_ash) { +if (is_chromeos) { proto_library("cdm-oemcrypto-proto") { sources = [ "//third_party/cros_system_api/dbus/cdm_oemcrypto/secure_buffer.proto",
diff --git a/media/gpu/chromeos/oop_video_decoder.cc b/media/gpu/chromeos/oop_video_decoder.cc index f1fedd7..471e077 100644 --- a/media/gpu/chromeos/oop_video_decoder.cc +++ b/media/gpu/chromeos/oop_video_decoder.cc
@@ -5,11 +5,18 @@ #include "media/gpu/chromeos/oop_video_decoder.h" #include "base/memory/ptr_util.h" +#include "build/chromeos_buildflags.h" +#include "chromeos/components/cdm_factory_daemon/stable_cdm_context_impl.h" #include "media/base/bind_to_current_loop.h" #include "media/gpu/macros.h" #include "media/mojo/common/mojo_decoder_buffer_converter.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" + +#if BUILDFLAG(USE_VAAPI) +#include "media/gpu/vaapi/vaapi_wrapper.h" +#endif // BUILDFLAG(USE_VAAPI) // Throughout this file, we have sprinkled many CHECK()s to assert invariants // that should hold regardless of the behavior of the remote decoder or @@ -170,16 +177,38 @@ return; } + mojo::PendingRemote<stable::mojom::StableCdmContext> + pending_remote_stable_cdm_context; + if (config.is_encrypted()) { +#if BUILDFLAG(IS_CHROMEOS) + if (!cdm_context || !cdm_context->GetChromeOsCdmContext()) { + std::move(init_cb).Run(DecoderStatus::Codes::kUnsupportedEncryptionMode); + return; + } + mojo::PendingReceiver<stable::mojom::StableCdmContext> cdm_receiver; + pending_remote_stable_cdm_context = + cdm_receiver.InitWithNewPipeAndPassRemote(); + mojo::MakeSelfOwnedReceiver( + std::make_unique<chromeos::StableCdmContextImpl>(cdm_context), + std::move(cdm_receiver)); +#if BUILDFLAG(USE_VAAPI) + // We need to signal that for AMD we will do transcryption on the GPU side. + // Then on the other end we just make transcryption a no-op. + needs_transcryption_ = (VaapiWrapper::GetImplementationType() == + VAImplementation::kMesaGallium); +#endif // BUILDFLAG(USE_VAAPI) +#else + std::move(init_cb).Run(DecoderStatus::Codes::kUnsupportedEncryptionMode); + return; +#endif // BUILDFLAG(IS_CHROMEOS) + } + init_cb_ = std::move(init_cb); output_cb_ = output_cb; waiting_cb_ = waiting_cb; - // TODO(b/171813538): plumb protected content. - mojo::PendingRemote<stable::mojom::StableCdmContext> - pending_remote_cdm_context; - remote_decoder_->Initialize(config, low_delay, - std::move(pending_remote_cdm_context), + std::move(pending_remote_stable_cdm_context), base::BindOnce(&OOPVideoDecoder::OnInitializeDone, weak_this_factory_.GetWeakPtr())); } @@ -390,7 +419,8 @@ } bool OOPVideoDecoder::NeedsTranscryption() { - return false; + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return needs_transcryption_; } void OOPVideoDecoder::OnVideoFrameDecoded(
diff --git a/media/gpu/chromeos/oop_video_decoder.h b/media/gpu/chromeos/oop_video_decoder.h index d61f3039..0ca038a1 100644 --- a/media/gpu/chromeos/oop_video_decoder.h +++ b/media/gpu/chromeos/oop_video_decoder.h
@@ -114,6 +114,10 @@ std::unique_ptr<MojoDecoderBufferWriter> mojo_decoder_buffer_writer_ GUARDED_BY_CONTEXT(sequence_checker_); + // This is to indicate we should perform transcryption before sending the data + // to the video decoder utility process. + bool needs_transcryption_ GUARDED_BY_CONTEXT(sequence_checker_) = false; + SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory<OOPVideoDecoder> weak_this_factory_
diff --git a/media/gpu/chromeos/video_decoder_pipeline.cc b/media/gpu/chromeos/video_decoder_pipeline.cc index bbabd6b..c491e5f 100644 --- a/media/gpu/chromeos/video_decoder_pipeline.cc +++ b/media/gpu/chromeos/video_decoder_pipeline.cc
@@ -295,9 +295,9 @@ main_frame_pool_.reset(); frame_converter_.reset(); decoder_.reset(); -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) buffer_transcryptor_.reset(); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#endif // BUILDFLAG(IS_CHROMEOS) } // static @@ -451,7 +451,7 @@ MEDIA_LOG(INFO, media_log_) << "VideoDecoderPipeline |decoder_| Initialize() successful"; -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) if (decoder_ && decoder_->NeedsTranscryption()) { if (!cdm_context) { VLOGF(1) << "CdmContext required for transcryption"; @@ -470,7 +470,7 @@ // In case this was created on a prior initialization but no longer needed. buffer_transcryptor_.reset(); } -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#endif // BUILDFLAG(IS_CHROMEOS) client_task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(init_cb), status)); @@ -502,10 +502,10 @@ image_processor_->Reset(); frame_converter_->AbortPendingFrames(); -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) if (buffer_transcryptor_) buffer_transcryptor_->Reset(DecoderStatus::Codes::kAborted); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#endif // BUILDFLAG(IS_CHROMEOS) CallFlushCbIfNeeded(DecoderStatus::Codes::kAborted); @@ -545,7 +545,7 @@ } const bool is_flush = buffer->end_of_stream(); -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) if (buffer_transcryptor_) { buffer_transcryptor_->EnqueueBuffer( std::move(buffer), @@ -553,7 +553,7 @@ is_flush, std::move(decode_cb))); return; } -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#endif // BUILDFLAG(IS_CHROMEOS) decoder_->Decode( std::move(buffer), @@ -656,10 +656,10 @@ MEDIA_LOG(ERROR, media_log_) << "VideoDecoderPipeline " << msg; has_error_ = true; -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) if (buffer_transcryptor_) buffer_transcryptor_->Reset(DecoderStatus::Codes::kFailed); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#endif // BUILDFLAG(IS_CHROMEOS) CallFlushCbIfNeeded(DecoderStatus::Codes::kFailed); } @@ -877,7 +877,7 @@ gfx::NativePixmapHandle::kNoModifier}; } -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) void VideoDecoderPipeline::OnBufferTranscrypted( scoped_refptr<DecoderBuffer> transcrypted_buffer, DecodeCB decode_callback) { @@ -891,6 +891,6 @@ decoder_->Decode(std::move(transcrypted_buffer), std::move(decode_callback)); } -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#endif // BUILDFLAG(IS_CHROMEOS) } // namespace media
diff --git a/media/gpu/chromeos/video_decoder_pipeline.h b/media/gpu/chromeos/video_decoder_pipeline.h index 2e984eb..2435f8ab 100644 --- a/media/gpu/chromeos/video_decoder_pipeline.h +++ b/media/gpu/chromeos/video_decoder_pipeline.h
@@ -27,9 +27,9 @@ #include "ui/gfx/native_pixmap.h" #include "ui/gfx/native_pixmap_handle.h" -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) #include "media/gpu/chromeos/decoder_buffer_transcryptor.h" -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#endif // BUILDFLAG(IS_CHROMEOS) namespace base { class SequencedTaskRunner; } @@ -233,11 +233,11 @@ // Call |client_flush_cb_| with |status|. void CallFlushCbIfNeeded(DecoderStatus status); -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) // Callback for when transcryption of a buffer completes. void OnBufferTranscrypted(scoped_refptr<DecoderBuffer> transcrypted_buffer, DecodeCB decode_callback); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#endif // BUILDFLAG(IS_CHROMEOS) // The client task runner and its sequence checker. All public methods should // run on this task runner. @@ -274,12 +274,12 @@ const std::unique_ptr<MediaLog> media_log_; -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) // The transcryptor for transcrypting DecoderBuffers when needed by the HW // decoder implementation. std::unique_ptr<DecoderBufferTranscryptor> buffer_transcryptor_ GUARDED_BY_CONTEXT(decoder_sequence_checker_); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#endif // BUILDFLAG(IS_CHROMEOS) // The current video decoder implementation. Valid after initialization is // successfully done.
diff --git a/media/gpu/chromeos/video_decoder_pipeline_unittest.cc b/media/gpu/chromeos/video_decoder_pipeline_unittest.cc index 8e79aea..b3875cb2 100644 --- a/media/gpu/chromeos/video_decoder_pipeline_unittest.cc +++ b/media/gpu/chromeos/video_decoder_pipeline_unittest.cc
@@ -114,6 +114,7 @@ void(chromeos::ChromeOsCdmContext::GetScreenResolutionsCB)); MOCK_METHOD0(GetCdmContextRef, std::unique_ptr<CdmContextRef>()); MOCK_CONST_METHOD0(UsingArcCdm, bool()); + MOCK_CONST_METHOD0(IsRemoteCdm, bool()); }; // A real implementation of this class would actually hold onto a reference of // the owner of the CdmContext to ensure it is not destructed before the
diff --git a/media/gpu/mac/vt_video_decode_accelerator_mac.cc b/media/gpu/mac/vt_video_decode_accelerator_mac.cc index e7d412b..2779486 100644 --- a/media/gpu/mac/vt_video_decode_accelerator_mac.cc +++ b/media/gpu/mac/vt_video_decode_accelerator_mac.cc
@@ -2149,7 +2149,6 @@ gl_params.format = gl_format; gl_params.type = GL_UNSIGNED_BYTE; gl_params.is_cleared = true; - gpu::GLTextureImageBackingHelper::UnpackStateAttribs gl_attribs; // Making the GL context current before performing below shared image // tasks. @@ -2163,7 +2162,7 @@ auto shared_image = std::make_unique<gpu::GLImageBacking>( gl_image, mailbox, viz_resource_format, plane_size, color_space, kTopLeft_GrSurfaceOrigin, kOpaque_SkAlphaType, shared_image_usage, - gl_params, gl_attribs, gl_client_.is_passthrough); + gl_params, gl_client_.is_passthrough); const bool success = shared_image_stub->factory()->RegisterBacking( std::move(shared_image), /*allow_legacy_mailbox=*/false);
diff --git a/media/gpu/vaapi/vaapi_video_decoder.cc b/media/gpu/vaapi/vaapi_video_decoder.cc index 0dbf3b9..551b8aa7 100644 --- a/media/gpu/vaapi/vaapi_video_decoder.cc +++ b/media/gpu/vaapi/vaapi_video_decoder.cc
@@ -946,13 +946,13 @@ DCHECK(state_ == State::kWaitingForInput); #if BUILDFLAG(IS_CHROMEOS_ASH) - // We do not need to invoke transcryption if this is coming from ARC since - // that will already be done. + // We do not need to invoke transcryption if this is coming from a remote CDM + // since it will already have been done. if (cdm_context_ref_ && cdm_context_ref_->GetCdmContext()->GetChromeOsCdmContext() && cdm_context_ref_->GetCdmContext() ->GetChromeOsCdmContext() - ->UsingArcCdm()) { + ->IsRemoteCdm()) { return false; } #endif // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/media/mojo/mojom/stable/BUILD.gn b/media/mojo/mojom/stable/BUILD.gn index 0ccab6e3..6f1b0d3 100644 --- a/media/mojo/mojom/stable/BUILD.gn +++ b/media/mojo/mojom/stable/BUILD.gn
@@ -31,6 +31,10 @@ { types = [ { + mojom = "media.stable.mojom.CdmContextEvent" + cpp = "::media::CdmContext::Event" + }, + { mojom = "media.stable.mojom.ColorSpacePrimaryID" cpp = "::gfx::ColorSpace::PrimaryID" }, @@ -66,6 +70,10 @@ nullable_is_same_type = true }, { + mojom = "media.stable.mojom.DecryptStatus" + cpp = "::media::Decryptor::Status" + }, + { mojom = "media.stable.mojom.EncryptionScheme" cpp = "::media::EncryptionScheme" },
diff --git a/media/mojo/mojom/stable/stable_video_decoder.mojom b/media/mojo/mojom/stable/stable_video_decoder.mojom index a4da00f..83b6bd9 100644 --- a/media/mojo/mojom/stable/stable_video_decoder.mojom +++ b/media/mojo/mojom/stable/stable_video_decoder.mojom
@@ -7,6 +7,7 @@ import "media/mojo/mojom/stable/stable_video_decoder_types.mojom"; import "mojo/public/mojom/base/unguessable_token.mojom"; import "sandbox/policy/mojom/sandbox.mojom"; +import "ui/gfx/geometry/mojom/geometry.mojom"; // This API is a stable version of VideoDecoder. This is used both by LaCrOS and // by out-of-process video decoding to allow the GPU process to forward video @@ -58,9 +59,37 @@ OnWaiting@1(WaitingReason reason); }; -// TODO(b/194429120): Implement when protected content support is integrated. +// Interface for handling callbacks from the StableCdmContext interface below. +// Next min method ID: 1 +[Stable, Uuid="a1a73e1f-5297-49a2-a4e5-df875a44b61e"] +interface CdmContextEventCallback { + // Sends the event back to the registrar. + EventCallback@0(CdmContextEvent event); +}; + +// Maps to the media::CdmContext interface for remoting it to another process. +// Next MinVersion: 2 +// Next min method ID: 4 [Stable, Uuid="33c7a00e-2970-41b3-8c7b-f1074a539740"] interface StableCdmContext { + // Proxies to media::CdmContext::GetChromeOsCdmContext()->GetHwKeyData. + [MinVersion=1] + GetHwKeyData@0(DecryptConfig decrypt_config, array<uint8> hw_identifier) => + (DecryptStatus status, array<uint8> key_data); + + // Registers an interface for receiving event callbacks. This maps to + // media::CdmContext::RegisterEventCB. + [MinVersion=1] + RegisterEventCallback@1(pending_remote<CdmContextEventCallback> callback); + + // Proxies to media::CdmContext::GetChromeOsCdmContext()->GetHwConfigData. + [MinVersion=1] + GetHwConfigData@2() => (bool success, array<uint8> config_data); + + // Proxies to media::CdmContext::GetChromeOsCdmContext()-> + // GetScreenResolutions. + [MinVersion=1] + GetScreenResolutions@3() => (array<gfx.mojom.Size> resolutions); }; // Based on |media.mojom.VideoDecoder|.
diff --git a/media/mojo/mojom/stable/stable_video_decoder_types.mojom b/media/mojo/mojom/stable/stable_video_decoder_types.mojom index 810c4fc6a..1f9b0058 100644 --- a/media/mojo/mojom/stable/stable_video_decoder_types.mojom +++ b/media/mojo/mojom/stable/stable_video_decoder_types.mojom
@@ -528,3 +528,21 @@ mojo_base.mojom.DeprecatedDictionaryValue params@2; mojo_base.mojom.TimeTicks time@3; }; + +[Stable, Extensible] +enum DecryptStatus { + kSuccess, + kNoKey, + [Default] kFailure, +}; + +[Stable, Extensible] +enum CdmContextEvent { + // We use |kHasAdditionalUsableKey| as the default since this maps to an + // existing enum in Chrome that only has the two values below. Receiving an + // event for |kHasAdditionalUsableKey| is always safe because it is a benign + // indicator that if something was waiting for a key, it should check again. + // It is not an indicator that the key it actually wanted is ready. + [Default] kHasAdditionalUsableKey, + kHardwareContextReset, +};
diff --git a/media/mojo/mojom/stable/stable_video_decoder_types_mojom_traits.h b/media/mojo/mojom/stable/stable_video_decoder_types_mojom_traits.h index ab317b6..63c9a4d 100644 --- a/media/mojo/mojom/stable/stable_video_decoder_types_mojom_traits.h +++ b/media/mojo/mojom/stable/stable_video_decoder_types_mojom_traits.h
@@ -6,6 +6,7 @@ #define MEDIA_MOJO_MOJOM_STABLE_STABLE_VIDEO_DECODER_TYPES_MOJOM_TRAITS_H_ #include "base/notreached.h" +#include "media/base/cdm_context.h" #include "media/base/video_frame.h" #include "media/base/video_frame_metadata.h" #include "media/mojo/mojom/stable/stable_video_decoder_types.mojom.h" @@ -14,6 +15,37 @@ namespace mojo { template <> +struct EnumTraits<media::stable::mojom::CdmContextEvent, + ::media::CdmContext::Event> { + static media::stable::mojom::CdmContextEvent ToMojom( + ::media::CdmContext::Event input) { + switch (input) { + case ::media::CdmContext::Event::kHasAdditionalUsableKey: + return media::stable::mojom::CdmContextEvent::kHasAdditionalUsableKey; + case ::media::CdmContext::Event::kHardwareContextReset: + return media::stable::mojom::CdmContextEvent::kHardwareContextReset; + } + + NOTREACHED(); + return media::stable::mojom::CdmContextEvent::kHasAdditionalUsableKey; + } + + static bool FromMojom(media::stable::mojom::CdmContextEvent input, + ::media::CdmContext::Event* output) { + switch (input) { + case media::stable::mojom::CdmContextEvent::kHasAdditionalUsableKey: + *output = ::media::CdmContext::Event::kHasAdditionalUsableKey; + return true; + case media::stable::mojom::CdmContextEvent::kHardwareContextReset: + *output = ::media::CdmContext::Event::kHardwareContextReset; + return true; + } + NOTREACHED(); + return false; + } +}; + +template <> struct EnumTraits<media::stable::mojom::ColorSpacePrimaryID, gfx::ColorSpace::PrimaryID> { static media::stable::mojom::ColorSpacePrimaryID ToMojom( @@ -508,6 +540,44 @@ }; template <> +struct EnumTraits<media::stable::mojom::DecryptStatus, + ::media::Decryptor::Status> { + static media::stable::mojom::DecryptStatus ToMojom( + ::media::Decryptor::Status input) { + switch (input) { + case ::media::Decryptor::Status::kSuccess: + return media::stable::mojom::DecryptStatus::kSuccess; + case ::media::Decryptor::Status::kNoKey: + return media::stable::mojom::DecryptStatus::kNoKey; + case ::media::Decryptor::Status::kNeedMoreData: + return media::stable::mojom::DecryptStatus::kFailure; + case ::media::Decryptor::Status::kError: + return media::stable::mojom::DecryptStatus::kFailure; + } + + NOTREACHED(); + return media::stable::mojom::DecryptStatus::kFailure; + } + + static bool FromMojom(media::stable::mojom::DecryptStatus input, + ::media::Decryptor::Status* output) { + switch (input) { + case media::stable::mojom::DecryptStatus::kSuccess: + *output = ::media::Decryptor::Status::kSuccess; + return true; + case media::stable::mojom::DecryptStatus::kNoKey: + *output = ::media::Decryptor::Status::kNoKey; + return true; + case media::stable::mojom::DecryptStatus::kFailure: + *output = ::media::Decryptor::Status::kError; + return true; + } + NOTREACHED(); + return false; + } +}; + +template <> struct EnumTraits<media::stable::mojom::EncryptionScheme, ::media::EncryptionScheme> { static media::stable::mojom::EncryptionScheme ToMojom(
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn index 22d16c17..5bfd1e9 100644 --- a/media/mojo/services/BUILD.gn +++ b/media/mojo/services/BUILD.gn
@@ -116,15 +116,15 @@ sources += [ "gpu_mojo_media_client_win.cc" ] } else if (use_vaapi || use_v4l2_codec) { sources += [ "gpu_mojo_media_client_cros.cc" ] - - if (is_chromeos) { - deps += - [ "//chromeos/components/cdm_factory_daemon:cdm_factory_daemon_gpu" ] - } } else { sources += [ "gpu_mojo_media_client_stubs.cc" ] } + if (is_chromeos) { + deps += + [ "//chromeos/components/cdm_factory_daemon:cdm_factory_daemon_gpu" ] + } + if (is_android) { sources += [ "android_mojo_media_client.cc",
diff --git a/media/mojo/services/DEPS b/media/mojo/services/DEPS index a3c15af..3b5b92e 100644 --- a/media/mojo/services/DEPS +++ b/media/mojo/services/DEPS
@@ -5,6 +5,12 @@ "media_manifest\.cc": [ "+chromecast/common/mojom", ], + "mojo_cdm_service_context\.h": [ + "+chromeos/components/cdm_factory_daemon/remote_cdm_context.h", + ], + "stable_video_decoder_service\.h": [ + "+chromeos/components/cdm_factory_daemon/remote_cdm_context.h", + ], "webrtc_video_perf_mojolpm_fuzzer\.cc": [ "+third_party/libprotobuf-mutator/src/src", "+components/leveldb_proto/testing/fake_db.h",
diff --git a/media/mojo/services/mojo_cdm_service_context.cc b/media/mojo/services/mojo_cdm_service_context.cc index 2ef0f97..e5a4a91 100644 --- a/media/mojo/services/mojo_cdm_service_context.cc +++ b/media/mojo/services/mojo_cdm_service_context.cc
@@ -44,6 +44,25 @@ cdm_services_.erase(cdm_id); } +#if BUILDFLAG(IS_CHROMEOS_ASH) +base::UnguessableToken MojoCdmServiceContext::RegisterRemoteCdmContext( + chromeos::RemoteCdmContext* remote_context) { + DCHECK(remote_context); + base::UnguessableToken cdm_id = GetNextCdmId(); + remote_cdm_contexts_[cdm_id] = remote_context; + DVLOG(1) << __func__ << ": RemoteCdmContext registered with CDM ID " + << cdm_id; + return cdm_id; +} + +void MojoCdmServiceContext::UnregisterRemoteCdmContext( + const base::UnguessableToken& cdm_id) { + DVLOG(1) << __func__ << ": cdm_id = " << cdm_id; + DCHECK(remote_cdm_contexts_.count(cdm_id)); + remote_cdm_contexts_.erase(cdm_id); +} +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + std::unique_ptr<CdmContextRef> MojoCdmServiceContext::GetCdmContextRef( const base::UnguessableToken& cdm_id) { DVLOG(1) << __func__ << ": cdm_id = " << cdm_id; @@ -58,6 +77,13 @@ return std::make_unique<CdmContextRefImpl>(cdm_service->second->GetCdm()); } +#if BUILDFLAG(IS_CHROMEOS_ASH) + // Try the remote contexts now. + auto remote_context = remote_cdm_contexts_.find(cdm_id); + if (remote_context != remote_cdm_contexts_.end()) + return remote_context->second->GetCdmContextRef(); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + LOG(ERROR) << "CdmContextRef cannot be obtained for CDM ID: " << cdm_id; return nullptr; }
diff --git a/media/mojo/services/mojo_cdm_service_context.h b/media/mojo/services/mojo_cdm_service_context.h index 790d290..41114d93 100644 --- a/media/mojo/services/mojo_cdm_service_context.h +++ b/media/mojo/services/mojo_cdm_service_context.h
@@ -11,9 +11,14 @@ #include <memory> #include "base/unguessable_token.h" +#include "build/chromeos_buildflags.h" #include "media/media_buildflags.h" #include "media/mojo/services/media_mojo_export.h" +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "chromeos/components/cdm_factory_daemon/remote_cdm_context.h" +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + namespace media { class CdmContextRef; @@ -35,6 +40,21 @@ // Unregisters the CDM. Must be called before the CDM is destroyed. void UnregisterCdm(const base::UnguessableToken& cdm_id); +#if BUILDFLAG(IS_CHROMEOS_ASH) + // Registers the |remote_context| and returns a unique (per-process) CDM ID. + // This is used with out-of-process video decoding with HWDRM. We run + // MojoCdmServiceContext in the GPU process which works with MojoCdmService. + // We also run MojoCdmServiceContext in the Video Decoder process which + // doesn't use MojoCdmService, which is why we need to deal with + // RemoteCdmContext directly. + base::UnguessableToken RegisterRemoteCdmContext( + chromeos::RemoteCdmContext* remote_context); + + // Unregisters the RemoteCdmContext. Must be called before the + // RemoteCdmContext is destroyed. + void UnregisterRemoteCdmContext(const base::UnguessableToken& cdm_id); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + // Returns the CdmContextRef associated with |cdm_id|. std::unique_ptr<CdmContextRef> GetCdmContextRef( const base::UnguessableToken& cdm_id); @@ -42,6 +62,12 @@ private: // A map between CDM ID and MojoCdmService. std::map<base::UnguessableToken, MojoCdmService*> cdm_services_; + +#if BUILDFLAG(IS_CHROMEOS_ASH) + // A map between CDM ID and RemoteCdmContext. + std::map<base::UnguessableToken, chromeos::RemoteCdmContext*> + remote_cdm_contexts_; +#endif // BUILDFLAG(IS_CHROMEOS_ASH) }; } // namespace media
diff --git a/media/mojo/services/stable_video_decoder_factory_service.cc b/media/mojo/services/stable_video_decoder_factory_service.cc index 5163fae..f77e39e9 100644 --- a/media/mojo/services/stable_video_decoder_factory_service.cc +++ b/media/mojo/services/stable_video_decoder_factory_service.cc
@@ -118,9 +118,9 @@ mojo_media_client_.get(), &cdm_service_context_, mojo::PendingRemote<stable::mojom::StableVideoDecoder>()); } - video_decoders_.Add( - std::make_unique<StableVideoDecoderService>(std::move(dst_video_decoder)), - std::move(receiver)); + video_decoders_.Add(std::make_unique<StableVideoDecoderService>( + std::move(dst_video_decoder), &cdm_service_context_), + std::move(receiver)); } } // namespace media
diff --git a/media/mojo/services/stable_video_decoder_service.cc b/media/mojo/services/stable_video_decoder_service.cc index ce70dcf1..0a5ea217 100644 --- a/media/mojo/services/stable_video_decoder_service.cc +++ b/media/mojo/services/stable_video_decoder_service.cc
@@ -9,12 +9,18 @@ namespace media { StableVideoDecoderService::StableVideoDecoderService( - std::unique_ptr<mojom::VideoDecoder> dst_video_decoder) + std::unique_ptr<mojom::VideoDecoder> dst_video_decoder, + MojoCdmServiceContext* cdm_service_context) : video_decoder_client_receiver_(this), media_log_receiver_(this), stable_video_frame_handle_releaser_receiver_(this), dst_video_decoder_(std::move(dst_video_decoder)), - dst_video_decoder_receiver_(dst_video_decoder_.get()) { + dst_video_decoder_receiver_(dst_video_decoder_.get()) +#if BUILDFLAG(IS_CHROMEOS_ASH) + , + cdm_service_context_(cdm_service_context) +#endif // BUILDFLAG(IS_CHROMEOS_ASH) +{ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); CHECK(!!dst_video_decoder_); dst_video_decoder_remote_.Bind( @@ -23,6 +29,11 @@ StableVideoDecoderService::~StableVideoDecoderService() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + +#if BUILDFLAG(IS_CHROMEOS_ASH) + if (cdm_id_) + cdm_service_context_->UnregisterRemoteCdmContext(cdm_id_.value()); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) } void StableVideoDecoderService::GetSupportedConfigs( @@ -85,17 +96,42 @@ // The |config| should have been validated at deserialization time. DCHECK(config.IsValidConfig()); - // TODO(b/195769334): implement out-of-process video decoding of hardware - // protected content. +#if BUILDFLAG(IS_CHROMEOS_ASH) + // This can change across initializations, so reset this state. + if (cdm_id_) { + cdm_service_context_->UnregisterRemoteCdmContext(cdm_id_.value()); + cdm_id_.reset(); + } + remote_cdm_context_.reset(); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + if (config.is_encrypted()) { +#if BUILDFLAG(IS_CHROMEOS_ASH) + if (!cdm_context) { + std::move(callback).Run(DecoderStatus::Codes::kMissingCDM, + /*needs_bitstream_conversion=*/false, + /*max_decode_requests=*/1, + VideoDecoderType::kUnknown); + return; + } + remote_cdm_context_ = base::WrapRefCounted( + new chromeos::RemoteCdmContext(std::move(cdm_context))); + cdm_id_ = cdm_service_context_->RegisterRemoteCdmContext( + remote_cdm_context_.get()); +#else std::move(callback).Run(DecoderStatus::Codes::kUnsupportedConfig, /*needs_bitstream_conversion=*/false, /*max_decode_requests=*/1, VideoDecoderType::kUnknown); return; +#endif // BUILDFLAG(IS_CHROMEOS_ASH) } - dst_video_decoder_remote_->Initialize( - config, low_delay, /*cdm_id=*/absl::nullopt, std::move(callback)); + + // Even though this is in-process, we still need to pass a |cdm_id_| + // instead of a media::CdmContext* since this goes through Mojo IPC. This is + // why we need to register with the |cdm_service_context_| above. + dst_video_decoder_remote_->Initialize(config, low_delay, cdm_id_, + std::move(callback)); } void StableVideoDecoderService::Decode(
diff --git a/media/mojo/services/stable_video_decoder_service.h b/media/mojo/services/stable_video_decoder_service.h index 20ee73a..0e708221 100644 --- a/media/mojo/services/stable_video_decoder_service.h +++ b/media/mojo/services/stable_video_decoder_service.h
@@ -5,17 +5,25 @@ #ifndef MEDIA_MOJO_SERVICES_STABLE_VIDEO_DECODER_SERVICE_H_ #define MEDIA_MOJO_SERVICES_STABLE_VIDEO_DECODER_SERVICE_H_ +#include "base/memory/raw_ptr.h" #include "base/sequence_checker.h" #include "base/thread_annotations.h" +#include "base/unguessable_token.h" +#include "build/chromeos_buildflags.h" #include "media/mojo/mojom/media_log.mojom.h" #include "media/mojo/mojom/stable/stable_video_decoder.mojom.h" #include "media/mojo/mojom/video_decoder.mojom.h" #include "media/mojo/services/media_mojo_export.h" +#include "media/mojo/services/mojo_cdm_service_context.h" #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "chromeos/components/cdm_factory_daemon/remote_cdm_context.h" +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + namespace media { // A StableVideoDecoderService serves as an adapter between the @@ -44,8 +52,9 @@ public mojom::VideoDecoderClient, public mojom::MediaLog { public: - explicit StableVideoDecoderService( - std::unique_ptr<mojom::VideoDecoder> dst_video_decoder); + StableVideoDecoderService( + std::unique_ptr<mojom::VideoDecoder> dst_video_decoder, + MojoCdmServiceContext* cdm_service_context); StableVideoDecoderService(const StableVideoDecoderService&) = delete; StableVideoDecoderService& operator=(const StableVideoDecoderService&) = delete; @@ -124,6 +133,18 @@ mojo::Remote<mojom::VideoDecoder> dst_video_decoder_remote_ GUARDED_BY_CONTEXT(sequence_checker_); +#if BUILDFLAG(IS_CHROMEOS_ASH) + // Used for registering the |remote_cdm_context_| so that it can be resolved + // from the |cdm_id_| later. + const raw_ptr<MojoCdmServiceContext> cdm_service_context_ + GUARDED_BY_CONTEXT(sequence_checker_); + scoped_refptr<chromeos::RemoteCdmContext> remote_cdm_context_ + GUARDED_BY_CONTEXT(sequence_checker_); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + + absl::optional<base::UnguessableToken> cdm_id_ + GUARDED_BY_CONTEXT(sequence_checker_); + SEQUENCE_CHECKER(sequence_checker_); };
diff --git a/mojo/core/BUILD.gn b/mojo/core/BUILD.gn index e3fca5cb..cc2e2444 100644 --- a/mojo/core/BUILD.gn +++ b/mojo/core/BUILD.gn
@@ -49,6 +49,7 @@ "configuration.h", "connection_params.h", "core.h", + "core_ipcz.h", "data_pipe_consumer_dispatcher.h", "data_pipe_control_message.h", "data_pipe_producer_dispatcher.h", @@ -59,6 +60,7 @@ "handle_signals_state.h", "handle_table.h", "invitation_dispatcher.h", + "ipcz_api.h", "message_pipe_dispatcher.h", "node_channel.h", "node_controller.h", @@ -79,6 +81,7 @@ "configuration.cc", "connection_params.cc", "core.cc", + "core_ipcz.cc", "data_pipe_consumer_dispatcher.cc", "data_pipe_control_message.cc", "data_pipe_producer_dispatcher.cc", @@ -86,6 +89,9 @@ "entrypoints.cc", "handle_table.cc", "invitation_dispatcher.cc", + "ipcz_api.cc", + "ipcz_driver/driver.cc", + "ipcz_driver/driver.h", "message_pipe_dispatcher.cc", "node_channel.cc", "node_controller.cc", @@ -111,6 +117,7 @@ "//mojo/core/ports", "//mojo/public/c/system:headers", "//mojo/public/cpp/platform", + "//third_party/ipcz/src:ipcz_chromium", ] if (is_fuchsia) { @@ -284,6 +291,7 @@ testonly = true sources = [ "channel_unittest.cc", + "core_ipcz_test.cc", "core_test_base.cc", "core_test_base.h", "core_unittest.cc", @@ -322,6 +330,7 @@ "//mojo/public/cpp/system", "//testing/gmock", "//testing/gtest", + "//third_party/ipcz/src:ipcz_chromium", ] }
diff --git a/mojo/core/DEPS b/mojo/core/DEPS index 4cc26fb..7dbf802 100644 --- a/mojo/core/DEPS +++ b/mojo/core/DEPS
@@ -6,6 +6,7 @@ "+native_client/src/public", "+testing", "+third_party/ashmem", + "+third_party/ipcz", # internal includes. "+mojo",
diff --git a/mojo/core/core_ipcz.cc b/mojo/core/core_ipcz.cc new file mode 100644 index 0000000..36d4685 --- /dev/null +++ b/mojo/core/core_ipcz.cc
@@ -0,0 +1,386 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/core/core_ipcz.h" + +#include "base/notreached.h" +#include "base/time/time.h" +#include "mojo/core/ipcz_api.h" +#include "third_party/ipcz/include/ipcz/ipcz.h" + +namespace mojo::core { + +namespace { + +extern "C" { + +MojoResult MojoInitializeIpcz(const struct MojoInitializeOptions* options) { + NOTREACHED(); + return MOJO_RESULT_OK; +} + +MojoTimeTicks MojoGetTimeTicksNowIpcz() { + return base::Time::Now().ToDeltaSinceWindowsEpoch().InMicroseconds(); +} + +MojoResult MojoCloseIpcz(MojoHandle handle) { + return GetIpczAPI().Close(handle, IPCZ_NO_FLAGS, nullptr); +} + +MojoResult MojoQueryHandleSignalsStateIpcz( + MojoHandle handle, + MojoHandleSignalsState* signals_state) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoCreateMessagePipeIpcz( + const MojoCreateMessagePipeOptions* options, + MojoHandle* message_pipe_handle0, + MojoHandle* message_pipe_handle1) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoWriteMessageIpcz(MojoHandle message_pipe_handle, + MojoMessageHandle message, + const MojoWriteMessageOptions* options) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoReadMessageIpcz(MojoHandle message_pipe_handle, + const MojoReadMessageOptions* options, + MojoMessageHandle* message) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoFuseMessagePipesIpcz( + MojoHandle handle0, + MojoHandle handle1, + const MojoFuseMessagePipesOptions* options) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoCreateMessageIpcz(const MojoCreateMessageOptions* options, + MojoMessageHandle* message) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoDestroyMessageIpcz(MojoMessageHandle message) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoSerializeMessageIpcz( + MojoMessageHandle message, + const MojoSerializeMessageOptions* options) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoAppendMessageDataIpcz( + MojoMessageHandle message, + uint32_t additional_payload_size, + const MojoHandle* handles, + uint32_t num_handles, + const MojoAppendMessageDataOptions* options, + void** buffer, + uint32_t* buffer_size) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoGetMessageDataIpcz(MojoMessageHandle message, + const MojoGetMessageDataOptions* options, + void** buffer, + uint32_t* num_bytes, + MojoHandle* handles, + uint32_t* num_handles) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoSetMessageContextIpcz( + MojoMessageHandle message, + uintptr_t context, + MojoMessageContextSerializer serializer, + MojoMessageContextDestructor destructor, + const MojoSetMessageContextOptions* options) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoGetMessageContextIpcz( + MojoMessageHandle message, + const MojoGetMessageContextOptions* options, + uintptr_t* context) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoNotifyBadMessageIpcz( + MojoMessageHandle message, + const char* error, + uint32_t error_num_bytes, + const MojoNotifyBadMessageOptions* options) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoCreateDataPipeIpcz(const MojoCreateDataPipeOptions* options, + MojoHandle* data_pipe_producer_handle, + MojoHandle* data_pipe_consumer_handle) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoWriteDataIpcz(MojoHandle data_pipe_producer_handle, + const void* elements, + uint32_t* num_elements, + const MojoWriteDataOptions* options) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoBeginWriteDataIpcz(MojoHandle data_pipe_producer_handle, + const MojoBeginWriteDataOptions* options, + void** buffer, + uint32_t* buffer_num_elements) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoEndWriteDataIpcz(MojoHandle data_pipe_producer_handle, + uint32_t num_elements_written, + const MojoEndWriteDataOptions* options) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoReadDataIpcz(MojoHandle data_pipe_consumer_handle, + const MojoReadDataOptions* options, + void* elements, + uint32_t* num_elements) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoBeginReadDataIpcz(MojoHandle data_pipe_consumer_handle, + const MojoBeginReadDataOptions* options, + const void** buffer, + uint32_t* buffer_num_elements) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoEndReadDataIpcz(MojoHandle data_pipe_consumer_handle, + uint32_t num_elements_read, + const MojoEndReadDataOptions* options) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoCreateSharedBufferIpcz( + uint64_t num_bytes, + const MojoCreateSharedBufferOptions* options, + MojoHandle* shared_buffer_handle) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoDuplicateBufferHandleIpcz( + MojoHandle buffer_handle, + const MojoDuplicateBufferHandleOptions* options, + MojoHandle* new_buffer_handle) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoMapBufferIpcz(MojoHandle buffer_handle, + uint64_t offset, + uint64_t num_bytes, + const MojoMapBufferOptions* options, + void** address) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoUnmapBufferIpcz(void* address) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoGetBufferInfoIpcz(MojoHandle buffer_handle, + const MojoGetBufferInfoOptions* options, + MojoSharedBufferInfo* info) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoCreateTrapIpcz(MojoTrapEventHandler handler, + const MojoCreateTrapOptions* options, + MojoHandle* trap_handle) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoAddTriggerIpcz(MojoHandle trap_handle, + MojoHandle handle, + MojoHandleSignals signals, + MojoTriggerCondition condition, + uintptr_t context, + const MojoAddTriggerOptions* options) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoRemoveTriggerIpcz(MojoHandle trap_handle, + uintptr_t context, + const MojoRemoveTriggerOptions* options) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoArmTrapIpcz(MojoHandle trap_handle, + const MojoArmTrapOptions* options, + uint32_t* num_blocking_events, + MojoTrapEvent* blocking_events) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoWrapPlatformHandleIpcz( + const MojoPlatformHandle* platform_handle, + const MojoWrapPlatformHandleOptions* options, + MojoHandle* mojo_handle) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoUnwrapPlatformHandleIpcz( + MojoHandle mojo_handle, + const MojoUnwrapPlatformHandleOptions* options, + MojoPlatformHandle* platform_handle) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoWrapPlatformSharedMemoryRegionIpcz( + const MojoPlatformHandle* platform_handles, + uint32_t num_platform_handles, + uint64_t num_bytes, + const MojoSharedBufferGuid* guid, + MojoPlatformSharedMemoryRegionAccessMode access_mode, + const MojoWrapPlatformSharedMemoryRegionOptions* options, + MojoHandle* mojo_handle) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoUnwrapPlatformSharedMemoryRegionIpcz( + MojoHandle mojo_handle, + const MojoUnwrapPlatformSharedMemoryRegionOptions* options, + MojoPlatformHandle* platform_handles, + uint32_t* num_platform_handles, + uint64_t* num_bytes, + MojoSharedBufferGuid* mojo_guid, + MojoPlatformSharedMemoryRegionAccessMode* access_mode) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoCreateInvitationIpcz(const MojoCreateInvitationOptions* options, + MojoHandle* invitation_handle) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoAttachMessagePipeToInvitationIpcz( + MojoHandle invitation_handle, + const void* name, + uint32_t name_num_bytes, + const MojoAttachMessagePipeToInvitationOptions* options, + MojoHandle* message_pipe_handle) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoExtractMessagePipeFromInvitationIpcz( + MojoHandle invitation_handle, + const void* name, + uint32_t name_num_bytes, + const MojoExtractMessagePipeFromInvitationOptions* options, + MojoHandle* message_pipe_handle) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoSendInvitationIpcz( + MojoHandle invitation_handle, + const MojoPlatformProcessHandle* process_handle, + const MojoInvitationTransportEndpoint* transport_endpoint, + MojoProcessErrorHandler error_handler, + uintptr_t error_handler_context, + const MojoSendInvitationOptions* options) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoAcceptInvitationIpcz( + const MojoInvitationTransportEndpoint* transport_endpoint, + const MojoAcceptInvitationOptions* options, + MojoHandle* invitation_handle) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoSetQuotaIpcz(MojoHandle handle, + MojoQuotaType type, + uint64_t limit, + const MojoSetQuotaOptions* options) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoQueryQuotaIpcz(MojoHandle handle, + MojoQuotaType type, + const MojoQueryQuotaOptions* options, + uint64_t* current_limit, + uint64_t* current_usage) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +MojoResult MojoShutdownIpcz(const MojoShutdownOptions* options) { + NOTREACHED(); + return MOJO_RESULT_OK; +} + +MojoResult MojoSetDefaultProcessErrorHandlerIpcz( + MojoDefaultProcessErrorHandler handler, + const MojoSetDefaultProcessErrorHandlerOptions* options) { + return MOJO_RESULT_UNIMPLEMENTED; +} + +} // extern "C" + +MojoSystemThunks2 g_mojo_ipcz_thunks = { + sizeof(MojoSystemThunks2), + MojoInitializeIpcz, + MojoGetTimeTicksNowIpcz, + MojoCloseIpcz, + MojoQueryHandleSignalsStateIpcz, + MojoCreateMessagePipeIpcz, + MojoWriteMessageIpcz, + MojoReadMessageIpcz, + MojoFuseMessagePipesIpcz, + MojoCreateMessageIpcz, + MojoDestroyMessageIpcz, + MojoSerializeMessageIpcz, + MojoAppendMessageDataIpcz, + MojoGetMessageDataIpcz, + MojoSetMessageContextIpcz, + MojoGetMessageContextIpcz, + MojoNotifyBadMessageIpcz, + MojoCreateDataPipeIpcz, + MojoWriteDataIpcz, + MojoBeginWriteDataIpcz, + MojoEndWriteDataIpcz, + MojoReadDataIpcz, + MojoBeginReadDataIpcz, + MojoEndReadDataIpcz, + MojoCreateSharedBufferIpcz, + MojoDuplicateBufferHandleIpcz, + MojoMapBufferIpcz, + MojoUnmapBufferIpcz, + MojoGetBufferInfoIpcz, + MojoCreateTrapIpcz, + MojoAddTriggerIpcz, + MojoRemoveTriggerIpcz, + MojoArmTrapIpcz, + MojoWrapPlatformHandleIpcz, + MojoUnwrapPlatformHandleIpcz, + MojoWrapPlatformSharedMemoryRegionIpcz, + MojoUnwrapPlatformSharedMemoryRegionIpcz, + MojoCreateInvitationIpcz, + MojoAttachMessagePipeToInvitationIpcz, + MojoExtractMessagePipeFromInvitationIpcz, + MojoSendInvitationIpcz, + MojoAcceptInvitationIpcz, + MojoSetQuotaIpcz, + MojoQueryQuotaIpcz, + MojoShutdownIpcz, + MojoSetDefaultProcessErrorHandlerIpcz}; + +} // namespace + +const MojoSystemThunks2* GetMojoIpczImpl() { + return &g_mojo_ipcz_thunks; +} + +} // namespace mojo::core
diff --git a/mojo/core/core_ipcz.h b/mojo/core/core_ipcz.h new file mode 100644 index 0000000..9519d64 --- /dev/null +++ b/mojo/core/core_ipcz.h
@@ -0,0 +1,17 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_CORE_CORE_IPCZ_H_ +#define MOJO_CORE_CORE_IPCZ_H_ + +#include "mojo/core/system_impl_export.h" +#include "mojo/public/c/system/thunks.h" + +namespace mojo::core { + +MOJO_SYSTEM_IMPL_EXPORT const MojoSystemThunks2* GetMojoIpczImpl(); + +} // namespace mojo::core + +#endif // MOJO_CORE_CORE_IPCZ_H_
diff --git a/mojo/core/core_ipcz_test.cc b/mojo/core/core_ipcz_test.cc new file mode 100644 index 0000000..460b52c --- /dev/null +++ b/mojo/core/core_ipcz_test.cc
@@ -0,0 +1,52 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/core/core_ipcz.h" + +#include "base/check.h" +#include "mojo/core/ipcz_api.h" +#include "mojo/public/c/system/thunks.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo::core { +namespace { + +// Basic smoke tests for the Mojo Core API as implemented over ipcz. +class CoreIpczTest : public testing::Test { + public: + const MojoSystemThunks2& mojo() const { return *mojo_; } + const IpczAPI& ipcz() const { return GetIpczAPI(); } + IpczHandle node() const { return GetIpczNode(); } + + CoreIpczTest() { CHECK(InitializeIpczNodeForProcess({.is_broker = true})); } + ~CoreIpczTest() override { DestroyIpczNodeForProcess(); } + + private: + const MojoSystemThunks2* const mojo_{GetMojoIpczImpl()}; +}; + +TEST_F(CoreIpczTest, Close) { + // With ipcz-based Mojo Core, Mojo handles are ipcz handles. So Mojo Close() + // forwards to ipcz Close(). + + IpczHandle a, b; + EXPECT_EQ(IPCZ_RESULT_OK, + ipcz().OpenPortals(node(), IPCZ_NO_FLAGS, nullptr, &a, &b)); + + IpczPortalStatus status = {.size = sizeof(status)}; + EXPECT_EQ(IPCZ_RESULT_OK, + ipcz().QueryPortalStatus(b, IPCZ_NO_FLAGS, nullptr, &status)); + EXPECT_FALSE(status.flags & IPCZ_PORTAL_STATUS_PEER_CLOSED); + + EXPECT_EQ(MOJO_RESULT_OK, mojo().Close(a)); + + EXPECT_EQ(IPCZ_RESULT_OK, + ipcz().QueryPortalStatus(b, IPCZ_NO_FLAGS, nullptr, &status)); + EXPECT_TRUE(status.flags & IPCZ_PORTAL_STATUS_PEER_CLOSED); + + EXPECT_EQ(MOJO_RESULT_OK, mojo().Close(b)); +} + +} // namespace +} // namespace mojo::core
diff --git a/mojo/core/ipcz_api.cc b/mojo/core/ipcz_api.cc new file mode 100644 index 0000000..e52fe0a --- /dev/null +++ b/mojo/core/ipcz_api.cc
@@ -0,0 +1,60 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/core/ipcz_api.h" + +#include "base/check_op.h" +#include "mojo/core/ipcz_driver/driver.h" +#include "third_party/ipcz/include/ipcz/ipcz.h" +#include "third_party/ipcz/src/api.h" + +namespace mojo::core { + +namespace { + +class IpczAPIInitializer { + public: + explicit IpczAPIInitializer(IpczAPI& api) { + IpczResult result = IpczGetAPI(&api); + CHECK_EQ(result, IPCZ_RESULT_OK); + } +}; + +IpczHandle g_node = IPCZ_INVALID_HANDLE; +IpczNodeOptions g_options = {.is_broker = false, + .use_local_shared_memory_allocation = false}; + +} // namespace + +const IpczAPI& GetIpczAPI() { + static IpczAPI api = {sizeof(api)}; + static IpczAPIInitializer initializer(api); + return api; +} + +IpczHandle GetIpczNode() { + return g_node; +} + +bool InitializeIpczNodeForProcess(const IpczNodeOptions& options) { + g_options = options; + IpczCreateNodeFlags flags = + options.is_broker ? IPCZ_CREATE_NODE_AS_BROKER : IPCZ_NO_FLAGS; + IpczResult result = + GetIpczAPI().CreateNode(&ipcz_driver::kDriver, IPCZ_INVALID_DRIVER_HANDLE, + flags, nullptr, &g_node); + return result == IPCZ_RESULT_OK; +} + +void DestroyIpczNodeForProcess() { + CHECK(g_node); + GetIpczAPI().Close(g_node, IPCZ_NO_FLAGS, nullptr); + g_node = IPCZ_INVALID_HANDLE; +} + +const IpczNodeOptions& GetIpczNodeOptions() { + return g_options; +} + +} // namespace mojo::core
diff --git a/mojo/core/ipcz_api.h b/mojo/core/ipcz_api.h new file mode 100644 index 0000000..3dd74fb --- /dev/null +++ b/mojo/core/ipcz_api.h
@@ -0,0 +1,39 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_CORE_IPCZ_API_H_ +#define MOJO_CORE_IPCZ_API_H_ + +#include "mojo/core/system_impl_export.h" +#include "third_party/ipcz/include/ipcz/ipcz.h" + +namespace mojo::core { + +// Returns a reference to the global ipcz implementation. +MOJO_SYSTEM_IMPL_EXPORT const IpczAPI& GetIpczAPI(); + +// Returns a handle to the global ipcz node for the calling process, as +// initialized by InitializeIpczForProcess(). +MOJO_SYSTEM_IMPL_EXPORT IpczHandle GetIpczNode(); + +// Initializes a global ipcz node for the calling process with a set of options +// to configure the node. +struct IpczNodeOptions { + bool is_broker; + bool use_local_shared_memory_allocation; +}; +MOJO_SYSTEM_IMPL_EXPORT bool InitializeIpczNodeForProcess( + const IpczNodeOptions& options = {}); + +// Used by tests to tear down global state initialized by +// InitializeIpczNodeForProcess(). +MOJO_SYSTEM_IMPL_EXPORT void DestroyIpczNodeForProcess(); + +// Retrieves the global ipcz node options configured by a call to +// InitializeIpczNodeForProcess(). +MOJO_SYSTEM_IMPL_EXPORT const IpczNodeOptions& GetIpczNodeOptions(); + +} // namespace mojo::core + +#endif // MOJO_CORE_IPCZ_API_H_
diff --git a/mojo/core/ipcz_driver/driver.cc b/mojo/core/ipcz_driver/driver.cc new file mode 100644 index 0000000..25229d9 --- /dev/null +++ b/mojo/core/ipcz_driver/driver.cc
@@ -0,0 +1,134 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/core/ipcz_driver/driver.h" + +#include "base/rand_util.h" +#include "third_party/ipcz/include/ipcz/ipcz.h" + +namespace mojo::core::ipcz_driver { + +namespace { + +IpczResult IPCZ_API Close(IpczDriverHandle handle, + uint32_t flags, + const void* options) { + return IPCZ_RESULT_UNIMPLEMENTED; +} + +IpczResult IPCZ_API Serialize(IpczDriverHandle handle, + IpczDriverHandle transport_handle, + uint32_t flags, + const void* options, + void* data, + size_t* num_bytes, + IpczDriverHandle* handles, + size_t* num_handles) { + return IPCZ_RESULT_UNIMPLEMENTED; +} + +IpczResult IPCZ_API Deserialize(const void* data, + size_t num_bytes, + const IpczDriverHandle* handles, + size_t num_handles, + IpczDriverHandle transport_handle, + uint32_t flags, + const void* options, + IpczDriverHandle* driver_handle) { + return IPCZ_RESULT_UNIMPLEMENTED; +} + +IpczResult IPCZ_API CreateTransports(IpczDriverHandle transport0, + IpczDriverHandle transport1, + uint32_t flags, + const void* options, + IpczDriverHandle* new_transport0, + IpczDriverHandle* new_transport1) { + return IPCZ_RESULT_UNIMPLEMENTED; +} + +IpczResult IPCZ_API +ActivateTransport(IpczDriverHandle driver_transport, + IpczHandle ipcz_transport, + IpczTransportActivityHandler activity_handler, + uint32_t flags, + const void* options) { + return IPCZ_RESULT_UNIMPLEMENTED; +} + +IpczResult IPCZ_API DeactivateTransport(IpczDriverHandle driver_transport, + uint32_t flags, + const void* options) { + return IPCZ_RESULT_UNIMPLEMENTED; +} + +IpczResult IPCZ_API Transmit(IpczDriverHandle driver_transport, + const void* data, + size_t num_bytes, + const IpczDriverHandle* handles, + size_t num_handles, + uint32_t flags, + const void* options) { + return IPCZ_RESULT_UNIMPLEMENTED; +} + +IpczResult IPCZ_API AllocateSharedMemory(size_t num_bytes, + uint32_t flags, + const void* options, + IpczDriverHandle* driver_memory) { + return IPCZ_RESULT_UNIMPLEMENTED; +} + +IpczResult IPCZ_API GetSharedMemoryInfo(IpczDriverHandle driver_memory, + uint32_t flags, + const void* options, + IpczSharedMemoryInfo* info) { + return IPCZ_RESULT_UNIMPLEMENTED; +} + +IpczResult IPCZ_API DuplicateSharedMemory(IpczDriverHandle driver_memory, + uint32_t flags, + const void* options, + IpczDriverHandle* new_driver_memory) { + return IPCZ_RESULT_UNIMPLEMENTED; +} + +IpczResult IPCZ_API MapSharedMemory(IpczDriverHandle driver_memory, + uint32_t flags, + const void* options, + void** address, + IpczDriverHandle* driver_mapping) { + return IPCZ_RESULT_UNIMPLEMENTED; +} + +IpczResult IPCZ_API GenerateRandomBytes(size_t num_bytes, + uint32_t flags, + const void* options, + void* buffer) { + if (!buffer || !num_bytes) { + return IPCZ_RESULT_INVALID_ARGUMENT; + } + base::RandBytes(buffer, num_bytes); + return IPCZ_RESULT_OK; +} + +} // namespace + +const IpczDriver kDriver = { + sizeof(kDriver), + Close, + Serialize, + Deserialize, + CreateTransports, + ActivateTransport, + DeactivateTransport, + Transmit, + AllocateSharedMemory, + GetSharedMemoryInfo, + DuplicateSharedMemory, + MapSharedMemory, + GenerateRandomBytes, +}; + +} // namespace mojo::core::ipcz_driver
diff --git a/mojo/core/ipcz_driver/driver.h b/mojo/core/ipcz_driver/driver.h new file mode 100644 index 0000000..b5190db --- /dev/null +++ b/mojo/core/ipcz_driver/driver.h
@@ -0,0 +1,23 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_CORE_IPCZ_DRIVER_DRIVER_H_ +#define MOJO_CORE_IPCZ_DRIVER_DRIVER_H_ + +#include "mojo/core/system_impl_export.h" +#include "third_party/ipcz/include/ipcz/ipcz.h" + +namespace mojo::core::ipcz_driver { + +// The IpczDriver implementation provided by Mojo. This driver uses a transport +// based on mojo::core::Channel, and shared memory is implemented using //base +// shared memory APIs. +// +// The driver also supports boxing of platform handles and shared memory regions +// to simplify the transition of the Mojo bindings implementation to ipcz. +MOJO_SYSTEM_IMPL_EXPORT extern const IpczDriver kDriver; + +} // namespace mojo::core::ipcz_driver + +#endif // MOJO_CORE_IPCZ_DRIVER_DRIVER_H_
diff --git a/mojo/public/DEPS b/mojo/public/DEPS index 8bed1ad..f9b6d57 100644 --- a/mojo/public/DEPS +++ b/mojo/public/DEPS
@@ -3,6 +3,7 @@ "+build", "+mojo/public", "+testing", + "+third_party/ipcz/include", "-mojo", "+mojo/public",
diff --git a/net/base/features.cc b/net/base/features.cc index 2b6b99c..b4154a26 100644 --- a/net/base/features.cc +++ b/net/base/features.cc
@@ -336,6 +336,10 @@ const base::FeatureParam<int> kStorageAccessAPIImplicitGrantLimit{ &kStorageAccessAPI, "storage-access-api-implicit-grant-limit", kStorageAccessAPIDefaultImplicitGrantLimit}; +const base::FeatureParam<bool> kStorageAccessAPIGrantsUnpartitionedStorage( + &kStorageAccessAPI, + "storage-access-api-grants-unpartitioned-storage", + false); // Enables partitioning of third party storage (IndexedDB, CacheStorage, etc.) // by the top level site to reduce fingerprinting.
diff --git a/net/base/features.h b/net/base/features.h index 5807d3e..f01a1d2 100644 --- a/net/base/features.h +++ b/net/base/features.h
@@ -476,8 +476,14 @@ NET_EXPORT extern const int kStorageAccessAPIDefaultImplicitGrantLimit; NET_EXPORT extern const base::FeatureParam<int> kStorageAccessAPIImplicitGrantLimit; +// Whether the Storage Access API can grant access to storage (even if it is +// unpartitioned). When this feature is disabled, access to storage is only +// granted if the storage is partitioned. +NET_EXPORT extern const base::FeatureParam<bool> + kStorageAccessAPIGrantsUnpartitionedStorage; NET_EXPORT extern const base::Feature kThirdPartyStoragePartitioning; + } // namespace net::features #endif // NET_BASE_FEATURES_H_
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc index 65225db5..c433232 100644 --- a/net/cookies/cookie_monster.cc +++ b/net/cookies/cookie_monster.cc
@@ -2265,6 +2265,20 @@ // Can be up to kMaxCookies. UMA_HISTOGRAM_COUNTS_10000("Cookie.NumKeys", num_keys_); + std::map<std::string, size_t> n_same_site_none_cookies; + for (const auto& [host_key, host_cookie] : cookies_) { + if (!host_cookie || !host_cookie->IsEffectivelySameSiteNone()) + continue; + n_same_site_none_cookies[host_key]++; + } + size_t max_n_cookies = 0; + for (const auto& entry : n_same_site_none_cookies) { + max_n_cookies = std::max(max_n_cookies, entry.second); + } + // Can be up to 180 cookies, the max per-domain. + base::UmaHistogramCounts1000("Cookie.MaxSameSiteNoneCookiesPerKey", + max_n_cookies); + // Collect stats for partitioned cookies if they are enabled. if (base::FeatureList::IsEnabled(features::kPartitionedCookies)) { base::UmaHistogramCounts1000("Cookie.PartitionCount",
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc index 6da3a84c..bdf4289 100644 --- a/net/cookies/cookie_monster_unittest.cc +++ b/net/cookies/cookie_monster_unittest.cc
@@ -3469,6 +3469,57 @@ } } +TEST_F(CookieMonsterTest, MaxSameSiteNoneCookiesPerKey) { + const char kHistogramName[] = "Cookie.MaxSameSiteNoneCookiesPerKey"; + + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); + ASSERT_EQ(0u, GetAllCookies(cm.get()).size()); + + { // Only SameSite cookies should not log a sample. + base::HistogramTester histogram_tester; + + ASSERT_TRUE(CreateAndSetCookie(cm.get(), GURL("https://domain1.test"), + "A=1;SameSite=Lax", + CookieOptions::MakeAllInclusive())); + ASSERT_EQ(1u, GetAllCookies(cm.get()).size()); + ASSERT_TRUE(cm->DoRecordPeriodicStatsForTesting()); + histogram_tester.ExpectUniqueSample(kHistogramName, 0 /* sample */, + 1 /* count */); + } + + { // SameSite=None cookie should log a sample. + base::HistogramTester histogram_tester; + + ASSERT_TRUE(CreateAndSetCookie(cm.get(), GURL("https://domain1.test"), + "B=2;SameSite=None;Secure", + CookieOptions::MakeAllInclusive())); + ASSERT_EQ(2u, GetAllCookies(cm.get()).size()); + ASSERT_TRUE(cm->DoRecordPeriodicStatsForTesting()); + histogram_tester.ExpectUniqueSample(kHistogramName, 1 /* sample */, + 1 /* count */); + } + + { // Should log the maximum number of SameSite=None cookies. + base::HistogramTester histogram_tester; + + ASSERT_TRUE(CreateAndSetCookie(cm.get(), GURL("https://domain2.test"), + "A=1;SameSite=None;Secure", + CookieOptions::MakeAllInclusive())); + ASSERT_TRUE(CreateAndSetCookie(cm.get(), GURL("https://domain2.test"), + "B=2;SameSite=None;Secure", + CookieOptions::MakeAllInclusive())); + ASSERT_TRUE(CreateAndSetCookie(cm.get(), GURL("https://domain3.test"), + "A=1;SameSite=None;Secure", + CookieOptions::MakeAllInclusive())); + ASSERT_EQ(5u, GetAllCookies(cm.get()).size()); + ASSERT_TRUE(cm->DoRecordPeriodicStatsForTesting()); + histogram_tester.ExpectUniqueSample(kHistogramName, 2 /* sample */, + 1 /* count */); + } +} + // Test that localhost URLs can set and get secure cookies, even if // non-cryptographic. TEST_F(CookieMonsterTest, SecureCookieLocalhost) { @@ -5308,12 +5359,14 @@ net::SchemefulSite member4(GURL("https://member4.test")); access_delegate_->SetFirstPartySets({ - {owner1, net::FirstPartySetEntry(owner1, net::SiteType::kPrimary)}, - {member1, net::FirstPartySetEntry(owner1, net::SiteType::kAssociated)}, - {member2, net::FirstPartySetEntry(owner1, net::SiteType::kAssociated)}, - {owner2, net::FirstPartySetEntry(owner2, net::SiteType::kPrimary)}, - {member3, net::FirstPartySetEntry(owner2, net::SiteType::kAssociated)}, - {member4, net::FirstPartySetEntry(owner2, net::SiteType::kAssociated)}, + {owner1, + net::FirstPartySetEntry(owner1, net::SiteType::kPrimary, absl::nullopt)}, + {member1, net::FirstPartySetEntry(owner1, net::SiteType::kAssociated, 0)}, + {member2, net::FirstPartySetEntry(owner1, net::SiteType::kAssociated, 1)}, + {owner2, + net::FirstPartySetEntry(owner2, net::SiteType::kPrimary, absl::nullopt)}, + {member3, net::FirstPartySetEntry(owner2, net::SiteType::kAssociated, 0)}, + {member4, net::FirstPartySetEntry(owner2, net::SiteType::kAssociated, 1)}, }); ASSERT_TRUE(SetCookie(cm(), GURL("https://owner1.test"), kValidCookieLine));
diff --git a/net/cookies/cookie_partition_key_collection_unittest.cc b/net/cookies/cookie_partition_key_collection_unittest.cc index 30df324..01a9bad 100644 --- a/net/cookies/cookie_partition_key_collection_unittest.cc +++ b/net/cookies/cookie_partition_key_collection_unittest.cc
@@ -113,10 +113,10 @@ TestCookieAccessDelegate delegate; delegate.SetFirstPartySets({ - {kOwnerSite, - net::FirstPartySetEntry(kOwnerSite, net::SiteType::kPrimary)}, + {kOwnerSite, net::FirstPartySetEntry(kOwnerSite, net::SiteType::kPrimary, + absl::nullopt)}, {kMemberSite, - net::FirstPartySetEntry(kOwnerSite, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(kOwnerSite, net::SiteType::kAssociated, 0)}, }); CookiePartitionKeyCollection empty_key_collection;
diff --git a/net/cookies/first_party_set_entry.cc b/net/cookies/first_party_set_entry.cc index 689789b..0bb5cca 100644 --- a/net/cookies/first_party_set_entry.cc +++ b/net/cookies/first_party_set_entry.cc
@@ -10,11 +10,33 @@ namespace net { +FirstPartySetEntry::SiteIndex::SiteIndex() = default; + +FirstPartySetEntry::SiteIndex::SiteIndex(uint32_t value) : value_(value) {} + +bool FirstPartySetEntry::SiteIndex::operator==(const SiteIndex& other) const { + return value_ == other.value_; +} + FirstPartySetEntry::FirstPartySetEntry() = default; +FirstPartySetEntry::FirstPartySetEntry( + SchemefulSite primary, + SiteType site_type, + absl::optional<FirstPartySetEntry::SiteIndex> site_index) + : primary_(primary), site_type_(site_type), site_index_(site_index) { + if (site_type_ == SiteType::kPrimary) { + DCHECK(!site_index_.has_value()); + } +} + FirstPartySetEntry::FirstPartySetEntry(SchemefulSite primary, - SiteType site_type) - : primary_(primary), site_type_(site_type) {} + SiteType site_type, + uint32_t site_index) + : FirstPartySetEntry( + primary, + site_type, + absl::make_optional(FirstPartySetEntry::SiteIndex(site_index))) {} FirstPartySetEntry::FirstPartySetEntry(const FirstPartySetEntry&) = default; FirstPartySetEntry& FirstPartySetEntry::operator=(const FirstPartySetEntry&) = @@ -26,17 +48,29 @@ FirstPartySetEntry::~FirstPartySetEntry() = default; bool FirstPartySetEntry::operator==(const FirstPartySetEntry& other) const { - return std::tie(primary_, site_type_) == - std::tie(other.primary_, other.site_type_); + return std::tie(primary_, site_type_, site_index_) == + std::tie(other.primary_, other.site_type_, other.site_index_); } bool FirstPartySetEntry::operator!=(const FirstPartySetEntry& other) const { return !(*this == other); } +std::ostream& operator<<(std::ostream& os, + const FirstPartySetEntry::SiteIndex& index) { + os << index.value(); + return os; +} + std::ostream& operator<<(std::ostream& os, const FirstPartySetEntry& entry) { os << "{" << entry.primary() << ", " << static_cast<int>(entry.site_type()) - << "}"; + << ", "; + if (entry.site_index().has_value()) { + os << entry.site_index().value(); + } else { + os << "{}"; + } + os << "}"; return os; }
diff --git a/net/cookies/first_party_set_entry.h b/net/cookies/first_party_set_entry.h index 458b05a..d4a8b7e 100644 --- a/net/cookies/first_party_set_entry.h +++ b/net/cookies/first_party_set_entry.h
@@ -23,11 +23,28 @@ // First-Party Set. class NET_EXPORT FirstPartySetEntry { public: - FirstPartySetEntry(); + class NET_EXPORT SiteIndex { + public: + SiteIndex(); + explicit SiteIndex(uint32_t value); + bool operator==(const SiteIndex& other) const; + + uint32_t value() const { return value_; } + + private: + uint32_t value_; + }; + + FirstPartySetEntry(); // `primary` is the primary site in the First-Party Set associated with this // entry. - FirstPartySetEntry(SchemefulSite primary, SiteType site_type); + FirstPartySetEntry(SchemefulSite primary, + SiteType site_type, + absl::optional<SiteIndex> site_index); + FirstPartySetEntry(SchemefulSite primary, + SiteType site_type, + uint32_t site_index); FirstPartySetEntry(const FirstPartySetEntry&); FirstPartySetEntry& operator=(const FirstPartySetEntry&); @@ -43,11 +60,22 @@ SiteType site_type() const { return site_type_; } + const absl::optional<SiteIndex>& site_index() const { return site_index_; } + private: + // The primary site associated with this site's set. SchemefulSite primary_; + // The type associated with this site. SiteType site_type_; + // The index of this site in the set declaration, if a meaningful index + // exists. Primary sites do not have indices, nor do sites that were defined + // or affected by an enterprise policy set. + absl::optional<SiteIndex> site_index_; }; +NET_EXPORT std::ostream& operator<<( + std::ostream& os, + const FirstPartySetEntry::SiteIndex& site_index); NET_EXPORT std::ostream& operator<<(std::ostream& os, const FirstPartySetEntry& fpse);
diff --git a/net/http/http_version.h b/net/http/http_version.h index 13864a6..29cbf81 100644 --- a/net/http/http_version.h +++ b/net/http/http_version.h
@@ -16,7 +16,8 @@ HttpVersion() : value_(0) { } // Build from unsigned major/minor pair. - HttpVersion(uint16_t major, uint16_t minor) : value_(major << 16 | minor) {} + HttpVersion(uint16_t major, uint16_t minor) + : value_(static_cast<uint32_t>(major << 16) | minor) {} // Major version number. uint16_t major_value() const { return value_ >> 16; }
diff --git a/net/traffic_annotation/network_traffic_annotation.h b/net/traffic_annotation/network_traffic_annotation.h index 1d01213..108717e 100644 --- a/net/traffic_annotation/network_traffic_annotation.h +++ b/net/traffic_annotation/network_traffic_annotation.h
@@ -21,8 +21,9 @@ // Recursively compute hash code of the given string as a constant expression. template <int N> constexpr uint32_t recursive_hash(const char* str) { - return static_cast<uint32_t>((recursive_hash<N - 1>(str) * 31 + str[N - 1]) % - 138003713); + return (recursive_hash<N - 1>(str) * 31u + + static_cast<uint32_t>(str[N - 1])) % + 138003713u; } // Recursion stopper for the above function. Note that string of size 0 will
diff --git a/net/url_request/url_request_http_job_unittest.cc b/net/url_request/url_request_http_job_unittest.cc index 9a19dd7..8d85ff0 100644 --- a/net/url_request/url_request_http_job_unittest.cc +++ b/net/url_request/url_request_http_job_unittest.cc
@@ -1923,10 +1923,10 @@ /*first_party_sets_enabled=*/false); auto cookie_access_delegate = std::make_unique<TestCookieAccessDelegate>(); cookie_access_delegate->SetFirstPartySets({ - {kOwnerSite, - net::FirstPartySetEntry(kOwnerSite, net::SiteType::kPrimary)}, + {kOwnerSite, net::FirstPartySetEntry(kOwnerSite, net::SiteType::kPrimary, + absl::nullopt)}, {kMemberSite, - net::FirstPartySetEntry(kOwnerSite, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(kOwnerSite, net::SiteType::kAssociated, 0)}, }); cookie_monster->SetCookieAccessDelegate(std::move(cookie_access_delegate)); context_builder->SetCookieStore(std::move(cookie_monster));
diff --git a/services/cert_verifier/BUILD.gn b/services/cert_verifier/BUILD.gn index bb1d831..0852a382 100644 --- a/services/cert_verifier/BUILD.gn +++ b/services/cert_verifier/BUILD.gn
@@ -70,18 +70,3 @@ "//testing/gtest", ] } - -source_set("test_support") { - testonly = true - - sources = [ - "test_cert_verifier_service_factory.cc", - "test_cert_verifier_service_factory.h", - ] - - deps = [ - ":lib", - "//base", - "//net", - ] -}
diff --git a/services/network/cookie_manager_unittest.cc b/services/network/cookie_manager_unittest.cc index 705f07ef..a426f12 100644 --- a/services/network/cookie_manager_unittest.cc +++ b/services/network/cookie_manager_unittest.cc
@@ -2960,10 +2960,11 @@ delegate_ = std::make_unique<net::TestCookieAccessDelegate>(); first_party_sets_.insert( {owner_site_, - net::FirstPartySetEntry(owner_site_, net::SiteType::kPrimary)}); + net::FirstPartySetEntry(owner_site_, net::SiteType::kPrimary, + absl::nullopt)}); first_party_sets_.insert( {member_site_, - net::FirstPartySetEntry(owner_site_, net::SiteType::kAssociated)}); + net::FirstPartySetEntry(owner_site_, net::SiteType::kAssociated, 0)}); delegate_->SetFirstPartySets(first_party_sets_); cookie_store()->SetCookieAccessDelegate(std::move(delegate_)); }
diff --git a/services/network/cookie_settings.cc b/services/network/cookie_settings.cc index 98856bb..bc8267d 100644 --- a/services/network/cookie_settings.cc +++ b/services/network/cookie_settings.cc
@@ -14,6 +14,8 @@ #include "base/ranges/algorithm.h" #include "base/stl_util.h" #include "components/content_settings/core/common/content_settings.h" +#include "components/content_settings/core/common/cookie_settings_base.h" +#include "net/base/features.h" #include "net/base/net_errors.h" #include "net/base/network_delegate.h" #include "net/cookies/canonical_cookie.h"
diff --git a/services/network/first_party_sets/first_party_sets_access_delegate_unittest.cc b/services/network/first_party_sets/first_party_sets_access_delegate_unittest.cc index 596ac68..53a4356 100644 --- a/services/network/first_party_sets/first_party_sets_access_delegate_unittest.cc +++ b/services/network/first_party_sets/first_party_sets_access_delegate_unittest.cc
@@ -73,15 +73,15 @@ &first_party_sets_manager_) { first_party_sets_manager_.SetCompleteSets({ {kSet1Member1, - net::FirstPartySetEntry(kSet1Owner, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(kSet1Owner, net::SiteType::kAssociated, 0)}, {kSet1Member2, - net::FirstPartySetEntry(kSet1Owner, net::SiteType::kAssociated)}, - {kSet1Owner, - net::FirstPartySetEntry(kSet1Owner, net::SiteType::kPrimary)}, + net::FirstPartySetEntry(kSet1Owner, net::SiteType::kAssociated, 1)}, + {kSet1Owner, net::FirstPartySetEntry( + kSet1Owner, net::SiteType::kPrimary, absl::nullopt)}, {kSet2Member1, - net::FirstPartySetEntry(kSet2Owner, net::SiteType::kAssociated)}, - {kSet2Owner, - net::FirstPartySetEntry(kSet2Owner, net::SiteType::kPrimary)}, + net::FirstPartySetEntry(kSet2Owner, net::SiteType::kAssociated, 0)}, + {kSet2Owner, net::FirstPartySetEntry( + kSet2Owner, net::SiteType::kPrimary, absl::nullopt)}, }); } @@ -108,10 +108,10 @@ TEST_F(NoopFirstPartySetsAccessDelegateTest, FindOwner) { EXPECT_THAT(delegate().FindOwner(kSet1Owner, base::NullCallback()), absl::make_optional(net::FirstPartySetEntry( - kSet1Owner, net::SiteType::kPrimary))); + kSet1Owner, net::SiteType::kPrimary, absl::nullopt))); EXPECT_THAT(delegate().FindOwner(kSet2Member1, base::NullCallback()), absl::make_optional(net::FirstPartySetEntry( - kSet2Owner, net::SiteType::kAssociated))); + kSet2Owner, net::SiteType::kAssociated, 0))); } TEST_F(NoopFirstPartySetsAccessDelegateTest, FindOwners) { @@ -119,9 +119,9 @@ delegate().FindOwners({kSet1Member1, kSet2Member1}, base::NullCallback()), FirstPartySetsAccessDelegate::OwnersResult({ {kSet1Member1, - net::FirstPartySetEntry(kSet1Owner, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(kSet1Owner, net::SiteType::kAssociated, 0)}, {kSet2Member1, - net::FirstPartySetEntry(kSet2Owner, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(kSet2Owner, net::SiteType::kAssociated, 0)}, })); } @@ -134,15 +134,15 @@ &first_party_sets_manager_) { first_party_sets_manager_.SetCompleteSets({ {kSet1Member1, - net::FirstPartySetEntry(kSet1Owner, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(kSet1Owner, net::SiteType::kAssociated, 0)}, {kSet1Member2, - net::FirstPartySetEntry(kSet1Owner, net::SiteType::kAssociated)}, - {kSet1Owner, - net::FirstPartySetEntry(kSet1Owner, net::SiteType::kPrimary)}, + net::FirstPartySetEntry(kSet1Owner, net::SiteType::kAssociated, 1)}, + {kSet1Owner, net::FirstPartySetEntry( + kSet1Owner, net::SiteType::kPrimary, absl::nullopt)}, {kSet2Member1, - net::FirstPartySetEntry(kSet2Owner, net::SiteType::kAssociated)}, - {kSet2Owner, - net::FirstPartySetEntry(kSet2Owner, net::SiteType::kPrimary)}, + net::FirstPartySetEntry(kSet2Owner, net::SiteType::kAssociated, 0)}, + {kSet2Owner, net::FirstPartySetEntry( + kSet2Owner, net::SiteType::kPrimary, absl::nullopt)}, }); } @@ -198,8 +198,8 @@ TEST_F(FirstPartySetsAccessDelegateDisabledTest, ComputeMetadata) { // Same as the default ctor, but just to be explicit: net::FirstPartySetMetadata expected_metadata(net::SamePartyContext(), - /*frame_owner=*/nullptr, - /*top_frame_owner=*/nullptr); + /*frame_entry=*/nullptr, + /*top_frame_entry=*/nullptr); EXPECT_THAT(delegate().ComputeMetadata( kSet1Member1, &kSet1Member1, {kSet1Member1, kSet1Owner}, @@ -250,7 +250,7 @@ delegate_remote()->NotifyReady(mojom::FirstPartySetsReadyEvent::New()); - net::FirstPartySetEntry entry(kSet1Owner, net::SiteType::kAssociated); + net::FirstPartySetEntry entry(kSet1Owner, net::SiteType::kAssociated, 0); EXPECT_EQ(future.Get(), net::FirstPartySetMetadata(net::SamePartyContext(Type::kSameParty), &entry, &entry)); @@ -263,7 +263,7 @@ delegate_remote()->NotifyReady(mojom::FirstPartySetsReadyEvent::New()); EXPECT_THAT(future.Get(), absl::make_optional(net::FirstPartySetEntry( - kSet1Owner, net::SiteType::kAssociated))); + kSet1Owner, net::SiteType::kAssociated, 0))); } TEST_F(AsyncFirstPartySetsAccessDelegateTest, QueryBeforeReady_FindOwners) { @@ -273,26 +273,29 @@ delegate_remote()->NotifyReady(mojom::FirstPartySetsReadyEvent::New()); - EXPECT_THAT(future.Get(), - FirstPartySetsAccessDelegate::OwnersResult({ - {kSet1Member1, net::FirstPartySetEntry( - kSet1Owner, net::SiteType::kAssociated)}, - {kSet2Member1, net::FirstPartySetEntry( - kSet2Owner, net::SiteType::kAssociated)}, - })); + EXPECT_THAT( + future.Get(), + FirstPartySetsAccessDelegate::OwnersResult({ + {kSet1Member1, + net::FirstPartySetEntry(kSet1Owner, net::SiteType::kAssociated, 0)}, + {kSet2Member1, + net::FirstPartySetEntry(kSet2Owner, net::SiteType::kAssociated, 0)}, + })); } TEST_F(AsyncFirstPartySetsAccessDelegateTest, OverrideSets_ComputeMetadata) { delegate_remote()->NotifyReady(CreateFirstPartySetsReadyEvent({ {kSet1Member1, - {net::FirstPartySetEntry(kSet3Owner, net::SiteType::kAssociated)}}, + {net::FirstPartySetEntry(kSet3Owner, net::SiteType::kAssociated, 0)}}, {kSet3Owner, - {net::FirstPartySetEntry(kSet3Owner, net::SiteType::kPrimary)}}, + {net::FirstPartySetEntry(kSet3Owner, net::SiteType::kPrimary, + absl::nullopt)}}, })); - net::FirstPartySetEntry primary_entry(kSet3Owner, net::SiteType::kPrimary); + net::FirstPartySetEntry primary_entry(kSet3Owner, net::SiteType::kPrimary, + absl::nullopt); net::FirstPartySetEntry associated_entry(kSet3Owner, - net::SiteType::kAssociated); + net::SiteType::kAssociated, 0); EXPECT_EQ(ComputeMetadataAndWait(kSet3Owner, &kSet1Member1, {kSet1Member1}), net::FirstPartySetMetadata(net::SamePartyContext(Type::kSameParty), &primary_entry, &associated_entry)); @@ -301,7 +304,8 @@ TEST_F(AsyncFirstPartySetsAccessDelegateTest, OverrideSets_FindOwner) { delegate_remote()->NotifyReady(CreateFirstPartySetsReadyEvent({ {kSet3Owner, - {net::FirstPartySetEntry(kSet3Owner, net::SiteType::kPrimary)}}, + {net::FirstPartySetEntry(kSet3Owner, net::SiteType::kPrimary, + absl::nullopt)}}, })); EXPECT_THAT(FindOwnerAndWait(kSet3Owner), Optional(_)); @@ -310,7 +314,8 @@ TEST_F(AsyncFirstPartySetsAccessDelegateTest, OverrideSets_FindOwners) { delegate_remote()->NotifyReady(CreateFirstPartySetsReadyEvent({ {kSet3Owner, - {net::FirstPartySetEntry(kSet3Owner, net::SiteType::kPrimary)}}, + {net::FirstPartySetEntry(kSet3Owner, net::SiteType::kPrimary, + absl::nullopt)}}, })); EXPECT_THAT(FindOwnersAndWait({kSet3Owner}), @@ -323,15 +328,16 @@ SyncFirstPartySetsAccessDelegateTest() { delegate_remote()->NotifyReady(CreateFirstPartySetsReadyEvent({ {kSet3Member1, - {net::FirstPartySetEntry(kSet3Owner, net::SiteType::kAssociated)}}, + {net::FirstPartySetEntry(kSet3Owner, net::SiteType::kAssociated, 0)}}, {kSet3Owner, - {net::FirstPartySetEntry(kSet3Owner, net::SiteType::kPrimary)}}, + {net::FirstPartySetEntry(kSet3Owner, net::SiteType::kPrimary, + absl::nullopt)}}, })); } }; TEST_F(SyncFirstPartySetsAccessDelegateTest, ComputeMetadata) { - net::FirstPartySetEntry entry(kSet1Owner, net::SiteType::kAssociated); + net::FirstPartySetEntry entry(kSet1Owner, net::SiteType::kAssociated, 0); EXPECT_EQ(ComputeMetadataAndWait(kSet1Member1, &kSet1Member1, {kSet1Member1}), net::FirstPartySetMetadata(net::SamePartyContext(Type::kSameParty), &entry, &entry)); @@ -340,7 +346,7 @@ TEST_F(SyncFirstPartySetsAccessDelegateTest, FindOwner) { EXPECT_THAT(FindOwnerAndWait(kSet1Member1), absl::make_optional(net::FirstPartySetEntry( - kSet1Owner, net::SiteType::kAssociated))); + kSet1Owner, net::SiteType::kAssociated, 0))); } TEST_F(SyncFirstPartySetsAccessDelegateTest, FindOwners) { @@ -348,11 +354,11 @@ FindOwnersAndWait({kSet1Member1, kSet2Member1, kSet3Member1}), FirstPartySetsAccessDelegate::OwnersResult({ {kSet1Member1, - net::FirstPartySetEntry(kSet1Owner, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(kSet1Owner, net::SiteType::kAssociated, 0)}, {kSet2Member1, - net::FirstPartySetEntry(kSet2Owner, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(kSet2Owner, net::SiteType::kAssociated, 0)}, {kSet3Member1, - net::FirstPartySetEntry(kSet3Owner, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(kSet3Owner, net::SiteType::kAssociated, 0)}, })); }
diff --git a/services/network/first_party_sets/first_party_sets_manager.cc b/services/network/first_party_sets/first_party_sets_manager.cc index 4218814..d08e661 100644 --- a/services/network/first_party_sets/first_party_sets_manager.cc +++ b/services/network/first_party_sets/first_party_sets_manager.cc
@@ -167,11 +167,11 @@ fps_context_config.customizations().find(normalized_site); it != fps_context_config.customizations().end()) { if (it->second.has_value()) { - entry = net::FirstPartySetEntry(it->second.value()); + entry = it->second.value(); } } else if (const auto it = sets_->find(normalized_site); it != sets_->end()) { - entry = net::FirstPartySetEntry(it->second); + entry = it->second; } }
diff --git a/services/network/first_party_sets/first_party_sets_manager_unittest.cc b/services/network/first_party_sets/first_party_sets_manager_unittest.cc index b3561c1..60dc3861 100644 --- a/services/network/first_party_sets/first_party_sets_manager_unittest.cc +++ b/services/network/first_party_sets/first_party_sets_manager_unittest.cc
@@ -106,11 +106,11 @@ SetCompleteSets({{net::SchemefulSite(GURL("https://aaaa.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}}); + net::SiteType::kPrimary, absl::nullopt)}}); EXPECT_THAT(FindOwnersAndWait({ net::SchemefulSite(GURL("https://aaaa.test")), @@ -135,11 +135,11 @@ true, {{net::SchemefulSite(GURL("https://member1.test")), {net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, {net::SchemefulSite(GURL("https://example.test")), {net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}}}); + net::SiteType::kPrimary, absl::nullopt)}}}); // Works if the site is provided with WSS scheme instead of HTTPS. EXPECT_THAT( @@ -160,21 +160,21 @@ SetCompleteSets({{net::SchemefulSite(GURL("https://member.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}}); + net::SiteType::kPrimary, absl::nullopt)}}); SetFirstPartySetsContextConfig( true, {{net::SchemefulSite(GURL("https://aaaa.test")), {net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, {net::SchemefulSite(GURL("https://example.test")), {net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}}}); + net::SiteType::kPrimary, absl::nullopt)}}}); EXPECT_FALSE( FindOwnerAndWait(net::SchemefulSite(GURL("https://example.test")))); @@ -192,11 +192,11 @@ SetCompleteSets({{net::SchemefulSite(GURL("https://aaaa.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}}); + net::SiteType::kPrimary, absl::nullopt)}}); EXPECT_THAT(FindOwnersAndWait({ net::SchemefulSite(GURL("https://aaaa.test")), @@ -206,11 +206,11 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://aaaa.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST_F(FirstPartySetsEnabledTest, SetCompleteSets_Idempotent) { @@ -221,11 +221,11 @@ SetCompleteSets({{net::SchemefulSite(GURL("https://aaaa.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}}); + net::SiteType::kPrimary, absl::nullopt)}}); EXPECT_THAT(FindOwnersAndWait({ net::SchemefulSite(GURL("https://aaaa.test")), net::SchemefulSite(GURL("https://example.test")), @@ -259,21 +259,21 @@ {net::SchemefulSite(GURL("https://member1.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://member3.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://member2.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://foo.test")), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, }); // We don't wait for the sets to be loaded before returning, in order to let @@ -296,7 +296,7 @@ { net::SchemefulSite owner(GURL("https://example.test")); - net::FirstPartySetEntry entry(owner, net::SiteType::kAssociated); + net::FirstPartySetEntry entry(owner, net::SiteType::kAssociated, 0); EXPECT_EQ(future.Get(), net::FirstPartySetMetadata( @@ -315,7 +315,7 @@ EXPECT_THAT(future.Get(), absl::make_optional(net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated))); + net::SiteType::kAssociated, 0))); } TEST_F(AsyncPopulatedFirstPartySetsManagerTest, QueryBeforeReady_FindOwners) { @@ -334,11 +334,11 @@ Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } class PopulatedFirstPartySetsManagerTest @@ -784,8 +784,10 @@ net::SchemefulSite owner(GURL("https://example.test")); net::SchemefulSite wss_member(GURL("wss://member1.test")); net::SchemefulSite wss_nonmember(GURL("wss://nonmember.test")); - net::FirstPartySetEntry primary_entry(owner, net::SiteType::kPrimary); - net::FirstPartySetEntry associated_entry(owner, net::SiteType::kAssociated); + net::FirstPartySetEntry primary_entry(owner, net::SiteType::kPrimary, + absl::nullopt); + net::FirstPartySetEntry associated_entry(owner, net::SiteType::kAssociated, + 0); // Works as usual for sites that are in First-Party sets. EXPECT_EQ(ComputeMetadataAndWait(member, &member, {member}), @@ -837,18 +839,20 @@ const absl::optional<net::FirstPartySetEntry> expected; } test_cases[] = { {"https://example.test", - net::FirstPartySetEntry(kSetOwner1, net::SiteType::kPrimary)}, + net::FirstPartySetEntry(kSetOwner1, net::SiteType::kPrimary, + absl::nullopt)}, // Insecure URL {"http://example.test", absl::nullopt}, // Test member {"https://member1.test", - net::FirstPartySetEntry(kSetOwner1, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(kSetOwner1, net::SiteType::kAssociated, 0)}, {"http://member1.test", absl::nullopt}, // Test another disjoint set {"https://foo.test", - net::FirstPartySetEntry(kSetOwner2, net::SiteType::kPrimary)}, + net::FirstPartySetEntry(kSetOwner2, net::SiteType::kPrimary, + absl::nullopt)}, {"https://member2.test", - net::FirstPartySetEntry(kSetOwner2, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(kSetOwner2, net::SiteType::kAssociated, 0)}, // Test a site not in a set {"https://nonmember.test", absl::nullopt}, }; @@ -871,13 +875,13 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)))); + net::SiteType::kPrimary, absl::nullopt)))); EXPECT_THAT(FindOwnersAndWait({kMember1}), UnorderedElementsAre( Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); EXPECT_THAT(FindOwnersAndWait({kNonmember}), IsEmpty()); EXPECT_THAT(FindOwnersAndWait({kExample, kNonmember}), @@ -885,54 +889,54 @@ Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)))); + net::SiteType::kPrimary, absl::nullopt)))); EXPECT_THAT(FindOwnersAndWait({kMember1, kNonmember}), UnorderedElementsAre( Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); EXPECT_THAT(FindOwnersAndWait({kExample, kFoo}), UnorderedElementsAre( Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://foo.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)))); + net::SiteType::kPrimary, absl::nullopt)))); EXPECT_THAT(FindOwnersAndWait({kMember1, kFoo}), UnorderedElementsAre( Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://foo.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)))); + net::SiteType::kPrimary, absl::nullopt)))); EXPECT_THAT(FindOwnersAndWait({kExample, kMember2}), UnorderedElementsAre( Pair(SerializesTo("https://example.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); EXPECT_THAT(FindOwnersAndWait({kMember1, kMember2}), UnorderedElementsAre( Pair(SerializesTo("https://member1.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)), + net::SiteType::kAssociated, 0)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } class OverrideSetsFirstPartySetsManagerTest : public FirstPartySetsEnabledTest { @@ -942,16 +946,16 @@ {net::SchemefulSite(GURL("https://member1.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, {net::SchemefulSite(GURL("https://member2.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kAssociated)}, + net::SiteType::kAssociated, 0)}, // Below are the owner self mappings. {net::SchemefulSite(GURL("https://example.test")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.test")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, }); SetFirstPartySetsContextConfig( @@ -961,14 +965,14 @@ {net::SchemefulSite(GURL("https://foo.test")), {net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)}}, + net::SiteType::kPrimary, absl::nullopt)}}, // Removed entry: {net::SchemefulSite(GURL("https://member1.test")), absl::nullopt}, // Remapped entry: {net::SchemefulSite(GURL("https://member2.test")), {net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)}}, + net::SiteType::kAssociated, 0)}}, }); } }; @@ -977,13 +981,13 @@ EXPECT_EQ( FindOwnerAndWait(net::SchemefulSite(GURL("https://foo.test"))), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)); + net::SiteType::kPrimary, absl::nullopt)); EXPECT_EQ(FindOwnerAndWait(net::SchemefulSite(GURL("https://member1.test"))), absl::nullopt); EXPECT_EQ( FindOwnerAndWait(net::SchemefulSite(GURL("https://member2.test"))), net::FirstPartySetEntry(net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)); + net::SiteType::kAssociated, 0)); } TEST_F(OverrideSetsFirstPartySetsManagerTest, FindOwners) { @@ -996,11 +1000,11 @@ Pair(SerializesTo("https://foo.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kPrimary)), + net::SiteType::kPrimary, absl::nullopt)), Pair(SerializesTo("https://member2.test"), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://foo.test")), - net::SiteType::kAssociated)))); + net::SiteType::kAssociated, 0)))); } TEST_F(OverrideSetsFirstPartySetsManagerTest, ComputeMetadata) { @@ -1009,10 +1013,12 @@ net::SchemefulSite member1(GURL("https://member1.test")); net::SchemefulSite member2(GURL("https://member2.test")); - net::FirstPartySetEntry example_primary_entry(example, - net::SiteType::kPrimary); - net::FirstPartySetEntry foo_primary_entry(foo, net::SiteType::kPrimary); - net::FirstPartySetEntry foo_associated_entry(foo, net::SiteType::kAssociated); + net::FirstPartySetEntry example_primary_entry( + example, net::SiteType::kPrimary, absl::nullopt); + net::FirstPartySetEntry foo_primary_entry(foo, net::SiteType::kPrimary, + absl::nullopt); + net::FirstPartySetEntry foo_associated_entry(foo, net::SiteType::kAssociated, + 0); { // member1 has been removed from its set. net::FirstPartySetMetadata expected(
diff --git a/services/network/public/cpp/first_party_sets_mojom_traits.cc b/services/network/public/cpp/first_party_sets_mojom_traits.cc index ef51d08..cbc0fe1 100644 --- a/services/network/public/cpp/first_party_sets_mojom_traits.cc +++ b/services/network/public/cpp/first_party_sets_mojom_traits.cc
@@ -15,6 +15,14 @@ namespace mojo { +bool StructTraits<network::mojom::SiteIndexDataView, + net::FirstPartySetEntry::SiteIndex>:: + Read(network::mojom::SiteIndexDataView index, + net::FirstPartySetEntry::SiteIndex* out) { + *out = net::FirstPartySetEntry::SiteIndex(index.value()); + return true; +} + bool EnumTraits<network::mojom::SiteType, net::SiteType>::FromMojom( network::mojom::SiteType site_type, net::SiteType* out) { @@ -54,7 +62,11 @@ if (!entry.ReadSiteType(&site_type)) return false; - *out = net::FirstPartySetEntry(primary, site_type); + absl::optional<net::FirstPartySetEntry::SiteIndex> site_index; + if (!entry.ReadSiteIndex(&site_index)) + return false; + + *out = net::FirstPartySetEntry(primary, site_type, site_index); return true; }
diff --git a/services/network/public/cpp/first_party_sets_mojom_traits.h b/services/network/public/cpp/first_party_sets_mojom_traits.h index d7de0e8..3cfaf32 100644 --- a/services/network/public/cpp/first_party_sets_mojom_traits.h +++ b/services/network/public/cpp/first_party_sets_mojom_traits.h
@@ -17,6 +17,18 @@ template <> struct COMPONENT_EXPORT(FIRST_PARTY_SETS_MOJOM_TRAITS) + StructTraits<network::mojom::SiteIndexDataView, + net::FirstPartySetEntry::SiteIndex> { + static uint32_t value(const net::FirstPartySetEntry::SiteIndex& i) { + return i.value(); + } + + static bool Read(network::mojom::SiteIndexDataView index, + net::FirstPartySetEntry::SiteIndex* out); +}; + +template <> +struct COMPONENT_EXPORT(FIRST_PARTY_SETS_MOJOM_TRAITS) EnumTraits<network::mojom::SiteType, net::SiteType> { static network::mojom::SiteType ToMojom(net::SiteType site_type); @@ -35,6 +47,11 @@ return e.site_type(); } + static const absl::optional<net::FirstPartySetEntry::SiteIndex>& site_index( + const net::FirstPartySetEntry& e) { + return e.site_index(); + } + static bool Read(network::mojom::FirstPartySetEntryDataView entry, net::FirstPartySetEntry* out); };
diff --git a/services/network/public/cpp/first_party_sets_mojom_traits_unittest.cc b/services/network/public/cpp/first_party_sets_mojom_traits_unittest.cc index 0c8c8d7..eb1893a 100644 --- a/services/network/public/cpp/first_party_sets_mojom_traits_unittest.cc +++ b/services/network/public/cpp/first_party_sets_mojom_traits_unittest.cc
@@ -15,10 +15,20 @@ namespace network { namespace { +TEST(FirstPartySetsTraitsTest, Roundtrips_SiteIndex) { + net::FirstPartySetEntry::SiteIndex original(1337); + net::FirstPartySetEntry::SiteIndex round_tripped; + + EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SiteIndex>( + original, round_tripped)); + + EXPECT_EQ(original, round_tripped); +} + TEST(FirstPartySetsTraitsTest, Roundtrips_FirstPartySetEntry) { net::SchemefulSite primary(GURL("https://primary.test")); - net::FirstPartySetEntry original(primary, net::SiteType::kAssociated); + net::FirstPartySetEntry original(primary, net::SiteType::kAssociated, 1); net::FirstPartySetEntry round_tripped; EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::FirstPartySetEntry>( @@ -64,9 +74,10 @@ net::SchemefulSite frame_owner(GURL("https://frame.test")); net::SchemefulSite top_frame_owner(GURL("https://top_frame.test")); - net::FirstPartySetEntry frame_entry(frame_owner, net::SiteType::kAssociated); + net::FirstPartySetEntry frame_entry(frame_owner, net::SiteType::kAssociated, + 1); net::FirstPartySetEntry top_frame_entry(top_frame_owner, - net::SiteType::kAssociated); + net::SiteType::kAssociated, 2); auto make_metadata = [&]() { // Use non-default values to ensure serialization/deserialization works
diff --git a/services/network/public/cpp/network_param_mojom_traits.h b/services/network/public/cpp/network_param_mojom_traits.h index 2f97594..2c39e62 100644 --- a/services/network/public/cpp/network_param_mojom_traits.h +++ b/services/network/public/cpp/network_param_mojom_traits.h
@@ -52,10 +52,10 @@ class COMPONENT_EXPORT(NETWORK_CPP_NETWORK_PARAM) StructTraits<network::mojom::HttpVersionDataView, net::HttpVersion> { public: - static int16_t major_value(net::HttpVersion version) { + static uint16_t major_value(net::HttpVersion version) { return version.major_value(); } - static int16_t minor_value(net::HttpVersion version) { + static uint16_t minor_value(net::HttpVersion version) { return version.minor_value(); }
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn index 38abaac..df80f5b7 100644 --- a/services/network/public/mojom/BUILD.gn +++ b/services/network/public/mojom/BUILD.gn
@@ -752,6 +752,10 @@ { types = [ { + mojom = "network.mojom.SiteIndex" + cpp = "::net::FirstPartySetEntry::SiteIndex" + }, + { mojom = "network.mojom.FirstPartySetEntry" cpp = "::net::FirstPartySetEntry" },
diff --git a/services/network/public/mojom/first_party_sets.mojom b/services/network/public/mojom/first_party_sets.mojom index 0422b46a..74416d6 100644 --- a/services/network/public/mojom/first_party_sets.mojom +++ b/services/network/public/mojom/first_party_sets.mojom
@@ -6,6 +6,12 @@ import "services/network/public/mojom/schemeful_site.mojom"; +// This struct should match net::FirstPartySetEntry::SiteIndex in +// //net/cookies/first_party_set_entry.h +struct SiteIndex { + uint32 value; +}; + // This enum should match //net/cookies/first_party_set_entry.h. enum SiteType { kPrimary, @@ -16,6 +22,7 @@ struct FirstPartySetEntry { SchemefulSite primary; SiteType site_type; + SiteIndex? site_index; }; // Computed for every cookie access attempt but is only relevant for SameParty
diff --git a/services/network/restricted_cookie_manager_unittest.cc b/services/network/restricted_cookie_manager_unittest.cc index 6e1e2c3..08538f3 100644 --- a/services/network/restricted_cookie_manager_unittest.cc +++ b/services/network/restricted_cookie_manager_unittest.cc
@@ -464,11 +464,11 @@ {{net::SchemefulSite(GURL("https://example.com")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.com")), - net::SiteType::kPrimary)}, + net::SiteType::kPrimary, absl::nullopt)}, {net::SchemefulSite(GURL("https://member1.com")), net::FirstPartySetEntry( net::SchemefulSite(GURL("https://example.com")), - net::SiteType::kAssociated)}}); + net::SiteType::kAssociated, 0)}}); first_party_sets_access_delegate_remote_->NotifyReady( mojom::FirstPartySetsReadyEvent::New()); auto cookie_access_delegate = std::make_unique<CookieAccessDelegateImpl>( @@ -2056,10 +2056,10 @@ auto cookie_access_delegate = std::make_unique<net::TestCookieAccessDelegate>(); cookie_access_delegate->SetFirstPartySets({ - {kOwnerSite, - net::FirstPartySetEntry(kOwnerSite, net::SiteType::kPrimary)}, + {kOwnerSite, net::FirstPartySetEntry(kOwnerSite, net::SiteType::kPrimary, + absl::nullopt)}, {kMemberSite, - net::FirstPartySetEntry(kOwnerSite, net::SiteType::kAssociated)}, + net::FirstPartySetEntry(kOwnerSite, net::SiteType::kAssociated, 0)}, }); cookie_monster_.SetCookieAccessDelegate(std::move(cookie_access_delegate));
diff --git a/storage/browser/file_system/obfuscated_file_util.cc b/storage/browser/file_system/obfuscated_file_util.cc index 2c692cf..b238431 100644 --- a/storage/browser/file_system/obfuscated_file_util.cc +++ b/storage/browser/file_system/obfuscated_file_util.cc
@@ -306,15 +306,17 @@ base::WeakPtr<ObfuscatedFileUtilMemoryDelegate> memory_file_util_; }; +const base::FilePath::CharType ObfuscatedFileUtil::kFileSystemDirectory[] = + FILE_PATH_LITERAL("File System"); + ObfuscatedFileUtil::ObfuscatedFileUtil( scoped_refptr<SpecialStoragePolicy> special_storage_policy, - const base::FilePath& file_system_directory, + const base::FilePath& profile_path, leveldb::Env* env_override, const std::set<std::string>& known_type_strings, SandboxFileSystemBackendDelegate* sandbox_delegate, bool is_incognito) : special_storage_policy_(std::move(special_storage_policy)), - file_system_directory_(file_system_directory), env_override_(env_override), is_incognito_(is_incognito), db_flush_delay_seconds_(10 * 60), // 10 mins. @@ -323,10 +325,15 @@ DETACH_FROM_SEQUENCE(sequence_checker_); DCHECK(!is_incognito_ || (env_override && leveldb_chrome::IsMemEnv(env_override))); + file_system_directory_ = profile_path.Append(kFileSystemDirectory); if (is_incognito_) { - delegate_ = std::make_unique<ObfuscatedFileUtilMemoryDelegate>( - file_system_directory_); + // profile_path is passed here, so that the delegate is able to accommodate + // both codepaths of {{profile_path}}/File System (first-party) and + // {{profile_path}}/WebStorage (buckets-based). + // See https://crrev.com/c/3817542 for more context. + delegate_ = + std::make_unique<ObfuscatedFileUtilMemoryDelegate>(profile_path); } else { delegate_ = std::make_unique<ObfuscatedFileUtilDiskDelegate>(); }
diff --git a/storage/browser/file_system/obfuscated_file_util.h b/storage/browser/file_system/obfuscated_file_util.h index 4b13568..8118736 100644 --- a/storage/browser/file_system/obfuscated_file_util.h +++ b/storage/browser/file_system/obfuscated_file_util.h
@@ -136,6 +136,9 @@ virtual bool HasTypeDirectory(const std::string& type_string) const = 0; }; + // The FileSystem directory component. + static const base::FilePath::CharType kFileSystemDirectory[]; + // The type string is used to provide per-type isolation in the sandboxed // filesystem directory. `known_type_strings` are known type string names that // this file system should care about. This info is used to determine whether @@ -146,7 +149,7 @@ // and as a result, directories should only be directly compared using type // string values. ObfuscatedFileUtil(scoped_refptr<SpecialStoragePolicy> special_storage_policy, - const base::FilePath& file_system_directory, + const base::FilePath& profile_path, leveldb::Env* env_override, const std::set<std::string>& known_type_strings, SandboxFileSystemBackendDelegate* sandbox_delegate,
diff --git a/storage/browser/file_system/obfuscated_file_util_unittest.cc b/storage/browser/file_system/obfuscated_file_util_unittest.cc index acb3b0a1..09174f73c 100644 --- a/storage/browser/file_system/obfuscated_file_util_unittest.cc +++ b/storage/browser/file_system/obfuscated_file_util_unittest.cc
@@ -65,14 +65,15 @@ namespace { -// TODO(https://crbug.com/1322223): create an additional parameterized -// test mode for kIncognitoThirdParty. enum TestMode { kRegularFirstParty, kRegularFirstPartyNonDefaultBucket, kRegularThirdParty, kRegularThirdPartyNonDefaultBucket, - kIncognitoFirstParty + kIncognitoFirstParty, + kIncognitoFirstPartyNonDefaultBucket, + kIncognitoThirdParty, + kIncognitoThirdPartyNonDefaultBucket }; bool FileExists(const base::FilePath& path) { @@ -203,14 +204,23 @@ ~ObfuscatedFileUtilTest() override = default; - bool is_incognito() { return GetParam() == TestMode::kIncognitoFirstParty; } + bool is_incognito() { + return GetParam() == TestMode::kIncognitoFirstParty || + (GetParam() == TestMode::kIncognitoFirstPartyNonDefaultBucket) || + (GetParam() == TestMode::kIncognitoThirdParty) || + (GetParam() == TestMode::kIncognitoThirdPartyNonDefaultBucket); + } bool is_third_party_context() { return GetParam() == TestMode::kRegularThirdParty || - (GetParam() == TestMode::kRegularThirdPartyNonDefaultBucket); + (GetParam() == TestMode::kRegularThirdPartyNonDefaultBucket) || + (GetParam() == TestMode::kIncognitoThirdParty) || + (GetParam() == TestMode::kIncognitoThirdPartyNonDefaultBucket); } bool is_non_default_bucket() { return GetParam() == TestMode::kRegularFirstPartyNonDefaultBucket || - (GetParam() == TestMode::kRegularThirdPartyNonDefaultBucket); + (GetParam() == TestMode::kRegularThirdPartyNonDefaultBucket) || + (GetParam() == TestMode::kIncognitoFirstPartyNonDefaultBucket) || + (GetParam() == TestMode::kIncognitoThirdPartyNonDefaultBucket); } void SetUp() override { @@ -941,7 +951,10 @@ TestMode::kRegularFirstPartyNonDefaultBucket, TestMode::kRegularThirdParty, TestMode::kRegularThirdPartyNonDefaultBucket, - TestMode::kIncognitoFirstParty)); + TestMode::kIncognitoFirstParty, + TestMode::kIncognitoFirstPartyNonDefaultBucket, + TestMode::kIncognitoThirdParty, + TestMode::kIncognitoThirdPartyNonDefaultBucket)); TEST_P(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) { FileSystemURL url = CreateURLFromUTF8("fake/file"); @@ -2541,10 +2554,6 @@ } TEST_P(ObfuscatedFileUtilTest, DeleteDirectoryForBucketAndType) { - // TODO(https://crbug.com/1322223): Remove this early return once we resolve - // failures involving non-default buckets in incognito mode. - if (is_incognito()) - return; // Create directories. std::unique_ptr<SandboxFileSystemTestHelper> fs1 = NewFileSystem(default_bucket_, kFileSystemTypeTemporary); @@ -2715,10 +2724,6 @@ } TEST_P(ObfuscatedFileUtilTest, DeleteDirectoryForBucketAndType_DeleteAll) { - // TODO(https://crbug.com/1322223): Remove this early return once we resolve - // failures involving non-default buckets in incognito mode. - if (is_incognito()) - return; // Create origin directories. std::unique_ptr<SandboxFileSystemTestHelper> fs1 = NewFileSystem(default_bucket_, kFileSystemTypeTemporary);
diff --git a/storage/browser/file_system/sandbox_file_system_backend_delegate.cc b/storage/browser/file_system/sandbox_file_system_backend_delegate.cc index 60e192f..ed0d7a68 100644 --- a/storage/browser/file_system/sandbox_file_system_backend_delegate.cc +++ b/storage/browser/file_system/sandbox_file_system_backend_delegate.cc
@@ -162,10 +162,6 @@ } // namespace -const base::FilePath::CharType - SandboxFileSystemBackendDelegate::kFileSystemDirectory[] = - FILE_PATH_LITERAL("File System"); - // static std::string SandboxFileSystemBackendDelegate::GetTypeString( FileSystemType type) { @@ -196,7 +192,7 @@ sandbox_file_util_(std::make_unique<AsyncFileUtilAdapter>( std::make_unique<ObfuscatedFileUtil>( special_storage_policy, - profile_path.Append(kFileSystemDirectory), + profile_path, env_override, GetKnownTypeStrings(), this, @@ -795,11 +791,11 @@ // static std::unique_ptr<ObfuscatedFileUtil> ObfuscatedFileUtil::CreateForTesting( scoped_refptr<SpecialStoragePolicy> special_storage_policy, - const base::FilePath& file_system_directory, + const base::FilePath& profile_path, leveldb::Env* env_override, bool is_incognito) { return std::make_unique<ObfuscatedFileUtil>( - std::move(special_storage_policy), file_system_directory, env_override, + std::move(special_storage_policy), profile_path, env_override, GetKnownTypeStrings(), /*sandbox_delegate=*/nullptr, is_incognito); }
diff --git a/storage/browser/file_system/sandbox_file_system_backend_delegate.h b/storage/browser/file_system/sandbox_file_system_backend_delegate.h index 5655c3adf..30fef5c 100644 --- a/storage/browser/file_system/sandbox_file_system_backend_delegate.h +++ b/storage/browser/file_system/sandbox_file_system_backend_delegate.h
@@ -73,9 +73,6 @@ using OpenFileSystemCallback = FileSystemBackend::OpenFileSystemCallback; using ResolveURLCallback = FileSystemBackend::ResolveURLCallback; - // The FileSystem directory name. - static const base::FilePath::CharType kFileSystemDirectory[]; - // StorageKey enumerator interface. // An instance of this interface is assumed to be called on the file thread. class StorageKeyEnumerator {
diff --git a/storage/browser/file_system/sandbox_file_system_backend_unittest.cc b/storage/browser/file_system/sandbox_file_system_backend_unittest.cc index 2290b355..fd43d57 100644 --- a/storage/browser/file_system/sandbox_file_system_backend_unittest.cc +++ b/storage/browser/file_system/sandbox_file_system_backend_unittest.cc
@@ -23,6 +23,7 @@ #include "storage/browser/file_system/file_system_backend.h" #include "storage/browser/file_system/file_system_features.h" #include "storage/browser/file_system/file_system_url.h" +#include "storage/browser/file_system/obfuscated_file_util.h" #include "storage/browser/file_system/sandbox_file_system_backend_delegate.h" #include "storage/browser/quota/quota_manager.h" #include "storage/browser/quota/quota_manager_proxy.h" @@ -203,8 +204,7 @@ } base::FilePath file_system_path() const { - return data_dir_.GetPath().Append( - SandboxFileSystemBackendDelegate::kFileSystemDirectory); + return data_dir_.GetPath().Append(ObfuscatedFileUtil::kFileSystemDirectory); } base::FilePath file_system_path_for_buckets() const {
diff --git a/testing/buildbot/filters/android.emulator_11_12.media_unittests.filter b/testing/buildbot/filters/android.emulator_11_12.media_unittests.filter index 33612d2..576eae8 100644 --- a/testing/buildbot/filters/android.emulator_11_12.media_unittests.filter +++ b/testing/buildbot/filters/android.emulator_11_12.media_unittests.filter
@@ -3,3 +3,13 @@ -PaintCanvasVideoRendererWithGLTest.CopyVideoFrameTexturesToGLTexture* -PaintCanvasVideoRendererWithGLTest.CopyVideoFrameYUVDataToGLTexture* -PaintCanvasVideoRendererWithGLTest.Paint* + +# Tests are flaky. +# https://crbug.com/1352098 +-PaintCanvasVideoRendererWithGLTest.CopyVideoFrameToWebGLTextureRGBA +-PaintCanvasVideoRendererWithGLTest.CopyVideoFrameToWebGLTexture_FlipY +-PaintCanvasVideoRendererWithGLTest.CopyVideoFrameToWebGLTextureRGBA_ReadLockFence +-PaintCanvasVideoRendererWithGLTest.CopyVideoFrameToWebGLTextureI420 +-PaintCanvasVideoRendererWithGLTest.CopyVideoFrameToWebGLTexture +-PaintCanvasVideoRendererWithGLTest.CopyVideoFrameToWebGLTextureNV12 +
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 9d34f08a..c1ccd562 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -3739,6 +3739,9 @@ "experiments": [ { "name": "Enabled", + "params": { + "StackCapacity": "16" + }, "enable_features": [ "DifferentWorkQueueCapacities" ] @@ -3857,12 +3860,11 @@ ], "experiments": [ { - "name": "enabled_ntp_native_dialog_20220713", + "name": "enabled_ntp_native_dialog_with_approved_strings_M104_20220809", "params": { "discount-consent-ntp-variation": "4", - "step-one-one-cart-content": "Get discount codes for $1", - "step-one-three-carts-content": "Get discount codes for $1, $2, and more", - "step-one-two-carts-content": "Get discount codes for $1 and $2" + "step-one-static-content": "Let Google help you find discounts for your carts", + "step-one-use-static-content": "true" }, "enable_features": [ "DiscountConsentV2" @@ -5178,6 +5180,9 @@ }, { "name": "EnabledWithTextClassifier", + "params": { + "confidence_score_threshold": "0.0" + }, "enable_features": [ "CalendarExperienceKit", "EnableExpKitCalendarTextClassifier"
diff --git a/third_party/bidimapper/.gitignore b/third_party/bidimapper/.gitignore new file mode 100644 index 0000000..fcfb397 --- /dev/null +++ b/third_party/bidimapper/.gitignore
@@ -0,0 +1,3 @@ +chromium-bidi-main/ +src/ +revision.info
diff --git a/third_party/bidimapper/LICENSE b/third_party/bidimapper/LICENSE new file mode 100644 index 0000000..f49a4e1 --- /dev/null +++ b/third_party/bidimapper/LICENSE
@@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file
diff --git a/third_party/bidimapper/OWNERS b/third_party/bidimapper/OWNERS new file mode 100644 index 0000000..c0113f0 --- /dev/null +++ b/third_party/bidimapper/OWNERS
@@ -0,0 +1,6 @@ +# primary reviewer +nechaev@chromium.org +sadym@chromium.org + +# secondary reviewer +mathias@chromium.org
diff --git a/third_party/bidimapper/README.chromium b/third_party/bidimapper/README.chromium new file mode 100644 index 0000000..70c159bb --- /dev/null +++ b/third_party/bidimapper/README.chromium
@@ -0,0 +1,32 @@ +Name: Implementation of WebDriver BiDi standard +Short Name: chromium-bidi +URL: https://github.com/GoogleChromeLabs/chromium-bidi/archive/4062a90162c96bf96a69a27998719f947d6f7297.zip +Version: 0 +Date: 2022-08-11 +Revision: 4062a90162c96bf96a69a27998719f947d6f7297 +SHA-512: 23f384d3d94b5a5c6b90419127ffda9acbe1f860ce14a80b817586013e8b29a24ea18856848e10f996fe6e02721a9ac84288320b1d1f8496ef6e2237d7e89f9a +License: Apache 2.0 +License File: LICENSE +Security Critical: yes +CPEPrefix: unknown + +Description: +WebDriver BiDi implementation for ChromeDriver. +The software is compiled into mapper.js script that is uploaded by ChromeDriver into the Chrome browser. + +Steps to build: +Assume the git-revision-full-sha1 is the wanted revision. +It can be found in the upstream repo: https://github.com/GoogleChromeLabs/chromium-bidi/commits/main. + +```bash +cd directory-of-this-README.chromium +./pull.sh git-revision-full-sha1 +./build.sh +``` + +The file README.chromium will be updated by build.sh + +Local Modifications: +Local modifications are not allowed. +The upstream is maintained by the Chromium developers. +All the changes must be done there.
diff --git a/third_party/bidimapper/README.chromium.in b/third_party/bidimapper/README.chromium.in new file mode 100644 index 0000000..1779d44 --- /dev/null +++ b/third_party/bidimapper/README.chromium.in
@@ -0,0 +1,32 @@ +Name: Implementation of WebDriver BiDi standard +Short Name: chromium-bidi +URL: https://github.com/GoogleChromeLabs/chromium-bidi/archive/${REVISION}.zip +Version: 0 +Date: ${DATE} +Revision: ${REVISION} +SHA-512: ${TAR-SHA512} +License: Apache 2.0 +License File: LICENSE +Security Critical: yes +CPEPrefix: unknown + +Description: +WebDriver BiDi implementation for ChromeDriver. +The software is compiled into mapper.js script that is uploaded by ChromeDriver into the Chrome browser. + +Steps to build: +Assume the git-revision-full-sha1 is the wanted revision. +It can be found in the upstream repo: https://github.com/GoogleChromeLabs/chromium-bidi/commits/main. + +```bash +cd directory-of-this-README.chromium +./pull.sh git-revision-full-sha1 +./build.sh +``` + +The file README.chromium will be updated by build.sh + +Local Modifications: +Local modifications are not allowed. +The upstream is maintained by the Chromium developers. +All the changes must be done there.
diff --git a/third_party/bidimapper/build.sh b/third_party/bidimapper/build.sh new file mode 100755 index 0000000..90b13f15 --- /dev/null +++ b/third_party/bidimapper/build.sh
@@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +if [ ! -f 'revision.info' ] +then + echo "File not found: revision.info" >&2 + echo "Execute pull.sh first" >&2 + exit 1 +fi + +dt=$(cut --fields=1 --delimiter=',' "revision.info") +revision=$(cut --fields=2 --delimiter=',' "revision.info") +sha512=$(cut --fields=3 --delimiter=',' "revision.info") + +if [ -z "$dt" -o -z "$revision" -o -z "$sha512" ] +then + echo "Incorrect format of revision.info" >&2 + echo "Execute pull.sh first" >&2 + exit 1 +fi + + +npm --prefix src install +npm --prefix src run build-mapper + +cp src/src/.build/bidiMapper/mapper.js . + +cp README.chromium.in README.chromium +sed --in-place --regexp-extended "s/\\$\\{DATE\\}/$dt/gi" README.chromium +sed --in-place --regexp-extended "s/\\$\\{REVISION\\}/$revision/gi" README.chromium +sed --in-place --regexp-extended "s/\\$\\{TAR-SHA512\\}/$sha512/gi" README.chromium
diff --git a/third_party/bidimapper/mapper.js b/third_party/bidimapper/mapper.js new file mode 100644 index 0000000..e3fa067d --- /dev/null +++ b/third_party/bidimapper/mapper.js
@@ -0,0 +1,20 @@ +!function(){"use strict";function e(e){return(...t)=>{if(globalThis.document?.documentElement){console.log(e,...t);const n=function(e){const t=e+"_log",n=document.getElementById(t);if(n)return n;const s=document.createElement("div");return s.id=t,s.innerHTML=`<h3>${e}:</h3>`,document.body.appendChild(s),s}(e),s=document.createElement("pre");s.textContent=t.join(", "),n.appendChild(s)}}}class t{method;params;constructor(e,t){this.method=e,this.params=t}}var n;!function(e){e.assertEqual=e=>e,e.assertIs=function(e){},e.assertNever=function(e){throw new Error},e.arrayToEnum=e=>{const t={};for(const n of e)t[n]=n;return t},e.getValidEnumValues=t=>{const n=e.objectKeys(t).filter((e=>"number"!=typeof t[t[e]])),s={};for(const e of n)s[e]=t[e];return e.objectValues(s)},e.objectValues=t=>e.objectKeys(t).map((function(e){return t[e]})),e.objectKeys="function"==typeof Object.keys?e=>Object.keys(e):e=>{const t=[];for(const n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.push(n);return t},e.find=(e,t)=>{for(const n of e)if(t(n))return n},e.isInteger="function"==typeof Number.isInteger?e=>Number.isInteger(e):e=>"number"==typeof e&&isFinite(e)&&Math.floor(e)===e,e.joinValues=function(e,t=" | "){return e.map((e=>"string"==typeof e?`'${e}'`:e)).join(t)}}(n||(n={}));const s=n.arrayToEnum(["string","nan","number","integer","float","boolean","date","bigint","symbol","function","undefined","null","array","object","unknown","promise","void","never","map","set"]),r=e=>{switch(typeof e){case"undefined":return s.undefined;case"string":return s.string;case"number":return isNaN(e)?s.nan:s.number;case"boolean":return s.boolean;case"function":return s.function;case"bigint":return s.bigint;case"object":return Array.isArray(e)?s.array:null===e?s.null:e.then&&"function"==typeof e.then&&e.catch&&"function"==typeof e.catch?s.promise:"undefined"!=typeof Map&&e instanceof Map?s.map:"undefined"!=typeof Set&&e instanceof Set?s.set:"undefined"!=typeof Date&&e instanceof Date?s.date:s.object;default:return s.unknown}},a=n.arrayToEnum(["invalid_type","invalid_literal","custom","invalid_union","invalid_union_discriminator","invalid_enum_value","unrecognized_keys","invalid_arguments","invalid_return_type","invalid_date","invalid_string","too_small","too_big","invalid_intersection_types","not_multiple_of"]);class i extends Error{constructor(e){super(),this.issues=[],this.addIssue=e=>{this.issues=[...this.issues,e]},this.addIssues=(e=[])=>{this.issues=[...this.issues,...e]};const t=new.target.prototype;Object.setPrototypeOf?Object.setPrototypeOf(this,t):this.__proto__=t,this.name="ZodError",this.issues=e}get errors(){return this.issues}format(e){const t=e||function(e){return e.message},n={_errors:[]},s=e=>{for(const r of e.issues)if("invalid_union"===r.code)r.unionErrors.map(s);else if("invalid_return_type"===r.code)s(r.returnTypeError);else if("invalid_arguments"===r.code)s(r.argumentsError);else if(0===r.path.length)n._errors.push(t(r));else{let e=n,s=0;for(;s<r.path.length;){const n=r.path[s];s===r.path.length-1?(e[n]=e[n]||{_errors:[]},e[n]._errors.push(t(r))):e[n]=e[n]||{_errors:[]},e=e[n],s++}}};return s(this),n}toString(){return this.message}get message(){return JSON.stringify(this.issues,b,2)}get isEmpty(){return 0===this.issues.length}flatten(e=(e=>e.message)){const t={},n=[];for(const s of this.issues)s.path.length>0?(t[s.path[0]]=t[s.path[0]]||[],t[s.path[0]].push(e(s))):n.push(e(s));return{formErrors:n,fieldErrors:t}}get formErrors(){return this.flatten()}}i.create=e=>new i(e);const o=(e,t)=>{let r;switch(e.code){case a.invalid_type:r=e.received===s.undefined?"Required":`Expected ${e.expected}, received ${e.received}`;break;case a.invalid_literal:r=`Invalid literal value, expected ${JSON.stringify(e.expected,b)}`;break;case a.unrecognized_keys:r=`Unrecognized key(s) in object: ${n.joinValues(e.keys,", ")}`;break;case a.invalid_union:r="Invalid input";break;case a.invalid_union_discriminator:r=`Invalid discriminator value. Expected ${n.joinValues(e.options)}`;break;case a.invalid_enum_value:r=`Invalid enum value. Expected ${n.joinValues(e.options)}, received '${e.received}'`;break;case a.invalid_arguments:r="Invalid function arguments";break;case a.invalid_return_type:r="Invalid function return type";break;case a.invalid_date:r="Invalid date";break;case a.invalid_string:"object"==typeof e.validation?"startsWith"in e.validation?r=`Invalid input: must start with "${e.validation.startsWith}"`:"endsWith"in e.validation?r=`Invalid input: must end with "${e.validation.endsWith}"`:n.assertNever(e.validation):r="regex"!==e.validation?`Invalid ${e.validation}`:"Invalid";break;case a.too_small:r="array"===e.type?`Array must contain ${e.inclusive?"at least":"more than"} ${e.minimum} element(s)`:"string"===e.type?`String must contain ${e.inclusive?"at least":"over"} ${e.minimum} character(s)`:"number"===e.type?`Number must be greater than ${e.inclusive?"or equal to ":""}${e.minimum}`:"date"===e.type?`Date must be greater than ${e.inclusive?"or equal to ":""}${new Date(e.minimum)}`:"Invalid input";break;case a.too_big:r="array"===e.type?`Array must contain ${e.inclusive?"at most":"less than"} ${e.maximum} element(s)`:"string"===e.type?`String must contain ${e.inclusive?"at most":"under"} ${e.maximum} character(s)`:"number"===e.type?`Number must be less than ${e.inclusive?"or equal to ":""}${e.maximum}`:"date"===e.type?`Date must be smaller than ${e.inclusive?"or equal to ":""}${new Date(e.maximum)}`:"Invalid input";break;case a.custom:r="Invalid input";break;case a.invalid_intersection_types:r="Intersection results could not be merged";break;case a.not_multiple_of:r=`Number must be a multiple of ${e.multipleOf}`;break;default:r=t.defaultError,n.assertNever(e)}return{message:r}};let c=o;function d(){return c}const l=e=>{const{data:t,path:n,errorMaps:s,issueData:r}=e,a=[...n,...r.path||[]],i={...r,path:a};let o="";const c=s.filter((e=>!!e)).slice().reverse();for(const e of c)o=e(i,{data:t,defaultError:o}).message;return{...r,path:a,message:r.message||o}};function u(e,t){const n=l({issueData:t,data:e.data,path:e.path,errorMaps:[e.common.contextualErrorMap,e.schemaErrorMap,d(),o].filter((e=>!!e))});e.common.issues.push(n)}class h{constructor(){this.value="valid"}dirty(){"valid"===this.value&&(this.value="dirty")}abort(){"aborted"!==this.value&&(this.value="aborted")}static mergeArray(e,t){const n=[];for(const s of t){if("aborted"===s.status)return p;"dirty"===s.status&&e.dirty(),n.push(s.value)}return{status:e.value,value:n}}static async mergeObjectAsync(e,t){const n=[];for(const e of t)n.push({key:await e.key,value:await e.value});return h.mergeObjectSync(e,n)}static mergeObjectSync(e,t){const n={};for(const s of t){const{key:t,value:r}=s;if("aborted"===t.status)return p;if("aborted"===r.status)return p;"dirty"===t.status&&e.dirty(),"dirty"===r.status&&e.dirty(),(void 0!==r.value||s.alwaysSet)&&(n[t.value]=r.value)}return{status:e.value,value:n}}}const p=Object.freeze({status:"aborted"}),m=e=>({status:"valid",value:e}),g=e=>"aborted"===e.status,f=e=>"dirty"===e.status,v=e=>"valid"===e.status,y=e=>void 0!==typeof Promise&&e instanceof Promise,b=(e,t)=>"bigint"==typeof t?t.toString():t;var _;!function(e){e.errToObj=e=>"string"==typeof e?{message:e}:e||{},e.toString=e=>"string"==typeof e?e:null==e?void 0:e.message}(_||(_={}));class w{constructor(e,t,n,s){this.parent=e,this.data=t,this._path=n,this._key=s}get path(){return this._path.concat(this._key)}}const x=(e,t)=>{if(v(t))return{success:!0,data:t.value};if(!e.common.issues.length)throw new Error("Validation failed but no issues detected.");return{success:!1,error:new i(e.common.issues)}};function C(e){if(!e)return{};const{errorMap:t,invalid_type_error:n,required_error:s,description:r}=e;if(t&&(n||s))throw new Error('Can\'t use "invalid" or "required" in conjunction with custom error map.');if(t)return{errorMap:t,description:r};return{errorMap:(e,t)=>"invalid_type"!==e.code?{message:t.defaultError}:void 0===t.data?{message:null!=s?s:t.defaultError}:{message:null!=n?n:t.defaultError},description:r}}class T{constructor(e){this.spa=this.safeParseAsync,this.superRefine=this._refinement,this._def=e,this.parse=this.parse.bind(this),this.safeParse=this.safeParse.bind(this),this.parseAsync=this.parseAsync.bind(this),this.safeParseAsync=this.safeParseAsync.bind(this),this.spa=this.spa.bind(this),this.refine=this.refine.bind(this),this.refinement=this.refinement.bind(this),this.superRefine=this.superRefine.bind(this),this.optional=this.optional.bind(this),this.nullable=this.nullable.bind(this),this.nullish=this.nullish.bind(this),this.array=this.array.bind(this),this.promise=this.promise.bind(this),this.or=this.or.bind(this),this.and=this.and.bind(this),this.transform=this.transform.bind(this),this.default=this.default.bind(this),this.describe=this.describe.bind(this),this.isNullable=this.isNullable.bind(this),this.isOptional=this.isOptional.bind(this)}get description(){return this._def.description}_getType(e){return r(e.data)}_getOrReturnCtx(e,t){return t||{common:e.parent.common,data:e.data,parsedType:r(e.data),schemaErrorMap:this._def.errorMap,path:e.path,parent:e.parent}}_processInputParams(e){return{status:new h,ctx:{common:e.parent.common,data:e.data,parsedType:r(e.data),schemaErrorMap:this._def.errorMap,path:e.path,parent:e.parent}}}_parseSync(e){const t=this._parse(e);if(y(t))throw new Error("Synchronous parse encountered promise.");return t}_parseAsync(e){const t=this._parse(e);return Promise.resolve(t)}parse(e,t){const n=this.safeParse(e,t);if(n.success)return n.data;throw n.error}safeParse(e,t){var n;const s={common:{issues:[],async:null!==(n=null==t?void 0:t.async)&&void 0!==n&&n,contextualErrorMap:null==t?void 0:t.errorMap},path:(null==t?void 0:t.path)||[],schemaErrorMap:this._def.errorMap,parent:null,data:e,parsedType:r(e)},a=this._parseSync({data:e,path:s.path,parent:s});return x(s,a)}async parseAsync(e,t){const n=await this.safeParseAsync(e,t);if(n.success)return n.data;throw n.error}async safeParseAsync(e,t){const n={common:{issues:[],contextualErrorMap:null==t?void 0:t.errorMap,async:!0},path:(null==t?void 0:t.path)||[],schemaErrorMap:this._def.errorMap,parent:null,data:e,parsedType:r(e)},s=this._parse({data:e,path:[],parent:n}),a=await(y(s)?s:Promise.resolve(s));return x(n,a)}refine(e,t){const n=e=>"string"==typeof t||void 0===t?{message:t}:"function"==typeof t?t(e):t;return this._refinement(((t,s)=>{const r=e(t),i=()=>s.addIssue({code:a.custom,...n(t)});return"undefined"!=typeof Promise&&r instanceof Promise?r.then((e=>!!e||(i(),!1))):!!r||(i(),!1)}))}refinement(e,t){return this._refinement(((n,s)=>!!e(n)||(s.addIssue("function"==typeof t?t(n,s):t),!1)))}_refinement(e){return new ie({schema:this,typeName:ge.ZodEffects,effect:{type:"refinement",refinement:e}})}optional(){return oe.create(this)}nullable(){return ce.create(this)}nullish(){return this.optional().nullable()}array(){return B.create(this)}promise(){return ae.create(this)}or(e){return W.create([this,e])}and(e){return q.create(this,e)}transform(e){return new ie({schema:this,typeName:ge.ZodEffects,effect:{type:"transform",transform:e}})}default(e){return new de({innerType:this,defaultValue:"function"==typeof e?e:()=>e,typeName:ge.ZodDefault})}brand(){return new he({typeName:ge.ZodBranded,type:this,...C(void 0)})}describe(e){return new(0,this.constructor)({...this._def,description:e})}isOptional(){return this.safeParse(void 0).success}isNullable(){return this.safeParse(null).success}}const S=/^c[^\s-]{8,}$/i,k=/^([a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}|00000000-0000-0000-0000-000000000000)$/i,O=/^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;class E extends T{constructor(){super(...arguments),this._regex=(e,t,n)=>this.refinement((t=>e.test(t)),{validation:t,code:a.invalid_string,..._.errToObj(n)}),this.nonempty=e=>this.min(1,_.errToObj(e)),this.trim=()=>new E({...this._def,checks:[...this._def.checks,{kind:"trim"}]})}_parse(e){if(this._getType(e)!==s.string){const t=this._getOrReturnCtx(e);return u(t,{code:a.invalid_type,expected:s.string,received:t.parsedType}),p}const t=new h;let r;for(const s of this._def.checks)if("min"===s.kind)e.data.length<s.value&&(r=this._getOrReturnCtx(e,r),u(r,{code:a.too_small,minimum:s.value,type:"string",inclusive:!0,message:s.message}),t.dirty());else if("max"===s.kind)e.data.length>s.value&&(r=this._getOrReturnCtx(e,r),u(r,{code:a.too_big,maximum:s.value,type:"string",inclusive:!0,message:s.message}),t.dirty());else if("email"===s.kind)O.test(e.data)||(r=this._getOrReturnCtx(e,r),u(r,{validation:"email",code:a.invalid_string,message:s.message}),t.dirty());else if("uuid"===s.kind)k.test(e.data)||(r=this._getOrReturnCtx(e,r),u(r,{validation:"uuid",code:a.invalid_string,message:s.message}),t.dirty());else if("cuid"===s.kind)S.test(e.data)||(r=this._getOrReturnCtx(e,r),u(r,{validation:"cuid",code:a.invalid_string,message:s.message}),t.dirty());else if("url"===s.kind)try{new URL(e.data)}catch(n){r=this._getOrReturnCtx(e,r),u(r,{validation:"url",code:a.invalid_string,message:s.message}),t.dirty()}else if("regex"===s.kind){s.regex.lastIndex=0;s.regex.test(e.data)||(r=this._getOrReturnCtx(e,r),u(r,{validation:"regex",code:a.invalid_string,message:s.message}),t.dirty())}else"trim"===s.kind?e.data=e.data.trim():"startsWith"===s.kind?e.data.startsWith(s.value)||(r=this._getOrReturnCtx(e,r),u(r,{code:a.invalid_string,validation:{startsWith:s.value},message:s.message}),t.dirty()):"endsWith"===s.kind?e.data.endsWith(s.value)||(r=this._getOrReturnCtx(e,r),u(r,{code:a.invalid_string,validation:{endsWith:s.value},message:s.message}),t.dirty()):n.assertNever(s);return{status:t.value,value:e.data}}_addCheck(e){return new E({...this._def,checks:[...this._def.checks,e]})}email(e){return this._addCheck({kind:"email",..._.errToObj(e)})}url(e){return this._addCheck({kind:"url",..._.errToObj(e)})}uuid(e){return this._addCheck({kind:"uuid",..._.errToObj(e)})}cuid(e){return this._addCheck({kind:"cuid",..._.errToObj(e)})}regex(e,t){return this._addCheck({kind:"regex",regex:e,..._.errToObj(t)})}startsWith(e,t){return this._addCheck({kind:"startsWith",value:e,..._.errToObj(t)})}endsWith(e,t){return this._addCheck({kind:"endsWith",value:e,..._.errToObj(t)})}min(e,t){return this._addCheck({kind:"min",value:e,..._.errToObj(t)})}max(e,t){return this._addCheck({kind:"max",value:e,..._.errToObj(t)})}length(e,t){return this.min(e,t).max(e,t)}get isEmail(){return!!this._def.checks.find((e=>"email"===e.kind))}get isURL(){return!!this._def.checks.find((e=>"url"===e.kind))}get isUUID(){return!!this._def.checks.find((e=>"uuid"===e.kind))}get isCUID(){return!!this._def.checks.find((e=>"cuid"===e.kind))}get minLength(){let e=null;for(const t of this._def.checks)"min"===t.kind&&(null===e||t.value>e)&&(e=t.value);return e}get maxLength(){let e=null;for(const t of this._def.checks)"max"===t.kind&&(null===e||t.value<e)&&(e=t.value);return e}}function I(e,t){const n=(e.toString().split(".")[1]||"").length,s=(t.toString().split(".")[1]||"").length,r=n>s?n:s;return parseInt(e.toFixed(r).replace(".",""))%parseInt(t.toFixed(r).replace(".",""))/Math.pow(10,r)}E.create=e=>new E({checks:[],typeName:ge.ZodString,...C(e)});class D extends T{constructor(){super(...arguments),this.min=this.gte,this.max=this.lte,this.step=this.multipleOf}_parse(e){if(this._getType(e)!==s.number){const t=this._getOrReturnCtx(e);return u(t,{code:a.invalid_type,expected:s.number,received:t.parsedType}),p}let t;const r=new h;for(const s of this._def.checks)if("int"===s.kind)n.isInteger(e.data)||(t=this._getOrReturnCtx(e,t),u(t,{code:a.invalid_type,expected:"integer",received:"float",message:s.message}),r.dirty());else if("min"===s.kind){(s.inclusive?e.data<s.value:e.data<=s.value)&&(t=this._getOrReturnCtx(e,t),u(t,{code:a.too_small,minimum:s.value,type:"number",inclusive:s.inclusive,message:s.message}),r.dirty())}else if("max"===s.kind){(s.inclusive?e.data>s.value:e.data>=s.value)&&(t=this._getOrReturnCtx(e,t),u(t,{code:a.too_big,maximum:s.value,type:"number",inclusive:s.inclusive,message:s.message}),r.dirty())}else"multipleOf"===s.kind?0!==I(e.data,s.value)&&(t=this._getOrReturnCtx(e,t),u(t,{code:a.not_multiple_of,multipleOf:s.value,message:s.message}),r.dirty()):n.assertNever(s);return{status:r.value,value:e.data}}gte(e,t){return this.setLimit("min",e,!0,_.toString(t))}gt(e,t){return this.setLimit("min",e,!1,_.toString(t))}lte(e,t){return this.setLimit("max",e,!0,_.toString(t))}lt(e,t){return this.setLimit("max",e,!1,_.toString(t))}setLimit(e,t,n,s){return new D({...this._def,checks:[...this._def.checks,{kind:e,value:t,inclusive:n,message:_.toString(s)}]})}_addCheck(e){return new D({...this._def,checks:[...this._def.checks,e]})}int(e){return this._addCheck({kind:"int",message:_.toString(e)})}positive(e){return this._addCheck({kind:"min",value:0,inclusive:!1,message:_.toString(e)})}negative(e){return this._addCheck({kind:"max",value:0,inclusive:!1,message:_.toString(e)})}nonpositive(e){return this._addCheck({kind:"max",value:0,inclusive:!0,message:_.toString(e)})}nonnegative(e){return this._addCheck({kind:"min",value:0,inclusive:!0,message:_.toString(e)})}multipleOf(e,t){return this._addCheck({kind:"multipleOf",value:e,message:_.toString(t)})}get minValue(){let e=null;for(const t of this._def.checks)"min"===t.kind&&(null===e||t.value>e)&&(e=t.value);return e}get maxValue(){let e=null;for(const t of this._def.checks)"max"===t.kind&&(null===e||t.value<e)&&(e=t.value);return e}get isInt(){return!!this._def.checks.find((e=>"int"===e.kind))}}D.create=e=>new D({checks:[],typeName:ge.ZodNumber,...C(e)});class P extends T{_parse(e){if(this._getType(e)!==s.bigint){const t=this._getOrReturnCtx(e);return u(t,{code:a.invalid_type,expected:s.bigint,received:t.parsedType}),p}return m(e.data)}}P.create=e=>new P({typeName:ge.ZodBigInt,...C(e)});class N extends T{_parse(e){if(this._getType(e)!==s.boolean){const t=this._getOrReturnCtx(e);return u(t,{code:a.invalid_type,expected:s.boolean,received:t.parsedType}),p}return m(e.data)}}N.create=e=>new N({typeName:ge.ZodBoolean,...C(e)});class j extends T{_parse(e){if(this._getType(e)!==s.date){const t=this._getOrReturnCtx(e);return u(t,{code:a.invalid_type,expected:s.date,received:t.parsedType}),p}if(isNaN(e.data.getTime())){return u(this._getOrReturnCtx(e),{code:a.invalid_date}),p}const t=new h;let r;for(const s of this._def.checks)"min"===s.kind?e.data.getTime()<s.value&&(r=this._getOrReturnCtx(e,r),u(r,{code:a.too_small,message:s.message,inclusive:!0,minimum:s.value,type:"date"}),t.dirty()):"max"===s.kind?e.data.getTime()>s.value&&(r=this._getOrReturnCtx(e,r),u(r,{code:a.too_big,message:s.message,inclusive:!0,maximum:s.value,type:"date"}),t.dirty()):n.assertNever(s);return{status:t.value,value:new Date(e.data.getTime())}}_addCheck(e){return new j({...this._def,checks:[...this._def.checks,e]})}min(e,t){return this._addCheck({kind:"min",value:e.getTime(),message:_.toString(t)})}max(e,t){return this._addCheck({kind:"max",value:e.getTime(),message:_.toString(t)})}get minDate(){let e=null;for(const t of this._def.checks)"min"===t.kind&&(null===e||t.value>e)&&(e=t.value);return null!=e?new Date(e):null}get maxDate(){let e=null;for(const t of this._def.checks)"max"===t.kind&&(null===e||t.value<e)&&(e=t.value);return null!=e?new Date(e):null}}j.create=e=>new j({checks:[],typeName:ge.ZodDate,...C(e)});class M extends T{_parse(e){if(this._getType(e)!==s.undefined){const t=this._getOrReturnCtx(e);return u(t,{code:a.invalid_type,expected:s.undefined,received:t.parsedType}),p}return m(e.data)}}M.create=e=>new M({typeName:ge.ZodUndefined,...C(e)});class R extends T{_parse(e){if(this._getType(e)!==s.null){const t=this._getOrReturnCtx(e);return u(t,{code:a.invalid_type,expected:s.null,received:t.parsedType}),p}return m(e.data)}}R.create=e=>new R({typeName:ge.ZodNull,...C(e)});class A extends T{constructor(){super(...arguments),this._any=!0}_parse(e){return m(e.data)}}A.create=e=>new A({typeName:ge.ZodAny,...C(e)});class L extends T{constructor(){super(...arguments),this._unknown=!0}_parse(e){return m(e.data)}}L.create=e=>new L({typeName:ge.ZodUnknown,...C(e)});class Z extends T{_parse(e){const t=this._getOrReturnCtx(e);return u(t,{code:a.invalid_type,expected:s.never,received:t.parsedType}),p}}Z.create=e=>new Z({typeName:ge.ZodNever,...C(e)});class F extends T{_parse(e){if(this._getType(e)!==s.undefined){const t=this._getOrReturnCtx(e);return u(t,{code:a.invalid_type,expected:s.void,received:t.parsedType}),p}return m(e.data)}}F.create=e=>new F({typeName:ge.ZodVoid,...C(e)});class B extends T{_parse(e){const{ctx:t,status:n}=this._processInputParams(e),r=this._def;if(t.parsedType!==s.array)return u(t,{code:a.invalid_type,expected:s.array,received:t.parsedType}),p;if(null!==r.minLength&&t.data.length<r.minLength.value&&(u(t,{code:a.too_small,minimum:r.minLength.value,type:"array",inclusive:!0,message:r.minLength.message}),n.dirty()),null!==r.maxLength&&t.data.length>r.maxLength.value&&(u(t,{code:a.too_big,maximum:r.maxLength.value,type:"array",inclusive:!0,message:r.maxLength.message}),n.dirty()),t.common.async)return Promise.all(t.data.map(((e,n)=>r.type._parseAsync(new w(t,e,t.path,n))))).then((e=>h.mergeArray(n,e)));const i=t.data.map(((e,n)=>r.type._parseSync(new w(t,e,t.path,n))));return h.mergeArray(n,i)}get element(){return this._def.type}min(e,t){return new B({...this._def,minLength:{value:e,message:_.toString(t)}})}max(e,t){return new B({...this._def,maxLength:{value:e,message:_.toString(t)}})}length(e,t){return this.min(e,t).max(e,t)}nonempty(e){return this.min(1,e)}}var z;B.create=(e,t)=>new B({type:e,minLength:null,maxLength:null,typeName:ge.ZodArray,...C(t)}),function(e){e.mergeShapes=(e,t)=>({...e,...t})}(z||(z={}));const V=e=>t=>new $({...e,shape:()=>({...e.shape(),...t})});function U(e){if(e instanceof $){const t={};for(const n in e.shape){const s=e.shape[n];t[n]=oe.create(U(s))}return new $({...e._def,shape:()=>t})}return e instanceof B?B.create(U(e.element)):e instanceof oe?oe.create(U(e.unwrap())):e instanceof ce?ce.create(U(e.unwrap())):e instanceof J?J.create(e.items.map((e=>U(e)))):e}class $ extends T{constructor(){super(...arguments),this._cached=null,this.nonstrict=this.passthrough,this.augment=V(this._def),this.extend=V(this._def)}_getCached(){if(null!==this._cached)return this._cached;const e=this._def.shape(),t=n.objectKeys(e);return this._cached={shape:e,keys:t}}_parse(e){if(this._getType(e)!==s.object){const t=this._getOrReturnCtx(e);return u(t,{code:a.invalid_type,expected:s.object,received:t.parsedType}),p}const{status:t,ctx:n}=this._processInputParams(e),{shape:r,keys:i}=this._getCached(),o=[];for(const e in n.data)i.includes(e)||o.push(e);const c=[];for(const e of i){const t=r[e],s=n.data[e];c.push({key:{status:"valid",value:e},value:t._parse(new w(n,s,n.path,e)),alwaysSet:e in n.data})}if(this._def.catchall instanceof Z){const e=this._def.unknownKeys;if("passthrough"===e)for(const e of o)c.push({key:{status:"valid",value:e},value:{status:"valid",value:n.data[e]}});else if("strict"===e)o.length>0&&(u(n,{code:a.unrecognized_keys,keys:o}),t.dirty());else if("strip"!==e)throw new Error("Internal ZodObject error: invalid unknownKeys value.")}else{const e=this._def.catchall;for(const t of o){const s=n.data[t];c.push({key:{status:"valid",value:t},value:e._parse(new w(n,s,n.path,t)),alwaysSet:t in n.data})}}return n.common.async?Promise.resolve().then((async()=>{const e=[];for(const t of c){const n=await t.key;e.push({key:n,value:await t.value,alwaysSet:t.alwaysSet})}return e})).then((e=>h.mergeObjectSync(t,e))):h.mergeObjectSync(t,c)}get shape(){return this._def.shape()}strict(e){return _.errToObj,new $({...this._def,unknownKeys:"strict",...void 0!==e?{errorMap:(t,n)=>{var s,r,a,i;const o=null!==(a=null===(r=(s=this._def).errorMap)||void 0===r?void 0:r.call(s,t,n).message)&&void 0!==a?a:n.defaultError;return"unrecognized_keys"===t.code?{message:null!==(i=_.errToObj(e).message)&&void 0!==i?i:o}:{message:o}}}:{}})}strip(){return new $({...this._def,unknownKeys:"strip"})}passthrough(){return new $({...this._def,unknownKeys:"passthrough"})}setKey(e,t){return this.augment({[e]:t})}merge(e){return new $({unknownKeys:e._def.unknownKeys,catchall:e._def.catchall,shape:()=>z.mergeShapes(this._def.shape(),e._def.shape()),typeName:ge.ZodObject})}catchall(e){return new $({...this._def,catchall:e})}pick(e){const t={};return n.objectKeys(e).map((e=>{this.shape[e]&&(t[e]=this.shape[e])})),new $({...this._def,shape:()=>t})}omit(e){const t={};return n.objectKeys(this.shape).map((s=>{-1===n.objectKeys(e).indexOf(s)&&(t[s]=this.shape[s])})),new $({...this._def,shape:()=>t})}deepPartial(){return U(this)}partial(e){const t={};if(e)return n.objectKeys(this.shape).map((s=>{-1===n.objectKeys(e).indexOf(s)?t[s]=this.shape[s]:t[s]=this.shape[s].optional()})),new $({...this._def,shape:()=>t});for(const e in this.shape){const n=this.shape[e];t[e]=n.optional()}return new $({...this._def,shape:()=>t})}required(){const e={};for(const t in this.shape){let n=this.shape[t];for(;n instanceof oe;)n=n._def.innerType;e[t]=n}return new $({...this._def,shape:()=>e})}keyof(){return ne(n.objectKeys(this.shape))}}$.create=(e,t)=>new $({shape:()=>e,unknownKeys:"strip",catchall:Z.create(),typeName:ge.ZodObject,...C(t)}),$.strictCreate=(e,t)=>new $({shape:()=>e,unknownKeys:"strict",catchall:Z.create(),typeName:ge.ZodObject,...C(t)}),$.lazycreate=(e,t)=>new $({shape:e,unknownKeys:"strip",catchall:Z.create(),typeName:ge.ZodObject,...C(t)});class W extends T{_parse(e){const{ctx:t}=this._processInputParams(e),n=this._def.options;if(t.common.async)return Promise.all(n.map((async e=>{const n={...t,common:{...t.common,issues:[]},parent:null};return{result:await e._parseAsync({data:t.data,path:t.path,parent:n}),ctx:n}}))).then((function(e){for(const t of e)if("valid"===t.result.status)return t.result;for(const n of e)if("dirty"===n.result.status)return t.common.issues.push(...n.ctx.common.issues),n.result;const n=e.map((e=>new i(e.ctx.common.issues)));return u(t,{code:a.invalid_union,unionErrors:n}),p}));{let e;const s=[];for(const r of n){const n={...t,common:{...t.common,issues:[]},parent:null},a=r._parseSync({data:t.data,path:t.path,parent:n});if("valid"===a.status)return a;"dirty"!==a.status||e||(e={result:a,ctx:n}),n.common.issues.length&&s.push(n.common.issues)}if(e)return t.common.issues.push(...e.ctx.common.issues),e.result;const r=s.map((e=>new i(e)));return u(t,{code:a.invalid_union,unionErrors:r}),p}}get options(){return this._def.options}}W.create=(e,t)=>new W({options:e,typeName:ge.ZodUnion,...C(t)});class K extends T{_parse(e){const{ctx:t}=this._processInputParams(e);if(t.parsedType!==s.object)return u(t,{code:a.invalid_type,expected:s.object,received:t.parsedType}),p;const n=this.discriminator,r=t.data[n],i=this.options.get(r);return i?t.common.async?i._parseAsync({data:t.data,path:t.path,parent:t}):i._parseSync({data:t.data,path:t.path,parent:t}):(u(t,{code:a.invalid_union_discriminator,options:this.validDiscriminatorValues,path:[n]}),p)}get discriminator(){return this._def.discriminator}get validDiscriminatorValues(){return Array.from(this.options.keys())}get options(){return this._def.options}static create(e,t,n){const s=new Map;try{t.forEach((t=>{const n=t.shape[e].value;s.set(n,t)}))}catch(e){throw new Error("The discriminator value could not be extracted from all the provided schemas")}if(s.size!==t.length)throw new Error("Some of the discriminator values are not unique");return new K({typeName:ge.ZodDiscriminatedUnion,discriminator:e,options:s,...C(n)})}}function H(e,t){const a=r(e),i=r(t);if(e===t)return{valid:!0,data:e};if(a===s.object&&i===s.object){const s=n.objectKeys(t),r=n.objectKeys(e).filter((e=>-1!==s.indexOf(e))),a={...e,...t};for(const n of r){const s=H(e[n],t[n]);if(!s.valid)return{valid:!1};a[n]=s.data}return{valid:!0,data:a}}if(a===s.array&&i===s.array){if(e.length!==t.length)return{valid:!1};const n=[];for(let s=0;s<e.length;s++){const r=H(e[s],t[s]);if(!r.valid)return{valid:!1};n.push(r.data)}return{valid:!0,data:n}}return a===s.date&&i===s.date&&+e==+t?{valid:!0,data:e}:{valid:!1}}class q extends T{_parse(e){const{status:t,ctx:n}=this._processInputParams(e),s=(e,s)=>{if(g(e)||g(s))return p;const r=H(e.value,s.value);return r.valid?((f(e)||f(s))&&t.dirty(),{status:t.value,value:r.data}):(u(n,{code:a.invalid_intersection_types}),p)};return n.common.async?Promise.all([this._def.left._parseAsync({data:n.data,path:n.path,parent:n}),this._def.right._parseAsync({data:n.data,path:n.path,parent:n})]).then((([e,t])=>s(e,t))):s(this._def.left._parseSync({data:n.data,path:n.path,parent:n}),this._def.right._parseSync({data:n.data,path:n.path,parent:n}))}}q.create=(e,t,n)=>new q({left:e,right:t,typeName:ge.ZodIntersection,...C(n)});class J extends T{_parse(e){const{status:t,ctx:n}=this._processInputParams(e);if(n.parsedType!==s.array)return u(n,{code:a.invalid_type,expected:s.array,received:n.parsedType}),p;if(n.data.length<this._def.items.length)return u(n,{code:a.too_small,minimum:this._def.items.length,inclusive:!0,type:"array"}),p;!this._def.rest&&n.data.length>this._def.items.length&&(u(n,{code:a.too_big,maximum:this._def.items.length,inclusive:!0,type:"array"}),t.dirty());const r=n.data.map(((e,t)=>{const s=this._def.items[t]||this._def.rest;return s?s._parse(new w(n,e,n.path,t)):null})).filter((e=>!!e));return n.common.async?Promise.all(r).then((e=>h.mergeArray(t,e))):h.mergeArray(t,r)}get items(){return this._def.items}rest(e){return new J({...this._def,rest:e})}}J.create=(e,t)=>new J({items:e,typeName:ge.ZodTuple,rest:null,...C(t)});class G extends T{get keySchema(){return this._def.keyType}get valueSchema(){return this._def.valueType}_parse(e){const{status:t,ctx:n}=this._processInputParams(e);if(n.parsedType!==s.object)return u(n,{code:a.invalid_type,expected:s.object,received:n.parsedType}),p;const r=[],i=this._def.keyType,o=this._def.valueType;for(const e in n.data)r.push({key:i._parse(new w(n,e,n.path,e)),value:o._parse(new w(n,n.data[e],n.path,e))});return n.common.async?h.mergeObjectAsync(t,r):h.mergeObjectSync(t,r)}get element(){return this._def.valueType}static create(e,t,n){return new G(t instanceof T?{keyType:e,valueType:t,typeName:ge.ZodRecord,...C(n)}:{keyType:E.create(),valueType:e,typeName:ge.ZodRecord,...C(t)})}}class X extends T{_parse(e){const{status:t,ctx:n}=this._processInputParams(e);if(n.parsedType!==s.map)return u(n,{code:a.invalid_type,expected:s.map,received:n.parsedType}),p;const r=this._def.keyType,i=this._def.valueType,o=[...n.data.entries()].map((([e,t],s)=>({key:r._parse(new w(n,e,n.path,[s,"key"])),value:i._parse(new w(n,t,n.path,[s,"value"]))})));if(n.common.async){const e=new Map;return Promise.resolve().then((async()=>{for(const n of o){const s=await n.key,r=await n.value;if("aborted"===s.status||"aborted"===r.status)return p;"dirty"!==s.status&&"dirty"!==r.status||t.dirty(),e.set(s.value,r.value)}return{status:t.value,value:e}}))}{const e=new Map;for(const n of o){const s=n.key,r=n.value;if("aborted"===s.status||"aborted"===r.status)return p;"dirty"!==s.status&&"dirty"!==r.status||t.dirty(),e.set(s.value,r.value)}return{status:t.value,value:e}}}}X.create=(e,t,n)=>new X({valueType:t,keyType:e,typeName:ge.ZodMap,...C(n)});class Q extends T{_parse(e){const{status:t,ctx:n}=this._processInputParams(e);if(n.parsedType!==s.set)return u(n,{code:a.invalid_type,expected:s.set,received:n.parsedType}),p;const r=this._def;null!==r.minSize&&n.data.size<r.minSize.value&&(u(n,{code:a.too_small,minimum:r.minSize.value,type:"set",inclusive:!0,message:r.minSize.message}),t.dirty()),null!==r.maxSize&&n.data.size>r.maxSize.value&&(u(n,{code:a.too_big,maximum:r.maxSize.value,type:"set",inclusive:!0,message:r.maxSize.message}),t.dirty());const i=this._def.valueType;function o(e){const n=new Set;for(const s of e){if("aborted"===s.status)return p;"dirty"===s.status&&t.dirty(),n.add(s.value)}return{status:t.value,value:n}}const c=[...n.data.values()].map(((e,t)=>i._parse(new w(n,e,n.path,t))));return n.common.async?Promise.all(c).then((e=>o(e))):o(c)}min(e,t){return new Q({...this._def,minSize:{value:e,message:_.toString(t)}})}max(e,t){return new Q({...this._def,maxSize:{value:e,message:_.toString(t)}})}size(e,t){return this.min(e,t).max(e,t)}nonempty(e){return this.min(1,e)}}Q.create=(e,t)=>new Q({valueType:e,minSize:null,maxSize:null,typeName:ge.ZodSet,...C(t)});class Y extends T{constructor(){super(...arguments),this.validate=this.implement}_parse(e){const{ctx:t}=this._processInputParams(e);if(t.parsedType!==s.function)return u(t,{code:a.invalid_type,expected:s.function,received:t.parsedType}),p;function n(e,n){return l({data:e,path:t.path,errorMaps:[t.common.contextualErrorMap,t.schemaErrorMap,d(),o].filter((e=>!!e)),issueData:{code:a.invalid_arguments,argumentsError:n}})}function r(e,n){return l({data:e,path:t.path,errorMaps:[t.common.contextualErrorMap,t.schemaErrorMap,d(),o].filter((e=>!!e)),issueData:{code:a.invalid_return_type,returnTypeError:n}})}const c={errorMap:t.common.contextualErrorMap},h=t.data;return this._def.returns instanceof ae?m((async(...e)=>{const t=new i([]),s=await this._def.args.parseAsync(e,c).catch((s=>{throw t.addIssue(n(e,s)),t})),a=await h(...s);return await this._def.returns._def.type.parseAsync(a,c).catch((e=>{throw t.addIssue(r(a,e)),t}))})):m(((...e)=>{const t=this._def.args.safeParse(e,c);if(!t.success)throw new i([n(e,t.error)]);const s=h(...t.data),a=this._def.returns.safeParse(s,c);if(!a.success)throw new i([r(s,a.error)]);return a.data}))}parameters(){return this._def.args}returnType(){return this._def.returns}args(...e){return new Y({...this._def,args:J.create(e).rest(L.create())})}returns(e){return new Y({...this._def,returns:e})}implement(e){return this.parse(e)}strictImplement(e){return this.parse(e)}}Y.create=(e,t,n)=>new Y({args:e?e.rest(L.create()):J.create([]).rest(L.create()),returns:t||L.create(),typeName:ge.ZodFunction,...C(n)});class ee extends T{get schema(){return this._def.getter()}_parse(e){const{ctx:t}=this._processInputParams(e);return this._def.getter()._parse({data:t.data,path:t.path,parent:t})}}ee.create=(e,t)=>new ee({getter:e,typeName:ge.ZodLazy,...C(t)});class te extends T{_parse(e){if(e.data!==this._def.value){return u(this._getOrReturnCtx(e),{code:a.invalid_literal,expected:this._def.value}),p}return{status:"valid",value:e.data}}get value(){return this._def.value}}function ne(e,t){return new se({values:e,typeName:ge.ZodEnum,...C(t)})}te.create=(e,t)=>new te({value:e,typeName:ge.ZodLiteral,...C(t)});class se extends T{_parse(e){if("string"!=typeof e.data){const t=this._getOrReturnCtx(e),s=this._def.values;return u(t,{expected:n.joinValues(s),received:t.parsedType,code:a.invalid_type}),p}if(-1===this._def.values.indexOf(e.data)){const t=this._getOrReturnCtx(e),n=this._def.values;return u(t,{received:t.data,code:a.invalid_enum_value,options:n}),p}return m(e.data)}get options(){return this._def.values}get enum(){const e={};for(const t of this._def.values)e[t]=t;return e}get Values(){const e={};for(const t of this._def.values)e[t]=t;return e}get Enum(){const e={};for(const t of this._def.values)e[t]=t;return e}}se.create=ne;class re extends T{_parse(e){const t=n.getValidEnumValues(this._def.values),r=this._getOrReturnCtx(e);if(r.parsedType!==s.string&&r.parsedType!==s.number){const e=n.objectValues(t);return u(r,{expected:n.joinValues(e),received:r.parsedType,code:a.invalid_type}),p}if(-1===t.indexOf(e.data)){const e=n.objectValues(t);return u(r,{received:r.data,code:a.invalid_enum_value,options:e}),p}return m(e.data)}get enum(){return this._def.values}}re.create=(e,t)=>new re({values:e,typeName:ge.ZodNativeEnum,...C(t)});class ae extends T{_parse(e){const{ctx:t}=this._processInputParams(e);if(t.parsedType!==s.promise&&!1===t.common.async)return u(t,{code:a.invalid_type,expected:s.promise,received:t.parsedType}),p;const n=t.parsedType===s.promise?t.data:Promise.resolve(t.data);return m(n.then((e=>this._def.type.parseAsync(e,{path:t.path,errorMap:t.common.contextualErrorMap}))))}}ae.create=(e,t)=>new ae({type:e,typeName:ge.ZodPromise,...C(t)});class ie extends T{innerType(){return this._def.schema}_parse(e){const{status:t,ctx:s}=this._processInputParams(e),r=this._def.effect||null;if("preprocess"===r.type){const e=r.transform(s.data);return s.common.async?Promise.resolve(e).then((e=>this._def.schema._parseAsync({data:e,path:s.path,parent:s}))):this._def.schema._parseSync({data:e,path:s.path,parent:s})}const a={addIssue:e=>{u(s,e),e.fatal?t.abort():t.dirty()},get path(){return s.path}};if(a.addIssue=a.addIssue.bind(a),"refinement"===r.type){const e=e=>{const t=r.refinement(e,a);if(s.common.async)return Promise.resolve(t);if(t instanceof Promise)throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead.");return e};if(!1===s.common.async){const n=this._def.schema._parseSync({data:s.data,path:s.path,parent:s});return"aborted"===n.status?p:("dirty"===n.status&&t.dirty(),e(n.value),{status:t.value,value:n.value})}return this._def.schema._parseAsync({data:s.data,path:s.path,parent:s}).then((n=>"aborted"===n.status?p:("dirty"===n.status&&t.dirty(),e(n.value).then((()=>({status:t.value,value:n.value}))))))}if("transform"===r.type){if(!1===s.common.async){const e=this._def.schema._parseSync({data:s.data,path:s.path,parent:s});if(!v(e))return e;const n=r.transform(e.value,a);if(n instanceof Promise)throw new Error("Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.");return{status:t.value,value:n}}return this._def.schema._parseAsync({data:s.data,path:s.path,parent:s}).then((e=>v(e)?Promise.resolve(r.transform(e.value,a)).then((e=>({status:t.value,value:e}))):e))}n.assertNever(r)}}ie.create=(e,t,n)=>new ie({schema:e,typeName:ge.ZodEffects,effect:t,...C(n)}),ie.createWithPreprocess=(e,t,n)=>new ie({schema:t,effect:{type:"preprocess",transform:e},typeName:ge.ZodEffects,...C(n)});class oe extends T{_parse(e){return this._getType(e)===s.undefined?m(void 0):this._def.innerType._parse(e)}unwrap(){return this._def.innerType}}oe.create=(e,t)=>new oe({innerType:e,typeName:ge.ZodOptional,...C(t)});class ce extends T{_parse(e){return this._getType(e)===s.null?m(null):this._def.innerType._parse(e)}unwrap(){return this._def.innerType}}ce.create=(e,t)=>new ce({innerType:e,typeName:ge.ZodNullable,...C(t)});class de extends T{_parse(e){const{ctx:t}=this._processInputParams(e);let n=t.data;return t.parsedType===s.undefined&&(n=this._def.defaultValue()),this._def.innerType._parse({data:n,path:t.path,parent:t})}removeDefault(){return this._def.innerType}}de.create=(e,t)=>new oe({innerType:e,typeName:ge.ZodOptional,...C(t)});class le extends T{_parse(e){if(this._getType(e)!==s.nan){const t=this._getOrReturnCtx(e);return u(t,{code:a.invalid_type,expected:s.nan,received:t.parsedType}),p}return{status:"valid",value:e.data}}}le.create=e=>new le({typeName:ge.ZodNaN,...C(e)});const ue=Symbol("zod_brand");class he extends T{_parse(e){const{ctx:t}=this._processInputParams(e),n=t.data;return this._def.type._parse({data:n,path:t.path,parent:t})}unwrap(){return this._def.type}}const pe=(e,t={},n)=>e?A.create().superRefine(((s,r)=>{if(!e(s)){const e="function"==typeof t?t(s):t,a="string"==typeof e?{message:e}:e;r.addIssue({code:"custom",...a,fatal:n})}})):A.create(),me={object:$.lazycreate};var ge;!function(e){e.ZodString="ZodString",e.ZodNumber="ZodNumber",e.ZodNaN="ZodNaN",e.ZodBigInt="ZodBigInt",e.ZodBoolean="ZodBoolean",e.ZodDate="ZodDate",e.ZodUndefined="ZodUndefined",e.ZodNull="ZodNull",e.ZodAny="ZodAny",e.ZodUnknown="ZodUnknown",e.ZodNever="ZodNever",e.ZodVoid="ZodVoid",e.ZodArray="ZodArray",e.ZodObject="ZodObject",e.ZodUnion="ZodUnion",e.ZodDiscriminatedUnion="ZodDiscriminatedUnion",e.ZodIntersection="ZodIntersection",e.ZodTuple="ZodTuple",e.ZodRecord="ZodRecord",e.ZodMap="ZodMap",e.ZodSet="ZodSet",e.ZodFunction="ZodFunction",e.ZodLazy="ZodLazy",e.ZodLiteral="ZodLiteral",e.ZodEnum="ZodEnum",e.ZodEffects="ZodEffects",e.ZodNativeEnum="ZodNativeEnum",e.ZodOptional="ZodOptional",e.ZodNullable="ZodNullable",e.ZodDefault="ZodDefault",e.ZodPromise="ZodPromise",e.ZodBranded="ZodBranded"}(ge||(ge={}));const fe=E.create,ve=D.create,ye=le.create,be=P.create,_e=N.create,we=j.create,xe=M.create,Ce=R.create,Te=A.create,Se=L.create,ke=Z.create,Oe=F.create,Ee=B.create,Ie=$.create,De=$.strictCreate,Pe=W.create,Ne=K.create,je=q.create,Me=J.create,Re=G.create,Ae=X.create,Le=Q.create,Ze=Y.create,Fe=ee.create,Be=te.create,ze=se.create,Ve=re.create,Ue=ae.create,$e=ie.create,We=oe.create,Ke=ce.create,He=ie.createWithPreprocess;var qe=Object.freeze({__proto__:null,getParsedType:r,ZodParsedType:s,makeIssue:l,EMPTY_PATH:[],addIssueToContext:u,ParseStatus:h,INVALID:p,DIRTY:e=>({status:"dirty",value:e}),OK:m,isAborted:g,isDirty:f,isValid:v,isAsync:y,jsonStringifyReplacer:b,ZodType:T,ZodString:E,ZodNumber:D,ZodBigInt:P,ZodBoolean:N,ZodDate:j,ZodUndefined:M,ZodNull:R,ZodAny:A,ZodUnknown:L,ZodNever:Z,ZodVoid:F,ZodArray:B,get objectUtil(){return z},ZodObject:$,ZodUnion:W,ZodDiscriminatedUnion:K,ZodIntersection:q,ZodTuple:J,ZodRecord:G,ZodMap:X,ZodSet:Q,ZodFunction:Y,ZodLazy:ee,ZodLiteral:te,ZodEnum:se,ZodNativeEnum:re,ZodPromise:ae,ZodEffects:ie,ZodTransformer:ie,ZodOptional:oe,ZodNullable:ce,ZodDefault:de,ZodNaN:le,BRAND:ue,ZodBranded:he,custom:pe,Schema:T,ZodSchema:T,late:me,get ZodFirstPartyTypeKind(){return ge},any:Te,array:Ee,bigint:be,boolean:_e,date:we,discriminatedUnion:Ne,effect:$e,enum:ze,function:Ze,instanceof:(e,t={message:`Input not instance of ${e.name}`})=>pe((t=>t instanceof e),t,!0),intersection:je,lazy:Fe,literal:Be,map:Ae,nan:ye,nativeEnum:Ve,never:ke,null:Ce,nullable:Ke,number:ve,object:Ie,oboolean:()=>_e().optional(),onumber:()=>ve().optional(),optional:We,ostring:()=>fe().optional(),preprocess:He,promise:Ue,record:Re,set:Le,strictObject:De,string:fe,transformer:$e,tuple:Me,undefined:xe,union:Pe,unknown:Se,void:Oe,ZodIssueCode:a,quotelessJson:e=>JSON.stringify(e,null,2).replace(/"([^"]+)":/g,"$1:"),ZodError:i,defaultErrorMap:o,setErrorMap:function(e){c=e},getErrorMap:d});class Je{constructor(e,t,n){this.error=e,this.message=t,this.stacktrace=n}error;message;stacktrace;toErrorResponse(e){return{id:e,error:this.error,message:this.message,stacktrace:this.stacktrace}}}class Ge extends Je{constructor(e,t){super("unknown error",e,t)}}class Xe extends Je{constructor(e,t){super("unknown command",e,t)}}class Qe extends Je{constructor(e,t){super("invalid argument",e,t)}}class Ye extends Je{constructor(e){super("no such frame",e)}}const et=e("command parser");function tt(e,t){const n=t.safeParse(e);if(n.success)return n.data;et(`Command ${JSON.stringify(e)} parse failed: ${JSON.stringify(n)}.`);const s=n.error.errors.map((e=>`${e.message} in ${e.path.map((e=>JSON.stringify(e))).join("/")}.`)).join(" ");throw new Qe(s)}var nt,st,rt,at,it,ot;!function(e){e.RemoteReferenceSchema=qe.object({handle:qe.string().min(1)});const t=qe.object({type:qe.literal("undefined")}),n=qe.object({type:qe.literal("null")}),s=qe.object({type:qe.literal("string"),value:qe.string()}),r=qe.enum(["NaN","-0","Infinity","+Infinity","-Infinity"]),a=qe.object({type:qe.literal("number"),value:qe.union([r,qe.number()])}),i=qe.object({type:qe.literal("boolean"),value:qe.boolean()}),o=qe.object({type:qe.literal("bigint"),value:qe.string()}),c=qe.union([t,n,s,a,i,o]);e.LocalValueSchema=qe.lazy((()=>qe.union([c,l,u,p,m,g,f])));const d=qe.array(e.LocalValueSchema),l=qe.lazy((()=>qe.object({type:qe.literal("array"),value:d}))),u=qe.object({type:qe.literal("date"),value:qe.string().min(1)}),h=qe.lazy((()=>qe.tuple([qe.union([qe.string(),e.LocalValueSchema]),e.LocalValueSchema]))),p=qe.object({type:qe.literal("map"),value:qe.array(h)}),m=qe.object({type:qe.literal("object"),value:qe.array(h)}),g=qe.lazy((()=>qe.object({type:qe.literal("regexp"),value:qe.object({pattern:qe.string(),flags:qe.string().optional()})}))),f=qe.lazy((()=>qe.object({type:qe.literal("set"),value:d})));e.BrowsingContextSchema=qe.string()}(nt||(nt={})),function(e){const t=qe.object({context:nt.BrowsingContextSchema,sandbox:qe.string().optional()}),n=qe.object({realm:qe.string().min(1)}),s=qe.union([t,n]),r=qe.enum(["root","none"]),a=qe.object({expression:qe.string(),awaitPromise:qe.boolean(),target:s,resultOwnership:r.optional()});e.parseEvaluateParams=function(e){return tt(e,a)};const i=qe.union([nt.RemoteReferenceSchema,nt.LocalValueSchema]),o=qe.object({functionDeclaration:qe.string(),target:s,arguments:qe.array(i).optional(),this:i.optional(),awaitPromise:qe.boolean(),resultOwnership:r.optional()});e.parseCallFunctionParams=function(e){return tt(e,o)}}(st||(st={})),function(e){const n=qe.object({maxDepth:qe.number().int().nonnegative().max(9007199254740991).optional(),root:nt.BrowsingContextSchema.optional()});e.parseGetTreeParams=function(e){return tt(e,n)};const s=qe.enum(["none","interactive","complete"]),r=qe.object({context:nt.BrowsingContextSchema,url:qe.string().url(),wait:s.optional()});e.parseNavigateParams=function(e){return tt(e,r)};const a=qe.object({type:qe.enum(["tab","window"])});e.parseCreateParams=function(e){return tt(e,a)};const i=qe.object({context:nt.BrowsingContextSchema});e.parseCloseParams=function(e){return tt(e,i)};class o extends t{static method="browsingContext.load";constructor(e){super(o.method,e)}}e.LoadEvent=o;class c extends t{static method="browsingContext.domContentLoaded";constructor(e){super(c.method,e)}}e.DomContentLoadedEvent=c;class d extends t{static method="browsingContext.contextCreated";constructor(e){super(d.method,e)}}e.ContextCreatedEvent=d;class l extends t{static method="browsingContext.contextDestroyed";constructor(e){super(l.method,e)}}e.ContextDestroyedEvent=l,function(e){const t=qe.object({context:nt.BrowsingContextSchema,selector:qe.string()});e.parseFindElementParams=function(e){return tt(e,t)}}(e.PROTO||(e.PROTO={})),e.EventNames=[o.method,c.method,d.method,l.method]}(rt||(rt={})),function(e){class n extends t{static method="log.entryAdded";constructor(e){super(n.method,e)}}e.LogEntryAddedEvent=n,e.EventNames=[n.method]}(at||(at={})),function(e){let n;!function(e){const n=qe.object({cdpMethod:qe.string(),cdpParams:qe.object({}).passthrough(),cdpSession:qe.string().optional()});e.parseSendCommandParams=function(e){return tt(e,n)};const s=qe.object({context:nt.BrowsingContextSchema});e.parseGetSessionParams=function(e){return tt(e,s)};class r extends t{static method="PROTO.cdp.eventReceived";constructor(e){super(r.method,e)}}e.EventReceivedEvent=r}(n=e.PROTO||(e.PROTO={})),e.EventNames=[n.EventReceivedEvent.method]}(it||(it={})),function(e){const t=qe.enum([...rt.EventNames,...at.EventNames,...it.EventNames]),n=qe.object({events:qe.array(t),contexts:qe.array(nt.BrowsingContextSchema).optional()});e.parseSubscribeParams=function(e){return tt(e,n)}}(ot||(ot={}));class ct{#e=()=>{};#t=()=>{};#n;#s=!1;get isFinished(){return this.#s}constructor(){this.#n=new Promise(((e,t)=>{this.#e=e,this.#t=t}))}then(e,t){return this.#n.then(e,t)}catch(e){return this.#n.catch(e)}resolve(e){this.#s=!0,this.#e(e)}reject(e){this.#s=!0,this.#t(e)}finally(e){return this.#n.finally(e)}[Symbol.toStringTag]="Promise"}const dt=["%s","%d","%i","%f","%o","%O","%c"];function lt(e){return dt.some((t=>e.includes(t)))}function ut(e){if(!["number","string","object"].includes(e.type))throw Error("Invalid value type: "+e.toString());if("number"===e.type&&(e.value,1))return e.value.toString();if("string"===e.type&&(e.value,1))return'"'+e.value.toString()+'"';if("object"===e.type&&(e.value,1))return'{"'+e.value[0][0]+'": '+ut(e.value[0][1])+"}";throw Error("Invalid value type: "+e.toString())}function ht(e,t){return 0==e.length?"":"string"===e[0].type&<(e[0].value.toString())&&t?function(e){let t="";const n=e[0].value.toString(),s=e.slice(1,void 0),r=n.split(new RegExp(dt.map((e=>"("+e+")")).join("|"),"g"));for(const n of r)if(void 0!==n&&""!=n)if(lt(n)){const r=s.shift();if(void 0===r)throw new Error('Less value is provided: "'+ht(e,!1)+'"');t+="%s"===n?r.value.toString():"%d"===n||"%i"===n?parseInt(r.value.toString(),10):"%f"===n?parseFloat(r.value.toString()):ut(r)}else t+=n;if(s.length>0)throw new Error('More value is provided: "'+ht(e,!1)+'"');return t}(e):e.map((e=>e.hasOwnProperty("value")?e.value.toString():e.type)).join(" ")}class pt{#r;#a;#i;#o;constructor(e,t,n,s){this.#o=s,this.#i=n,this.#a=t,this.#r=e}static create(e,t,n,s){const r=new pt(e,t,n,s);return r.#c(),r}#c(){this.#d()}#d(){this.#l()}#l(){this.#a.Runtime.on("consoleAPICalled",(async e=>{const t=await Promise.all(e.args.map((async t=>this.#o?.serializeCdpObject(t,"none",e.executionContextId))));await this.#i.sendMessage(new at.LogEntryAddedEvent({level:pt.#u(e.type),text:ht(t,!0),timestamp:e.timestamp,stackTrace:pt.#h(e.stackTrace),type:"console",method:e.type,realm:this.#r,args:t}))})),this.#a.Runtime.on("exceptionThrown",(async e=>{let t=e.exceptionDetails.text;if(e.exceptionDetails.exception)if(void 0===e.exceptionDetails.executionContextId)t=JSON.stringify(e.exceptionDetails.exception);else{const n=await this.#o.stringifyObject(e.exceptionDetails.exception,e.exceptionDetails.executionContextId);n&&(t=n)}await this.#i.sendMessage(new at.LogEntryAddedEvent({level:"error",text:t,timestamp:e.timestamp,stackTrace:pt.#h(e.exceptionDetails.stackTrace),type:"javascript",realm:this.#r}))}))}static#u(e){return e in["error","assert"]?"error":e in["debug","trace"]?"debug":e in["warning","warn"]?"warning":"info"}static#h(e){const t=e?.callFrames.map((e=>({columnNumber:e.columnNumber,functionName:e.functionName,lineNumber:e.lineNumber,url:e.url})));return t?{callFrames:t}:void 0}}class mt{#a;#p=0;#m=1;constructor(e){this.#a=e}static create(e){return new mt(e)}async serializeCdpObject(e,t,n){const s=await this.#a.Runtime.callFunctionOn({functionDeclaration:String((e=>e)),awaitPromise:!1,arguments:[e],generateWebDriverValue:!0,objectId:await this.#g(n)});return await this.#f(s,t)}async stringifyObject(e,t){return(await this.#a.Runtime.callFunctionOn({functionDeclaration:String((function(e){return String(e)})),awaitPromise:!1,arguments:[e],returnByValue:!0,objectId:await this.#g(t)})).result.value}async#g(e){return(await this.#a.Runtime.evaluate({expression:"(()=>{return {}})()",contextId:e})).result.objectId}async callFunction(e,t,n,s,r,a){const i=`(...args)=>{ return _callFunction((\n${t}\n), args);\n function _callFunction(f, args) {\n const deserializedThis = args.shift();\n const deserializedArgs = args;\n return f.apply(deserializedThis, deserializedArgs);\n }}`,o=[await this.#v(n,e)];o.push(...await Promise.all(s.map((async t=>await this.#v(t,e)))));const c=await this.#a.Runtime.callFunctionOn({functionDeclaration:i,awaitPromise:r,arguments:o,generateWebDriverValue:!0,objectId:await this.#g(e)});return c.exceptionDetails?{exceptionDetails:await this.#y(c.exceptionDetails,this.#m,a,e),realm:"TODO: ADD"}:{result:await this.#f(c,a),realm:"TODO: ADD"}}async#y(e,t,n,s){const r=e.stackTrace?.callFrames.map((e=>({url:e.url,functionName:e.functionName,lineNumber:e.lineNumber-t,columnNumber:e.columnNumber}))),a=await this.serializeCdpObject(e.exception,n,s),i=await this.stringifyObject(e.exception,s);return{exception:a,columnNumber:e.columnNumber,lineNumber:e.lineNumber-t,stackTrace:{callFrames:r||[]},text:i||e.text}}async#f(e,t){const n=e.result.webDriverValue;if(!e.result.objectId)return n;const s=e.result.objectId,r=n;return"root"===t?r.handle=s:await this.#a.Runtime.releaseObject({objectId:s}),r}async scriptEvaluate(e,t,n,s){let r=await this.#a.Runtime.evaluate({contextId:e,expression:t,awaitPromise:n,generateWebDriverValue:!0});return r.exceptionDetails?{result:{exceptionDetails:await this.#y(r.exceptionDetails,this.#p,s,e),realm:"TODO: ADD"}}:{result:{result:await this.#f(r,s),realm:"TODO: ADD"}}}async#v(e,t){if("handle"in e)return{objectId:e.handle};switch(e.type){case"undefined":return{unserializableValue:"undefined"};case"null":return{unserializableValue:"null"};case"string":return{value:e.value};case"number":return"NaN"===e.value?{unserializableValue:"NaN"}:"-0"===e.value?{unserializableValue:"-0"}:"+Infinity"===e.value?{unserializableValue:"+Infinity"}:"Infinity"===e.value?{unserializableValue:"Infinity"}:"-Infinity"===e.value?{unserializableValue:"-Infinity"}:{value:e.value};case"boolean":return{value:!!e.value};case"bigint":return{unserializableValue:`BigInt(${JSON.stringify(e.value)})`};case"date":return{unserializableValue:`new Date(Date.parse(${JSON.stringify(e.value)}))`};case"regexp":return{unserializableValue:`new RegExp(${JSON.stringify(e.value.pattern)}, ${JSON.stringify(e.value.flags)})`};case"map":{const n=await this.#b(e.value,t);return{objectId:(await this.#a.Runtime.callFunctionOn({functionDeclaration:String((function(...e){const t=new Map;for(let n=0;n<e.length;n+=2)t.set(e[n],e[n+1]);return t})),awaitPromise:!1,arguments:n,returnByValue:!1,objectId:await this.#g(t)})).result.objectId}}case"object":{const n=await this.#b(e.value,t);return{objectId:(await this.#a.Runtime.callFunctionOn({functionDeclaration:String((function(...e){const t={};for(let n=0;n<e.length;n+=2){t[e[n]]=e[n+1]}return t})),awaitPromise:!1,arguments:n,returnByValue:!1,objectId:await this.#g(t)})).result.objectId}}case"array":{const n=await this.#_(e.value,t);return{objectId:(await this.#a.Runtime.callFunctionOn({functionDeclaration:String((function(...e){return e})),awaitPromise:!1,arguments:n,returnByValue:!1,objectId:await this.#g(t)})).result.objectId}}case"set":{const n=await this.#_(e.value,t);return{objectId:(await this.#a.Runtime.callFunctionOn({functionDeclaration:String((function(...e){return new Set(e)})),awaitPromise:!1,arguments:n,returnByValue:!1,objectId:await this.#g(t)})).result.objectId}}default:throw new Error(`Value ${JSON.stringify(e)} is not deserializable.`)}}async#b(e,t){const n=[];for(let s of e){const e=s[0],r=s[1];let a,i;a="string"==typeof e?{value:e}:await this.#v(e,t),i=await this.#v(r,t),n.push(a),n.push(i)}return n}async#_(e,t){const n=[];for(let s of e)n.push(await this.#v(s,t));return n}}var gt=rt.LoadEvent;class ft{#w={documentInitialized:new ct,targetUnblocked:new ct,Page:{navigatedWithinDocument:new ct,lifecycleEvent:{DOMContentLoaded:new ct,load:new ct}}};#r;#x;#C="about:blank";#T=null;#S;#a;#i;#k;#O=[];#E;#I=null;constructor(e,t,n,s,r,a){this.#r=e,this.#x=t,this.#a=n,this.#k=a,this.#S=r,this.#i=s,this.#E=mt.create(n),this.#D()}static createFrameContext(e,t,n,s,r,a){const i=new ft(e,t,n,s,r,a);return i.#w.targetUnblocked.resolve(),i}static createTargetContext(e,t,n,s,r,a){const i=new ft(e,t,n,s,r,a);return i.#P(),i}static convertFrameToTargetContext(e,t,n){return e.#N(t,n),e.#P(),e}#N(e,t){this.#w.targetUnblocked.isFinished||this.#w.targetUnblocked.reject("OOPiF"),this.#w.targetUnblocked=new ct,this.#a=e,this.#S=t,this.#E=mt.create(e),this.#D()}async#P(){pt.create(this.#r,this.#a,this.#i,this.#E),await this.#a.Runtime.enable(),await this.#a.Page.enable(),await this.#a.Page.setLifecycleEventsEnabled({enabled:!0}),await this.#a.Target.setAutoAttach({autoAttach:!0,waitForDebuggerOnStart:!0,flatten:!0}),await this.#a.Runtime.runIfWaitingForDebugger(),this.#w.targetUnblocked.resolve()}get contextId(){return this.#r}get parentId(){return this.#x}get cdpSessionId(){return this.#S}get children(){return this.#O}get url(){return this.#C}addChild(e){this.#O.push(e)}serializeToBidiValue(e,t){return{context:this.#r,url:this.url,children:e>0?this.children.map((t=>t.serializeToBidiValue(e-1,!1))):null,...t?{parent:this.#x}:{}}}#D(){this.#a.Target.on("targetInfoChanged",(e=>{this.contextId===e.targetInfo.targetId&&(this.#C=e.targetInfo.url)})),this.#a.Page.on("frameNavigated",(e=>{this.contextId===e.frame.id&&(this.#C=e.frame.url+(e.frame.urlFragment??""))})),this.#a.Page.on("navigatedWithinDocument",(e=>{this.contextId===e.frameId&&(this.#C=e.url,this.#w.Page.navigatedWithinDocument.resolve(e))})),this.#a.Page.on("lifecycleEvent",(async e=>{if(this.contextId===e.frameId&&("init"===e.name&&(this.#j(e.loaderId),this.#w.documentInitialized.resolve()),e.loaderId===this.#T))switch(e.name){case"DOMContentLoaded":this.#w.Page.lifecycleEvent.DOMContentLoaded.resolve(e),await this.#k.sendEvent(new rt.DomContentLoadedEvent({context:this.contextId,navigation:this.#T}),this.contextId);break;case"load":this.#w.Page.lifecycleEvent.load.resolve(e),await this.#k.sendEvent(new gt({context:this.contextId,navigation:this.#T}),this.contextId)}})),this.#a.Runtime.on("executionContextCreated",(e=>{e.context.auxData.frameId===this.contextId&&e.context.auxData.isDefault&&(this.#I=e.context.id)}))}#j(e){this.#T!==e&&(this.#w.documentInitialized.isFinished||this.#w.documentInitialized.reject("Document changed"),this.#w.documentInitialized=new ct,this.#w.Page.navigatedWithinDocument.isFinished||this.#w.Page.navigatedWithinDocument.reject("Document changed"),this.#w.Page.navigatedWithinDocument=new ct,this.#w.Page.lifecycleEvent.DOMContentLoaded.isFinished||this.#w.Page.lifecycleEvent.DOMContentLoaded.reject("Document changed"),this.#w.Page.lifecycleEvent.DOMContentLoaded=new ct,this.#w.Page.lifecycleEvent.load.isFinished||this.#w.Page.lifecycleEvent.load.reject("Document changed"),this.#w.Page.lifecycleEvent.load=new ct,this.#T=e)}async navigate(e,t){await this.#w.targetUnblocked;const n=await this.#a.Page.navigate({url:e,frameId:this.contextId});if(n.errorText)throw new Ge(n.errorText);switch(void 0!==n.loaderId&&n.loaderId!==this.#T&&this.#j(n.loaderId),t){case"none":break;case"interactive":void 0===n.loaderId?await this.#w.Page.navigatedWithinDocument:await this.#w.Page.lifecycleEvent.DOMContentLoaded;break;case"complete":void 0===n.loaderId?await this.#w.Page.navigatedWithinDocument:await this.#w.Page.lifecycleEvent.load;break;default:throw new Error(`Not implemented wait '${t}'`)}return{result:{navigation:n.loaderId||null,url:e}}}async callFunction(e,t,n,s,r){if(await this.#w.targetUnblocked,null===this.#I)throw Error("No execution context");return{result:await this.#E.callFunction(this.#I,e,t,n,s,r)}}async scriptEvaluate(e,t,n){if(await this.#w.targetUnblocked,null===this.#I)throw Error("No execution context");return this.#E.scriptEvaluate(this.#I,e,t,n)}async findElement(e){await this.#w.targetUnblocked;const t=String((e=>document.querySelector(e))),n=[{type:"string",value:e}];return await this.callFunction(t,{type:"undefined"},n,!0,"root")}}const vt=e("context");class yt{static#M=new Map;static#R(){return Array.from(yt.#M.values()).filter((e=>null===e.parentId))}static#A(e){yt.#M.delete(e)}static#L(e){yt.#M.set(e.contextId,e),null!==e.parentId&&yt.#Z(e.parentId).addChild(e)}static#F(e){return yt.#M.has(e)}static#Z(e){if(!yt.#F(e))throw new Ye(`Context ${e} not found`);return yt.#M.get(e)}sessions=new Set;#B;#z;#i;#k;constructor(e,t,n,s){this.#B=e,this.#z=t,this.#i=n,this.#k=s,this.#V(this.#B.browserClient())}#V(e){this.#U(e)}#U(e){e.Target.on("attachedToTarget",(async t=>{await this.#$(t,e)})),e.Target.on("detachedFromTarget",(async e=>{await this.#W(e)}))}#K(e){if(this.sessions.has(e))return;this.sessions.add(e);const t=this.#B.getCdpClient(e);this.#U(t),t.on("event",(async(t,n)=>{await this.#k.sendEvent({method:"PROTO.cdp.eventReceived",params:{cdpMethod:t,cdpParams:n,session:e}},null)})),t.Page.on("frameAttached",(async n=>{const s=ft.createFrameContext(n.frameId,n.parentFrameId,t,this.#i,e,this.#k);yt.#L(s),await this.#k.sendEvent(new rt.ContextCreatedEvent(s.serializeToBidiValue(0,!0)),s.contextId)}))}async#$(e,t){vt("AttachedToTarget event received: "+JSON.stringify(e));const{sessionId:n,targetInfo:s}=e;let r=this.#B.getCdpClient(n);if(!this.#H(s))return await r.Runtime.runIfWaitingForDebugger(),void await t.Target.detachFromTarget(e);if(this.#K(n),yt.#F(s.targetId))ft.convertFrameToTargetContext(yt.#Z(s.targetId),r,n);else{const e=ft.createTargetContext(s.targetId,null,r,this.#i,n,this.#k);yt.#L(e),await this.#k.sendEvent(new rt.ContextCreatedEvent(e.serializeToBidiValue(0,!0)),e.contextId)}}async#W(e){vt("detachedFromTarget event received: "+JSON.stringify(e));const t=e.targetId;if(!yt.#F(t))return;const n=yt.#Z(t);yt.#A(t),await this.#k.sendEvent(new rt.ContextDestroyedEvent(n.serializeToBidiValue(0,!0)),t)}async process_browsingContext_getTree(e){return{result:{contexts:(void 0===e.root?yt.#R():[yt.#Z(e.root)]).map((t=>t.serializeToBidiValue(e.maxDepth??Number.MAX_VALUE,!0)))}}}async process_browsingContext_create(e){const t=this.#B.browserClient();return{result:{context:(await t.Target.createTarget({url:"about:blank",newWindow:"window"===e.type})).targetId,parent:null,url:"about:blank",children:[]}}}async process_browsingContext_navigate(e){const t=yt.#Z(e.context);return await t.navigate(e.url,void 0!==e.wait?e.wait:"none")}async process_script_evaluate(e){const t=yt.#Z(e.target.context);return await t.scriptEvaluate(e.expression,e.awaitPromise,e.resultOwnership??"none")}async process_script_callFunction(e){const t=yt.#Z(e.target.context);return await t.callFunction(e.functionDeclaration,e.this||{type:"undefined"},e.arguments||[],e.awaitPromise,e.resultOwnership??"none")}async process_PROTO_browsingContext_findElement(e){const t=yt.#Z(e.context);return await t.findElement(e.selector)}async process_browsingContext_close(e){const t=this.#B.browserClient();if(null!==yt.#Z(e.context).parentId)throw new Qe("Not a top-level browsing context cannot be closed.");const n=new Promise((async n=>{const s=r=>{r.targetId===e.context&&(t.Target.removeListener("detachedFromTarget",s),n())};t.Target.on("detachedFromTarget",s)}));return await this.#B.browserClient().Target.closeTarget({targetId:e.context}),await n,{result:{}}}#H(e){return e.targetId!==this.#z&&["page","iframe"].includes(e.type)}async process_PROTO_cdp_sendCommand(e){return{result:await this.#B.sendCommand(e.cdpMethod,e.cdpParams,e.cdpSession??null)}}async process_PROTO_cdp_getSession(e){const t=e.context,n=yt.#Z(t).cdpSessionId;return void 0===n?{result:{session:null}}:{result:{session:n}}}}class bt{#q;#i;#k;static run(e,t,n,s){new bt(e,t,n,s).#J()}constructor(e,t,n,s){this.#k=n,this.#i=t,this.#q=new yt(e,s,t,n)}#J(){this.#i.on("message",(e=>this.#G(e)))}async#X(){return{result:{ready:!0,message:"ready"}}}async#Q(e){return await this.#k.subscribe(e.events,e.contexts??null),{result:{}}}async#Y(e){return await this.#k.unsubscribe(e.events,e.contexts??null),{result:{}}}async#ee(e){switch(e.method){case"session.status":return await this.#X();case"session.subscribe":return await this.#Q(ot.parseSubscribeParams(e.params));case"session.unsubscribe":return await this.#Y(ot.parseSubscribeParams(e.params));case"browsingContext.create":return await this.#q.process_browsingContext_create(rt.parseCreateParams(e.params));case"browsingContext.close":return await this.#q.process_browsingContext_close(rt.parseCloseParams(e.params));case"browsingContext.getTree":return await this.#q.process_browsingContext_getTree(rt.parseGetTreeParams(e.params));case"browsingContext.navigate":return await this.#q.process_browsingContext_navigate(rt.parseNavigateParams(e.params));case"script.callFunction":return await this.#q.process_script_callFunction(st.parseCallFunctionParams(e.params));case"script.evaluate":return await this.#q.process_script_evaluate(st.parseEvaluateParams(e.params));case"PROTO.browsingContext.findElement":return await this.#q.process_PROTO_browsingContext_findElement(rt.PROTO.parseFindElementParams(e.params));case"PROTO.cdp.sendCommand":return await this.#q.process_PROTO_cdp_sendCommand(it.PROTO.parseSendCommandParams(e.params));case"PROTO.cdp.getSession":return await this.#q.process_PROTO_cdp_getSession(it.PROTO.parseGetSessionParams(e.params));default:throw new Xe(`Unknown command '${e.method}'.`)}}#G=async e=>{try{const t=await this.#ee(e),n={id:e.id,...t};await this.#i.sendMessage(n)}catch(t){if(t instanceof Je){const n=t;await this.#i.sendMessage(n.toErrorResponse(e.id))}else{const n=t;console.error(n),await this.#i.sendMessage(new Ge(n.message).toErrorResponse(e.id))}}}}function _t(){}function wt(){wt.init.call(this)}function xt(e){return void 0===e._maxListeners?wt.defaultMaxListeners:e._maxListeners}function Ct(e,t,n){if(t)e.call(n);else for(var s=e.length,r=Pt(e,s),a=0;a<s;++a)r[a].call(n)}function Tt(e,t,n,s){if(t)e.call(n,s);else for(var r=e.length,a=Pt(e,r),i=0;i<r;++i)a[i].call(n,s)}function St(e,t,n,s,r){if(t)e.call(n,s,r);else for(var a=e.length,i=Pt(e,a),o=0;o<a;++o)i[o].call(n,s,r)}function kt(e,t,n,s,r,a){if(t)e.call(n,s,r,a);else for(var i=e.length,o=Pt(e,i),c=0;c<i;++c)o[c].call(n,s,r,a)}function Ot(e,t,n,s){if(t)e.apply(n,s);else for(var r=e.length,a=Pt(e,r),i=0;i<r;++i)a[i].apply(n,s)}function Et(e,t,n,s){var r,a,i,o;if("function"!=typeof n)throw new TypeError('"listener" argument must be a function');if((a=e._events)?(a.newListener&&(e.emit("newListener",t,n.listener?n.listener:n),a=e._events),i=a[t]):(a=e._events=new _t,e._eventsCount=0),i){if("function"==typeof i?i=a[t]=s?[n,i]:[i,n]:s?i.unshift(n):i.push(n),!i.warned&&(r=xt(e))&&r>0&&i.length>r){i.warned=!0;var c=new Error("Possible EventEmitter memory leak detected. "+i.length+" "+t+" listeners added. Use emitter.setMaxListeners() to increase limit");c.name="MaxListenersExceededWarning",c.emitter=e,c.type=t,c.count=i.length,o=c,"function"==typeof console.warn?console.warn(o):console.log(o)}}else i=a[t]=n,++e._eventsCount;return e}function It(e,t,n){var s=!1;function r(){e.removeListener(t,r),s||(s=!0,n.apply(e,arguments))}return r.listener=n,r}function Dt(e){var t=this._events;if(t){var n=t[e];if("function"==typeof n)return 1;if(n)return n.length}return 0}function Pt(e,t){for(var n=new Array(t);t--;)n[t]=e[t];return n}_t.prototype=Object.create(null),wt.EventEmitter=wt,wt.usingDomains=!1,wt.prototype.domain=void 0,wt.prototype._events=void 0,wt.prototype._maxListeners=void 0,wt.defaultMaxListeners=10,wt.init=function(){this.domain=null,wt.usingDomains&&undefined.active,this._events&&this._events!==Object.getPrototypeOf(this)._events||(this._events=new _t,this._eventsCount=0),this._maxListeners=this._maxListeners||void 0},wt.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||isNaN(e))throw new TypeError('"n" argument must be a positive number');return this._maxListeners=e,this},wt.prototype.getMaxListeners=function(){return xt(this)},wt.prototype.emit=function(e){var t,n,s,r,a,i,o,c="error"===e;if(i=this._events)c=c&&null==i.error;else if(!c)return!1;if(o=this.domain,c){if(t=arguments[1],!o){if(t instanceof Error)throw t;var d=new Error('Uncaught, unspecified "error" event. ('+t+")");throw d.context=t,d}return t||(t=new Error('Uncaught, unspecified "error" event')),t.domainEmitter=this,t.domain=o,t.domainThrown=!1,o.emit("error",t),!1}if(!(n=i[e]))return!1;var l="function"==typeof n;switch(s=arguments.length){case 1:Ct(n,l,this);break;case 2:Tt(n,l,this,arguments[1]);break;case 3:St(n,l,this,arguments[1],arguments[2]);break;case 4:kt(n,l,this,arguments[1],arguments[2],arguments[3]);break;default:for(r=new Array(s-1),a=1;a<s;a++)r[a-1]=arguments[a];Ot(n,l,this,r)}return!0},wt.prototype.addListener=function(e,t){return Et(this,e,t,!1)},wt.prototype.on=wt.prototype.addListener,wt.prototype.prependListener=function(e,t){return Et(this,e,t,!0)},wt.prototype.once=function(e,t){if("function"!=typeof t)throw new TypeError('"listener" argument must be a function');return this.on(e,It(this,e,t)),this},wt.prototype.prependOnceListener=function(e,t){if("function"!=typeof t)throw new TypeError('"listener" argument must be a function');return this.prependListener(e,It(this,e,t)),this},wt.prototype.removeListener=function(e,t){var n,s,r,a,i;if("function"!=typeof t)throw new TypeError('"listener" argument must be a function');if(!(s=this._events))return this;if(!(n=s[e]))return this;if(n===t||n.listener&&n.listener===t)0==--this._eventsCount?this._events=new _t:(delete s[e],s.removeListener&&this.emit("removeListener",e,n.listener||t));else if("function"!=typeof n){for(r=-1,a=n.length;a-- >0;)if(n[a]===t||n[a].listener&&n[a].listener===t){i=n[a].listener,r=a;break}if(r<0)return this;if(1===n.length){if(n[0]=void 0,0==--this._eventsCount)return this._events=new _t,this;delete s[e]}else!function(e,t){for(var n=t,s=n+1,r=e.length;s<r;n+=1,s+=1)e[n]=e[s];e.pop()}(n,r);s.removeListener&&this.emit("removeListener",e,i||t)}return this},wt.prototype.removeAllListeners=function(e){var t,n;if(!(n=this._events))return this;if(!n.removeListener)return 0===arguments.length?(this._events=new _t,this._eventsCount=0):n[e]&&(0==--this._eventsCount?this._events=new _t:delete n[e]),this;if(0===arguments.length){for(var s,r=Object.keys(n),a=0;a<r.length;++a)"removeListener"!==(s=r[a])&&this.removeAllListeners(s);return this.removeAllListeners("removeListener"),this._events=new _t,this._eventsCount=0,this}if("function"==typeof(t=n[e]))this.removeListener(e,t);else if(t)do{this.removeListener(e,t[t.length-1])}while(t[0]);return this},wt.prototype.listeners=function(e){var t,n=this._events;return n&&(t=n[e])?"function"==typeof t?[t.listener||t]:function(e){for(var t=new Array(e.length),n=0;n<t.length;++n)t[n]=e[n].listener||e[n];return t}(t):[]},wt.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):Dt.call(e,t)},wt.prototype.listenerCount=Dt,wt.prototype.eventNames=function(){return this._eventsCount>0?Reflect.ownKeys(this._events):[]};const Nt=[{domain:"Accessibility",commands:["disable","enable","getPartialAXTree","getFullAXTree","getRootAXNode","getAXNodeAndAncestors","getChildAXNodes","queryAXTree"]},{domain:"Animation",commands:["disable","enable","getCurrentTime","getPlaybackRate","releaseAnimations","resolveAnimation","seekAnimations","setPaused","setPlaybackRate","setTiming"]},{domain:"Audits",commands:["getEncodedResponse","disable","enable","checkContrast"]},{domain:"BackgroundService",commands:["startObserving","stopObserving","setRecording","clearEvents"]},{domain:"Browser",commands:["setPermission","grantPermissions","resetPermissions","setDownloadBehavior","cancelDownload","close","crash","crashGpuProcess","getVersion","getBrowserCommandLine","getHistograms","getHistogram","getWindowBounds","getWindowForTarget","setWindowBounds","setDockTile","executeBrowserCommand"]},{domain:"CSS",commands:["addRule","collectClassNames","createStyleSheet","disable","enable","forcePseudoState","getBackgroundColors","getComputedStyleForNode","getInlineStylesForNode","getMatchedStylesForNode","getMediaQueries","getPlatformFontsForNode","getStyleSheetText","getLayersForNode","trackComputedStyleUpdates","takeComputedStyleUpdates","setEffectivePropertyValueForNode","setKeyframeKey","setMediaText","setContainerQueryText","setSupportsText","setRuleSelector","setStyleSheetText","setStyleTexts","startRuleUsageTracking","stopRuleUsageTracking","takeCoverageDelta","setLocalFontsEnabled"]},{domain:"CacheStorage",commands:["deleteCache","deleteEntry","requestCacheNames","requestCachedResponse","requestEntries"]},{domain:"Cast",commands:["enable","disable","setSinkToUse","startDesktopMirroring","startTabMirroring","stopCasting"]},{domain:"DOM",commands:["collectClassNamesFromSubtree","copyTo","describeNode","scrollIntoViewIfNeeded","disable","discardSearchResults","enable","focus","getAttributes","getBoxModel","getContentQuads","getDocument","getFlattenedDocument","getNodesForSubtreeByStyle","getNodeForLocation","getOuterHTML","getRelayoutBoundary","getSearchResults","hideHighlight","highlightNode","highlightRect","markUndoableState","moveTo","performSearch","pushNodeByPathToFrontend","pushNodesByBackendIdsToFrontend","querySelector","querySelectorAll","redo","removeAttribute","removeNode","requestChildNodes","requestNode","resolveNode","setAttributeValue","setAttributesAsText","setFileInputFiles","setNodeStackTracesEnabled","getNodeStackTraces","getFileInfo","setInspectedNode","setNodeName","setNodeValue","setOuterHTML","undo","getFrameOwner","getContainerForNode","getQueryingDescendantsForContainer"]},{domain:"DOMDebugger",commands:["getEventListeners","removeDOMBreakpoint","removeEventListenerBreakpoint","removeInstrumentationBreakpoint","removeXHRBreakpoint","setBreakOnCSPViolation","setDOMBreakpoint","setEventListenerBreakpoint","setInstrumentationBreakpoint","setXHRBreakpoint"]},{domain:"EventBreakpoints",commands:["setInstrumentationBreakpoint","removeInstrumentationBreakpoint"]},{domain:"DOMSnapshot",commands:["disable","enable","getSnapshot","captureSnapshot"]},{domain:"DOMStorage",commands:["clear","disable","enable","getDOMStorageItems","removeDOMStorageItem","setDOMStorageItem"]},{domain:"Database",commands:["disable","enable","executeSQL","getDatabaseTableNames"]},{domain:"DeviceOrientation",commands:["clearDeviceOrientationOverride","setDeviceOrientationOverride"]},{domain:"Emulation",commands:["canEmulate","clearDeviceMetricsOverride","clearGeolocationOverride","resetPageScaleFactor","setFocusEmulationEnabled","setAutoDarkModeOverride","setCPUThrottlingRate","setDefaultBackgroundColorOverride","setDeviceMetricsOverride","setScrollbarsHidden","setDocumentCookieDisabled","setEmitTouchEventsForMouse","setEmulatedMedia","setEmulatedVisionDeficiency","setGeolocationOverride","setIdleOverride","clearIdleOverride","setNavigatorOverrides","setPageScaleFactor","setScriptExecutionDisabled","setTouchEmulationEnabled","setVirtualTimePolicy","setLocaleOverride","setTimezoneOverride","setVisibleSize","setDisabledImageTypes","setHardwareConcurrencyOverride","setUserAgentOverride","setAutomationOverride"]},{domain:"HeadlessExperimental",commands:["beginFrame","disable","enable"]},{domain:"IO",commands:["close","read","resolveBlob"]},{domain:"IndexedDB",commands:["clearObjectStore","deleteDatabase","deleteObjectStoreEntries","disable","enable","requestData","getMetadata","requestDatabase","requestDatabaseNames"]},{domain:"Input",commands:["dispatchDragEvent","dispatchKeyEvent","insertText","imeSetComposition","dispatchMouseEvent","dispatchTouchEvent","emulateTouchFromMouseEvent","setIgnoreInputEvents","setInterceptDrags","synthesizePinchGesture","synthesizeScrollGesture","synthesizeTapGesture"]},{domain:"Inspector",commands:["disable","enable"]},{domain:"LayerTree",commands:["compositingReasons","disable","enable","loadSnapshot","makeSnapshot","profileSnapshot","releaseSnapshot","replaySnapshot","snapshotCommandLog"]},{domain:"Log",commands:["clear","disable","enable","startViolationsReport","stopViolationsReport"]},{domain:"Memory",commands:["getDOMCounters","prepareForLeakDetection","forciblyPurgeJavaScriptMemory","setPressureNotificationsSuppressed","simulatePressureNotification","startSampling","stopSampling","getAllTimeSamplingProfile","getBrowserSamplingProfile","getSamplingProfile"]},{domain:"Network",commands:["setAcceptedEncodings","clearAcceptedEncodingsOverride","canClearBrowserCache","canClearBrowserCookies","canEmulateNetworkConditions","clearBrowserCache","clearBrowserCookies","continueInterceptedRequest","deleteCookies","disable","emulateNetworkConditions","enable","getAllCookies","getCertificate","getCookies","getResponseBody","getRequestPostData","getResponseBodyForInterception","takeResponseBodyForInterceptionAsStream","replayXHR","searchInResponseBody","setBlockedURLs","setBypassServiceWorker","setCacheDisabled","setCookie","setCookies","setExtraHTTPHeaders","setAttachDebugStack","setRequestInterception","setUserAgentOverride","getSecurityIsolationStatus","enableReportingApi","loadNetworkResource"]},{domain:"Overlay",commands:["disable","enable","getHighlightObjectForTest","getGridHighlightObjectsForTest","getSourceOrderHighlightObjectForTest","hideHighlight","highlightFrame","highlightNode","highlightQuad","highlightRect","highlightSourceOrder","setInspectMode","setShowAdHighlights","setPausedInDebuggerMessage","setShowDebugBorders","setShowFPSCounter","setShowGridOverlays","setShowFlexOverlays","setShowScrollSnapOverlays","setShowContainerQueryOverlays","setShowPaintRects","setShowLayoutShiftRegions","setShowScrollBottleneckRects","setShowHitTestBorders","setShowWebVitals","setShowViewportSizeOnResize","setShowHinge","setShowIsolatedElements"]},{domain:"Page",commands:["addScriptToEvaluateOnLoad","addScriptToEvaluateOnNewDocument","bringToFront","captureScreenshot","captureSnapshot","clearDeviceMetricsOverride","clearDeviceOrientationOverride","clearGeolocationOverride","createIsolatedWorld","deleteCookie","disable","enable","getAppManifest","getInstallabilityErrors","getManifestIcons","getAppId","getCookies","getFrameTree","getLayoutMetrics","getNavigationHistory","resetNavigationHistory","getResourceContent","getResourceTree","handleJavaScriptDialog","navigate","navigateToHistoryEntry","printToPDF","reload","removeScriptToEvaluateOnLoad","removeScriptToEvaluateOnNewDocument","screencastFrameAck","searchInResource","setAdBlockingEnabled","setBypassCSP","getPermissionsPolicyState","getOriginTrials","setDeviceMetricsOverride","setDeviceOrientationOverride","setFontFamilies","setFontSizes","setDocumentContent","setDownloadBehavior","setGeolocationOverride","setLifecycleEventsEnabled","setTouchEmulationEnabled","startScreencast","stopLoading","crash","close","setWebLifecycleState","stopScreencast","produceCompilationCache","addCompilationCache","clearCompilationCache","setSPCTransactionMode","generateTestReport","waitForDebugger","setInterceptFileChooserDialog"]},{domain:"Performance",commands:["disable","enable","setTimeDomain","getMetrics"]},{domain:"PerformanceTimeline",commands:["enable"]},{domain:"Security",commands:["disable","enable","setIgnoreCertificateErrors","handleCertificateError","setOverrideCertificateErrors"]},{domain:"ServiceWorker",commands:["deliverPushMessage","disable","dispatchSyncEvent","dispatchPeriodicSyncEvent","enable","inspectWorker","setForceUpdateOnPageLoad","skipWaiting","startWorker","stopAllWorkers","stopWorker","unregister","updateRegistration"]},{domain:"Storage",commands:["getStorageKeyForFrame","clearDataForOrigin","getCookies","setCookies","clearCookies","getUsageAndQuota","overrideQuotaForOrigin","trackCacheStorageForOrigin","trackIndexedDBForOrigin","untrackCacheStorageForOrigin","untrackIndexedDBForOrigin","getTrustTokens","clearTrustTokens","getInterestGroupDetails","setInterestGroupTracking"]},{domain:"SystemInfo",commands:["getInfo","getProcessInfo"]},{domain:"Target",commands:["activateTarget","attachToTarget","attachToBrowserTarget","closeTarget","exposeDevToolsProtocol","createBrowserContext","getBrowserContexts","createTarget","detachFromTarget","disposeBrowserContext","getTargetInfo","getTargets","sendMessageToTarget","setAutoAttach","autoAttachRelated","setDiscoverTargets","setRemoteLocations"]},{domain:"Tethering",commands:["bind","unbind"]},{domain:"Tracing",commands:["end","getCategories","recordClockSyncMarker","requestMemoryDump","start"]},{domain:"Fetch",commands:["disable","enable","failRequest","fulfillRequest","continueRequest","continueWithAuth","continueResponse","getResponseBody","takeResponseBodyAsStream"]},{domain:"WebAudio",commands:["enable","disable","getRealtimeData"]},{domain:"WebAuthn",commands:["enable","disable","addVirtualAuthenticator","removeVirtualAuthenticator","addCredential","getCredential","getCredentials","removeCredential","clearCredentials","setUserVerified","setAutomaticPresenceSimulation"]},{domain:"Media",commands:["enable","disable"]},{domain:"Console",commands:["clearMessages","disable","enable"]},{domain:"Debugger",commands:["continueToLocation","disable","enable","evaluateOnCallFrame","getPossibleBreakpoints","getScriptSource","getWasmBytecode","getStackTrace","pause","pauseOnAsyncCall","removeBreakpoint","restartFrame","resume","searchInContent","setAsyncCallStackDepth","setBlackboxPatterns","setBlackboxedRanges","setBreakpoint","setInstrumentationBreakpoint","setBreakpointByUrl","setBreakpointOnFunctionCall","setBreakpointsActive","setPauseOnExceptions","setReturnValue","setScriptSource","setSkipAllPauses","setVariableValue","stepInto","stepOut","stepOver"]},{domain:"HeapProfiler",commands:["addInspectedHeapObject","collectGarbage","disable","enable","getHeapObjectId","getObjectByHeapObjectId","getSamplingProfile","startSampling","startTrackingHeapObjects","stopSampling","stopTrackingHeapObjects","takeHeapSnapshot"]},{domain:"Profiler",commands:["disable","enable","getBestEffortCoverage","setSamplingInterval","start","startPreciseCoverage","startTypeProfile","stop","stopPreciseCoverage","stopTypeProfile","takePreciseCoverage","takeTypeProfile"]},{domain:"Runtime",commands:["awaitPromise","callFunctionOn","compileScript","disable","discardConsoleEntries","enable","evaluate","getIsolateId","getHeapUsage","getProperties","globalLexicalScopeNames","queryObjects","releaseObject","releaseObjectGroup","runIfWaitingForDebugger","runScript","setAsyncCallStackDepth","setCustomObjectFormatterEnabled","setMaxCallStackSizeToCapture","terminateExecution","addBinding","removeBinding","getExceptionDetails"]},{domain:"Schema",commands:["getDomains"]}],jt=new Map;class Mt extends wt{_client;constructor(e){super(),this._client=e}}for(let e of Nt){class t extends Mt{constructor(e){super(e)}}for(let n of e.commands)Object.defineProperty(t.prototype,n,{value:async function(t){return await this._client.sendCommand(`${e.domain}.${n}`,t)}});jt.set(e.domain,t)}class Rt extends wt{_cdpConnection;_sessionId;_domains;constructor(e,t){super(),this._cdpConnection=e,this._sessionId=t,this._domains=new Map;for(const[e,t]of jt.entries())this._domains.set(e,new t(this)),Object.defineProperty(this,e,{get(){return this._domains.get(e)}})}sendCommand(e,t){return this._cdpConnection.sendCommand(e,t,this._sessionId)}_onCdpEvent(e,t){this.emit("event",e,t);const[n,s]=e.split("."),r=this._domains.get(n);r&&r.emit(s,t)}}function At(e,t){return new Rt(e,t)}const Lt=e("cdp");class Zt{_transport;_browserCdpClient;_sessionCdpClients=new Map;_commandCallbacks=new Map;_nextId;constructor(e){this._transport=e,this._nextId=0,this._transport.setOnMessage(this._onMessage),this._browserCdpClient=At(this,null)}close(){this._transport.close();for(const[e,{reject:t}]of this._commandCallbacks)t(new Error("Disconnected"));this._commandCallbacks.clear(),this._sessionCdpClients.clear()}browserClient(){return this._browserCdpClient}getCdpClient(e){const t=this._sessionCdpClients.get(e);if(!t)throw new Error("Unknown CDP session ID");return t}sendCommand(e,t,n){return new Promise(((s,r)=>{const a=this._nextId++;this._commandCallbacks.set(a,{resolve:s,reject:r});let i={id:a,method:e,params:t};n&&(i.sessionId=n);const o=JSON.stringify(i);this._transport.sendMessage(o),Lt("sent > "+o)}))}_onMessage=async e=>{Lt("received < "+e);const t=JSON.parse(e);if("Target.attachedToTarget"===t.method){const{sessionId:e}=t.params;this._sessionCdpClients.set(e,At(this,e))}else if("Target.detachedFromTarget"===t.method){const{sessionId:e}=t.params;this._sessionCdpClients.get(e)&&this._sessionCdpClients.delete(e)}if(void 0!==t.id){const e=this._commandCallbacks.get(t.id);e&&(t.result?e.resolve(t.result):t.error&&e.reject(t.error))}else if(t.method){const e=t.sessionId?this._sessionCdpClients.get(t.sessionId):this._browserCdpClient;e&&e._onCdpEvent(t.method,t.params||{})}}}const Ft=e("bidi");class Bt extends wt{_transport;constructor(e){super(),this._transport=e,this._transport.setOnMessage(this._onBidiMessage)}async sendMessage(e){const t=JSON.stringify(e);Ft("sent > "+t),this._transport.sendMessage(t)}close(){this._transport.close()}_onBidiMessage=async e=>{let t;Ft("received < "+e);try{t=this._parseBidiMessage(e)}catch(t){return void this._respondWithError(e,"invalid argument",t.message)}this.emit("message",t)};_respondWithError(e,t,n){const s=this._getErrorResponse(e,t,n);this.sendMessage(s)}_getJsonType(e){return null===e?"null":Array.isArray(e)?"array":typeof e}_getErrorResponse(e,t,n){let s;try{const t=JSON.parse(e);"object"===this._getJsonType(t)&&"id"in t&&(s=t.id)}catch{}return{id:s,error:t,message:n}}_parseBidiMessage(e){let t;try{t=JSON.parse(e)}catch{throw new Error("Cannot parse data as JSON")}const n=this._getJsonType(t);if("object"!==n)throw new Error(`Expected JSON object but got ${n}`);const{id:s,method:r,params:a}=t,i=this._getJsonType(s);if("number"!==i||!Number.isInteger(s)||s<0)throw new Error(`Expected unsigned integer but got ${i}`);const o=this._getJsonType(r);if("string"!==o)throw new Error(`Expected string method but got ${o}`);const c=this._getJsonType(a);if("object"!==c)throw new Error(`Expected object params but got ${c}`);return{id:s,method:r,params:a}}}class zt{#te=new Map;#i;constructor(e){this.#i=e}async sendEvent(e,t){(this.#ne(e.method,null)||null!==t&&this.#ne(e.method,t))&&await this.#i.sendMessage(e)}#ne(e,t){return this.#te.has(t)&&this.#te.get(t).has(e)}async subscribe(e,t){for(let n of e)if(null===t)this.#se(n,null);else for(let e of t)this.#se(n,e)}#se(e,t){this.#te.has(t)||this.#te.set(t,new Set),this.#te.get(t).add(e)}async unsubscribe(e,t){for(let n of e)if(null===t)this.#re(n,null);else for(let e of t)this.#re(n,e)}#re(e,t){const n=this.#te.get(t);n?.delete(e),0===n?.size&&this.#te.delete(t)}} +/** + * Copyright 2021 Google LLC. + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @license + */const Vt=e("system"),Ut=async function(){return await new Promise((e=>{window.setSelfTargetId=function(t){Vt("current target ID: "+t),e(t)}}))}();(async()=>{window.document.documentElement.innerHTML="<h1>Bidi mapper runs here!</h1><h2>Don't close.</h2>",window.document.title="BiDi Mapper";const e=function(){class e{_onMessage=null;constructor(){window.cdp.onmessage=e=>{this._onMessage&&this._onMessage.call(null,e)}}setOnMessage(e){this._onMessage=e}async sendMessage(e){window.cdp.send(e)}close(){this._onMessage=null,window.cdp.onmessage=null}}return new Zt(new e)}(),t=e.browserClient(),n=function(){class e{_onMessage=null;constructor(){window.onBidiMessage=e=>{this._onMessage&&this._onMessage.call(null,e)}}setOnMessage(e){this._onMessage=e}async sendMessage(e){window.sendBidiResponse(e)}close(){this._onMessage=null,window.onBidiMessage=null}}return new Bt(new e)}(),s=new zt(n),r=await Ut;bt.run(e,n,s,r),await async function(e){await e.Target.setDiscoverTargets({discover:!0}),await e.Target.setAutoAttach({autoAttach:!0,waitForDebuggerOnStart:!0,flatten:!0})}(t),Vt("launched"),n.sendMessage({launched:!0})})()}(); +//# sourceMappingURL=mapper.js.map
diff --git a/third_party/bidimapper/pull.sh b/third_party/bidimapper/pull.sh new file mode 100755 index 0000000..4a92605 --- /dev/null +++ b/third_party/bidimapper/pull.sh
@@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Exit if any command fails +set -e + +revision="$1" + +if [ -z "$revision" ] +then + echo "Usage: $0 git-revision-full-sha1" >&2 + exit 1 +fi + +[ -f "chromium-bidi.zip" ] && rm "chromium-bidi.zip" +[ -d "src" ] && rm --recursive --force "src" + + +wget --output-document="chromium-bidi.zip" "https://github.com/GoogleChromeLabs/chromium-bidi/archive/$revision.zip" +unzip "chromium-bidi.zip" +mv "chromium-bidi-$revision" src + +date=$(date "+%Y-%m-%d") +sha512=$(sha512sum --binary "chromium-bidi.zip" | cut --fields=1 --delimiter=' ') +rm "chromium-bidi.zip" +echo "$date,$revision,$sha512" > "revision.info" +
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 050ae2c..2dc05ed 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -1442,7 +1442,10 @@ mojom_component("script_type_mojo_bindings") { generate_java = true - sources = [ "script/script_type.mojom" ] + sources = [ + "script/script_evaluation_params.mojom", + "script/script_type.mojom", + ] macro_prefix = "SCRIPT_TYPE_MOJOM" output_prefix = "script_type_mojom"
diff --git a/third_party/blink/public/mojom/devtools/inspector_issue.mojom b/third_party/blink/public/mojom/devtools/inspector_issue.mojom index 95e547d..3506928f 100644 --- a/third_party/blink/public/mojom/devtools/inspector_issue.mojom +++ b/third_party/blink/public/mojom/devtools/inspector_issue.mojom
@@ -208,7 +208,6 @@ kErrorFetchingIdTokenHttpNotFound, kErrorFetchingIdTokenNoResponse, kErrorFetchingIdTokenInvalidResponse, - kErrorFetchingIdTokenInvalidRequest, kErrorCanceled, kError, };
diff --git a/third_party/blink/public/mojom/script/script_evaluation_params.mojom b/third_party/blink/public/mojom/script/script_evaluation_params.mojom new file mode 100644 index 0000000..014cba2 --- /dev/null +++ b/third_party/blink/public/mojom/script/script_evaluation_params.mojom
@@ -0,0 +1,49 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file. + +module blink.mojom; + +// Parameters to evaluate scripts, mainly from outside Blink. + +// Whether the script evaluation should be associated with a user gesture. +enum UserActivationOption { + kDoNotActivate, + kActivate, +}; + +enum WantResultOption { + kNoResult, + + // Evaluation result (or promise resolution result if + // `PromiseResultOption::kAwait` is used) is passed to callback. + kWantResult, +}; + +enum PromiseResultOption { + // If the result of the executed script is a promise or other then-able, + // wait for it to settle and pass the result of the promise to the caller. + // If the promise (and any subsequent thenables) resolves, this passes the + // value. If the promise rejects, the corresponding value will be empty. + kAwait, + + // Don't wait for any promise to settle. + kDoNotWait, +}; + +enum EvaluationTiming { + // Execute scripts asynchronously. + kAsynchronous, + + // Execute scripts synchronously, unless the page is suspended. + // Even in this case, completion can be asynchronous, e.g. when + // `PromiseResultOption::kAwait` is used. + // If the page is suspended, execute scripts asynchronously. + kSynchronous, +}; + +// Whether to block window load event until the scripts are evaluated. +enum LoadEventBlockingOption { + kDoNotBlock, + kBlock, +};
diff --git a/third_party/blink/public/mojom/webid/federated_auth_request.mojom b/third_party/blink/public/mojom/webid/federated_auth_request.mojom index 6f2e2de..675d957 100644 --- a/third_party/blink/public/mojom/webid/federated_auth_request.mojom +++ b/third_party/blink/public/mojom/webid/federated_auth_request.mojom
@@ -41,17 +41,24 @@ string account_id; }; +// The details of an identity provider. +struct IdentityProvider { + url.mojom.Url config_url; + + // Can be an empty string to be omitted in the request sent to the provider. + string client_id; + + // Can be an empty string to be omitted in the request sent to the provider. + string nonce; +}; + // Create a federated sign-in request using the specified provider. // This interface is called from a renderer process and implemented in the // browser process. interface FederatedAuthRequest { - // Requests a token to be generated, given an IDP URL. - // |client_id| and |nonce| can be empty strings to omit the fields in the - // request sent to the provider. + // Requests a token to be generated, given an IdentityProvider. // Returns the raw content of the token. - RequestToken(url.mojom.Url provider, - string client_id, - string nonce, + RequestToken(IdentityProvider identity_provider_ptr, bool prefer_auto_sign_in) => (RequestTokenStatus status, string? token);
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index 9229e433..787171d 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -112,6 +112,7 @@ BLINK_PLATFORM_EXPORT static void EnableFedCm(bool); BLINK_PLATFORM_EXPORT static void EnableFedCmIdpSignout(bool); BLINK_PLATFORM_EXPORT static void EnableFedCmIframeSupport(bool); + BLINK_PLATFORM_EXPORT static void EnableFedCmMultipleIdentityProviders(bool); BLINK_PLATFORM_EXPORT static void EnableFencedFrames(bool); BLINK_PLATFORM_EXPORT static bool IsFencedFramesEnabled(); BLINK_PLATFORM_EXPORT static void EnableFileSystem(bool);
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h index 8c82414..fb11ec3 100644 --- a/third_party/blink/public/web/web_local_frame.h +++ b/third_party/blink/public/web/web_local_frame.h
@@ -36,6 +36,7 @@ #include "third_party/blink/public/mojom/page/widget.mojom-shared.h" #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-shared.h" #include "third_party/blink/public/mojom/portal/portal.mojom-shared.h" +#include "third_party/blink/public/mojom/script/script_evaluation_params.mojom-shared.h" #include "third_party/blink/public/mojom/selection_menu/selection_menu_behavior.mojom-shared.h" #include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom-shared.h" #include "third_party/blink/public/platform/cross_variant_mojo_util.h" @@ -414,35 +415,17 @@ v8::Local<v8::Value> argv[], WebScriptExecutionCallback*) = 0; - enum ScriptExecutionType { - // Execute script synchronously, unless the page is suspended. - kSynchronous, - // Execute script asynchronously. - kAsynchronous, - // Execute script asynchronously, blocking the window.onload event. - kAsynchronousBlockingOnload - }; - - enum class PromiseBehavior { - // If the result of the executed script is a promise or other then-able, - // wait for it to settle and pass the result of the promise to the caller. - // If the promise (and any subsequent thenables) resolves, this passes the - // value. If the promise rejects, the corresponding value will be empty. - kAwait, - // Don't wait for any promise to settle. - kDontWait, - }; - // Executes the script in the main world of the page. // Use kMainDOMWorldId to execute in the main world; otherwise, // `world_id` must be a positive integer and less than kEmbedderWorldIdLimit. virtual void RequestExecuteScript(int32_t world_id, base::span<const WebScriptSource> sources, - bool user_gesture, - ScriptExecutionType, + mojom::UserActivationOption, + mojom::EvaluationTiming, + mojom::LoadEventBlockingOption, WebScriptExecutionCallback*, BackForwardCacheAware, - PromiseBehavior) = 0; + mojom::PromiseResultOption) = 0; // Logs to the console associated with this frame. If |discard_duplicates| is // set, the message will only be added if it is unique (i.e. has not been @@ -475,8 +458,8 @@ virtual WebRange MarkedRange() const = 0; // Returns the text range rectangle in the viepwort coordinate space. - virtual bool FirstRectForCharacterRange(unsigned location, - unsigned length, + virtual bool FirstRectForCharacterRange(uint32_t location, + uint32_t length, gfx::Rect&) const = 0; // Supports commands like Undo, Redo, Cut, Copy, Paste, SelectAll,
diff --git a/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc index 5734f71..a9865c4 100644 --- a/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc
@@ -343,7 +343,7 @@ const StyleResolverState& state) const { const auto& color_pair = To<InterpolableList>(interpolable_value); Color color = ResolveInterpolableColor(*color_pair.Get(kUnvisited), state); - return cssvalue::CSSColor::Create(color.Rgb()); + return cssvalue::CSSColor::Create(color); } void CSSColorInterpolationType::Composite(
diff --git a/third_party/blink/renderer/core/css/binary_data_font_face_source.cc b/third_party/blink/renderer/core/css/binary_data_font_face_source.cc index 203696a..ba38d46 100644 --- a/third_party/blink/renderer/core/css/binary_data_font_face_source.cc +++ b/third_party/blink/renderer/core/css/binary_data_font_face_source.cc
@@ -40,6 +40,7 @@ return SimpleFontData::Create( custom_platform_data_->GetFontPlatformData( font_description.EffectiveFontSize(), + font_description.AdjustedSpecifiedSize(), font_description.IsSyntheticBold() && font_description.SyntheticBoldAllowed(), font_description.IsSyntheticItalic() &&
diff --git a/third_party/blink/renderer/core/css/css_color.cc b/third_party/blink/renderer/core/css/css_color.cc index bf1b0e7..80509508 100644 --- a/third_party/blink/renderer/core/css/css_color.cc +++ b/third_party/blink/renderer/core/css/css_color.cc
@@ -10,21 +10,21 @@ namespace blink { namespace cssvalue { -CSSColor* CSSColor::Create(RGBA32 color) { +CSSColor* CSSColor::Create(const Color& color) { // These are the empty and deleted values of the hash table. - if (Color::FromRGBA32(color) == Color::kTransparent) + if (color == Color::kTransparent) return CssValuePool().TransparentColor(); - if (Color::FromRGBA32(color) == Color::kWhite) + if (color == Color::kWhite) return CssValuePool().WhiteColor(); // Just because it is common. - if (Color::FromRGBA32(color) == Color::kBlack) + if (color == Color::kBlack) return CssValuePool().BlackColor(); + // TODO(https://crbug.com/1351544): Use blink::Color as the cache key. CSSValuePool::ColorValueCache::AddResult entry = - CssValuePool().GetColorCacheEntry(color); + CssValuePool().GetColorCacheEntry(color.Rgb()); if (entry.is_new_entry) { - entry.stored_value->value = - MakeGarbageCollected<CSSColor>(Color::FromRGBA32(color)); + entry.stored_value->value = MakeGarbageCollected<CSSColor>(color); } return entry.stored_value->value; }
diff --git a/third_party/blink/renderer/core/css/css_color.h b/third_party/blink/renderer/core/css/css_color.h index ec0a383..13ef2eb3 100644 --- a/third_party/blink/renderer/core/css/css_color.h +++ b/third_party/blink/renderer/core/css/css_color.h
@@ -20,8 +20,7 @@ // Represents the non-keyword subset of <color>. class CORE_EXPORT CSSColor : public CSSValue { public: - // TODO(sashab): Make this create() method take a Color instead. - static CSSColor* Create(RGBA32 color); + static CSSColor* Create(const Color& color); CSSColor(Color color) : CSSValue(kColorClass), color_(color) {}
diff --git a/third_party/blink/renderer/core/css/css_gradient_value.cc b/third_party/blink/renderer/core/css/css_gradient_value.cc index 72fbe5e..5528bd8 100644 --- a/third_party/blink/renderer/core/css/css_gradient_value.cc +++ b/third_party/blink/renderer/core/css/css_gradient_value.cc
@@ -359,7 +359,7 @@ case CSSValueID::kCurrentcolor: if (allow_visited_style) { stop.color_ = CSSColor::Create( - style.VisitedDependentColor(GetCSSPropertyColor()).Rgb()); + style.VisitedDependentColor(GetCSSPropertyColor())); } else { stop.color_ = ComputedStyleUtils::CurrentColorOrValidColor( style, StyleColor(), CSSValuePhase::kComputedValue); @@ -367,10 +367,8 @@ break; default: // TODO(crbug.com/929098) Need to pass an appropriate color scheme here. - stop.color_ = - CSSColor::Create(StyleColor::ColorFromKeyword( - value_id, mojom::blink::ColorScheme::kLight) - .Rgb()); + stop.color_ = CSSColor::Create(StyleColor::ColorFromKeyword( + value_id, mojom::blink::ColorScheme::kLight)); } AddStop(stop); }
diff --git a/third_party/blink/renderer/core/css/cssom/css_color_value.cc b/third_party/blink/renderer/core/css/cssom/css_color_value.cc index 843b43c8..59ccee3 100644 --- a/third_party/blink/renderer/core/css/cssom/css_color_value.cc +++ b/third_party/blink/renderer/core/css/cssom/css_color_value.cc
@@ -43,7 +43,7 @@ } const CSSValue* CSSColorValue::ToCSSValue() const { - return cssvalue::CSSColor::Create(ToColor().Rgb()); + return cssvalue::CSSColor::Create(ToColor()); } CSSNumericValue* CSSColorValue::ToNumberOrPercentage(
diff --git a/third_party/blink/renderer/core/css/cssom/css_unsupported_color.cc b/third_party/blink/renderer/core/css/cssom/css_unsupported_color.cc index a66dd45..06c9f4c 100644 --- a/third_party/blink/renderer/core/css/cssom/css_unsupported_color.cc +++ b/third_party/blink/renderer/core/css/cssom/css_unsupported_color.cc
@@ -22,9 +22,7 @@ } const CSSValue* CSSUnsupportedColor::ToCSSValue() const { - return cssvalue::CSSColor::Create( - MakeRGBA(color_value_.Red(), color_value_.Green(), color_value_.Blue(), - color_value_.Alpha())); + return cssvalue::CSSColor::Create(color_value_); } } // namespace blink
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc index c555bf038..dc102386 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc +++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
@@ -812,7 +812,7 @@ }); if (!parse_result) return nullptr; - return cssvalue::CSSColor::Create(color); + return cssvalue::CSSColor::Create(Color::FromRGBA32(color)); } CSSValue* CSSParserFastPaths::ParseColor(const String& string,
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc index 85644bb..8c1d0ff 100644 --- a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc +++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
@@ -119,7 +119,7 @@ const StyleColor& color, CSSValuePhase value_phase) { return cssvalue::CSSColor::Create( - color.Resolve(style.GetCurrentColor(), style.UsedColorScheme()).Rgb()); + color.Resolve(style.GetCurrentColor(), style.UsedColorScheme())); } const blink::Color ComputedStyleUtils::BorderSideColor( @@ -3032,10 +3032,8 @@ const StyleAutoColor& color, CSSValuePhase value_phase) { if (color.IsAutoColor()) { - return cssvalue::CSSColor::Create( - StyleColor::CurrentColor() - .Resolve(style.GetCurrentColor(), style.UsedColorScheme()) - .Rgb()); + return cssvalue::CSSColor::Create(StyleColor::CurrentColor().Resolve( + style.GetCurrentColor(), style.UsedColorScheme())); } return ComputedStyleUtils::CurrentColorOrValidColor( style, color.ToStyleColor(), value_phase);
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc index 85f40e1..8e51849c 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -1747,7 +1747,7 @@ return ConsumeInternalLightDark(ConsumeColor, range, context, accept_quirky_colors, allowed_keywords); } - return cssvalue::CSSColor::Create(color); + return cssvalue::CSSColor::Create(Color::FromRGBA32(color)); } CSSValue* ConsumeLineWidth(CSSParserTokenRange& range,
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc index 6e15db32..27c1e95c 100644 --- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc +++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -602,7 +602,7 @@ const LayoutObject*, bool allow_visited_style) const { if (allow_visited_style) { - return cssvalue::CSSColor::Create(style.VisitedDependentColor(*this).Rgb()); + return cssvalue::CSSColor::Create(style.VisitedDependentColor(*this)); } StyleColor background_color = style.BackgroundColor(); @@ -844,8 +844,7 @@ // https://drafts.csswg.org/cssom/#resolved-values // For this property, the resolved value is the used value. return allow_visited_style - ? cssvalue::CSSColor::Create( - style.VisitedDependentColor(*this).Rgb()) + ? cssvalue::CSSColor::Create(style.VisitedDependentColor(*this)) : ComputedStyleUtils::CurrentColorOrValidColor( style, border_bottom_color, CSSValuePhase::kUsedValue); } @@ -1107,8 +1106,7 @@ // https://drafts.csswg.org/cssom/#resolved-values // For this property, the resolved value is the used value. return allow_visited_style - ? cssvalue::CSSColor::Create( - style.VisitedDependentColor(*this).Rgb()) + ? cssvalue::CSSColor::Create(style.VisitedDependentColor(*this)) : ComputedStyleUtils::CurrentColorOrValidColor( style, border_left_color, CSSValuePhase::kUsedValue); } @@ -1167,8 +1165,7 @@ // https://drafts.csswg.org/cssom/#resolved-values // For this property, the resolved value is the used value. return allow_visited_style - ? cssvalue::CSSColor::Create( - style.VisitedDependentColor(*this).Rgb()) + ? cssvalue::CSSColor::Create(style.VisitedDependentColor(*this)) : ComputedStyleUtils::CurrentColorOrValidColor( style, border_right_color, CSSValuePhase::kUsedValue); } @@ -1241,8 +1238,7 @@ // https://drafts.csswg.org/cssom/#resolved-values // For this property, the resolved value is the used value. return allow_visited_style - ? cssvalue::CSSColor::Create( - style.VisitedDependentColor(*this).Rgb()) + ? cssvalue::CSSColor::Create(style.VisitedDependentColor(*this)) : ComputedStyleUtils::ComputedStyleUtils::CurrentColorOrValidColor( style, border_top_color, CSSValuePhase::kUsedValue); } @@ -1410,7 +1406,7 @@ const LayoutObject*, bool allow_visited_style) const { if (allow_visited_style) { - return cssvalue::CSSColor::Create(style.VisitedDependentColor(*this).Rgb()); + return cssvalue::CSSColor::Create(style.VisitedDependentColor(*this)); } StyleAutoColor auto_color = style.CaretColor(); @@ -1419,8 +1415,7 @@ StyleColor result = auto_color.IsAutoColor() ? StyleColor::CurrentColor() : auto_color.ToStyleColor(); if (style.ShouldForceColor(result)) { - return cssvalue::CSSColor::Create( - style.GetInternalForcedCurrentColor().Rgb()); + return cssvalue::CSSColor::Create(style.GetInternalForcedCurrentColor()); } // https://drafts.csswg.org/cssom/#resolved-values @@ -1573,9 +1568,9 @@ return GetCSSPropertyInternalForcedColor().CSSValueFromComputedStyle( style, nullptr, allow_visited_style); } - return cssvalue::CSSColor::Create( - allow_visited_style ? style.VisitedDependentColor(*this).Rgb() - : style.GetCurrentColor().Rgb()); + return cssvalue::CSSColor::Create(allow_visited_style + ? style.VisitedDependentColor(*this) + : style.GetCurrentColor()); } void Color::ApplyInitial(StyleResolverState& state) const { @@ -1814,11 +1809,11 @@ const ComputedStyle& style, const LayoutObject*, bool allow_visited_style) const { - return allow_visited_style ? cssvalue::CSSColor::Create( - style.VisitedDependentColor(*this).Rgb()) - : ComputedStyleUtils::CurrentColorOrValidColor( - style, style.ColumnRuleColor(), - CSSValuePhase::kComputedValue); + return allow_visited_style + ? cssvalue::CSSColor::Create(style.VisitedDependentColor(*this)) + : ComputedStyleUtils::CurrentColorOrValidColor( + style, style.ColumnRuleColor(), + CSSValuePhase::kComputedValue); } const CSSValue* ColumnRuleStyle::CSSValueFromComputedStyleInternal( @@ -4121,7 +4116,7 @@ bool visited_link = allow_visited_style && style.InsideLink() == EInsideLink::kInsideVisitedLink; return cssvalue::CSSColor::Create( - ColorIncludingFallback(visited_link, style).Rgb()); + ColorIncludingFallback(visited_link, style)); } const CSSValue* InternalForcedBackgroundColor::ParseSingleValue( @@ -4150,7 +4145,7 @@ bool visited_link = allow_visited_style && style.InsideLink() == EInsideLink::kInsideVisitedLink; return cssvalue::CSSColor::Create( - ColorIncludingFallback(visited_link, style).Rgb()); + ColorIncludingFallback(visited_link, style)); } const CSSValue* InternalForcedBorderColor::ParseSingleValue( @@ -4201,8 +4196,8 @@ const LayoutObject*, bool allow_visited_style) const { return cssvalue::CSSColor::Create( - allow_visited_style ? style.VisitedDependentColor(*this).Rgb() - : style.GetInternalForcedCurrentColor().Rgb()); + allow_visited_style ? style.VisitedDependentColor(*this) + : style.GetInternalForcedCurrentColor()); } const CSSValue* InternalForcedColor::ParseSingleValue( @@ -4231,7 +4226,7 @@ bool visited_link = allow_visited_style && style.InsideLink() == EInsideLink::kInsideVisitedLink; return cssvalue::CSSColor::Create( - ColorIncludingFallback(visited_link, style).Rgb()); + ColorIncludingFallback(visited_link, style)); } const CSSValue* InternalForcedOutlineColor::ParseSingleValue( @@ -5233,8 +5228,7 @@ // https://drafts.csswg.org/cssom/#resolved-values // For this property, the resolved value is the used value. return allow_visited_style - ? cssvalue::CSSColor::Create( - style.VisitedDependentColor(*this).Rgb()) + ? cssvalue::CSSColor::Create(style.VisitedDependentColor(*this)) : ComputedStyleUtils::CurrentColorOrValidColor( style, outline_color, CSSValuePhase::kUsedValue); }
diff --git a/third_party/blink/renderer/core/css/remote_font_face_source.cc b/third_party/blink/renderer/core/css/remote_font_face_source.cc index cf944c61..465097b67 100644 --- a/third_party/blink/renderer/core/css/remote_font_face_source.cc +++ b/third_party/blink/renderer/core/css/remote_font_face_source.cc
@@ -351,6 +351,7 @@ return SimpleFontData::Create( custom_font_data_->GetFontPlatformData( font_description.EffectiveFontSize(), + font_description.AdjustedSpecifiedSize(), font_description.IsSyntheticBold() && font_description.SyntheticBoldAllowed(), font_description.IsSyntheticItalic() &&
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc index 662abec3..50cedb1 100644 --- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc +++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -2110,7 +2110,7 @@ : mojom::blink::ColorScheme::kLight; Color color = document.GetTextLinkColors().ColorFromCSSValue( value, Color(), scheme, false); - return *cssvalue::CSSColor::Create(color.Rgb()); + return *cssvalue::CSSColor::Create(color); } }
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 1cf9a9f5..2df1357 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -2626,8 +2626,7 @@ document.PopupHintShowing()->HidePopUpInternal(focus_behavior, forcing_level); } - while (!document.PopupStack().IsEmpty() && - document.PopupStack().back() != endpoint) { + while (!document.PopupStack().IsEmpty()) { document.PopupStack().back()->HidePopUpInternal(focus_behavior, forcing_level); }
diff --git a/third_party/blink/renderer/core/editing/ime/edit_context.cc b/third_party/blink/renderer/core/editing/ime/edit_context.cc index 551c0a4..e50917f6 100644 --- a/third_party/blink/renderer/core/editing/ime/edit_context.cc +++ b/third_party/blink/renderer/core/editing/ime/edit_context.cc
@@ -140,9 +140,10 @@ static_cast<WTF::wtf_size_t>(ime_text_spans.size())); for (const auto& ime_text_span : ime_text_spans) { - const int range_start = - ime_text_span.start_offset + composition_range_start_; - const int range_end = ime_text_span.end_offset + composition_range_start_; + const auto range_start = base::checked_cast<wtf_size_t>( + ime_text_span.start_offset + composition_range_start_); + const auto range_end = base::checked_cast<wtf_size_t>( + ime_text_span.end_offset + composition_range_start_); String underline_thickness; String underline_style;
diff --git a/third_party/blink/renderer/core/editing/ime/ime_text_span.cc b/third_party/blink/renderer/core/editing/ime/ime_text_span.cc index 5fc34de..c9fb0f76 100644 --- a/third_party/blink/renderer/core/editing/ime/ime_text_span.cc +++ b/third_party/blink/renderer/core/editing/ime/ime_text_span.cc
@@ -5,6 +5,8 @@ #include "third_party/blink/renderer/core/editing/ime/ime_text_span.h" #include <algorithm> + +#include "base/numerics/safe_conversions.h" #include "ui/base/ime/ime_text_span.h" #include "ui/base/ime/mojom/ime_types.mojom-blink.h" @@ -29,8 +31,8 @@ } ImeTextSpan::ImeTextSpan(Type type, - unsigned start_offset, - unsigned end_offset, + wtf_size_t start_offset, + wtf_size_t end_offset, const Color& underline_color, ui::mojom::ImeTextSpanThickness thickness, ui::mojom::ImeTextSpanUnderlineStyle underline_style, @@ -54,7 +56,7 @@ // possible position. // TODO(wkorman): Consider replacing with DCHECK_LT(startOffset, endOffset). start_offset_ = - std::min(start_offset, std::numeric_limits<unsigned>::max() - 1u); + std::min(start_offset, std::numeric_limits<wtf_size_t>::max() - 1u); end_offset_ = std::max(start_offset_ + 1u, end_offset); } @@ -133,8 +135,8 @@ ImeTextSpan::ImeTextSpan(const ui::ImeTextSpan& ime_text_span) : ImeTextSpan(ConvertUiTypeToType(ime_text_span.type), - ime_text_span.start_offset, - ime_text_span.end_offset, + base::checked_cast<wtf_size_t>(ime_text_span.start_offset), + base::checked_cast<wtf_size_t>(ime_text_span.end_offset), Color::FromSkColor(ime_text_span.underline_color), ConvertUiThicknessToThickness(ime_text_span.thickness), ConvertUiUnderlineToUnderline(ime_text_span.underline_style),
diff --git a/third_party/blink/renderer/core/editing/ime/ime_text_span.h b/third_party/blink/renderer/core/editing/ime/ime_text_span.h index 57b4c2e..bb6d5fd 100644 --- a/third_party/blink/renderer/core/editing/ime/ime_text_span.h +++ b/third_party/blink/renderer/core/editing/ime/ime_text_span.h
@@ -49,8 +49,8 @@ }; ImeTextSpan(Type, - unsigned start_offset, - unsigned end_offset, + wtf_size_t start_offset, + wtf_size_t end_offset, const Color& underline_color, ui::mojom::ImeTextSpanThickness, ui::mojom::ImeTextSpanUnderlineStyle, @@ -64,8 +64,8 @@ explicit ImeTextSpan(const ui::ImeTextSpan&); Type GetType() const { return type_; } - unsigned StartOffset() const { return start_offset_; } - unsigned EndOffset() const { return end_offset_; } + wtf_size_t StartOffset() const { return start_offset_; } + wtf_size_t EndOffset() const { return end_offset_; } const Color& UnderlineColor() const { return underline_color_; } ui::mojom::ImeTextSpanThickness Thickness() const { return thickness_; } ui::mojom::ImeTextSpanUnderlineStyle UnderlineStyle() const { @@ -86,8 +86,8 @@ private: Type type_; - unsigned start_offset_; - unsigned end_offset_; + wtf_size_t start_offset_; + wtf_size_t end_offset_; Color underline_color_; ui::mojom::ImeTextSpanThickness thickness_; ui::mojom::ImeTextSpanUnderlineStyle underline_style_;
diff --git a/third_party/blink/renderer/core/editing/ime/input_method_controller.cc b/third_party/blink/renderer/core/editing/ime/input_method_controller.cc index c7262fc4..9fc1f5a5 100644 --- a/third_party/blink/renderer/core/editing/ime/input_method_controller.cc +++ b/third_party/blink/renderer/core/editing/ime/input_method_controller.cc
@@ -736,9 +736,9 @@ ContainerNode* base_element, unsigned offset_in_plain_chars) { for (const auto& ime_text_span : ime_text_spans) { - unsigned ime_text_span_start = + wtf_size_t ime_text_span_start = offset_in_plain_chars + ime_text_span.StartOffset(); - unsigned ime_text_span_end = + wtf_size_t ime_text_span_end = offset_in_plain_chars + ime_text_span.EndOffset(); EphemeralRange ephemeral_line_range =
diff --git a/third_party/blink/renderer/core/editing/ime/text_format.cc b/third_party/blink/renderer/core/editing/ime/text_format.cc index a2a1862..d2019d0 100644 --- a/third_party/blink/renderer/core/editing/ime/text_format.cc +++ b/third_party/blink/renderer/core/editing/ime/text_format.cc
@@ -8,8 +8,8 @@ namespace blink { -TextFormat::TextFormat(uint32_t range_start, - uint32_t range_end, +TextFormat::TextFormat(wtf_size_t range_start, + wtf_size_t range_end, const String& text_color, const String& background_color, const String& underline_color, @@ -23,8 +23,8 @@ underline_style_(underline_style), underline_thickness_(underline_thickness) {} -TextFormat* TextFormat::Create(uint32_t range_start, - uint32_t range_end, +TextFormat* TextFormat::Create(wtf_size_t range_start, + wtf_size_t range_end, const String& text_color, const String& background_color, const String& underline_color, @@ -62,11 +62,11 @@ return MakeGarbageCollected<TextFormat>(dict); } -uint32_t TextFormat::rangeStart() const { +wtf_size_t TextFormat::rangeStart() const { return range_start_; } -uint32_t TextFormat::rangeEnd() const { +wtf_size_t TextFormat::rangeEnd() const { return range_end_; }
diff --git a/third_party/blink/renderer/core/editing/ime/text_format.h b/third_party/blink/renderer/core/editing/ime/text_format.h index ef78028..2a2af5a5 100644 --- a/third_party/blink/renderer/core/editing/ime/text_format.h +++ b/third_party/blink/renderer/core/editing/ime/text_format.h
@@ -23,24 +23,24 @@ public: static TextFormat* Create(const TextFormatInit* dict); - static TextFormat* Create(uint32_t range_start, - uint32_t range_end, + static TextFormat* Create(wtf_size_t range_start, + wtf_size_t range_end, const String& text_color, const String& background_color, const String& underline_color, const String& underline_style, const String& underline_thickness); explicit TextFormat(const TextFormatInit* dict); - TextFormat(uint32_t range_start, - uint32_t range_end, + TextFormat(wtf_size_t range_start, + wtf_size_t range_end, const String& text_color, const String& background_color, const String& underline_color, const String& underline_style, const String& underline_thickness); - uint32_t rangeStart() const; - uint32_t rangeEnd() const; + wtf_size_t rangeStart() const; + wtf_size_t rangeEnd() const; String textColor() const; String backgroundColor() const; String underlineColor() const; @@ -48,8 +48,8 @@ String underlineThickness() const; private: - uint32_t range_start_ = 0; - uint32_t range_end_ = 0; + wtf_size_t range_start_ = 0; + wtf_size_t range_end_ = 0; String text_color_; String background_color_; String underline_color_;
diff --git a/third_party/blink/renderer/core/frame/attribution_src_loader.cc b/third_party/blink/renderer/core/frame/attribution_src_loader.cc index 57948b7a..dea509e 100644 --- a/third_party/blink/renderer/core/frame/attribution_src_loader.cc +++ b/third_party/blink/renderer/core/frame/attribution_src_loader.cc
@@ -29,6 +29,7 @@ #include "third_party/blink/renderer/core/frame/local_frame_client.h" #include "third_party/blink/renderer/core/html/html_element.h" #include "third_party/blink/renderer/core/inspector/identifiers_factory.h" +#include "third_party/blink/renderer/core/inspector/inspector_audits_issue.h" #include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/heap/self_keep_alive.h" #include "third_party/blink/renderer/platform/loader/attribution_header_constants.h" @@ -111,43 +112,6 @@ } // namespace -bool CanRegisterAttributionInContext(LocalFrame* frame, - HTMLElement* element, - absl::optional<uint64_t> request_id, - bool log_issues) { - DCHECK(frame); - - LocalDOMWindow* window = frame->DomWindow(); - DCHECK(window); - - if (!RuntimeEnabledFeatures::AttributionReportingEnabled(window)) - return false; - - const bool feature_policy_enabled = window->IsFeatureEnabled( - mojom::blink::PermissionsPolicyFeature::kAttributionReporting); - - if (!feature_policy_enabled) { - if (log_issues) { - LogAuditIssue(window, - AttributionReportingIssueType::kPermissionPolicyDisabled, - element, request_id, /*invalid_parameter=*/String()); - } - return false; - } - - if (!window->IsSecureContext()) { - if (log_issues) { - LogAuditIssue( - window, AttributionReportingIssueType::kInsecureContext, element, - request_id, /*invalid_parameter=*/ - window->GetSecurityContext().GetSecurityOrigin()->ToString()); - } - return false; - } - - return true; -} - class AttributionSrcLoader::ResourceClient : public GarbageCollected<AttributionSrcLoader::ResourceClient>, public RawResourceClient { @@ -295,10 +259,8 @@ return nullptr; } - if (!ReportingOriginForUrlIfValid(src_url, element, - /*request_id=*/absl::nullopt)) { + if (!CanRegister(src_url, element, /*request_id=*/absl::nullopt)) return nullptr; - } Document* document = window->document(); @@ -365,21 +327,45 @@ AttributionSrcLoader::ReportingOriginForUrlIfValid( const KURL& url, HTMLElement* element, - absl::optional<uint64_t> request_id) { + absl::optional<uint64_t> request_id, + bool log_issues) { LocalDOMWindow* window = local_frame_->DomWindow(); DCHECK(window); - if (!CanRegisterAttributionInContext(local_frame_, element, request_id)) + auto maybe_log_audit_issue = [&](AttributionReportingIssueType issue_type, + const SecurityOrigin* invalid_origin = + nullptr) { + if (!log_issues) + return; + + LogAuditIssue(window, issue_type, element, request_id, + /*invalid_parameter=*/ + invalid_origin ? invalid_origin->ToString() : String()); + }; + + if (!RuntimeEnabledFeatures::AttributionReportingEnabled(window)) return nullptr; + if (!window->IsFeatureEnabled( + mojom::blink::PermissionsPolicyFeature::kAttributionReporting)) { + maybe_log_audit_issue( + AttributionReportingIssueType::kPermissionPolicyDisabled); + return nullptr; + } + + if (!window->IsSecureContext()) { + maybe_log_audit_issue(AttributionReportingIssueType::kInsecureContext, + window->GetSecurityContext().GetSecurityOrigin()); + return nullptr; + } + scoped_refptr<const SecurityOrigin> reporting_origin = SecurityOrigin::Create(url); if (!url.ProtocolIsInHTTPFamily() || !reporting_origin->IsPotentiallyTrustworthy()) { - LogAuditIssue(window, - AttributionReportingIssueType::kUntrustworthyReportingOrigin, - element, request_id, - /*invalid_parameter=*/reporting_origin->ToString()); + maybe_log_audit_issue( + AttributionReportingIssueType::kUntrustworthyReportingOrigin, + reporting_origin.get()); return nullptr; } @@ -393,6 +379,13 @@ return reporting_origin; } +bool AttributionSrcLoader::CanRegister(const KURL& url, + HTMLElement* element, + absl::optional<uint64_t> request_id, + bool log_issues) { + return !!ReportingOriginForUrlIfValid(url, element, request_id, log_issues); +} + bool AttributionSrcLoader::MaybeRegisterAttributionHeaders( const ResourceRequest& request, const ResourceResponse& response,
diff --git a/third_party/blink/renderer/core/frame/attribution_src_loader.h b/third_party/blink/renderer/core/frame/attribution_src_loader.h index 04cefcd..90f3e3ac 100644 --- a/third_party/blink/renderer/core/frame/attribution_src_loader.h +++ b/third_party/blink/renderer/core/frame/attribution_src_loader.h
@@ -11,7 +11,6 @@ #include "base/memory/scoped_refptr.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/inspector/inspector_audits_issue.h" #include "third_party/blink/renderer/platform/heap/forward.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/heap/member.h" @@ -64,6 +63,18 @@ absl::optional<Impression> RegisterNavigation(const KURL& attribution_src, HTMLElement* element = nullptr); + // Returns true if `url` can be used as an attributionsrc: its scheme is HTTP + // or HTTPS, its origin is potentially trustworthy, the document's permission + // policy supports Attribution Reporting, the window's context is secure, and + // the Attribution Reporting runtime-enabled feature is enabled. + // + // Reports a DevTools issue using `element` and `request_id` otherwise, if + // `log_issues` is true. + [[nodiscard]] bool CanRegister(const KURL& url, + HTMLElement* element, + absl::optional<uint64_t> request_id, + bool log_issues = true); + void Trace(Visitor* visitor) const; static constexpr size_t kMaxConcurrentRequests = 30; @@ -80,11 +91,13 @@ // Returns the reporting origin corresponding to `url` if its protocol is in // the HTTP family, its origin is potentially trustworthy, and attribution is - // allowed. Returns `nullptr` and reports a DevTools issue otherwise. + // allowed. Returns `nullptr` otherwise, and reports a DevTools issue using + // `element` and `request_id if `log_issues` is true. scoped_refptr<const SecurityOrigin> ReportingOriginForUrlIfValid( const KURL& url, HTMLElement* element, - absl::optional<uint64_t> request_id); + absl::optional<uint64_t> request_id, + bool log_issues = true); ResourceClient* CreateAndSendRequest(const KURL& src_url, HTMLElement* element, @@ -95,15 +108,6 @@ size_t num_resource_clients_ = 0; }; -// Returns whether attribution is allowed, and logs DevTools issues if -// registration was attempted in a context that is not allowed. -// `element` may be null. -CORE_EXPORT bool CanRegisterAttributionInContext( - LocalFrame* frame, - HTMLElement* element, - absl::optional<uint64_t> request_id, - bool log_issues = true); - } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_ATTRIBUTION_SRC_LOADER_H_
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc index cae474b..047a94f 100644 --- a/third_party/blink/renderer/core/frame/local_dom_window.cc +++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -2089,7 +2089,7 @@ } WebWindowFeatures window_features = - GetWindowFeaturesFromString(features, entered_window); + GetWindowFeaturesFromString(features, entered_window, completed_url); // In fenced frames, we should always use `noopener`. if (GetFrame()->IsInFencedFrameTree()) {
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc index 358ba6b..2ad89c64 100644 --- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc +++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -1161,8 +1161,8 @@ : GetCurrentCursorPositionInFrame(frame_); WebLocalFrameImpl::FromFrame(frame_)->FirstRectForCharacterRange( - base::checked_cast<unsigned>(start), - base::checked_cast<unsigned>(range.length()), rect); + base::checked_cast<uint32_t>(start), + base::checked_cast<uint32_t>(range.length()), rect); } }
diff --git a/third_party/blink/renderer/core/frame/pausable_script_executor.cc b/third_party/blink/renderer/core/frame/pausable_script_executor.cc index 50802cd9d..34ba150b 100644 --- a/third_party/blink/renderer/core/frame/pausable_script_executor.cc +++ b/third_party/blink/renderer/core/frame/pausable_script_executor.cc
@@ -144,26 +144,27 @@ public: WebScriptExecutor(Vector<WebScriptSource>, int32_t world_id, - bool user_gesture); + mojom::blink::UserActivationOption); Vector<v8::Local<v8::Value>> Execute(LocalDOMWindow*) override; private: Vector<WebScriptSource> sources_; int32_t world_id_; - bool user_gesture_; + mojom::blink::UserActivationOption user_gesture_; }; -WebScriptExecutor::WebScriptExecutor(Vector<WebScriptSource> sources, - int32_t world_id, - bool user_gesture) +WebScriptExecutor::WebScriptExecutor( + Vector<WebScriptSource> sources, + int32_t world_id, + mojom::blink::UserActivationOption user_gesture) : sources_(std::move(sources)), world_id_(world_id), user_gesture_(user_gesture) {} Vector<v8::Local<v8::Value>> WebScriptExecutor::Execute( LocalDOMWindow* window) { - if (user_gesture_) { + if (user_gesture_ == mojom::blink::UserActivationOption::kActivate) { // TODO(mustaq): Need to make sure this is safe. https://crbug.com/1082273 LocalFrame::NotifyUserActivation( window->GetFrame(), @@ -284,7 +285,7 @@ LocalDOMWindow* window, scoped_refptr<DOMWrapperWorld> world, Vector<WebScriptSource> sources, - bool user_gesture, + mojom::blink::UserActivationOption user_gesture, WebScriptExecutionCallback* callback) : PausableScriptExecutor( window, @@ -302,7 +303,7 @@ : ExecutionContextLifecycleObserver(window), script_state_(script_state), callback_(callback), - blocking_option_(kNonBlocking), + blocking_option_(mojom::blink::LoadEventBlockingOption::kDoNotBlock), executor_(executor) { CHECK(script_state_); CHECK(script_state_->ContextIsValid()); @@ -320,11 +321,12 @@ PostExecuteAndDestroySelf(context); } -void PausableScriptExecutor::RunAsync(BlockingOption blocking) { +void PausableScriptExecutor::RunAsync( + mojom::blink::LoadEventBlockingOption blocking) { ExecutionContext* context = GetExecutionContext(); DCHECK(context); blocking_option_ = blocking; - if (blocking_option_ == kOnloadBlocking) + if (blocking_option_ == mojom::blink::LoadEventBlockingOption::kBlock) To<LocalDOMWindow>(context)->document()->IncrementLoadEventDelayCount(); PostExecuteAndDestroySelf(context); @@ -353,21 +355,24 @@ if (!script_state_->ContextIsValid()) return; - if (wait_for_promise_) { - // Use a SelfKeepAlive to extend the lifetime of the PausableScriptExecutor - // while we wait for promises to settle. We don't just use a reference in - // the callback to PromiseAggregator to avoid a cycle with a GC root. - // Cleared in Dispose(), which is called when all promises settle or when - // the ExecutionContext is invalidated. - keep_alive_ = this; - MakeGarbageCollected<PromiseAggregator>( - script_state_, results, - WTF::Bind(&PausableScriptExecutor::HandleResults, - WrapWeakPersistent(this))); - return; - } + switch (wait_for_promise_) { + case mojom::blink::PromiseResultOption::kAwait: + // Use a SelfKeepAlive to extend the lifetime of the + // PausableScriptExecutor while we wait for promises to settle. We don't + // just use a reference in the callback to PromiseAggregator to avoid a + // cycle with a GC root. Cleared in Dispose(), which is called when all + // promises settle or when the ExecutionContext is invalidated. + keep_alive_ = this; + MakeGarbageCollected<PromiseAggregator>( + script_state_, results, + WTF::Bind(&PausableScriptExecutor::HandleResults, + WrapWeakPersistent(this))); + break; - HandleResults(results); + case mojom::blink::PromiseResultOption::kDoNotWait: + HandleResults(results); + break; + } } void PausableScriptExecutor::HandleResults( @@ -379,7 +384,7 @@ auto* window = To<LocalDOMWindow>(GetExecutionContext()); - if (blocking_option_ == kOnloadBlocking) + if (blocking_option_ == mojom::blink::LoadEventBlockingOption::kBlock) window->document()->DecrementLoadEventDelayCount(); if (callback_)
diff --git a/third_party/blink/renderer/core/frame/pausable_script_executor.h b/third_party/blink/renderer/core/frame/pausable_script_executor.h index 0aaa752a..3c9b611 100644 --- a/third_party/blink/renderer/core/frame/pausable_script_executor.h +++ b/third_party/blink/renderer/core/frame/pausable_script_executor.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_PAUSABLE_SCRIPT_EXECUTOR_H_ #include "base/memory/scoped_refptr.h" +#include "third_party/blink/public/mojom/script/script_evaluation_params.mojom-blink.h" #include "third_party/blink/public/web/web_script_source.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" @@ -26,8 +27,6 @@ : public GarbageCollected<PausableScriptExecutor>, public ExecutionContextLifecycleObserver { public: - enum BlockingOption { kNonBlocking, kOnloadBlocking }; - static void CreateAndRun(LocalDOMWindow*, v8::Local<v8::Context>, v8::Local<v8::Function>, @@ -48,7 +47,7 @@ PausableScriptExecutor(LocalDOMWindow*, scoped_refptr<DOMWrapperWorld>, Vector<WebScriptSource>, - bool, + mojom::blink::UserActivationOption, WebScriptExecutionCallback*); PausableScriptExecutor(LocalDOMWindow*, ScriptState*, @@ -57,12 +56,13 @@ ~PausableScriptExecutor() override; void Run(); - void RunAsync(BlockingOption); + void RunAsync(mojom::blink::LoadEventBlockingOption); void ContextDestroyed() override; void Trace(Visitor*) const override; - void set_wait_for_promise(bool wait_for_promise) { + void set_wait_for_promise( + mojom::blink::PromiseResultOption wait_for_promise) { wait_for_promise_ = wait_for_promise; } @@ -75,14 +75,15 @@ Member<ScriptState> script_state_; WebScriptExecutionCallback* callback_; - BlockingOption blocking_option_; + mojom::blink::LoadEventBlockingOption blocking_option_; TaskHandle task_handle_; Member<Executor> executor_; // Whether to wait for a promise to resolve, if the executed script evaluates // to a promise. - bool wait_for_promise_ = false; + mojom::blink::PromiseResultOption wait_for_promise_ = + mojom::blink::PromiseResultOption::kDoNotWait; // A keepalive used when waiting on promises to settle. SelfKeepAlive<PausableScriptExecutor> keep_alive_;
diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc index 487a8b84..731d6c5c 100644 --- a/third_party/blink/renderer/core/frame/web_frame_test.cc +++ b/third_party/blink/renderer/core/frame/web_frame_test.cc
@@ -259,27 +259,33 @@ // A helper function to execute the given `scripts` in the main world of the // specified `frame`. -void ExecuteScriptsInMainWorld(WebLocalFrame* frame, - base::span<const String> scripts, - WebScriptExecutionCallback* callback, - bool wait_for_promise = true, - bool user_gesture = false) { +void ExecuteScriptsInMainWorld( + WebLocalFrame* frame, + base::span<const String> scripts, + WebScriptExecutionCallback* callback, + mojom::blink::PromiseResultOption wait_for_promise = + mojom::blink::PromiseResultOption::kAwait, + mojom::blink::UserActivationOption user_gesture = + mojom::blink::UserActivationOption::kDoNotActivate) { Vector<WebScriptSource> sources; for (auto script : scripts) sources.push_back(WebScriptSource(script)); frame->RequestExecuteScript( DOMWrapperWorld::kMainWorldId, sources, user_gesture, - WebLocalFrame::kSynchronous, callback, BackForwardCacheAware::kAllow, - wait_for_promise ? WebLocalFrame::PromiseBehavior::kAwait - : WebLocalFrame::PromiseBehavior::kDontWait); + mojom::blink::EvaluationTiming::kSynchronous, + mojom::blink::LoadEventBlockingOption::kDoNotBlock, callback, + BackForwardCacheAware::kAllow, wait_for_promise); } // Same as above, but for a single script. -void ExecuteScriptInMainWorld(WebLocalFrame* frame, - String script_string, - WebScriptExecutionCallback* callback, - bool wait_for_promise = true, - bool user_gesture = false) { +void ExecuteScriptInMainWorld( + WebLocalFrame* frame, + String script_string, + WebScriptExecutionCallback* callback, + mojom::blink::PromiseResultOption wait_for_promise = + mojom::blink::PromiseResultOption::kAwait, + mojom::blink::UserActivationOption user_gesture = + mojom::blink::UserActivationOption::kDoNotActivate) { ExecuteScriptsInMainWorld(frame, base::make_span(&script_string, 1), callback, wait_for_promise, user_gesture); } @@ -655,7 +661,7 @@ web_view_helper.LocalMainFrame()->MainWorldScriptContext()); ExecuteScriptInMainWorld(web_view_helper.GetWebView()->MainFrameImpl(), kScript, &callback_helper, - /*wait_for_promise=*/false); + mojom::blink::PromiseResultOption::kDoNotWait); RunPendingTasks(); // Since the caller specified the script shouldn't wait for the promise to // be resolved, the callback should have completed normally and the result @@ -747,7 +753,7 @@ ScriptExecutionCallbackHelper callback_helper( web_view_helper.LocalMainFrame()->MainWorldScriptContext()); ExecuteScriptsInMainWorld(web_view_helper.GetWebView()->MainFrameImpl(), - scripts, &callback_helper, true); + scripts, &callback_helper); RunPendingTasks(); EXPECT_TRUE(callback_helper.DidComplete()); EXPECT_EQ("hello", callback_helper.StringValueAt(0)); @@ -769,7 +775,7 @@ ScriptExecutionCallbackHelper callback_helper( web_view_helper.LocalMainFrame()->MainWorldScriptContext()); ExecuteScriptsInMainWorld(web_view_helper.GetWebView()->MainFrameImpl(), - scripts, &callback_helper, true); + scripts, &callback_helper); RunPendingTasks(); EXPECT_FALSE(callback_helper.DidComplete()); @@ -804,7 +810,7 @@ ScriptExecutionCallbackHelper callback_helper( web_view_helper.LocalMainFrame()->MainWorldScriptContext()); ExecuteScriptsInMainWorld(web_view_helper.GetWebView()->MainFrameImpl(), - scripts, &callback_helper, true); + scripts, &callback_helper); RunPendingTasks(); EXPECT_TRUE(callback_helper.DidComplete()); @@ -827,7 +833,7 @@ ScriptExecutionCallbackHelper callback_helper( web_view_helper.LocalMainFrame()->MainWorldScriptContext()); ExecuteScriptsInMainWorld(web_view_helper.GetWebView()->MainFrameImpl(), - scripts, &callback_helper, true); + scripts, &callback_helper); RunPendingTasks(); EXPECT_TRUE(callback_helper.DidComplete()); EXPECT_EQ("hello", callback_helper.StringValueAt(0)); @@ -1025,7 +1031,8 @@ // user activation but without the delegation option. ExecuteScriptInMainWorld(web_view_helper.GetWebView()->MainFrameImpl(), post_message_wo_request, &callback_helper, - /*wait_for_promise=*/true, /*user_gesture=*/true); + blink::mojom::PromiseResultOption::kAwait, + blink::mojom::UserActivationOption::kActivate); RunPendingTasks(); EXPECT_TRUE(callback_helper.DidComplete()); EXPECT_FALSE(message_event_listener->DelegateCapability()); @@ -1034,7 +1041,8 @@ // both user activation and the delegation option. ExecuteScriptInMainWorld(web_view_helper.GetWebView()->MainFrameImpl(), post_message_w_payment_request, &callback_helper, - /*wait_for_promise=*/true, /*user_gesture=*/true); + blink::mojom::PromiseResultOption::kAwait, + blink::mojom::UserActivationOption::kActivate); RunPendingTasks(); EXPECT_TRUE(callback_helper.DidComplete()); EXPECT_TRUE(message_event_listener->DelegateCapability()); @@ -1051,7 +1059,8 @@ ExecuteScriptInMainWorld(web_view_helper.GetWebView()->MainFrameImpl(), post_message_w_fullscreen_request, &callback_helper, - /*wait_for_promise=*/true, /*user_gesture=*/true); + blink::mojom::PromiseResultOption::kAwait, + blink::mojom::UserActivationOption::kActivate); RunPendingTasks(); EXPECT_TRUE(callback_helper.DidComplete()); EXPECT_TRUE(message_event_listener->DelegateCapability()); @@ -1066,7 +1075,8 @@ // user activation and the delegation option for an unknown capability. ExecuteScriptInMainWorld(web_view_helper.GetWebView()->MainFrameImpl(), post_message_w_unknown_request, &callback_helper, - /*wait_for_promise=*/true, /*user_gesture=*/true); + blink::mojom::PromiseResultOption::kAwait, + blink::mojom::UserActivationOption::kActivate); RunPendingTasks(); EXPECT_TRUE(callback_helper.DidComplete()); EXPECT_FALSE(message_event_listener->DelegateCapability());
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc index e169c480..a051def3 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -38,6 +38,7 @@ #include "base/debug/crash_logging.h" #include "base/debug/dump_without_crashing.h" #include "base/metrics/histogram_macros.h" +#include "base/numerics/safe_conversions.h" #include "base/task/single_thread_task_runner.h" #include "base/time/time.h" #include "build/build_config.h" @@ -3605,9 +3606,11 @@ for (const auto& ime_text_span : ime_text_spans) { gfx::Rect rect; - unsigned length = ime_text_span.end_offset - ime_text_span.start_offset; - focused_frame->FirstRectForCharacterRange(ime_text_span.start_offset, - length, rect); + auto length = base::checked_cast<wtf_size_t>(ime_text_span.end_offset - + ime_text_span.start_offset); + focused_frame->FirstRectForCharacterRange( + base::checked_cast<wtf_size_t>(ime_text_span.start_offset), length, + rect); ime_text_spans_info.push_back(ui::mojom::blink::ImeTextSpanInfo::New( ime_text_span, widget_base_->BlinkSpaceToEnclosedDIPs(rect)));
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index 0fda041..d2a7456 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -1081,11 +1081,12 @@ void WebLocalFrameImpl::RequestExecuteScript( int32_t world_id, base::span<const WebScriptSource> sources, - bool user_gesture, - ScriptExecutionType execution_type, + mojom::blink::UserActivationOption user_gesture, + mojom::blink::EvaluationTiming evaluation_timing, + mojom::blink::LoadEventBlockingOption blocking_option, WebScriptExecutionCallback* callback, BackForwardCacheAware back_forward_cache_aware, - PromiseBehavior promise_behavior) { + mojom::blink::PromiseResultOption promise_behavior) { DCHECK(GetFrame()); scoped_refptr<DOMWrapperWorld> world; @@ -1108,15 +1109,12 @@ auto* executor = MakeGarbageCollected<PausableScriptExecutor>( GetFrame()->DomWindow(), std::move(world), std::move(script_sources), user_gesture, callback); - executor->set_wait_for_promise(promise_behavior == PromiseBehavior::kAwait); - switch (execution_type) { - case kAsynchronousBlockingOnload: - executor->RunAsync(PausableScriptExecutor::kOnloadBlocking); + executor->set_wait_for_promise(promise_behavior); + switch (evaluation_timing) { + case mojom::blink::EvaluationTiming::kAsynchronous: + executor->RunAsync(blocking_option); break; - case kAsynchronous: - executor->RunAsync(PausableScriptExecutor::kNonBlocking); - break; - case kSynchronous: + case mojom::blink::EvaluationTiming::kSynchronous: executor->Run(); break; } @@ -1262,8 +1260,8 @@ } bool WebLocalFrameImpl::FirstRectForCharacterRange( - unsigned location, - unsigned length, + uint32_t location, + uint32_t length, gfx::Rect& rect_in_viewport) const { if ((location + length < location) && (location + length)) length = 0;
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h index 3377e3e3..3c12154d 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -54,6 +54,7 @@ #include "third_party/blink/public/mojom/input/input_handler.mojom-blink-forward.h" #include "third_party/blink/public/mojom/page/widget.mojom-blink.h" #include "third_party/blink/public/mojom/portal/portal.mojom-blink-forward.h" +#include "third_party/blink/public/mojom/script/script_evaluation_params.mojom-blink-forward.h" #include "third_party/blink/public/platform/web_file_system_type.h" #include "third_party/blink/public/web/web_history_commit_type.h" #include "third_party/blink/public/web/web_local_frame.h" @@ -184,11 +185,12 @@ WebScriptExecutionCallback*) override; void RequestExecuteScript(int32_t world_id, base::span<const WebScriptSource> sources, - bool user_gesture, - ScriptExecutionType, + mojom::blink::UserActivationOption, + mojom::blink::EvaluationTiming, + mojom::blink::LoadEventBlockingOption, WebScriptExecutionCallback*, BackForwardCacheAware back_forward_cache_aware, - PromiseBehavior) override; + mojom::blink::PromiseResultOption) override; void Alert(const WebString& message) override; bool Confirm(const WebString& message) override; WebString Prompt(const WebString& message, @@ -198,8 +200,8 @@ void UnmarkText() override; bool HasMarkedText() const override; WebRange MarkedRange() const override; - bool FirstRectForCharacterRange(unsigned location, - unsigned length, + bool FirstRectForCharacterRange(uint32_t location, + uint32_t length, gfx::Rect&) const override; bool ExecuteCommand(const WebString&) override; bool ExecuteCommand(const WebString&, const WebString& value) override;
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third_party/blink/renderer/core/html/html_anchor_element.cc index 138b079..609d2ec3 100644 --- a/third_party/blink/renderer/core/html/html_anchor_element.cc +++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -537,8 +537,9 @@ // If the impression could not be set, or if the value was null, mark that // the frame request is eligible for attribution by adding an impression. if (!frame_request.Impression() && - CanRegisterAttributionInContext(frame, this, - /*request_id=*/absl::nullopt)) { + frame->GetAttributionSrcLoader()->CanRegister( + completed_url, this, + /*request_id=*/absl::nullopt)) { frame_request.SetImpression(blink::Impression()); } }
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc index c002234..2d6135a6 100644 --- a/third_party/blink/renderer/core/html/html_element.cc +++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -1743,8 +1743,7 @@ if (!ParseColorWithLegacyRules(attribute_value, parsed_color)) return; - style->SetProperty(property_id, - *cssvalue::CSSColor::Create(parsed_color.Rgb())); + style->SetProperty(property_id, *cssvalue::CSSColor::Create(parsed_color)); } LabelsNodeList* HTMLElement::labels() {
diff --git a/third_party/blink/renderer/core/html/html_hr_element.cc b/third_party/blink/renderer/core/html/html_hr_element.cc index 77058e1..fcb36835 100644 --- a/third_party/blink/renderer/core/html/html_hr_element.cc +++ b/third_party/blink/renderer/core/html/html_hr_element.cc
@@ -87,7 +87,7 @@ style, CSSPropertyID::kBorderStyle, CSSValueID::kSolid); const cssvalue::CSSColor& dark_gray_value = - *cssvalue::CSSColor::Create(Color::kDarkGray.Rgb()); + *cssvalue::CSSColor::Create(Color::kDarkGray); style->SetProperty(CSSPropertyID::kBorderColor, dark_gray_value); style->SetProperty(CSSPropertyID::kBackgroundColor, dark_gray_value); }
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc index e3f05f6..0289f48 100644 --- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc +++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
@@ -42,7 +42,6 @@ #include "third_party/blink/renderer/core/css/parser/sizes_attribute_parser.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/execution_context/security_context.h" -#include "third_party/blink/renderer/core/frame/attribution_src_loader.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/frame/viewport_data.h" @@ -341,8 +340,7 @@ if (scanner_type_ == ScannerType::kInsertion) request->SetFromInsertionScanner(true); - if (attributionsrc_attr_set_ && - document_parameters.can_register_attribution) { + if (attributionsrc_attr_set_) { DCHECK(is_script || is_img); request->SetAttributionReportingEligibleImgOrScript(true); } @@ -1189,12 +1187,6 @@ } probe::GetDisabledImageTypes(document->GetExecutionContext(), &disabled_image_types); - - can_register_attribution = - CanRegisterAttributionInContext(document->Loader()->GetFrame(), - /*element=*/nullptr, - /*request_id=*/absl::nullopt, - /*log_issues=*/false); } } // namespace blink
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h index ccd176c..35a3d54 100644 --- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h +++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
@@ -92,7 +92,6 @@ SubresourceIntegrity::IntegrityFeatures integrity_features; LocalFrame::LazyLoadImageSetting lazy_load_image_setting; HashSet<String> disabled_image_types; - bool can_register_attribution; }; class TokenPreloadScanner {
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc index 1bf19f9..8f67df6e 100644 --- a/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc +++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
@@ -99,6 +99,7 @@ struct AttributionSrcTestCase { bool use_secure_document_url; + const char* base_url; const char* input_html; const char* expected_header; }; @@ -247,9 +248,6 @@ Resource* resource = preload_request_->Start(document); ASSERT_TRUE(resource); - EXPECT_EQ(!!expected_header, - preload_request_->IsAttributionReportingEligibleImgOrScript()); - EXPECT_EQ(expected_header, resource->GetResourceRequest().HttpHeaderField( http_names::kAttributionReportingEligible)); } @@ -428,7 +426,7 @@ void Test(AttributionSrcTestCase test_case) { SCOPED_TRACE(test_case.input_html); HTMLMockHTMLResourcePreloader preloader(GetDocument().Url()); - KURL base_url("http://example.test/"); + KURL base_url(test_case.base_url); scanner_->AppendToEnd(String(test_case.input_html)); std::unique_ptr<PendingPreloadData> preload_data = scanner_->Scan(base_url); preloader.TakePreloadData(std::move(preload_data)); @@ -1090,19 +1088,36 @@ } TEST_F(HTMLPreloadScannerTest, testAttributionSrc) { + static constexpr bool kSecureDocumentUrl = true; + static constexpr bool kInsecureDocumentUrl = false; + + static constexpr char kSecureBaseURL[] = "https://example.test"; + static constexpr char kInsecureBaseURL[] = "http://example.test"; + AttributionSrcTestCase test_cases[] = { // Insecure context - {false, "<img src='/image' attributionsrc>", nullptr}, - {false, "<script src='/script' attributionsrc></script>", nullptr}, + {kInsecureDocumentUrl, kSecureBaseURL, + "<img src='/image' attributionsrc>", nullptr}, + {kInsecureDocumentUrl, kSecureBaseURL, + "<script src='/script' attributionsrc></script>", nullptr}, // No attributionsrc attribute - {true, "<img src='/image'>", nullptr}, - {true, "<script src='/script'></script>", nullptr}, + {kSecureDocumentUrl, kSecureBaseURL, "<img src='/image'>", nullptr}, + {kSecureDocumentUrl, kSecureBaseURL, "<script src='/script'></script>", + nullptr}, // Irrelevant element type - {true, "<video poster='/image' attributionsrc>", nullptr}, - // Secure context, attributionsrc attribute - {true, "<img src='/image' attributionsrc>", + {kSecureDocumentUrl, kSecureBaseURL, + "<video poster='/image' attributionsrc>", nullptr}, + // Not potentially trustworthy reporting origin + {kSecureDocumentUrl, kInsecureBaseURL, + "<img src='/image' attributionsrc>", nullptr}, + {kSecureDocumentUrl, kInsecureBaseURL, + "<script src='/script' attributionsrc></script>", nullptr}, + // Secure context, potentially trustworthy reporting origin, + // attributionsrc attribute + {kSecureDocumentUrl, kSecureBaseURL, "<img src='/image' attributionsrc>", kAttributionEligibleEventSourceAndTrigger}, - {true, "<script src='/script' attributionsrc></script>", + {kSecureDocumentUrl, kSecureBaseURL, + "<script src='/script' attributionsrc></script>", kAttributionEligibleEventSourceAndTrigger}, };
diff --git a/third_party/blink/renderer/core/html/parser/preload_request.cc b/third_party/blink/renderer/core/html/parser/preload_request.cc index 244cbe7..129c4676 100644 --- a/third_party/blink/renderer/core/html/parser/preload_request.cc +++ b/third_party/blink/renderer/core/html/parser/preload_request.cc
@@ -8,6 +8,7 @@ #include "base/metrics/histogram_functions.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/frame/attribution_src_loader.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/settings.h" @@ -109,7 +110,12 @@ resource_request.SetFetchPriorityHint(fetch_priority_hint_); - if (is_attribution_reporting_eligible_img_or_script_) { + // Disable issue logging to avoid duplicates, since `CanRegister()` will be + // called again later. + if (is_attribution_reporting_eligible_img_or_script_ && + document->domWindow()->GetFrame()->GetAttributionSrcLoader()->CanRegister( + url, /*element=*/nullptr, + /*request_id=*/absl::nullopt, /*log_issues=*/false)) { resource_request.SetHttpHeaderField( http_names::kAttributionReportingEligible, kAttributionEligibleEventSourceAndTrigger);
diff --git a/third_party/blink/renderer/core/html/plugin_document.cc b/third_party/blink/renderer/core/html/plugin_document.cc index 98b26a4..adf2832 100644 --- a/third_party/blink/renderer/core/html/plugin_document.cc +++ b/third_party/blink/renderer/core/html/plugin_document.cc
@@ -107,9 +107,8 @@ auto* body = MakeGarbageCollected<HTMLBodyElement>(*GetDocument()); body->setAttribute(html_names::kStyleAttr, "height: 100%; width: 100%; overflow: hidden; margin: 0"); - body->SetInlineStyleProperty( - CSSPropertyID::kBackgroundColor, - *cssvalue::CSSColor::Create(background_color_.Rgb())); + body->SetInlineStyleProperty(CSSPropertyID::kBackgroundColor, + *cssvalue::CSSColor::Create(background_color_)); root_element->AppendChild(body); if (IsStopped()) { // Possibly detached by a mutation event listener installed in
diff --git a/third_party/blink/renderer/core/html/track/text_track_container.cc b/third_party/blink/renderer/core/html/track/text_track_container.cc index 333389a3..2a0939c 100644 --- a/third_party/blink/renderer/core/html/track/text_track_container.cc +++ b/third_party/blink/renderer/core/html/track/text_track_container.cc
@@ -38,6 +38,7 @@ #include "third_party/blink/renderer/core/layout/layout_video.h" #include "third_party/blink/renderer/core/resize_observer/resize_observer.h" #include "third_party/blink/renderer/core/resize_observer/resize_observer_entry.h" +#include "ui/accessibility/accessibility_features.h" namespace blink { @@ -222,7 +223,13 @@ if (!cue->track() || !cue->track()->IsRendered() || !cue->IsActive()) continue; - cue->UpdateDisplay(*this); + if (features::IsTextBasedAudioDescriptionEnabled() && + cue->track()->IsSpokenKind()) { + cue->UpdateSpeech(*this); + } else { + cue->UpdateDisplay(*this); + } + cue->UpdatePastAndFutureNodes(movie_time); }
diff --git a/third_party/blink/renderer/core/html/track/text_track_cue.h b/third_party/blink/renderer/core/html/track/text_track_cue.h index bc11866..ae5b9ad 100644 --- a/third_party/blink/renderer/core/html/track/text_track_cue.h +++ b/third_party/blink/renderer/core/html/track/text_track_cue.h
@@ -80,6 +80,9 @@ // already been added. virtual void UpdateDisplay(HTMLDivElement& container) = 0; + // Vocalizes text that reaches this method. + virtual void UpdateSpeech(HTMLDivElement& container) = 0; + // Marks the nodes of the display tree as past or future relative to // movieTime. If |updateDisplay| has not been called there is no display // tree and nothing is done.
diff --git a/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc b/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc index 1c8886e..510ef64 100644 --- a/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc +++ b/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc
@@ -746,6 +746,11 @@ display_tree_->remove(ASSERT_NO_EXCEPTION); } +void VTTCue::UpdateSpeech(HTMLDivElement& container) { + // TODO: handle vocalization + // Text to be vocalized can be accessed through the variable text_ +} + void VTTCue::UpdateDisplay(HTMLDivElement& container) { DCHECK(track() && track()->IsRendered() && IsActive());
diff --git a/third_party/blink/renderer/core/html/track/vtt/vtt_cue.h b/third_party/blink/renderer/core/html/track/vtt/vtt_cue.h index 764f97a..53000444 100644 --- a/third_party/blink/renderer/core/html/track/vtt/vtt_cue.h +++ b/third_party/blink/renderer/core/html/track/vtt/vtt_cue.h
@@ -136,6 +136,7 @@ DocumentFragment* getCueAsHTML(); void UpdateDisplay(HTMLDivElement& container) override; + void UpdateSpeech(HTMLDivElement& container) override; void UpdatePastAndFutureNodes(double movie_time) override;
diff --git a/third_party/blink/renderer/core/loader/image_loader.cc b/third_party/blink/renderer/core/loader/image_loader.cc index ef14123..f31294c 100644 --- a/third_party/blink/renderer/core/loader/image_loader.cc +++ b/third_party/blink/renderer/core/loader/image_loader.cc
@@ -504,9 +504,9 @@ if (IsA<HTMLImageElement>(GetElement()) && GetElement()->FastHasAttribute(html_names::kAttributionsrcAttr) && - CanRegisterAttributionInContext(frame, - To<HTMLImageElement>(GetElement()), - /*request_id=*/absl::nullopt)) { + frame->GetAttributionSrcLoader()->CanRegister( + url, To<HTMLImageElement>(GetElement()), + /*request_id=*/absl::nullopt)) { resource_request.SetHttpHeaderField( http_names::kAttributionReportingEligible, kAttributionEligibleEventSourceAndTrigger);
diff --git a/third_party/blink/renderer/core/loader/navigation_policy_test.cc b/third_party/blink/renderer/core/loader/navigation_policy_test.cc index 6a58caa..56bfb3d 100644 --- a/third_party/blink/renderer/core/loader/navigation_policy_test.cc +++ b/third_party/blink/renderer/core/loader/navigation_policy_test.cc
@@ -40,6 +40,7 @@ #include "third_party/blink/renderer/core/events/current_input_event.h" #include "third_party/blink/renderer/core/events/mouse_event.h" #include "third_party/blink/renderer/core/page/create_window.h" +#include "third_party/blink/renderer/platform/weborigin/kurl.h" namespace blink { @@ -244,7 +245,7 @@ for (const auto& test : kCases) { EXPECT_EQ(test.policy, NavigationPolicyForCreateWindow(GetWindowFeaturesFromString( - test.feature_string, nullptr /* dom_window */))) + test.feature_string, /*dom_window=*/nullptr, KURL()))) << "Testing '" << test.feature_string << "'"; } } @@ -270,7 +271,7 @@ for (const auto& test : kCases) { EXPECT_EQ(test.policy, NavigationPolicyForCreateWindow(GetWindowFeaturesFromString( - test.feature_string, nullptr /* dom_window */))) + test.feature_string, /*dom_window=*/nullptr, KURL()))) << "Testing '" << test.feature_string << "'"; } } @@ -295,7 +296,7 @@ for (const auto& test : kCases) { EXPECT_EQ(test.policy, NavigationPolicyForCreateWindow(GetWindowFeaturesFromString( - test.feature_string, nullptr /* dom_window */))) + test.feature_string, /*dom_window=*/nullptr, KURL()))) << "Testing '" << test.feature_string << "'"; } }
diff --git a/third_party/blink/renderer/core/page/create_window.cc b/third_party/blink/renderer/core/page/create_window.cc index 02438d58..7e73ad64 100644 --- a/third_party/blink/renderer/core/page/create_window.cc +++ b/third_party/blink/renderer/core/page/create_window.cc
@@ -66,7 +66,8 @@ } WebWindowFeatures GetWindowFeaturesFromString(const String& feature_string, - LocalDOMWindow* dom_window) { + LocalDOMWindow* dom_window, + const KURL& url) { WebWindowFeatures window_features; bool attribution_reporting_enabled = @@ -226,9 +227,10 @@ // If the impression could not be set, or if the value was empty, mark // attribution eligibility by adding an impression. if (!window_features.impression && - CanRegisterAttributionInContext(dom_window->GetFrame(), - /*element=*/nullptr, - /*request_id=*/absl::nullopt)) { + dom_window->GetFrame()->GetAttributionSrcLoader()->CanRegister( + url, + /*element=*/nullptr, + /*request_id=*/absl::nullopt)) { window_features.impression = blink::Impression(); } }
diff --git a/third_party/blink/renderer/core/page/create_window.h b/third_party/blink/renderer/core/page/create_window.h index 0f5e82ab..da595dc0 100644 --- a/third_party/blink/renderer/core/page/create_window.h +++ b/third_party/blink/renderer/core/page/create_window.h
@@ -33,6 +33,7 @@ namespace blink { class Frame; +class KURL; class LocalDOMWindow; class LocalFrame; struct FrameLoadRequest; @@ -43,7 +44,8 @@ CORE_EXPORT WebWindowFeatures GetWindowFeaturesFromString(const String& feature_string, - LocalDOMWindow* dom_window); + LocalDOMWindow* dom_window, + const KURL& url); } // namespace blink
diff --git a/third_party/blink/renderer/core/page/window_features_test.cc b/third_party/blink/renderer/core/page/window_features_test.cc index 4ea8b7c4..2c1e476 100644 --- a/third_party/blink/renderer/core/page/window_features_test.cc +++ b/third_party/blink/renderer/core/page/window_features_test.cc
@@ -1,11 +1,13 @@ // Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// + #include "third_party/blink/renderer/core/page/create_window.h" #include <gtest/gtest.h> + #include "third_party/blink/public/web/web_window_features.h" +#include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { @@ -28,9 +30,10 @@ }; for (const auto& test : kCases) { - EXPECT_EQ(test.noopener, GetWindowFeaturesFromString( - test.feature_string, nullptr /* dom_window */) - .noopener) + EXPECT_EQ(test.noopener, + GetWindowFeaturesFromString(test.feature_string, + /*dom_window=*/nullptr, KURL()) + .noopener) << "Testing '" << test.feature_string << "'"; } } @@ -61,7 +64,7 @@ for (const auto& test : kCases) { EXPECT_EQ(test.noreferrer, GetWindowFeaturesFromString(test.feature_string, - nullptr /* dom_window */) + /*dom_window=*/nullptr, KURL()) .noreferrer) << "Testing '" << test.feature_string << "'"; }
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index f834a23..5a1ebe5 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -2138,30 +2138,6 @@ return !clipper->HitTestClipContent(reference_box, location); } -bool PaintLayer::IntersectsDamageRect( - const PhysicalRect& layer_bounds, - const PhysicalRect& damage_rect, - const PhysicalOffset& offset_from_root) const { - // Always examine the canvas and the root. - // FIXME: Could eliminate the isDocumentElement() check if we fix background - // painting so that the LayoutView paints the root's background. - if (IsRootLayer() || GetLayoutObject().IsDocumentElement()) - return true; - - // If we aren't an inline flow, and our layer bounds do intersect the damage - // rect, then we can go ahead and return true. - LayoutView* view = GetLayoutObject().View(); - DCHECK(view); - if (view && !GetLayoutObject().IsLayoutInline()) { - if (layer_bounds.Intersects(damage_rect)) - return true; - } - - // Otherwise we need to compute the bounding box of this single layer and see - // if it intersects the damage rect. - return PhysicalBoundingBox(offset_from_root).Intersects(damage_rect); -} - PhysicalRect PaintLayer::LocalBoundingBox() const { PhysicalRect rect = GetLayoutObject().PhysicalVisualOverflowRect(); if (GetLayoutObject().IsEffectiveRootScroller() || IsRootLayer()) { @@ -2185,16 +2161,6 @@ return result; } -PhysicalRect PaintLayer::FragmentsBoundingBox( - const PaintLayer* ancestor_layer) const { - if (!EnclosingPaginationLayer()) - return PhysicalBoundingBox(ancestor_layer); - - PhysicalRect result = LocalBoundingBox(); - ConvertFromFlowThreadToVisualBoundingBoxInAncestor(ancestor_layer, result); - return result; -} - void PaintLayer::ExpandRectForSelfPaintingDescendants( PhysicalRect& result) const { // If we're locked, then the subtree does not contribute painted output.
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h index 3a53065..b96c387 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.h +++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -340,15 +340,10 @@ HitTestResult&, const PhysicalRect& hit_test_area); - bool IntersectsDamageRect(const PhysicalRect& layer_bounds, - const PhysicalRect& damage_rect, - const PhysicalOffset& offset_from_root) const; - // Bounding box relative to some ancestor layer. Pass offsetFromRoot if known. PhysicalRect PhysicalBoundingBox( const PhysicalOffset& offset_from_root) const; PhysicalRect PhysicalBoundingBox(const PaintLayer* ancestor_layer) const; - PhysicalRect FragmentsBoundingBox(const PaintLayer* ancestor_layer) const; // Static position is set in parent's coordinate space. LayoutUnit StaticInlinePosition() const { return static_inline_position_; }
diff --git a/third_party/blink/renderer/core/scheduler_integration_tests/virtual_time_test.cc b/third_party/blink/renderer/core/scheduler_integration_tests/virtual_time_test.cc index c8c86f6..693bd0c 100644 --- a/third_party/blink/renderer/core/scheduler_integration_tests/virtual_time_test.cc +++ b/third_party/blink/renderer/core/scheduler_integration_tests/virtual_time_test.cc
@@ -48,10 +48,12 @@ ScriptExecutionCallbackHelper callback_helper; WebScriptSource source(script_source); WebView().MainFrame()->ToWebLocalFrame()->RequestExecuteScript( - DOMWrapperWorld::kMainWorldId, base::make_span(&source, 1), false, - WebLocalFrame::kSynchronous, &callback_helper, + DOMWrapperWorld::kMainWorldId, base::make_span(&source, 1), + mojom::blink::UserActivationOption::kDoNotActivate, + mojom::blink::EvaluationTiming::kSynchronous, + mojom::blink::LoadEventBlockingOption::kDoNotBlock, &callback_helper, BackForwardCacheAware::kAllow, - WebLocalFrame::PromiseBehavior::kDontWait); + mojom::blink::PromiseResultOption::kDoNotWait); return callback_helper.Result(); }
diff --git a/third_party/blink/renderer/core/script/script_loader.cc b/third_party/blink/renderer/core/script/script_loader.cc index 34bef140..96148a1 100644 --- a/third_party/blink/renderer/core/script/script_loader.cc +++ b/third_party/blink/renderer/core/script/script_loader.cc
@@ -545,23 +545,14 @@ potentially_render_blocking ? RenderBlockingBehavior::kBlocking : RenderBlockingBehavior::kNonBlocking; - // TODO(apaseltiner): Propagate the element instead of passing nullptr. - const auto attribution_reporting_eligibility = - element_->HasAttributionsrcAttribute() && - CanRegisterAttributionInContext(context_window->GetFrame(), - /*element=*/nullptr, - /*request_id=*/absl::nullopt) - ? ScriptFetchOptions::AttributionReportingEligibility::kEligible - : ScriptFetchOptions::AttributionReportingEligibility::kIneligible; - // <spec step="27">Let options be a script fetch options whose cryptographic // nonce is cryptographic nonce, integrity metadata is integrity metadata, // parser metadata is parser metadata, credentials mode is module script // credentials mode, and referrer policy is referrer policy.</spec> - ScriptFetchOptions options( - nonce, integrity_metadata, integrity_attr, parser_state, credentials_mode, - referrer_policy, fetch_priority_hint, render_blocking_behavior, - RejectCoepUnsafeNone(false), attribution_reporting_eligibility); + ScriptFetchOptions options(nonce, integrity_metadata, integrity_attr, + parser_state, credentials_mode, referrer_policy, + fetch_priority_hint, render_blocking_behavior, + RejectCoepUnsafeNone(false)); // <spec step="28">Let settings object be el's node document's relevant // settings object.</spec> @@ -647,6 +638,16 @@ return nullptr; } + // TODO(apaseltiner): Propagate the element instead of passing nullptr. + if (element_->HasAttributionsrcAttribute() && + context_window->GetFrame()->GetAttributionSrcLoader()->CanRegister( + url, + /*element=*/nullptr, + /*request_id=*/absl::nullopt)) { + options.SetAttributionReportingEligibility( + ScriptFetchOptions::AttributionReportingEligibility::kEligible); + } + // <spec step="29.6">If el is potentially render-blocking, then block // rendering on el.</spec> if (potentially_render_blocking &&
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc index 4b4f6a3..b158b7f 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc +++ b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc
@@ -20,6 +20,7 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_cable_authentication_data.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_cable_registration_data.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_identity_credential_logout_r_ps_request.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_identity_provider.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_public_key_credential_creation_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_public_key_credential_descriptor.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_public_key_credential_parameters.h" @@ -49,6 +50,8 @@ using blink::mojom::blink::CredentialInfo; using blink::mojom::blink::CredentialInfoPtr; using blink::mojom::blink::CredentialType; +using blink::mojom::blink::IdentityProvider; +using blink::mojom::blink::IdentityProviderPtr; using blink::mojom::blink::LargeBlobSupport; using blink::mojom::blink::LogoutRpsRequest; using blink::mojom::blink::LogoutRpsRequestPtr; @@ -691,4 +694,16 @@ blink_value.sameOriginWithAncestors()); } +// static +IdentityProviderPtr +TypeConverter<IdentityProviderPtr, blink::IdentityProvider>::Convert( + const blink::IdentityProvider& provider) { + auto mojo_provider = IdentityProvider::New(); + + mojo_provider->config_url = blink::KURL(provider.configURL()); + mojo_provider->client_id = provider.clientId(); + mojo_provider->nonce = provider.nonce(); + return mojo_provider; +} + } // namespace mojo
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h index 751d070..6b320da1ca 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h +++ b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h
@@ -20,6 +20,7 @@ class CableRegistrationData; class Credential; class IdentityCredentialLogoutRPsRequest; +class IdentityProvider; class PublicKeyCredentialCreationOptions; class PublicKeyCredentialDescriptor; class PublicKeyCredentialParameters; @@ -190,6 +191,13 @@ const blink::RemoteDesktopClientOverride&); }; +template <> +struct TypeConverter<blink::mojom::blink::IdentityProviderPtr, + blink::IdentityProvider> { + static blink::mojom::blink::IdentityProviderPtr Convert( + const blink::IdentityProvider&); +}; + } // namespace mojo #endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CREDENTIALMANAGEMENT_CREDENTIAL_MANAGER_TYPE_CONVERTERS_H_
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc index bea385e6..c0bea7dc 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc +++ b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
@@ -1210,7 +1210,6 @@ // Some of this has not been spec'd yet. KURL provider_url(provider->configURL()); String client_id = provider->clientId(); - String nonce = provider->getNonceOr(""); if (!provider_url.IsValid() || client_id == "") { resolver->Reject(MakeGarbageCollected<DOMException>( @@ -1235,12 +1234,14 @@ options->signal()->AddAlgorithm(WTF::Bind(&AbortIdentityCredentialRequest, WrapPersistent(script_state))); } + mojom::blink::IdentityProviderPtr identity_provider = + blink::mojom::blink::IdentityProvider::From(*provider); bool prefer_auto_sign_in = options->identity()->preferAutoSignIn(); auto* auth_request = CredentialManagerProxy::From(script_state)->FederatedAuthRequest(); auth_request->RequestToken( - provider_url, client_id, nonce, prefer_auto_sign_in, + std::move(identity_provider), prefer_auto_sign_in, WTF::Bind(&OnRequestToken, WrapPersistent(resolver), provider_url, client_id, WrapPersistent(options)));
diff --git a/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc b/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc index e30f7ae5..db9b9d38 100644 --- a/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc +++ b/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc
@@ -8,7 +8,6 @@ #include "base/bind.h" #include "base/check.h" -#include "base/numerics/safe_conversions.h" #include "skia/ext/image_operations.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h" #include "third_party/blink/public/platform/interface_registry.h" @@ -59,12 +58,29 @@ return DecodeImageData(data, mime_type, preferred_size); } -// Images are allowed only if the following criteria is true: -// If |max_image_size| == 0, denoting that no upper limit is provided for image -// size. -// If size of image (width and height) is <= max_image_size. -// For all other cases, the image is filtered out. -void FilterImagesBasedOnMaximalSize( +// Proportionally resizes the |image| to fit in a box of size +// |max_image_size|. +SkBitmap ResizeImage(const SkBitmap& image, uint32_t max_image_size) { + if (max_image_size == 0) + return image; + uint32_t max_dimension = std::max(image.width(), image.height()); + if (max_dimension <= max_image_size) + return image; + // Proportionally resize the minimal image to fit in a box of size + // max_image_size. + return skia::ImageOperations::Resize( + image, skia::ImageOperations::RESIZE_BEST, + static_cast<uint32_t>(image.width()) * max_image_size / max_dimension, + static_cast<uint32_t>(image.height()) * max_image_size / max_dimension); +} + +// Filters the array of bitmaps, removing all images that do not fit in a box of +// size |max_image_size|. Returns the result if it is not empty. Otherwise, +// find the smallest image in the array and resize it proportionally to fit +// in a box of size |max_image_size|. +// Sets |original_image_sizes| to the sizes of |images| before resizing. Both +// output vectors are guaranteed to have the same size. +void FilterAndResizeImagesForMaximalSize( const WTF::Vector<SkBitmap>& unfiltered, uint32_t max_image_size, WTF::Vector<SkBitmap>* images, @@ -75,14 +91,38 @@ if (unfiltered.IsEmpty()) return; - for (const SkBitmap& image : unfiltered) { - if ((max_image_size == 0) || - (base::checked_cast<uint32_t>(image.width()) <= max_image_size && - base::checked_cast<uint32_t>(image.height()) <= max_image_size)) { + if (max_image_size == 0) + max_image_size = std::numeric_limits<uint32_t>::max(); + + const SkBitmap* min_image = nullptr; + uint32_t min_image_size = std::numeric_limits<uint32_t>::max(); + // Filter the images by |max_image_size|, and also identify the smallest image + // in case all the images are bigger than |max_image_size|. + for (auto* it = unfiltered.begin(); it != unfiltered.end(); ++it) { + const SkBitmap& image = *it; + uint32_t current_size = std::max(it->width(), it->height()); + if (current_size < min_image_size) { + min_image = ℑ + min_image_size = current_size; + } + if (static_cast<uint32_t>(image.width()) <= max_image_size && + static_cast<uint32_t>(image.height()) <= max_image_size) { images->push_back(image); original_image_sizes->push_back(gfx::Size(image.width(), image.height())); } } + DCHECK(min_image); + if (images->size()) + return; + // Proportionally resize the minimal image to fit in a box of size + // |max_image_size|. + SkBitmap resized = ResizeImage(*min_image, max_image_size); + // Drop null or empty SkBitmap. + if (resized.drawsNothing()) + return; + images->push_back(resized); + original_image_sizes->push_back( + gfx::Size(min_image->width(), min_image->height())); } } // namespace @@ -163,8 +203,8 @@ const WTF::Vector<SkBitmap>& images) { WTF::Vector<SkBitmap> result_images; WTF::Vector<gfx::Size> result_original_image_sizes; - FilterImagesBasedOnMaximalSize(images, max_image_size, &result_images, - &result_original_image_sizes); + FilterAndResizeImagesForMaximalSize(images, max_image_size, &result_images, + &result_original_image_sizes); DCHECK_EQ(result_images.size(), result_original_image_sizes.size());
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc index efb6d14..793c9a64 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc
@@ -161,7 +161,12 @@ if (track->kind() == track->CaptionsKeyword()) { track_kind_marker->SetShadowPseudoId(AtomicString( "-internal-media-controls-text-track-list-kind-captions")); + } else if (track->kind() == track->DescriptionsKeyword()) { + track_kind_marker->SetShadowPseudoId(AtomicString( + "-internal-media-controls-text-track-list-kind-descriptions")); } else { + // Aside from Captions and Descriptions, Subtitles is the only other + // supported keyword. DCHECK_EQ(track->kind(), track->SubtitlesKeyword()); track_kind_marker->SetShadowPseudoId(AtomicString( "-internal-media-controls-text-track-list-kind-subtitles"));
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index 209333a..12e173e 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1008,6 +1008,7 @@ "graphics/paint/paint_canvas.h", "graphics/paint/paint_chunk.cc", "graphics/paint/paint_chunk.h", + "graphics/paint/paint_chunk_subset.cc", "graphics/paint/paint_chunk_subset.h", "graphics/paint/paint_chunker.cc", "graphics/paint/paint_chunker.h",
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index 23353f7..323bfe6d 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -647,6 +647,10 @@ RuntimeEnabledFeatures::SetFedCmIframeSupportEnabled(enable); } +void WebRuntimeFeatures::EnableFedCmMultipleIdentityProviders(bool enable) { + RuntimeEnabledFeatures::SetFedCmMultipleIdentityProvidersEnabled(enable); +} + void WebRuntimeFeatures::EnableDocumentTransition(bool enable) { RuntimeEnabledFeatures::SetDocumentTransitionEnabled(enable); }
diff --git a/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc b/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc index 56d57e3..8df0ae27 100644 --- a/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc +++ b/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc
@@ -83,10 +83,9 @@ FontCustomPlatformData::~FontCustomPlatformData() = default; -// TODO(crbug.com/1205794): Optical sizing should use specified size, instead of -// zoomed size. FontPlatformData FontCustomPlatformData::GetFontPlatformData( float size, + float adjusted_specified_size, bool bold, bool italic, const FontSelectionRequest& selection_request, @@ -189,7 +188,7 @@ if (!explicit_opsz_configured) { if (optical_sizing == kAutoOpticalSizing) { SkFontArguments::VariationPosition::Coordinate opsz_coordinate = { - kOpszTag, SkFloatToScalar(size)}; + kOpszTag, SkFloatToScalar(adjusted_specified_size)}; variation.push_back(opsz_coordinate); } else if (optical_sizing == kNoneOpticalSizing) { // Explicitly set default value to avoid automatic application of
diff --git a/third_party/blink/renderer/platform/fonts/font_custom_platform_data.h b/third_party/blink/renderer/platform/fonts/font_custom_platform_data.h index 6a5efce6..e1eeb46 100644 --- a/third_party/blink/renderer/platform/fonts/font_custom_platform_data.h +++ b/third_party/blink/renderer/platform/fonts/font_custom_platform_data.h
@@ -63,8 +63,13 @@ FontCustomPlatformData& operator=(const FontCustomPlatformData&) = delete; ~FontCustomPlatformData(); + // The size argument should come from EffectiveFontSize() and + // adjusted_specified_size should come from AdjustedSpecifiedSize() of + // FontDescription. The latter is needed for correctly applying + // font-optical-sizing: auto; independent of zoom level. FontPlatformData GetFontPlatformData( float size, + float adjusted_specified_size, bool bold, bool italic, const FontSelectionRequest&,
diff --git a/third_party/blink/renderer/platform/fonts/font_description.cc b/third_party/blink/renderer/platform/fonts/font_description.cc index dd2dfc0..d59e4b24 100644 --- a/third_party/blink/renderer/platform/fonts/font_description.cc +++ b/third_party/blink/renderer/platform/fonts/font_description.cc
@@ -235,6 +235,14 @@ FontCacheKey::PrecisionMultiplier(); } +float FontDescription::AdjustedSpecifiedSize() const { + if (HasSizeAdjust() || fields_.has_size_adjust_descriptor_) { + return SpecifiedSize() * (AdjustedSize() / ComputedSize()); + } else { + return SpecifiedSize(); + } +} + FontDescription FontDescription::SizeAdjustedFontDescription( float size_adjust) const { // TODO(crbug.com/451346): The font-size-adjust property and size-adjust
diff --git a/third_party/blink/renderer/platform/fonts/font_description.h b/third_party/blink/renderer/platform/fonts/font_description.h index adcd990e..9167d5d 100644 --- a/third_party/blink/renderer/platform/fonts/font_description.h +++ b/third_party/blink/renderer/platform/fonts/font_description.h
@@ -186,6 +186,11 @@ return Size(KeywordSize(), SpecifiedSize(), IsAbsoluteSize()); } float SpecifiedSize() const { return specified_size_; } + // Returns the result of applying font-size-adjust to the specified size. This + // is useful as an input to optical sizing and takes zooming out of the + // equation for determining the font size to be used for font-optical-sizing: + // auto;. + float AdjustedSpecifiedSize() const; float ComputedSize() const { return computed_size_; } // TODO(xiaochengh): The functions and members for size-adjust descriptor and
diff --git a/third_party/blink/renderer/platform/graphics/compositing/pending_layer.cc b/third_party/blink/renderer/platform/graphics/compositing/pending_layer.cc index a86d04f93..5949d54a 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/pending_layer.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/pending_layer.cc
@@ -140,16 +140,7 @@ result->SetObject("property_tree_state", GetPropertyTreeState().ToJSON()); result->SetArray("offset_of_decomposited_transforms", VectorAsJSONArray(offset_of_decomposited_transforms_)); - std::unique_ptr<JSONArray> json_chunks = std::make_unique<JSONArray>(); - for (auto it = chunks_.begin(); it != chunks_.end(); ++it) { - StringBuilder sb; - sb.Append("index="); - sb.AppendNumber(it.IndexInPaintArtifact()); - sb.Append(" "); - sb.Append(it->ToString(chunks_.GetPaintArtifact())); - json_chunks->PushString(sb.ToString()); - } - result->SetArray("paint_chunks", std::move(json_chunks)); + result->SetArray("paint_chunks", chunks_.ToJSON()); result->SetBoolean("draws_content", DrawsContent()); return result; }
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc index 380b071..b4909dc 100644 --- a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc +++ b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
@@ -62,4 +62,38 @@ return id.ToString(); } +std::unique_ptr<JSONArray> PaintArtifact::ToJSON() const { + auto json = std::make_unique<JSONArray>(); + AppendChunksAsJSON(0, chunks_.size(), *json, 0); + return json; +} + +void PaintArtifact::AppendChunksAsJSON(wtf_size_t start_chunk_index, + wtf_size_t end_chunk_index, + JSONArray& json_array, + unsigned flags) const { + DCHECK_GT(end_chunk_index, start_chunk_index); + for (auto i = start_chunk_index; i < end_chunk_index; ++i) { + const auto& chunk = chunks_[i]; + auto json_object = std::make_unique<JSONObject>(); + + json_object->SetString("chunk", ClientDebugName(chunk.id.client_id) + " " + + chunk.id.ToString(*this)); + json_object->SetString("state", chunk.properties.ToString()); + json_object->SetString("bounds", String(chunk.bounds.ToString())); +#if DCHECK_IS_ON() + if (flags & DisplayItemList::kShowPaintRecords) + json_object->SetString("chunkData", chunk.ToString(*this)); + json_object->SetArray("displayItems", DisplayItemList::DisplayItemsAsJSON( + *this, chunk.begin_index, + DisplayItemsInChunk(i), flags)); +#endif + json_array.PushObject(std::move(json_object)); + } +} + +std::ostream& operator<<(std::ostream& os, const PaintArtifact& artifact) { + return os << artifact.ToJSON()->ToPrettyJSONString().Utf8(); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h index 0cb3b06..29fe1b1 100644 --- a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h +++ b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
@@ -67,6 +67,12 @@ DOMNodeId ClientOwnerNodeId(DisplayItemClientId) const; String IdAsString(const DisplayItem::Id& id) const; + std::unique_ptr<JSONArray> ToJSON() const; + void AppendChunksAsJSON(wtf_size_t start_chunk_index, + wtf_size_t end_chunk_index, + JSONArray&, + unsigned flags) const; + private: struct ClientDebugInfo { String name; @@ -80,6 +86,8 @@ DebugInfo debug_info_; }; +PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const PaintArtifact&); + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_ARTIFACT_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.cc b/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.cc new file mode 100644 index 0000000..45e9fe6 --- /dev/null +++ b/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.cc
@@ -0,0 +1,28 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h" + +#include "third_party/blink/renderer/platform/wtf/text/string_builder.h" + +namespace blink { + +std::unique_ptr<JSONArray> PaintChunkSubset::ToJSON() const { + auto json = std::make_unique<JSONArray>(); + for (auto it = begin(); it != end(); ++it) { + StringBuilder sb; + sb.Append("index="); + sb.AppendNumber(it.IndexInPaintArtifact()); + sb.Append(" "); + sb.Append(it->ToString(GetPaintArtifact())); + json->PushString(sb.ToString()); + } + return json; +} + +std::ostream& operator<<(std::ostream& os, const PaintChunkSubset& subset) { + return os << subset.ToJSON()->ToPrettyJSONString().Utf8(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h b/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h index 08719c3..38e7f62 100644 --- a/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h +++ b/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h
@@ -149,6 +149,8 @@ return sizeof(*this) + subset_indices_.CapacityInBytes(); } + std::unique_ptr<JSONArray> ToJSON() const; + private: bool UsesSubsetIndices() const { return begin_index_ == kNotFound; } @@ -162,6 +164,9 @@ using PaintChunkIterator = PaintChunkSubset::Iterator; +PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, + const PaintChunkSubset&); + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_CHUNK_SUBSET_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc b/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc index d3c0b5b..e910b43 100644 --- a/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc +++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc
@@ -32,7 +32,6 @@ private: std::unique_ptr<JSONObject> SubsequenceAsJSONObjectRecursive(); std::unique_ptr<JSONArray> ChunksAsJSONArrayRecursive(wtf_size_t, wtf_size_t); - void AppendChunksAsJSON(wtf_size_t, wtf_size_t, JSONArray&); const PaintArtifact& artifact_; const Vector<SubsequenceMarkers>& subsequences_; @@ -48,9 +47,9 @@ auto json_object = std::make_unique<JSONObject>(); json_object->SetString( - "subsequence", - String::Format("client: 0x%" PRIuPTR " ", subsequence.client_id) + - artifact_.ClientDebugName(subsequence.client_id)); + "subsequence", String::Format("client: %p ", reinterpret_cast<void*>( + subsequence.client_id)) + + artifact_.ClientDebugName(subsequence.client_id)); json_object->SetArray( "chunks", ChunksAsJSONArrayRecursive(subsequence.start_chunk_index, subsequence.end_chunk_index)); @@ -76,44 +75,20 @@ DCHECK_GE(subsequence.start_chunk_index, chunk_index); DCHECK_LE(subsequence.end_chunk_index, end_chunk_index); - if (chunk_index < subsequence.start_chunk_index) - AppendChunksAsJSON(chunk_index, subsequence.start_chunk_index, *array); + if (chunk_index < subsequence.start_chunk_index) { + artifact_.AppendChunksAsJSON(chunk_index, subsequence.start_chunk_index, + *array, flags_); + } array->PushObject(SubsequenceAsJSONObjectRecursive()); chunk_index = subsequence.end_chunk_index; } if (chunk_index < end_chunk_index) - AppendChunksAsJSON(chunk_index, end_chunk_index, *array); + artifact_.AppendChunksAsJSON(chunk_index, end_chunk_index, *array, flags_); return array; } -void PaintController::PaintArtifactAsJSON::AppendChunksAsJSON( - wtf_size_t start_chunk_index, - wtf_size_t end_chunk_index, - JSONArray& json_array) { - DCHECK_GT(end_chunk_index, start_chunk_index); - for (auto i = start_chunk_index; i < end_chunk_index; ++i) { - const auto& chunk = artifact_.PaintChunks()[i]; - auto json_object = std::make_unique<JSONObject>(); - - json_object->SetString("chunk", - artifact_.ClientDebugName(chunk.id.client_id) + " " + - chunk.id.ToString(artifact_)); - json_object->SetString("state", chunk.properties.ToString()); - json_object->SetString("bounds", String(chunk.bounds.ToString())); - if (flags_ & DisplayItemList::kShowPaintRecords) - json_object->SetString("chunkData", chunk.ToString(artifact_)); - - json_object->SetArray("displayItems", - DisplayItemList::DisplayItemsAsJSON( - artifact_, chunk.begin_index, - artifact_.DisplayItemsInChunk(i), flags_)); - - json_array.PushObject(std::move(json_object)); - } -} - void PaintController::ShowDebugDataInternal( DisplayItemList::JsonFlags flags) const { auto current_list_flags = flags;
diff --git a/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h b/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h index 670ef46..ad7cc90 100644 --- a/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h +++ b/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h
@@ -46,19 +46,16 @@ referrer_policy_(network::mojom::ReferrerPolicy::kDefault), fetch_priority_hint_(mojom::blink::FetchPriorityHint::kAuto) {} - ScriptFetchOptions( - const String& nonce, - const IntegrityMetadataSet& integrity_metadata, - const String& integrity_attribute, - ParserDisposition parser_state, - network::mojom::CredentialsMode credentials_mode, - network::mojom::ReferrerPolicy referrer_policy, - mojom::blink::FetchPriorityHint fetch_priority_hint, - RenderBlockingBehavior render_blocking_behavior, - RejectCoepUnsafeNone reject_coep_unsafe_none = - RejectCoepUnsafeNone(false), - AttributionReportingEligibility attribution_reporting_eligibility = - AttributionReportingEligibility::kIneligible) + ScriptFetchOptions(const String& nonce, + const IntegrityMetadataSet& integrity_metadata, + const String& integrity_attribute, + ParserDisposition parser_state, + network::mojom::CredentialsMode credentials_mode, + network::mojom::ReferrerPolicy referrer_policy, + mojom::blink::FetchPriorityHint fetch_priority_hint, + RenderBlockingBehavior render_blocking_behavior, + RejectCoepUnsafeNone reject_coep_unsafe_none = + RejectCoepUnsafeNone(false)) : nonce_(nonce), integrity_metadata_(integrity_metadata), integrity_attribute_(integrity_attribute), @@ -67,8 +64,7 @@ referrer_policy_(referrer_policy), fetch_priority_hint_(fetch_priority_hint), render_blocking_behavior_(render_blocking_behavior), - reject_coep_unsafe_none_(reject_coep_unsafe_none), - attribution_reporting_eligibility_(attribution_reporting_eligibility) {} + reject_coep_unsafe_none_(reject_coep_unsafe_none) {} ~ScriptFetchOptions() = default; const String& Nonce() const { return nonce_; } @@ -95,6 +91,11 @@ return render_blocking_behavior_; } + void SetAttributionReportingEligibility( + AttributionReportingEligibility eligibility) { + attribution_reporting_eligibility_ = eligibility; + } + // https://html.spec.whatwg.org/C/#fetch-a-classic-script // Steps 1 and 3. FetchParameters CreateFetchParameters( @@ -135,7 +136,9 @@ RejectCoepUnsafeNone(false); // https://wicg.github.io/attribution-reporting-api - const AttributionReportingEligibility attribution_reporting_eligibility_ = + // TODO(crbug.com/1338976): make this member const once the attributionsrc + // spec is drafted. + AttributionReportingEligibility attribution_reporting_eligibility_ = AttributionReportingEligibility::kIneligible; };
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 43635dd..f30a8dad 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1004,6 +1004,10 @@ status: "test", }, { + name: "FedCmMultipleIdentityProviders", + status: "test", + }, + { name: "FencedFrames", // This helps enable and expose the <fencedframe> element, but note that // blink::features::kFencedFrames must be enabled as well, similar to
diff --git a/third_party/blink/renderer/platform/testing/font_test_helpers.cc b/third_party/blink/renderer/platform/testing/font_test_helpers.cc index d297fe29..953b8ea5 100644 --- a/third_party/blink/renderer/platform/testing/font_test_helpers.cc +++ b/third_party/blink/renderer/platform/testing/font_test_helpers.cc
@@ -51,6 +51,7 @@ {NormalWeightValue(), NormalWeightValue()}); FontPlatformData platform_data = custom_platform_data_->GetFontPlatformData( font_description.EffectiveFontSize(), + font_description.AdjustedSpecifiedSize(), font_description.IsSyntheticBold() && font_description.SyntheticBoldAllowed(), font_description.IsSyntheticItalic() &&
diff --git a/third_party/blink/renderer/platform/text/segmented_string.cc b/third_party/blink/renderer/platform/text/segmented_string.cc index d3d71e0..39dc87da 100644 --- a/third_party/blink/renderer/platform/text/segmented_string.cc +++ b/third_party/blink/renderer/platform/text/segmented_string.cc
@@ -124,6 +124,24 @@ Prepend(s.current_string_, type); } +void SegmentedString::Advance(unsigned num_chars, + unsigned num_lines, + int current_column) { + SECURITY_DCHECK(num_chars <= length()); + current_line_ += num_lines; + while (num_chars) { + num_chars -= current_string_.Advance(num_chars); + if (num_chars) { + // AdvanceSubstring() assumes one char is remaining. + DCHECK_EQ(current_string_.length(), 1); + AdvanceSubstring(); + --num_chars; + } + } + number_of_characters_consumed_prior_to_current_line_ = + NumberOfCharactersConsumed() - current_column; +} + UChar SegmentedString::AdvanceSubstring() { number_of_characters_consumed_prior_to_current_string_ += current_string_.NumberOfCharactersConsumed() + 1;
diff --git a/third_party/blink/renderer/platform/text/segmented_string.h b/third_party/blink/renderer/platform/text/segmented_string.h index 7bcf501..386e637 100644 --- a/third_party/blink/renderer/platform/text/segmented_string.h +++ b/third_party/blink/renderer/platform/text/segmented_string.h
@@ -116,6 +116,18 @@ return data_.string8_ptr < data_last_char_; } + // Advances up to `delta` characters, returning how many characters were + // advanced. This will not advance past the last character. + unsigned Advance(unsigned delta) { + DCHECK_NE(0, length()); + delta = std::min(static_cast<unsigned>(length()) - 1, delta); + if (is_8bit_) + data_.string8_ptr += delta; + else + data_.string16_ptr += delta; + return delta; + } + ALWAYS_INLINE UChar Advance() { return is_8bit_ ? *++data_.string8_ptr : *++data_.string16_ptr; } @@ -216,6 +228,12 @@ return LookAheadInline(string, kTextCaseASCIIInsensitive); } + // Used to advance by multiple characters. Specifically this advances by + // `num_chars` and `num_lines`. This function advances without analyzing the + // input string in anyway. As a result, the caller must know `num_lines` and + // `current_column`. + void Advance(unsigned num_chars, unsigned num_lines, int current_column); + ALWAYS_INLINE UChar Advance() { if (LIKELY(current_string_.CanAdvance())) { return current_string_.Advance();
diff --git a/third_party/blink/renderer/platform/text/segmented_string_test.cc b/third_party/blink/renderer/platform/text/segmented_string_test.cc index 48b6d05..53ed801 100644 --- a/third_party/blink/renderer/platform/text/segmented_string_test.cc +++ b/third_party/blink/renderer/platform/text/segmented_string_test.cc
@@ -104,4 +104,42 @@ EXPECT_EQ(s1.NumberOfCharactersConsumed(), 3); } +TEST(SegmentedStringTest, AdvanceCurrentString) { + SegmentedString s("0123456789"); + + s.Advance(4, 0, 4); + EXPECT_EQ(6u, s.length()); + EXPECT_EQ(4, s.NumberOfCharactersConsumed()); + EXPECT_EQ(4, s.CurrentColumn().ZeroBasedInt()); + EXPECT_EQ(0, s.CurrentLine().ZeroBasedInt()); + EXPECT_EQ('4', static_cast<char>(s.CurrentChar())); +} + +TEST(SegmentedStringTest, AdvanceThroughMultipleStrings) { + SegmentedString s("a"); + s.Append(SegmentedString("b")); + s.Append(SegmentedString("c")); + s.Advance(2, 0, 0); + EXPECT_EQ(1u, s.length()); + EXPECT_EQ(2, s.NumberOfCharactersConsumed()); + EXPECT_EQ(0, s.CurrentColumn().ZeroBasedInt()); + EXPECT_EQ(0, s.CurrentLine().ZeroBasedInt()); + EXPECT_EQ('c', static_cast<char>(s.CurrentChar())); +} + +TEST(SegmentedStringTest, AdvanceThroughNextString) { + SegmentedString s("0123456789"); + s.Append(SegmentedString("\nabcdefg")); + + // Advance through the first character + s.Advance(); + // Advance through first string. + s.Advance(11, 1, 2); + EXPECT_EQ(6u, s.length()); + EXPECT_EQ(12, s.NumberOfCharactersConsumed()); + EXPECT_EQ(2, s.CurrentColumn().ZeroBasedInt()); + EXPECT_EQ(1, s.CurrentLine().ZeroBasedInt()); + EXPECT_EQ('b', static_cast<char>(s.CurrentChar())); +} + } // namespace blink
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py index 64254bd6..1daba38 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py +++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py
@@ -537,24 +537,12 @@ test_flag_pairs_to_suffixes[test, flag_spec].update( self._suffixes_for_actual_failures(test, build, step_name)) - suffixes_flag_spec = collections.defaultdict(set) - test_list = collections.defaultdict(list) + optimize_commands = [] for (test, flag_spec), suffixes in test_flag_pairs_to_suffixes.items(): + # No need to optimize baselines for a test with no failures. if not suffixes: continue - if flag_spec is None: - flag_spec = 'default' - - suffixes_flag_spec[flag_spec].update(suffixes) - test_list[flag_spec].append(test) - - optimize_commands = collections.defaultdict(lambda: ([], '')) - cwd = self._tool.git().checkout_root - path_to_blink_tool = self._tool.path() - - # Build one optimize-baselines invocation command for each flag_spec. - # All the tests in the test list will be optimized iteratively. - for flag_spec, test_list_flag in test_list.items(): + path_to_blink_tool = self._tool.path() command = [ self._tool.executable, path_to_blink_tool, @@ -566,15 +554,11 @@ ] if verbose: command.append('--verbose') - if flag_spec != 'default': + if flag_spec: command.extend(['--flag-specific', flag_spec]) - command.extend([ - '--suffixes', ','.join(sorted(suffixes_flag_spec[flag_spec])) - ]) - for test in test_list_flag: - command.append(test) - - optimize_commands[flag_spec] = (command, cwd) + command.extend(['--suffixes', ','.join(sorted(suffixes)), test]) + cwd = self._tool.git().checkout_root + optimize_commands.append((command, cwd)) return optimize_commands @@ -668,14 +652,9 @@ self._update_expectations_files(lines_to_remove) if options.optimize: - optimize_commands = self._optimize_commands( - test_baseline_set, options.verbose, options.resultDB) - - for _, (cmd, cwd) in optimize_commands.items(): - output = self._tool.executive.run_command(cmd, cwd) - # log stderr if any. - for line in output[1]: - print(line) + self._run_in_parallel( + self._optimize_commands(test_baseline_set, options.verbose, + options.resultDB)) self._tool.git().add_list(self.unstaged_baselines())
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py index 48292e063..8dba493 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py +++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py
@@ -649,7 +649,7 @@ '--step-name', 'blink_web_tests (with patch)', ]], - [ + [[ 'python', 'echo', 'optimize-baselines', @@ -657,7 +657,7 @@ '--suffixes', 'wav', 'one/flaky-fail.html', - ]]) + ]]]) def test_rebaseline_command_invocations_multiple_steps(self): """Test the rebaseline tool handles multiple steps on the same builder. @@ -700,20 +700,21 @@ 'not_site_per_process_blink_web_tests (with patch)' ], ]) - print(self.tool.executive.calls) - self.assertEqual(self.tool.executive.calls[2], [ - 'python', 'echo', 'optimize-baselines', '--no-manifest-update', - '--suffixes', 'txt', 'one/text-fail.html' - ]) - self.assertEqual(self.tool.executive.calls[3], [ - 'python', 'echo', 'optimize-baselines', '--no-manifest-update', - '--flag-specific', 'disable-layout-ng', '--suffixes', 'txt', - 'one/text-fail.html' - ]) - self.assertEqual(self.tool.executive.calls[4], [ - 'python', 'echo', 'optimize-baselines', '--no-manifest-update', - '--flag-specific', 'disable-site-isolation-trials', '--suffixes', - 'txt', 'one/text-fail.html' + self.assertEqual(sorted(self.tool.executive.calls[2]), [ + [ + 'python', 'echo', 'optimize-baselines', '--no-manifest-update', + '--flag-specific', 'disable-layout-ng', '--suffixes', 'txt', + 'one/text-fail.html' + ], + [ + 'python', 'echo', 'optimize-baselines', '--no-manifest-update', + '--flag-specific', 'disable-site-isolation-trials', + '--suffixes', 'txt', 'one/text-fail.html' + ], + [ + 'python', 'echo', 'optimize-baselines', '--no-manifest-update', + '--suffixes', 'txt', 'one/text-fail.html' + ] ]) def test_trigger_try_jobs(self):
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py index 0d8a3b5..09350f30 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py +++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py
@@ -457,7 +457,7 @@ '--step-name', 'blink_web_tests (with patch)', ]], - [ + [[ 'python', 'echo', 'optimize-baselines', @@ -466,7 +466,7 @@ '--suffixes', 'png,txt', 'userscripts/first-test.html', - ]]) + ]]]) def test_rebaseline_debug(self): test_baseline_set = TestBaselineSet(self.tool) @@ -504,7 +504,7 @@ '--step-name', 'blink_web_tests (with patch)', ]], - [ + [[ 'python', 'echo', 'optimize-baselines', @@ -513,7 +513,7 @@ '--suffixes', 'png,txt', 'userscripts/first-test.html', - ]]) + ]]]) def test_no_optimize(self): test_baseline_set = TestBaselineSet(self.tool) @@ -631,7 +631,7 @@ '--step-name', 'blink_web_tests (with patch)', ]], - [ + [[ 'python', 'echo', 'optimize-baselines', @@ -640,7 +640,7 @@ '--suffixes', 'png,txt', 'userscripts/first-test.html', - ]]) + ]]]) class TestRebaselineUpdatesExpectationsFiles(BaseTestCase):
diff --git a/third_party/blink/web_tests/FlagExpectations/force-renderer-accessibility b/third_party/blink/web_tests/FlagExpectations/force-renderer-accessibility index cac050e..42999ac2 100644 --- a/third_party/blink/web_tests/FlagExpectations/force-renderer-accessibility +++ b/third_party/blink/web_tests/FlagExpectations/force-renderer-accessibility
@@ -109,4 +109,4 @@ # Most likely a forced style/layout update from accessibiity while we are # render blocking, which should not happen. -crbug.com/1351811 external/wpt/css/css-transitions/no-transition-from-ua-to-blocking-stylesheet.html [ Pass Failure ] +crbug.com/1351811 external/wpt/css/css-transitions/no-transition-from-ua-to-blocking-stylesheet.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index b4af098..2254887d 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -3388,7 +3388,7 @@ crbug.com/626703 [ Mac11 ] virtual/fenced-frame-shadow-dom/wpt_internal/fenced_frame/background-sync.https.html [ Timeout ] crbug.com/626703 [ Mac10.15 ] external/wpt/fullscreen/api/document-fullscreen-enabled-cross-origin.sub.html [ Timeout ] crbug.com/626703 [ Win10.20h2 ] virtual/attribution-reporting-debug-mode/wpt_internal/attribution-reporting/debug-key.sub.https.html?include=trigger [ Failure Timeout ] -crbug.com/626703 [ Mac11 ] virtual/attribution-reporting-debug-mode/wpt_internal/attribution-reporting/source-registration.sub.https.html?method=img&eligible [ Timeout ] +crbug.com/626703 [ Mac11 ] virtual/attribution-reporting-debug-mode/wpt_internal/attribution-reporting/source-registration.sub.https.html?method=img&eligible [ Skip Timeout ] crbug.com/626703 [ Win11 ] virtual/attribution-reporting-debug-mode/wpt_internal/attribution-reporting/trigger-data-sanitization.sub.https.html?source-type=navigation [ Failure Timeout ] crbug.com/626703 [ Mac11-arm64 ] virtual/fenced-frame-mparch/wpt_internal/fenced_frame/key-scrolling.https.html [ Failure Timeout ] crbug.com/626703 virtual/attribution-reporting-debug-mode/wpt_internal/attribution-reporting/trigger-registration.sub.https.html?method=xhr [ Pass Timeout ] @@ -3399,9 +3399,9 @@ crbug.com/626703 virtual/attribution-reporting-debug-mode/wpt_internal/attribution-reporting/trigger-registration.sub.https.html?method=script [ Pass Timeout ] crbug.com/626703 virtual/attribution-reporting-debug-mode/wpt_internal/attribution-reporting/trigger-registration.sub.https.html?method=script&eligible [ Pass Timeout ] crbug.com/626703 [ Mac11 ] virtual/document-transition/wpt_internal/document-transition/commit-timeout-crash.html [ Timeout ] -crbug.com/626703 [ Win11 ] virtual/attribution-reporting-debug-mode/wpt_internal/attribution-reporting/source-registration.sub.https.html?method=a [ Timeout ] -crbug.com/626703 [ Win11 ] virtual/attribution-reporting-debug-mode/wpt_internal/attribution-reporting/source-registration.sub.https.html?method=fetch&eligible=event-source [ Timeout ] -crbug.com/626703 [ Win11 ] virtual/attribution-reporting-debug-mode/wpt_internal/attribution-reporting/source-registration.sub.https.html?method=script&eligible [ Timeout ] +crbug.com/626703 [ Win11 ] virtual/attribution-reporting-debug-mode/wpt_internal/attribution-reporting/source-registration.sub.https.html?method=a [ Skip Timeout ] +crbug.com/626703 [ Win11 ] virtual/attribution-reporting-debug-mode/wpt_internal/attribution-reporting/source-registration.sub.https.html?method=fetch&eligible=event-source [ Skip Timeout ] +crbug.com/626703 [ Win11 ] virtual/attribution-reporting-debug-mode/wpt_internal/attribution-reporting/source-registration.sub.https.html?method=script&eligible [ Skip Timeout ] crbug.com/626703 [ Win10.20h2 ] wpt_internal/geolocation-api/watchPosition-page-visibility.https.html [ Timeout ] crbug.com/626703 [ Win11 ] virtual/attribution-reporting-debug-mode/wpt_internal/attribution-reporting/debug-key-test.sub.https.html?include=source [ Timeout ] crbug.com/626703 [ Win11 ] virtual/attribution-reporting-debug-mode/wpt_internal/attribution-reporting/simple-event-level-report-test.sub.https.html [ Timeout ] @@ -7000,9 +7000,6 @@ crbug.com/1180274 virtual/partitioned-cookies/http/tests/inspector-protocol/network/navigate-iframe-out2in.js [ Skip ] # Sheriff 2022-07-11 -crbug.com/1343262 [ Win11 ] compositing/overlap-blending/reflection-opacity-huge.html [ Failure ] -crbug.com/1343262 [ Win11 ] compositing/reflections/nested-reflection-opacity.html [ Failure ] -crbug.com/1343262 [ Win11 ] fast/reflections/transparent-reflected-sublayers.html [ Failure ] crbug.com/1343270 [ Win11 ] media/controls/video-controls-with-cast-rendering.html [ Failure ] # Sheriff 2022-07-12 @@ -7100,3 +7097,8 @@ # TODO(crbug.com/1352009): Research how to re-enable test once not flaky crbug.com/1352009 external/wpt/preload/preconnect.html [ Failure Pass ] + +# Sheriff 2022-08-11 +# Most likely a forced style/layout update from accessibiity while we are +# render blocking, which should not happen. +crbug.com/1351811 external/wpt/css/css-transitions/no-transition-from-ua-to-blocking-stylesheet.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version index 596ce405..8a82631 100644 --- a/third_party/blink/web_tests/external/Version +++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@ -Version: 321bbd64536947a851b62a1af992efd8f8efc1fe +Version: 1d7b12e92199a765ff83c89c8c4f8345fb5137c3
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 1e23bb1..35dc05f4 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -833,6 +833,13 @@ ] ] }, + "table-in-abspos-multicol-with-nested-meter-crash.html": [ + "363324b225b2e72d05defcb2ddea4865ca76ef8a", + [ + null, + {} + ] + ], "table-row-end-border-1-crash.html": [ "3947dbdadaa1b8a5c836cc82ac0fb3508eeb45e1", [ @@ -3553,6 +3560,13 @@ {} ] ], + "forwarddelete-delete-after-justifyleft-indent.html": [ + "0b0e188732751cf79141cab3fb95726ae5b91c3a", + [ + null, + {} + ] + ], "forwarddelete-in-list-editing-host-after-selectall-with-focus.html": [ "266cc4fb600227ed134c062d6c01cf52a9f1abed", [ @@ -3574,6 +3588,13 @@ {} ] ], + "indent-outdent-after-closing-editable-dialog-element.html": [ + "7f73de048d714c99ce47ae4da61d7128e53216e8", + [ + null, + {} + ] + ], "insert-image-with-joining-header-element-and-body.html": [ "cf5b2df225be06c833fea6d3bf2ceab6b1231018", [ @@ -185362,7 +185383,7 @@ ] ], "transform-interpolation-rotate.html": [ - "d69023c9b7acbeb97fa790482ccc93a82b233528", + "cba2d2086fc7feb7542d8cac9b7271a394e6af14", [ null, [ @@ -185382,7 +185403,7 @@ ], [ 0, - 17 + 246 ] ] ] @@ -189831,7 +189852,7 @@ ] ], "transform-3d-rotateY-stair-above-001.xht": [ - "ce03b4fca16936167aaed9c778538ee799b85044", + "e637eb0b828eadf22c2254583e5dfeeb54863d7b", [ null, [ @@ -189844,7 +189865,7 @@ ] ], "transform-3d-rotateY-stair-below-001.xht": [ - "9282f245f733803f7fa21cd351293a36ee4ae7f4", + "8d9b610bf030a83a60185dadd3b26c6e546af261", [ null, [ @@ -189860,7 +189881,7 @@ [ [ 0, - 3 + 14 ], [ 0, @@ -439325,7 +439346,7 @@ ] ], "FileSystemSyncAccessHandle-read-write.https.tentative.worker.js": [ - "9f2a61db78e6cc79748ac6e037797d468fc77941", + "cdefc78b6cb2115114accbd449e34766fbf0849b", [ "fs/FileSystemSyncAccessHandle-read-write.https.tentative.worker.html", {}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/transform-interpolation-rotate.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/transform-interpolation-rotate.html index d69023c9..cba2d20 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/transform-interpolation-rotate.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/transform-interpolation-rotate.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <html class="reftest-wait"> <link rel="match" href="transform-interpolation-ref.html?rotate"> -<meta name="fuzzy" content="maxDifference=0-2;totalPixels=0-17"> +<meta name="fuzzy" content="maxDifference=0-2;totalPixels=0-246"> <link rel="help" href="https://drafts.csswg.org/css-transforms/"> <script src="../../../common/reftest-wait.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-above-001.xht b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-above-001.xht index ce03b4f..e637eb0b 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-above-001.xht +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-above-001.xht
@@ -45,7 +45,7 @@ } #three { width: 33px; - height: 147px; + height: 148px; top: 21px; left: 86px; }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-below-001.xht b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-below-001.xht index 9282f24..8d9b610 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-below-001.xht +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-below-001.xht
@@ -5,7 +5,7 @@ <link rel="author" title="Apple Inc." href="http://www.apple.com/"/> <link rel="help" href="http://www.w3.org/TR/css-transforms-2/#3d-transform-rendering"/> <link rel="match" href="reference/transform-3d-rotateY-stair-above-ref-001.xht"/> - <meta name="fuzzy" content="maxDifference=0-3;totalPixels=0-80" /> + <meta name="fuzzy" content="maxDifference=0-14;totalPixels=0-80" /> <meta name="assert" content="A rotateY transform with perspective should result in a trapezoid."/> <style type="text/css"><![CDATA[
diff --git a/third_party/blink/web_tests/external/wpt/editing/crashtests/forwarddelete-delete-after-justifyleft-indent.html b/third_party/blink/web_tests/external/wpt/editing/crashtests/forwarddelete-delete-after-justifyleft-indent.html new file mode 100644 index 0000000..0b0e188 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/editing/crashtests/forwarddelete-delete-after-justifyleft-indent.html
@@ -0,0 +1,20 @@ +<script> +document.addEventListener("DOMContentLoaded", () => { + const fieldset = document.querySelector("fieldset"); + document.documentElement.contentEditable = true; + fieldset.contentEditable = false; + document.execCommand("justifyLeft"); + document.designMode = "on"; + document.execCommand("indent"); + document.execCommand("forwardDelete"); + document.execCommand("delete"); +}); +</script> +<acronym readonly autofocus> +<sup> +<fieldset> + +here is fieldset +</fieldset> +</acronym> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/editing/crashtests/indent-outdent-after-closing-editable-dialog-element.html b/third_party/blink/web_tests/external/wpt/editing/crashtests/indent-outdent-after-closing-editable-dialog-element.html new file mode 100644 index 0000000..7f73de04 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/editing/crashtests/indent-outdent-after-closing-editable-dialog-element.html
@@ -0,0 +1,31 @@ +<html class="reftest-wait"> +<script> +var eventCount = 0; +document.addEventListener("DOMContentLoaded", () => { + const dialog = document.querySelector("dialog"); + const object = document.createElement("object"); + object.addEventListener("DOMSubtreeModified", () => { + dialog.show(); + dialog.focus(); + document.execCommand("selectAll"); + dialog.close(); + setTimeout(() => { + document.execCommand("selectAll"); + document.execCommand("strikeThrough"); + document.execCommand("indent"); + document.execCommand("outdent"); + eventCount--; + if (!eventCount) { + document.documentElement.removeAttribute("class"); + } + }); + eventCount++; + }); + object.setAttribute("role", "x"); // Run DOMSubtreeModified + object.setAttribute("role", "y"); // Run DOMSubtreeModified + document.execCommand("forwardDelete"); + document.execCommand("justifyRight"); +}) +</script> +<dialog id="a" contenteditable="true">a</dialog> +</html> \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/attribution-reporting/insecure-subresource-preload.js b/third_party/blink/web_tests/http/tests/inspector-protocol/attribution-reporting/insecure-subresource-preload.js new file mode 100644 index 0000000..1902cb8 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/attribution-reporting/insecure-subresource-preload.js
@@ -0,0 +1,19 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async function(testRunner) { + const {page, dp} = await testRunner.startBlank( + `Test that an untrustworthy attributionsrc triggers an issue when the img is preloaded.`); + + await dp.Audits.enable(); + + const issuePromise = dp.Audits.onceIssueAdded(); + + await page.navigate( + 'https://devtools.test:8443/inspector-protocol/attribution-reporting/resources/preload.html'); + + const issue = await issuePromise; + testRunner.log(issue.params.issue, 'Issue reported: ', ['violatingNodeId']); + testRunner.completeTest(); +})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/attribution-reporting/resources/preload.html b/third_party/blink/web_tests/http/tests/inspector-protocol/attribution-reporting/resources/preload.html new file mode 100644 index 0000000..d5525de --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/attribution-reporting/resources/preload.html
@@ -0,0 +1,5 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Preloaded Attributionsrc</title> +<body> +<img attributionsrc src="wss://example.test">
diff --git a/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/attribution-reporting/insecure-subresource-preload-expected.txt b/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/attribution-reporting/insecure-subresource-preload-expected.txt new file mode 100644 index 0000000..029846ef --- /dev/null +++ b/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/attribution-reporting/insecure-subresource-preload-expected.txt
@@ -0,0 +1,12 @@ +Test that an untrustworthy attributionsrc triggers an issue when the img is preloaded. +Issue reported: { + code : AttributionReportingIssue + details : { + attributionReportingIssueDetails : { + invalidParameter : wss://example.test + violatingNodeId : <number> + violationType : UntrustworthyReportingOrigin + } + } +} +
diff --git a/third_party/blink/web_tests/platform/win/compositing/overlap-blending/reflection-opacity-huge-expected.png b/third_party/blink/web_tests/platform/win/compositing/overlap-blending/reflection-opacity-huge-expected.png index 3b00e70..acbed94 100644 --- a/third_party/blink/web_tests/platform/win/compositing/overlap-blending/reflection-opacity-huge-expected.png +++ b/third_party/blink/web_tests/platform/win/compositing/overlap-blending/reflection-opacity-huge-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/reflections/transparent-reflected-sublayers-expected.png b/third_party/blink/web_tests/platform/win/fast/reflections/transparent-reflected-sublayers-expected.png index b0124c78..497baee2c 100644 --- a/third_party/blink/web_tests/platform/win/fast/reflections/transparent-reflected-sublayers-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/reflections/transparent-reflected-sublayers-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/compositing/overlap-blending/reflection-opacity-huge-expected.png b/third_party/blink/web_tests/platform/win10/compositing/overlap-blending/reflection-opacity-huge-expected.png deleted file mode 100644 index acbed94..0000000 --- a/third_party/blink/web_tests/platform/win10/compositing/overlap-blending/reflection-opacity-huge-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/fast/reflections/transparent-reflected-sublayers-expected.png b/third_party/blink/web_tests/platform/win10/fast/reflections/transparent-reflected-sublayers-expected.png deleted file mode 100644 index 497baee2c..0000000 --- a/third_party/blink/web_tests/platform/win10/fast/reflections/transparent-reflected-sublayers-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/source-registration.sub.https.html b/third_party/blink/web_tests/wpt_internal/attribution-reporting/source-registration.sub.https.html index 19ae2bcb..d751c1c 100644 --- a/third_party/blink/web_tests/wpt_internal/attribution-reporting/source-registration.sub.https.html +++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/source-registration.sub.https.html
@@ -1,5 +1,6 @@ <!doctype html> <meta charset=utf-8> +<meta name=timeout content=long> <meta name=variant content="?method=a"> <meta name=variant content="?method=a&eligible"> <meta name=variant content="?method=fetch&eligible=event-source">
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-fonts/resources/variabletest_box.ttf b/third_party/blink/web_tests/wpt_internal/css/css-fonts/resources/variabletest_box.ttf new file mode 100644 index 0000000..0d5bf3e2 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/css-fonts/resources/variabletest_box.ttf Binary files differ
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-fonts/variable-opsz-zoom-ref.html b/third_party/blink/web_tests/wpt_internal/css/css-fonts/variable-opsz-zoom-ref.html new file mode 100644 index 0000000..0cd4d2b --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/css-fonts/variable-opsz-zoom-ref.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<meta charset="utf-8"> +<style> + @font-face { + font-family: variabletest_box; + src: url(resources/variabletest_box.ttf); + } + + body { + font-family: variabletest_box, sans-serif; + font-optical-sizing: none; + } + + .columns { + display: flex; + gap: 20px; + } +</style> +<div class="columns"> +<div> +<div style="font-size: 6px; font-variation-settings: 'opsz' 6;">B</div> +<div style="font-size: 12px; font-variation-settings: 'opsz' 12;">B</div> +<div style="font-size: 24px; font-variation-settings: 'opsz' 24;">B</div> +</div> +<div> +<div style="font-size: 48px; font-variation-settings: 'opsz' 48;">B</div> +<div style="font-size: 64px; font-variation-settings: 'opsz' 64;">B</div> +<div style="font-size: 128px; font-variation-settings: 'opsz' 128;">B</div> +</div> +<div> +<div style="font-size: 24px; font-variation-settings: 'opsz' 128;">B</div> +<div style="font-size: 48px; font-variation-settings: 'opsz' 12;">B</div> +</div> +</div> +<script> + matchMedia('(resolution: 2dppx)').addEventListener("change", zoomReached, { once: true }) + if (window.testRunner) + testRunner.setPageZoomFactor(2); + + function zoomReached() { + document.fonts.ready.then( + () => { document.documentElement.classList.remove("reftest-wait"); }); + } +</script> +</html>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-fonts/variable-opsz-zoom-size-adjust-ref.html b/third_party/blink/web_tests/wpt_internal/css/css-fonts/variable-opsz-zoom-size-adjust-ref.html new file mode 100644 index 0000000..566c746 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/css-fonts/variable-opsz-zoom-size-adjust-ref.html
@@ -0,0 +1,45 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<meta charset="utf-8"> +<style> + @font-face { + font-family: variabletest_box; + src: url(resources/variabletest_box.ttf); + } + + body { + font-family: variabletest_box, sans-serif; + font-optical-sizing: none; + } + + .columns { + display: flex; + gap: 20px; + } +</style> +<div class="columns"> +<div> +<div style="font-size: 9px; font-variation-settings: 'opsz' 9;">B</div> +<div style="font-size: 18px; font-variation-settings: 'opsz' 18;">B</div> +<div style="font-size: 36px; font-variation-settings: 'opsz' 36;">B</div> +</div> +<div> +<div style="font-size: 72px; font-variation-settings: 'opsz' 72;">B</div> +<div style="font-size: 96px; font-variation-settings: 'opsz' 96;">B</div> +</div> +<div> +<div style="font-size: 36px; font-variation-settings: 'opsz' 128;">B</div> +<div style="font-size: 72px; font-variation-settings: 'opsz' 12;">B</div> +</div> +</div> +<script> + matchMedia('(resolution: 2dppx)').addEventListener("change", zoomReached, { once: true }) + if (window.testRunner) + testRunner.setPageZoomFactor(2); + + function zoomReached() { + document.fonts.ready.then( + () => { document.documentElement.classList.remove("reftest-wait"); }); + } +</script> +</html>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-fonts/variable-opsz-zoom-size-adjust.html b/third_party/blink/web_tests/wpt_internal/css/css-fonts/variable-opsz-zoom-size-adjust.html new file mode 100644 index 0000000..3ec9d72e --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/css-fonts/variable-opsz-zoom-size-adjust.html
@@ -0,0 +1,53 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="author" title="Dominik Röttsches" href="drott@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-fonts-4/#font-optical-sizing-def"/> +<link rel="help" href="https://drafts.csswg.org/css-fonts-5/#size-adjust-desc"/> +<meta name="assert" content="Ensures that optical size is automatically applied, including under zoom."/> +<link rel="match" href="variable-opsz-zoom-size-adjust-ref.html"> +<meta charset="utf-8"> +<style> + @font-face { + font-family: variabletest_box; + src: url(resources/variabletest_box.ttf); + size-adjust: 150%; + } + + body { + font-family: variabletest_box, sans-serif; + } + .columns { + display: flex; + gap: 20px; + } +</style> +<!-- The variabletest_box font file contains a glyph for letter B which moves a + horizontal bar up from the middle for opsz > 12 and moves it down for opsz > + 12 where the opsz axis ranges from 12 to 128. --> +<div class="columns"> +<div> +<div style="font-size: 6px;">B</div> +<div style="font-size: 12px;">B</div> +<div style="font-size: 24px;">B</div> +</div> +<div> +<div style="font-size: 48px;">B</div> +<div style="font-size: 64px;">B</div> +</div> +<div> +<!-- Explicit value overrides auto. --> +<div style="font-size: 24px; font-variation-settings: 'opsz' 128;">B</div> +<div style="font-size: 48px; font-optical-sizing: none;">B</div> +</div> +</div> + <script> + matchMedia('(resolution: 2dppx)').addEventListener("change", zoomReached, { once: true }) + if (window.testRunner) + testRunner.setPageZoomFactor(2); + + function zoomReached() { + document.fonts.ready.then( + () => { document.documentElement.classList.remove("reftest-wait"); }); + } +</script> +</html>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-fonts/variable-opsz-zoom.html b/third_party/blink/web_tests/wpt_internal/css/css-fonts/variable-opsz-zoom.html new file mode 100644 index 0000000..de76eae --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/css-fonts/variable-opsz-zoom.html
@@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="author" title="Dominik Röttsches" href="drott@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-fonts-4/#font-optical-sizing-def"/> +<meta name="assert" content="Ensures that optical size is automatically applied, including under zoom."/> +<link rel="match" href="variable-opsz-zoom-ref.html"> +<meta charset="utf-8"> +<style> + @font-face { + font-family: variabletest_box; + src: url(resources/variabletest_box.ttf); + } + + body { + font-family: variabletest_box, sans-serif; + } + .columns { + display: flex; + gap: 20px; + } +</style> +<!-- The variabletest_box font file contains a glyph for letter B which moves a + horizontal bar up from the middle for opsz > 12 and moves it down for opsz > + 12 where the opsz axis ranges from 12 to 128. --> +<div class="columns"> +<div> +<div style="font-size: 6px;">B</div> +<div style="font-size: 12px;">B</div> +<div style="font-size: 24px;">B</div> +</div> +<div> +<div style="font-size: 48px;">B</div> +<div style="font-size: 64px;">B</div> +<div style="font-size: 128px;">B</div> +</div> +<div> +<!-- Explicit value overrides auto. --> +<div style="font-size: 24px; font-variation-settings: 'opsz' 128;">B</div> +<div style="font-size: 48px; font-optical-sizing: none;">B</div> +</div> +</div> + <script> + matchMedia('(resolution: 2dppx)').addEventListener("change", zoomReached, { once: true }) + if (window.testRunner) + testRunner.setPageZoomFactor(2); + + function zoomReached() { + document.fonts.ready.then( + () => { document.documentElement.classList.remove("reftest-wait"); }); + } +</script> +</html>
diff --git a/third_party/ipcz/src/reference_drivers/random.cc b/third_party/ipcz/src/reference_drivers/random.cc index d2d0310..9131225 100644 --- a/third_party/ipcz/src/reference_drivers/random.cc +++ b/third_party/ipcz/src/reference_drivers/random.cc
@@ -29,6 +29,7 @@ #if BUILDFLAG(IS_POSIX) #include <fcntl.h> +#include <unistd.h> #endif #if BUILDFLAG(IS_WIN) @@ -97,6 +98,8 @@ } else { RandomBytesFromDevUrandom(destination); } +#elif BUILDFLAG(IS_IOS) + RandomBytesFromDevUrandom(destination); #elif BUILDFLAG(IS_NACL) while (!destination.empty()) { size_t nread;
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium index ad185d5..086f5b1 100644 --- a/third_party/nearby/README.chromium +++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@ Name: Nearby Connections Library Short Name: Nearby URL: https://github.com/google/nearby -Version: 30a82350cdda38c01fd6794d9addee89ced7d10f +Version: 76d45f20db7260c315b52396c740ae3e3f7bfd9f 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 edc99fc..c205ff4 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -56159,6 +56159,7 @@ <int value="-1818565030" label="AutofillUseConsistentPopupSettingsIcons:disabled"/> <int value="-1818135677" label="DisableLacrosTtsSupport:enabled"/> + <int value="-1817721380" label="RemoveCanceledTasksInTaskQueue2:disabled"/> <int value="-1817209284" label="PayWithGoogleV1:enabled"/> <int value="-1816066138" label="CastAllowAllIPs:enabled"/> <int value="-1813088913" label="CCTResizable90MaximumHeight:disabled"/> @@ -56770,6 +56771,7 @@ <int value="-1437526584" label="HelpAppReleaseNotes:enabled"/> <int value="-1436892902" label="FastPairSavedDevices:disabled"/> <int value="-1436251034" label="VoiceSearchOnLocalNtp:disabled"/> + <int value="-1435804236" label="ThrottleIntersectionObserverUMA:enabled"/> <int value="-1433719718" label="enable-webrtc-stun-origin"/> <int value="-1433452630" label="AllowRemoteContextForNotifications:enabled"/> <int value="-1433087548" label="enable-app-install-alerts"/> @@ -58342,6 +58344,7 @@ <int value="-470247915" label="AutofillUpstreamEditableExpirationDate:enabled"/> <int value="-468697885" label="ArcInputMethod:enabled"/> + <int value="-468657548" label="ReduceGpuPriorityOnBackground:enabled"/> <int value="-467792766" label="ReengagementNotification:enabled"/> <int value="-466704882" label="webview-log-js-console-messages"/> <int value="-466164593" @@ -59045,6 +59048,7 @@ <int value="-9599490" label="KernelnextVMs:disabled"/> <int value="-9322265" label="ShowBluetoothDebugLogToggle:enabled"/> <int value="-8063095" label="AutofillEnableRemadeDownstreamMetrics:enabled"/> + <int value="-7996532" label="ThrottleIntersectionObserverUMA:disabled"/> <int value="-5492723" label="CCTIncognito:enabled"/> <int value="-5305648" label="OmniboxClosePopupWithEscape:enabled"/> <int value="-5052940" label="enable-simplified-fullscreen"/> @@ -59613,6 +59617,7 @@ <int value="353898777" label="ClipboardHistoryScreenshotNudge:disabled"/> <int value="354466842" label="UachOverrideBlank:enabled"/> <int value="354631905" label="RecoverFromNeverSaveAndroid:disabled"/> + <int value="354662118" label="RemoveCanceledTasksInTaskQueue2:enabled"/> <int value="355367368" label="SharesheetCopyToClipboard:disabled"/> <int value="357138275" label="enable-floating-virtual-keyboard:disabled"/> <int value="357165937" label="ShareToGoogleCollections:enabled"/> @@ -61435,6 +61440,7 @@ <int value="1514066770" label="DisplayCutoutAPI:enabled"/> <int value="1514119870" label="enable-file-manager-touch-mode"/> <int value="1514158607" label="NearbySharingDeviceContacts:enabled"/> + <int value="1514951731" label="ReduceGpuPriorityOnBackground:disabled"/> <int value="1515196403" label="fast-user-switching"/> <int value="1515334367" label="ToolbarMicIphAndroid:disabled"/> <int value="1515472077" label="VirtualKeyboardRoundCorners:disabled"/>
diff --git a/tools/metrics/histograms/metadata/cookie/histograms.xml b/tools/metrics/histograms/metadata/cookie/histograms.xml index c7f0244..1b4080a 100644 --- a/tools/metrics/histograms/metadata/cookie/histograms.xml +++ b/tools/metrics/histograms/metadata/cookie/histograms.xml
@@ -429,7 +429,7 @@ </histogram> <histogram name="Cookie.IsPartitionedValid" enum="BooleanValid" - expires_after="2022-10-30"> + expires_after="2023-02-01"> <owner>dylancutler@chromium.org</owner> <owner>bingler@chromium.org</owner> <summary> @@ -471,6 +471,18 @@ </summary> </histogram> +<histogram name="Cookie.MaxSameSiteNoneCookiesPerKey" units="units" + expires_after="2023-02-01"> + <owner>dylancutler@chromium.org</owner> + <owner>src/net/cookies/OWNERS</owner> + <summary> + Maximum number of SameSite=None cookies that belong to a single domain on + the client. This histogram will be used to inform the + per-partition-per-domain limit for partitioned cookies. Recorded every 10 + minutes of active browsing time. + </summary> +</histogram> + <histogram name="Cookie.NumDomainPurgedKeys" units="keys" expires_after="2022-08-28"> <owner>cfredric@chromium.org</owner>
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc index 38256f64..966b3c9 100644 --- a/ui/accessibility/ax_tree.cc +++ b/ui/accessibility/ax_tree.cc
@@ -1171,7 +1171,7 @@ if (!root_) { ACCESSIBILITY_TREE_UNSERIALIZE_ERROR_HISTOGRAM( AXTreeUnserializeError::kNoRoot); - RecordError("Tree has no root."); + RecordError(update_state, "Tree has no root."); return false; } @@ -1530,8 +1530,10 @@ if (!is_new_root) { ACCESSIBILITY_TREE_UNSERIALIZE_ERROR_HISTOGRAM( AXTreeUnserializeError::kNotInTree); - RecordError(base::StringPrintf( - "%d will not be in the tree and is not the new root", new_data.id)); + RecordError(*update_state, + base::StringPrintf( + "%d will not be in the tree and is not the new root", + new_data.id)); return false; } @@ -1541,9 +1543,11 @@ absl::nullopt)) { ACCESSIBILITY_TREE_UNSERIALIZE_ERROR_HISTOGRAM( AXTreeUnserializeError::kCreationPending); - RecordError(base::StringPrintf( - "Node %d is already pending for creation, cannot be the new root", - new_data.id)); + RecordError( + *update_state, + base::StringPrintf( + "Node %d is already pending for creation, cannot be the new root", + new_data.id)); return false; } if (update_state->pending_root_id) { @@ -1559,7 +1563,8 @@ if (base::Contains(new_child_id_set, new_child_id)) { ACCESSIBILITY_TREE_UNSERIALIZE_ERROR_HISTOGRAM( AXTreeUnserializeError::kDuplicateChild); - RecordError(base::StringPrintf("Node %d has duplicate child id %d", + RecordError(*update_state, + base::StringPrintf("Node %d has duplicate child id %d", new_data.id, new_child_id)); return false; } @@ -1584,9 +1589,10 @@ new_data.id)) { ACCESSIBILITY_TREE_UNSERIALIZE_ERROR_HISTOGRAM( AXTreeUnserializeError::kCreationPendingForChild); - RecordError(base::StringPrintf( - "Node %d is already pending for creation, cannot be a new child", - child_id)); + RecordError(*update_state, + base::StringPrintf("Node %d is already pending for " + "creation, cannot be a new child", + child_id)); return false; } } @@ -1628,9 +1634,10 @@ if (update_state->ShouldPendingNodeExistInTree(child_id)) { ACCESSIBILITY_TREE_UNSERIALIZE_ERROR_HISTOGRAM( AXTreeUnserializeError::kReparent); - RecordError(base::StringPrintf( - "Node %d is not marked for destruction, would be reparented to %d", - child_id, new_data.id)); + RecordError(*update_state, + base::StringPrintf("Node %d is not marked for destruction, " + "would be reparented to %d", + child_id, new_data.id)); return false; } @@ -1641,9 +1648,10 @@ new_data.id)) { ACCESSIBILITY_TREE_UNSERIALIZE_ERROR_HISTOGRAM( AXTreeUnserializeError::kCreationPendingForChild); - RecordError(base::StringPrintf( - "Node %d is already pending for creation, cannot be a new child", - child_id)); + RecordError(*update_state, + base::StringPrintf("Node %d is already pending for " + "creation, cannot be a new child", + child_id)); return false; } } else { @@ -1682,8 +1690,9 @@ if (!is_new_root) { ACCESSIBILITY_TREE_UNSERIALIZE_ERROR_HISTOGRAM( AXTreeUnserializeError::kNotInTree); - RecordError(base::StringPrintf( - "%d is not in the tree and not the new root", src.id)); + RecordError(*update_state, + base::StringPrintf( + "%d is not in the tree and not the new root", src.id)); return false; } @@ -2007,7 +2016,7 @@ std::string error = "Nodes left pending by the update:"; for (const AXNodeID pending_id : update_state.pending_node_ids) error += base::StringPrintf(" %d", pending_id); - RecordError(error); + RecordError(update_state, error); return false; } @@ -2033,11 +2042,13 @@ if (has_pending_changes) { ACCESSIBILITY_TREE_UNSERIALIZE_ERROR_HISTOGRAM( AXTreeUnserializeError::kPendingChanges); - RecordError(base::StringPrintf( - "Changes left pending by the update; " - "destroy subtrees: %s, destroy nodes: %s, create nodes: %s", - destroy_subtree_ids.c_str(), destroy_node_ids.c_str(), - create_node_ids.c_str())); + RecordError( + update_state, + base::StringPrintf( + "Changes left pending by the update; " + "destroy subtrees: %s, destroy nodes: %s, create nodes: %s", + destroy_subtree_ids.c_str(), destroy_node_ids.c_str(), + create_node_ids.c_str())); } return !has_pending_changes; } @@ -2146,7 +2157,8 @@ // If this case occurs, continue so this node isn't left in an // inconsistent state, but return failure at the end. if (child->parent()) { - RecordError(base::StringPrintf("Node %d reparented from %d to %d", + RecordError(*update_state, + base::StringPrintf("Node %d reparented from %d to %d", child->id(), child->parent()->id(), node->id())); } else { @@ -2728,18 +2740,36 @@ observer.OnTreeManagerWillBeRemoved(previous_tree_id); } -void AXTree::RecordError(std::string new_error) { +void AXTree::RecordError(const AXTreeUpdateState& update_state, + std::string new_error) { if (!error_.empty()) error_ = error_ + "\n"; // Add visual separation between errors. error_ = error_ + new_error; - if (!error_.empty()) { - // Add a crash key so we can figure out why this is happening. - static crash_reporter::CrashKeyString<256> ax_tree_error( - "ax_tree_unserialize_error"); - ax_tree_error.Set(error_); - LOG(ERROR) << error_; - } + LOG(ERROR) << new_error; + + static auto* const ax_tree_error_key = base::debug::AllocateCrashKeyString( + "ax_tree_error", base::debug::CrashKeySize::Size256); + static auto* const ax_tree_update_key = base::debug::AllocateCrashKeyString( + "ax_tree_update", base::debug::CrashKeySize::Size256); + static auto* const ax_tree_key = base::debug::AllocateCrashKeyString( + "ax_tree", base::debug::CrashKeySize::Size256); + static auto* const ax_tree_data_key = base::debug::AllocateCrashKeyString( + "ax_tree_data", base::debug::CrashKeySize::Size256); + + // Log additional crash keys so we can debug bad tree updates. + base::debug::SetCrashKeyString(ax_tree_error_key, new_error); + base::debug::SetCrashKeyString(ax_tree_update_key, + update_state.pending_tree_update.ToString()); + base::debug::SetCrashKeyString(ax_tree_key, TreeToStringHelper(root_, 1)); + base::debug::SetCrashKeyString(ax_tree_data_key, data().ToString()); + + // In fast-failing-builds, crash immediately with a message, otherwise + // rely on AccessibilityFatalError(), which will not crash until multiple + // errors occur. + SANITIZER_NOTREACHED() << new_error << "\n" + << update_state.pending_tree_update.ToString() << "\n" + << ToString(); } } // namespace ui
diff --git a/ui/accessibility/ax_tree.h b/ui/accessibility/ax_tree.h index 0686f564..fd17b85a 100644 --- a/ui/accessibility/ax_tree.h +++ b/ui/accessibility/ax_tree.h
@@ -14,6 +14,7 @@ #include <vector> #include "base/containers/flat_map.h" +#include "base/debug/crash_logging.h" #include "base/memory/raw_ptr.h" #include "base/metrics/histogram_functions.h" #include "base/observer_list.h" @@ -247,7 +248,9 @@ // Accumulate errors as there can be more than one before Chrome is crashed // via AccessibilityFatalError(); - void RecordError(std::string new_error); + // In an AX_FAIL_FAST_BUILD, will assert/crash immediately. + void RecordError(const AXTreeUpdateState& update_state, + std::string new_error); // AXNode::OwnerTree override. //
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc index 9388778..c40f5b5 100644 --- a/ui/accessibility/ax_tree_unittest.cc +++ b/ui/accessibility/ax_tree_unittest.cc
@@ -449,6 +449,10 @@ update.node_id_to_clear = 2; update.nodes.resize(1); update.nodes[0].id = 3; +#if defined(AX_FAIL_FAST_BUILD) + EXPECT_DEATH_IF_SUPPORTED(tree.Unserialize(update), + "Nodes left pending by the update: 2"); +#else EXPECT_FALSE(tree.Unserialize(update)); ASSERT_EQ("Nodes left pending by the update: 2", tree.error()); histogram_tester.ExpectUniqueSample( @@ -456,6 +460,7 @@ AXTreeUnserializeError::kPendingNodes, 1); histogram_tester.ExpectTotalCount( "Accessibility.Performance.Tree.Unserialize", 2); +#endif } TEST(AXTreeTest, LeaveOrphanedNewChildFails) { @@ -475,6 +480,10 @@ update.nodes.resize(1); update.nodes[0].id = 1; update.nodes[0].child_ids.push_back(2); +#if defined(AX_FAIL_FAST_BUILD) + EXPECT_DEATH_IF_SUPPORTED(tree.Unserialize(update), + "Nodes left pending by the update: 2"); +#else EXPECT_FALSE(tree.Unserialize(update)); ASSERT_EQ("Nodes left pending by the update: 2", tree.error()); histogram_tester.ExpectUniqueSample( @@ -482,6 +491,7 @@ AXTreeUnserializeError::kPendingNodes, 1); histogram_tester.ExpectTotalCount( "Accessibility.Performance.Tree.Unserialize", 2); +#endif } TEST(AXTreeTest, DuplicateChildIdFails) { @@ -502,6 +512,10 @@ update.nodes[0].child_ids.push_back(2); update.nodes[0].child_ids.push_back(2); update.nodes[1].id = 2; +#if defined(AX_FAIL_FAST_BUILD) + EXPECT_DEATH_IF_SUPPORTED(tree.Unserialize(update), + "Node 1 has duplicate child id 2"); +#else EXPECT_FALSE(tree.Unserialize(update)); ASSERT_EQ("Node 1 has duplicate child id 2", tree.error()); histogram_tester.ExpectUniqueSample( @@ -509,6 +523,7 @@ AXTreeUnserializeError::kDuplicateChild, 1); histogram_tester.ExpectTotalCount( "Accessibility.Performance.Tree.Unserialize", 1); +#endif } TEST(AXTreeTest, InvalidReparentingFails) { @@ -536,6 +551,11 @@ update.nodes[0].child_ids.push_back(2); update.nodes[1].id = 2; update.nodes[2].id = 3; +#if defined(AX_FAIL_FAST_BUILD) + EXPECT_DEATH_IF_SUPPORTED( + tree.Unserialize(update), + "Node 3 is not marked for destruction, would be reparented to 1"); +#else EXPECT_FALSE(tree.Unserialize(update)); ASSERT_EQ("Node 3 is not marked for destruction, would be reparented to 1", tree.error()); @@ -544,6 +564,7 @@ AXTreeUnserializeError::kReparent, 1); histogram_tester.ExpectTotalCount( "Accessibility.Performance.Tree.Unserialize", 1); +#endif } TEST(AXTreeTest, NoReparentingOfRootIfNoNewRoot) { @@ -1205,7 +1226,13 @@ node2.child_ids.push_back(0); initial_state.nodes.push_back(node2); ui::AXTree tree; - tree.Unserialize(initial_state); +#if defined(AX_FAIL_FAST_BUILD) + EXPECT_DEATH_IF_SUPPORTED(tree.Unserialize(initial_state), + "Node 0 has duplicate child id 0"); +#else + EXPECT_FALSE(tree.Unserialize(initial_state)); + EXPECT_EQ("Node 0 has duplicate child id 0", tree.error()); +#endif } // UAF caught by ax_tree_fuzzer @@ -1223,7 +1250,13 @@ initial_state.nodes.push_back(node2); ui::AXTree tree; - tree.Unserialize(initial_state); +#if defined(AX_FAIL_FAST_BUILD) + EXPECT_DEATH_IF_SUPPORTED(tree.Unserialize(initial_state), + "Node 1 has duplicate child id 1"); +#else + EXPECT_FALSE(tree.Unserialize(initial_state)); + EXPECT_EQ("Node 1 has duplicate child id 1", tree.error()); +#endif } TEST(AXTreeTest, RoleAndStateChangeCallbacks) { @@ -5381,10 +5414,17 @@ ui::AXNodeData disconnected_node; disconnected_node.id = 2; tree_update_3.nodes.push_back(disconnected_node); +#if defined(AX_FAIL_FAST_BUILD) + EXPECT_DEATH_IF_SUPPORTED( + tree.Unserialize(tree_update_3), + "2 will not be in the tree and is not the new root"); +#else EXPECT_FALSE(tree.Unserialize(tree_update_3)); + EXPECT_EQ("2 will not be in the tree and is not the new root", tree.error()); histogram_tester.ExpectUniqueSample( "Accessibility.Reliability.Tree.UnserializeError", AXTreeUnserializeError::kNotInTree, 1); +#endif } } // namespace ui
diff --git a/ui/base/cocoa/menu_controller.h b/ui/base/cocoa/menu_controller.h index 6eb5d2e..823d80a 100644 --- a/ui/base/cocoa/menu_controller.h +++ b/ui/base/cocoa/menu_controller.h
@@ -21,7 +21,7 @@ // Called as each item is created during menu or submenu creation. - (void)controllerWillAddItem:(NSMenuItem*)menuItem fromModel:(ui::MenuModel*)model - atIndex:(NSInteger)index + atIndex:(size_t)index withColorProvider:(const ui::ColorProvider*)colorProvider; // Called after all menu items in a menu or submenu are created. - (void)controllerWillAddMenu:(NSMenu*)menu fromModel:(ui::MenuModel*)model;
diff --git a/ui/base/ime/dummy_text_input_client.cc b/ui/base/ime/dummy_text_input_client.cc index 309b66f..0b0c567 100644 --- a/ui/base/ime/dummy_text_input_client.cc +++ b/ui/base/ime/dummy_text_input_client.cc
@@ -82,7 +82,7 @@ } bool DummyTextInputClient::GetCompositionCharacterBounds( - uint32_t index, + size_t index, gfx::Rect* rect) const { return false; }
diff --git a/ui/base/ime/dummy_text_input_client.h b/ui/base/ime/dummy_text_input_client.h index cfbb4df..26ee8c8 100644 --- a/ui/base/ime/dummy_text_input_client.h +++ b/ui/base/ime/dummy_text_input_client.h
@@ -42,7 +42,7 @@ bool CanComposeInline() const override; gfx::Rect GetCaretBounds() const override; gfx::Rect GetSelectionBoundingBox() const override; - bool GetCompositionCharacterBounds(uint32_t index, + bool GetCompositionCharacterBounds(size_t index, gfx::Rect* rect) const override; bool HasCompositionText() const override; ui::TextInputClient::FocusReason GetFocusReason() const override;
diff --git a/ui/base/ime/fake_text_input_client.cc b/ui/base/ime/fake_text_input_client.cc index 4c58110..a5d110c 100644 --- a/ui/base/ime/fake_text_input_client.cc +++ b/ui/base/ime/fake_text_input_client.cc
@@ -93,7 +93,7 @@ return {}; } -bool FakeTextInputClient::GetCompositionCharacterBounds(uint32_t index, +bool FakeTextInputClient::GetCompositionCharacterBounds(size_t index, gfx::Rect* rect) const { return false; }
diff --git a/ui/base/ime/fake_text_input_client.h b/ui/base/ime/fake_text_input_client.h index ebaed0f..3792ef09 100644 --- a/ui/base/ime/fake_text_input_client.h +++ b/ui/base/ime/fake_text_input_client.h
@@ -49,7 +49,7 @@ bool CanComposeInline() const override; gfx::Rect GetCaretBounds() const override; gfx::Rect GetSelectionBoundingBox() const override; - bool GetCompositionCharacterBounds(uint32_t index, + bool GetCompositionCharacterBounds(size_t index, gfx::Rect* rect) const override; bool HasCompositionText() const override; ui::TextInputClient::FocusReason GetFocusReason() const override;
diff --git a/ui/base/ime/ime_text_span.cc b/ui/base/ime/ime_text_span.cc index 1fa3bb0..3a54dd87 100644 --- a/ui/base/ime/ime_text_span.cc +++ b/ui/base/ime/ime_text_span.cc
@@ -10,8 +10,8 @@ namespace ui { ImeTextSpan::ImeTextSpan(Type type, - uint32_t start_offset, - uint32_t end_offset, + size_t start_offset, + size_t end_offset, Thickness thickness, UnderlineStyle underline_style, SkColor background_color,
diff --git a/ui/base/ime/ime_text_span.h b/ui/base/ime/ime_text_span.h index 2d373da..d03f57b 100644 --- a/ui/base/ime/ime_text_span.h +++ b/ui/base/ime/ime_text_span.h
@@ -48,8 +48,8 @@ explicit ImeTextSpan( Type type = Type::kComposition, - uint32_t start_offset = 0, - uint32_t end_offset = 0, + size_t start_offset = 0, + size_t end_offset = 0, Thickness thickness = Thickness::kThin, UnderlineStyle underline_style = UnderlineStyle::kSolid, SkColor background_color = SK_ColorTRANSPARENT, @@ -80,8 +80,8 @@ bool operator!=(const ImeTextSpan& rhs) const { return !(*this == rhs); } Type type; - uint32_t start_offset; - uint32_t end_offset; + size_t start_offset; + size_t end_offset; SkColor underline_color = SK_ColorTRANSPARENT; Thickness thickness; UnderlineStyle underline_style;
diff --git a/ui/base/ime/mojom/ime_types_mojom_traits.h b/ui/base/ime/mojom/ime_types_mojom_traits.h index 50489fa..bd8235d 100644 --- a/ui/base/ime/mojom/ime_types_mojom_traits.h +++ b/ui/base/ime/mojom/ime_types_mojom_traits.h
@@ -43,10 +43,10 @@ struct COMPONENT_EXPORT(IME_SHARED_MOJOM_TRAITS) StructTraits<ui::mojom::ImeTextSpanDataView, ui::ImeTextSpan> { static ui::ImeTextSpan::Type type(const ui::ImeTextSpan& c) { return c.type; } - static uint32_t start_offset(const ui::ImeTextSpan& c) { + static size_t start_offset(const ui::ImeTextSpan& c) { return c.start_offset; } - static uint32_t end_offset(const ui::ImeTextSpan& c) { return c.end_offset; } + static size_t end_offset(const ui::ImeTextSpan& c) { return c.end_offset; } static uint32_t underline_color(const ui::ImeTextSpan& c) { return c.underline_color; }
diff --git a/ui/base/ime/text_input_client.h b/ui/base/ime/text_input_client.h index 8e12d28..5b7b255 100644 --- a/ui/base/ime/text_input_client.h +++ b/ui/base/ime/text_input_client.h
@@ -146,7 +146,7 @@ // The |index| is zero-based index of character position in composition text. // Returns false if there is no composition text or |index| is out of range. // The |rect| is not touched in the case of failure. - virtual bool GetCompositionCharacterBounds(uint32_t index, + virtual bool GetCompositionCharacterBounds(size_t index, gfx::Rect* rect) const = 0; // Returns true if there is composition text.
diff --git a/ui/base/ime/win/tsf_text_store_unittest.cc b/ui/base/ime/win/tsf_text_store_unittest.cc index e25ca61..d09d1ae7 100644 --- a/ui/base/ime/win/tsf_text_store_unittest.cc +++ b/ui/base/ime/win/tsf_text_store_unittest.cc
@@ -49,7 +49,7 @@ MOCK_CONST_METHOD0(CanComposeInline, bool()); MOCK_CONST_METHOD0(GetCaretBounds, gfx::Rect()); MOCK_CONST_METHOD0(GetSelectionBoundingBox, gfx::Rect()); - MOCK_CONST_METHOD2(GetCompositionCharacterBounds, bool(uint32_t, gfx::Rect*)); + MOCK_CONST_METHOD2(GetCompositionCharacterBounds, bool(size_t, gfx::Rect*)); MOCK_CONST_METHOD0(HasCompositionText, bool()); MOCK_CONST_METHOD0(GetFocusReason, ui::TextInputClient::FocusReason()); MOCK_METHOD0(ShouldDoLearning, bool());
diff --git a/ui/base/interaction/element_identifier.h b/ui/base/interaction/element_identifier.h index 3542cd458..021c0f1 100644 --- a/ui/base/interaction/element_identifier.h +++ b/ui/base/interaction/element_identifier.h
@@ -11,6 +11,7 @@ #include <set> #include "base/component_export.h" +#include "base/numerics/safe_conversions.h" #include "ui/base/class_property.h" // Overview: @@ -246,7 +247,7 @@ public: static int64_t ToInt64(ui::ElementIdentifier x) { return x.GetRawValue(); } static ui::ElementIdentifier FromInt64(int64_t x) { - return ui::ElementIdentifier::FromRawValue(x); + return ui::ElementIdentifier::FromRawValue(base::checked_cast<intptr_t>(x)); } };
diff --git a/ui/chromeos/styles/cros_sys_colors.json5 b/ui/chromeos/styles/cros_sys_colors.json5 index 5c31e35..ad949cb 100644 --- a/ui/chromeos/styles/cros_sys_colors.json5 +++ b/ui/chromeos/styles/cros_sys_colors.json5
@@ -185,6 +185,12 @@ // TODO(b/224402466): Add cros.sys.warning // TODO(b/224402466): Add cros.sys.success + // These values have a very specific meaning and should never be tinted. + 'privacy-indicator': { + light: '#146c2e', + dark: '#37be5f', + }, + /* Effects */ 'hover-on-prominent': { light: 'rgba($cros.ref.neutral10.rgb, 0.10)',
diff --git a/ui/compositor/layer_animation_element.cc b/ui/compositor/layer_animation_element.cc index c27bdfb9..82bfcc5 100644 --- a/ui/compositor/layer_animation_element.cc +++ b/ui/compositor/layer_animation_element.cc
@@ -385,10 +385,10 @@ DCHECK_EQ(start_.step_count(), target_.step_count()); for (auto i = 0; i < static_cast<int>(start_.step_count()); ++i) { gradient_mask.AddStep( - gfx::Tween::FloatValueBetween(t, start_.steps()[i].percent, - target_.steps()[i].percent), + gfx::Tween::FloatValueBetween(t, start_.steps()[i].fraction, + target_.steps()[i].fraction), gfx::Tween::IntValueBetween(t, start_.steps()[i].alpha, - target_.steps()[i].alpha)); + target_.steps()[i].alpha)); } delegate->SetGradientMaskFromAnimation(
diff --git a/ui/compositor/layer_animation_element_unittest.cc b/ui/compositor/layer_animation_element_unittest.cc index c412c9e..3d1fe60 100644 --- a/ui/compositor/layer_animation_element_unittest.cc +++ b/ui/compositor/layer_animation_element_unittest.cc
@@ -475,9 +475,9 @@ gfx::LinearGradient start(45); start.AddStep(0, 0); gfx::LinearGradient target(135); - target.AddStep(50, 255); + target.AddStep(.5, 255); gfx::LinearGradient middle(90); - middle.AddStep(25, 127); + middle.AddStep(.25, 127); base::TimeTicks start_time; base::TimeDelta delta = base::Seconds(1);
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc index 6497d7d1..fc4de27 100644 --- a/ui/compositor/layer_unittest.cc +++ b/ui/compositor/layer_unittest.cc
@@ -773,7 +773,7 @@ gfx::Rect clip_rect(1, 1, 2, 2); gfx::LinearGradient gradient_mask(45); - gradient_mask.AddStep(50, 50); + gradient_mask.AddStep(.5, 50); layer->SetTransform(transform); layer->SetColor(SK_ColorRED); @@ -816,7 +816,7 @@ layer->SetRoundedCornerRadius({3, 6, 9, 12}); gradient_mask.set_angle(90); - gradient_mask.AddStep(90, 30); + gradient_mask.AddStep(.9, 30); layer->SetGradientMask(gradient_mask); // The clone is an independent copy, so state changes do not propagate. @@ -1064,7 +1064,7 @@ constexpr viz::SubtreeCaptureId kSubtreeCaptureId(22); l1->SetSubtreeCaptureId(kSubtreeCaptureId); gfx::LinearGradient gradient_mask(45); - gradient_mask.AddStep(50, 50); + gradient_mask.AddStep(.5, 50); l1->SetGradientMask(gradient_mask); EXPECT_EQ(gfx::Point3F(), l1->cc_layer_for_testing()->transform_origin()); @@ -1348,7 +1348,7 @@ TEST_F(LayerWithDelegateTest, GradientMask) { gfx::Rect layer_bounds(10, 20, 100, 100); gfx::LinearGradient gradient_mask; - gradient_mask.AddStep(50, 50); + gradient_mask.AddStep(.5, 50); auto layer = std::make_unique<Layer>(LAYER_TEXTURED);
diff --git a/ui/gfx/geometry/linear_gradient.cc b/ui/gfx/geometry/linear_gradient.cc index 05f9c39..ef7ca260 100644 --- a/ui/gfx/geometry/linear_gradient.cc +++ b/ui/gfx/geometry/linear_gradient.cc
@@ -28,16 +28,16 @@ LinearGradient::LinearGradient(const LinearGradient& copy) = default; -void LinearGradient::AddStep(float percent, uint8_t alpha) { +void LinearGradient::AddStep(float fraction, uint8_t alpha) { DCHECK_LT(step_count_, kMaxStepSize); - DCHECK_GE(percent, 0); - DCHECK_LE(percent, 100); - // make sure the step's percent is monotonically increasing. - DCHECK(step_count_ ? steps_[step_count_ - 1].percent < percent : true) + DCHECK_GE(fraction, 0); + DCHECK_LE(fraction, 1); + // make sure the step's fraction is monotonically increasing. + DCHECK(step_count_ ? steps_[step_count_ - 1].fraction < fraction : true) << base::StringPrintf("prev[%zu]=%f, next[%zu]=%f", step_count_ - 1, - steps_[step_count_ - 1].percent, step_count_, - steps_[step_count_].percent); - steps_[step_count_].percent = percent; + steps_[step_count_ - 1].fraction, step_count_, + fraction); + steps_[step_count_].fraction = fraction; steps_[step_count_++].alpha = alpha; } @@ -45,7 +45,7 @@ std::reverse(steps_.begin(), steps_.end()); std::rotate(steps_.begin(), steps_.end() - step_count_, steps_.end()); for (size_t i = 0; i < step_count_; i++) - steps_[i].percent = 100.f - steps_[i].percent; + steps_[i].fraction = 1.f - steps_[i].fraction; } void LinearGradient::Transform(const gfx::Transform& transform) { @@ -70,7 +70,7 @@ for (size_t i = 0; i < step_count_; ++i) { if (i) result += " - "; - result += base::StringPrintf("%f:%u", steps_[i].percent, steps_[i].alpha); + result += base::StringPrintf("%f:%u", steps_[i].fraction, steps_[i].alpha); } return result + "]}"; }
diff --git a/ui/gfx/geometry/linear_gradient.h b/ui/gfx/geometry/linear_gradient.h index cb638fe..aa57451 100644 --- a/ui/gfx/geometry/linear_gradient.h +++ b/ui/gfx/geometry/linear_gradient.h
@@ -26,8 +26,8 @@ class GEOMETRY_SKIA_EXPORT LinearGradient { public: struct Step { - // Percent that defines a position in diagonal, from 0 to 100. - float percent = 0; + // Fraction that defines a position in diagonal, from 0 to 1. + float fraction = 0; // Alpha, from 0 to 255. uint8_t alpha = 0; }; @@ -44,7 +44,7 @@ bool IsEmpty() const { return !step_count_; } // Add a new step. Adding more than 6 results in DCHECK or ignored. - void AddStep(float percent, uint8_t alpha); + void AddStep(float fraction, uint8_t alpha); // Get step information. const StepArray& steps() const { return steps_; } @@ -72,7 +72,7 @@ inline bool operator==(const LinearGradient::Step& lhs, const LinearGradient::Step& rhs) { - return lhs.percent == rhs.percent && lhs.alpha == rhs.alpha; + return lhs.fraction == rhs.fraction && lhs.alpha == rhs.alpha; } inline bool operator==(const LinearGradient& lhs, const LinearGradient& rhs) {
diff --git a/ui/gfx/geometry/linear_gradient_unittest.cc b/ui/gfx/geometry/linear_gradient_unittest.cc index 79c6ffb6..bf29ee5 100644 --- a/ui/gfx/geometry/linear_gradient_unittest.cc +++ b/ui/gfx/geometry/linear_gradient_unittest.cc
@@ -15,31 +15,31 @@ LinearGradient gradient(45); EXPECT_TRUE(gradient.IsEmpty()); - gradient.AddStep(10, 0); - gradient.AddStep(50, 50); - gradient.AddStep(80, 1); + gradient.AddStep(.1, 0); + gradient.AddStep(.5, 50); + gradient.AddStep(.8, 1); EXPECT_FALSE(gradient.IsEmpty()); EXPECT_EQ(45, gradient.angle()); EXPECT_EQ(3u, gradient.step_count()); - EXPECT_EQ(gradient.steps()[0].percent, 10); + EXPECT_FLOAT_EQ(gradient.steps()[0].fraction, .1); EXPECT_EQ(gradient.steps()[0].alpha, 0); - EXPECT_EQ(gradient.steps()[1].percent, 50); + EXPECT_FLOAT_EQ(gradient.steps()[1].fraction, .5); EXPECT_EQ(gradient.steps()[1].alpha, 50); - EXPECT_EQ(gradient.steps()[2].percent, 80); + EXPECT_FLOAT_EQ(gradient.steps()[2].fraction, .8); EXPECT_EQ(gradient.steps()[2].alpha, 1); LinearGradient gradient2(90); - gradient2.AddStep(10, 0); - gradient2.AddStep(50, 50); - gradient2.AddStep(80, 1); + gradient2.AddStep(.1, 0); + gradient2.AddStep(.5, 50); + gradient2.AddStep(.8, 1); EXPECT_NE(gradient, gradient2); gradient2.set_angle(45); EXPECT_EQ(gradient, gradient2); - gradient2.AddStep(90, 0); + gradient2.AddStep(.9, 0); EXPECT_NE(gradient, gradient2); } @@ -48,20 +48,20 @@ // Make sure reversing an empty LinearGradient doesn't cause an issue. gradient.ReverseSteps(); - gradient.AddStep(10, 0); - gradient.AddStep(50, 50); - gradient.AddStep(80, 1); + gradient.AddStep(.1, 0); + gradient.AddStep(.5, 50); + gradient.AddStep(.8, 1); gradient.ReverseSteps(); EXPECT_EQ(45, gradient.angle()); EXPECT_EQ(3u, gradient.step_count()); - EXPECT_EQ(gradient.steps()[0].percent, 20); + EXPECT_FLOAT_EQ(gradient.steps()[0].fraction, .2); EXPECT_EQ(gradient.steps()[0].alpha, 1); - EXPECT_EQ(gradient.steps()[1].percent, 50); + EXPECT_FLOAT_EQ(gradient.steps()[1].fraction, .5); EXPECT_EQ(gradient.steps()[1].alpha, 50); - EXPECT_EQ(gradient.steps()[2].percent, 90); + EXPECT_FLOAT_EQ(gradient.steps()[2].fraction, .9); EXPECT_EQ(gradient.steps()[2].alpha, 0); }
diff --git a/ui/gfx/gpu_memory_buffer.h b/ui/gfx/gpu_memory_buffer.h index fd5f5c1..1ab6446a 100644 --- a/ui/gfx/gpu_memory_buffer.h +++ b/ui/gfx/gpu_memory_buffer.h
@@ -74,7 +74,7 @@ GpuMemoryBufferId id{0}; base::UnsafeSharedMemoryRegion region; uint32_t offset = 0; - int32_t stride = 0; + uint32_t stride = 0; #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA) NativePixmapHandle native_pixmap_handle; #elif BUILDFLAG(IS_MAC)
diff --git a/ui/gfx/image/image_util.cc b/ui/gfx/image/image_util.cc index bb49ea5..63305ce 100644 --- a/ui/gfx/image/image_util.cc +++ b/ui/gfx/image/image_util.cc
@@ -8,17 +8,13 @@ #include <algorithm> #include <memory> -#include <vector> -#include "base/check.h" #include "base/cxx17_backports.h" -#include "base/numerics/safe_conversions.h" #include "build/build_config.h" #include "skia/ext/image_operations.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/codec/jpeg_codec.h" #include "ui/gfx/codec/webp_codec.h" -#include "ui/gfx/geometry/size.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_rep.h" @@ -162,61 +158,4 @@ *right = bitmap.width() - 1 - x; } -SkBitmap ResizeImageToLargestSize(const SkBitmap& image, - uint32_t max_image_size) { - uint32_t max_dimension = std::max(image.width(), image.height()); - if (max_dimension <= max_image_size) - return image; - // Proportionally resize the minimal image to fit in a box of size - // max_image_size. - return skia::ImageOperations::Resize( - image, skia::ImageOperations::RESIZE_BEST, - base::checked_cast<uint32_t>(image.width()) * max_image_size / - max_dimension, - base::checked_cast<uint32_t>(image.height()) * max_image_size / - max_dimension); -} - -void FilterAndResizeImagesForMaximalSize( - const std::vector<SkBitmap>& images, - uint32_t max_image_size, - std::vector<SkBitmap>& filtered_images, - std::vector<gfx::Size>& filtered_image_sizes) { - filtered_images.clear(); - filtered_image_sizes.clear(); - - if (images.empty()) - return; - - const SkBitmap* min_image = nullptr; - uint32_t min_image_size = std::numeric_limits<uint32_t>::max(); - // Filter the images by |max_image_size|, and also identify the smallest - // image in case all the images are bigger than |max_image_size|. - for (const SkBitmap& image : images) { - uint32_t current_size = std::max(image.width(), image.height()); - if (current_size < min_image_size) { - min_image = ℑ - min_image_size = current_size; - } - if (base::checked_cast<uint32_t>(image.width()) <= max_image_size && - base::checked_cast<uint32_t>(image.height()) <= max_image_size) { - filtered_images.emplace_back(image); - filtered_image_sizes.emplace_back( - gfx::Size(image.width(), image.height())); - } - } - if (!filtered_images.empty()) - return; - // Proportionally resize the minimal image to fit in a box of size - // |max_image_size|. - DCHECK(min_image); - SkBitmap resized = ResizeImageToLargestSize(*min_image, max_image_size); - // Drop null or empty SkBitmap. - if (resized.drawsNothing()) - return; - filtered_images.emplace_back(resized); - filtered_image_sizes.emplace_back( - gfx::Size(min_image->width(), min_image->height())); -} - } // namespace gfx
diff --git a/ui/gfx/image/image_util.h b/ui/gfx/image/image_util.h index 140403e50..aa954a2 100644 --- a/ui/gfx/image/image_util.h +++ b/ui/gfx/image/image_util.h
@@ -9,8 +9,6 @@ #include <vector> -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/gfx/geometry/size.h" #include "ui/gfx/gfx_export.h" namespace gfx { @@ -76,24 +74,6 @@ int max_height, int max_area); -// Proportionally resizes the |image| to fit in a box of size -// |max_image_size|. If the |image| already fits, it is -// returned without any resizing. -GFX_EXPORT SkBitmap ResizeImageToLargestSize(const SkBitmap& image, - uint32_t max_image_size); - -// Filters the array of bitmaps, removing all images that do not fit in a box of -// size |max_image_size|. Returns the result if it is not empty. Otherwise, -// find the smallest image in the array and resize it proportionally to fit -// in a box of size |max_image_size|. -// Sets |filtered_image_sizes| to the sizes of |filtered_images| before -// resizing. Both output vectors are guaranteed to have the same size. -GFX_EXPORT void FilterAndResizeImagesForMaximalSize( - const std::vector<SkBitmap>& images, - uint32_t max_image_size, - std::vector<SkBitmap>& filtered_images, - std::vector<gfx::Size>& filtered_image_sizes); - } // namespace gfx #endif // UI_GFX_IMAGE_IMAGE_UTIL_H_
diff --git a/ui/gfx/image/image_util_unittest.cc b/ui/gfx/image/image_util_unittest.cc index 5244772..0ef65fd 100644 --- a/ui/gfx/image/image_util_unittest.cc +++ b/ui/gfx/image/image_util_unittest.cc
@@ -14,17 +14,6 @@ #include "ui/gfx/image/image_unittest_util.h" #include "ui/gfx/image/resize_image_dimensions.h" -namespace { - -SkBitmap CreateRandomImage(int size, SkColor color) { - SkBitmap bitmap; - bitmap.allocN32Pixels(size, size); - bitmap.eraseColor(color); - return bitmap; -} - -} // namespace - TEST(ImageUtilTest, JPEGEncodeAndDecode) { gfx::Image original = gfx::test::CreateImage(100, 100); @@ -168,70 +157,3 @@ EXPECT_EQ(resized_image.Width(), 400); EXPECT_EQ(resized_image.Height(), 400); } - -TEST(ImageUtilTest, NoFilterNoResize) { - std::vector<SkBitmap> previous_images; - previous_images.push_back(CreateRandomImage(1, SK_ColorBLACK)); - previous_images.push_back(CreateRandomImage(2, SK_ColorGRAY)); - previous_images.push_back(CreateRandomImage(3, SK_ColorBLUE)); - - std::vector<SkBitmap> filtered_images; - std::vector<gfx::Size> filtered_sizes; - gfx::FilterAndResizeImagesForMaximalSize( - previous_images, /*max_image_size=*/5, filtered_images, filtered_sizes); - - // No image gets filtered. - EXPECT_EQ(filtered_images.size(), previous_images.size()); - EXPECT_EQ(3u, filtered_sizes.size()); - EXPECT_EQ(SK_ColorBLACK, filtered_images.at(0).getColor(0, 0)); - EXPECT_EQ(SK_ColorGRAY, filtered_images.at(1).getColor(1, 1)); - EXPECT_EQ(SK_ColorBLUE, filtered_images.at(2).getColor(2, 2)); -} - -TEST(ImageUtilTest, FilterImageNoResize) { - std::vector<SkBitmap> previous_images; - previous_images.push_back(CreateRandomImage(1, SK_ColorBLACK)); - previous_images.push_back(CreateRandomImage(3, SK_ColorGRAY)); - previous_images.push_back(CreateRandomImage(4, SK_ColorBLUE)); - - std::vector<SkBitmap> filtered_images; - std::vector<gfx::Size> filtered_sizes; - gfx::FilterAndResizeImagesForMaximalSize( - previous_images, /*max_image_size=*/2, filtered_images, filtered_sizes); - - // No image gets filtered. - EXPECT_EQ(1u, filtered_images.size()); - EXPECT_EQ(1u, filtered_sizes.size()); - EXPECT_EQ(SK_ColorBLACK, filtered_images.at(0).getColor(0, 0)); - // Verify grey and blue SkBitmaps are not in the filtered image. - EXPECT_NE(SK_ColorGRAY, filtered_images.at(0).getColor(0, 0)); - EXPECT_NE(SK_ColorBLUE, filtered_images.at(0).getColor(0, 0)); -} - -TEST(ImageUtilTest, AllFilterOnlyResize) { - std::vector<SkBitmap> previous_images; - previous_images.push_back(CreateRandomImage(6, SK_ColorBLACK)); - previous_images.push_back(CreateRandomImage(5, SK_ColorGRAY)); - previous_images.push_back(CreateRandomImage(4, SK_ColorBLUE)); - - std::vector<SkBitmap> filtered_images; - std::vector<gfx::Size> filtered_sizes; - gfx::FilterAndResizeImagesForMaximalSize( - previous_images, /*max_image_size=*/3, filtered_images, filtered_sizes); - - // Only 1 image gets resized, and it is the smallest one (the blue one). - // All other images are not filtered. - EXPECT_EQ(1u, filtered_images.size()); - EXPECT_EQ(1u, filtered_sizes.size()); - // Verify that resizing happens to proper size. - EXPECT_EQ(3, filtered_images.at(0).dimensions().width()); - EXPECT_EQ(3, filtered_images.at(0).dimensions().height()); - // Original sizes. - EXPECT_EQ(4, filtered_sizes.at(0).width()); - EXPECT_EQ(4, filtered_sizes.at(0).height()); - // Verify grey and black SkBitmaps are not in the filtered image. - // Only blue image is filtered. - EXPECT_EQ(SK_ColorBLUE, filtered_images.at(0).getColor(0, 0)); - EXPECT_NE(SK_ColorGRAY, filtered_images.at(0).getColor(0, 0)); - EXPECT_NE(SK_ColorBLACK, filtered_images.at(0).getColor(0, 0)); -}
diff --git a/ui/gfx/mojom/linear_gradient.mojom b/ui/gfx/mojom/linear_gradient.mojom index c95519c..b535aa19 100644 --- a/ui/gfx/mojom/linear_gradient.mojom +++ b/ui/gfx/mojom/linear_gradient.mojom
@@ -6,7 +6,7 @@ // See ui/gfx/geometry/linear_gradient.h. struct Step { - float percent; + float fraction; uint8 alpha; };
diff --git a/ui/gfx/mojom/linear_gradient_mojom_traits.cc b/ui/gfx/mojom/linear_gradient_mojom_traits.cc index 07d741f..25057da6 100644 --- a/ui/gfx/mojom/linear_gradient_mojom_traits.cc +++ b/ui/gfx/mojom/linear_gradient_mojom_traits.cc
@@ -18,7 +18,7 @@ return false; for (int i = 0; i < data.step_count(); ++i) { - out->AddStep(steps_data[i].percent, steps_data[i].alpha); + out->AddStep(steps_data[i].fraction, steps_data[i].alpha); } out->set_angle(data.angle());
diff --git a/ui/gfx/mojom/linear_gradient_mojom_traits.h b/ui/gfx/mojom/linear_gradient_mojom_traits.h index 09412c3..1480d0ad 100644 --- a/ui/gfx/mojom/linear_gradient_mojom_traits.h +++ b/ui/gfx/mojom/linear_gradient_mojom_traits.h
@@ -12,8 +12,8 @@ template <> struct StructTraits<gfx::mojom::StepDataView, gfx::LinearGradient::Step> { - static float percent(const gfx::LinearGradient::Step& input) { - return input.percent; + static float fraction(const gfx::LinearGradient::Step& input) { + return input.fraction; } static uint8_t alpha(const gfx::LinearGradient::Step& input) { @@ -22,7 +22,7 @@ static bool Read(gfx::mojom::StepDataView data, gfx::LinearGradient::Step* out) { - out->percent = data.percent(); + out->fraction = data.fraction(); out->alpha = data.alpha(); return true; }
diff --git a/ui/gfx/mojom/mojom_traits_unittest.cc b/ui/gfx/mojom/mojom_traits_unittest.cc index 2ba0059..40681ac 100644 --- a/ui/gfx/mojom/mojom_traits_unittest.cc +++ b/ui/gfx/mojom/mojom_traits_unittest.cc
@@ -147,7 +147,7 @@ TEST_F(StructTraitsTest, GpuMemoryBufferHandle) { const gfx::GpuMemoryBufferId kId(99); const uint32_t kOffset = 126; - const int32_t kStride = 256; + const uint32_t kStride = 256; base::UnsafeSharedMemoryRegion shared_memory_region = base::UnsafeSharedMemoryRegion::Create(1024); ASSERT_TRUE(shared_memory_region.IsValid());
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py index 1203312c..aceaf5eb 100755 --- a/ui/gl/generate_bindings.py +++ b/ui/gl/generate_bindings.py
@@ -2819,6 +2819,7 @@ 'EGL_ANGLE_create_context_webgl_compatibility', 'EGL_ANGLE_external_context_and_surface', 'EGL_ANGLE_keyed_mutex', + 'EGL_ANGLE_program_cache_control', 'EGL_ANGLE_robust_resource_initialization', 'EGL_ANGLE_surface_orientation', 'EGL_ANGLE_window_fixed_size',
diff --git a/ui/gl/gl_bindings_autogen_egl.cc b/ui/gl/gl_bindings_autogen_egl.cc index e203c35..7b03af65 100644 --- a/ui/gl/gl_bindings_autogen_egl.cc +++ b/ui/gl/gl_bindings_autogen_egl.cc
@@ -302,6 +302,8 @@ gfx::HasExtension(extensions, "EGL_ANGLE_keyed_mutex"); b_EGL_ANGLE_power_preference = gfx::HasExtension(extensions, "EGL_ANGLE_power_preference"); + b_EGL_ANGLE_program_cache_control = + gfx::HasExtension(extensions, "EGL_ANGLE_program_cache_control"); b_EGL_ANGLE_query_surface_pointer = gfx::HasExtension(extensions, "EGL_ANGLE_query_surface_pointer"); b_EGL_ANGLE_robust_resource_initialization =
diff --git a/ui/gl/gl_bindings_autogen_egl.h b/ui/gl/gl_bindings_autogen_egl.h index 2fdffb0..0113878b 100644 --- a/ui/gl/gl_bindings_autogen_egl.h +++ b/ui/gl/gl_bindings_autogen_egl.h
@@ -355,6 +355,7 @@ bool b_EGL_ANGLE_external_context_and_surface; bool b_EGL_ANGLE_keyed_mutex; bool b_EGL_ANGLE_power_preference; + bool b_EGL_ANGLE_program_cache_control; bool b_EGL_ANGLE_query_surface_pointer; bool b_EGL_ANGLE_robust_resource_initialization; bool b_EGL_ANGLE_stream_producer_d3d_texture;
diff --git a/ui/gl/gl_context_egl.cc b/ui/gl/gl_context_egl.cc index d210618..f22f7cc 100644 --- a/ui/gl/gl_context_egl.cc +++ b/ui/gl/gl_context_egl.cc
@@ -87,6 +87,11 @@ #define EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE 0x3481 #endif /* EGL_ANGLE_context_virtualization */ +#ifndef EGL_ANGLE_program_cache_control +#define EGL_ANGLE_program_cache_control 1 +#define EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE 0x3459 +#endif /* EGL_ANGLE_program_cache_control */ + using ui::GetLastEGLErrorString; namespace gl { @@ -310,6 +315,14 @@ static_cast<EGLint>(attribs.angle_context_virtualization_group_number)); } + // Skia manages program cache by itself. + // For WebGL program, it should manage program by itself too. + if (gl_display_->ext->b_EGL_ANGLE_program_cache_control) { + context_attributes.push_back( + EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE); + context_attributes.push_back(EGL_FALSE); + } + // Append final EGL_NONE to signal the context attributes are finished context_attributes.push_back(EGL_NONE); context_attributes.push_back(EGL_NONE);
diff --git a/ui/platform_window/platform_window_init_properties.h b/ui/platform_window/platform_window_init_properties.h index b67f867..51d227b 100644 --- a/ui/platform_window/platform_window_init_properties.h +++ b/ui/platform_window/platform_window_init_properties.h
@@ -11,6 +11,7 @@ #include "base/memory/raw_ptr.h" #include "build/build_config.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/native_widget_types.h" @@ -118,7 +119,7 @@ #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) bool prefer_dark_theme = false; raw_ptr<gfx::ImageSkia> icon = nullptr; - absl::optional<int> background_color; + absl::optional<SkColor> background_color; // Specifies the res_name and res_class fields, // respectively, of the WM_CLASS window property. Controls window grouping
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index cf74f307..cbcbd2e 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -500,7 +500,12 @@ ] sources += get_target_outputs(":views_vector_icons") - configs += [ "//build/config:precompiled_headers" ] + + configs += [ + "//build/config:precompiled_headers", + "//build/config/compiler:prevent_unsafe_narrowing", + ] + defines = [ "VIEWS_IMPLEMENTATION" ] deps = [
diff --git a/ui/views/cocoa/native_widget_mac_ns_window_host.mm b/ui/views/cocoa/native_widget_mac_ns_window_host.mm index aebada61..cdaf472a 100644 --- a/ui/views/cocoa/native_widget_mac_ns_window_host.mm +++ b/ui/views/cocoa/native_widget_mac_ns_window_host.mm
@@ -11,6 +11,7 @@ #include "base/containers/contains.h" #include "base/mac/foundation_util.h" #include "base/no_destructor.h" +#include "base/numerics/safe_conversions.h" #include "base/strings/sys_string_conversions.h" #include "base/time/time.h" #include "components/remote_cocoa/app_shim/mouse_capture.h" @@ -1170,7 +1171,8 @@ display_.color_spaces()); } if (display_id_changed) { - display_link_ = ui::DisplayLinkMac::GetForDisplay(display_.id()); + display_link_ = ui::DisplayLinkMac::GetForDisplay( + base::checked_cast<CGDirectDisplayID>(display_.id())); if (!display_link_) { // Note that on some headless systems, the display link will fail to be // created, so this should not be a fatal error.
diff --git a/ui/views/controls/menu/menu_runner_impl_cocoa.mm b/ui/views/controls/menu/menu_runner_impl_cocoa.mm index 46722c1..a6dec3b 100644 --- a/ui/views/controls/menu/menu_runner_impl_cocoa.mm +++ b/ui/views/controls/menu/menu_runner_impl_cocoa.mm
@@ -9,6 +9,7 @@ #include "base/i18n/rtl.h" #include "base/mac/mac_util.h" #import "base/message_loop/message_pump_mac.h" +#include "base/numerics/safe_conversions.h" #import "skia/ext/skia_utils_mac.h" #import "ui/base/cocoa/cocoa_base_utils.h" #import "ui/base/cocoa/menu_controller.h" @@ -212,7 +213,7 @@ - (void)controllerWillAddItem:(NSMenuItem*)menuItem fromModel:(ui::MenuModel*)model - atIndex:(NSInteger)index + atIndex:(size_t)index withColorProvider:(const ui::ColorProvider*)colorProvider { if (model->IsNewFeatureAt(index)) { NSMutableAttributedString* attrTitle = [[[NSMutableAttributedString alloc] @@ -262,7 +263,9 @@ if ([menu respondsToSelector:@selector(_menuImpl)]) { NSCarbonMenuImpl* menuImpl = [menu_obj _menuImpl]; if ([menuImpl respondsToSelector:@selector(highlightItemAtIndex:)]) { - [menuImpl highlightItemAtIndex:alerted_index.value()]; + const auto index = + base::checked_cast<NSInteger>(alerted_index.value()); + [menuImpl highlightItemAtIndex:index]; } } } @@ -366,8 +369,10 @@ // Returns the first item in |menu_controller|'s menu that will be checked. NSMenuItem* FirstCheckedItem(MenuControllerCocoa* menu_controller) { for (NSMenuItem* item in [[menu_controller menu] itemArray]) { - if ([menu_controller model]->IsItemCheckedAt([item tag])) + if ([menu_controller model]->IsItemCheckedAt( + base::checked_cast<size_t>([item tag]))) { return item; + } } return nil; }
diff --git a/ui/views/controls/prefix_selector.cc b/ui/views/controls/prefix_selector.cc index 37cc84dd..a65c9e2 100644 --- a/ui/views/controls/prefix_selector.cc +++ b/ui/views/controls/prefix_selector.cc
@@ -93,7 +93,7 @@ return gfx::Rect(); } -bool PrefixSelector::GetCompositionCharacterBounds(uint32_t index, +bool PrefixSelector::GetCompositionCharacterBounds(size_t index, gfx::Rect* rect) const { // TextInputClient::GetCompositionCharacterBounds is expected to fill |rect| // in screen coordinates and GetCaretBounds returns screen coordinates.
diff --git a/ui/views/controls/prefix_selector.h b/ui/views/controls/prefix_selector.h index 9b5977f..ce19d4d8d 100644 --- a/ui/views/controls/prefix_selector.h +++ b/ui/views/controls/prefix_selector.h
@@ -59,7 +59,7 @@ bool CanComposeInline() const override; gfx::Rect GetCaretBounds() const override; gfx::Rect GetSelectionBoundingBox() const override; - bool GetCompositionCharacterBounds(uint32_t index, + bool GetCompositionCharacterBounds(size_t index, gfx::Rect* rect) const override; bool HasCompositionText() const override; FocusReason GetFocusReason() const override;
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc index e051ad7b..7efde3e 100644 --- a/ui/views/controls/textfield/textfield.cc +++ b/ui/views/controls/textfield/textfield.cc
@@ -1459,7 +1459,7 @@ return gfx::Rect(); } -bool Textfield::GetCompositionCharacterBounds(uint32_t index, +bool Textfield::GetCompositionCharacterBounds(size_t index, gfx::Rect* rect) const { DCHECK(rect); if (!HasCompositionText())
diff --git a/ui/views/controls/textfield/textfield.h b/ui/views/controls/textfield/textfield.h index 8703148..9768a28 100644 --- a/ui/views/controls/textfield/textfield.h +++ b/ui/views/controls/textfield/textfield.h
@@ -421,7 +421,7 @@ bool CanComposeInline() const override; gfx::Rect GetCaretBounds() const override; gfx::Rect GetSelectionBoundingBox() const override; - bool GetCompositionCharacterBounds(uint32_t index, + bool GetCompositionCharacterBounds(size_t index, gfx::Rect* rect) const override; bool HasCompositionText() const override; FocusReason GetFocusReason() const override;
diff --git a/ui/views/style/platform_style_mac.mm b/ui/views/style/platform_style_mac.mm index 218163c..227be4a8 100644 --- a/ui/views/style/platform_style_mac.mm +++ b/ui/views/style/platform_style_mac.mm
@@ -4,6 +4,7 @@ #include "ui/views/style/platform_style.h" +#include "base/numerics/safe_conversions.h" #include "base/strings/sys_string_conversions.h" #include "ui/base/buildflags.h" #include "ui/gfx/color_utils.h" @@ -71,16 +72,18 @@ base::ScopedCFTypeRef<CFStringRef> cf_string(CFStringCreateWithCharacters( kCFAllocatorDefault, reinterpret_cast<const UniChar*>(text.data()), - text.size())); + base::checked_cast<CFIndex>(text.size()))); CFRange range_to_delete = CFStringGetRangeOfCharacterClusterAtIndex( - cf_string, cursor_position - 1, kCFStringBackwardDeletionCluster); + cf_string, base::checked_cast<CFIndex>(cursor_position - 1), + kCFStringBackwardDeletionCluster); if (range_to_delete.location == NSNotFound) return gfx::Range(); // The range needs to be reversed to undo correctly. - return gfx::Range(range_to_delete.location + range_to_delete.length, - range_to_delete.location); + return gfx::Range(base::checked_cast<size_t>(range_to_delete.location + + range_to_delete.length), + base::checked_cast<size_t>(range_to_delete.location)); } } // namespace views
diff --git a/ui/views/view.cc b/ui/views/view.cc index a363a58..7e786be 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc
@@ -18,6 +18,7 @@ #include "base/i18n/rtl.h" #include "base/logging.h" #include "base/notreached.h" +#include "base/numerics/safe_conversions.h" #include "base/observer_list.h" #include "base/scoped_observation.h" #include "base/strings/utf_string_conversions.h" @@ -2389,7 +2390,8 @@ void View::AfterPropertyChange(const void* key, int64_t old_value) { if (key == kElementIdentifierKey) { const ui::ElementIdentifier old_element_id = - ui::ElementIdentifier::FromRawValue(old_value); + ui::ElementIdentifier::FromRawValue( + base::checked_cast<intptr_t>(old_value)); if (old_element_id) { views::ElementTrackerViews::GetInstance()->UnregisterView(old_element_id, this);
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm index d9df913..b3fc364 100644 --- a/ui/views/widget/native_widget_mac.mm +++ b/ui/views/widget/native_widget_mac.mm
@@ -54,7 +54,7 @@ static base::RepeatingCallback<void(NativeWidgetMac*)>* g_init_native_widget_callback = nullptr; -NSInteger StyleMaskForParams(const Widget::InitParams& params) { +uint64_t StyleMaskForParams(const Widget::InitParams& params) { // If the Widget is modal, it will be displayed as a sheet. This works best if // it has NSWindowStyleMaskTitled. For example, with // NSWindowStyleMaskBorderless, the parent window still accepts input.
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc index 7438cdf5..29e812d4 100644 --- a/ui/views/win/hwnd_message_handler.cc +++ b/ui/views/win/hwnd_message_handler.cc
@@ -862,7 +862,8 @@ // tasks while in windows move loop. base::CurrentThread::ScopedNestableTaskAllower allow_nested; - SendMessage(hwnd(), WM_SYSCOMMAND, SC_MOVE | 0x0002, GetMessagePos()); + SendMessage(hwnd(), WM_SYSCOMMAND, SC_MOVE | 0x0002, + static_cast<LPARAM>(GetMessagePos())); // Windows doesn't appear to offer a way to determine whether the user // canceled the move or not. We assume if the user released the mouse it was // successful.
diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn index 5bb59f9b..af92076 100644 --- a/ui/webui/resources/BUILD.gn +++ b/ui/webui/resources/BUILD.gn
@@ -174,7 +174,7 @@ "cr_elements/cr_radio_button/cr_card_radio_button.m.d.ts", "cr_elements/cr_radio_button/cr_radio_button_behavior.m.d.ts", "cr_elements/cr_radio_button/cr_radio_button.m.d.ts", - "cr_elements/cr_radio_group/cr_radio_group.m.d.ts", + "cr_elements/cr_radio_group/cr_radio_group.d.ts", "cr_elements/cr_scrollable_behavior.m.d.ts", "cr_elements/cr_toggle/cr_toggle.m.d.ts", "cr_elements/find_shortcut_behavior.d.ts",
diff --git a/ui/webui/resources/cr_components/chromeos/network/BUILD.gn b/ui/webui/resources/cr_components/chromeos/network/BUILD.gn index 27a001dd..6fceab5 100644 --- a/ui/webui/resources/cr_components/chromeos/network/BUILD.gn +++ b/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
@@ -146,7 +146,6 @@ deps = [ ":cr_policy_network_behavior_mojo", ":onc_mojo", - "../../../cr_elements/cr_radio_group:cr_radio_group", "//ui/webui/resources/js:i18n_behavior", ] } @@ -512,7 +511,7 @@ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/cr_elements/cr_input:cr_input.m", "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button.m", - "//ui/webui/resources/cr_elements/cr_radio_group:cr_radio_group.m", + "//ui/webui/resources/cr_elements/cr_radio_group:cr_radio_group", "//ui/webui/resources/cr_elements/policy:cr_policy_indicator.m", "//ui/webui/resources/js:i18n_behavior.m", ] @@ -798,6 +797,7 @@ html_file = "network_nameservers.html" html_type = "dom-module" auto_imports = cr_components_chromeos_auto_imports + migrated_imports = cr_components_migrated_imports } polymer_modulizer("network_password_input") {
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_nameservers.js b/ui/webui/resources/cr_components/chromeos/network/network_nameservers.js index b9799c99..676c03e1 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_nameservers.js +++ b/ui/webui/resources/cr_components/chromeos/network/network_nameservers.js
@@ -107,10 +107,10 @@ /* * Returns the nameserver type CrRadioGroupElement. - * @return {?CrRadioGroupElement} + * @return {?HTMLElement} */ getNameserverRadioButtons() { - return /** @type {?CrRadioGroupElement} */ (this.$$('#nameserverType')); + return /** @type {?HTMLElement} */ (this.$$('#nameserverType')); }, /**
diff --git a/ui/webui/resources/cr_components/chromeos/os_cr_components.gni b/ui/webui/resources/cr_components/chromeos/os_cr_components.gni index da0a181..cbb9e2ab 100644 --- a/ui/webui/resources/cr_components/chromeos/os_cr_components.gni +++ b/ui/webui/resources/cr_components/chromeos/os_cr_components.gni
@@ -73,5 +73,6 @@ cr_components_migrated_imports = [ "ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html", + "ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.html", "ui/webui/resources/html/list_property_update_behavior.html", ]
diff --git a/ui/webui/resources/cr_elements/BUILD.gn b/ui/webui/resources/cr_elements/BUILD.gn index 5a15887..639bd22 100644 --- a/ui/webui/resources/cr_elements/BUILD.gn +++ b/ui/webui/resources/cr_elements/BUILD.gn
@@ -103,8 +103,6 @@ "cr_radio_button/cr_radio_button.html", "cr_radio_button/cr_radio_button.js", "cr_radio_button/cr_radio_button_style_css.html", - "cr_radio_group/cr_radio_group.html", - "cr_radio_group/cr_radio_group.js", "cr_scrollable_behavior.html", "cr_scrollable_behavior.js", "cr_toggle/cr_toggle.html", @@ -149,7 +147,7 @@ "cr_radio_button/cr_radio_button_behavior.m.js", "cr_radio_button/cr_radio_button.m.js", "cr_radio_button/cr_radio_button_style_css.m.js", - "cr_radio_group/cr_radio_group.m.js", + "cr_radio_group/cr_radio_group.js", "cr_scrollable_behavior.m.js", "cr_toggle/cr_toggle.m.js", "hidden_style_css.m.js", @@ -195,10 +193,7 @@ ] if (is_chromeos_ash) { - deps += [ - "cr_button:closure_compile", - "cr_radio_group:closure_compile", - ] + deps += [ "cr_button:closure_compile" ] } } @@ -296,7 +291,7 @@ "cr_input:polymer3_elements", "cr_lottie:cr_lottie_module", "cr_radio_button:polymer3_elements", - "cr_radio_group:cr_radio_group_module", + "cr_radio_group:web_components", "cr_toggle:cr_toggle_module", "policy:polymer3_elements", ]
diff --git a/ui/webui/resources/cr_elements/cr_radio_group/BUILD.gn b/ui/webui/resources/cr_elements/cr_radio_group/BUILD.gn index 6b44fc4..d24aeeb 100644 --- a/ui/webui/resources/cr_elements/cr_radio_group/BUILD.gn +++ b/ui/webui/resources/cr_elements/cr_radio_group/BUILD.gn
@@ -4,46 +4,22 @@ import("//build/config/chromeos/ui_mode.gni") import("//third_party/closure_compiler/compile_js.gni") -import("//tools/polymer/polymer.gni") - -if (is_chromeos_ash) { - js_type_check("closure_compile") { - uses_legacy_modules = true - deps = [ ":cr_radio_group" ] - } - - js_library("cr_radio_group") { - deps = [ - "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button", - "//ui/webui/resources/js:event_tracker", - ] - } -} +import("//tools/polymer/html_to_js.gni") # Targets for auto-generating and typechecking Polymer 3 JS modules - -polymer_modulizer("cr_radio_group") { - js_file = "cr_radio_group.js" - html_file = "cr_radio_group.html" - html_type = "dom-module" - auto_imports = [ - "ui/webui/resources/html/event_tracker.html|EventTracker", - "ui/webui/resources/html/polymer.html|Polymer,html,dom", - ] - namespace_rewrites = [ "Polymer.dom|dom" ] +html_to_js("web_components") { + js_files = [ "cr_radio_group.js" ] } js_type_check("closure_compile_module") { is_polymer3 = true - deps = [ ":cr_radio_group.m" ] + deps = [ ":cr_radio_group" ] } -js_library("cr_radio_group.m") { - sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.m.js" ] +js_library("cr_radio_group") { deps = [ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button.m", "//ui/webui/resources/js:event_tracker.m", ] - extra_deps = [ ":cr_radio_group_module" ] }
diff --git a/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.m.d.ts b/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.d.ts similarity index 100% rename from ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.m.d.ts rename to ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.d.ts
diff --git a/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.html b/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.html index 0e4996e4..63c43aa9 100644 --- a/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.html +++ b/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.html
@@ -1,11 +1,3 @@ -<link rel="import" href="../../html/polymer.html"> - -<link rel="import" href="../../html/event_tracker.html"> -<link rel="import" href="../cr_radio_button/cr_radio_button.html"> -<link rel="import" href="../shared_vars_css.html"> - -<dom-module id="cr-radio-group"> - <template> <style> :host { display: inline-block; @@ -26,6 +18,3 @@ } </style> <slot></slot> - </template> - <script src="cr_radio_group.js"></script> -</dom-module>
diff --git a/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js b/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js index 5b5bdfe3..edf77214 100644 --- a/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js +++ b/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js
@@ -2,21 +2,33 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -(() => { +import '../cr_radio_button/cr_radio_button.m.js'; +import '../shared_vars_css.m.js'; - /** - * @param {!Element} radio - * @return {boolean} - */ - function isEnabled(radio) { - return radio.matches(':not([disabled]):not([hidden])') && - radio.style.display !== 'none' && radio.style.visibility !== 'hidden'; +import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {EventTracker} from '../../js/event_tracker.m.js'; + +/** + * @param {!Element} radio + * @return {boolean} + */ +function isEnabled(radio) { + return radio.matches(':not([disabled]):not([hidden])') && + radio.style.display !== 'none' && radio.style.visibility !== 'hidden'; +} + +export class CrRadioGroupElement extends PolymerElement { + static get is() { + return 'cr-radio-group'; } - Polymer({ - is: 'cr-radio-group', + static get template() { + return html`{__html_template__}`; + } - properties: { + static get properties() { + return { disabled: { type: Boolean, value: false, @@ -43,240 +55,233 @@ value: Object, computed: 'computeSelectableRegExp_(selectableElements)', }, - }, + }; + } - listeners: { - keydown: 'onKeyDown_', - click: 'onClick_', - }, + constructor() { + super(); + /** @private {?Array<!CrRadioButtonElement>} */ + this.buttons_ = null; - hostAttributes: { - 'aria-disabled': 'false', - role: 'radiogroup', - }, + /** @private {?EventTracker} */ + this.buttonEventTracker_ = null; - /** @private {Array<!CrRadioButtonElement>} */ - buttons_: null, - - /** @private {cr.EventTracker} */ - buttonEventTracker_: null, - - /** @private {Map<string, number>} */ - deltaKeyMap_: null, + /** @private {?Map<string, number>} */ + this.deltaKeyMap_ = null; /** @private {boolean} */ - isRtl_: false, - - /** @private {PolymerDomApi.ObserveHandle} */ - observer_: null, + this.isRtl_ = false; /** @private {Function} */ - populateBound_: null, + this.populateBound_ = null; + } - /** @override */ - attached() { - this.isRtl_ = this.matches(':host-context([dir=rtl]) cr-radio-group'); - this.deltaKeyMap_ = new Map([ - ['ArrowDown', 1], - ['ArrowLeft', this.isRtl_ ? 1 : -1], - ['ArrowRight', this.isRtl_ ? -1 : 1], - ['ArrowUp', -1], - ['PageDown', 1], - ['PageUp', -1], - ]); - this.buttonEventTracker_ = new cr.EventTracker(); + /** @override */ + ready() { + super.ready(); + this.addEventListener( + 'keydown', e => this.onKeyDown_(/** @type {!KeyboardEvent} */ (e))); + this.addEventListener('click', this.onClick_.bind(this)); - this.populateBound_ = () => this.populate_(); - // Needed for when the radio buttons change when using dom-repeat or - // dom-if. - // TODO(crbug.com/738611): After migration to Polymer 2, remove Polymer 1 - // references. - if (Polymer.DomIf) { - this.$$('slot').addEventListener('slotchange', this.populateBound_); - } else { - this.observer_ = Polymer.dom(this).observeNodes(this.populateBound_); - } + if (!this.hasAttribute('role')) { + this.setAttribute('role', 'radiogroup'); + } + this.setAttribute('aria-disabled', 'false'); + } - this.populate_(); - }, + /** @override */ + connectedCallback() { + super.connectedCallback(); + this.isRtl_ = this.matches(':host-context([dir=rtl]) cr-radio-group'); + this.deltaKeyMap_ = new Map([ + ['ArrowDown', 1], + ['ArrowLeft', this.isRtl_ ? 1 : -1], + ['ArrowRight', this.isRtl_ ? -1 : 1], + ['ArrowUp', -1], + ['PageDown', 1], + ['PageUp', -1], + ]); + this.buttonEventTracker_ = new EventTracker(); - /** @override */ - detached() { - if (Polymer.DomIf) { - this.$$('slot').removeEventListener('slotchange', this.populateBound_); - } else if (this.observer_) { - Polymer.dom(this).unobserveNodes( - /** @type {!PolymerDomApi.ObserveHandle} */ (this.observer_)); - } - this.buttonEventTracker_.removeAll(); - }, + this.populateBound_ = () => this.populate_(); + this.shadowRoot.querySelector('slot').addEventListener( + 'slotchange', this.populateBound_); - /** @override */ - focus() { - if (this.disabled || !this.buttons_) { - return; - } + this.populate_(); + } - const radio = - this.buttons_.find(radio => this.isButtonEnabledAndSelected_(radio)); - if (radio) { - radio.focus(); - } - }, + /** @override */ + disconnectedCallback() { + super.disconnectedCallback(); + this.shadowRoot.querySelector('slot').removeEventListener( + 'slotchange', this.populateBound_); + this.buttonEventTracker_.removeAll(); + } - /** - * @param {!KeyboardEvent} event - * @private - */ - onKeyDown_(event) { - if (this.disabled) { - return; - } + /** @override */ + focus() { + if (this.disabled || !this.buttons_) { + return; + } - if (event.ctrlKey || event.shiftKey || event.metaKey || event.altKey) { - return; - } + const radio = + this.buttons_.find(radio => this.isButtonEnabledAndSelected_(radio)); + if (radio) { + radio.focus(); + } + } - const targetElement = /** @type {!CrRadioButtonElement} */ (event.target); - if (!this.buttons_.includes(targetElement)) { - return; - } + /** + * @param {!KeyboardEvent} event + * @private + */ + onKeyDown_(event) { + if (this.disabled) { + return; + } - if (event.key === ' ' || event.key === 'Enter') { - event.preventDefault(); - this.select_(/** @type {!CrRadioButtonElement} */ (event.target)); - return; - } + if (event.ctrlKey || event.shiftKey || event.metaKey || event.altKey) { + return; + } - const enabledRadios = this.buttons_.filter(isEnabled); - if (enabledRadios.length === 0) { - return; - } + const targetElement = /** @type {!CrRadioButtonElement} */ (event.target); + if (!this.buttons_.includes(targetElement)) { + return; + } - let selectedIndex; - const max = enabledRadios.length - 1; - if (event.key === 'Home') { + if (event.key === ' ' || event.key === 'Enter') { + event.preventDefault(); + this.select_(/** @type {!CrRadioButtonElement} */ (event.target)); + return; + } + + const enabledRadios = this.buttons_.filter(isEnabled); + if (enabledRadios.length === 0) { + return; + } + + let selectedIndex; + const max = enabledRadios.length - 1; + if (event.key === 'Home') { + selectedIndex = 0; + } else if (event.key === 'End') { + selectedIndex = max; + } else if (this.deltaKeyMap_.has(event.key)) { + const delta = this.deltaKeyMap_.get(event.key); + // If nothing selected, start from the first radio then add |delta|. + const lastSelection = enabledRadios.findIndex(radio => radio.checked); + selectedIndex = Math.max(0, lastSelection) + delta; + // Wrap the selection, if needed. + if (selectedIndex > max) { selectedIndex = 0; - } else if (event.key === 'End') { + } else if (selectedIndex < 0) { selectedIndex = max; - } else if (this.deltaKeyMap_.has(event.key)) { - const delta = this.deltaKeyMap_.get(event.key); - // If nothing selected, start from the first radio then add |delta|. - const lastSelection = enabledRadios.findIndex(radio => radio.checked); - selectedIndex = Math.max(0, lastSelection) + delta; - // Wrap the selection, if needed. - if (selectedIndex > max) { - selectedIndex = 0; - } else if (selectedIndex < 0) { - selectedIndex = max; - } + } + } else { + return; + } + + const radio = enabledRadios[selectedIndex]; + const name = `${radio.name}`; + if (this.selected !== name) { + event.preventDefault(); + this.selected = name; + radio.focus(); + } + } + + /** + * @return {!RegExp} + * @private + */ + computeSelectableRegExp_() { + const tags = this.selectableElements.split(', ').join('|'); + return new RegExp(`^(${tags})$`, 'i'); + } + + /** + * @param {!Event} event + * @private + */ + onClick_(event) { + const path = event.composedPath(); + if (path.some(target => /^a$/i.test(target.tagName))) { + return; + } + const target = /** @type {!CrRadioButtonElement} */ ( + path.find(n => this.selectableRegExp_.test(n.tagName))); + if (target && this.buttons_.includes(target)) { + this.select_(/** @type {!CrRadioButtonElement} */ (target)); + } + } + + /** @private */ + populate_() { + const nodes = + this.shadowRoot.querySelector('slot').assignedNodes({flatten: true}); + this.buttons_ = Array.from(nodes).filter( + node => node.nodeType === Node.ELEMENT_NODE && + node.matches(this.selectableElements)); + this.buttonEventTracker_.removeAll(); + this.buttons_.forEach(el => { + this.buttonEventTracker_.add( + el, 'disabled-changed', () => this.populate_()); + this.buttonEventTracker_.add(el, 'name-changed', () => this.populate_()); + }); + this.update_(); + } + + /** + * @param {!CrRadioButtonElement} button + * @private + */ + select_(button) { + if (!isEnabled(button)) { + return; + } + + const name = `${button.name}`; + if (this.selected !== name) { + this.selected = name; + } + } + + /** + * @param {!Element} button + * @return {boolean} + * @private + */ + isButtonEnabledAndSelected_(button) { + return !this.disabled && button.checked && isEnabled(button); + } + + /** @private */ + update_() { + if (!this.buttons_) { + return; + } + let noneMadeFocusable = true; + this.buttons_.forEach(radio => { + radio.checked = + this.selected !== undefined && `${radio.name}` === `${this.selected}`; + const disabled = this.disabled || !isEnabled(radio); + const canBeFocused = radio.checked && !disabled; + if (canBeFocused) { + radio.focusable = true; + noneMadeFocusable = false; } else { - return; + radio.focusable = false; } - - const radio = enabledRadios[selectedIndex]; - const name = `${radio.name}`; - if (this.selected !== name) { - event.preventDefault(); - this.selected = name; - radio.focus(); + radio.setAttribute('aria-disabled', `${disabled}`); + }); + this.setAttribute('aria-disabled', `${this.disabled}`); + if (noneMadeFocusable && !this.disabled) { + const radio = this.buttons_.find(isEnabled); + if (radio) { + radio.focusable = true; } - }, + } + } +} - /** - * @return {!RegExp} - * @private - */ - computeSelectableRegExp_() { - const tags = this.selectableElements.split(', ').join('|'); - return new RegExp(`^(${tags})$`, 'i'); - }, - - /** - * @param {!Event} event - * @private - */ - onClick_(event) { - const path = event.composedPath(); - if (path.some(target => /^a$/i.test(target.tagName))) { - return; - } - const target = /** @type {!CrRadioButtonElement} */ ( - path.find(n => this.selectableRegExp_.test(n.tagName))); - if (target && this.buttons_.includes(target)) { - this.select_(/** @type {!CrRadioButtonElement} */ (target)); - } - }, - - /** @private */ - populate_() { - // TODO(crbug.com/738611): After migration to Polymer 2, remove - // Polymer 1 references. - this.buttons_ = Polymer.DomIf ? - this.$$('slot') - .assignedNodes({flatten: true}) - .filter(n => this.selectableRegExp_.test(n.tagName)) : - this.queryAllEffectiveChildren(this.selectableElements); - this.buttonEventTracker_.removeAll(); - this.buttons_.forEach(el => { - this.buttonEventTracker_.add( - el, 'disabled-changed', () => this.populate_()); - this.buttonEventTracker_.add( - el, 'name-changed', () => this.populate_()); - }); - this.update_(); - }, - - /** - * @param {!CrRadioButtonElement} button - * @private - */ - select_(button) { - if (!isEnabled(button)) { - return; - } - - const name = `${button.name}`; - if (this.selected !== name) { - this.selected = name; - } - }, - - /** - * @param {!Element} button - * @return {boolean} - * @private - */ - isButtonEnabledAndSelected_(button) { - return !this.disabled && button.checked && isEnabled(button); - }, - - /** @private */ - update_() { - if (!this.buttons_) { - return; - } - let noneMadeFocusable = true; - this.buttons_.forEach(radio => { - radio.checked = this.selected !== undefined && - `${radio.name}` === `${this.selected}`; - const disabled = this.disabled || !isEnabled(radio); - const canBeFocused = radio.checked && !disabled; - if (canBeFocused) { - radio.focusable = true; - noneMadeFocusable = false; - } else { - radio.focusable = false; - } - radio.setAttribute('aria-disabled', `${disabled}`); - }); - this.setAttribute('aria-disabled', `${this.disabled}`); - if (noneMadeFocusable && !this.disabled) { - const radio = this.buttons_.find(isEnabled); - if (radio) { - radio.focusable = true; - } - } - }, - }); -})(); +customElements.define(CrRadioGroupElement.is, CrRadioGroupElement);
diff --git a/weblayer/browser/permissions/permission_manager_factory.cc b/weblayer/browser/permissions/permission_manager_factory.cc index ef813c2..b13d7428 100644 --- a/weblayer/browser/permissions/permission_manager_factory.cc +++ b/weblayer/browser/permissions/permission_manager_factory.cc
@@ -126,7 +126,7 @@ continue; #endif ContentSettingsType content_settings_type = - permissions::PermissionUtil::PermissionTypeToContentSetting(type); + permissions::PermissionUtil::PermissionTypeToContentSettingType(type); if (permission_contexts.find(content_settings_type) == permission_contexts.end()) { permission_contexts[content_settings_type] =
diff --git a/weblayer/browser/permissions/weblayer_permissions_client.cc b/weblayer/browser/permissions/weblayer_permissions_client.cc index e099327..6cd171c 100644 --- a/weblayer/browser/permissions/weblayer_permissions_client.cc +++ b/weblayer/browser/permissions/weblayer_permissions_client.cc
@@ -12,7 +12,6 @@ #include "weblayer/browser/cookie_settings_factory.h" #include "weblayer/browser/host_content_settings_map_factory.h" #include "weblayer/browser/permissions/permission_decision_auto_blocker_factory.h" -#include "weblayer/browser/permissions/permission_manager_factory.h" #include "weblayer/browser/subresource_filter_profile_context_factory.h" #if BUILDFLAG(IS_ANDROID) @@ -63,11 +62,6 @@ return nullptr; } -permissions::PermissionManager* WebLayerPermissionsClient::GetPermissionManager( - content::BrowserContext* browser_context) { - return PermissionManagerFactory::GetForBrowserContext(browser_context); -} - permissions::ObjectPermissionContextBase* WebLayerPermissionsClient::GetChooserContext( content::BrowserContext* browser_context,
diff --git a/weblayer/browser/permissions/weblayer_permissions_client.h b/weblayer/browser/permissions/weblayer_permissions_client.h index a193c0ea..a772aeb3 100644 --- a/weblayer/browser/permissions/weblayer_permissions_client.h +++ b/weblayer/browser/permissions/weblayer_permissions_client.h
@@ -30,8 +30,6 @@ content::BrowserContext* browser_context) override; permissions::PermissionDecisionAutoBlocker* GetPermissionDecisionAutoBlocker( content::BrowserContext* browser_context) override; - permissions::PermissionManager* GetPermissionManager( - content::BrowserContext* browser_context) override; permissions::ObjectPermissionContextBase* GetChooserContext( content::BrowserContext* browser_context, ContentSettingsType type) override;
diff --git a/weblayer/browser/url_bar/page_info_browsertest.cc b/weblayer/browser/url_bar/page_info_browsertest.cc index b5e8fd7..ab6368a2 100644 --- a/weblayer/browser/url_bar/page_info_browsertest.cc +++ b/weblayer/browser/url_bar/page_info_browsertest.cc
@@ -8,6 +8,8 @@ #include "components/content_settings/core/common/content_settings.h" #include "components/page_info/android/page_info_client.h" #include "components/page_info/page_info_delegate.h" +#include "third_party/blink/public/common/permissions/permission_utils.h" +#include "url/origin.h" #include "weblayer/browser/tab_impl.h" #include "weblayer/browser/url_bar/page_info_delegate_impl.h" #include "weblayer/public/navigation_controller.h" @@ -70,7 +72,7 @@ EXPECT_TRUE(page_info_delegate->GetContentSettings()); } -IN_PROC_BROWSER_TEST_F(PageInfoBrowserTest, PermissionStatus) { +IN_PROC_BROWSER_TEST_F(PageInfoBrowserTest, PermissionResult) { std::unique_ptr<PageInfoDelegate> page_info_delegate = page_info::GetPageInfoClient()->CreatePageInfoDelegate(GetWebContents()); ASSERT_TRUE(page_info_delegate); @@ -83,7 +85,8 @@ // Check that |page_info_delegate| returns expected ContentSettingsType. EXPECT_EQ(page_info_delegate - ->GetPermissionStatus(ContentSettingsType::NOTIFICATIONS, url) + ->GetPermissionResult(blink::PermissionType::NOTIFICATIONS, + url::Origin::Create(url)) .content_setting, CONTENT_SETTING_BLOCK); }
diff --git a/weblayer/browser/url_bar/page_info_delegate_impl.cc b/weblayer/browser/url_bar/page_info_delegate_impl.cc index a3ae2bbd..687a31d 100644 --- a/weblayer/browser/url_bar/page_info_delegate_impl.cc +++ b/weblayer/browser/url_bar/page_info_delegate_impl.cc
@@ -5,16 +5,17 @@ #include "weblayer/browser/url_bar/page_info_delegate_impl.h" #include "build/build_config.h" -#include "components/permissions/permission_manager.h" #include "components/security_interstitials/content/stateful_ssl_host_state_delegate.h" #include "components/security_state/content/content_utils.h" #include "components/subresource_filter/content/browser/subresource_filter_content_settings_manager.h" #include "components/subresource_filter/content/browser/subresource_filter_profile_context.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_result.h" +#include "url/origin.h" #include "weblayer/browser/host_content_settings_map_factory.h" #include "weblayer/browser/page_specific_content_settings_delegate.h" #include "weblayer/browser/permissions/permission_decision_auto_blocker_factory.h" -#include "weblayer/browser/permissions/permission_manager_factory.h" #include "weblayer/browser/stateful_ssl_host_state_delegate_factory.h" #include "weblayer/browser/subresource_filter_profile_context_factory.h" @@ -55,11 +56,14 @@ } #endif -permissions::PermissionResult PageInfoDelegateImpl::GetPermissionStatus( - ContentSettingsType type, - const GURL& site_url) { - return PermissionManagerFactory::GetForBrowserContext(GetBrowserContext()) - ->GetPermissionStatusForDisplayOnSettingsUI(type, site_url); +permissions::PermissionResult PageInfoDelegateImpl::GetPermissionResult( + blink::PermissionType permission, + const url::Origin& origin) { + content::PermissionResult permission_result = + GetBrowserContext() + ->GetPermissionController() + ->GetPermissionResultForOriginWithoutContext(permission, origin); + return permissions::PermissionUtil::ToPermissionResult(permission_result); } #if !BUILDFLAG(IS_ANDROID)
diff --git a/weblayer/browser/url_bar/page_info_delegate_impl.h b/weblayer/browser/url_bar/page_info_delegate_impl.h index 7c3062f..1d666633a 100644 --- a/weblayer/browser/url_bar/page_info_delegate_impl.h +++ b/weblayer/browser/url_bar/page_info_delegate_impl.h
@@ -32,9 +32,9 @@ void OnUserActionOnPasswordUi(safe_browsing::WarningAction action) override; std::u16string GetWarningDetailText() override; #endif - permissions::PermissionResult GetPermissionStatus( - ContentSettingsType type, - const GURL& site_url) override; + permissions::PermissionResult GetPermissionResult( + blink::PermissionType permission, + const url::Origin& origin) override; #if !BUILDFLAG(IS_ANDROID) bool CreateInfoBarDelegate() override;