diff --git a/AUTHORS b/AUTHORS index 2244e67..9cc81a4 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -1012,6 +1012,7 @@ Prashant Hiremath <prashhir@cisco.com> Prashant Nevase <prashant.n@samsung.com> Prashant Patil <prashant.patil@imgtec.com> +Pratham <prathamIN@proton.me> Praveen Akkiraju <praveen.anp@samsung.com> Preeti Nayak <preeti.nayak@samsung.com> Pritam Nikam <pritam.nikam@samsung.com>
diff --git a/DEPS b/DEPS index f588a66..73435d6 100644 --- a/DEPS +++ b/DEPS
@@ -300,15 +300,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': '79088c6b7a33d69358e79bbd8bb90db71ecd6564', + 'skia_revision': 'ef226c5a7930c04e78f987ff7bfb14f487baf79f', # 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': '0f44e4c2a6fe21c4ef4cf1f1fba2aa145209d91d', + 'v8_revision': 'aa5ec7646265bd97a4ecd51d2bdcfeae116253d8', # 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': 'c04ad8e025ee06b64b52ff7009a19fb7c1e720a4', + 'angle_revision': 'ae0f0f47e1b4cb3ac7e8919a2930ca174a7f5a5d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -387,7 +387,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'cc55777c34d501ad6be16c52e17f318b0822a1c3', + 'devtools_frontend_revision': '70475a9b48dddc74a07cd67b2be714b98e8458a8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -427,7 +427,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '30dc1b5abb1f90cf32a16008688ebba4476e0e55', + 'dawn_revision': '55e57b362bc99bcd9db4bea8781906daf2d37e31', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -463,7 +463,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'cros_components_revision': '29226ca637ca0a5cd8348994c0798c7416b78244', + 'cros_components_revision': '0c2d6bae878ffcdd629744501166852beb64384e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -803,7 +803,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '26ebce4f7765b4b6881b238930863e750e134a60', + 'dac084598c86c1719fce71aedab9fcdbcecf54bb', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1233,7 +1233,7 @@ Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '20ada862d00f9533e867112b95b36ac2e2ec3ada', + 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '7b4ebf8878d739aa9fad8fe292301d0613f32a5e', 'condition': 'checkout_src_internal', }, @@ -1700,7 +1700,7 @@ Var('pdfium_git') + '/pdfium.git' + '@' + Var('pdfium_revision'), 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '87d4934194957d4d3073209cd450c197843fe25a', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'f7a6f0099ec3287ef9496bac0a27d0405b9fb4c3', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1845,7 +1845,7 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@2968842d10ac82d571ba996e0a81bd5eb11816cf', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@dc49e5c6de1eb6410fb92ab591891ed951eee02e', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907', @@ -1885,7 +1885,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'b033a4f1ae4a0e19ae4d5563fae023001bbf570f', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '0483755f4e4b362fdd8aeb35e86df3f6f5ceef9e', + Var('webrtc_git') + '/src.git' + '@' + '15feded162a254474a3aa7c573724b5ed460a57b', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -2038,7 +2038,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/projector_app/app', - 'version': 'MqvBJn3bTBo7m4NpvMicINE2i_MCX3Rxupza4aKSUMkC', + 'version': 'D8-w6E8xqGQGNB8P70FyWLHOXBlmZcoAKid5nL8JbHUC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -4174,7 +4174,7 @@ 'src/ios_internal': { 'url': '{chrome_git}/chrome/ios_internal.git' + '@' + - 'eaf3983e83a2fc7122f713828677293ee0dbbe93', + '8450392c60de3eddbc68e3d0d51fe794451f312b', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index 7fe85b1..3c56044 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -626,8 +626,6 @@ ":common_platform_services_java", ":common_variations_java", ":resources", - "//android_webview:common_platform_services_java", - "//android_webview/proto:aw_variations_seed_proto_java", "//android_webview/proto:metrics_bridge_records_proto_java", "//base:base_java", "//base:jni_java",
diff --git a/android_webview/java/src/org/chromium/android_webview/AwDevToolsServer.java b/android_webview/java/src/org/chromium/android_webview/AwDevToolsServer.java index 81cb368..c70d296 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwDevToolsServer.java +++ b/android_webview/java/src/org/chromium/android_webview/AwDevToolsServer.java
@@ -4,12 +4,14 @@ package org.chromium.android_webview; +import org.chromium.android_webview.common.Lifetime; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeMethods; /** * Controller for Remote Web Debugging (Developer Tools). */ +@Lifetime.Singleton @JNINamespace("android_webview") public class AwDevToolsServer {
diff --git a/android_webview/java/src/org/chromium/android_webview/AwDisplayCutoutController.java b/android_webview/java/src/org/chromium/android_webview/AwDisplayCutoutController.java index f3922a7..f386ff4 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwDisplayCutoutController.java +++ b/android_webview/java/src/org/chromium/android_webview/AwDisplayCutoutController.java
@@ -13,6 +13,7 @@ import androidx.annotation.RequiresApi; import androidx.annotation.VisibleForTesting; +import org.chromium.android_webview.common.Lifetime; import org.chromium.base.Log; /** @@ -21,6 +22,7 @@ * This object should be constructed in WebView's constructor to support set listener logic for * Android P and above. */ +@Lifetime.WebView @RequiresApi(Build.VERSION_CODES.P) public class AwDisplayCutoutController { private static final boolean DEBUG = false;
diff --git a/android_webview/java/src/org/chromium/android_webview/AwDisplayModeController.java b/android_webview/java/src/org/chromium/android_webview/AwDisplayModeController.java index 29b26f7f..8ee5028 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwDisplayModeController.java +++ b/android_webview/java/src/org/chromium/android_webview/AwDisplayModeController.java
@@ -9,6 +9,7 @@ import android.graphics.Rect; import android.view.View; +import org.chromium.android_webview.common.Lifetime; import org.chromium.base.Log; import org.chromium.blink.mojom.DisplayMode; @@ -18,6 +19,7 @@ * Display mode will be used for display cutout controller's internal implementation since we only * apply display cutout to fullscreen mode. Also, display mode will be reported as CSS property. */ +@Lifetime.WebView public class AwDisplayModeController { private static final boolean DEBUG = false; private static final String TAG = "DisplayMode";
diff --git a/android_webview/nonembedded/BUILD.gn b/android_webview/nonembedded/BUILD.gn index 06c44fd4..1f5cd97 100644 --- a/android_webview/nonembedded/BUILD.gn +++ b/android_webview/nonembedded/BUILD.gn
@@ -130,7 +130,6 @@ "//android_webview:common_java", "//android_webview:common_platform_services_java", "//android_webview:common_variations_java", - "//android_webview/proto:aw_variations_seed_proto_java", "//android_webview/proto:metrics_bridge_records_proto_java", "//base:base_java", "//base:jni_java",
diff --git a/ash/app_list/app_list_presenter_unittest.cc b/ash/app_list/app_list_presenter_unittest.cc index abde981..57cd0b45 100644 --- a/ash/app_list/app_list_presenter_unittest.cc +++ b/ash/app_list/app_list_presenter_unittest.cc
@@ -3792,7 +3792,8 @@ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState()); } -TEST_F(AppListPresenterTest, ClickingShelfArrowDoesNotHideAppList) { +// TODO(b/283753290): Deflake and re-enable the test. +TEST_F(AppListPresenterTest, DISABLED_ClickingShelfArrowDoesNotHideAppList) { // Add enough shelf items for the shelf to enter overflow. Shelf* const shelf = GetPrimaryShelf(); ScrollableShelfView* const scrollable_shelf_view =
diff --git a/ash/booting/booting_animation_controller.cc b/ash/booting/booting_animation_controller.cc index efbc8f9a..e3deba73 100644 --- a/ash/booting/booting_animation_controller.cc +++ b/ash/booting/booting_animation_controller.cc
@@ -11,9 +11,11 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/shell.h" #include "base/files/file_util.h" +#include "base/location.h" #include "base/system/sys_info.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" +#include "base/time/time.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -52,6 +54,12 @@ BootingAnimationController::~BootingAnimationController() = default; void BootingAnimationController::Show() { + // If data fetch failed, notify caller immediately without showing the widget. + if (data_fetch_failed_.has_value() && data_fetch_failed_.value()) { + std::move(animation_played_callback_).Run(); + return; + } + widget_ = std::make_unique<views::Widget>(); views::Widget::InitParams params; params.delegate = new views::WidgetDelegate; // Takes ownership. @@ -73,7 +81,7 @@ params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent; widget_->Init(std::move(params)); - if (animation_data_.empty()) { + if (!data_fetch_failed_.has_value()) { LOG(ERROR) << "Booting animation isn't ready yet."; start_once_ready_ = true; return; @@ -87,13 +95,21 @@ // Don't wait for GPU to be ready in non-ChromeOS environment. if (!base::SysInfo::IsRunningOnChromeOS()) { - is_gpu_ready_ = true; - scoped_display_configurator_observer_.Reset(); + IgnoreGpuReadiness(); + return; } - if (!scoped_display_configurator_observer_.IsObserving()) { - Show(); + // If we are still waiting for the signal from DisplayConfigurator wait for + // not more than a second and play the animation anyway. + if (scoped_display_configurator_observer_.IsObserving()) { + base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&BootingAnimationController::IgnoreGpuReadiness, + weak_factory_.GetWeakPtr()), + base::TimeDelta(base::Seconds(1))); + return; } + Show(); } void BootingAnimationController::Finish() { @@ -138,9 +154,15 @@ void BootingAnimationController::OnAnimationDataFetched(std::string data) { if (data.empty()) { LOG(ERROR) << "No booting animation file available."; + data_fetch_failed_ = true; + // Notify caller immediately that there is no animation file. + if (!animation_played_callback_.is_null()) { + std::move(animation_played_callback_).Run(); + } return; } + data_fetch_failed_ = false; animation_data_ = std::move(data); if (start_once_ready_) { @@ -164,4 +186,18 @@ view->Play(); } +void BootingAnimationController::IgnoreGpuReadiness() { + // Don't do anything if we already stopped observing DisplayConfigurator. + if (!scoped_display_configurator_observer_.IsObserving()) { + return; + } + LOG(ERROR) << "Ignore the readinees of the GPU and play the animation."; + + is_gpu_ready_ = true; + scoped_display_configurator_observer_.Reset(); + if (!animation_played_callback_.is_null()) { + Show(); + } +} + } // namespace ash
diff --git a/ash/booting/booting_animation_controller.h b/ash/booting/booting_animation_controller.h index b387ded40..8bcbbe1 100644 --- a/ash/booting/booting_animation_controller.h +++ b/ash/booting/booting_animation_controller.h
@@ -49,9 +49,11 @@ void Show(); void OnAnimationDataFetched(std::string data); void StartAnimation(); + void IgnoreGpuReadiness(); std::string animation_data_; std::unique_ptr<views::Widget> widget_; + absl::optional<bool> data_fetch_failed_; bool start_once_ready_ = false; bool was_shown_ = false; bool is_gpu_ready_ = false;
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc index 8639534a..026bfc9 100644 --- a/ash/login/ui/login_auth_user_view.cc +++ b/ash/login/ui/login_auth_user_view.cc
@@ -40,6 +40,7 @@ #include "ash/system/time/time_of_day.h" #include "base/functional/bind.h" #include "base/i18n/time_formatting.h" +#include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/memory/raw_ptr.h" #include "base/strings/string_util.h" @@ -794,6 +795,11 @@ DCHECK(callbacks.on_easy_unlock_icon_hovered); DCHECK(callbacks.on_auth_factor_is_hiding_password_changed); DCHECK_NE(user.basic_user_info.type, user_manager::USER_TYPE_PUBLIC_ACCOUNT); + if (Shell::Get()->login_screen_controller()->IsAuthenticating()) { + // TODO(b/276246832): We should avoid re-layouting during Authentication. + LOG(WARNING) + << "LoginAuthUserView::LoginAuthUserView called during Authentication."; + } // Build child views. auto user_view = std::make_unique<LoginUserView>(
diff --git a/ash/login/ui/login_password_view.cc b/ash/login/ui/login_password_view.cc index 7d307c8..e804c05 100644 --- a/ash/login/ui/login_password_view.cc +++ b/ash/login/ui/login_password_view.cc
@@ -6,6 +6,7 @@ #include "ash/accessibility/accessibility_controller_impl.h" #include "ash/constants/ash_features.h" +#include "ash/login/login_screen_controller.h" #include "ash/login/ui/arrow_button_view.h" #include "ash/login/ui/horizontal_image_sequence_animation_decoder.h" #include "ash/login/ui/hover_notifier.h" @@ -20,6 +21,7 @@ #include "ash/style/ash_color_provider.h" #include "ash/style/color_util.h" #include "base/functional/bind.h" +#include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -767,6 +769,13 @@ } void LoginPasswordView::SetReadOnly(bool read_only) { + if (!read_only && + Shell::Get()->login_screen_controller()->IsAuthenticating()) { + // TODO(b/276246832): We shouldn't enable the LoginPasswordView during + // Authentication. + LOG(WARNING) << "LoginPasswordView::SetReadOnly called with false during " + "Authentication."; + } textfield_->SetReadOnly(read_only); textfield_->SetCursorEnabled(!read_only); UpdateUiState();
diff --git a/ash/login/ui/login_pin_input_view.cc b/ash/login/ui/login_pin_input_view.cc index d3d1ff08..33458a4 100644 --- a/ash/login/ui/login_pin_input_view.cc +++ b/ash/login/ui/login_pin_input_view.cc
@@ -5,11 +5,14 @@ #include "ash/login/ui/login_pin_input_view.h" #include "ash/constants/ash_features.h" +#include "ash/login/login_screen_controller.h" #include "ash/login/ui/access_code_input.h" +#include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/style/ash_color_id.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" +#include "base/logging.h" #include "base/strings/utf_string_conversions.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/accessibility/ax_enums.mojom-shared.h" @@ -243,6 +246,13 @@ } void LoginPinInputView::SetReadOnly(bool read_only) { + if (!read_only && + Shell::Get()->login_screen_controller()->IsAuthenticating()) { + // TODO(b/276246832): We shouldn't enable the LoginPinInputView during + // Authentication. + LOG(WARNING) << "LoginPinInputView::SetReadOnly called with false during " + "Authentication."; + } is_read_only_ = read_only; code_input_->SetReadOnly(read_only); }
diff --git a/ash/system/unified/date_tray_unittest.cc b/ash/system/unified/date_tray_unittest.cc index 56fc3bb..590a30f 100644 --- a/ash/system/unified/date_tray_unittest.cc +++ b/ash/system/unified/date_tray_unittest.cc
@@ -188,7 +188,7 @@ EXPECT_FALSE(AreContentsViewShown()); } -TEST_P(DateTrayTest, ShowTasksComboModel) { +TEST_P(DateTrayTest, DISABLED_ShowTasksComboModel) { LeftClickOn(GetDateTray()); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(IsBubbleShown());
diff --git a/ash/webui/camera_app_ui/resources/js/main.ts b/ash/webui/camera_app_ui/resources/js/main.ts index 6b0f3d2..eb9f2d6 100644 --- a/ash/webui/camera_app_ui/resources/js/main.ts +++ b/ash/webui/camera_app_ui/resources/js/main.ts
@@ -121,6 +121,7 @@ windowController.addListener(() => nav.layoutShownViews()); util.setupI18nElements(document.body); + this.setupTooltip(); this.setupToggles(); localStorage.cleanup(); this.setupEffect(); @@ -137,6 +138,47 @@ } /** + * Sets up tooltips for elements having `i18n-label` attribute. This method + * also setup tooltips for the elements: + * * Added to the DOM and have a `i18n-label` attribute. + * * Newly set with a `i18n-label` attribute. + * + * Note `i18n-label` attribute should not be removed from elements. + */ + private setupTooltip() { + const tooltipAttribute = 'i18n-label'; + const elements = + Array.from(dom.getAll(`[${tooltipAttribute}]`, HTMLElement)); + tooltip.setup(elements); + const observer = new MutationObserver((mutations) => { + const elements: HTMLElement[] = []; + for (const mutation of mutations) { + if (mutation.type === 'childList') { + for (const node of mutation.addedNodes) { + if (node instanceof HTMLElement && + node.hasAttribute(tooltipAttribute)) { + elements.push(node); + } + } + } else if (mutation.type === 'attributes') { + const {target: node, attributeName, oldValue} = mutation; + if (node instanceof HTMLElement && + attributeName === tooltipAttribute && oldValue === null) { + elements.push(node); + } + } + } + tooltip.setup(elements); + }); + observer.observe(document.body, { + subtree: true, + childList: true, + attributes: true, + attributeOldValue: true, + }); + } + + /** * Sets up toggles (checkbox and radio) by data attributes. */ private setupToggles() {
diff --git a/ash/webui/camera_app_ui/resources/js/tooltip.ts b/ash/webui/camera_app_ui/resources/js/tooltip.ts index a994a01..e0651f6 100644 --- a/ash/webui/camera_app_ui/resources/js/tooltip.ts +++ b/ash/webui/camera_app_ui/resources/js/tooltip.ts
@@ -89,9 +89,8 @@ * Sets up tooltips for elements. * * @param elements Elements whose tooltips to be shown. - * @return Elements whose tooltips have been set up. */ -export function setup(elements: HTMLElement[]): HTMLElement[] { +export function setup(elements: HTMLElement[]): void { wrapper = dom.get('#tooltip', HTMLElement); for (const el of elements) { function handler() { @@ -100,9 +99,10 @@ hide(); } } - el.addEventListener('mouseout', handler); + el.addEventListener('mouseleave', handler); el.addEventListener('click', handler); - el.addEventListener('mouseover', () => show(el)); + el.addEventListener('blur', handler); + el.addEventListener('mouseenter', () => show(el)); + el.addEventListener('focus', () => show(el)); } - return elements; }
diff --git a/ash/webui/camera_app_ui/resources/js/util.ts b/ash/webui/camera_app_ui/resources/js/util.ts index 39bd420b..7edeb7f 100644 --- a/ash/webui/camera_app_ui/resources/js/util.ts +++ b/ash/webui/camera_app_ui/resources/js/util.ts
@@ -8,7 +8,6 @@ import {I18nString} from './i18n_string.js'; import * as loadTimeData from './models/load_time_data.js'; import * as state from './state.js'; -import * as tooltip from './tooltip.js'; import {AspectRatioSet, Facing, FpsRange, Resolution} from './type.js'; /** @@ -188,11 +187,10 @@ element.setAttribute( 'tooltip-false', getMessage(element, 'i18n-tooltip-false')); } - for (const element of getElements('i18n-aria')) { - setAriaLabel(element, 'i18n-aria'); - } - for (const element of tooltip.setup(getElements('i18n-label'))) { - setAriaLabel(element, 'i18n-label'); + for (const attribute of ['i18n-aria', 'i18n-label']) { + for (const element of getElements(attribute)) { + setAriaLabel(element, attribute); + } } }
diff --git a/ash/webui/camera_app_ui/resources/js/views/document_fix_mode.ts b/ash/webui/camera_app_ui/resources/js/views/document_fix_mode.ts index 194e636..0c756c0b 100644 --- a/ash/webui/camera_app_ui/resources/js/views/document_fix_mode.ts +++ b/ash/webui/camera_app_ui/resources/js/views/document_fix_mode.ts
@@ -556,7 +556,7 @@ const cornerIndex = (this.getRotationIndex(this.rotation) + index) % this.corners.length; const cornElement = this.corners[cornerIndex].el; - cornElement.setAttribute('i18n-aria', label); + cornElement.setAttribute('i18n-label', label); } util.setupI18nElements(this.root); }
diff --git a/base/allocator/partition_allocator/address_pool_manager.cc b/base/allocator/partition_allocator/address_pool_manager.cc index 3604507..63a9c467 100644 --- a/base/allocator/partition_allocator/address_pool_manager.cc +++ b/base/allocator/partition_allocator/address_pool_manager.cc
@@ -51,7 +51,7 @@ void AddressPoolManager::Add(pool_handle handle, uintptr_t ptr, size_t length) { PA_DCHECK(!(ptr & kSuperPageOffsetMask)); PA_DCHECK(!((ptr + length) & kSuperPageOffsetMask)); - PA_CHECK(handle > 0 && handle <= std::size(aligned_pools_.pools_)); + PA_CHECK(handle > 0 && handle <= std::size(pools_)); Pool* pool = GetPool(handle); PA_CHECK(!pool->IsInitialized()); @@ -79,8 +79,8 @@ } void AddressPoolManager::ResetForTesting() { - for (size_t i = 0; i < std::size(aligned_pools_.pools_); ++i) { - aligned_pools_.pools_[i].Reset(); + for (size_t i = 0; i < std::size(pools_); ++i) { + pools_[i].Reset(); } } @@ -554,11 +554,11 @@ // in Pool. void AddressPoolManager::AssertThreadIsolatedLayout() { constexpr size_t last_pool_offset = - offsetof(AlignedPools, pools_) + sizeof(Pool) * (kNumPools - 1); + offsetof(AddressPoolManager, pools_) + sizeof(Pool) * (kNumPools - 1); constexpr size_t alloc_bitset_offset = last_pool_offset + offsetof(Pool, alloc_bitset_); static_assert(alloc_bitset_offset % PA_THREAD_ISOLATED_ALIGN_SZ == 0); - static_assert(sizeof(AlignedPools) % PA_THREAD_ISOLATED_ALIGN_SZ == 0); + static_assert(sizeof(AddressPoolManager) % PA_THREAD_ISOLATED_ALIGN_SZ == 0); } #endif // BUILDFLAG(ENABLE_THREAD_ISOLATION)
diff --git a/base/allocator/partition_allocator/address_pool_manager.h b/base/allocator/partition_allocator/address_pool_manager.h index 9791158..b7105883 100644 --- a/base/allocator/partition_allocator/address_pool_manager.h +++ b/base/allocator/partition_allocator/address_pool_manager.h
@@ -51,7 +51,8 @@ // to judge whether a given address is in a pool that supports BackupRefPtr or // in a pool that doesn't. All PartitionAlloc allocations must be in either of // the pools. -class PA_COMPONENT_EXPORT(PARTITION_ALLOC) AddressPoolManager { +class PA_COMPONENT_EXPORT(PARTITION_ALLOC) + PA_THREAD_ISOLATED_ALIGN AddressPoolManager { public: static AddressPoolManager& GetInstance(); @@ -118,7 +119,6 @@ #if BUILDFLAG(HAS_64_BIT_POINTERS) - struct AlignedPools; class Pool { public: constexpr Pool() = default; @@ -147,7 +147,7 @@ // lock can be used without acquiring write-permission first (via // DumpStats()). So instead of protecting the whole variable, we only // protect the memory after the lock. - // See the alignment of `aligned_pools_` below. + // See the alignment of ` below. Lock lock_; // The bitset stores the allocation state of the address pool. 1 bit per @@ -167,14 +167,13 @@ #endif #if BUILDFLAG(ENABLE_THREAD_ISOLATION) - friend void AddressPoolManager::AssertThreadIsolatedLayout(); - friend struct AlignedPools; + friend class AddressPoolManager; #endif // BUILDFLAG(ENABLE_THREAD_ISOLATION) }; PA_ALWAYS_INLINE Pool* GetPool(pool_handle handle) { PA_DCHECK(kNullPoolHandle < handle && handle <= kNumPools); - return &aligned_pools_.pools_[handle - 1]; + return &pools_[handle - 1]; } // Gets the stats for the pool identified by `handle`, if @@ -186,15 +185,11 @@ // front of the pools so that the isolated one starts on a page boundary. // We also skip the Lock at the beginning of the pool since it needs to be // used in contexts where we didn't enable write access to the pool memory. - struct AlignedPools { - char pad_[PA_THREAD_ISOLATED_ARRAY_PAD_SZ_WITH_OFFSET( - Pool, - kNumPools, - offsetof(Pool, alloc_bitset_))] = {}; - Pool pools_[kNumPools]; - char pad_after_[PA_THREAD_ISOLATED_FILL_PAGE_SZ( - sizeof(Pool) - offsetof(Pool, alloc_bitset_))] = {}; - } aligned_pools_ PA_THREAD_ISOLATED_ALIGN; + char pad_[PA_THREAD_ISOLATED_ARRAY_PAD_SZ_WITH_OFFSET( + Pool, + kNumPools, + offsetof(Pool, alloc_bitset_))] = {}; + Pool pools_[kNumPools]; #endif // BUILDFLAG(HAS_64_BIT_POINTERS)
diff --git a/base/allocator/partition_allocator/reservation_offset_table.cc b/base/allocator/partition_allocator/reservation_offset_table.cc index 6b0a421c..2d53cd2 100644 --- a/base/allocator/partition_allocator/reservation_offset_table.cc +++ b/base/allocator/partition_allocator/reservation_offset_table.cc
@@ -9,9 +9,7 @@ namespace partition_alloc::internal { #if BUILDFLAG(HAS_64_BIT_POINTERS) -ReservationOffsetTable::_PaddedReservationOffsetTables - ReservationOffsetTable::padded_reservation_offset_tables_ - PA_THREAD_ISOLATED_ALIGN; +ReservationOffsetTable ReservationOffsetTable::singleton_; #else ReservationOffsetTable::_ReservationOffsetTable ReservationOffsetTable::reservation_offset_table_;
diff --git a/base/allocator/partition_allocator/reservation_offset_table.h b/base/allocator/partition_allocator/reservation_offset_table.h index 98f94912..73ea576 100644 --- a/base/allocator/partition_allocator/reservation_offset_table.h +++ b/base/allocator/partition_allocator/reservation_offset_table.h
@@ -64,7 +64,8 @@ // to further determine which part of the super page is used by // PartitionAlloc. This isn't a problem in 64-bit mode, where allocation // granularity is kSuperPageSize. -class PA_COMPONENT_EXPORT(PARTITION_ALLOC) ReservationOffsetTable { +class PA_COMPONENT_EXPORT(PARTITION_ALLOC) + PA_THREAD_ISOLATED_ALIGN ReservationOffsetTable { public: #if BUILDFLAG(HAS_64_BIT_POINTERS) // There is one reservation offset table per Pool in 64-bit mode. @@ -99,15 +100,10 @@ // If thread isolation support is enabled, we need to write-protect the tables // of the thread isolated pool. For this, we need to pad the tables so that // the thread isolated ones start on a page boundary. - struct _PaddedReservationOffsetTables { - char pad_[PA_THREAD_ISOLATED_ARRAY_PAD_SZ(_ReservationOffsetTable, - kNumPools)] = {}; - struct _ReservationOffsetTable tables[kNumPools]; - char pad_after_[PA_THREAD_ISOLATED_FILL_PAGE_SZ( - sizeof(_ReservationOffsetTable))] = {}; - }; - static PA_CONSTINIT _PaddedReservationOffsetTables - padded_reservation_offset_tables_ PA_THREAD_ISOLATED_ALIGN; + char pad_[PA_THREAD_ISOLATED_ARRAY_PAD_SZ(_ReservationOffsetTable, + kNumPools)] = {}; + struct _ReservationOffsetTable tables[kNumPools]; + static PA_CONSTINIT ReservationOffsetTable singleton_; #else // A single table for the entire 32-bit address space. static PA_CONSTINIT struct _ReservationOffsetTable reservation_offset_table_; @@ -117,9 +113,7 @@ #if BUILDFLAG(HAS_64_BIT_POINTERS) PA_ALWAYS_INLINE uint16_t* GetReservationOffsetTable(pool_handle handle) { PA_DCHECK(kNullPoolHandle < handle && handle <= kNumPools); - return ReservationOffsetTable::padded_reservation_offset_tables_ - .tables[handle - 1] - .offsets; + return ReservationOffsetTable::singleton_.tables[handle - 1].offsets; } PA_ALWAYS_INLINE const uint16_t* GetReservationOffsetTableEnd(
diff --git a/base/allocator/partition_allocator/thread_isolation/pkey_unittest.cc b/base/allocator/partition_allocator/thread_isolation/pkey_unittest.cc index 3e695bf5..1fb4d7c0e 100644 --- a/base/allocator/partition_allocator/thread_isolation/pkey_unittest.cc +++ b/base/allocator/partition_allocator/thread_isolation/pkey_unittest.cc
@@ -30,14 +30,13 @@ namespace partition_alloc::internal { -struct IsolatedGlobals { +struct PA_THREAD_ISOLATED_ALIGN IsolatedGlobals { int pkey = kInvalidPkey; - void* isolatedStack; + void* stack; partition_alloc::internal::base::NoDestructor< partition_alloc::PartitionAllocator> allocator{}; - partition_alloc::ThreadSafePartitionRoot* allocatorRoot; -} isolatedGlobals PA_THREAD_ISOLATED_ALIGN; +} isolated_globals; int ProtFromSegmentFlags(ElfW(Word) flags) { int prot = 0; @@ -67,12 +66,12 @@ } uintptr_t start = info->dlpi_addr + phdr->p_vaddr; uintptr_t end = start + phdr->p_memsz; - uintptr_t startPage = RoundDownToSystemPage(start); - uintptr_t endPage = RoundUpToSystemPage(end); - uintptr_t size = endPage - startPage; - PA_PCHECK(PkeyMprotect(reinterpret_cast<void*>(startPage), size, + uintptr_t start_page = RoundDownToSystemPage(start); + uintptr_t end_page = RoundUpToSystemPage(end); + uintptr_t size = end_page - start_page; + PA_PCHECK(PkeyMprotect(reinterpret_cast<void*>(start_page), size, ProtFromSegmentFlags(phdr->p_flags), - isolatedGlobals.pkey) == 0); + isolated_globals.pkey) == 0); } return 0; } @@ -82,19 +81,18 @@ static void PkeyProtectMemory() { PA_PCHECK(dl_iterate_phdr(ProtectROSegments, nullptr) == 0); - PA_PCHECK(PkeyMprotect(&isolatedGlobals, sizeof(isolatedGlobals), - PROT_READ | PROT_WRITE, isolatedGlobals.pkey) == 0); + PA_PCHECK(PkeyMprotect(&isolated_globals, sizeof(isolated_globals), + PROT_READ | PROT_WRITE, isolated_globals.pkey) == 0); - PA_PCHECK(PkeyMprotect(isolatedGlobals.isolatedStack, - kIsolatedThreadStackSize, PROT_READ | PROT_WRITE, - isolatedGlobals.pkey) == 0); + PA_PCHECK(PkeyMprotect(isolated_globals.stack, kIsolatedThreadStackSize, + PROT_READ | PROT_WRITE, isolated_globals.pkey) == 0); } static void InitializeIsolatedThread() { - isolatedGlobals.isolatedStack = + isolated_globals.stack = mmap(nullptr, kIsolatedThreadStackSize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_STACK, -1, 0); - PA_PCHECK(isolatedGlobals.isolatedStack != MAP_FAILED); + PA_PCHECK(isolated_globals.stack != MAP_FAILED); PkeyProtectMemory(); } @@ -102,7 +100,7 @@ void SetUp() override { // SetUp only once, but we can't do it in SetUpTestSuite since that runs // before other PartitionAlloc initialization happened. - if (isolatedGlobals.pkey != kInvalidPkey) { + if (isolated_globals.pkey != kInvalidPkey) { return; } @@ -110,14 +108,13 @@ if (pkey == -1) { return; } - isolatedGlobals.pkey = pkey; + isolated_globals.pkey = pkey; - isolatedGlobals.allocator->init(PartitionOptions{ + isolated_globals.allocator->init(PartitionOptions{ .aligned_alloc = PartitionOptions::AlignedAlloc::kAllowed, .cookie = PartitionOptions::Cookie::kAllowed, - .thread_isolation = ThreadIsolationOption(isolatedGlobals.pkey), + .thread_isolation = ThreadIsolationOption(isolated_globals.pkey), }); - isolatedGlobals.allocatorRoot = isolatedGlobals.allocator->root(); InitializeIsolatedThread(); @@ -125,14 +122,14 @@ } static void TearDownTestSuite() { - if (isolatedGlobals.pkey == kInvalidPkey) { + if (isolated_globals.pkey == kInvalidPkey) { return; } - PA_PCHECK(PkeyMprotect(&isolatedGlobals, sizeof(isolatedGlobals), + PA_PCHECK(PkeyMprotect(&isolated_globals, sizeof(isolated_globals), PROT_READ | PROT_WRITE, kDefaultPkey) == 0); - isolatedGlobals.pkey = kDefaultPkey; + isolated_globals.pkey = kDefaultPkey; InitializeIsolatedThread(); - PkeyFree(isolatedGlobals.pkey); + PkeyFree(isolated_globals.pkey); } }; @@ -141,12 +138,12 @@ // In the final use, we'll likely allow at least read access to the default // pkey. ISOLATED_FUNCTION uint64_t IsolatedAllocFree(void* arg) { - char* buf = (char*)isolatedGlobals.allocatorRoot->AllocWithFlagsNoHooks( + char* buf = (char*)isolated_globals.allocator->root()->AllocWithFlagsNoHooks( 0, 1024, partition_alloc::PartitionPageSize()); if (!buf) { return 0xffffffffffffffffllu; } - isolatedGlobals.allocatorRoot->FreeNoHooks(buf); + isolated_globals.allocator->root()->FreeNoHooks(buf); return kTestReturnValue; } @@ -159,14 +156,14 @@ // order to do this, we need to tag all global read-only memory with our pkey as // well as switch to a pkey-tagged stack. TEST_F(PkeyTest, AllocWithoutDefaultPkey) { - if (isolatedGlobals.pkey == kInvalidPkey) { + if (isolated_globals.pkey == kInvalidPkey) { return; } uint64_t ret; uint32_t pkru_value = 0; for (int pkey = 0; pkey < kNumPkey; pkey++) { - if (pkey != isolatedGlobals.pkey) { + if (pkey != isolated_globals.pkey) { pkru_value |= (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE) << (2 * pkey); } } @@ -245,7 +242,7 @@ : "=r"(ret) : "a"(pkru_value), "c"(0), "d"(0), - "r"(reinterpret_cast<uintptr_t>(isolatedGlobals.isolatedStack) + + "r"(reinterpret_cast<uintptr_t>(isolated_globals.stack) + kIsolatedThreadStackSize - 8) : "memory", "cc", "r8", "r9", "r10", "r11", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", @@ -262,7 +259,7 @@ }; TEST_F(PkeyTest, DumpPkeyPoolStats) { - if (isolatedGlobals.pkey == kInvalidPkey) { + if (isolated_globals.pkey == kInvalidPkey) { return; }
diff --git a/base/allocator/partition_allocator/thread_isolation/thread_isolation.cc b/base/allocator/partition_allocator/thread_isolation/thread_isolation.cc index 3df0ade..dfb836e 100644 --- a/base/allocator/partition_allocator/thread_isolation/thread_isolation.cc +++ b/base/allocator/partition_allocator/thread_isolation/thread_isolation.cc
@@ -18,8 +18,7 @@ namespace partition_alloc::internal { #if BUILDFLAG(PA_DCHECK_IS_ON) -ThreadIsolationSettings ThreadIsolationSettings::settings - PA_THREAD_ISOLATED_ALIGN; +ThreadIsolationSettings ThreadIsolationSettings::settings; #endif void WriteProtectThreadIsolatedMemory(ThreadIsolationOption thread_isolation,
diff --git a/base/allocator/partition_allocator/thread_isolation/thread_isolation.h b/base/allocator/partition_allocator/thread_isolation/thread_isolation.h index 79c575c..7c74e0a 100644 --- a/base/allocator/partition_allocator/thread_isolation/thread_isolation.h +++ b/base/allocator/partition_allocator/thread_isolation/thread_isolation.h
@@ -54,10 +54,9 @@ #if BUILDFLAG(PA_DCHECK_IS_ON) -struct ThreadIsolationSettings { +struct PA_THREAD_ISOLATED_ALIGN ThreadIsolationSettings { bool enabled = false; - char pad_[PA_THREAD_ISOLATED_FILL_PAGE_SZ(sizeof(enabled))] = {}; - static ThreadIsolationSettings settings PA_THREAD_ISOLATED_ALIGN PA_CONSTINIT; + static ThreadIsolationSettings settings PA_CONSTINIT; }; #if BUILDFLAG(ENABLE_PKEYS)
diff --git a/base/message_loop/message_pump_glib.cc b/base/message_loop/message_pump_glib.cc index f2dca14..fca4b535 100644 --- a/base/message_loop/message_pump_glib.cc +++ b/base/message_loop/message_pump_glib.cc
@@ -252,7 +252,7 @@ // this case. struct WorkSource : public GSource { - raw_ptr<MessagePumpGlib, DanglingUntriaged> pump; + raw_ptr<MessagePumpGlib> pump; }; gboolean WorkSourcePrepare(GSource* source, gint* timeout_ms) { @@ -276,12 +276,20 @@ return TRUE; } +void WorkSourceFinalize(GSource* source) { + // Since the WorkSource object memory is managed by glib, WorkSource implicit + // destructor is never called, and thus WorkSource's raw_ptr never release + // its internal reference on the pump pointer. This leads to adding pressure + // to the BRP quarantine. + static_cast<WorkSource*>(source)->pump = nullptr; +} + // I wish these could be const, but g_source_new wants non-const. GSourceFuncs g_work_source_funcs = {WorkSourcePrepare, WorkSourceCheck, - WorkSourceDispatch, nullptr}; + WorkSourceDispatch, WorkSourceFinalize}; struct ObserverSource : public GSource { - raw_ptr<MessagePumpGlib, DanglingUntriaged> pump; + raw_ptr<MessagePumpGlib> pump; }; gboolean ObserverPrepare(GSource* gsource, gint* timeout_ms) { @@ -297,8 +305,13 @@ return source->pump->HandleObserverCheck(); } +void ObserverFinalize(GSource* source) { + // Read the comment in `WorkSourceFinalize`, the issue is exactly the same. + static_cast<ObserverSource*>(source)->pump = nullptr; +} + GSourceFuncs g_observer_funcs = {ObserverPrepare, ObserverCheck, nullptr, - nullptr}; + ObserverFinalize}; struct FdWatchSource : public GSource { raw_ptr<MessagePumpGlib> pump; @@ -323,8 +336,16 @@ return TRUE; } +void FdWatchSourcFinalize(GSource* gsource) { + // Read the comment in `WorkSourceFinalize`, the issue is exactly the same. + auto* source = static_cast<FdWatchSource*>(gsource); + source->pump = nullptr; + source->controller = nullptr; +} + GSourceFuncs g_fd_watch_source_funcs = { - FdWatchSourcePrepare, FdWatchSourceCheck, FdWatchSourceDispatch, nullptr}; + FdWatchSourcePrepare, FdWatchSourceCheck, FdWatchSourceDispatch, + FdWatchSourcFinalize}; } // namespace
diff --git a/build/config/rust.gni b/build/config/rust.gni index a36e1fd8..0629d96 100644 --- a/build/config/rust.gni +++ b/build/config/rust.gni
@@ -19,9 +19,9 @@ # should not be removed. # TODO(crbug.com/1386212): Mac # TODO(crbug.com/1271215): Windows - # TODO(crbug.com/1229419): is_official_build enable_rust = - !is_mac && !is_ios && !is_win && !is_official_build && build_with_chromium + !is_mac && !is_ios && !is_win && + (!is_official_build || is_linux || is_android) && build_with_chromium # As we incrementally enable Rust on mainstream builders, we want to enable # the toolchain (by switching 'enable_rust' to true) while still disabling
diff --git a/cc/metrics/compositor_frame_reporter.cc b/cc/metrics/compositor_frame_reporter.cc index f4bec63..4f75391 100644 --- a/cc/metrics/compositor_frame_reporter.cc +++ b/cc/metrics/compositor_frame_reporter.cc
@@ -1359,49 +1359,41 @@ float total_predicted_delta = 0; bool had_gesture_scrolls = false; + // This handles cases when we have multiple scroll events. Events for dropped + // frames are reported by the reporter for next presented frame which could + // lead to having multiple scroll events. base::TimeTicks input_generation_ts = base::TimeTicks::Max(); base::TimeTicks last_coalesced_ts = base::TimeTicks::Min(); for (const auto& event : events_metrics_) { TRACE_EVENT("input", "GestureType", "gesture", event->type()); + const auto* scroll_update = event->AsScrollUpdate(); + if (!scroll_update) { + continue; + } + + total_predicted_delta += scroll_update->predicted_delta(); + had_gesture_scrolls = true; + input_generation_ts = std::min( + input_generation_ts, event->GetDispatchStageTimestamp( + EventMetrics::DispatchStage::kGenerated)); + last_coalesced_ts = + std::max(last_coalesced_ts, scroll_update->last_timestamp()); + switch (event->type()) { - // TODO(kartarsingh): Clean up common logic here. Related discussion: - // https://crrev.com/c/4430615/19/cc/metrics/compositor_frame_reporter.cc#1393 - case EventMetrics::EventType::kGestureScrollUpdate: - normal_input_count += event->AsScrollUpdate()->coalesced_event_count(); - total_predicted_delta += event->AsScrollUpdate()->predicted_delta(); - had_gesture_scrolls = true; - input_generation_ts = std::min( - input_generation_ts, event->GetDispatchStageTimestamp( - EventMetrics::DispatchStage::kGenerated)); - last_coalesced_ts = std::max(last_coalesced_ts, - event->AsScrollUpdate()->last_timestamp()); - break; case EventMetrics::EventType::kFirstGestureScrollUpdate: - normal_input_count += event->AsScrollUpdate()->coalesced_event_count(); - total_predicted_delta += event->AsScrollUpdate()->predicted_delta(); if (global_trackers_.predictor_jank_tracker) { global_trackers_.predictor_jank_tracker ->ResetCurrentScrollReporting(); } - had_gesture_scrolls = true; - input_generation_ts = std::min( - input_generation_ts, event->GetDispatchStageTimestamp( - EventMetrics::DispatchStage::kGenerated)); - last_coalesced_ts = std::max(last_coalesced_ts, - event->AsScrollUpdate()->last_timestamp()); + ABSL_FALLTHROUGH_INTENDED; + case EventMetrics::EventType::kGestureScrollUpdate: + normal_input_count += scroll_update->coalesced_event_count(); break; case EventMetrics::EventType::kInertialGestureScrollUpdate: - fling_input_count += event->AsScrollUpdate()->coalesced_event_count(); - total_predicted_delta += event->AsScrollUpdate()->predicted_delta(); - had_gesture_scrolls = true; - input_generation_ts = std::min( - input_generation_ts, event->GetDispatchStageTimestamp( - EventMetrics::DispatchStage::kGenerated)); - last_coalesced_ts = std::max(last_coalesced_ts, - event->AsScrollUpdate()->last_timestamp()); + fling_input_count += scroll_update->coalesced_event_count(); break; default: - continue; + NOTREACHED(); } } // To handle web test failures which causes an event to be coalesced with an
diff --git a/cc/metrics/event_metrics.h b/cc/metrics/event_metrics.h index 480fe35..36afa6e 100644 --- a/cc/metrics/event_metrics.h +++ b/cc/metrics/event_metrics.h
@@ -405,9 +405,9 @@ float predicted_delta() const { return predicted_delta_; } - int32_t coalesced_event_count() { return coalesced_event_count_; } + int32_t coalesced_event_count() const { return coalesced_event_count_; } - absl::optional<TraceId> trace_id() { return trace_id_; } + absl::optional<TraceId> trace_id() const { return trace_id_; } void set_predicted_delta(float predicted_delta) { predicted_delta_ = predicted_delta;
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni index d0c8e8f..b2d4650 100644 --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni
@@ -38,7 +38,6 @@ "java/res/drawable-hdpi/ic_dialer_not_found_red_40dp.png", "java/res/drawable-hdpi/ic_download_pause.png", "java/res/drawable-hdpi/ic_download_pending.png", - "java/res/drawable-hdpi/ic_drive_site_white_24dp.png", "java/res/drawable-hdpi/ic_email_googblue_36dp.png", "java/res/drawable-hdpi/ic_error_grey800_24dp_filled.png", "java/res/drawable-hdpi/ic_error_outline_red_24dp.png", @@ -108,7 +107,6 @@ "java/res/drawable-mdpi/ic_dialer_not_found_red_40dp.png", "java/res/drawable-mdpi/ic_download_pause.png", "java/res/drawable-mdpi/ic_download_pending.png", - "java/res/drawable-mdpi/ic_drive_site_white_24dp.png", "java/res/drawable-mdpi/ic_email_googblue_36dp.png", "java/res/drawable-mdpi/ic_error_grey800_24dp_filled.png", "java/res/drawable-mdpi/ic_error_outline_red_24dp.png", @@ -178,7 +176,6 @@ "java/res/drawable-xhdpi/ic_dialer_not_found_red_40dp.png", "java/res/drawable-xhdpi/ic_download_pause.png", "java/res/drawable-xhdpi/ic_download_pending.png", - "java/res/drawable-xhdpi/ic_drive_site_white_24dp.png", "java/res/drawable-xhdpi/ic_email_googblue_36dp.png", "java/res/drawable-xhdpi/ic_error_grey800_24dp_filled.png", "java/res/drawable-xhdpi/ic_error_outline_red_24dp.png", @@ -242,7 +239,6 @@ "java/res/drawable-xxhdpi/ic_dialer_not_found_red_40dp.png", "java/res/drawable-xxhdpi/ic_download_pause.png", "java/res/drawable-xxhdpi/ic_download_pending.png", - "java/res/drawable-xxhdpi/ic_drive_site_white_24dp.png", "java/res/drawable-xxhdpi/ic_email_googblue_36dp.png", "java/res/drawable-xxhdpi/ic_error_grey800_24dp_filled.png", "java/res/drawable-xxhdpi/ic_error_outline_red_24dp.png", @@ -304,7 +300,6 @@ "java/res/drawable-xxxhdpi/ic_devices_16dp.png", "java/res/drawable-xxxhdpi/ic_dialer_icon_blue_40dp.png", "java/res/drawable-xxxhdpi/ic_dialer_not_found_red_40dp.png", - "java/res/drawable-xxxhdpi/ic_drive_site_white_24dp.png", "java/res/drawable-xxxhdpi/ic_email_googblue_36dp.png", "java/res/drawable-xxxhdpi/ic_error_grey800_24dp_filled.png", "java/res/drawable-xxxhdpi/ic_error_outline_red_24dp.png", @@ -650,7 +645,6 @@ "java/res/values/values.xml", "java/res/xml/about_chrome_preferences.xml", "java/res/xml/account_management_preferences.xml", - "java/res/xml/account_management_preferences_legacy.xml", "java/res/xml/ad_services_config.xml", "java/res/xml/bookmark_widget_info.xml", "java/res/xml/clear_browsing_data_preferences_tab.xml",
diff --git a/chrome/android/java/res/drawable-hdpi/ic_drive_site_white_24dp.png b/chrome/android/java/res/drawable-hdpi/ic_drive_site_white_24dp.png deleted file mode 100644 index c5aea62..0000000 --- a/chrome/android/java/res/drawable-hdpi/ic_drive_site_white_24dp.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/ic_drive_site_white_24dp.png b/chrome/android/java/res/drawable-mdpi/ic_drive_site_white_24dp.png deleted file mode 100644 index f877c7c..0000000 --- a/chrome/android/java/res/drawable-mdpi/ic_drive_site_white_24dp.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/ic_drive_site_white_24dp.png b/chrome/android/java/res/drawable-xhdpi/ic_drive_site_white_24dp.png deleted file mode 100644 index 1da6d397..0000000 --- a/chrome/android/java/res/drawable-xhdpi/ic_drive_site_white_24dp.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/ic_drive_site_white_24dp.png b/chrome/android/java/res/drawable-xxhdpi/ic_drive_site_white_24dp.png deleted file mode 100644 index 06e345df9..0000000 --- a/chrome/android/java/res/drawable-xxhdpi/ic_drive_site_white_24dp.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/ic_drive_site_white_24dp.png b/chrome/android/java/res/drawable-xxxhdpi/ic_drive_site_white_24dp.png deleted file mode 100644 index 0cb4f82e..0000000 --- a/chrome/android/java/res/drawable-xxxhdpi/ic_drive_site_white_24dp.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/xml/account_management_preferences.xml b/chrome/android/java/res/xml/account_management_preferences.xml index 1d1d334..74049ef 100644 --- a/chrome/android/java/res/xml/account_management_preferences.xml +++ b/chrome/android/java/res/xml/account_management_preferences.xml
@@ -5,14 +5,13 @@ found in the LICENSE file. --> -<!--Used only when ChromeFeatureList.ADD_EDU_ACCOUNT_FROM_ACCOUNT_SETTINGS_FOR_SUPERVISED_USERS is enabled--> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <org.chromium.components.browser_ui.settings.TextMessagePreference android:key="parent_account_category" - tools:summary="@string/account_management_two_parent_names"/> + tools:summary="@string/account_management_header_two_parent_names"/> <PreferenceCategory android:key="accounts_category"
diff --git a/chrome/android/java/res/xml/account_management_preferences_legacy.xml b/chrome/android/java/res/xml/account_management_preferences_legacy.xml deleted file mode 100644 index 5c55904..0000000 --- a/chrome/android/java/res/xml/account_management_preferences_legacy.xml +++ /dev/null
@@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2015 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<PreferenceScreen - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools"> - - <PreferenceCategory - android:key="accounts_category" - android:title="@string/account_management_title"/> - - <PreferenceCategory - android:key="parental_settings" - android:title="@string/account_management_parental_settings"/> - - <org.chromium.components.browser_ui.settings.TextMessagePreference - android:key="parent_accounts" - tools:summary="@string/account_management_two_parent_names"/> - - <Preference - android:key="child_content" - android:selectable="false" - android:title="@string/account_management_child_content_title"/> - - <Preference - android:layout="@layout/divider_preference"/> - - <Preference - android:key="sign_out" - android:title="@string/account_management_sign_out"/> - - <Preference - android:key="sign_out_divider" - android:layout="@layout/divider_preference"/> - -</PreferenceScreen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/COMMON_METADATA b/chrome/android/java/src/org/chromium/chrome/browser/autofill/COMMON_METADATA index 8dc897c..b597ffd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/COMMON_METADATA +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/COMMON_METADATA
@@ -1,3 +1,3 @@ monorail { - component: "UI>Browser>Autofill>UI" + component: "UI>Browser>Autofill" }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java index 296c458..8b303a8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java
@@ -7,8 +7,6 @@ import android.accounts.Account; import android.content.Context; import android.content.Intent; -import android.graphics.PorterDuff; -import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.UserManager; @@ -20,9 +18,7 @@ import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceScreen; -import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.ProfileAccountManagementMetrics; @@ -34,7 +30,6 @@ import org.chromium.chrome.browser.signin.services.SigninManager; import org.chromium.chrome.browser.signin.services.SigninManager.SignInStateObserver; import org.chromium.chrome.browser.signin.services.SigninMetricsUtils; -import org.chromium.chrome.browser.superviseduser.FilteringBehavior; import org.chromium.chrome.browser.sync.SyncService; import org.chromium.chrome.browser.ui.signin.SignOutDialogCoordinator; import org.chromium.chrome.browser.ui.signin.SignOutDialogCoordinator.Listener; @@ -42,7 +37,6 @@ import org.chromium.components.browser_ui.settings.ChromeBasePreference; import org.chromium.components.browser_ui.settings.CustomDividerFragment; import org.chromium.components.browser_ui.settings.SettingsLauncher; -import org.chromium.components.browser_ui.styles.SemanticColorUtils; import org.chromium.components.prefs.PrefService; import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.AccountManagerFacadeProvider; @@ -173,18 +167,9 @@ mProfileDataCache.getProfileDataOrDefault(mSignedInAccountName); getActivity().setTitle(SyncSettingsUtils.getDisplayableFullNameOrEmailWithPreference( profileData, getContext(), SyncSettingsUtils.TitlePreference.FULL_NAME)); - - if (ChromeFeatureList.isEnabled( - ChromeFeatureList.ADD_EDU_ACCOUNT_FROM_ACCOUNT_SETTINGS_FOR_SUPERVISED_USERS)) { - addPreferencesFromResource(R.xml.account_management_preferences); - configureSignOutSwitch(); - configureChildAccountPreferences(); - } else { - addPreferencesFromResource(R.xml.account_management_preferences_legacy); - configureSignOutSwitch(); - configureChildAccountPreferencesLegacy(); - } - + addPreferencesFromResource(R.xml.account_management_preferences); + configureSignOutSwitch(); + configureChildAccountPreferences(); AccountManagerFacadeProvider.getInstance().getAccounts().then(this::updateAccountsList); } @@ -266,52 +251,6 @@ } } - private void configureChildAccountPreferencesLegacy() { - Preference parentAccounts = findPreference(PREF_PARENT_ACCOUNTS); - Preference childContent = findPreference(PREF_CHILD_CONTENT); - if (mProfile.isChild()) { - PrefService prefService = UserPrefs.get(mProfile); - - String firstParent = prefService.getString(Pref.SUPERVISED_USER_CUSTODIAN_EMAIL); - String secondParent = - prefService.getString(Pref.SUPERVISED_USER_SECOND_CUSTODIAN_EMAIL); - String parentText; - - if (!secondParent.isEmpty()) { - parentText = getString( - R.string.account_management_two_parent_names, firstParent, secondParent); - } else if (!firstParent.isEmpty()) { - parentText = getString(R.string.account_management_one_parent_name, firstParent); - } else { - parentText = getString(R.string.account_management_no_parental_data); - } - parentAccounts.setSummary(parentText); - - final int childContentSummary; - int defaultBehavior = - prefService.getInteger(Pref.DEFAULT_SUPERVISED_USER_FILTERING_BEHAVIOR); - if (defaultBehavior == FilteringBehavior.BLOCK) { - childContentSummary = R.string.account_management_child_content_approved; - } else if (prefService.getBoolean(Pref.SUPERVISED_USER_SAFE_SITES)) { - childContentSummary = R.string.account_management_child_content_filter_mature; - } else { - childContentSummary = R.string.account_management_child_content_all; - } - childContent.setSummary(childContentSummary); - - Drawable newIcon = ApiCompatibilityUtils.getDrawable( - getResources(), R.drawable.ic_drive_site_white_24dp); - newIcon.mutate().setColorFilter( - SemanticColorUtils.getDefaultIconColor(getContext()), PorterDuff.Mode.SRC_IN); - childContent.setIcon(newIcon); - } else { - PreferenceScreen prefScreen = getPreferenceScreen(); - prefScreen.removePreference(findPreference(PREF_PARENTAL_SETTINGS)); - prefScreen.removePreference(parentAccounts); - prefScreen.removePreference(childContent); - } - } - private void updateAccountsList(List<Account> accounts) { // This method is called asynchronously on accounts fetched from AccountManagerFacade. // Make sure the fragment is alive before updating preferences. @@ -339,13 +278,7 @@ accountsCategory.addPreference(createAccountPreference(account)); } } - - if (!mProfile.isChild() - || ChromeFeatureList.isEnabled( - ChromeFeatureList - .ADD_EDU_ACCOUNT_FROM_ACCOUNT_SETTINGS_FOR_SUPERVISED_USERS)) { - accountsCategory.addPreference(createAddAccountPreference()); - } + accountsCategory.addPreference(createAddAccountPreference()); } private Preference createAccountPreference(Account account) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java index 97ae09b..205616bf 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java
@@ -29,6 +29,7 @@ import org.chromium.base.CollectionUtil; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; @@ -195,6 +196,7 @@ @Test @LargeTest @Feature({"RenderTest"}) + @DisabledTest(message = "crbug.com/1407312") public void testRenderSearchHistoryLinkSignedInUnknownNonGoogleDSE() throws IOException { mSigninTestRule.addTestAccountThenSigninAndEnableSync(); setSyncable(false); @@ -207,8 +209,6 @@ View view = mSettingsActivityTestRule.getActivity() .findViewById(android.R.id.content) .getRootView(); - // Looking for "Frees up less than 1 MB" but could conceivably free up more space. - // See crbug.com/1407312 waitForView(withText("Frees up")); mRenderTestRule.render(view, "clear_browsing_data_basic_shl_unknown_signed_in"); } @@ -216,6 +216,7 @@ @Test @LargeTest @Feature({"RenderTest"}) + @DisabledTest(message = "crbug.com/1407312") public void testRenderSearchHistoryLinkSignedOutKnownNonGoogleDSE() throws IOException { configureMockSearchEngine(); Mockito.doReturn(false).when(mMockTemplateUrlService).isDefaultSearchEngineGoogle();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerIntegrationTest.java index 89584aa..dd48e375 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerIntegrationTest.java
@@ -103,6 +103,7 @@ ChromeSurveyController.resetMessageShownForTesting(); } + @DisabledTest(message = "https:://crbug.com/1447519") @Test @MediumTest public void testMessagePrimaryButtonClicked() throws TimeoutException, ExecutionException { @@ -120,7 +121,7 @@ mTestSurveyController.showSurveyCallbackHelper.getCallCount()); } - @DisabledTest(message = "https:://crbug.com/1447085") + @DisabledTest(message = "https:://crbug.com/1447519") @Test @MediumTest public void testMessageDismissed() throws TimeoutException, ExecutionException { @@ -130,7 +131,7 @@ () -> mMessageDispatcher.dismissMessage(message, DismissReason.GESTURE)); } - @DisabledTest(message = "https:://crbug.com/1447085") + @DisabledTest(message = "https:://crbug.com/1447519") @Test @MediumTest public void testNoMessageInNewTab() throws InterruptedException, ExecutionException {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java index 969a1fd0..f772a95 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java
@@ -90,10 +90,8 @@ @Test @MediumTest @Feature("RenderTest") - @DisableFeatures({ChromeFeatureList.ADD_EDU_ACCOUNT_FROM_ACCOUNT_SETTINGS_FOR_SUPERVISED_USERS, - ChromeFeatureList.HIDE_NON_DISPLAYABLE_ACCOUNT_EMAIL}) - public void - testAccountManagementFragmentView() throws Exception { + @DisableFeatures(ChromeFeatureList.HIDE_NON_DISPLAYABLE_ACCOUNT_EMAIL) + public void testAccountManagementFragmentView() throws Exception { mSigninTestRule.addTestAccountThenSigninAndEnableSync(); mSettingsActivityTestRule.startSettingsActivity(); View view = mSettingsActivityTestRule.getFragment().getView(); @@ -104,19 +102,6 @@ @Test @MediumTest @Feature("RenderTest") - @EnableFeatures(ChromeFeatureList.ADD_EDU_ACCOUNT_FROM_ACCOUNT_SETTINGS_FOR_SUPERVISED_USERS) - public void testAccountManagementFragmentViewWithAddEduAccountEnabled() throws Exception { - mSigninTestRule.addTestAccountThenSigninAndEnableSync(); - mSettingsActivityTestRule.startSettingsActivity(); - View view = mSettingsActivityTestRule.getFragment().getView(); - onViewWaiting(allOf(is(view), isDisplayed())); - mRenderTestRule.render( - view, "account_management_fragment_view_with_add_account_for_supervised_users"); - } - - @Test - @MediumTest - @Feature("RenderTest") @EnableFeatures(ChromeFeatureList.HIDE_NON_DISPLAYABLE_ACCOUNT_EMAIL) public void testAccountManagementFragmentViewWithHideNonDisplayableAccountEmailEnabled() throws Exception { @@ -142,26 +127,6 @@ @Test @MediumTest - @Feature("RenderTest") - @DisableFeatures({ChromeFeatureList.ADD_EDU_ACCOUNT_FROM_ACCOUNT_SETTINGS_FOR_SUPERVISED_USERS}) - public void testAccountManagementViewForChildAccount() throws Exception { - mSigninTestRule.addAccountAndWaitForSeeding(CHILD_ACCOUNT_NAME); - final Profile profile = TestThreadUtils.runOnUiThreadBlockingNoException( - Profile::getLastUsedRegularProfile); - CriteriaHelper.pollUiThread(profile::isChild); - mSettingsActivityTestRule.startSettingsActivity(); - CriteriaHelper.pollUiThread(() -> { - return mSettingsActivityTestRule.getFragment() - .getProfileDataCacheForTesting() - .hasProfileDataForTesting(CHILD_ACCOUNT_NAME); - }); - View view = mSettingsActivityTestRule.getFragment().getView(); - onViewWaiting(allOf(is(view), isDisplayed())); - mRenderTestRule.render(view, "account_management_fragment_for_child_account"); - } - - @Test - @MediumTest @EnableFeatures({ChromeFeatureList.HIDE_NON_DISPLAYABLE_ACCOUNT_EMAIL}) public void testAccountManagementViewForChildAccountWithNonDisplayableAccountEmail() throws Exception { @@ -215,9 +180,7 @@ @Test @MediumTest @Feature("RenderTest") - @EnableFeatures(ChromeFeatureList.ADD_EDU_ACCOUNT_FROM_ACCOUNT_SETTINGS_FOR_SUPERVISED_USERS) - public void testAccountManagementViewForChildAccountWithAddEduAccountEnabled() - throws Exception { + public void testAccountManagementViewForChildAccount() throws Exception { mSigninTestRule.addAccountAndWaitForSeeding(CHILD_ACCOUNT_NAME); final Profile profile = TestThreadUtils.runOnUiThreadBlockingNoException( Profile::getLastUsedRegularProfile); @@ -237,35 +200,8 @@ @Test @MediumTest @Feature("RenderTest") - @DisableFeatures({ChromeFeatureList.ADD_EDU_ACCOUNT_FROM_ACCOUNT_SETTINGS_FOR_SUPERVISED_USERS}) public void testAccountManagementViewForChildAccountWithSecondaryEduAccount() throws Exception { mSigninTestRule.addAccount(CHILD_ACCOUNT_NAME); - // The code under test doesn't care what account type this is, though in practice only - // EDU accounts are supported on devices where the primary account is a child account. - mSigninTestRule.addAccount("account@school.com"); - mSigninTestRule.waitForSeeding(); - final Profile profile = TestThreadUtils.runOnUiThreadBlockingNoException( - Profile::getLastUsedRegularProfile); - CriteriaHelper.pollUiThread(profile::isChild); - mSettingsActivityTestRule.startSettingsActivity(); - CriteriaHelper.pollUiThread(() -> { - return mSettingsActivityTestRule.getFragment() - .getProfileDataCacheForTesting() - .hasProfileDataForTesting(CHILD_ACCOUNT_NAME); - }); - View view = mSettingsActivityTestRule.getFragment().getView(); - onViewWaiting(allOf(is(view), isDisplayed())); - mRenderTestRule.render(view, "account_management_fragment_for_child_and_edu_accounts"); - } - - @Test - @MediumTest - @Feature("RenderTest") - @EnableFeatures(ChromeFeatureList.ADD_EDU_ACCOUNT_FROM_ACCOUNT_SETTINGS_FOR_SUPERVISED_USERS) - public void - testAccountManagementViewForChildAccountWithSecondaryEduAccountAndAddEduAccountEnabled() - throws Exception { - mSigninTestRule.addAccount(CHILD_ACCOUNT_NAME); mSigninTestRule.addAccount("account@school.com"); mSigninTestRule.waitForSeeding(); final Profile profile = TestThreadUtils.runOnUiThreadBlockingNoException(
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 3d87f9f1..743161e 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4598,13 +4598,6 @@ {"cormorant", flag_descriptions::kCormorantName, flag_descriptions::kCormorantDescription, kOsAndroid, FEATURE_VALUE_TYPE(feed::kCormorant)}, - {"add-edu-account-for-supervised-users", - flag_descriptions::kAddEduAccountFromAccountSettingsForSupervisedUsersName, - flag_descriptions:: - kAddEduAccountFromAccountSettingsForSupervisedUsersDescription, - kOsAndroid, - FEATURE_VALUE_TYPE( - chrome::android::kAddEduAccountFromAccountSettingsForSupervisedUsers)}, {"hide-non-displayable-account-email", flag_descriptions::kHideNonDisplayableAccountEmailName, flag_descriptions::kHideNonDisplayableAccountEmailDescription, kOsAndroid,
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn index 27cf6b3..b20e2e2 100644 --- a/chrome/browser/ash/BUILD.gn +++ b/chrome/browser/ash/BUILD.gn
@@ -738,6 +738,8 @@ "browser_accelerator_configuration.h", "browser_context_keyed_service_factories.cc", "browser_context_keyed_service_factories.h", + "bruschetta/bruschetta_download.cc", + "bruschetta/bruschetta_download.h", "bruschetta/bruschetta_download_client.cc", "bruschetta/bruschetta_download_client.h", "bruschetta/bruschetta_features.cc", @@ -1194,6 +1196,8 @@ "file_system_provider/notification_manager.h", "file_system_provider/notification_manager_interface.h", "file_system_provider/observer.h", + "file_system_provider/odfs_metrics.cc", + "file_system_provider/odfs_metrics.h", "file_system_provider/operation_request_manager.cc", "file_system_provider/operation_request_manager.h", "file_system_provider/operations/abort.cc", @@ -5038,6 +5042,7 @@ "borealis/infra/described_unittest.cc", "borealis/infra/transition_unittest.cc", "browser_accelerator_configuration_unittest.cc", + "bruschetta/bruschetta_download_unittest.cc", "bruschetta/bruschetta_installer_impl_unittest.cc", "bruschetta/bruschetta_launcher_unittest.cc", "bruschetta/bruschetta_mount_provider_unittest.cc",
diff --git a/chrome/browser/ash/bruschetta/bruschetta_download.cc b/chrome/browser/ash/bruschetta/bruschetta_download.cc new file mode 100644 index 0000000..0ff5050 --- /dev/null +++ b/chrome/browser/ash/bruschetta/bruschetta_download.cc
@@ -0,0 +1,153 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/bruschetta/bruschetta_download.h" + +#include "base/files/scoped_temp_dir.h" +#include "base/memory/ptr_util.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" +#include "chrome/browser/extensions/cws_info_service.h" +#include "chrome/browser/profiles/profile.h" +#include "content/public/browser/storage_partition.h" +#include "crypto/secure_hash.h" +#include "crypto/sha2.h" +#include "services/network/public/cpp/resource_request.h" +#include "services/network/public/cpp/simple_url_loader.h" + +namespace bruschetta { + +const net::NetworkTrafficAnnotationTag kBruschettaTrafficAnnotation = + net::DefineNetworkTrafficAnnotation("bruschetta_installer_download", + R"( + semantics { + sender: "Bruschetta VM Installer", + description: "Request sent to download firmware and VM image for " + "a Bruschetta VM, which allows the user to run the VM." + trigger: "User installing a Bruschetta VM" + internal { + contacts { + email: "clumptini+oncall@google.com" + } + } + user_data: { + type: ACCESS_TOKEN + } + data: "Request to download Bruschetta firmware and VM image. " + "Sends cookies associated with the source to authenticate the user." + destination: WEBSITE + last_reviewed: "2023-01-09" + } + policy { + cookies_allowed: YES + cookies_store: "user" + chrome_policy { + BruschettaVMConfiguration { + BruschettaVMConfiguration: "{}" + } + } + } + )"); + +namespace { + +std::unique_ptr<base::ScopedTempDir> MakeTempDir() { + auto dir = std::make_unique<base::ScopedTempDir>(); + CHECK(dir->CreateUniqueTempDir()); + return dir; +} + +// Calculates the sha256 hash of the file at `path` incrementally i.e. without +// loading the entire thing into memory at once. Blocking. +std::string Sha256File(const base::FilePath& path) { + base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); + if (!file.IsValid()) { + return ""; + } + + std::unique_ptr<crypto::SecureHash> ctx( + crypto::SecureHash::Create(crypto::SecureHash::SHA256)); + const size_t kReadBufferSize = 4096; + char buffer[kReadBufferSize]; + while (true) { + int count = file.ReadAtCurrentPos(buffer, kReadBufferSize); + + // Treat EOF the same as any other error, stop reading and return the hash + // of what we read. If there was a disk error or something we'll end up with + // an invalid hash, same as if the file were truncated. + if (count <= 0) { + break; + } + ctx->Update(buffer, count); + } + + char digest_bytes[crypto::kSHA256Length]; + ctx->Finish(digest_bytes, crypto::kSHA256Length); + + return base::HexEncode(digest_bytes, crypto::kSHA256Length); +} + +} // namespace + +std::string Sha256FileForTesting(const base::FilePath& path) { + return Sha256File(path); +} + +std::unique_ptr<SimpleURLLoaderDownload> SimpleURLLoaderDownload::StartDownload( + Profile* profile, + GURL url, + base::OnceCallback<void(base::FilePath path, std::string sha256)> + callback) { + return base::WrapUnique(new SimpleURLLoaderDownload(profile, std::move(url), + std::move(callback))); +} + +SimpleURLLoaderDownload::SimpleURLLoaderDownload( + Profile* profile, + GURL url, + base::OnceCallback<void(base::FilePath path, std::string sha256)> callback) + : profile_(profile), url_(std::move(url)), callback_(std::move(callback)) { + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock()}, base::BindOnce(&MakeTempDir), + base::BindOnce(&SimpleURLLoaderDownload::Download, + weak_ptr_factory_.GetWeakPtr())); +} + +SimpleURLLoaderDownload::~SimpleURLLoaderDownload() { + auto seq = base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()}); + seq->DeleteSoon(FROM_HERE, std::move(scoped_temp_dir_)); + if (post_deletion_closure_for_testing_) { + seq->PostTask(FROM_HERE, std::move(post_deletion_closure_for_testing_)); + } +} + +void SimpleURLLoaderDownload::Download( + std::unique_ptr<base::ScopedTempDir> dir) { + scoped_temp_dir_ = std::move(dir); + auto path = scoped_temp_dir_->GetPath().Append("download"); + auto req = std::make_unique<network::ResourceRequest>(); + req->url = url_; + loader_ = network::SimpleURLLoader::Create(std::move(req), + kBruschettaTrafficAnnotation); + auto factory = profile_->GetDefaultStoragePartition() + ->GetURLLoaderFactoryForBrowserProcess(); + loader_->DownloadToFile(factory.get(), + base::BindOnce(&SimpleURLLoaderDownload::Finished, + weak_ptr_factory_.GetWeakPtr()), + std::move(path)); +} + +void SimpleURLLoaderDownload::Finished(base::FilePath path) { + if (path.empty()) { + LOG(ERROR) << "Download failed"; + std::move(callback_).Run(path, ""); + return; + } + + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock()}, base::BindOnce(&Sha256File, path), + base::BindOnce(std::move(callback_), path)); +} + +} // namespace bruschetta
diff --git a/chrome/browser/ash/bruschetta/bruschetta_download.h b/chrome/browser/ash/bruschetta/bruschetta_download.h new file mode 100644 index 0000000..1cd562e --- /dev/null +++ b/chrome/browser/ash/bruschetta/bruschetta_download.h
@@ -0,0 +1,69 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_BRUSCHETTA_BRUSCHETTA_DOWNLOAD_H_ +#define CHROME_BROWSER_ASH_BRUSCHETTA_BRUSCHETTA_DOWNLOAD_H_ + +#include "base/files/scoped_temp_dir.h" +#include "base/functional/callback_forward.h" +#include "base/functional/callback_helpers.h" +#include "base/memory/raw_ptr.h" +#include "services/network/public/cpp/simple_url_loader.h" +#include "url/gurl.h" + +class Profile; +namespace network { +class SimpleURLLoader; +} // namespace network + +namespace bruschetta { + +extern const net::NetworkTrafficAnnotationTag kBruschettaTrafficAnnotation; + +// Only exposed so unit tests can test it. +std::string Sha256FileForTesting(const base::FilePath& path); + +// Wraps SimpleURLLoader to make it even simpler for Bruschetta to use it for +// downloading files. +class SimpleURLLoaderDownload { + public: + // Starts downloading the file at `url`, will invoke `callback` upon + // completion. Either with the path to the downloaded file and a sha256 hash + // of its contents, or in case of error will run `callback` with an empty + // path. Destroying the returned download instance will cancel any active + // downloads and delete any downloaded files. + static std::unique_ptr<SimpleURLLoaderDownload> StartDownload( + Profile* profile, + GURL url, + base::OnceCallback<void(base::FilePath path, std::string sha256)> + callback); + + void SetPostDeletionCallbackForTesting(base::OnceClosure closure) { + post_deletion_closure_for_testing_ = std::move(closure); + } + + ~SimpleURLLoaderDownload(); + + private: + SimpleURLLoaderDownload( + Profile* profile, + GURL url, + base::OnceCallback<void(base::FilePath path, std::string sha256)> + callback); + void Download(std::unique_ptr<base::ScopedTempDir> dir); + void Finished(base::FilePath path); + + base::raw_ptr<Profile> profile_; + GURL url_; + std::unique_ptr<base::ScopedTempDir> scoped_temp_dir_; + base::OnceCallback<void(base::FilePath path, std::string sha256)> callback_; + std::unique_ptr<network::SimpleURLLoader> loader_; + base::OnceClosure post_deletion_closure_for_testing_; + + base::WeakPtrFactory<SimpleURLLoaderDownload> weak_ptr_factory_{this}; +}; + +} // namespace bruschetta + +#endif // CHROME_BROWSER_ASH_BRUSCHETTA_BRUSCHETTA_DOWNLOAD_H_
diff --git a/chrome/browser/ash/bruschetta/bruschetta_download_browsertest.cc b/chrome/browser/ash/bruschetta/bruschetta_download_browsertest.cc new file mode 100644 index 0000000..a06982b8 --- /dev/null +++ b/chrome/browser/ash/bruschetta/bruschetta_download_browsertest.cc
@@ -0,0 +1,84 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/bruschetta/bruschetta_download.h" + +#include "base/files/file_util.h" +#include "base/run_loop.h" +#include "base/strings/string_util.h" +#include "base/test/test_future.h" +#include "base/threading/thread_restrictions.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "content/public/test/browser_test.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace bruschetta { +namespace { + +class BruschettaDownloadBrowserTest : public InProcessBrowserTest { + public: + BruschettaDownloadBrowserTest() = default; + ~BruschettaDownloadBrowserTest() override = default; + + BruschettaDownloadBrowserTest(const BruschettaDownloadBrowserTest&) = delete; + BruschettaDownloadBrowserTest& operator=( + const BruschettaDownloadBrowserTest&) = delete; + + protected: + void SetUpInProcessBrowserTestFixture() override { + InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); + } +}; + +bool PathExistsBlockingAllowed(const base::FilePath& path) { + base::ScopedAllowBlockingForTesting allow_blocking; + return base::PathExists(path); +} + +IN_PROC_BROWSER_TEST_F(BruschettaDownloadBrowserTest, TestHappyPath) { + auto expected_hash = base::ToUpperASCII( + "f54d00e6d24844ee3b1d0d8c2b9d2ed80b967e94eb1055bb1fd43eb9522908cc"); + + net::EmbeddedTestServer server(net::EmbeddedTestServer::TYPE_HTTPS); + server.ServeFilesFromSourceDirectory("chrome/test/data/bruschetta"); + auto server_handle = server.StartAndReturnHandle(); + ASSERT_TRUE(server_handle); + GURL url = server.GetURL("/download_file.img"); + + base::test::TestFuture<base::FilePath, std::string> future; + base::FilePath path; + auto download = SimpleURLLoaderDownload::StartDownload( + browser()->profile(), url, future.GetCallback()); + + path = future.Get<base::FilePath>(); + auto hash = future.Get<std::string>(); + + ASSERT_FALSE(path.empty()); + EXPECT_EQ(hash, expected_hash); + + // Deleting the download should clean up downloaded files. I found + // RunUntilIdle to be flaky hence we have an explicit callback for after + // deletion completes. + base::RunLoop run_loop; + download->SetPostDeletionCallbackForTesting(run_loop.QuitClosure()); + download.reset(); + run_loop.Run(); + EXPECT_FALSE(PathExistsBlockingAllowed(path)); +} + +IN_PROC_BROWSER_TEST_F(BruschettaDownloadBrowserTest, TestDownloadFailed) { + base::test::TestFuture<base::FilePath, std::string> future; + auto download = SimpleURLLoaderDownload::StartDownload( + browser()->profile(), GURL("bad url"), future.GetCallback()); + + auto path = future.Get<base::FilePath>(); + auto hash = future.Get<std::string>(); + + ASSERT_TRUE(path.empty()); + EXPECT_EQ(hash, ""); +} + +} // namespace +} // namespace bruschetta
diff --git a/chrome/browser/ash/bruschetta/bruschetta_download_client.h b/chrome/browser/ash/bruschetta/bruschetta_download_client.h index b0c22790..32dd84e 100644 --- a/chrome/browser/ash/bruschetta/bruschetta_download_client.h +++ b/chrome/browser/ash/bruschetta/bruschetta_download_client.h
@@ -52,4 +52,4 @@ } // namespace bruschetta -#endif +#endif // CHROME_BROWSER_ASH_BRUSCHETTA_BRUSCHETTA_DOWNLOAD_CLIENT_H_
diff --git a/chrome/browser/ash/bruschetta/bruschetta_download_unittest.cc b/chrome/browser/ash/bruschetta/bruschetta_download_unittest.cc new file mode 100644 index 0000000..b68ed0b --- /dev/null +++ b/chrome/browser/ash/bruschetta/bruschetta_download_unittest.cc
@@ -0,0 +1,36 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/bruschetta/bruschetta_download.h" + +#include <cstring> + +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace bruschetta { +namespace { + +class BruschettaDownloadTest : public testing::Test {}; + +TEST_F(BruschettaDownloadTest, TestSha256File) { + base::ScopedTempDir dir; + ASSERT_TRUE(dir.CreateUniqueTempDir()); + const int kBufSize = + 4096 * 2 + 1; // Sha256File uses 4k block size, so make sure the file is + // multiple blocks and not a complete block. + char buff[kBufSize]; + memset(buff, 'd', kBufSize); + auto path = dir.GetPath().Append("file"); + const char* expected = + "B1AAAD3DBE85816D70C94C35B873D45F0C68F9D3B3DB6F6AB858A1560540E4DF"; + ASSERT_TRUE(base::WriteFile(path, buff, kBufSize)); + auto hash = Sha256FileForTesting(path); + + ASSERT_EQ(hash, expected); +} + +} // namespace +} // namespace bruschetta
diff --git a/chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc b/chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc index 8f41a7f..669fda9 100644 --- a/chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc +++ b/chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc
@@ -7,11 +7,14 @@ #include <memory> #include "base/check.h" +#include "base/command_line.h" #include "base/files/file_path.h" -#include "base/files/file_util.h" +#include "base/functional/bind.h" #include "base/functional/callback_forward.h" +#include "base/functional/callback_helpers.h" #include "base/metrics/histogram_functions.h" #include "base/task/thread_pool.h" +#include "chrome/browser/ash/bruschetta/bruschetta_download.h" #include "chrome/browser/ash/bruschetta/bruschetta_download_client.h" #include "chrome/browser/ash/bruschetta/bruschetta_installer.h" #include "chrome/browser/ash/bruschetta/bruschetta_pref_names.h" @@ -39,38 +42,6 @@ namespace { -const net::NetworkTrafficAnnotationTag kBruschettaTrafficAnnotation = - net::DefineNetworkTrafficAnnotation("bruschetta_installer_download", - R"( - semantics { - sender: "Bruschetta VM Installer", - description: "Request sent to download firmware and VM image for " - "a Bruschetta VM, which allows the user to run the VM." - trigger: "User installing a Bruschetta VM" - internal { - contacts { - email: "clumptini+oncall@google.com" - } - } - user_data: { - type: ACCESS_TOKEN - } - data: "Request to download Bruschetta firmware and VM image. " - "Sends cookies associated with the source to authenticate the user." - destination: WEBSITE - last_reviewed: "2023-01-09" - } - policy { - cookies_allowed: YES - cookies_store: "user" - chrome_policy { - BruschettaVMConfiguration { - BruschettaVMConfiguration: "{}" - } - } - } - )"); - std::unique_ptr<BruschettaInstallerImpl::Fds> OpenFdsBlocking( base::FilePath boot_disk_path, base::FilePath pflash_path, @@ -195,7 +166,17 @@ return; } - DownloadBootDisk(); + std::string strategy; + auto* cmdline = base::CommandLine::ForCurrentProcess(); + if (cmdline->HasSwitch(kBruschettaInstallerDownloadStrategyFlag)) { + strategy = + cmdline->GetSwitchValueASCII(kBruschettaInstallerDownloadStrategyFlag); + } + if (strategy == kBruschettaInstallerDownloadStrategySimpleURLLoader) { + DownloadBootDiskURLLoader(); + } else { + DownloadBootDiskDownloadService(); + } } void BruschettaInstallerImpl::StartDownload(GURL url, @@ -264,7 +245,7 @@ std::move(download_callback_).Run(completion_info); } -void BruschettaInstallerImpl::DownloadBootDisk() { +void BruschettaInstallerImpl::DownloadBootDiskDownloadService() { VLOG(2) << "Downloading boot disk"; // We need to generate the download UUID before notifying because the tests // need it to set the response. @@ -273,12 +254,14 @@ const std::string* url = config_.FindDict(prefs::kPolicyImageKey) ->FindString(prefs::kPolicyURLKey); - StartDownload(GURL(*url), - base::BindOnce(&BruschettaInstallerImpl::OnBootDiskDownloaded, - weak_ptr_factory_.GetWeakPtr())); + StartDownload( + GURL(*url), + base::BindOnce( + &BruschettaInstallerImpl::OnBootDiskDownloadedDownloadService, + weak_ptr_factory_.GetWeakPtr())); } -void BruschettaInstallerImpl::OnBootDiskDownloaded( +void BruschettaInstallerImpl::OnBootDiskDownloadedDownloadService( const download::CompletionInfo& completion_info) { if (MaybeClose()) { return; @@ -298,10 +281,10 @@ boot_disk_path_ = completion_info.path; - DownloadPflash(); + DownloadPflashDownloadService(); } -void BruschettaInstallerImpl::DownloadPflash() { +void BruschettaInstallerImpl::DownloadPflashDownloadService() { VLOG(2) << "Downloading pflash"; // We need to generate the download UUID before notifying because the tests // need it to set the response. @@ -318,11 +301,12 @@ const std::string* url = pflash->FindString(prefs::kPolicyURLKey); StartDownload(GURL(*url), - base::BindOnce(&BruschettaInstallerImpl::OnPflashDownloaded, - weak_ptr_factory_.GetWeakPtr())); + base::BindOnce( + &BruschettaInstallerImpl::OnPflashDownloadedDownloadService, + weak_ptr_factory_.GetWeakPtr())); } -void BruschettaInstallerImpl::OnPflashDownloaded( +void BruschettaInstallerImpl::OnPflashDownloadedDownloadService( const download::CompletionInfo& completion_info) { if (MaybeClose()) { return; @@ -345,6 +329,86 @@ OpenFds(); } +void BruschettaInstallerImpl::DownloadBootDiskURLLoader() { + VLOG(2) << "Downloading boot disk"; + NotifyObserver(State::kBootDiskDownload); + + const std::string* url = config_.FindDict(prefs::kPolicyImageKey) + ->FindString(prefs::kPolicyURLKey); + boot_disk_download_ = SimpleURLLoaderDownload::StartDownload( + profile_, GURL(*url), + base::BindOnce( + &bruschetta::BruschettaInstallerImpl::OnBootDiskDownloadedURLLoader, + weak_ptr_factory_.GetWeakPtr())); +} + +void BruschettaInstallerImpl::OnBootDiskDownloadedURLLoader(base::FilePath path, + std::string hash) { + if (MaybeClose()) { + return; + } + if (path.empty()) { + install_running_ = false; + Error(BruschettaInstallResult::kDownloadError); + return; + } + const std::string* expected = config_.FindDict(prefs::kPolicyImageKey) + ->FindString(prefs::kPolicyHashKey); + + if (!base::EqualsCaseInsensitiveASCII(hash, *expected)) { + install_running_ = false; + Error(BruschettaInstallResult::kInvalidBootDisk); + LOG(ERROR) << "Downloaded boot disk has incorrect hash"; + LOG(ERROR) << "Actual " << hash; + LOG(ERROR) << "Expected " << expected; + return; + } + + boot_disk_path_ = path; + + DownloadPflashURLLoader(); +} + +void BruschettaInstallerImpl::DownloadPflashURLLoader() { + VLOG(2) << "Downloading pflash"; + NotifyObserver(State::kPflashDownload); + + const std::string* url = config_.FindDict(prefs::kPolicyPflashKey) + ->FindString(prefs::kPolicyURLKey); + pflash_download_ = SimpleURLLoaderDownload::StartDownload( + profile_, GURL(*url), + base::BindOnce( + &bruschetta::BruschettaInstallerImpl::OnPflashDownloadedURLLoader, + weak_ptr_factory_.GetWeakPtr())); +} + +void BruschettaInstallerImpl::OnPflashDownloadedURLLoader(base::FilePath path, + std::string hash) { + if (MaybeClose()) { + return; + } + if (path.empty()) { + install_running_ = false; + Error(BruschettaInstallResult::kDownloadError); + return; + } + const std::string* expected = config_.FindDict(prefs::kPolicyPflashKey) + ->FindString(prefs::kPolicyHashKey); + + if (!base::EqualsCaseInsensitiveASCII(hash, *expected)) { + install_running_ = false; + Error(BruschettaInstallResult::kInvalidPflash); + LOG(ERROR) << "Downloaded pflash has incorrect hash"; + LOG(ERROR) << "Actual " << hash; + LOG(ERROR) << "Expected " << expected; + return; + } + + pflash_path_ = path; + + OpenFds(); +} + void BruschettaInstallerImpl::OpenFds() { VLOG(2) << "Opening fds"; NotifyObserver(State::kOpenFiles);
diff --git a/chrome/browser/ash/bruschetta/bruschetta_installer_impl.h b/chrome/browser/ash/bruschetta/bruschetta_installer_impl.h index e6142a6e..387b4bc 100644 --- a/chrome/browser/ash/bruschetta/bruschetta_installer_impl.h +++ b/chrome/browser/ash/bruschetta/bruschetta_installer_impl.h
@@ -21,6 +21,7 @@ class Profile; namespace bruschetta { +class SimpleURLLoaderDownload; class BruschettaInstallerImpl : public BruschettaInstaller { public: @@ -61,10 +62,18 @@ void InstallFirmwareDlc(); void OnFirmwareDlcInstalled( guest_os::GuestOsDlcInstallation::Result install_result); - void DownloadBootDisk(); - void OnBootDiskDownloaded(const download::CompletionInfo& completion_info); - void DownloadPflash(); - void OnPflashDownloaded(const download::CompletionInfo& completion_info); + // TODO(b/270656010): Pick the winner between the two strategies. Loser gets + // deleted, winner gets renamed back to "DownloadBootDisk" and etc. + void DownloadBootDiskDownloadService(); + void OnBootDiskDownloadedDownloadService( + const download::CompletionInfo& completion_info); + void DownloadPflashDownloadService(); + void OnPflashDownloadedDownloadService( + const download::CompletionInfo& completion_info); + void DownloadBootDiskURLLoader(); + void OnBootDiskDownloadedURLLoader(base::FilePath path, std::string hash); + void DownloadPflashURLLoader(); + void OnPflashDownloadedURLLoader(base::FilePath path, std::string hash); void OpenFds(); void OnOpenFds(std::unique_ptr<Fds> fds); void CreateVmDisk(); @@ -99,6 +108,10 @@ const raw_ptr<Profile> profile_; + // The downloaded files get deleted once these go out of scope. + std::unique_ptr<SimpleURLLoaderDownload> boot_disk_download_; + std::unique_ptr<SimpleURLLoaderDownload> pflash_download_; + base::OnceClosure close_closure_; raw_ptr<Observer> observer_ = nullptr;
diff --git a/chrome/browser/ash/crosapi/browser_loader.cc b/chrome/browser/ash/crosapi/browser_loader.cc index 8a527d1..efc5022 100644 --- a/chrome/browser/ash/crosapi/browser_loader.cc +++ b/chrome/browser/ash/crosapi/browser_loader.cc
@@ -76,16 +76,12 @@ return true; } -void BrowserLoader::SelectRootfsLacros(LoadCompletionCallback callback, - bool load_stateful_lacros) { +void BrowserLoader::SelectRootfsLacros(LoadCompletionCallback callback) { LOG(WARNING) << "rootfs lacros is selected"; rootfs_lacros_loader_->Load( base::BindOnce(&BrowserLoader::OnLoadComplete, weak_factory_.GetWeakPtr(), std::move(callback), LacrosSelection::kRootfs)); - if (load_stateful_lacros) { - stateful_lacros_loader_->Load({}); - } } void BrowserLoader::SelectStatefulLacros(LoadCompletionCallback callback) { @@ -132,8 +128,7 @@ // too. switch (lacros_selection.value()) { case browser_util::LacrosSelection::kRootfs: - SelectRootfsLacros(std::move(callback), - /*load_stateful_lacros=*/false); + SelectRootfsLacros(std::move(callback)); return; case browser_util::LacrosSelection::kStateful: SelectStatefulLacros(std::move(callback)); @@ -219,7 +214,7 @@ switch (selected->selection) { case LacrosSelection::kRootfs: { - SelectRootfsLacros(std::move(callback), /*load_stateful_lacros=*/true); + SelectRootfsLacros(std::move(callback)); break; } case LacrosSelection::kStateful: {
diff --git a/chrome/browser/ash/crosapi/browser_loader.h b/chrome/browser/ash/crosapi/browser_loader.h index df0f095d..0b5df89 100644 --- a/chrome/browser/ash/crosapi/browser_loader.h +++ b/chrome/browser/ash/crosapi/browser_loader.h
@@ -99,10 +99,7 @@ OnLoadSelectionPolicyIsUserChoiceAndCommandLineIsStateful); FRIEND_TEST_ALL_PREFIXES(BrowserLoaderTest, OnLoadLacrosSpecifiedBySwitch); - // `load_stateful_lacros` specifies whether we should start the installation - // of stateful lacros in the background. - void SelectRootfsLacros(LoadCompletionCallback callback, - bool load_stateful_lacros); + void SelectRootfsLacros(LoadCompletionCallback callback); void SelectStatefulLacros(LoadCompletionCallback callback); // Called on GetVersion for each rootfs and stateful lacros loader.
diff --git a/chrome/browser/ash/crosapi/move_migrator.cc b/chrome/browser/ash/crosapi/move_migrator.cc index 99a72a2..6c96ab9 100644 --- a/chrome/browser/ash/crosapi/move_migrator.cc +++ b/chrome/browser/ash/crosapi/move_migrator.cc
@@ -266,14 +266,14 @@ } } - const int64_t extra_bytes_created = + const int64_t estimated_extra_bytes_created = browser_data_migrator_util::EstimatedExtraBytesCreated( original_profile_dir); // Now check if there is enough disk space for the migration to be carried // out. const int64_t extra_bytes_required_to_be_freed = browser_data_migrator_util::ExtraBytesRequiredToBeFreed( - extra_bytes_created, original_profile_dir); + estimated_extra_bytes_created, original_profile_dir); UMA_HISTOGRAM_MEDIUM_TIMES(kMoveMigratorPreMigrationCleanUpTimeUMA, timer.Elapsed()); @@ -289,7 +289,8 @@ extra_bytes_required_to_be_freed}; } - return {TaskStatus::kSucceeded}; + return {TaskStatus::kSucceeded, absl::nullopt, absl::nullopt, + estimated_extra_bytes_created}; } void MoveMigrator::OnPreMigrationCleanUp(MoveMigrator::TaskResult result) { @@ -299,6 +300,8 @@ return; } + estimated_extra_bytes_created_ = *result.estimated_extra_bytes_created; + base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE, @@ -374,18 +377,22 @@ return; } + DCHECK(estimated_extra_bytes_created_.has_value()); + base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE, base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, - base::BindOnce(&MoveMigrator::SetupAshSplitDir, original_profile_dir_), + base::BindOnce(&MoveMigrator::SetupAshSplitDir, original_profile_dir_, + *estimated_extra_bytes_created_), base::BindOnce(&MoveMigrator::OnSetupAshSplitDir, weak_factory_.GetWeakPtr())); } // static MoveMigrator::TaskResult MoveMigrator::SetupAshSplitDir( - const base::FilePath& original_profile_dir) { + const base::FilePath& original_profile_dir, + const int64_t estimated_extra_bytes_created) { LOG(WARNING) << "Running SetupAshSplitDir()"; const base::FilePath tmp_user_dir = @@ -499,6 +506,26 @@ } } + // Collect UMAs on sizes of artifacts created by migration. + const int64_t tmp_profile_dir_size = + base::ComputeDirectorySize(tmp_profile_dir); + const int64_t tmp_split_dir_size = base::ComputeDirectorySize(tmp_split_dir); + const int64_t extra_bytes_created = tmp_profile_dir_size + tmp_split_dir_size; + const int64_t extra_bytes_over_estimate = + extra_bytes_created - estimated_extra_bytes_created; + base::UmaHistogramCustomCounts(kMoveMigratorTmpProfileDirSize, + tmp_profile_dir_size / 1024 / 1024, 1, 10000, + 100); + base::UmaHistogramCustomCounts(kMoveMigratorTmpSplitDirSize, + tmp_split_dir_size / 1024 / 1024, 1, 10000, + 100); + base::UmaHistogramCustomCounts(kMoveMigratorExtraDiskSpaceOccupied, + extra_bytes_created / 1024 / 1024, 1, 10000, + 100); + base::UmaHistogramCustomCounts(kMoveMigratorExtraDiskSpaceOccupiedDiffWithEst, + extra_bytes_over_estimate / 1024 / 1024, + -10000, 10000, 100); + return {TaskStatus::kSucceeded}; }
diff --git a/chrome/browser/ash/crosapi/move_migrator.h b/chrome/browser/ash/crosapi/move_migrator.h index 19e7b39..2fa79e9 100644 --- a/chrome/browser/ash/crosapi/move_migrator.h +++ b/chrome/browser/ash/crosapi/move_migrator.h
@@ -63,6 +63,15 @@ "Ash.BrowserDataMigrator.MoveMigrator.MoveLacrosItemsTimeMS"; constexpr char kMoveMigratorPosixErrnoUMA[] = "Ash.BrowserDataMigrator.MoveMigrator.PosixErrno."; +constexpr char kMoveMigratorTmpProfileDirSize[] = + "Ash.BrowserDataMigrator.MoveMigrator.TmpProfileDirSize"; +constexpr char kMoveMigratorTmpSplitDirSize[] = + "Ash.BrowserDataMigrator.MoveMigrator.TmpSplitDirSize"; +constexpr char kMoveMigratorExtraDiskSpaceOccupied[] = + "Ash.BrowserDataMigrator.MoveMigrator.ExtraDiskSpaceOccupied"; +constexpr char kMoveMigratorExtraDiskSpaceOccupiedDiffWithEst[] = + "Ash.BrowserDataMigrator.MoveMigrator.ExtraDiskSpaceOccupied." + "DiffWithEstimate"; // This class "moves" Lacros data from Ash to Lacros. It migrates user data from // `original_profile_dir` (/home/user/<hash>/), denoted as <Ash PDD> from here @@ -190,6 +199,11 @@ // be carried out. Only set if `status` is // `kPreMigrationCleanUpNotEnoughSpace`. absl::optional<uint64_t> extra_bytes_required_to_be_freed; + + // Extra bytes that are estimated to be created due to the migration. It + // will later be used to calculate the diff between this estimate and the + // actual value. + absl::optional<int64_t> estimated_extra_bytes_created; }; // Called to determine where to start the migration. Returns @@ -243,7 +257,8 @@ // Set up a temporary directory to hold items that need to be split between // ash and lacros. This folder will hold ash's version of the items. static TaskResult SetupAshSplitDir( - const base::FilePath& original_profile_dir); + const base::FilePath& original_profile_dir, + const int64_t estimated_extra_bytes_created); // Called as a reply to `SetupAshSplitDir()`. Posts `MoveLacrosItemsToNewDir` // as the next step. @@ -334,6 +349,9 @@ // data on how long the migration takes. const base::ElapsedTimer timer_; + // Extra bytes that are estimated to be created due to the migration. + absl::optional<int64_t> estimated_extra_bytes_created_; + base::WeakPtrFactory<MoveMigrator> weak_factory_{this}; };
diff --git a/chrome/browser/ash/crosapi/move_migrator_unittest.cc b/chrome/browser/ash/crosapi/move_migrator_unittest.cc index ebe603b..022b15a 100644 --- a/chrome/browser/ash/crosapi/move_migrator_unittest.cc +++ b/chrome/browser/ash/crosapi/move_migrator_unittest.cc
@@ -551,7 +551,7 @@ ASSERT_TRUE(base::CreateDirectory(tmp_user_dir)); ASSERT_TRUE(base::CreateDirectory(tmp_profile_dir)); - EXPECT_EQ(MoveMigrator::SetupAshSplitDir(original_profile_dir).status, + EXPECT_EQ(MoveMigrator::SetupAshSplitDir(original_profile_dir, 0).status, MoveMigrator::TaskStatus::kSucceeded); const base::FilePath tmp_split_dir =
diff --git a/chrome/browser/ash/crosapi/stateful_lacros_loader.cc b/chrome/browser/ash/crosapi/stateful_lacros_loader.cc index 354b0d6e..06cdb4e 100644 --- a/chrome/browser/ash/crosapi/stateful_lacros_loader.cc +++ b/chrome/browser/ash/crosapi/stateful_lacros_loader.cc
@@ -9,7 +9,6 @@ #include "ash/constants/ash_switches.h" #include "base/command_line.h" #include "base/files/file_enumerator.h" -#include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/functional/bind.h" #include "base/logging.h" @@ -19,10 +18,12 @@ #include "base/task/thread_pool.h" #include "chrome/browser/ash/crosapi/browser_data_back_migrator.h" #include "chrome/browser/ash/crosapi/browser_util.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/component_updater/cros_component_installer_chromeos.h" #include "chrome/common/channel_info.h" #include "chromeos/ash/components/cryptohome/system_salt_getter.h" #include "components/component_updater/component_updater_paths.h" +#include "components/component_updater/component_updater_service.h" namespace crosapi { @@ -128,12 +129,15 @@ StatefulLacrosLoader::StatefulLacrosLoader( scoped_refptr<component_updater::CrOSComponentManager> manager) : StatefulLacrosLoader(manager, + g_browser_process->component_updater(), browser_util::GetLacrosComponentInfo().name) {} StatefulLacrosLoader::StatefulLacrosLoader( scoped_refptr<component_updater::CrOSComponentManager> manager, + component_updater::ComponentUpdateService* updater, const std::string& lacros_component_name) : component_manager_(manager), + component_update_service_(updater), lacros_component_name_(lacros_component_name) { base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::MayBlock()}, @@ -146,16 +150,18 @@ void StatefulLacrosLoader::Load(LoadCompletionCallback callback) { LOG(WARNING) << "Loading stateful lacros."; - component_manager_->Load( - lacros_component_name_, - component_updater::CrOSComponentManager::MountPolicy::kMount, - // If a compatible installation exists, use that and download any updates - // in the background. - component_updater::CrOSComponentManager::UpdatePolicy::kDontForce, - // If `callback` is null, means stateful lacros-chrome should be - // installed/updated but rootfs lacros-chrome will be used. - base::BindOnce(&StatefulLacrosLoader::OnLoad, weak_factory_.GetWeakPtr(), - std::move(callback))); + + // If stateful lacros-chrome is already loaded once, run `callback` + // immediately with cached version and path values. + // This code path is used in most cases as they are already calculated on + // getting version except for the case where BrowserLoader is forced to select + // stateful lacros-chrome by lacros selection policy. + if (IsReady()) { + std::move(callback).Run(version_.value(), path_.value()); + return; + } + + LoadInternal(std::move(callback)); } void StatefulLacrosLoader::Unload() { @@ -171,6 +177,7 @@ // TODO(crbug.com/1432069): Reset call while loading breaks the behavior. Need // to handle such edge cases. version_ = absl::nullopt; + path_ = absl::nullopt; } void StatefulLacrosLoader::GetVersion( @@ -178,7 +185,7 @@ // If version is already calculated, immediately return the cached value. // Calculate if not. // Note that version value is reset on reloading. - if (version_.has_value()) { + if (IsReady()) { std::move(callback).Run(version_.value()); return; } @@ -193,6 +200,23 @@ weak_factory_.GetWeakPtr(), std::move(callback))); } +void StatefulLacrosLoader::LoadInternal(LoadCompletionCallback callback) { + component_manager_->Load( + lacros_component_name_, + component_updater::CrOSComponentManager::MountPolicy::kMount, + // If a compatible installation exists, use that and download any updates + // in the background. + component_updater::CrOSComponentManager::UpdatePolicy::kDontForce, + // If `callback` is null, means stateful lacros-chrome should be + // installed/updated but rootfs lacros-chrome will be used. + base::BindOnce(&StatefulLacrosLoader::OnLoad, weak_factory_.GetWeakPtr(), + std::move(callback))); +} + +bool StatefulLacrosLoader::IsReady() { + return version_.has_value() && path_.has_value(); +} + void StatefulLacrosLoader::OnLoad( LoadCompletionCallback callback, component_updater::CrOSComponentManager::Error error, @@ -206,30 +230,19 @@ << "Error loading lacros component image: " << static_cast<int>(error) << ", " << path; - // If `version_` is already set, run `callback` immediately with the - // `version_` value. This code path is used in most cases except for the case - // where lacros selection is based on selection policy so that it skips the - // version comparison. - if (version_.has_value()) { - if (callback) { - std::move(callback).Run(version_.value(), path); - } - return; - } + version_ = is_stateful_lacros_available + ? browser_util::GetInstalledLacrosComponentVersion( + component_update_service_) + : base::Version(); + path_ = path; - component_manager_->GetVersion( - lacros_component_name_, - base::BindOnce( - &StatefulLacrosLoader::OnGetVersionFromComponentManager, - weak_factory_.GetWeakPtr(), - base::BindOnce( - [](LoadCompletionCallback callback, const base::FilePath& path, - const base::Version& version) { - if (callback) { - std::move(callback).Run(std::move(version), path); - } - }, - std::move(callback), path))); + if (callback) { + std::move(callback).Run(version_.value(), path_.value()); + } else { + LOG(WARNING) + << "stateful lacros-chrome installation completed in the background in " + << path << ", version is " << version_.value(); + } } void StatefulLacrosLoader::OnCheckInstalledToGetVersion( @@ -238,29 +251,20 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!is_installed) { - version_ = base::Version(); - std::move(callback).Run(version_.value()); + // Run `callback` immediately with empty version and start loading stateful + // lacros-chrome in the background. + // TODO(crbug.com/1432069): Reconsider `version_` and `path_` values + // semantics. + LoadInternal({}); + std::move(callback).Run(base::Version()); return; } - component_manager_->GetVersion( - lacros_component_name_, - base::BindOnce(&StatefulLacrosLoader::OnGetVersionFromComponentManager, - weak_factory_.GetWeakPtr(), std::move(callback))); -} - -void StatefulLacrosLoader::OnGetVersionFromComponentManager( - base::OnceCallback<void(const base::Version&)> callback, - const base::Version& version) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - LOG_IF(WARNING, version.IsValid()) - << "Error getting version of lacros component image"; - - version_ = version; - if (callback) { - std::move(callback).Run(version_.value()); - } + LoadInternal(base::BindOnce( + [](base::OnceCallback<void(const base::Version&)> callback, + base::Version version, + const base::FilePath&) { std::move(callback).Run(version); }, + std::move(callback))); } void StatefulLacrosLoader::OnCheckInstalledToUnload(bool was_installed) {
diff --git a/chrome/browser/ash/crosapi/stateful_lacros_loader.h b/chrome/browser/ash/crosapi/stateful_lacros_loader.h index ed25c5b4..d4e0dcf 100644 --- a/chrome/browser/ash/crosapi/stateful_lacros_loader.h +++ b/chrome/browser/ash/crosapi/stateful_lacros_loader.h
@@ -7,7 +7,9 @@ #include <string> +#include "base/files/file_path.h" #include "base/functional/callback.h" +#include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" @@ -16,9 +18,9 @@ #include "chrome/browser/component_updater/cros_component_manager.h" #include "third_party/abseil-cpp/absl/types/optional.h" -namespace base { -class FilePath; -} // namespace base +namespace component_updater { +class ComponentUpdateService; +} // namespace component_updater namespace crosapi { @@ -30,6 +32,7 @@ // Constructor for testing. explicit StatefulLacrosLoader( scoped_refptr<component_updater::CrOSComponentManager> manager, + component_updater::ComponentUpdateService* updater, const std::string& lacros_component_name); StatefulLacrosLoader(const StatefulLacrosLoader&) = delete; StatefulLacrosLoader& operator=(const StatefulLacrosLoader&) = delete; @@ -43,6 +46,12 @@ base::OnceCallback<void(const base::Version&)> callback) override; private: + void LoadInternal(LoadCompletionCallback callback); + + // Returns true if the stateful lacros-chrome is already loaded and both + // `version_` and `path_` are ready. + bool IsReady(); + // Called after Load. void OnLoad(LoadCompletionCallback callback, component_updater::CrOSComponentManager::Error error, @@ -70,9 +79,15 @@ // For cases where it failed to read the version, invalid `base::Version()` is // set. absl::optional<base::Version> version_; + // Cache the path to installed lacros-chrome path. + absl::optional<base::FilePath> path_; scoped_refptr<component_updater::CrOSComponentManager> component_manager_; + // May be null in tests. + const raw_ptr<component_updater::ComponentUpdateService, ExperimentalAsh> + component_update_service_; + const std::string lacros_component_name_; // Used for DCHECKs to ensure method calls executed in the correct thread.
diff --git a/chrome/browser/ash/crosapi/stateful_lacros_loader_unittest.cc b/chrome/browser/ash/crosapi/stateful_lacros_loader_unittest.cc index 949658e..ff2d7ef 100644 --- a/chrome/browser/ash/crosapi/stateful_lacros_loader_unittest.cc +++ b/chrome/browser/ash/crosapi/stateful_lacros_loader_unittest.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/component_updater/fake_cros_component_manager.h" #include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h" #include "chromeos/ash/components/standalone_browser/browser_support.h" +#include "components/component_updater/mock_component_updater_service.h" #include "components/update_client/update_client.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" @@ -25,7 +26,10 @@ namespace crosapi { namespace { +using testing::Return; + constexpr char kLacrosComponentName[] = "lacros-dogfood-dev"; +constexpr char kLacrosComponentId[] = "ldobopbhiamakmncndpkeelenhdmgfhk"; class StatefulLacrosLoaderTest : public testing::Test { public: @@ -45,7 +49,8 @@ browser_part_->InitializeCrosComponentManager(component_manager_); stateful_lacros_loader_ = std::make_unique<StatefulLacrosLoader>( - component_manager_, kLacrosComponentName); + component_manager_, &mock_component_update_service_, + kLacrosComponentName); EXPECT_TRUE(BrowserLoader::WillLoadStatefulComponentBuilds()); } @@ -58,12 +63,19 @@ protected: content::BrowserTaskEnvironment task_environment_; + component_updater::MockComponentUpdateService mock_component_update_service_; scoped_refptr<component_updater::FakeCrOSComponentManager> component_manager_; std::unique_ptr<BrowserProcessPlatformPartTestApi> browser_part_; std::unique_ptr<StatefulLacrosLoader> stateful_lacros_loader_; }; TEST_F(StatefulLacrosLoaderTest, LoadStatefulLacros) { + std::u16string lacros_component_name = + base::UTF8ToUTF16(base::StringPiece(kLacrosComponentName)); + EXPECT_CALL(mock_component_update_service_, GetComponents()) + .WillOnce(Return(std::vector<component_updater::ComponentInfo>{ + {kLacrosComponentId, "", lacros_component_name, version, ""}})); + // Set stateful lacros-chrome version. Wait until the version calculation is // completed before verifying the version. base::test::TestFuture<base::Version, const base::FilePath&> future;
diff --git a/chrome/browser/ash/dbus/dlp_files_policy_service_provider.cc b/chrome/browser/ash/dbus/dlp_files_policy_service_provider.cc index 4f87a17..ec879fc 100644 --- a/chrome/browser/ash/dbus/dlp_files_policy_service_provider.cc +++ b/chrome/browser/ash/dbus/dlp_files_policy_service_provider.cc
@@ -57,8 +57,8 @@ return data_controls::Component::kUsb; case ::dlp::DlpComponent::GOOGLE_DRIVE: return data_controls::Component::kDrive; - case ::dlp::DlpComponent::MICROSOFT_ONEDRIVE: // TODO(b/280575394): Handle - // OneDrive properly. + case ::dlp::DlpComponent::MICROSOFT_ONEDRIVE: + return data_controls::Component::kOneDrive; case ::dlp::DlpComponent::UNKNOWN_COMPONENT: case ::dlp::DlpComponent::SYSTEM: return data_controls::Component::kUnknownComponent;
diff --git a/chrome/browser/ash/extensions/file_manager/private_api_file_system.cc b/chrome/browser/ash/extensions/file_manager/private_api_file_system.cc index 83cd4c9..9396926 100644 --- a/chrome/browser/ash/extensions/file_manager/private_api_file_system.cc +++ b/chrome/browser/ash/extensions/file_manager/private_api_file_system.cc
@@ -270,6 +270,8 @@ return VolumeType::VOLUME_TYPE_REMOVABLE; case Component::kDrive: return VolumeType::VOLUME_TYPE_DRIVE; + case Component::kOneDrive: + return VolumeType::VOLUME_TYPE_PROVIDED; case Component::kUnknownComponent: NOTREACHED() << "DLP component not set."; return {};
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest.cc b/chrome/browser/ash/file_manager/file_manager_browsertest.cc index 858c780..69e7e7ee 100644 --- a/chrome/browser/ash/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
@@ -224,6 +224,11 @@ return *this; } + TestCase& EnableDriveShortcuts() { + options.enable_drive_shortcuts = true; + return *this; + } + TestCase& SetDeviceMode(DeviceMode device_mode) { options.device_mode = device_mode; return *this; @@ -305,6 +310,10 @@ full_name += "_DriveBulkPinning"; } + if (options.enable_drive_shortcuts) { + full_name += "_DriveShortcuts"; + } + switch (options.device_mode) { case kDeviceModeNotSet: break; @@ -1545,6 +1554,7 @@ TestCase("driveAvailableOfflineDirectoryGearMenu"), TestCase("driveAvailableOfflineActionBar"), TestCase("driveLinkToDirectory"), + TestCase("driveLinkToDirectory").EnableDriveShortcuts(), TestCase("driveLinkOpenFileThroughLinkedDirectory"), TestCase("driveLinkOpenFileThroughTransitiveLink"), TestCase("driveWelcomeBanner"),
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc index 59df4d4..740642f 100644 --- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc +++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -2159,6 +2159,12 @@ ash::features::kFeatureManagementDriveFsBulkPinning); } + if (options.enable_drive_shortcuts) { + enabled_features.push_back(ash::features::kFilesDriveShortcuts); + } else { + disabled_features.push_back(ash::features::kFilesDriveShortcuts); + } + if (options.feature_ids.size() > 0) { for (const std::string& feature_id : options.feature_ids) { base::AddTagToTestResult("feature_id", feature_id); @@ -3354,6 +3360,11 @@ return; } + if (name == "isDriveShortcutsEnabled") { + *output = options.enable_drive_shortcuts ? "true" : "false"; + return; + } + if (name == "isOsFeedbackEnabled") { *output = options.enable_os_feedback ? "true" : "false"; return;
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.h b/chrome/browser/ash/file_manager/file_manager_browsertest_base.h index 8b07328..fc16e5a9 100644 --- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.h +++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.h
@@ -179,6 +179,9 @@ // Whether tests should enable the Google Drive bulk pinning feature. bool enable_drive_bulk_pinning = false; + // Whether to enable Drive shortcuts showing a badge or not. + bool enable_drive_shortcuts = false; + // Feature IDs associated for mapping test cases and features. std::vector<std::string> feature_ids; };
diff --git a/chrome/browser/ash/file_manager/file_manager_string_util.cc b/chrome/browser/ash/file_manager/file_manager_string_util.cc index f2b2ea4..caeb8f9c 100644 --- a/chrome/browser/ash/file_manager/file_manager_string_util.cc +++ b/chrome/browser/ash/file_manager/file_manager_string_util.cc
@@ -220,6 +220,8 @@ IDS_FILE_BROWSER_BULK_PINNING_OFFLINE_LABEL); SET_STRING("DRIVE_BULK_PINNING_NOT_ENOUGH_SPACE", IDS_FILE_BROWSER_BULK_PINNING_NOT_ENOUGH_SPACE_LABEL); + SET_STRING("DRIVE_PREPARING_TO_SYNC", + IDS_FILE_BROWSER_BULK_PINNING_PREPARING_TO_SYNC); } void AddStringsForMediaView(base::Value::Dict* dict) { @@ -1093,6 +1095,8 @@ SET_STRING("DLP_COMPONENT_PLAY", IDS_FILE_BROWSER_DLP_COMPONENT_PLAY); SET_STRING("DLP_COMPONENT_LINUX", IDS_FILE_BROWSER_DLP_COMPONENT_LINUX); SET_STRING("DLP_COMPONENT_VM", IDS_FILE_BROWSER_DLP_COMPONENT_VM); + SET_STRING("DLP_COMPONENT_MICROSOFT_ONEDRIVE", + IDS_FILE_BROWSER_DLP_COMPONENT_MICROSOFT_ONEDRIVE); SET_STRING("ONE_DRIVE_MOVED_FILE_NUDGE", IDS_FILE_BROWSER_ONE_DRIVE_MOVED_FILE_NUDGE); SET_STRING("DRIVE_MOVED_FILE_NUDGE", IDS_FILE_BROWSER_DRIVE_MOVED_FILE_NUDGE);
diff --git a/chrome/browser/ash/file_manager/io_task.cc b/chrome/browser/ash/file_manager/io_task.cc index 51c1439..a662707 100644 --- a/chrome/browser/ash/file_manager/io_task.cc +++ b/chrome/browser/ash/file_manager/io_task.cc
@@ -22,6 +22,12 @@ void IOTask::CompleteWithError(PolicyErrorType policy_error) {} +bool ConflictPauseParams::operator==(const ConflictPauseParams& other) const = + default; + +bool PolicyPauseParams::operator==(const PolicyPauseParams& other) const = + default; + PauseParams::PauseParams() = default; PauseParams::PauseParams(const PauseParams& other) = default; @@ -32,6 +38,11 @@ PauseParams& PauseParams::operator=(PauseParams&& other) = default; +bool PauseParams::operator==(const PauseParams& other) const { + return (conflict_params == other.conflict_params) && + (policy_params == other.policy_params); +} + PauseParams::~PauseParams() = default; ResumeParams::ResumeParams() = default; @@ -142,7 +153,29 @@ base::BindOnce(&DummyIOTask::DoProgress, weak_ptr_factory_.GetWeakPtr())); } +void DummyIOTask::Pause(PauseParams pause_params) { + progress_.state = State::kPaused; + progress_.pause_params = pause_params; +} + +void DummyIOTask::Resume(ResumeParams resume_params) { + progress_.state = State::kInProgress; +} + +void DummyIOTask::Cancel() { + progress_.state = State::kCancelled; +} + +void DummyIOTask::CompleteWithError(PolicyErrorType policy_error) { + progress_.state = State::kError; + progress_.policy_error = policy_error; +} + void DummyIOTask::DoProgress() { + if (progress_.IsPaused()) { + return; + } + progress_.bytes_transferred = 1; progress_callback_.Run(progress_); @@ -160,8 +193,4 @@ std::move(complete_callback_).Run(std::move(progress_)); } -void DummyIOTask::Cancel() { - progress_.state = State::kCancelled; -} - } // namespace file_manager::io_task
diff --git a/chrome/browser/ash/file_manager/io_task.h b/chrome/browser/ash/file_manager/io_task.h index 56c9eac..389b552 100644 --- a/chrome/browser/ash/file_manager/io_task.h +++ b/chrome/browser/ash/file_manager/io_task.h
@@ -92,6 +92,8 @@ // The conflict copy or move target URL. std::string conflict_target_url; + + bool operator==(const ConflictPauseParams& other) const; }; // I/O task state::PAUSED parameters when paused to show a policy warning. @@ -99,6 +101,8 @@ struct PolicyPauseParams { // One of kDlp, kEnterpriseConnectors. PolicyErrorType type; + + bool operator==(const PolicyPauseParams& other) const; }; // I/O task state::PAUSED parameters. Only one of conflict or policy params @@ -112,6 +116,8 @@ PauseParams(PauseParams&& other); PauseParams& operator=(PauseParams&& other); + bool operator==(const PauseParams& other) const; + ~PauseParams(); // Set iff pausing due to name conflict. @@ -323,10 +329,13 @@ bool show_notification = true); ~DummyIOTask() override; + // IOTask overrides: void Execute(ProgressCallback progress_callback, CompleteCallback complete_callback) override; - + void Pause(PauseParams pause_params) override; + void Resume(ResumeParams resume_params) override; void Cancel() override; + void CompleteWithError(PolicyErrorType policy_error) override; private: void DoProgress();
diff --git a/chrome/browser/ash/file_manager/io_task_controller.cc b/chrome/browser/ash/file_manager/io_task_controller.cc index d6072cf..8ffcb13 100644 --- a/chrome/browser/ash/file_manager/io_task_controller.cc +++ b/chrome/browser/ash/file_manager/io_task_controller.cc
@@ -88,6 +88,19 @@ return task_id; } +void IOTaskController::Pause(IOTaskId task_id, PauseParams params) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + auto it = tasks_.find(task_id); + if (it != tasks_.end()) { + IOTask* task = it->second.get(); + task->Pause(std::move(params)); + NotifyIOTaskObservers(task->progress()); + } else { + LOG(WARNING) << "Failed to pause task: " << task_id << " not found"; + } +} + void IOTaskController::Resume(IOTaskId task_id, ResumeParams params) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -95,6 +108,7 @@ if (it != tasks_.end()) { IOTask* task = it->second.get(); task->Resume(std::move(params)); + NotifyIOTaskObservers(task->progress()); } else { LOG(WARNING) << "Failed to resume task: " << task_id << " not found"; } @@ -129,6 +143,21 @@ } } +void IOTaskController::CompleteWithError(IOTaskId task_id, + PolicyErrorType policy_error) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + auto it = tasks_.find(task_id); + if (it != tasks_.end()) { + IOTask* task = it->second.get(); + task->CompleteWithError(std::move(policy_error)); + NotifyIOTaskObservers(task->progress()); + RemoveIOTask(task_id); + } else { + LOG(WARNING) << "Failed to abort task: " << task_id << " not found"; + } +} + device::mojom::WakeLock* IOTaskController::GetWakeLock() { if (!wake_lock_) { mojo::Remote<device::mojom::WakeLockProvider> provider;
diff --git a/chrome/browser/ash/file_manager/io_task_controller.h b/chrome/browser/ash/file_manager/io_task_controller.h index 185db0e0..a3cda298 100644 --- a/chrome/browser/ash/file_manager/io_task_controller.h +++ b/chrome/browser/ash/file_manager/io_task_controller.h
@@ -47,6 +47,9 @@ // Queues an IOTask and returns its ID. IOTaskId Add(std::unique_ptr<IOTask> task); + // Pauses a task from the queue. + void Pause(IOTaskId task_id, PauseParams params); + // Resumes a task from the queue. void Resume(IOTaskId task_id, ResumeParams params); @@ -56,6 +59,9 @@ // Makes tasks in state::PAUSED emit (broadcast) their progress status. void ProgressPausedTasks(); + // Aborts a task from the queue. + void CompleteWithError(IOTaskId task_id, PolicyErrorType policy_error); + // For tests only; returns the current wake lock counter. This counter is // incremented by 1 for every time we get a wake lock and decremented every // time we release it.
diff --git a/chrome/browser/ash/file_manager/io_task_controller_unittest.cc b/chrome/browser/ash/file_manager/io_task_controller_unittest.cc index 9584e1f..49fa37a8 100644 --- a/chrome/browser/ash/file_manager/io_task_controller_unittest.cc +++ b/chrome/browser/ash/file_manager/io_task_controller_unittest.cc
@@ -147,6 +147,111 @@ io_task_controller_.RemoveObserver(&observer); } +TEST_F(IOTaskControllerTest, PauseResume) { + IOTaskStatusObserver observer; + io_task_controller_.AddObserver(&observer); + + std::vector<storage::FileSystemURL> source_urls{ + CreateFileSystemURL("filesystem:chrome-extension://abc/external/foo/src"), + }; + auto dest = CreateFileSystemURL( + "filesystem:chrome-extension://abc/external/foo/dest"); + + // All progress statuses should return the same |type|, |source_urls| and + // |destination_folder| given, so set up a base matcher to check this. + auto base_matcher = + AllOf(Field(&ProgressStatus::type, OperationType::kMove), + Field(&ProgressStatus::sources, EntryStatusUrls(source_urls)), + Property(&ProgressStatus::GetDestinationFolder, dest)); + + // The controller should synchronously send out a progress status when queued. + EXPECT_CALL(observer, OnIOTaskStatus( + AllOf(Field(&ProgressStatus::state, State::kQueued), + base_matcher))); + + // The controller should also synchronously execute the I/O task, which will + // send out another status. + EXPECT_CALL(observer, OnIOTaskStatus(AllOf( + Field(&ProgressStatus::state, State::kInProgress), + base_matcher))); + + auto task_id = io_task_controller_.Add( + std::make_unique<DummyIOTask>(source_urls, dest, OperationType::kMove)); + + // Pause should synchronously send a progress status. + PauseParams pause_params; + pause_params.policy_params = PolicyPauseParams(PolicyErrorType::kDlp); + EXPECT_CALL(observer, OnIOTaskStatus(AllOf( + Field(&ProgressStatus::state, State::kPaused), + Field(&ProgressStatus::task_id, task_id), + Field(&ProgressStatus::pause_params, pause_params), + base_matcher))); + io_task_controller_.Pause(task_id, pause_params); + + // Resume should synchronously send a progress status. + EXPECT_CALL(observer, + OnIOTaskStatus(AllOf( + Field(&ProgressStatus::state, State::kInProgress), + Field(&ProgressStatus::task_id, task_id), base_matcher))); + io_task_controller_.Resume(task_id, ResumeParams()); + + // Wait for the task to finish successfully. + EXPECT_CALL(observer, + OnIOTaskStatus(AllOf( + Field(&ProgressStatus::state, State::kSuccess), + Field(&ProgressStatus::task_id, task_id), base_matcher))); + base::RunLoop().RunUntilIdle(); + + io_task_controller_.RemoveObserver(&observer); +} + +TEST_F(IOTaskControllerTest, CompleteWithError) { + IOTaskStatusObserver observer; + io_task_controller_.AddObserver(&observer); + + std::vector<storage::FileSystemURL> source_urls{ + CreateFileSystemURL("filesystem:chrome-extension://abc/external/foo/src"), + }; + auto dest = CreateFileSystemURL( + "filesystem:chrome-extension://abc/external/foo/dest"); + + // All progress statuses should return the same |type|, |source_urls| and + // |destination_folder| given, so set up a base matcher to check this. + auto base_matcher = + AllOf(Field(&ProgressStatus::type, OperationType::kMove), + Field(&ProgressStatus::sources, EntryStatusUrls(source_urls)), + Property(&ProgressStatus::GetDestinationFolder, dest)); + + // The controller should synchronously send out a progress status when queued. + EXPECT_CALL(observer, OnIOTaskStatus( + AllOf(Field(&ProgressStatus::state, State::kQueued), + base_matcher))); + + // The controller should also synchronously execute the I/O task, which will + // send out another status. + EXPECT_CALL(observer, OnIOTaskStatus(AllOf( + Field(&ProgressStatus::state, State::kInProgress), + base_matcher))); + + auto task_id = io_task_controller_.Add( + std::make_unique<DummyIOTask>(source_urls, dest, OperationType::kMove)); + + // CompleteWithError should synchronously send a progress status. + EXPECT_CALL(observer, + OnIOTaskStatus(AllOf( + Field(&ProgressStatus::state, State::kError), + Field(&ProgressStatus::task_id, task_id), + Field(&ProgressStatus::policy_error, PolicyErrorType::kDlp), + base_matcher))); + io_task_controller_.CompleteWithError(task_id, PolicyErrorType::kDlp); + + // No more observer notifications should come after CompleteWithError as the + // task is deleted. + base::RunLoop().RunUntilIdle(); + + io_task_controller_.RemoveObserver(&observer); +} + } // namespace } // namespace io_task } // namespace file_manager
diff --git a/chrome/browser/ash/file_system_provider/extension_provider.cc b/chrome/browser/ash/file_system_provider/extension_provider.cc index 1bd1a81..cb7f86a 100644 --- a/chrome/browser/ash/file_system_provider/extension_provider.cc +++ b/chrome/browser/ash/file_system_provider/extension_provider.cc
@@ -13,12 +13,14 @@ #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/ash/file_system_provider/mount_request_handler.h" +#include "chrome/browser/ash/file_system_provider/odfs_metrics.h" #include "chrome/browser/ash/file_system_provider/provided_file_system.h" #include "chrome/browser/ash/file_system_provider/request_dispatcher_impl.h" #include "chrome/browser/ash/file_system_provider/throttled_file_system.h" #include "chrome/browser/chromeos/extensions/file_system_provider/service_worker_lifetime_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_features.h" +#include "chrome/common/extensions/extension_constants.h" #include "chromeos/constants/chromeos_features.h" #include "components/services/app_service/public/cpp/app_types.h" #include "extensions/browser/event_router.h" @@ -153,8 +155,16 @@ base::BindRepeating(&ExtensionProvider::OnLacrosOperationForwarded, weak_ptr_factory_.GetWeakPtr()), GetServiceWorkerLifetimeManager(profile)); + if (chromeos::features::IsUploadOfficeToCloudEnabled() && + provider_id_.GetExtensionId() == extension_misc::kODFSExtensionId) { + odfs_metrics_ = std::make_unique<ODFSMetrics>(); + } request_manager_ = std::make_unique<RequestManager>( profile, /*notification_manager=*/nullptr, kDefaultMountTimeout); + if (chromeos::features::IsUploadOfficeToCloudEnabled() && + provider_id_.GetExtensionId() == extension_misc::kODFSExtensionId) { + request_manager_->AddObserver(odfs_metrics_.get()); + } ObserveAppServiceForIcons(profile); }
diff --git a/chrome/browser/ash/file_system_provider/extension_provider.h b/chrome/browser/ash/file_system_provider/extension_provider.h index 8dde59b0..ec8fa02 100644 --- a/chrome/browser/ash/file_system_provider/extension_provider.h +++ b/chrome/browser/ash/file_system_provider/extension_provider.h
@@ -27,6 +27,7 @@ namespace file_system_provider { class RequestDispatcher; +class ODFSMetrics; class ExtensionProvider : public ProviderInterface, public apps::AppRegistryCache::Observer { @@ -73,6 +74,7 @@ std::string name_; IconSet icon_set_; std::unique_ptr<RequestDispatcher> request_dispatcher_; + std::unique_ptr<ODFSMetrics> odfs_metrics_; std::unique_ptr<RequestManager> request_manager_; base::WeakPtrFactory<ExtensionProvider> weak_ptr_factory_{this};
diff --git a/chrome/browser/ash/file_system_provider/odfs_metrics.cc b/chrome/browser/ash/file_system_provider/odfs_metrics.cc new file mode 100644 index 0000000..00ed93c1 --- /dev/null +++ b/chrome/browser/ash/file_system_provider/odfs_metrics.cc
@@ -0,0 +1,121 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/file_system_provider/odfs_metrics.h" + +#include "base/metrics/histogram_functions.h" +#include "base/strings/strcat.h" + +namespace ash::file_system_provider { + +namespace { + +const char* ToString(RequestType request_type) { + switch (request_type) { + case RequestType::kAbort: + return "onAbortRequested"; + case RequestType::kAddWatcher: + return "onAddWatcherRequested"; + case RequestType::kCloseFile: + return "onCloseFileRequested"; + case RequestType::kConfigure: + return "onConfigureRequested"; + case RequestType::kCopyEntry: + return "onCopyEntryRequested"; + case RequestType::kCreateDirectory: + return "onCreateDirectoryRequested"; + case RequestType::kCreateFile: + return "onCreateFileRequested"; + case RequestType::kDeleteEntry: + return "onDeleteEntryRequested"; + case RequestType::kExecuteAction: + return "onExecuteActionRequested"; + case RequestType::kGetActions: + return "onGetActionsRequested"; + case RequestType::kGetMetadata: + return "onGetMetadataRequested"; + case RequestType::kMount: + return "onMountRequested"; + case RequestType::kMoveEntry: + return "onMoveEntryRequested"; + case RequestType::kOpenFile: + return "onOpenFileRequested"; + case RequestType::kReadDirectory: + return "onReadDirectoryRequested"; + case RequestType::kReadFile: + return "onReadFileRequested"; + case RequestType::kRemoveWatcher: + return "onRemoveWatcherRequested"; + case RequestType::kTruncate: + return "onTruncateRequested"; + case RequestType::kUnmount: + return "onUnmountRequested"; + case RequestType::kWriteFile: + return "onWriteFileRequested"; + } +} + +std::string GetHistogramName(const char* metric, RequestType request_type) { + return base::StrCat({"FileBrowser.OfficeFiles.ODFS.FileSystemProvider.", + metric, ".", ToString(request_type)}); +} + +} // namespace + +struct ODFSMetrics::Request { + RequestType request_type; + base::File::Error result = base::File::FILE_OK; + base::ElapsedTimer latency_timer; +}; + +ODFSMetrics::ODFSMetrics() = default; + +ODFSMetrics::~ODFSMetrics() = default; + +void ODFSMetrics::OnRequestCreated(int request_id, RequestType type) { + Request& request = requests_[request_id]; + request.request_type = type; + request.latency_timer.Begin(); +} + +void ODFSMetrics::OnRequestDestroyed(int request_id) { + auto it = requests_.find(request_id); + if (it == requests_.end()) { + return; + } + Request& request = it->second; + base::UmaHistogramMediumTimes(GetHistogramName("Time", request.request_type), + request.latency_timer.Elapsed()); + requests_.erase(it); +} + +void ODFSMetrics::OnRequestExecuted(int request_id) {} + +void ODFSMetrics::OnRequestFulfilled(int request_id, + const RequestValue& result, + bool has_more) { + if (!has_more) { + RecordResult(request_id, base::File::FILE_OK); + } +} + +void ODFSMetrics::OnRequestRejected(int request_id, + const RequestValue& result, + base::File::Error error) { + RecordResult(request_id, error); +} + +void ODFSMetrics::OnRequestTimedOut(int request_id) {} + +void ODFSMetrics::RecordResult(int request_id, base::File::Error error) { + auto it = requests_.find(request_id); + if (it == requests_.end()) { + return; + } + Request& request = it->second; + base::UmaHistogramExactLinear(GetHistogramName("Error", request.request_type), + -error, -base::File::FILE_ERROR_MAX); +} + +} // namespace ash::file_system_provider
diff --git a/chrome/browser/ash/file_system_provider/odfs_metrics.h b/chrome/browser/ash/file_system_provider/odfs_metrics.h new file mode 100644 index 0000000..829dc46 --- /dev/null +++ b/chrome/browser/ash/file_system_provider/odfs_metrics.h
@@ -0,0 +1,41 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_FILE_SYSTEM_PROVIDER_ODFS_METRICS_H_ +#define CHROME_BROWSER_ASH_FILE_SYSTEM_PROVIDER_ODFS_METRICS_H_ + +#include <map> + +#include "base/files/file.h" +#include "base/timer/elapsed_timer.h" +#include "chrome/browser/ash/file_system_provider/request_manager.h" + +namespace ash::file_system_provider { + +class ODFSMetrics : public RequestManager::Observer { + public: + ODFSMetrics(); + ~ODFSMetrics() override; + // RequestManager::Observer overrides: + void OnRequestCreated(int request_id, RequestType type) override; + void OnRequestDestroyed(int request_id) override; + void OnRequestExecuted(int request_id) override; + void OnRequestFulfilled(int request_id, + const RequestValue& result, + bool has_more) override; + void OnRequestRejected(int request_id, + const RequestValue& result, + base::File::Error error) override; + void OnRequestTimedOut(int request_id) override; + + private: + struct Request; + void RecordResult(int request_id, base::File::Error error); + + std::map<int, Request> requests_; +}; + +} // namespace ash::file_system_provider + +#endif // CHROME_BROWSER_ASH_FILE_SYSTEM_PROVIDER_ODFS_METRICS_H_
diff --git a/chrome/browser/ash/file_system_provider/provided_file_system.cc b/chrome/browser/ash/file_system_provider/provided_file_system.cc index 72fbf06..49a77ebd 100644 --- a/chrome/browser/ash/file_system_provider/provided_file_system.cc +++ b/chrome/browser/ash/file_system_provider/provided_file_system.cc
@@ -15,6 +15,7 @@ #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "chrome/browser/ash/file_system_provider/notification_manager.h" +#include "chrome/browser/ash/file_system_provider/odfs_metrics.h" #include "chrome/browser/ash/file_system_provider/operation_request_manager.h" #include "chrome/browser/ash/file_system_provider/operations/abort.h" #include "chrome/browser/ash/file_system_provider/operations/add_watcher.h" @@ -170,6 +171,11 @@ base::BindRepeating(&ProvidedFileSystem::OnLacrosOperationForwarded, weak_ptr_factory_.GetWeakPtr()), GetServiceWorkerLifetimeManager(profile_)); + const ProviderId& provider_id = file_system_info_.provider_id(); + if (chromeos::features::IsUploadOfficeToCloudEnabled() && + provider_id.GetExtensionId() == extension_misc::kODFSExtensionId) { + odfs_metrics_ = std::make_unique<ODFSMetrics>(); + } ConstructRequestManager(); } @@ -903,6 +909,11 @@ request_manager_ = std::make_unique<OperationRequestManager>( profile_, extension_id, notification_manager_.get(), operation_timeout); + + if (chromeos::features::IsUploadOfficeToCloudEnabled() && + extension_id == extension_misc::kODFSExtensionId) { + request_manager_->AddObserver(odfs_metrics_.get()); + } } } // namespace file_system_provider
diff --git a/chrome/browser/ash/file_system_provider/provided_file_system.h b/chrome/browser/ash/file_system_provider/provided_file_system.h index c0b8137f..8dee964 100644 --- a/chrome/browser/ash/file_system_provider/provided_file_system.h +++ b/chrome/browser/ash/file_system_provider/provided_file_system.h
@@ -44,6 +44,7 @@ class NotificationManagerInterface; class RequestDispatcher; +class ODFSMetrics; // Automatically calls the |update_callback| after all of the callbacks created // with |CreateCallback| are called. @@ -257,6 +258,7 @@ ProvidedFileSystemInfo file_system_info_; std::unique_ptr<NotificationManagerInterface> notification_manager_; std::unique_ptr<RequestDispatcher> request_dispatcher_; + std::unique_ptr<ODFSMetrics> odfs_metrics_; std::unique_ptr<OperationRequestManager> request_manager_; Watchers watchers_; Queue watcher_queue_;
diff --git a/chrome/browser/ash/login/app_mode/test/kiosk_enterprise_browsertest.cc b/chrome/browser/ash/login/app_mode/test/kiosk_enterprise_browsertest.cc index 36abf13b..553a6ff 100644 --- a/chrome/browser/ash/login/app_mode/test/kiosk_enterprise_browsertest.cc +++ b/chrome/browser/ash/login/app_mode/test/kiosk_enterprise_browsertest.cc
@@ -258,17 +258,9 @@ WaitForAppLaunchSuccess(); } -// TODO(crbug.com/1446486): Flaky on Chrome OS. -#if BUILDFLAG(IS_CHROMEOS) -#define MAYBE_LaunchingAppThatRequiresNetworkWhilstOfflineShouldShowNetworkScreen \ - DISABLED_LaunchingAppThatRequiresNetworkWhilstOfflineShouldShowNetworkScreen -#else -#define MAYBE_LaunchingAppThatRequiresNetworkWhilstOfflineShouldShowNetworkScreen \ - LaunchingAppThatRequiresNetworkWhilstOfflineShouldShowNetworkScreen -#endif IN_PROC_BROWSER_TEST_F( KioskEnterpriseTest, - MAYBE_LaunchingAppThatRequiresNetworkWhilstOfflineShouldShowNetworkScreen) { + LaunchingAppThatRequiresNetworkWhilstOfflineShouldShowNetworkScreen) { ScopedCanConfigureNetwork can_configure_network(true); // Start app launch with network portal state.
diff --git a/chrome/browser/ash/login/ui/login_display_host_webui.cc b/chrome/browser/ash/login/ui/login_display_host_webui.cc index 32c56eda..340e0df 100644 --- a/chrome/browser/ash/login/ui/login_display_host_webui.cc +++ b/chrome/browser/ash/login/ui/login_display_host_webui.cc
@@ -838,7 +838,9 @@ // Subscribe to crash events. content::WebContentsObserver::Observe(login_view_->GetWebContents()); login_view_->LoadURL(url); - login_window_->Show(); + if (!features::IsOobeSimonEnabled()) { + login_window_->Show(); + } CHECK(GetOobeUI()); GetOobeUI()->AddObserver(this); }
diff --git a/chrome/browser/ash/login/wizard_controller_browsertest.cc b/chrome/browser/ash/login/wizard_controller_browsertest.cc index 05ecd048..78bd92e 100644 --- a/chrome/browser/ash/login/wizard_controller_browsertest.cc +++ b/chrome/browser/ash/login/wizard_controller_browsertest.cc
@@ -1723,6 +1723,8 @@ EXPECT_EQ(AutoEnrollmentCheckScreenView::kScreenId.AsId(), GetErrorScreen()->GetParentScreen()); test::OobeJS().ExpectHiddenPath(kGuestSessionLink); + histogram_tester()->ExpectBucketCount( + "Enterprise.AutoEnrollmentControllerTimeout", 3 /*kTimeoutUnified*/, 1); } // Tests that AutoEnrollmentController does not create another
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller_ash.cc b/chrome/browser/ash/policy/dlp/dlp_files_controller_ash.cc index 9e8f928..4fbb8ec 100644 --- a/chrome/browser/ash/policy/dlp/dlp_files_controller_ash.cc +++ b/chrome/browser/ash/policy/dlp/dlp_files_controller_ash.cc
@@ -51,6 +51,7 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.h" #include "chromeos/dbus/dlp/dlp_client.h" #include "chromeos/dbus/dlp/dlp_service.pb.h" #include "chromeos/ui/base/file_icon_util.h" @@ -176,6 +177,20 @@ return data_controls::Component::kDrive; } + if (ash::cloud_upload::CloudUploadDialog::IsODFSMounted(profile)) { + auto* service = ash::file_system_provider::Service::Get(profile); + auto provider_id = + ash::file_system_provider::ProviderId::CreateFromExtensionId( + file_manager::file_tasks::GetODFSExtensionId(profile)); + auto one_drive_file_systems = + service->GetProvidedFileSystemInfoList(provider_id); + CHECK(one_drive_file_systems.size() == 1); + + if (one_drive_file_systems[0].mount_path().IsParent(file_path)) { + return data_controls::Component::kOneDrive; + } + } + base::FilePath linux_files = file_manager::util::GetCrostiniMountDirectory(profile); if (linux_files == file_path || linux_files.IsParent(file_path)) { @@ -213,6 +228,8 @@ return ::dlp::DlpComponent::USB; case data_controls::Component::kDrive: return ::dlp::DlpComponent::GOOGLE_DRIVE; + case data_controls::Component::kOneDrive: + return ::dlp::DlpComponent::MICROSOFT_ONEDRIVE; } } @@ -440,6 +457,8 @@ return ::dlp::DlpComponent::USB; case data_controls::Component::kDrive: return ::dlp::DlpComponent::GOOGLE_DRIVE; + case data_controls::Component::kOneDrive: + return ::dlp::DlpComponent::MICROSOFT_ONEDRIVE; } }
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_browsertest.cc b/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_browsertest.cc index 4dad80a8..05dd39b 100644 --- a/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_browsertest.cc +++ b/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_browsertest.cc
@@ -8,14 +8,22 @@ #include "base/functional/callback_forward.h" #include "base/memory/raw_ptr.h" #include "base/strings/string_piece_forward.h" +#include "base/test/mock_callback.h" +#include "chrome/browser/ash/file_manager/file_manager_test_util.h" +#include "chrome/browser/ash/file_system_provider/fake_extension_provider.h" +#include "chrome/browser/ash/file_system_provider/service.h" #include "chrome/browser/ash/policy/dlp/dlp_files_controller_ash.h" #include "chrome/browser/chromeos/policy/dlp/dlp_file_destination.h" +#include "chrome/browser/chromeos/policy/dlp/dlp_policy_event.pb.h" +#include "chrome/browser/chromeos/policy/dlp/dlp_reporting_manager.h" +#include "chrome/browser/chromeos/policy/dlp/dlp_reporting_manager_test_helper.h" #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h" #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h" #include "chrome/browser/chromeos/policy/dlp/mock_dlp_rules_manager.h" #include "chrome/browser/extensions/api/file_system/file_entry_picker.h" #include "chrome/browser/file_select_helper.h" #include "chrome/browser/ui/browser.h" +#include "chrome/common/extensions/extension_constants.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/file_select_listener.h" @@ -114,6 +122,72 @@ }; IN_PROC_BROWSER_TEST_F(DlpFilesControllerAshBrowserTest, + CheckIfDownloadAllowed_OneDrive) { + // Mount OneDrive file system. + auto fake_provider = ash::file_system_provider::FakeExtensionProvider::Create( + extension_misc::kODFSExtensionId); + const auto providerId = fake_provider->GetId(); + auto* service = ash::file_system_provider::Service::Get(browser()->profile()); + service->RegisterProvider(std::move(fake_provider)); + + const auto mount_options = ash::file_system_provider::MountOptions( + "test-filesystem", "OneDrive Test FileSystem"); + service->MountFileSystem(providerId, mount_options); + + const auto file_system_list = + service->GetProvidedFileSystemInfoList(providerId); + EXPECT_EQ(file_system_list.size(), 1UL); + + // Setup the reporting manager. + std::vector<DlpPolicyEvent> events; + auto reporting_manager = std::make_unique<DlpReportingManager>(); + SetReportQueueForReportingManager( + reporting_manager.get(), events, + base::SequencedTaskRunner::GetCurrentDefault()); + ON_CALL(*mock_rules_manager_, GetReportingManager) + .WillByDefault(::testing::Return(reporting_manager.get())); + + const std::string rule_name = "Rule name"; + const std::string rule_id = "Rule ID"; + + const DlpRulesManager::RuleMetadata ruleMetadata(rule_name, rule_id); + + EXPECT_CALL( + *mock_rules_manager_, + IsRestrictedComponent(_, data_controls::Component::kOneDrive, _, _, _)) + .WillOnce( + testing::DoAll(testing::SetArgPointee<3>(kExampleUrl), + testing::SetArgPointee<4>(ruleMetadata), + testing::Return(DlpRulesManager::Level::kBlock))); + + EXPECT_CALL(*mock_rules_manager_, GetReportingManager()) + .Times(::testing::AnyNumber()); + + testing::StrictMock< + base::MockCallback<DlpFilesControllerAsh::CheckIfDlpAllowedCallback>> + cb; + EXPECT_CALL(cb, Run(/*is_allowed=*/false)).Times(1); + + const std::string file_path = "Downloads/file.txt"; + + files_controller_->CheckIfDownloadAllowed( + DlpFileDestination(kExampleUrl), + base::FilePath(file_system_list[0].mount_path().Append(file_path)), + cb.Get()); + + ASSERT_EQ(events.size(), 1u); + + auto event_builder = DlpPolicyEventBuilder::Event( + kExampleUrl, rule_name, rule_id, DlpRulesManager::Restriction::kFiles, + DlpRulesManager::Level::kBlock); + + event_builder->SetDestinationComponent(data_controls::Component::kOneDrive); + event_builder->SetContentName(base::FilePath(file_path).BaseName().value()); + + EXPECT_THAT(events[0], IsDlpPolicyEvent(event_builder->Create())); +} + +IN_PROC_BROWSER_TEST_F(DlpFilesControllerAshBrowserTest, FilesUploadCallerPassed) { ui::FakeSelectFileDialog::Factory* select_file_dialog_factory = ui::FakeSelectFileDialog::RegisterFactory();
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_unittest.cc b/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_unittest.cc index 5d65125..00025ea8 100644 --- a/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_unittest.cc +++ b/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_unittest.cc
@@ -997,6 +997,8 @@ data_controls::Component::kUsb); components[DlpRulesManager::Level::kWarn].insert( data_controls::Component::kDrive); + components[DlpRulesManager::Level::kReport].insert( + data_controls::Component::kOneDrive); EXPECT_CALL(*rules_manager_, GetAggregatedDestinations) .WillOnce(testing::Return(destinations)); @@ -1006,7 +1008,7 @@ ASSERT_TRUE(files_controller_); auto result = files_controller_->GetDlpRestrictionDetails(kExampleUrl1); - ASSERT_EQ(result.size(), 3u); + ASSERT_EQ(result.size(), 4u); std::vector<std::string> expected_urls; std::vector<data_controls::Component> expected_components; // Block: @@ -1022,13 +1024,20 @@ EXPECT_EQ(result[1].level, DlpRulesManager::Level::kAllow); EXPECT_EQ(result[1].urls, expected_urls); EXPECT_EQ(result[1].components, expected_components); + // Report: + expected_urls.clear(); + expected_components.clear(); + expected_components.push_back(data_controls::Component::kOneDrive); + EXPECT_EQ(result[2].level, DlpRulesManager::Level::kReport); + EXPECT_EQ(result[2].urls, expected_urls); + EXPECT_EQ(result[2].components, expected_components); // Warn: expected_urls.clear(); expected_components.clear(); expected_components.push_back(data_controls::Component::kDrive); - EXPECT_EQ(result[2].level, DlpRulesManager::Level::kWarn); - EXPECT_EQ(result[2].urls, expected_urls); - EXPECT_EQ(result[2].components, expected_components); + EXPECT_EQ(result[3].level, DlpRulesManager::Level::kWarn); + EXPECT_EQ(result[3].urls, expected_urls); + EXPECT_EQ(result[3].components, expected_components); } TEST_F(DlpFilesControllerAshTest, GetDlpRestrictionDetails_Components) {
diff --git a/chrome/browser/ash/policy/enrollment/auto_enrollment_controller.cc b/chrome/browser/ash/policy/enrollment/auto_enrollment_controller.cc index f1511e5..21420134 100644 --- a/chrome/browser/ash/policy/enrollment/auto_enrollment_controller.cc +++ b/chrome/browser/ash/policy/enrollment/auto_enrollment_controller.cc
@@ -153,10 +153,13 @@ } enum class AutoEnrollmentControllerTimeoutReport { + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. kTimeoutCancelled = 0, - kTimeoutFRE, - kTimeout, - kMaxValue = kTimeout, + kTimeoutFRE = 1, + kTimeout = 2, + kTimeoutUnified = 3, + kMaxValue = kTimeoutUnified }; void ReportTimeoutUMA(AutoEnrollmentControllerTimeoutReport report) { @@ -644,7 +647,7 @@ // keeps the connection open. LOG(ERROR) << "EnrollmentStateFetcher didn't complete within time limit."; UpdateState(AutoEnrollmentState::kConnectionError); - // TODO(b/265923216): Report unified enrollment timeouts to UMA. + ReportTimeoutUMA(AutoEnrollmentControllerTimeoutReport::kTimeoutUnified); return; }
diff --git a/chrome/browser/ash/policy/enrollment/auto_enrollment_type_checker.cc b/chrome/browser/ash/policy/enrollment/auto_enrollment_type_checker.cc index 4256be01..a8112f5 100644 --- a/chrome/browser/ash/policy/enrollment/auto_enrollment_type_checker.cc +++ b/chrome/browser/ash/policy/enrollment/auto_enrollment_type_checker.cc
@@ -12,11 +12,13 @@ #include "base/functional/callback.h" #include "base/json/json_reader.h" #include "base/logging.h" +#include "base/metrics/histogram_functions.h" #include "build/branding_buildflags.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chromeos/ash/components/system/factory_ping_embargo_check.h" #include "chromeos/ash/components/system/statistics_provider.h" +#include "components/policy/core/common/cloud/enterprise_metrics.h" #include "net/base/load_flags.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/resource_request.h" @@ -60,7 +62,7 @@ } // Kill switch config request parameters. -const net::NetworkTrafficAnnotationTag kKSConfigTrafficAnnotation = +constexpr net::NetworkTrafficAnnotationTag kKSConfigTrafficAnnotation = net::DefineNetworkTrafficAnnotation( "unified_state_determination_kill_switch", R"( @@ -90,13 +92,17 @@ setting: "This feature cannot be controlled by Chrome settings." chrome_policy {} })"); -const char kKSConfigUrl[] = +constexpr char kKSConfigUrl[] = "https://www.gstatic.com/chromeos-usd-experiment/v1.json"; -const base::TimeDelta kKSConfigFetchTimeout = base::Seconds(1); -const int kKSConfigFetchRetries = 4; -const size_t kKSConfigMaxSize = 1024; // 1KB -const char kKSConfigFetchMethod[] = "GET"; -const char kKSConfigDisableUpToVersionKey[] = "disable_up_to_version"; +constexpr base::TimeDelta kKSConfigFetchTimeout = base::Seconds(1); +constexpr int kKSConfigFetchTries = 4; +constexpr size_t kKSConfigMaxSize = 1024; // 1KB +constexpr char kKSConfigFetchMethod[] = "GET"; +constexpr char kKSConfigDisableUpToVersionKey[] = "disable_up_to_version"; +constexpr int kUMAKSFetchNumTriesMinValue = 1; +constexpr int kUMAKSFetchNumTriesExclusiveMaxValue = 51; +constexpr int kUMAKSFetchNumTriesBuckets = + kUMAKSFetchNumTriesExclusiveMaxValue - kUMAKSFetchNumTriesMinValue; // This value represents current version of the code. After we have enabled kill // switch for a particular version, we can increment it after fixing the logic. @@ -108,6 +114,13 @@ // When set to true, unified state determination is disabled. absl::optional<bool> g_unified_state_determination_kill_switch; +void ReportKillSwitchFetchTries(int tries) { + base::UmaHistogramCustomCounts(kUMAStateDeterminationKillSwitchFetchNumTries, + tries, kUMAKSFetchNumTriesMinValue, + kUMAKSFetchNumTriesExclusiveMaxValue, + kUMAKSFetchNumTriesBuckets); +} + void ParseKSConfig(base::OnceClosure init_callback, const std::string& response) { absl::optional<base::Value> config = base::JSONReader::Read(response); @@ -134,10 +147,16 @@ void FetchKSConfig( scoped_refptr<network::SharedURLLoaderFactory> loader_factory, base::OnceClosure init_callback, - int retries_left, + int tries_left, std::unique_ptr<network::SimpleURLLoader> loader = nullptr, std::unique_ptr<std::string> response = nullptr) { - if (!response && retries_left) { + if (loader) { + base::UmaHistogramSparse( + kUMAStateDeterminationKillSwitchFetchNetworkErrorCode, + -loader->NetError()); + } + + if (!response && tries_left) { auto request = std::make_unique<network::ResourceRequest>(); request->url = GURL(kKSConfigUrl); request->method = kKSConfigFetchMethod; @@ -152,7 +171,7 @@ loader_ptr->DownloadToString( loader_factory.get(), base::BindOnce(FetchKSConfig, loader_factory, std::move(init_callback), - retries_left - 1, std::move(loader)), + tries_left - 1, std::move(loader)), kKSConfigMaxSize); return; } @@ -162,12 +181,14 @@ if (!response) { LOG(ERROR) << "Kill switch config request failed with code " << loader->NetError(); + ReportKillSwitchFetchTries(kKSConfigFetchTries); std::move(init_callback).Run(); return; } VLOG(1) << "Received kill switch config response after " - << (kKSConfigFetchRetries - retries_left) << " tries: " << *response; + << (kKSConfigFetchTries - tries_left) << " tries: " << *response; + ReportKillSwitchFetchTries(kKSConfigFetchTries - tries_left); ParseKSConfig(std::move(init_callback), *response); } @@ -184,8 +205,7 @@ void AutoEnrollmentTypeChecker::Initialize( scoped_refptr<network::SharedURLLoaderFactory> loader_factory, base::OnceClosure init_callback) { - FetchKSConfig(loader_factory, std::move(init_callback), - kKSConfigFetchRetries); + FetchKSConfig(loader_factory, std::move(init_callback), kKSConfigFetchTries); } // static
diff --git a/chrome/browser/ash/policy/enrollment/auto_enrollment_type_checker_unittest.cc b/chrome/browser/ash/policy/enrollment/auto_enrollment_type_checker_unittest.cc index a1a46139..6fc9233 100644 --- a/chrome/browser/ash/policy/enrollment/auto_enrollment_type_checker_unittest.cc +++ b/chrome/browser/ash/policy/enrollment/auto_enrollment_type_checker_unittest.cc
@@ -8,6 +8,7 @@ #include "ash/constants/ash_switches.h" #include "base/strings/stringprintf.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_command_line.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" @@ -18,6 +19,7 @@ #include "chromeos/ash/components/system/factory_ping_embargo_check.h" #include "chromeos/ash/components/system/fake_statistics_provider.h" #include "chromeos/ash/components/system/statistics_provider.h" +#include "components/policy/core/common/cloud/enterprise_metrics.h" #include "net/base/load_flags.h" #include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" @@ -447,6 +449,34 @@ EXPECT_FALSE(AutoEnrollmentTypeChecker::Initialized()); } +TEST_F(AutoEnrollmentTypeCheckerInitializationTest, UmaHistograms) { + base::HistogramTester histograms; + base::test::TestFuture<void> future; + network::URLLoaderCompletionStatus status; + + AutoEnrollmentTypeChecker::Initialize(test_shared_loader_factory_, + future.GetCallback()); + + status.error_code = net::ERR_NETWORK_CHANGED; + test_url_loader_factory_.SimulateResponseForPendingRequest( + GURL("https://www.gstatic.com/chromeos-usd-experiment/v1.json"), status, + network::mojom::URLResponseHead::New(), ""); + test_url_loader_factory_.AddResponse( + "https://www.gstatic.com/chromeos-usd-experiment/v1.json", + R"({"disable_up_to_version": 1})", net::HTTP_OK); + + ASSERT_TRUE(future.Wait()); + histograms.ExpectTotalCount( + kUMAStateDeterminationKillSwitchFetchNetworkErrorCode, 2); + histograms.ExpectBucketCount( + kUMAStateDeterminationKillSwitchFetchNetworkErrorCode, + -net::ERR_NETWORK_CHANGED, 1); + histograms.ExpectBucketCount( + kUMAStateDeterminationKillSwitchFetchNetworkErrorCode, -net::OK, 1); + histograms.ExpectUniqueSample(kUMAStateDeterminationKillSwitchFetchNumTries, + 2, 1); +} + TEST_F(AutoEnrollmentTypeCheckerInitializationTest, KilledBeforeInitStarted) { EXPECT_FALSE(AutoEnrollmentTypeChecker::Initialized()); EXPECT_TRUE(AutoEnrollmentTypeChecker:: @@ -524,7 +554,7 @@ base::test::TestFuture<void> future; test_url_loader_factory_.AddResponse( "https://www.gstatic.com/chromeos-usd-experiment/v1.json", - "{\"disable_up_to_version\": 1}", net::HTTP_OK); + R"({"disable_up_to_version": 1})", net::HTTP_OK); AutoEnrollmentTypeChecker::Initialize(test_shared_loader_factory_, future.GetCallback()); @@ -539,7 +569,7 @@ test_url_loader_factory_.AddResponse( "https://www.gstatic.com/chromeos-usd-experiment/v1.json", // TODO(b/265923216): Change to 0 when kCodeVersion is 1. - "{\"disable_up_to_version\": -1}", net::HTTP_OK); + R"({"disable_up_to_version": -1})", net::HTTP_OK); AutoEnrollmentTypeChecker::Initialize(test_shared_loader_factory_, future.GetCallback());
diff --git a/chrome/browser/ash/policy/enrollment/enrollment_state_fetcher.cc b/chrome/browser/ash/policy/enrollment/enrollment_state_fetcher.cc index 8940b67..02b5a0a 100644 --- a/chrome/browser/ash/policy/enrollment/enrollment_state_fetcher.cc +++ b/chrome/browser/ash/policy/enrollment/enrollment_state_fetcher.cc
@@ -14,6 +14,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/metrics/histogram_functions.h" +#include "base/notreached.h" #include "base/strings/strcat.h" #include "base/time/time.h" #include "base/types/expected.h" @@ -33,6 +34,7 @@ #include "chromeos/ash/components/dbus/system_clock/system_clock_sync_observation.h" #include "chromeos/ash/components/system/factory_ping_embargo_check.h" #include "chromeos/ash/components/system/statistics_provider.h" +#include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/dmserver_job_configurations.h" #include "components/policy/core/common/cloud/enterprise_metrics.h" #include "components/policy/proto/device_management_backend.pb.h" @@ -47,9 +49,6 @@ namespace em = enterprise_management; -// TODO(b/265923216): Review UMA stats in this file and compare them to stats -// reported by auto_enrollment_client_impl.cc. Add missing, remove unnecessary. - // TODO(b/265923216): Wrap callbacks into an object ensuring they are called. RlwePlaintextId ConstructPlainttextId(const std::string& rlz_brand_code, @@ -110,9 +109,6 @@ // membership for. Must be set before RlweOprf and RlweQuery steps. std::unique_ptr<private_membership::rlwe::PrivateMembershipRlweClient> psm_rlwe_client; - - // Time at which OPRF request was sent. Used to compute PSM protocol time. - base::TimeTicks oprf_request_time_; }; void StorePsmError(PrefService* local_state) { @@ -215,8 +211,42 @@ .value_or("")); out_serial_number = std::string(statistics_provider->GetMachineID().value_or("")); + ReportDeviceIdentifierStatus(out_serial_number.empty(), + out_rlz_brand_code.empty()); return !out_serial_number.empty() && !out_rlz_brand_code.empty(); } + + private: + static void ReportDeviceIdentifierStatus(bool serial_number_missing, + bool rlz_brand_code_missing) { + enum class DeviceIdentifierStatus { + // These values are persisted to logs. Entries should not be renumbered + // and numeric values should never be reused. + kAllPresent = 0, + kSerialNumberMissing = 1, + kRlzBrandCodeMissing = 2, + kAllMissing = 3, + kMaxValue = kAllMissing + }; + + if (serial_number_missing && rlz_brand_code_missing) { + base::UmaHistogramEnumeration( + kUMAStateDeterminationDeviceIdentifierStatus, + DeviceIdentifierStatus::kAllMissing); + } else if (serial_number_missing) { + base::UmaHistogramEnumeration( + kUMAStateDeterminationDeviceIdentifierStatus, + DeviceIdentifierStatus::kSerialNumberMissing); + } else if (rlz_brand_code_missing) { + base::UmaHistogramEnumeration( + kUMAStateDeterminationDeviceIdentifierStatus, + DeviceIdentifierStatus::kRlzBrandCodeMissing); + } else { + base::UmaHistogramEnumeration( + kUMAStateDeterminationDeviceIdentifierStatus, + DeviceIdentifierStatus::kAllPresent); + } + } }; // Class to obtain state keys. @@ -303,7 +333,6 @@ ->mutable_oprf_request() = *oprf_request; VLOG(1) << "Send PSM RLWE OPRF request"; - context.oprf_request_time_ = base::TimeTicks::Now(); job_ = context.device_management_service->CreateJob(std::move(config)); } @@ -311,6 +340,12 @@ void OnRequestDone(CompletionCallback completion_callback, DMServerJobResult result) { // Handle errors + base::UmaHistogramEnumeration( + kUMAStateDeterminationPsmRlweOprfRequestDmStatusCode, result.dm_status, + static_cast<policy::DeviceManagementStatus>(DM_STATUS_SERVICE_MAX + 1)); + base::UmaHistogramSparse( + kUMAStateDeterminationPsmRlweOprfRequestNetworkErrorCode, + -result.net_error); switch (result.dm_status) { case DM_STATUS_SUCCESS: { if (!result.response.has_private_set_membership_response() || @@ -389,8 +424,7 @@ /*oauth_token=*/absl::nullopt, context.url_loader_factory, base::BindOnce(&RlweQuery::OnRequestDone, weak_factory_.GetWeakPtr(), base::Unretained(context.psm_rlwe_client.get()), - std::move(completion_callback), - context.oprf_request_time_)); + std::move(completion_callback))); *config->request() ->mutable_private_set_membership_request() @@ -404,9 +438,14 @@ void OnRequestDone( private_membership::rlwe::PrivateMembershipRlweClient* psm_rlwe_client, CompletionCallback completion_callback, - base::TimeTicks oprf_request_time, DMServerJobResult result) { // Handle errors + base::UmaHistogramEnumeration( + kUMAStateDeterminationPsmRlweQueryRequestDmStatusCode, result.dm_status, + static_cast<policy::DeviceManagementStatus>(DM_STATUS_SERVICE_MAX + 1)); + base::UmaHistogramSparse( + kUMAStateDeterminationPsmRlweQueryRequestNetworkErrorCode, + -result.net_error); switch (result.dm_status) { case DM_STATUS_SUCCESS: { // Check if the RLWE query response is empty. @@ -500,7 +539,7 @@ /*oauth_token=*/absl::nullopt, context.url_loader_factory, base::BindOnce(&EnrollmentState::OnRequestDone, weak_factory_.GetWeakPtr(), - std::move(completion_callback), base::TimeTicks::Now())); + std::move(completion_callback))); auto* request = config->request()->mutable_device_state_retrieval_request(); if (context.state_key.has_value()) { @@ -514,9 +553,13 @@ } void OnRequestDone(CompletionCallback completion_callback, - base::TimeTicks start_time, DMServerJobResult result) { // Handle errors + base::UmaHistogramEnumeration( + kUMAStateDeterminationStateRequestDmStatusCode, result.dm_status, + static_cast<policy::DeviceManagementStatus>(DM_STATUS_SERVICE_MAX + 1)); + base::UmaHistogramSparse(kUMAStateDeterminationStateRequestNetworkErrorCode, + -result.net_error); switch (result.dm_status) { case DM_STATUS_SUCCESS: { if (!result.response.has_device_state_retrieval_response()) { @@ -793,15 +836,21 @@ context_(std::move(context)) {} void Start() { - if (!AutoEnrollmentTypeChecker::IsUnifiedStateDeterminationEnabled()) { + fetch_started_ = base::TimeTicks::Now(); + const bool enabled = + AutoEnrollmentTypeChecker::IsUnifiedStateDeterminationEnabled(); + base::UmaHistogramBoolean(kUMAStateDeterminationEnabled, enabled); + if (!enabled) { VLOG(1) << "Unified state determination is disabled"; - return std::move(report_result_).Run(AutoEnrollmentState::kNoEnrollment); + return ReportResult(AutoEnrollmentState::kNoEnrollment); } // Flex devices do not support FRE, hence there is no need to perform state // determination. Users are still able to manually enroll devices though. - if (ash::switches::IsRevenBranding()) { - return std::move(report_result_).Run(AutoEnrollmentState::kNoEnrollment); + const bool is_on_flex = ash::switches::IsRevenBranding(); + base::UmaHistogramBoolean(kUMAStateDeterminationOnFlex, is_on_flex); + if (is_on_flex) { + return ReportResult(AutoEnrollmentState::kNoEnrollment); } // TODO(b/265923216): Investigate the possibility of using bypassing PSM and // using state key to directly request state when identifiers are missing. @@ -809,24 +858,75 @@ context_.rlz_brand_code, context_.serial_number)) { // Skip enrollment if serial number or brand code are missing. - return std::move(report_result_).Run(AutoEnrollmentState::kNoEnrollment); + return ReportResult(AutoEnrollmentState::kNoEnrollment); } + step_started_ = base::TimeTicks::Now(); system_clock_.Sync(context_.system_clock_client, base::BindOnce(&Sequence::OnSystemClockSynced, weak_factory_.GetWeakPtr())); } private: - void OnSystemClockSynced(bool synchronized) { - if (!synchronized) { - LOG(ERROR) << "System clock failed to synchronize"; - return std::move(report_result_) - .Run(AutoEnrollmentState::kConnectionError); + void ReportTotalDuration(base::TimeDelta fetch_duration, + AutoEnrollmentState state) { + std::string uma_suffix; + switch (state) { + case AutoEnrollmentState::kIdle: + case AutoEnrollmentState::kPending: + NOTREACHED(); + break; + case AutoEnrollmentState::kConnectionError: + uma_suffix = kUMASuffixConnectionError; + break; + case AutoEnrollmentState::kDisabled: + uma_suffix = kUMASuffixDisabled; + break; + case AutoEnrollmentState::kEnrollment: + uma_suffix = kUMASuffixEnrollment; + break; + case AutoEnrollmentState::kNoEnrollment: + uma_suffix = kUMASuffixNoEnrollment; + break; + case AutoEnrollmentState::kServerError: + uma_suffix = kUMASuffixServerError; + break; } - if (!embargo_date_.Passed(context_)) { - return std::move(report_result_).Run(AutoEnrollmentState::kNoEnrollment); + base::UmaHistogramMediumTimes(kUMAStateDeterminationTotalDuration, + fetch_duration); + base::UmaHistogramMediumTimes( + base::StrCat({kUMAStateDeterminationTotalDurationByState, uma_suffix}), + fetch_duration); + } + + void ReportStepDurationAndResetTimer(base::StringPiece uma_step_suffix) { + base::UmaHistogramTimes( + base::StrCat({kUMAStateDeterminationStepDuration, uma_step_suffix}), + base::TimeTicks::Now() - step_started_); + step_started_ = base::TimeTicks::Now(); + } + + void ReportResult(AutoEnrollmentState state) { + DCHECK(state != AutoEnrollmentState::kIdle); + DCHECK(state != AutoEnrollmentState::kPending); + ReportTotalDuration(base::TimeTicks::Now() - fetch_started_, state); + std::move(report_result_).Run(state); + } + + void OnSystemClockSynced(bool synchronized) { + ReportStepDurationAndResetTimer(kUMASuffixSystemClockSync); + base::UmaHistogramBoolean(kUMAStateDeterminationSystemClockSynchronized, + synchronized); + if (!synchronized) { + LOG(ERROR) << "System clock failed to synchronize"; + return ReportResult(AutoEnrollmentState::kConnectionError); + } + + const bool passed = embargo_date_.Passed(context_); + base::UmaHistogramBoolean(kUMAStateDeterminationEmbargoDatePassed, passed); + if (!passed) { + return ReportResult(AutoEnrollmentState::kNoEnrollment); } ownership_.Check(context_.device_settings_service, @@ -835,14 +935,19 @@ } void OnOwnershipChecked(ash::DeviceSettingsService::OwnershipStatus status) { + ReportStepDurationAndResetTimer(kUMASuffixOwnershipCheck); + base::UmaHistogramEnumeration( + kUMAStateDeterminationOwnershipStatus, status, + static_cast<ash::DeviceSettingsService::OwnershipStatus>( + ash::DeviceSettingsService::OwnershipStatus::OWNERSHIP_MAX + 1)); if (status == ash::DeviceSettingsService::OWNERSHIP_UNKNOWN) { LOG(ERROR) << "Device ownership is unknown. Skipping enrollment"; - return std::move(report_result_).Run(AutoEnrollmentState::kNoEnrollment); + return ReportResult(AutoEnrollmentState::kNoEnrollment); } if (status == ash::DeviceSettingsService::OWNERSHIP_TAKEN) { VLOG(1) << "Device ownership is already taken. Skipping enrollment"; - return std::move(report_result_).Run(AutoEnrollmentState::kNoEnrollment); + return ReportResult(AutoEnrollmentState::kNoEnrollment); } state_keys_.Retrieve(context_.state_key_broker, @@ -851,6 +956,9 @@ } void OnStateKeysRetrieved(absl::optional<std::string> state_key) { + ReportStepDurationAndResetTimer(kUMASuffixStateKeyRetrieval); + base::UmaHistogramBoolean(kUMAStateDeterminationStateKeysRetrieved, + state_key.has_value()); LOG_IF(WARNING, !state_key) << "Failed to obtain state keys"; context_.state_key = state_key; context_.psm_rlwe_client = context_.rlwe_client_factory.Run( @@ -860,9 +968,10 @@ } void OnOprfRequestDone(RlweOprf::Result result) { + ReportStepDurationAndResetTimer(kUMASuffixOPRFRequest); if (!result.has_value()) { StorePsmError(local_state_); - return std::move(report_result_).Run(result.error()); + return ReportResult(result.error()); } query_.Request(context_, result.value(), base::BindOnce(&Sequence::OnQueryRequestDone, @@ -870,9 +979,10 @@ } void OnQueryRequestDone(RlweQuery::Result result) { + ReportStepDurationAndResetTimer(kUMASuffixQueryRequest); if (!result.has_value()) { StorePsmError(local_state_); - return std::move(report_result_).Run(result.error()); + return ReportResult(result.error()); } RlwePlaintextId psm_id = @@ -882,8 +992,10 @@ << psm_id.sensitive_id() << " is " << (result.value() ? "" : " not") << " present on the server"; + base::UmaHistogramBoolean(kUMAStateDeterminationPsmReportedAvailableState, + result.value()); if (!result.value()) { - return std::move(report_result_).Run(AutoEnrollmentState::kNoEnrollment); + return ReportResult(AutoEnrollmentState::kNoEnrollment); } query_.StoreResponse(local_state_, result.value()); state_.Request(context_, base::BindOnce(&Sequence::OnStateRequestDone, @@ -891,17 +1003,24 @@ } void OnStateRequestDone(EnrollmentState::Result result) { + ReportStepDurationAndResetTimer(kUMASuffixStateRequest); + base::UmaHistogramBoolean(kUMAStateDeterminationStateReturned, + result.has_value()); if (!result.has_value()) { - return std::move(report_result_).Run(result.error()); + return ReportResult(result.error()); } state_.StoreResponse(local_state_, result->dict); - return std::move(report_result_).Run(result->state); + return ReportResult(result->state); } // Used to report an error or the determined enrollment state. In production // code, this will point to `AutoEnrollmentController::UpdateState`. base::OnceCallback<void(AutoEnrollmentState)> report_result_; + // Time at which overall fetch or individual step has been started. + base::TimeTicks fetch_started_; + base::TimeTicks step_started_; + // Used to store the initial enrollment state (if available) in a dict at // `prefs::kServerBackedDeviceState`. // Must not be nullptr for initial enrollment state determination.
diff --git a/chrome/browser/ash/policy/enrollment/enrollment_state_fetcher_unittest.cc b/chrome/browser/ash/policy/enrollment/enrollment_state_fetcher_unittest.cc index 1b1755e..96604d9 100644 --- a/chrome/browser/ash/policy/enrollment/enrollment_state_fetcher_unittest.cc +++ b/chrome/browser/ash/policy/enrollment/enrollment_state_fetcher_unittest.cc
@@ -8,8 +8,10 @@ #include "ash/constants/ash_switches.h" #include "base/functional/bind.h" +#include "base/strings/strcat.h" #include "base/strings/stringprintf.h" #include "base/test/gmock_callback_support.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_command_line.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" @@ -26,7 +28,9 @@ #include "chromeos/ash/components/install_attributes/stub_install_attributes.h" #include "chromeos/ash/components/system/fake_statistics_provider.h" #include "chromeos/ash/components/system/statistics_provider.h" +#include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/device_management_service.h" +#include "components/policy/core/common/cloud/enterprise_metrics.h" #include "components/policy/core/common/cloud/mock_device_management_service.h" #include "components/policy/proto/device_management_backend.pb.h" #include "components/prefs/pref_registry_simple.h" @@ -50,6 +54,10 @@ const char kTestPsmId[] = "474F4F47/test-serial-number"; const char kTestDisabledMessage[] = "test-disabled-message"; +using base::test::RunOnceCallback; +using testing::DoAll; +using testing::InvokeWithoutArgs; + class MockStateKeyBroker : public ServerBackedStateKeysBroker { public: MockStateKeyBroker() : ServerBackedStateKeysBroker(nullptr) {} @@ -125,10 +133,11 @@ state_request.brand_code() == brand_code; } +MATCHER(WithAnyOprfRequest, "") { + return arg.has_oprf_request(); +} + MATCHER_P(WithOprfRequestFor, test_case, "") { - if (!test_case) { - return arg.has_oprf_request(); - } return arg.oprf_request().SerializeAsString() == test_case->expected_oprf_request().SerializeAsString(); } @@ -142,6 +151,9 @@ class EnrollmentStateFetcherTest : public testing::Test { public: + EnrollmentStateFetcherTest() + : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} + void SetUp() override { psm_test_case_ = psm::testing::LoadTestCase(/*is_member=*/true); fake_dm_service_ = @@ -176,27 +188,31 @@ } protected: - void ExpectOwnershipCheck() { + void ExpectOwnershipCheck(base::TimeDelta time = base::TimeDelta()) { EXPECT_CALL(device_settings_service_, GetOwnershipStatusAsync) - .WillOnce(base::test::RunOnceCallback<0>( - ash::DeviceSettingsService::OWNERSHIP_NONE)); + .WillOnce(DoAll( + InvokeWithoutArgs([=]() { task_environment_.AdvanceClock(time); }), + RunOnceCallback<0>(ash::DeviceSettingsService::OWNERSHIP_NONE))); } - void ExpectStateKeysRequest() { + void ExpectStateKeysRequest(base::TimeDelta time = base::TimeDelta()) { EXPECT_CALL(state_key_broker_, RequestStateKeys) - .WillOnce(base::test::RunOnceCallback<0>( - std::vector<std::string>{kTestStateKey})); + .WillOnce(DoAll( + InvokeWithoutArgs([=]() { task_environment_.AdvanceClock(time); }), + RunOnceCallback<0>(std::vector<std::string>{kTestStateKey}))); } - void ExpectOprfRequest(bool any = false) { + void ExpectOprfRequest(base::TimeDelta time = base::TimeDelta()) { EXPECT_CALL(job_creation_handler_, - OnJobCreation(JobWithPsmRlweRequest( - WithOprfRequestFor((any ? nullptr : &psm_test_case_))))) - .WillOnce(fake_dm_service_->SendJobOKAsync( - CreatePsmOprfResponse(psm_test_case_))); + OnJobCreation( + JobWithPsmRlweRequest(WithOprfRequestFor(&psm_test_case_)))) + .WillOnce(DoAll( + InvokeWithoutArgs([=]() { task_environment_.AdvanceClock(time); }), + fake_dm_service_->SendJobOKAsync( + CreatePsmOprfResponse(psm_test_case_)))); } - void ExpectQueryRequest() { + void ExpectQueryRequest(base::TimeDelta time = base::TimeDelta()) { em::DeviceManagementResponse response; auto* rlwe_response = response.mutable_private_set_membership_response() ->mutable_rlwe_response(); @@ -204,7 +220,20 @@ EXPECT_CALL(job_creation_handler_, OnJobCreation(JobWithPsmRlweRequest( WithQueryRequestFor(&psm_test_case_)))) - .WillOnce(fake_dm_service_->SendJobOKAsync(response)); + .WillOnce(DoAll( + InvokeWithoutArgs([=]() { task_environment_.AdvanceClock(time); }), + fake_dm_service_->SendJobOKAsync(response))); + } + + void ExpectStateRequest(base::TimeDelta time = base::TimeDelta()) { + em::DeviceManagementResponse response; + response.mutable_device_state_retrieval_response(); + EXPECT_CALL(job_creation_handler_, + OnJobCreation(JobWithStateRequest( + kTestStateKey, kTestSerialNumber, kTestBrandCode))) + .WillOnce(DoAll( + InvokeWithoutArgs([=]() { task_environment_.AdvanceClock(time); }), + fake_dm_service_->SendJobOKAsync(response))); } content::BrowserTaskEnvironment task_environment_; @@ -255,6 +284,17 @@ EXPECT_EQ(state, AutoEnrollmentState::kNoEnrollment); } +TEST_F(EnrollmentStateFetcherTest, DisabledOnFlex) { + base::HistogramTester histograms; + command_line_.GetProcessCommandLine()->AppendSwitch( + ash::switches::kRevenBranding); + + AutoEnrollmentState state = FetchEnrollmentState(); + + EXPECT_EQ(state, AutoEnrollmentState::kNoEnrollment); + histograms.ExpectUniqueSample(kUMAStateDeterminationOnFlex, true, 1); +} + TEST_F(EnrollmentStateFetcherTest, SystemClockNotSyncronized) { system_clock_.DisableService(); @@ -278,26 +318,45 @@ } TEST_F(EnrollmentStateFetcherTest, RlzBrandCodeMissing) { + base::HistogramTester histograms; statistics_provider_.ClearMachineStatistic(ash::system::kRlzBrandCodeKey); AutoEnrollmentState state = FetchEnrollmentState(); EXPECT_EQ(state, AutoEnrollmentState::kNoEnrollment); + histograms.ExpectUniqueSample(kUMAStateDeterminationDeviceIdentifierStatus, + 2 /*kRlzBrandCodeMissing*/, 1); } TEST_F(EnrollmentStateFetcherTest, SerialNumberMissing) { + base::HistogramTester histograms; statistics_provider_.ClearMachineStatistic( ash::system::kSerialNumberKeyForTest); AutoEnrollmentState state = FetchEnrollmentState(); EXPECT_EQ(state, AutoEnrollmentState::kNoEnrollment); + histograms.ExpectUniqueSample(kUMAStateDeterminationDeviceIdentifierStatus, + 1 /*kRlzBrandCodeMissing*/, 1); +} + +TEST_F(EnrollmentStateFetcherTest, RlzBrandCodeAndSerialNumberMissing) { + base::HistogramTester histograms; + statistics_provider_.ClearMachineStatistic(ash::system::kRlzBrandCodeKey); + statistics_provider_.ClearMachineStatistic( + ash::system::kSerialNumberKeyForTest); + + AutoEnrollmentState state = FetchEnrollmentState(); + + EXPECT_EQ(state, AutoEnrollmentState::kNoEnrollment); + histograms.ExpectUniqueSample(kUMAStateDeterminationDeviceIdentifierStatus, + 3 /*kAllMissing*/, 1); } TEST_F(EnrollmentStateFetcherTest, OwnershipTaken) { EXPECT_CALL(device_settings_service_, GetOwnershipStatusAsync) - .WillOnce(base::test::RunOnceCallback<0>( - ash::DeviceSettingsService::OWNERSHIP_TAKEN)); + .WillOnce( + RunOnceCallback<0>(ash::DeviceSettingsService::OWNERSHIP_TAKEN)); AutoEnrollmentState state = FetchEnrollmentState(); @@ -306,8 +365,8 @@ TEST_F(EnrollmentStateFetcherTest, OwnershipUnknown) { EXPECT_CALL(device_settings_service_, GetOwnershipStatusAsync) - .WillOnce(base::test::RunOnceCallback<0>( - ash::DeviceSettingsService::OWNERSHIP_UNKNOWN)); + .WillOnce( + RunOnceCallback<0>(ash::DeviceSettingsService::OWNERSHIP_UNKNOWN)); AutoEnrollmentState state = FetchEnrollmentState(); @@ -317,8 +376,7 @@ TEST_F(EnrollmentStateFetcherTest, ProceedWithMissingStateKeys) { ExpectOwnershipCheck(); EXPECT_CALL(state_key_broker_, RequestStateKeys) - .WillRepeatedly( - base::test::RunOnceCallback<0>(std::vector<std::string>{})); + .WillRepeatedly(RunOnceCallback<0>(std::vector<std::string>{})); ExpectOprfRequest(); ExpectQueryRequest(); EXPECT_CALL(job_creation_handler_, OnJobCreation(JobWithStateRequest( @@ -373,7 +431,10 @@ TEST_F(EnrollmentStateFetcherTest, FailToCreateQueryRequest) { ExpectOwnershipCheck(); ExpectStateKeysRequest(); - ExpectOprfRequest(/*any=*/true); + EXPECT_CALL(job_creation_handler_, + OnJobCreation(JobWithPsmRlweRequest(WithAnyOprfRequest()))) + .WillOnce(fake_dm_service_->SendJobOKAsync( + CreatePsmOprfResponse(psm_test_case_))); base::test::TestFuture<AutoEnrollmentState> future; auto fetcher = EnrollmentStateFetcher::Create( future.GetCallback(), &local_state_, @@ -438,6 +499,21 @@ EXPECT_EQ(state, AutoEnrollmentState::kServerError); } +TEST_F(EnrollmentStateFetcherTest, PsmReportsNoState) { + base::HistogramTester histograms; + psm_test_case_ = psm::testing::LoadTestCase(/*is_member=*/false); + ExpectOwnershipCheck(); + ExpectStateKeysRequest(); + ExpectOprfRequest(); + ExpectQueryRequest(); + + AutoEnrollmentState state = FetchEnrollmentState(); + + EXPECT_EQ(state, AutoEnrollmentState::kNoEnrollment); + histograms.ExpectUniqueSample(kUMAStateDeterminationPsmReportedAvailableState, + false, 1); +} + TEST_F(EnrollmentStateFetcherTest, EmptyEnrollmentStateResponse) { ExpectOwnershipCheck(); ExpectStateKeysRequest(); @@ -505,6 +581,81 @@ EXPECT_TRUE(device_state.empty()); } +TEST_F(EnrollmentStateFetcherTest, UmaHistogramsCounts) { + base::HistogramTester histograms; + ExpectOwnershipCheck(); + ExpectStateKeysRequest(); + ExpectOprfRequest(); + ExpectQueryRequest(); + ExpectStateRequest(); + + FetchEnrollmentState(); + + histograms.ExpectUniqueSample(kUMAStateDeterminationDeviceIdentifierStatus, + 0 /*kAllPresent*/, 1); + histograms.ExpectUniqueSample(kUMAStateDeterminationEmbargoDatePassed, true, + 1); + histograms.ExpectUniqueSample(kUMAStateDeterminationEnabled, true, 1); + histograms.ExpectUniqueSample(kUMAStateDeterminationOnFlex, false, 1); + histograms.ExpectUniqueSample(kUMAStateDeterminationSystemClockSynchronized, + true, 1); + histograms.ExpectUniqueSample(kUMAStateDeterminationOwnershipStatus, + ash::DeviceSettingsService::OWNERSHIP_NONE, 1); + histograms.ExpectUniqueSample(kUMAStateDeterminationStateKeysRetrieved, true, + 1); + histograms.ExpectUniqueSample( + kUMAStateDeterminationPsmRlweOprfRequestDmStatusCode, DM_STATUS_SUCCESS, + 1); + histograms.ExpectUniqueSample( + kUMAStateDeterminationPsmRlweOprfRequestNetworkErrorCode, net::OK, 1); + histograms.ExpectUniqueSample( + kUMAStateDeterminationPsmRlweQueryRequestDmStatusCode, DM_STATUS_SUCCESS, + 1); + histograms.ExpectUniqueSample( + kUMAStateDeterminationPsmRlweQueryRequestNetworkErrorCode, net::OK, 1); + histograms.ExpectUniqueSample(kUMAStateDeterminationPsmReportedAvailableState, + true, 1); + histograms.ExpectUniqueSample(kUMAStateDeterminationStateRequestDmStatusCode, + DM_STATUS_SUCCESS, 1); + histograms.ExpectUniqueSample( + kUMAStateDeterminationStateRequestNetworkErrorCode, net::OK, 1); + histograms.ExpectUniqueSample(kUMAStateDeterminationStateReturned, true, 1); +} + +TEST_F(EnrollmentStateFetcherTest, UmaHistogramsTimes) { + base::HistogramTester histograms; + ExpectOwnershipCheck(/*time=*/base::Seconds(1)); + ExpectStateKeysRequest(/*time=*/base::Seconds(2)); + ExpectOprfRequest(/*time=*/base::Seconds(3)); + ExpectQueryRequest(/*time=*/base::Seconds(4)); + ExpectStateRequest(/*time=*/base::Seconds(5)); + + FetchEnrollmentState(); + + const char* ds = kUMAStateDeterminationTotalDurationByState; + histograms.ExpectUniqueTimeSample(base::StrCat({ds, kUMASuffixNoEnrollment}), + base::Seconds(15), 1); + histograms.ExpectTotalCount(base::StrCat({ds, kUMASuffixConnectionError}), 0); + histograms.ExpectTotalCount(base::StrCat({ds, kUMASuffixDisabled}), 0); + histograms.ExpectTotalCount(base::StrCat({ds, kUMASuffixEnrollment}), 0); + histograms.ExpectTotalCount(base::StrCat({ds, kUMASuffixServerError}), 0); + histograms.ExpectTotalCount(kUMAStateDeterminationTotalDuration, 1); + + const char* step_d = kUMAStateDeterminationStepDuration; + histograms.ExpectUniqueTimeSample( + base::StrCat({step_d, kUMASuffixSystemClockSync}), base::Seconds(0), 1); + histograms.ExpectUniqueTimeSample( + base::StrCat({step_d, kUMASuffixOwnershipCheck}), base::Seconds(1), 1); + histograms.ExpectUniqueTimeSample( + base::StrCat({step_d, kUMASuffixStateKeyRetrieval}), base::Seconds(2), 1); + histograms.ExpectUniqueTimeSample( + base::StrCat({step_d, kUMASuffixOPRFRequest}), base::Seconds(3), 1); + histograms.ExpectUniqueTimeSample( + base::StrCat({step_d, kUMASuffixQueryRequest}), base::Seconds(4), 1); + histograms.ExpectUniqueTimeSample( + base::StrCat({step_d, kUMASuffixStateRequest}), base::Seconds(5), 1); +} + TEST_F(EnrollmentStateFetcherTest, PackagedLicenseWithoutEnrollment) { ExpectOwnershipCheck(); ExpectStateKeysRequest();
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_reboot_job_browsertest.cc b/chrome/browser/ash/policy/remote_commands/device_command_reboot_job_browsertest.cc index 4fff30a3..63e2bdb3 100644 --- a/chrome/browser/ash/policy/remote_commands/device_command_reboot_job_browsertest.cc +++ b/chrome/browser/ash/policy/remote_commands/device_command_reboot_job_browsertest.cc
@@ -6,6 +6,8 @@ #include "base/time/time.h" #include "chrome/browser/ash/login/app_mode/test/kiosk_apps_mixin.h" +#include "chrome/browser/ash/login/app_mode/test/kiosk_base_test.h" +#include "chrome/browser/ash/login/app_mode/test/web_kiosk_base_test.h" #include "chrome/browser/ash/login/login_manager_test.h" #include "chrome/browser/ash/login/test/device_state_mixin.h" #include "chrome/browser/ash/login/test/login_manager_mixin.h" @@ -50,7 +52,7 @@ }; } // namespace -class DeviceCommandRebootJobKioskBrowserTest +class DeviceCommandRebootJobAutoLaunchKioskBrowserTest : public DeviceCommandRebootBaseTest<ash::LoginManagerTest> { protected: void SetUpInProcessBrowserTestFixture() override { @@ -68,23 +70,66 @@ ash::DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED}; }; -IN_PROC_BROWSER_TEST_F(DeviceCommandRebootJobKioskBrowserTest, - RebootsKioskInstantly) { +IN_PROC_BROWSER_TEST_F(DeviceCommandRebootJobAutoLaunchKioskBrowserTest, + RebootsInstantly) { ASSERT_TRUE(ash::LoginState::Get()->IsKioskSession()); ASSERT_EQ( chromeos::FakePowerManagerClient::Get()->num_request_restart_calls(), 0); - em::RemoteCommandResult result = - SendRemoteCommand(RemoteCommandBuilder() - .SetType(em::RemoteCommand_Type_DEVICE_REBOOT) - .Build()); + em::RemoteCommandResult result = SendRemoteCommand( + RemoteCommandBuilder().SetType(em::RemoteCommand::DEVICE_REBOOT).Build()); - EXPECT_EQ(result.result(), em::RemoteCommandResult_ResultType_RESULT_SUCCESS); + EXPECT_EQ(result.result(), em::RemoteCommandResult::RESULT_SUCCESS); EXPECT_EQ( chromeos::FakePowerManagerClient::Get()->num_request_restart_calls(), 1); } -// TODO(b/225913691) Add test case for manually launched kiosk. +class DeviceCommandRebootJobKioskBrowserTest + : public DeviceCommandRebootBaseTest<ash::KioskBaseTest> { + private: + ash::DeviceStateMixin device_state_{ + &mixin_host_, + ash::DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED}; +}; + +IN_PROC_BROWSER_TEST_F(DeviceCommandRebootJobKioskBrowserTest, + RebootsInstantly) { + StartAppLaunchFromLoginScreen( + ash::NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE); + WaitForAppLaunchWithOptions(false /* check launch data */, + false /* terminate app */, + true /* keep app open */); + + ASSERT_TRUE(ash::LoginState::Get()->IsKioskSession()); + ASSERT_EQ( + chromeos::FakePowerManagerClient::Get()->num_request_restart_calls(), 0); + + em::RemoteCommandResult result = SendRemoteCommand( + RemoteCommandBuilder().SetType(em::RemoteCommand::DEVICE_REBOOT).Build()); + + EXPECT_EQ(result.result(), em::RemoteCommandResult::RESULT_SUCCESS); + EXPECT_EQ( + chromeos::FakePowerManagerClient::Get()->num_request_restart_calls(), 1); +} + +class DeviceCommandRebootJobWebKioskBrowserTest + : public DeviceCommandRebootBaseTest<ash::WebKioskBaseTest> {}; + +IN_PROC_BROWSER_TEST_F(DeviceCommandRebootJobWebKioskBrowserTest, + RebootsInstantly) { + InitializeRegularOnlineKiosk(); + + ASSERT_TRUE(ash::LoginState::Get()->IsKioskSession()); + ASSERT_EQ( + chromeos::FakePowerManagerClient::Get()->num_request_restart_calls(), 0); + + em::RemoteCommandResult result = SendRemoteCommand( + RemoteCommandBuilder().SetType(em::RemoteCommand::DEVICE_REBOOT).Build()); + + EXPECT_EQ(result.result(), em::RemoteCommandResult::RESULT_SUCCESS); + EXPECT_EQ( + chromeos::FakePowerManagerClient::Get()->num_request_restart_calls(), 1); +} class DeviceCommandRebootJobUserBrowserTest : public DeviceCommandRebootBaseTest<MixinBasedInProcessBrowserTest> { @@ -104,12 +149,10 @@ ASSERT_EQ( chromeos::FakePowerManagerClient::Get()->num_request_restart_calls(), 0); - em::RemoteCommandResult result = - SendRemoteCommand(RemoteCommandBuilder() - .SetType(em::RemoteCommand_Type_DEVICE_REBOOT) - .Build()); + em::RemoteCommandResult result = SendRemoteCommand( + RemoteCommandBuilder().SetType(em::RemoteCommand::DEVICE_REBOOT).Build()); - EXPECT_EQ(result.result(), em::RemoteCommandResult_ResultType_RESULT_SUCCESS); + EXPECT_EQ(result.result(), em::RemoteCommandResult::RESULT_SUCCESS); EXPECT_EQ( chromeos::FakePowerManagerClient::Get()->num_request_restart_calls(), 1); }
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job.cc b/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job.cc index 45cc4deb..6f53517 100644 --- a/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job.cc +++ b/chrome/browser/ash/policy/remote_commands/device_command_start_crd_session_job.cc
@@ -287,12 +287,6 @@ curtain_local_user_session_ = (crd_session_type == CrdSessionType::REMOTE_ACCESS_SESSION); - if (base::FeatureList::IsEnabled( - remoting::features::kForceCrdAdminRemoteAccess)) { - CRD_LOG(WARNING) << "Forcing remote access"; - curtain_local_user_session_ = true; - } - if (curtain_local_user_session_ && !base::FeatureList::IsEnabled( remoting::features::kEnableCrdAdminRemoteAccess)) {
diff --git a/chrome/browser/ash/settings/device_settings_service.h b/chrome/browser/ash/settings/device_settings_service.h index 6f3b3bd..15b2733 100644 --- a/chrome/browser/ash/settings/device_settings_service.h +++ b/chrome/browser/ash/settings/device_settings_service.h
@@ -53,12 +53,15 @@ public: // Indicates ownership status of the device (listed in upgrade order). enum OwnershipStatus { + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. OWNERSHIP_UNKNOWN = 0, // Not yet owned. - OWNERSHIP_NONE, - // Either consumer ownership, cloud management or Active Directory - // management. - OWNERSHIP_TAKEN + OWNERSHIP_NONE = 1, + // Either consumer ownership or cloud management. + OWNERSHIP_TAKEN = 2, + // TODO(b/265923216): Convert to enum class and rename this to kMaxValue. + OWNERSHIP_MAX = OWNERSHIP_TAKEN }; using OwnershipStatusCallback = base::OnceCallback<void(OwnershipStatus)>;
diff --git a/chrome/browser/autofill/autofill_across_iframes_browsertest.cc b/chrome/browser/autofill/autofill_across_iframes_browsertest.cc index b8fa2a7..c046b41 100644 --- a/chrome/browser/autofill/autofill_across_iframes_browsertest.cc +++ b/chrome/browser/autofill/autofill_across_iframes_browsertest.cc
@@ -503,29 +503,15 @@ // Test fixture for "shared-autofill". The parameter indicates whether or not // shared-autofill has the "relaxed" semantics. class AutofillAcrossIframesTest_SharedAutofill - : public AutofillAcrossIframesTest_Simple, - public ::testing::WithParamInterface<bool> { - public: - AutofillAcrossIframesTest_SharedAutofill() { - feature_list_.InitAndEnableFeatureWithParameters( - features::kAutofillSharedAutofill, - {{features::kAutofillSharedAutofillRelaxedParam.name, - is_relaxed() ? "true" : "false"}}); - } - - bool is_relaxed() const { return GetParam(); } - + : public AutofillAcrossIframesTest_Simple { private: - base::test::ScopedFeatureList feature_list_; + base::test::ScopedFeatureList feature_list_{ + features::kAutofillSharedAutofill}; }; -INSTANTIATE_TEST_SUITE_P(AutofillAcrossIframesTest, - AutofillAcrossIframesTest_SharedAutofill, - ::testing::Bool()); - // Tests that autofilling on a main-origin field also fills cross-origin fields // whose frames have shared-autofill enabled. -IN_PROC_BROWSER_TEST_P(AutofillAcrossIframesTest_SharedAutofill, +IN_PROC_BROWSER_TEST_F(AutofillAcrossIframesTest_SharedAutofill, FillWhenTriggeredOnMainOrigin) { const FormStructure* form = LoadForm({"$1", "$2", "$3", "$4"}, {"", "", "", "allow=shared-autofill"}); @@ -534,27 +520,15 @@ ElementsAre(kNameFull, "", "", kCvc)); } -// Tests that autofilling on a cross-origin field also fills cross-origin fields -// whose frames have shared-autofill enabled iff shared-autofill is relaxed. -IN_PROC_BROWSER_TEST_P(AutofillAcrossIframesTest_SharedAutofill, +// Tests that autofilling on a cross-origin field does not fill cross-origin +// fields, even if shared-autofill in their document. +IN_PROC_BROWSER_TEST_F(AutofillAcrossIframesTest_SharedAutofill, FillWhenTriggeredOnNonMainOriginIffRelaxed) { const FormStructure* form = LoadForm({"$1", "$2", "$3", "$4"}, {"", "", "", "allow=shared-autofill"}); ASSERT_TRUE(form); EXPECT_THAT(FillForm(*form, *form->field(1)), - ElementsAre(kNameFull, kNumber, "", is_relaxed() ? kCvc : "")); -} - -// Tests that autofilling on a cross-origin field also fills main-origin fields -// irrespective of their type if shared-autofill is relaxed. -IN_PROC_BROWSER_TEST_P( - AutofillAcrossIframesTest_SharedAutofill, - FillEverythingOnMainOriginWhenTriggeredOnNonMainOriginIffRelaxed) { - const FormStructure* form = - LoadForm({"$1", "$2", "$1", "$1"}, {"", "", "", "allow=shared-autofill"}); - ASSERT_TRUE(form); - EXPECT_THAT(FillForm(*form, *form->field(1)), - ElementsAre(kNameFull, kNumber, kExp, is_relaxed() ? kCvc : "")); + ElementsAre(kNameFull, kNumber, "", "")); } // Test fixture where a form changes dynamically when it is filled.
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 774f642..a7b1f7b3 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1862,9 +1862,15 @@ std::unique_ptr<content::WebContentsViewDelegate> ChromeContentBrowserClient::GetWebContentsViewDelegate( content::WebContents* web_contents) { - if (auto* registry = - performance_manager::PerformanceManagerRegistry::GetInstance()) { - registry->MaybeCreatePageNodeForWebContents(web_contents); + Profile* profile = + Profile::FromBrowserContext(web_contents->GetBrowserContext()); + // Do not track web contents performance for profiles that have Keyed Services + // disabled. + if (!AreKeyedServicesDisabledForProfileByDefault(profile)) { + if (auto* registry = + performance_manager::PerformanceManagerRegistry::GetInstance()) { + registry->MaybeCreatePageNodeForWebContents(web_contents); + } } return CreateWebContentsViewDelegate(web_contents); }
diff --git a/chrome/browser/chromeos/kcer_nss/kcer_nss_unittest.cc b/chrome/browser/chromeos/kcer_nss/kcer_nss_unittest.cc index 7f250812..13207a96 100644 --- a/chrome/browser/chromeos/kcer_nss/kcer_nss_unittest.cc +++ b/chrome/browser/chromeos/kcer_nss/kcer_nss_unittest.cc
@@ -20,6 +20,7 @@ #include "content/public/browser/browser_thread.h" #include "content/public/test/browser_task_environment.h" #include "crypto/scoped_test_nss_db.h" +#include "crypto/secure_hash.h" #include "crypto/signature_verifier.h" #include "net/cert/pem.h" #include "net/test/cert_builder.h" @@ -159,6 +160,27 @@ return StrToBytes(tokenizer.data()); } +// Returns |hash| prefixed with DER-encoded PKCS#1 DigestInfo with +// AlgorithmIdentifier=id-sha256. +// This is useful for testing Kcer::SignRsaPkcs1Raw which only +// appends PKCS#1 v1.5 padding before signing. +std::vector<uint8_t> PrependSHA256DigestInfo(base::span<const uint8_t> hash) { + // DER-encoded PKCS#1 DigestInfo "prefix" with + // AlgorithmIdentifier=id-sha256. + // The encoding is taken from https://tools.ietf.org/html/rfc3447#page-43 + const std::vector<uint8_t> kDigestInfoSha256DerData = { + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, + 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; + + std::vector<uint8_t> result; + result.reserve(kDigestInfoSha256DerData.size() + hash.size()); + + result.insert(result.end(), kDigestInfoSha256DerData.begin(), + kDigestInfoSha256DerData.end()); + result.insert(result.end(), hash.begin(), hash.end()); + return result; +} + // A helper class to work with tokens (that exist on the IO thread) from the UI // thread. class TokenHolder { @@ -363,6 +385,10 @@ base::test::TestFuture<base::expected<Signature, Error>> sign_waiter; kcer->Sign(PrivateKeyHandle(PublicKeySpki()), SigningScheme::kRsaPkcs1Sha512, DataToSign({1, 2, 3}), sign_waiter.GetCallback()); + base::test::TestFuture<base::expected<Signature, Error>> sign_digest_waiter; + kcer->SignRsaPkcs1Raw(PrivateKeyHandle(PublicKeySpki()), + DigestWithPrefix({1, 2, 3}), + sign_digest_waiter.GetCallback()); base::test::TestFuture<base::expected<TokenInfo, Error>> get_token_info_waiter; kcer->GetTokenInfo(Token::kUser, get_token_info_waiter.GetCallback()); @@ -416,6 +442,9 @@ Error::kTokenInitializationFailed); ASSERT_FALSE(sign_waiter.Get().has_value()); EXPECT_EQ(sign_waiter.Get().error(), Error::kTokenInitializationFailed); + ASSERT_FALSE(sign_digest_waiter.Get().has_value()); + EXPECT_EQ(sign_digest_waiter.Get().error(), + Error::kTokenInitializationFailed); ASSERT_FALSE(get_token_info_waiter.Get().has_value()); EXPECT_EQ(get_token_info_waiter.Get().error(), Error::kTokenInitializationFailed); @@ -542,6 +571,56 @@ } } +// Test that `Kcer::SignRsaPkcs1Raw()` produces a correct signature. +TEST_F(KcerNssTest, SignRsaPkcs1Raw) { + TokenHolder user_token(Token::kUser); + user_token.Initialize(); + + std::unique_ptr<Kcer> kcer = internal::CreateKcer( + IOTaskRunner(), user_token.GetWeakPtr(), /*device_token=*/nullptr); + + base::test::TestFuture<base::expected<PublicKey, Error>> generate_key_waiter; + kcer->GenerateRsaKey(Token::kUser, /*modulus_length_bits=*/2048, + /*hardware_backed=*/true, + generate_key_waiter.GetCallback()); + ASSERT_TRUE(generate_key_waiter.Get().has_value()); + const PublicKey& public_key = generate_key_waiter.Get().value(); + + DataToSign data_to_sign({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); + + // A caller would need to hash the data themself before calling + // `SignRsaPkcs1Raw`, do that here. + auto hasher = crypto::SecureHash::Create(crypto::SecureHash::SHA256); + hasher->Update(data_to_sign->data(), data_to_sign->size()); + std::vector<uint8_t> hash(hasher->GetHashLength()); + hasher->Finish(hash.data(), hash.size()); + DigestWithPrefix digest_with_prefix(PrependSHA256DigestInfo(hash)); + + // Generate the signature. + base::test::TestFuture<base::expected<Signature, Error>> sign_waiter; + kcer->SignRsaPkcs1Raw(PrivateKeyHandle(public_key), + std::move(digest_with_prefix), + sign_waiter.GetCallback()); + ASSERT_TRUE(sign_waiter.Get().has_value()); + const Signature& signature = sign_waiter.Get().value(); + + // Verify the signature. + crypto::SignatureVerifier signature_verifier; + ASSERT_TRUE(signature_verifier.VerifyInit( + crypto::SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA256, + signature.value(), public_key.GetSpki().value())); + signature_verifier.VerifyUpdate(data_to_sign.value()); + EXPECT_TRUE(signature_verifier.VerifyFinal()); + + // Verify that manual hashing + `SignRsaPkcs1Raw` produces the same + // signature as just `Sign`. + base::test::TestFuture<base::expected<Signature, Error>> normal_sign_waiter; + kcer->Sign(PrivateKeyHandle(public_key), SigningScheme::kRsaPkcs1Sha256, + data_to_sign, normal_sign_waiter.GetCallback()); + ASSERT_TRUE(normal_sign_waiter.Get().has_value()); + EXPECT_EQ(sign_waiter.Get().value(), normal_sign_waiter.Get().value()); +} + // Test that Kcer::GetTokenInfo() method returns meaningful values. TEST_F(KcerNssTest, GetTokenInfo) { TokenHolder user_token(Token::kUser); @@ -640,8 +719,8 @@ // Hardware- vs software-backed indicators on real devices are provided by // Chaps and are wrong in unit tests. expected_key_info.is_hardware_backed = true; - // NSS sets an empty nickname by default, this doesn't have to be like this in - // general. + // NSS sets an empty nickname by default, this doesn't have to be like this + // in general. expected_key_info.nickname = ""; // Custom attributes are stored differently in tests and have empty values by // default. @@ -655,8 +734,8 @@ ASSERT_TRUE(key_info_waiter.Get().has_value()); const KeyInfo& key_info = key_info_waiter.Get().value(); - // Copy some fields, their values are covered by dedicated tests, this test - // only checks that they don't change when they shouldn't. + // Copy some fields, their values are covered by dedicated tests, this + // test only checks that they don't change when they shouldn't. expected_key_info.key_type = key_info.key_type; expected_key_info.supported_signing_schemes = key_info.supported_signing_schemes;
diff --git a/chrome/browser/chromeos/kcer_nss/kcer_token_impl_nss.cc b/chrome/browser/chromeos/kcer_nss/kcer_token_impl_nss.cc index d41e6ac6..827760a 100644 --- a/chrome/browser/chromeos/kcer_nss/kcer_token_impl_nss.cc +++ b/chrome/browser/chromeos/kcer_nss/kcer_token_impl_nss.cc
@@ -464,6 +464,83 @@ return std::move(callback).Run(Signature(std::move(signature))); } +// Checks whether |input_length| is lower or equal to the maximum input length +// for a RSA PKCS#1 v1.5 signature generated using |private_key| with PK11_Sign. +// Returns false if |input_length| is too large. +// If the maximum input length can not be determined (which is possible because +// it queries the PKCS#11 module), returns true and logs a warning. +bool CheckRsaPkcs1SignDigestInputLength(SECKEYPrivateKey* private_key, + size_t input_length) { + // For RSA keys, PK11_Sign will perform PKCS#1 v1.5 padding, which needs at + // least 11 bytes. RSA Sign can process an input of max. modulus length. + // Thus the maximum input length for the sign operation is + // |modulus_length - 11|. + int modulus_length_bytes = PK11_GetPrivateModulusLen(private_key); + if (modulus_length_bytes <= 0) { + LOG(WARNING) << "Could not determine modulus length"; + return true; + } + size_t max_input_length_after_padding = + static_cast<size_t>(modulus_length_bytes); + // PKCS#1 v1.5 Padding needs at least this many bytes. + size_t kMinPaddingLength = 11u; + return input_length + kMinPaddingLength <= max_input_length_after_padding; +} + +// Performs "raw" PKCS1 v1.5 padding + signing by calling PK11_Sign on |key|. +// TODO(b/244408117): This method is mostly a copy of +// `PlatformKeysService::SignRSAPKCS1Raw` from platform_keys_service_nss.cc . +// The original method should be replaced during the upcoming refactoring to +// remove direct usages of NSS. +void SignRsaPkcs1RawOnWorkerThread(crypto::ScopedPK11Slot slot, + PrivateKeyHandle key, + DigestWithPrefix digest_with_prefix, + Kcer::SignCallback callback) { + base::expected<crypto::ScopedSECKEYPrivateKey, Error> private_key = + GetSECKEYPrivateKey(slot, key); + if (!private_key.has_value()) { + return std::move(callback).Run(base::unexpected(private_key.error())); + } + const crypto::ScopedSECKEYPrivateKey& sec_private_key = private_key.value(); + if (sec_private_key->keyType != ::KeyType::rsaKey) { + return std::move(callback).Run( + base::unexpected(Error::kKeyDoesNotSupportSigningScheme)); + } + + static_assert( + sizeof(*digest_with_prefix->data()) == sizeof(char), + "Can't reinterpret data if its characters are not 8 bit large."); + SECItem input = {siBuffer, + const_cast<unsigned char*>(digest_with_prefix->data()), + static_cast<unsigned int>(digest_with_prefix->size())}; + + // Compute signature of hash. + int signature_len = PK11_SignatureLen(sec_private_key.get()); + if (signature_len <= 0) { + return std::move(callback).Run( + base::unexpected(Error::kFailedToSignBadSignatureLength)); + } + + std::vector<unsigned char> signature(signature_len); + SECItem signature_output = {siBuffer, signature.data(), + static_cast<unsigned int>(signature.size())}; + if (PK11_Sign(sec_private_key.get(), &signature_output, &input) != + SECSuccess) { + // Input size is checked after a failure - obtaining max input size + // involves extracting key modulus length which is not a free operation, so + // don't bother if signing succeeded. + // Note: It would be better if this could be determined from some library + // return code (e.g. PORT_GetError), but this was not possible with + // NSS+chaps at this point. + if (!CheckRsaPkcs1SignDigestInputLength(sec_private_key.get(), + digest_with_prefix->size())) { + return std::move(callback).Run(base::unexpected(Error::kInputTooLong)); + } + return std::move(callback).Run(base::unexpected(Error::kFailedToSign)); + } + return std::move(callback).Run(Signature(std::move(signature))); +} + std::vector<SigningScheme> GetSigningSchemes(bool supports_pss, KeyType key_type) { std::vector<SigningScheme> result; @@ -981,10 +1058,29 @@ } void KcerTokenImplNss::SignRsaPkcs1Raw(PrivateKeyHandle key, - SigningScheme signing_scheme, DigestWithPrefix digest_with_prefix, Kcer::SignCallback callback) { - // TODO(244408716): Implement. + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + if (UNLIKELY(state_ == State::kInitializationFailed)) { + return HandleInitializationFailed(std::move(callback)); + } + if (is_blocked_) { + return task_queue_.push(base::BindOnce( + &KcerTokenImplNss::SignRsaPkcs1Raw, weak_factory_.GetWeakPtr(), + std::move(key), std::move(digest_with_prefix), std::move(callback))); + } + + // Block task queue, attach unblocking task to the callback. + auto unblocking_callback = std::move(callback).Then(BlockQueueGetUnblocker()); + + base::ThreadPool::PostTask( + FROM_HERE, + {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, + base::BindOnce(&SignRsaPkcs1RawOnWorkerThread, + crypto::ScopedPK11Slot(PK11_ReferenceSlot(slot_.get())), + std::move(key), std::move(digest_with_prefix), + std::move(unblocking_callback))); } void KcerTokenImplNss::GetTokenInfo(Kcer::GetTokenInfoCallback callback) {
diff --git a/chrome/browser/chromeos/kcer_nss/kcer_token_impl_nss.h b/chrome/browser/chromeos/kcer_nss/kcer_token_impl_nss.h index 348a153..dca805c 100644 --- a/chrome/browser/chromeos/kcer_nss/kcer_token_impl_nss.h +++ b/chrome/browser/chromeos/kcer_nss/kcer_token_impl_nss.h
@@ -94,7 +94,6 @@ DataToSign data, Kcer::SignCallback callback) override; void SignRsaPkcs1Raw(PrivateKeyHandle key, - SigningScheme signing_scheme, DigestWithPrefix digest_with_prefix, Kcer::SignCallback callback) override; void GetTokenInfo(Kcer::GetTokenInfoCallback callback) override;
diff --git a/chrome/browser/chromeos/policy/dlp/dialogs/files_policy_dialog.cc b/chrome/browser/chromeos/policy/dlp/dialogs/files_policy_dialog.cc index de9de482..e9aa24c 100644 --- a/chrome/browser/chromeos/policy/dlp/dialogs/files_policy_dialog.cc +++ b/chrome/browser/chromeos/policy/dlp/dialogs/files_policy_dialog.cc
@@ -9,6 +9,7 @@ #include <utility> #include <vector> +#include "base/files/file_path.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/chromeos/policy/dlp/dialogs/policy_dialog_base.h" #include "chrome/browser/chromeos/policy/dlp/dlp_confidential_file.h" @@ -56,6 +57,9 @@ IDS_POLICY_DLP_FILES_DESTINATION_REMOVABLE_STORAGE); case data_controls::Component::kDrive: return l10n_util::GetStringUTF16(IDS_FILE_BROWSER_DRIVE_DIRECTORY_LABEL); + case data_controls::Component::kOneDrive: + return l10n_util::GetStringUTF16( + IDS_FILE_BROWSER_DLP_COMPONENT_MICROSOFT_ONEDRIVE); case data_controls::Component::kUnknownComponent: NOTREACHED(); return u"";
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_policy_constants.h b/chrome/browser/chromeos/policy/dlp/dlp_policy_constants.h index ce28d2f7..bdf75394 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_policy_constants.h +++ b/chrome/browser/chromeos/policy/dlp/dlp_policy_constants.h
@@ -22,6 +22,7 @@ constexpr char kCrostini[] = "CROSTINI"; constexpr char kPluginVm[] = "PLUGIN_VM"; constexpr char kDrive[] = "DRIVE"; +constexpr char kOneDrive[] = "ONEDRIVE"; constexpr char kUsb[] = "USB"; constexpr char kAllowLevel[] = "ALLOW";
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_policy_event.proto b/chrome/browser/chromeos/policy/dlp/dlp_policy_event.proto index a84daeb..2768a909 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_policy_event.proto +++ b/chrome/browser/chromeos/policy/dlp/dlp_policy_event.proto
@@ -21,6 +21,7 @@ PLUGIN_VM = 3; USB = 4; DRIVE = 5; + ONEDRIVE = 6; } // Either |url| or |component| should be set.
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager.cc b/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager.cc index 90ae5577..5b0a9653 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager.cc
@@ -205,6 +205,10 @@ event_destination->set_component( DlpPolicyEventDestination_Component_DRIVE); break; + case (data_controls::Component::kOneDrive): + event_destination->set_component( + DlpPolicyEventDestination_Component_ONEDRIVE); + break; case (data_controls::Component::kUnknownComponent): event_destination->set_component( DlpPolicyEventDestination_Component_UNDEFINED_COMPONENT);
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager_unittest.cc b/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager_unittest.cc index cf6db22..119941c3 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager_unittest.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager_unittest.cc
@@ -162,10 +162,13 @@ DlpPolicyEventDestination_Component_USB, 3u); ReportEventAndCheckComponent(data_controls::Component::kDrive, DlpPolicyEventDestination_Component_DRIVE, 4u); + ReportEventAndCheckComponent(data_controls::Component::kOneDrive, + DlpPolicyEventDestination_Component_ONEDRIVE, + 5u); ReportEventAndCheckComponent( data_controls::Component::kUnknownComponent, - DlpPolicyEventDestination_Component_UNDEFINED_COMPONENT, 5u); - EXPECT_EQ(manager_.events_reported(), 6u); + DlpPolicyEventDestination_Component_UNDEFINED_COMPONENT, 6u); + EXPECT_EQ(manager_.events_reported(), 7u); } TEST_F(DlpReportingManagerTest, ReportEventWithoutNameAndRuleId) {
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h index 92e5526..ca8df884c 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h +++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h
@@ -26,10 +26,10 @@ public: // List of all possible component values, used to simplify iterating over all // the options. - constexpr static const std::array<data_controls::Component, 5> components = { - data_controls::Component::kArc, data_controls::Component::kCrostini, + constexpr static const std::array<data_controls::Component, 6> components = { + data_controls::Component::kArc, data_controls::Component::kCrostini, data_controls::Component::kPluginVm, data_controls::Component::kUsb, - data_controls::Component::kDrive}; + data_controls::Component::kDrive, data_controls::Component::kOneDrive}; // Represents file metadata. struct FileMetadata {
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.cc b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.cc index ef9dad0..5ffd666b 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.cc
@@ -62,6 +62,7 @@ constexpr char kWildCardMatching[] = "*"; constexpr char kDrivePattern[] = "drive.google.com"; +constexpr char kOneDrivePattern[] = "onedrive.live.com"; DlpRulesManager::Restriction GetClassMapping(const std::string& restriction) { static constexpr auto kRestrictionsMap = @@ -102,6 +103,7 @@ {dlp::kCrostini, data_controls::Component::kCrostini}, {dlp::kPluginVm, data_controls::Component::kPluginVm}, {dlp::kDrive, data_controls::Component::kDrive}, + {dlp::kOneDrive, data_controls::Component::kOneDrive}, {dlp::kUsb, data_controls::Component::kUsb}}); auto* it = kComponentsMap.find(component); @@ -179,7 +181,13 @@ switch (component) { case data_controls::Component::kDrive: return {kDrivePattern}; - default: + case data_controls::Component::kOneDrive: + return {kOneDrivePattern}; + case data_controls::Component::kUnknownComponent: + case data_controls::Component::kArc: + case data_controls::Component::kCrostini: + case data_controls::Component::kPluginVm: + case data_controls::Component::kUsb: return {}; } }
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc index 13a049ca..5d71a16 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc
@@ -40,6 +40,7 @@ constexpr char kGmailUrl[] = "https://www.gmail.com"; constexpr char kCompanyUrl[] = "https://company.com"; constexpr char kDriveUrl[] = "https://drive.google.com"; +constexpr char kOneDriveUrl[] = "https://onedrive.live.com"; constexpr char kHttpsPrefix[] = "https://www."; @@ -50,6 +51,7 @@ constexpr char kCompanyPattern[] = ".company.com"; constexpr char kGooglePattern[] = "google.com"; constexpr char kMailPattern[] = "mail.google.com"; +constexpr char kOneDrivePattern[] = "onedrive.live.com"; constexpr char kWrongRestriction[] = "WrongRestriction"; constexpr char kWrongComponent[] = "WrongComponent"; @@ -343,6 +345,7 @@ dlp_test_util::DlpRule rule(kRuleName1, "Block", kRuleId1); rule.AddSrcUrl(kExampleUrl) .AddDstComponent(dlp::kDrive) + .AddDstComponent(dlp::kOneDrive) .AddRestriction(dlp::kFilesRestriction, dlp::kBlockLevel); UpdatePolicyPref({rule}); @@ -352,6 +355,11 @@ DlpRulesManager::Restriction::kFiles, DlpRulesManager::Level::kBlock, kExampleUrl, DlpRulesManager::RuleMetadata(kRuleName1, kRuleId1)); + CheckIsRestrictedComponent( + kExampleUrl, data_controls::Component::kOneDrive, + DlpRulesManager::Restriction::kFiles, DlpRulesManager::Level::kBlock, + kExampleUrl, DlpRulesManager::RuleMetadata(kRuleName1, kRuleId1)); + // Make sure that blocking the components also blocks their associated // website. CheckIsRestrictedDestination( @@ -359,6 +367,11 @@ DlpRulesManager::Level::kBlock, kExampleUrl, kDrivePattern, DlpRulesManager::RuleMetadata(kRuleName1, kRuleId1)); + CheckIsRestrictedDestination( + kExampleUrl, kOneDriveUrl, DlpRulesManager::Restriction::kFiles, + DlpRulesManager::Level::kBlock, kExampleUrl, kOneDrivePattern, + DlpRulesManager::RuleMetadata(kRuleName1, kRuleId1)); + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, run_loop_.QuitClosure()); @@ -918,6 +931,8 @@ data_controls::Component::kUsb); expected[DlpRulesManager::Level::kAllow].insert( data_controls::Component::kDrive); + expected[DlpRulesManager::Level::kAllow].insert( + data_controls::Component::kOneDrive); EXPECT_EQ(result, expected);
diff --git a/chrome/browser/enterprise/data_controls/component.h b/chrome/browser/enterprise/data_controls/component.h index f8d2031..3750aa2 100644 --- a/chrome/browser/enterprise/data_controls/component.h +++ b/chrome/browser/enterprise/data_controls/component.h
@@ -18,7 +18,8 @@ kPluginVm, // Plugin VM (Parallels/Windows) as a Guest OS. kUsb, // Removable disk. kDrive, // Google drive for file storage. - kMaxValue = kDrive + kOneDrive, // Microsoft OneDrive for file storage. + kMaxValue = kOneDrive }; } // namespace data_controls
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index aa8af296..0e218df 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -69,14 +69,6 @@ "expiry_milestone": 118 }, { - "name": "add-edu-account-for-supervised-users", - "owners": [ - "mlbipin", - "chrome-kids-eng@google.com" - ], - "expiry_milestone": 118 - }, - { "name": "add-identity-in-can-make-payment", "owners": [ "rouslan", "chrome-payments-team@google.com" ], "expiry_milestone": 115 @@ -6545,6 +6537,11 @@ "expiry_milestone": 118 }, { + "name": "replace-sync-promos-with-sign-in-promos", + "owners": [ "treib", "mastiz", "jood@google.com", "bling-flags@google.com", "chrome-sync-dev@google.com", "chrome-signin-team"], + "expiry_milestone": 119 + }, + { "name": "request-desktop-site-additions", "owners": [ "shuyng@google.com", "skavuluru@google.com", "twellington", "clank-app-team@google.com" ], "expiry_milestone": 116
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 3703cce..7d91aca 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -44,13 +44,6 @@ const char kPdfUseSkiaRendererDescription[] = "Use Skia as the PDF renderer."; #endif -extern const char kAddEduAccountFromAccountSettingsForSupervisedUsersName[] = - "Add Edu Account From Account Settings For Supervised Users"; -extern const char - kAddEduAccountFromAccountSettingsForSupervisedUsersDescription[] = - "Enables supervised users to add additional Edu accounts and " - "simplifies settings UI"; - const char kAppDeduplicationServiceFondueName[] = "Identify duplicate app groups."; const char kAppDeduplicationServiceFondueDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 6365fbf..001810a 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -59,10 +59,6 @@ extern const char kPdfUseSkiaRendererDescription[]; #endif -extern const char kAddEduAccountFromAccountSettingsForSupervisedUsersName[]; -extern const char - kAddEduAccountFromAccountSettingsForSupervisedUsersDescription[]; - extern const char kAlignWakeUpsName[]; extern const char kAlignWakeUpsDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index f1fab85..ac679a27 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -156,7 +156,6 @@ &kAdaptiveButtonInTopToolbarTranslate, &kAdaptiveButtonInTopToolbarAddToBookmarks, &kAdaptiveButtonInTopToolbarCustomizationV2, - &kAddEduAccountFromAccountSettingsForSupervisedUsers, &kAddToHomescreenIPH, &kAllowNewIncognitoTabIntents, &kAndroidAppIntegration, @@ -432,10 +431,6 @@ "AdaptiveButtonInTopToolbarCustomizationV2", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kAddEduAccountFromAccountSettingsForSupervisedUsers, - "AddEduAccountFromAccountSettingsForSupervisedUsers", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kAddToHomescreenIPH, "AddToHomescreenIPH", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index 6abef2b..934e2f2 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -17,7 +17,6 @@ BASE_DECLARE_FEATURE(kAdaptiveButtonInTopToolbarTranslate); BASE_DECLARE_FEATURE(kAdaptiveButtonInTopToolbarAddToBookmarks); BASE_DECLARE_FEATURE(kAdaptiveButtonInTopToolbarCustomizationV2); -BASE_DECLARE_FEATURE(kAddEduAccountFromAccountSettingsForSupervisedUsers); BASE_DECLARE_FEATURE(kAddToHomescreenIPH); BASE_DECLARE_FEATURE(kAllowNewIncognitoTabIntents); BASE_DECLARE_FEATURE(kAndroidAppIntegration);
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index 7f81e8a4d..28ea868 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -105,8 +105,6 @@ "AdaptiveButtonInTopToolbarAddToBookmarks"; public static final String ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2 = "AdaptiveButtonInTopToolbarCustomizationV2"; - public static final String ADD_EDU_ACCOUNT_FROM_ACCOUNT_SETTINGS_FOR_SUPERVISED_USERS = - "AddEduAccountFromAccountSettingsForSupervisedUsers"; public static final String ADD_TO_HOMESCREEN_IPH = "AddToHomescreenIPH"; public static final String ALLOW_NEW_INCOGNITO_TAB_INTENTS = "AllowNewIncognitoTabIntents"; public static final String ANDROID_APP_INTEGRATION = "AndroidAppIntegration";
diff --git a/chrome/browser/password_manager/android/password_accessory_controller_impl_unittest.cc b/chrome/browser/password_manager/android/password_accessory_controller_impl_unittest.cc index ea4fd16..cc949b53 100644 --- a/chrome/browser/password_manager/android/password_accessory_controller_impl_unittest.cc +++ b/chrome/browser/password_manager/android/password_accessory_controller_impl_unittest.cc
@@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include "base/android/build_info.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/memory/ptr_util.h" @@ -1013,6 +1014,9 @@ } TEST_F(PasswordAccessoryControllerTest, ShowCredManReentry) { + if (!base::android::BuildInfo::GetInstance()->is_at_least_u()) { + return; + } base::test::ScopedFeatureList enable_feature(device::kWebAuthnAndroidCredMan); CreateSheetController(); cred_man_delegate()->OnCredManConditionalRequestPending( @@ -1028,6 +1032,9 @@ } TEST_F(PasswordAccessoryControllerTest, HideCredManReentryWithoutResult) { + if (!base::android::BuildInfo::GetInstance()->is_at_least_u()) { + return; + } base::test::ScopedFeatureList enable_feature(device::kWebAuthnAndroidCredMan); CreateSheetController(); cred_man_delegate()->OnCredManConditionalRequestPending(
diff --git a/chrome/browser/password_manager/android/pwd_migration/BUILD.gn b/chrome/browser/password_manager/android/pwd_migration/BUILD.gn index 815022ec..131d30b 100644 --- a/chrome/browser/password_manager/android/pwd_migration/BUILD.gn +++ b/chrome/browser/password_manager/android/pwd_migration/BUILD.gn
@@ -35,6 +35,7 @@ "//chrome/browser/password_manager/android:password_manager_resource_provider_java", "//chrome/browser/ui/android/strings:ui_strings_grd", "//components/browser_ui/bottomsheet/android:java", + "//components/browser_ui/widget/android:java", "//components/version_info/android:version_constants_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_appcompat_appcompat_java", @@ -48,6 +49,8 @@ "java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningCoordinator.java", "java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningIntroFragment.java", "java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningMediator.java", + "java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningOnClickHandler.java", + "java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningOptionsFragment.java", "java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningProperties.java", "java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningView.java", "java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningViewBinder.java", @@ -113,10 +116,14 @@ } android_resources("java_resources") { - deps = [ "//ui/android:ui_java_resources" ] + deps = [ + "//components/browser_ui/widget/android:java_resources", + "//ui/android:ui_java_resources", + ] sources = [ "java/res/layout/pwd_migration_warning.xml", "java/res/layout/pwd_migration_warning_intro_fragment.xml", + "java/res/layout/pwd_migration_warning_options.xml", "java/res/values/dimens.xml", ] }
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/res/layout/pwd_migration_warning_intro_fragment.xml b/chrome/browser/password_manager/android/pwd_migration/java/res/layout/pwd_migration_warning_intro_fragment.xml index c537287..69bea78 100644 --- a/chrome/browser/password_manager/android/pwd_migration/java/res/layout/pwd_migration_warning_intro_fragment.xml +++ b/chrome/browser/password_manager/android/pwd_migration/java/res/layout/pwd_migration_warning_intro_fragment.xml
@@ -14,8 +14,8 @@ android:id="@+id/migration_warning_sheet_subtitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/pwd_migration_warning_margin" android:layout_gravity="center_horizontal" + android:layout_marginBottom="@dimen/pwd_migration_warning_margin" android:textAppearance="@style/TextAppearance.TextMedium.Secondary"/> <org.chromium.ui.widget.ButtonCompat @@ -23,9 +23,9 @@ android:id="@+id/acknowledge_password_migration_button" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="12dp" - android:minHeight="@dimen/pwd_migration_warning_button_height" android:layout_gravity="center_horizontal" + android:layout_marginBottom="@dimen/pwd_migration_warning_button_spacing" + android:minHeight="@dimen/pwd_migration_warning_button_height" android:ellipsize="end" android:singleLine="true" android:text="@string/password_migration_warning_acknowledge" @@ -36,9 +36,9 @@ android:id="@+id/password_migration_more_options_button" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" android:layout_marginBottom="@dimen/pwd_migration_warning_margin" android:minHeight="@dimen/pwd_migration_warning_button_height" - android:layout_gravity="center_horizontal" android:ellipsize="end" android:singleLine="true" android:text="@string/password_migration_warning_other_options"
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/res/layout/pwd_migration_warning_options.xml b/chrome/browser/password_manager/android/pwd_migration/java/res/layout/pwd_migration_warning_options.xml new file mode 100644 index 0000000..6080126 --- /dev/null +++ b/chrome/browser/password_manager/android/pwd_migration/java/res/layout/pwd_migration_warning_options.xml
@@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2023 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:orientation="vertical" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal"> + + <org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout + android:id="@+id/radio_button_layout" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/pwd_migration_warning_margin"> + + <org.chromium.components.browser_ui.widget.RadioButtonWithDescription + android:id="@+id/radio_sign_in_or_sync" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:primaryText="@string/password_migration_warning_turn_on_sync" + app:descriptionText="@string/password_migration_warning_turn_on_sync_subtitle" /> + + <org.chromium.components.browser_ui.widget.RadioButtonWithDescription + android:id="@+id/radio_password_export" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:primaryText="@string/password_migration_warning_password_export" /> + </org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout> + + <org.chromium.ui.widget.ButtonCompat + android:descendantFocusability="blocksDescendants" + android:id="@+id/password_migration_next_button" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_marginBottom="@dimen/pwd_migration_warning_button_spacing" + android:minHeight="@dimen/pwd_migration_warning_button_height" + android:ellipsize="end" + android:singleLine="true" + android:text="@string/password_migration_warning_next" + style="@style/FilledButton.Flat"/> + + <org.chromium.ui.widget.ButtonCompat + android:descendantFocusability="blocksDescendants" + android:id="@+id/password_migration_cancel_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_marginBottom="@dimen/pwd_migration_warning_margin" + android:minHeight="@dimen/pwd_migration_warning_button_height" + android:ellipsize="end" + android:singleLine="true" + android:text="@string/password_migration_warning_cancel" + style="@style/TextButton"/> +</LinearLayout>
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/res/values/dimens.xml b/chrome/browser/password_manager/android/pwd_migration/java/res/values/dimens.xml index f32d911f..cbaa6ed 100644 --- a/chrome/browser/password_manager/android/pwd_migration/java/res/values/dimens.xml +++ b/chrome/browser/password_manager/android/pwd_migration/java/res/values/dimens.xml
@@ -9,4 +9,5 @@ <dimen name="pwd_migration_warning_margin">24dp</dimen> <dimen name="pwd_migration_warning_button_height">48dp</dimen> <dimen name="pwd_migration_warning_icon_size">32dp</dimen> + <dimen name="pwd_migration_warning_button_spacing">12dp</dimen> </resources>
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningCoordinator.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningCoordinator.java index b71b7c6..3695d89 100644 --- a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningCoordinator.java +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningCoordinator.java
@@ -8,6 +8,7 @@ import androidx.annotation.Nullable; +import org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.ScreenType; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; @@ -19,14 +20,15 @@ public PasswordMigrationWarningCoordinator( @Nullable Context context, BottomSheetController sheetController) { - mMediator.initialize( - PasswordMigrationWarningProperties.createDefaultModel(mMediator::onDismissed)); + PropertyModel model = PasswordMigrationWarningProperties.createDefaultModel( + mMediator::onDismissed, mMediator); + mMediator.initialize(model); setUpModelChangeProcessors( - mMediator.getModel(), new PasswordMigrationWarningView(context, sheetController)); + model, new PasswordMigrationWarningView(context, sheetController)); } public void showWarning() { - mMediator.showWarning(); + mMediator.showWarning(ScreenType.INTRO_SCREEN); } static void setUpModelChangeProcessors(PropertyModel model, PasswordMigrationWarningView view) {
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningIntroFragment.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningIntroFragment.java index f3467829..3a19d1a 100644 --- a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningIntroFragment.java +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningIntroFragment.java
@@ -7,40 +7,37 @@ import android.content.Context; import android.os.Bundle; import android.view.View; +import android.widget.Button; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import org.chromium.components.version_info.VersionInfo; import org.chromium.ui.widget.TextViewWithLeading; /** This fragment contains the UI for the first page of the password migration warning. */ public class PasswordMigrationWarningIntroFragment extends Fragment { private Context mContext; + private Runnable mAcknowledgeCallback; + private Runnable mMoreOptionsCallback; + private String mChannelString; - public PasswordMigrationWarningIntroFragment(Context context) { + public PasswordMigrationWarningIntroFragment(Context context, Runnable acknowledgeCallback, + Runnable moreOptionsCallback, String channelString) { super(R.layout.pwd_migration_warning_intro_fragment); mContext = context; + mAcknowledgeCallback = acknowledgeCallback; + mMoreOptionsCallback = moreOptionsCallback; + mChannelString = channelString; } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { TextViewWithLeading subtitleView = view.findViewById(R.id.migration_warning_sheet_subtitle); subtitleView.setText(mContext.getString(R.string.password_migration_warning_subtitle) - .replace("%1$s", getChannelString())); - } - - private String getChannelString() { - if (VersionInfo.isCanaryBuild()) { - return "Canary"; - } - if (VersionInfo.isDevBuild()) { - return "Dev"; - } - if (VersionInfo.isBetaBuild()) { - return "Beta"; - } - assert !VersionInfo.isStableBuild(); - return ""; + .replace("%1$s", mChannelString)); + Button acknowledgeButton = view.findViewById(R.id.acknowledge_password_migration_button); + Button moreOptionsButton = view.findViewById(R.id.password_migration_more_options_button); + acknowledgeButton.setOnClickListener((unusedView) -> mAcknowledgeCallback.run()); + moreOptionsButton.setOnClickListener((unusedView) -> mMoreOptionsCallback.run()); } }
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningMediator.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningMediator.java index 67f9297..9eac7db 100644 --- a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningMediator.java +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningMediator.java
@@ -4,8 +4,11 @@ package org.chromium.chrome.browser.pwd_migration; +import static org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.CURRENT_SCREEN; import static org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.VISIBLE; +import org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.ScreenType; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason; import org.chromium.ui.modelutil.PropertyModel; @@ -13,14 +16,15 @@ * Contains the logic for the local passwords migration warning. It sets the state of the model and * reacts to events. */ -class PasswordMigrationWarningMediator { +class PasswordMigrationWarningMediator implements PasswordMigrationWarningOnClickHandler { private PropertyModel mModel; void initialize(PropertyModel model) { mModel = model; } - void showWarning() { + void showWarning(int screenType) { + mModel.set(CURRENT_SCREEN, screenType); mModel.set(VISIBLE, true); } @@ -29,7 +33,23 @@ mModel.set(VISIBLE, false); } - PropertyModel getModel() { - return mModel; + @Override + public void onAcknowledge(BottomSheetController bottomSheetController) { + bottomSheetController.collapseSheet(true); + } + + @Override + public void onMoreOptions() { + mModel.set(CURRENT_SCREEN, ScreenType.OPTIONS_SCREEN); + } + + @Override + public void onNext() { + // TODO(crbug.com/1445065): Launch the password Export flow. + } + + @Override + public void onCancel(BottomSheetController bottomSheetController) { + bottomSheetController.collapseSheet(true); } }
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningMediatorTest.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningMediatorTest.java index d7d4838..e3aaefd 100644 --- a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningMediatorTest.java +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningMediatorTest.java
@@ -4,10 +4,13 @@ package org.chromium.chrome.browser.pwd_migration; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.verify; +import static org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.CURRENT_SCREEN; import static org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.DISMISS_HANDLER; import static org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.VISIBLE; @@ -24,6 +27,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.Batch; +import org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.ScreenType; import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason; @@ -42,6 +46,7 @@ public TestRule mProcessor = new Features.JUnitProcessor(); private PasswordMigrationWarningMediator mMediator = new PasswordMigrationWarningMediator(); + private PropertyModel mModel; @Mock private BottomSheetController mBottomSheetController; @@ -49,35 +54,50 @@ @Before public void setUp() { MockitoAnnotations.initMocks(this); - mMediator.initialize( - PasswordMigrationWarningProperties.createDefaultModel(mMediator::onDismissed)); + mModel = PasswordMigrationWarningProperties.createDefaultModel( + mMediator::onDismissed, mMediator); + mMediator.initialize(mModel); } @Test public void testShowWarningChangesVisibility() { - PropertyModel model = mMediator.getModel(); - assertFalse(model.get(VISIBLE)); - mMediator.showWarning(); - assertTrue(model.get(VISIBLE)); + mModel.set(VISIBLE, false); + mMediator.showWarning(ScreenType.INTRO_SCREEN); + assertTrue(mModel.get(VISIBLE)); } @Test - public void testOnDismissedChangesVisibility() { - PropertyModel model = mMediator.getModel(); - mMediator.showWarning(); - assertTrue(model.get(VISIBLE)); + public void testOnDismissedHidesTheSheet() { + mMediator.showWarning(ScreenType.INTRO_SCREEN); mMediator.onDismissed(StateChangeReason.NONE); - assertFalse(model.get(VISIBLE)); + assertFalse(mModel.get(VISIBLE)); } @Test - public void testDismissHandlerChangesVisibility() { - PropertyModel model = mMediator.getModel(); - assertNotNull(model.get(DISMISS_HANDLER)); - assertFalse(model.get(VISIBLE)); - mMediator.showWarning(); - assertTrue(model.get(VISIBLE)); - model.get(DISMISS_HANDLER).onResult(StateChangeReason.NONE); - assertFalse(model.get(VISIBLE)); + public void testDismissHandlerHidesTheSheet() { + assertNotNull(mModel.get(DISMISS_HANDLER)); + mMediator.showWarning(ScreenType.INTRO_SCREEN); + mModel.get(DISMISS_HANDLER).onResult(StateChangeReason.NONE); + assertFalse(mModel.get(VISIBLE)); + } + + @Test + public void testOnMoreOptionsChangesTheModel() { + mMediator.showWarning(ScreenType.INTRO_SCREEN); + assertEquals(mModel.get(CURRENT_SCREEN), ScreenType.INTRO_SCREEN); + mMediator.onMoreOptions(); + assertEquals(mModel.get(CURRENT_SCREEN), ScreenType.OPTIONS_SCREEN); + } + + @Test + public void testOnAcknowledgeCollapsesTheSheet() { + mMediator.onAcknowledge(mBottomSheetController); + verify(mBottomSheetController).collapseSheet(true); + } + + @Test + public void testOnCancelCollapsesTheSheet() { + mMediator.onCancel(mBottomSheetController); + verify(mBottomSheetController).collapseSheet(true); } }
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningOnClickHandler.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningOnClickHandler.java new file mode 100644 index 0000000..e726d766 --- /dev/null +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningOnClickHandler.java
@@ -0,0 +1,41 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.pwd_migration; + +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; + +/** + * Contains the logic for the on click listeners of all the buttons on the + * password migration warning sheet. + */ +interface PasswordMigrationWarningOnClickHandler { + /** + * Closes the sheet and marks that the user acknowledged the notice by + * clicking on the "Got it" button. + * + * @param bottomSheetController used to close the sheet. + */ + void onAcknowledge(BottomSheetController bottomSheetController); + + /** + * Shows a screen with more options when the "More options" button is + * clicked. + */ + void onMoreOptions(); + + /** + * Starts the sign-in/sync flow or the export flow depending on the user + * choice in the screen with more options. + */ + void onNext(); + + /** + * Closes the sheet when the "Cancel" button is clicked, but doesn't mark + * that the user acknowledged the notice. + * + * @param bottomSheetController used to close the sheet. + */ + void onCancel(BottomSheetController bottomSheetController); +}
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningOptionsFragment.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningOptionsFragment.java new file mode 100644 index 0000000..4cf115d --- /dev/null +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningOptionsFragment.java
@@ -0,0 +1,54 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +package org.chromium.chrome.browser.pwd_migration; + +import android.content.Context; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import org.chromium.components.browser_ui.widget.RadioButtonWithDescription; + +/** + * This fragment contains the UI for the second page of the password migration + * warning. The page shows alternative options for users who didn't acknowledge + * the upcoming merge of passwords for different Chrome channels. The offered + * alternatives are to export the passwords or to start syncing passwords. + */ +public class PasswordMigrationWarningOptionsFragment extends Fragment { + private Context mContext; + private boolean mShouldSignIn = true; + private Runnable mNextCallback; + private Runnable mCancelCallback; + private String mChannelString; + + public PasswordMigrationWarningOptionsFragment( + Context context, Runnable nextCallback, Runnable cancelCallback, String channelString) { + super(R.layout.pwd_migration_warning_options); + mContext = context; + mNextCallback = nextCallback; + mCancelCallback = cancelCallback; + mChannelString = channelString; + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + RadioButtonWithDescription signInOrSyncButton = + view.findViewById(R.id.radio_sign_in_or_sync); + RadioButtonWithDescription passwordExportButton = + view.findViewById(R.id.radio_password_export); + Button nextButton = view.findViewById(R.id.password_migration_next_button); + Button cancelButton = view.findViewById(R.id.password_migration_cancel_button); + + signInOrSyncButton.setChecked(true); + passwordExportButton.setDescriptionText( + mContext.getString(R.string.password_migration_warning_password_export_subtitle) + .replace("%1$s", mChannelString)); + nextButton.setOnClickListener((unusedView) -> mNextCallback.run()); + cancelButton.setOnClickListener((unusedView) -> mCancelCallback.run()); + } +}
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningProperties.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningProperties.java index 7e9d2f90..9baf042 100644 --- a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningProperties.java +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningProperties.java
@@ -4,22 +4,44 @@ package org.chromium.chrome.browser.pwd_migration; +import androidx.annotation.IntDef; + import org.chromium.base.Callback; import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.modelutil.PropertyModel.ReadableObjectPropertyKey; +import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey; +import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * Properties defined here reflect the visible state of the local passwords migration warning. */ class PasswordMigrationWarningProperties { - static final PropertyModel.WritableBooleanPropertyKey VISIBLE = - new PropertyModel.WritableBooleanPropertyKey("visible"); - static final PropertyModel.ReadableObjectPropertyKey<Callback<Integer>> DISMISS_HANDLER = - new PropertyModel.ReadableObjectPropertyKey<>("dismiss_handler"); + /** + * The different screens that can be shown on the sheet. + */ + @IntDef({ScreenType.INTRO_SCREEN, ScreenType.OPTIONS_SCREEN}) + @Retention(RetentionPolicy.SOURCE) + public @interface ScreenType { + int INTRO_SCREEN = 0; + int OPTIONS_SCREEN = 1; + } - static PropertyModel createDefaultModel(Callback<Integer> dismissHandler) { - return new PropertyModel.Builder(VISIBLE, DISMISS_HANDLER) - .with(VISIBLE, false) + static final WritableBooleanPropertyKey VISIBLE = new WritableBooleanPropertyKey("visible"); + static final ReadableObjectPropertyKey<Callback<Integer>> DISMISS_HANDLER = + new ReadableObjectPropertyKey<>("dismiss_handler"); + static final ReadableObjectPropertyKey<PasswordMigrationWarningOnClickHandler> + ON_CLICK_HANDLER = new ReadableObjectPropertyKey<>("on_click_handler"); + public static final WritableIntPropertyKey CURRENT_SCREEN = + new WritableIntPropertyKey("current_screen"); + + static PropertyModel createDefaultModel(Callback<Integer> dismissHandler, + PasswordMigrationWarningOnClickHandler onClickHandler) { + return new PropertyModel.Builder(VISIBLE, DISMISS_HANDLER, ON_CLICK_HANDLER, CURRENT_SCREEN) .with(DISMISS_HANDLER, dismissHandler) + .with(ON_CLICK_HANDLER, onClickHandler) .build(); }
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningRenderTest.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningRenderTest.java index bf392bc..1e79378 100644 --- a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningRenderTest.java +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningRenderTest.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.pwd_migration; +import static org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.CURRENT_SCREEN; import static org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.VISIBLE; import static org.chromium.content_public.browser.test.util.TestThreadUtils.runOnUiThreadBlocking; import static org.chromium.ui.base.LocalizationUtils.setRtlForTesting; @@ -30,6 +31,7 @@ import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.night_mode.ChromeNightModeTestUtils; +import org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.ScreenType; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; @@ -57,6 +59,8 @@ @Mock private Callback<Integer> mDismissCallback; + @Mock + private PasswordMigrationWarningOnClickHandler mOnClickHandler; private BottomSheetController mBottomSheetController; private PasswordMigrationWarningView mView; @@ -67,7 +71,7 @@ @Rule public final ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus() - .setRevision(1) + .setRevision(2) .setBugComponent(Component.UI_BROWSER_AUTOFILL) .build(); @@ -86,7 +90,8 @@ .getRootUiCoordinatorForTesting() .getBottomSheetController(); runOnUiThreadBlocking(() -> { - mModel = PasswordMigrationWarningProperties.createDefaultModel(mDismissCallback); + mModel = PasswordMigrationWarningProperties.createDefaultModel( + mDismissCallback, mOnClickHandler); mView = new PasswordMigrationWarningView( mActivityTestRule.getActivity(), mBottomSheetController); PropertyModelChangeProcessor.create(mModel, mView, @@ -111,6 +116,7 @@ @MediumTest @Feature({"RenderTest"}) public void testShowsPasswordMigrationWwarningFirstPage() throws Exception { + runOnUiThreadBlocking(() -> mModel.set(CURRENT_SCREEN, ScreenType.INTRO_SCREEN)); runOnUiThreadBlocking(() -> mModel.set(VISIBLE, true)); BottomSheetTestSupport.waitForOpen(mBottomSheetController); @@ -119,4 +125,20 @@ mActivityTestRule.getActivity().findViewById(R.id.pwd_migration_warning_sheet); mRenderTestRule.render(bottomSheetView, "pwd_migration_warning_first_page"); } + + @Test + @MediumTest + @Feature({"RenderTest"}) + public void testShowsPasswordMigrationWarningSecondPageWithNoUserSignedIn() throws Exception { + runOnUiThreadBlocking(() -> mModel.set(CURRENT_SCREEN, ScreenType.OPTIONS_SCREEN)); + runOnUiThreadBlocking(() -> mModel.set(VISIBLE, true)); + + BottomSheetTestSupport.waitForOpen(mBottomSheetController); + + View bottomSheetView = + mActivityTestRule.getActivity().findViewById(R.id.pwd_migration_warning_sheet); + + mRenderTestRule.render( + bottomSheetView, "pwd_migration_warning_second_page_no_user_signed_in"); + } }
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningView.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningView.java index fb312989..b09b07c 100644 --- a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningView.java +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningView.java
@@ -17,10 +17,12 @@ import org.chromium.base.Callback; import org.chromium.chrome.browser.password_manager.PasswordManagerResourceProviderFactory; +import org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.ScreenType; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver; import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver; +import org.chromium.components.version_info.VersionInfo; /** * This class is responsible for rendering the bottom sheet that shows the passwords @@ -29,9 +31,10 @@ class PasswordMigrationWarningView implements BottomSheetContent { private final BottomSheetController mBottomSheetController; private Callback<Integer> mDismissHandler; + private PasswordMigrationWarningOnClickHandler mOnClickHandler; private FragmentManager mFragmentManager; - private PasswordMigrationWarningIntroFragment mIntroFragment; private final RelativeLayout mContentView; + private Context mContext; private final BottomSheetObserver mBottomSheetObserver = new EmptyBottomSheetObserver() { @Override @@ -53,6 +56,7 @@ }; PasswordMigrationWarningView(Context context, BottomSheetController bottomSheetController) { + mContext = context; mBottomSheetController = bottomSheetController; mContentView = (RelativeLayout) LayoutInflater.from(context).inflate( R.layout.pwd_migration_warning, null); @@ -60,15 +64,17 @@ mContentView.findViewById(R.id.touch_to_fill_sheet_header_image); sheetHeaderImage.setImageDrawable(AppCompatResources.getDrawable( context, PasswordManagerResourceProviderFactory.create().getPasswordManagerIcon())); - mFragmentManager = ((AppCompatActivity) context).getSupportFragmentManager(); - mIntroFragment = new PasswordMigrationWarningIntroFragment(context); } void setDismissHandler(Callback<Integer> dismissHandler) { mDismissHandler = dismissHandler; } + void setOnClickHandler(PasswordMigrationWarningOnClickHandler onClickHandler) { + mOnClickHandler = onClickHandler; + } + boolean setVisible(boolean isVisible) { if (!isVisible) { mBottomSheetController.hideContent(this, true); @@ -79,14 +85,47 @@ mBottomSheetController.removeObserver(mBottomSheetObserver); return false; } - mFragmentManager.beginTransaction() - .setReorderingAllowed(true) - .add(R.id.fragment_container_view, mIntroFragment, - "PasswordMigrationWarningFragment") - .commit(); return true; } + void setScreen(int screenType) { + if (screenType == ScreenType.INTRO_SCREEN) { + PasswordMigrationWarningIntroFragment introFragment = + new PasswordMigrationWarningIntroFragment(mContext, + () + -> mOnClickHandler.onAcknowledge(mBottomSheetController), + () -> mOnClickHandler.onMoreOptions(), getChannelString()); + mFragmentManager.beginTransaction() + .setReorderingAllowed(true) + .replace(R.id.fragment_container_view, introFragment) + .commit(); + } else if (screenType == ScreenType.OPTIONS_SCREEN) { + PasswordMigrationWarningOptionsFragment optionsFragment = + new PasswordMigrationWarningOptionsFragment(mContext, mOnClickHandler::onNext, + () + -> mOnClickHandler.onCancel(mBottomSheetController), + getChannelString()); + mFragmentManager.beginTransaction() + .setReorderingAllowed(true) + .replace(R.id.fragment_container_view, optionsFragment) + .commit(); + } + } + + private String getChannelString() { + if (VersionInfo.isCanaryBuild()) { + return "Canary"; + } + if (VersionInfo.isDevBuild()) { + return "Dev"; + } + if (VersionInfo.isBetaBuild()) { + return "Beta"; + } + assert !VersionInfo.isStableBuild(); + return ""; + } + @Nullable @Override public View getContentView() {
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningViewBinder.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningViewBinder.java index ba17aa65..7ed2a51 100644 --- a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningViewBinder.java +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningViewBinder.java
@@ -4,7 +4,9 @@ package org.chromium.chrome.browser.pwd_migration; +import static org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.CURRENT_SCREEN; import static org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.DISMISS_HANDLER; +import static org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.ON_CLICK_HANDLER; import static org.chromium.chrome.browser.pwd_migration.PasswordMigrationWarningProperties.VISIBLE; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; @@ -28,10 +30,15 @@ view.setDismissHandler(model.get(DISMISS_HANDLER)); } else if (propertyKey == VISIBLE) { boolean visibilityChangeSuccessful = view.setVisible(model.get(VISIBLE)); + // TODO(crbug.com/1446996): Move this logic out of the view binder. if (!visibilityChangeSuccessful && model.get(VISIBLE)) { assert model.get(DISMISS_HANDLER) != null; model.get(DISMISS_HANDLER).onResult(BottomSheetController.StateChangeReason.NONE); } + } else if (propertyKey == CURRENT_SCREEN) { + view.setScreen(model.get(CURRENT_SCREEN)); + } else if (propertyKey == ON_CLICK_HANDLER) { + view.setOnClickHandler(model.get(ON_CLICK_HANDLER)); } else { assert false : "Unhandled update to property:" + propertyKey; }
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningViewTest.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningViewTest.java index 66a8f12a..57272f2 100644 --- a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningViewTest.java +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningViewTest.java
@@ -49,6 +49,8 @@ @Mock private Callback<Integer> mDismissCallback; + @Mock + private PasswordMigrationWarningOnClickHandler mOnClickHandler; private BottomSheetController mBottomSheetController; private PasswordMigrationWarningView mView; @@ -62,7 +64,8 @@ .getRootUiCoordinatorForTesting() .getBottomSheetController(); runOnUiThreadBlocking(() -> { - mModel = PasswordMigrationWarningProperties.createDefaultModel(mDismissCallback); + mModel = PasswordMigrationWarningProperties.createDefaultModel( + mDismissCallback, mOnClickHandler); mView = new PasswordMigrationWarningView( mActivityTestRule.getActivity(), mBottomSheetController); PropertyModelChangeProcessor.create(mModel, mView,
diff --git a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.cc b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.cc index e543a12..e027a20 100644 --- a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.cc +++ b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.cc
@@ -48,7 +48,6 @@ ProfileSelections::Builder() .WithRegular(ProfileSelection::kOwnInstance) .WithGuest(ProfileSelection::kOwnInstance) - .WithSystem(ProfileSelection::kOwnInstance) .Build()) { DependsOn(HistoryServiceFactory::GetInstance()); }
diff --git a/chrome/browser/profiles/profile_keyed_service_browsertest.cc b/chrome/browser/profiles/profile_keyed_service_browsertest.cc index f75bd2a6..f2e9d01 100644 --- a/chrome/browser/profiles/profile_keyed_service_browsertest.cc +++ b/chrome/browser/profiles/profile_keyed_service_browsertest.cc
@@ -172,13 +172,6 @@ IN_PROC_BROWSER_TEST_F(ProfileKeyedServiceBrowserTest, SystemProfileOTR_NeededServices) { - // clang-format off - // List of services expected to be created for the System OTR Profile. - std::set<std::string> system_otr_active_services { - "SiteDataCacheFacadeFactory" - }; - // clang-format on - Profile* system_profile = CreateProfileAndWaitForAllTasks(ProfileManager::GetSystemProfilePath()); ASSERT_TRUE(system_profile->HasAnyOffTheRecordProfile()); @@ -186,23 +179,17 @@ ASSERT_TRUE(system_profile_otr->IsOffTheRecord()); ASSERT_TRUE(system_profile_otr->IsSystemProfile()); TestKeyedProfileServicesActives(system_profile_otr, - system_otr_active_services); + /*expected_active_services_names=*/{}); } IN_PROC_BROWSER_TEST_F(ProfileKeyedServiceBrowserTest, SystemProfileParent_NeededServices) { - // clang-format off - // List of services expected to be created for the Parent System Profile. - std::set<std::string> system_active_services { - "SiteDataCacheFacadeFactory" - }; - // clang-format on - Profile* system_profile = CreateProfileAndWaitForAllTasks(ProfileManager::GetSystemProfilePath()); ASSERT_FALSE(system_profile->IsOffTheRecord()); ASSERT_TRUE(system_profile->IsSystemProfile()); - TestKeyedProfileServicesActives(system_profile, system_active_services); + TestKeyedProfileServicesActives(system_profile, + /*expected_active_services_names=*/{}); } IN_PROC_BROWSER_TEST_F(ProfileKeyedServiceBrowserTest,
diff --git a/chrome/browser/resources/password_manager/password_details_section.html b/chrome/browser/resources/password_manager/password_details_section.html index 1fdcf92..ce4713d3 100644 --- a/chrome/browser/resources/password_manager/password_details_section.html +++ b/chrome/browser/resources/password_manager/password_details_section.html
@@ -15,6 +15,10 @@ --site-favicon-height: 20px; --site-favicon-width: 20px; } + + #title { + line-height: normal; + } </style> <div id="header"> <cr-icon-button class="icon-arrow-back" id="backButton"
diff --git a/chrome/browser/sync/sync_ui_util.cc b/chrome/browser/sync/sync_ui_util.cc index 4996864..d9ea0b4f6 100644 --- a/chrome/browser/sync/sync_ui_util.cc +++ b/chrome/browser/sync/sync_ui_util.cc
@@ -352,17 +352,17 @@ return true; } - // If sync is running in transport-only mode, every type is "preferred", so - // IsTrustedVaultKeyRequiredForPreferredDataTypes() could return true even if - // the user isn't trying to sync any of the encrypted types. The check below - // tries to avoid showing an unexpected "You couldn't sync X" error in that - // case. It works fine if IsEncryptEverythingEnabled() is false, since - // PASSWORDS is the only one of AlwaysEncryptedUserTypes() currently - // supporting transport mode. Otherwise, it should really be OR-ed with other - // checks. - // TODO(crbug.com/1134090): Fix the definition of preferred types for - // transport mode so calling IsTrustedVaultKeyRequiredForPreferredDataTypes() - // is enough. + // On desktop transport mode, IsTrustedVaultKeyRequiredForPreferredDataTypes() + // returns true even if the user isn't trying to sync any of the encrypted + // types. The check below tries to avoid showing an unexpected "You couldn't + // sync X" error in that case. It works fine if IsEncryptEverythingEnabled() + // is false, since PASSWORDS is the only one of AlwaysEncryptedUserTypes() + // currently supporting transport mode. Otherwise, it should really be OR-ed + // with other checks. + // TODO(crbug.com/1447083): Once the Desktop precondition for + // EnablePasswordsAccountStorage becomes "PASSWORDS is a selected type", and + // not a PreconditionState of the controller, this function can be replaced + // with a single IsTrustedVaultKeyRequiredForPreferredDataTypes() check. // // WARNING: Must match CredentialModelTypeController::GetPreconditionState(). return password_manager::features_util::IsOptedInForAccountStorage( @@ -381,16 +381,16 @@ return true; } - // In transport-only mode, IsTrustedVaultRecoverabilityDegraded() returns true - // even if the user isn't trying to sync any of the encrypted types. The check - // below tries to avoid unnecessarily showing the error in that case. It works - // fine if IsEncryptEverythingEnabled() is false, since PASSWORDS is the only - // one of AlwaysEncryptedUserTypes() currently supporting transport mode. + // On desktop transport mode, IsTrustedVaultRecoverabilityDegraded() returns + // true even if the user isn't trying to sync any of the encrypted types. The + // check below tries to avoid unnecessarily showing the error in that case. It + // works fine if IsEncryptEverythingEnabled() is false, since PASSWORDS is the + // only one of AlwaysEncryptedUserTypes() currently supporting transport mode. // Otherwise, it should really be OR-ed with other checks. - // TODO(crbug.com/1134090): Fix the definition of preferred types for - // transport mode so calling IsTrustedVaultRecoverabilityDegraded() is enough - // (SyncUserSettingsImpl::IsEncryptedDatatypeEnabled() relies on the preferred - // types). + // TODO(crbug.com/1447083): Once the Desktop precondition for + // EnablePasswordsAccountStorage becomes "PASSWORDS is a selected type", and + // not a PreconditionState of the controller, this function can be replaced + // with a single IsTrustedVaultRecoverabilityDegraded() check. // // WARNING: Must match CredentialModelTypeController::GetPreconditionState(). return password_manager::features_util::IsOptedInForAccountStorage(
diff --git a/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_mac.cc b/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_mac.cc index a5e629848..4b30dbf 100644 --- a/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_mac.cc +++ b/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_mac.cc
@@ -41,26 +41,6 @@ IN_PROC_BROWSER_TEST_F( WebAppIntegration, - WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_28_40Client2_46Standalone_1Standalone_24) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); - helper_.CheckWindowCreated(); - helper_.CheckAppInListWindowed(Site::kStandalone); - helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); - helper_.CheckWindowControlsOverlayToggle(Site::kStandalone, - IsShown::kNotShown); - helper_.ClosePwa(); - helper_.SwitchProfileClients(ProfileClient::kClient2); - helper_.InstallLocally(Site::kStandalone); - helper_.LaunchFromPlatformShortcut(Site::kStandalone); - helper_.CheckWindowCreated(); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, WAI_31Standalone_24_12Standalone_7Standalone_112StandaloneNotShown_40Client2_45Standalone_46Standalone_7Standalone_12Standalone_1Standalone_127) { // Test contents are generated by script. Please do not modify! // See `docs/webapps/why-is-this-test-failing.md` or @@ -143,5 +123,27 @@ helper_.CheckWindowCreated(); } +IN_PROC_BROWSER_TEST_F( + WebAppIntegration, + WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_28_12Standalone_7Standalone_40Client2_46Standalone_1Standalone_24) { + // Test contents are generated by script. Please do not modify! + // See `docs/webapps/why-is-this-test-failing.md` or + // `docs/webapps/integration-testing-framework` for more info. + // Sheriffs: Disabling this test is supported. + helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); + helper_.CheckWindowCreated(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.CheckWindowControlsOverlayToggle(Site::kStandalone, + IsShown::kNotShown); + helper_.ClosePwa(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.SwitchProfileClients(ProfileClient::kClient2); + helper_.InstallLocally(Site::kStandalone); + helper_.LaunchFromPlatformShortcut(Site::kStandalone); + helper_.CheckWindowCreated(); +} + } // namespace } // namespace web_app::integration_tests
diff --git a/chrome/browser/touch_to_fill/payments/DIR_METADATA b/chrome/browser/touch_to_fill/payments/DIR_METADATA index 110957a..d9bf029 100644 --- a/chrome/browser/touch_to_fill/payments/DIR_METADATA +++ b/chrome/browser/touch_to_fill/payments/DIR_METADATA
@@ -1,3 +1,3 @@ monorail: { - component: "UI>Browser>Autofill>UI" + component: "UI>Browser>Autofill>Payments" }
diff --git a/chrome/browser/ui/DEPS b/chrome/browser/ui/DEPS index b56a704e..a9e4f632 100644 --- a/chrome/browser/ui/DEPS +++ b/chrome/browser/ui/DEPS
@@ -63,4 +63,7 @@ "signin_intercept_first_run_experience_dialog_browsertest.cc": [ "+chrome/browser/ui/views/profiles/avatar_toolbar_button.h", ], + "save_update_address_profile_bubble_controller_impl_interactive_uitest.cc": [ + "+chrome/browser/ui/views/autofill" + ] }
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index b05b731a..f3aba28c 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -747,7 +747,24 @@ <message name="IDS_PASSWORD_MIGRATION_WARNING_OTHER_OPTIONS" desc="The text on the button that leads to other options in the password migration warning sheet."> Other options </message> - + <message name="IDS_PASSWORD_MIGRATION_WARNING_TURN_ON_SYNC" desc="The text that describes the option to start syncing that is offered in the password migration warning sheet."> + Save the passwords on this device in your Google Account by turning on sync + </message> + <message name="IDS_PASSWORD_MIGRATION_WARNING_TURN_ON_SYNC_SUBTITLE" desc="The subtitle that appears under the option to turn on sync in the password migration warning sheet if the user is not signed in."> + You’ll be asked to sign in to your Google Account + </message> + <message name="IDS_PASSWORD_MIGRATION_WARNING_PASSWORD_EXPORT" desc="The text that describes the option to export the passwords that is offered in the password migration warning sheet."> + Export & delete passwords saved to this device + </message> + <message name="IDS_PASSWORD_MIGRATION_WARNING_PASSWORD_EXPORT_SUBTITLE" desc="The subtitle that explaint the password export option in the password migration warning sheet."> + All passwords will be downloaded on your device and removed from Chrome <ph name="CHROME_CHANNEL">%1$s<ex>Dev</ex></ph> + </message> + <message name="IDS_PASSWORD_MIGRATION_WARNING_NEXT" desc="The text for the next button in the password migration warning sheet. It starts one of the flows offered on the sheet."> + Next + </message> + <message name="IDS_PASSWORD_MIGRATION_WARNING_CANCEL" desc="The text for the cancel button in the password migration warning sheet. It closes the sheet"> + Cancel + </message> <!-- Lock Screen Fragment --> <message name="IDS_LOCKSCREEN_DESCRIPTION_COPY" desc="When a user attempts to copy a password for a particular website into clipboard in Chrome's settings, Chrome launches a lock screen to verify the user's identity and displays the following explanation."> @@ -1963,30 +1980,6 @@ </message> <!-- Child accounts --> - <message name="IDS_ACCOUNT_MANAGEMENT_PARENTAL_SETTINGS" desc="Title of parental settings section of account page for child account."> - Parental Settings - </message> - <message name="IDS_ACCOUNT_MANAGEMENT_NO_PARENTAL_DATA" desc="String saying that we are waiting for family information."> - Waiting for details of parents. - </message> - <message name="IDS_ACCOUNT_MANAGEMENT_ONE_PARENT_NAME" desc="String for name of single parent for child account."> - This browser is managed by <ph name="PARENT_NAME">%1$s<ex>parent1@gmail.com</ex></ph>. - </message> - <message name="IDS_ACCOUNT_MANAGEMENT_TWO_PARENT_NAMES" desc="String for names of two parents for child account."> - This browser is managed by <ph name="PARENT_NAME_1">%1$s<ex>parent1@gmail.com</ex></ph> and <ph name="PARENT_NAME_2">%2$s<ex>parent2@gmail.com</ex></ph>. - </message> - <message name="IDS_ACCOUNT_MANAGEMENT_CHILD_CONTENT_TITLE" desc="Title of the Content setting, which controls which websites a child is allowed to visit."> - Content - </message> - <message name="IDS_ACCOUNT_MANAGEMENT_CHILD_CONTENT_APPROVED" desc="Setting that permits child accounts to visit only sites approved by their parents."> - Only allow certain sites - </message> - <message name="IDS_ACCOUNT_MANAGEMENT_CHILD_CONTENT_FILTER_MATURE" desc="Setting that permits child accounts to visit any websites that don't have mature contents. As the filter is not perfect, the browser can only attempt to block these sites."> - Try to block mature sites - </message> - <message name="IDS_ACCOUNT_MANAGEMENT_CHILD_CONTENT_ALL" desc="Setting that permits child accounts to visit any websites."> - Allow all sites - </message> <message name="IDS_ACCOUNT_MANAGEMENT_HEADER_NO_PARENTAL_DATA" desc="String saying that child should go to parent for help for child account."> If you need help, ask your parent </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCOUNT_MANAGEMENT_ONE_PARENT_NAME.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCOUNT_MANAGEMENT_ONE_PARENT_NAME.png.sha1 deleted file mode 100644 index 65262e2..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCOUNT_MANAGEMENT_ONE_PARENT_NAME.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -4b08d2bcd2cf01c731b627606f9a61a493a6e510 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCOUNT_MANAGEMENT_TWO_PARENT_NAMES.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCOUNT_MANAGEMENT_TWO_PARENT_NAMES.png.sha1 deleted file mode 100644 index 45327087f..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCOUNT_MANAGEMENT_TWO_PARENT_NAMES.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -34718a5428024af7781bac690b64386af9b19ec0 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_CANCEL.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_CANCEL.png.sha1 new file mode 100644 index 0000000..9b9ac1e --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_CANCEL.png.sha1
@@ -0,0 +1 @@ +d45ee4610ee415649d0636e8f6cc38a5feacc2b0 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_NEXT.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_NEXT.png.sha1 new file mode 100644 index 0000000..9b9ac1e --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_NEXT.png.sha1
@@ -0,0 +1 @@ +d45ee4610ee415649d0636e8f6cc38a5feacc2b0 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_PASSWORD_EXPORT.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_PASSWORD_EXPORT.png.sha1 new file mode 100644 index 0000000..9b9ac1e --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_PASSWORD_EXPORT.png.sha1
@@ -0,0 +1 @@ +d45ee4610ee415649d0636e8f6cc38a5feacc2b0 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_PASSWORD_EXPORT_SUBTITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_PASSWORD_EXPORT_SUBTITLE.png.sha1 new file mode 100644 index 0000000..9b9ac1e --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_PASSWORD_EXPORT_SUBTITLE.png.sha1
@@ -0,0 +1 @@ +d45ee4610ee415649d0636e8f6cc38a5feacc2b0 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_TURN_ON_SYNC.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_TURN_ON_SYNC.png.sha1 new file mode 100644 index 0000000..9b9ac1e --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_TURN_ON_SYNC.png.sha1
@@ -0,0 +1 @@ +d45ee4610ee415649d0636e8f6cc38a5feacc2b0 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_TURN_ON_SYNC_SUBTITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_TURN_ON_SYNC_SUBTITLE.png.sha1 new file mode 100644 index 0000000..9b9ac1e --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PASSWORD_MIGRATION_WARNING_TURN_ON_SYNC_SUBTITLE.png.sha1
@@ -0,0 +1 @@ +d45ee4610ee415649d0636e8f6cc38a5feacc2b0 \ No newline at end of file
diff --git a/chrome/browser/ui/autofill/DIR_METADATA b/chrome/browser/ui/autofill/DIR_METADATA index 8dc897c..b597ffd 100644 --- a/chrome/browser/ui/autofill/DIR_METADATA +++ b/chrome/browser/ui/autofill/DIR_METADATA
@@ -1,3 +1,3 @@ monorail { - component: "UI>Browser>Autofill>UI" + component: "UI>Browser>Autofill" }
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc index 23b20e76..7379ddf 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc +++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -397,7 +397,9 @@ std::u16string* body) { return delegate_->GetDeletionConfirmationText( suggestions_[list_index].main_text.value, - suggestions_[list_index].frontend_id, title, body); + suggestions_[list_index].frontend_id, + suggestions_[list_index].GetPayload<Suggestion::BackendId>(), title, + body); } bool AutofillPopupControllerImpl::RemoveSuggestion(int list_index) { @@ -411,8 +413,10 @@ // TODO(crbug.com/1209792): Replace these checks with a stronger identifier. if (list_index < 0 || static_cast<size_t>(list_index) >= suggestions_.size()) return false; - if (!delegate_->RemoveSuggestion(suggestions_[list_index].main_text.value, - suggestions_[list_index].frontend_id)) { + if (!delegate_->RemoveSuggestion( + suggestions_[list_index].main_text.value, + suggestions_[list_index].frontend_id, + suggestions_[list_index].GetPayload<Suggestion::BackendId>())) { return false; }
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc index 34d8211..1db8b780 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc +++ b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
@@ -110,7 +110,8 @@ Suggestion::FrontendId frontend_id, const Suggestion::BackendId& backend_id) override {} bool RemoveSuggestion(const std::u16string& value, - Suggestion::FrontendId frontend_id) override { + Suggestion::FrontendId frontend_id, + Suggestion::BackendId backend_id) override { return true; } base::WeakPtr<AutofillExternalDelegate> GetWeakPtr() {
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc index ef184707..36ebcfa 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -386,8 +386,6 @@ AutofillDriver* driver) { auto* cad = static_cast<ContentAutofillDriver*>(driver); content::RenderFrameHost* rfh = cad->render_frame_host(); - if (!rfh) - return nullptr; #if BUILDFLAG(IS_ANDROID) return std::make_unique<InternalAuthenticatorAndroid>(rfh); #else
diff --git a/chrome/browser/ui/autofill/payments/DIR_METADATA b/chrome/browser/ui/autofill/payments/DIR_METADATA new file mode 100644 index 0000000..d9bf029 --- /dev/null +++ b/chrome/browser/ui/autofill/payments/DIR_METADATA
@@ -0,0 +1,3 @@ +monorail: { + component: "UI>Browser>Autofill>Payments" +}
diff --git a/chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl_browsertest.cc b/chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl_browsertest.cc deleted file mode 100644 index 5bbd78b..0000000 --- a/chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl_browsertest.cc +++ /dev/null
@@ -1,78 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl.h" - -#include "base/functional/callback_helpers.h" -#include "base/memory/raw_ptr.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/test/test_browser_dialog.h" -#include "components/autofill/content/browser/content_autofill_client.h" -#include "components/autofill/core/browser/autofill_client.h" -#include "components/autofill/core/browser/autofill_test_utils.h" -#include "components/autofill/core/common/autofill_features.h" -#include "content/public/test/browser_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace autofill { - -class SaveUpdateAddressProfileBubbleControllerImplTest - : public DialogBrowserTest { - public: - SaveUpdateAddressProfileBubbleControllerImplTest() = default; - - void SetUpCommandLine(base::CommandLine* command_line) override { - DialogBrowserTest::SetUpCommandLine(command_line); - } - - // DialogBrowserTest: - void ShowUi(const std::string& name) override { - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - autofill::ContentAutofillClient* autofill_client = - autofill::ContentAutofillClient::FromWebContents(web_contents); - AutofillProfile profile = test::GetFullProfile(); - AutofillProfile* original_profile = (name == "Update") ? &profile : nullptr; - autofill_client->ConfirmSaveAddressProfile( - profile, original_profile, - AutofillClient::SaveAddressProfilePromptOptions{.show_prompt = true}, - base::DoNothing()); - DCHECK(controller()); - } - - SaveUpdateAddressProfileBubbleControllerImpl* controller() { - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - DCHECK(web_contents); - return SaveUpdateAddressProfileBubbleControllerImpl::FromWebContents( - web_contents); - } -}; - -IN_PROC_BROWSER_TEST_F(SaveUpdateAddressProfileBubbleControllerImplTest, - InvokeUi_Save) { - ShowAndVerifyUi(); -} - -IN_PROC_BROWSER_TEST_F(SaveUpdateAddressProfileBubbleControllerImplTest, - InvokeUi_Update) { - ShowAndVerifyUi(); -} - -IN_PROC_BROWSER_TEST_F(SaveUpdateAddressProfileBubbleControllerImplTest, - InvokeUi_SaveCloseThenReopen) { - ShowAndVerifyUi(); - controller()->OnBubbleClosed(); - ShowAndVerifyUi(); -} - -IN_PROC_BROWSER_TEST_F(SaveUpdateAddressProfileBubbleControllerImplTest, - CloseTabWhileBubbleIsOpen) { - ShowAndVerifyUi(); - content::WebContents* tab = - browser()->tab_strip_model()->GetActiveWebContents(); - tab->Close(); -} - -} // namespace autofill
diff --git a/chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl_interactive_uitest.cc b/chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl_interactive_uitest.cc new file mode 100644 index 0000000..29f8f59 --- /dev/null +++ b/chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl_interactive_uitest.cc
@@ -0,0 +1,277 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl.h" + +#include "base/functional/bind.h" +#include "chrome/browser/ui/views/autofill/edit_address_profile_view.h" +#include "chrome/browser/ui/views/autofill/save_address_profile_view.h" +#include "chrome/browser/ui/views/autofill/update_address_profile_view.h" +#include "chrome/test/interaction/interactive_browser_test.h" +#include "components/autofill/content/browser/content_autofill_client.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/data_model/autofill_profile.h" +#include "content/public/test/browser_test.h" +#include "ui/base/interaction/element_identifier.h" +#include "ui/views/bubble/bubble_frame_view.h" +#include "ui/views/window/dialog_client_view.h" + +namespace autofill { + +constexpr char kSuppressedScreenshotError[] = + "Screenshot can only run in pixel_tests on Windows."; + +class BaseSaveUpdateAddressProfileBubbleControllerImplTest + : public InteractiveBrowserTest { + protected: + autofill::ContentAutofillClient* autofill_client() { + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + return autofill::ContentAutofillClient::FromWebContents(web_contents); + } + + virtual void TriggerBubble() = 0; + + InteractiveTestApi::StepBuilder ShowInitBubble() { + return Do([this]() { + user_decision_ = + AutofillClient::SaveAddressProfileOfferUserDecision::kUndefined; + TriggerBubble(); + }); + } + + InteractiveTestApi::StepBuilder EnsureClosedWithDecision( + AutofillClient::SaveAddressProfileOfferUserDecision + expected_user_decision) { + return Do([this, expected_user_decision]() { + ASSERT_EQ(expected_user_decision, user_decision_); + }); + } + + void OnUserDecision( + AutofillClient::SaveAddressProfileOfferUserDecision decision, + AutofillProfile profile) { + user_decision_ = decision; + } + + private: + // The latest user decisive interaction with a popup, e.g. Save/Update + // or Cancel the prompt, it is set in the AddressProfileSavePromptCallback + // passed to the prompt. + AutofillClient::SaveAddressProfileOfferUserDecision user_decision_; +}; + +/////////////////////////////////////////////////////////////////////////////// +// SaveAddressProfileTest + +class SaveAddressProfileTest + : public BaseSaveUpdateAddressProfileBubbleControllerImplTest { + void TriggerBubble() override { + autofill_client()->ConfirmSaveAddressProfile( + test::GetFullProfile(), nullptr, + AutofillClient::SaveAddressProfilePromptOptions{.show_prompt = true}, + base::BindOnce(&SaveAddressProfileTest::OnUserDecision, + base::Unretained(this))); + } +}; + +IN_PROC_BROWSER_TEST_F(SaveAddressProfileTest, SaveAccept) { + RunTestSequence( + ShowInitBubble(), + PressButton(views::DialogClientView::kOkButtonElementId), + EnsureClosedWithDecision( + AutofillClient::SaveAddressProfileOfferUserDecision::kAccepted)); +} + +IN_PROC_BROWSER_TEST_F(SaveAddressProfileTest, SaveDecline) { + RunTestSequence( + ShowInitBubble(), + PressButton(views::DialogClientView::kCancelButtonElementId), + EnsureClosedWithDecision( + AutofillClient::SaveAddressProfileOfferUserDecision::kDeclined)); +} + +IN_PROC_BROWSER_TEST_F(SaveAddressProfileTest, SaveWithEdit) { + RunTestSequence( + ShowInitBubble(), + SetOnIncompatibleAction(OnIncompatibleAction::kIgnoreAndContinue, + kSuppressedScreenshotError), + Screenshot(SaveAddressProfileView::kTopViewId, "save_popup", "4535916"), + PressButton(SaveAddressProfileView::kEditButtonViewId), + + // The editor popup resides in a different context on MacOS. + InAnyContext( + Steps(WaitForShow(EditAddressProfileView::kTopViewId), + Screenshot(EditAddressProfileView::kTopViewId, "edit_popup", + "4535916"), + PressButton(views::DialogClientView::kCancelButtonElementId))), + + WaitForShow(SaveAddressProfileView::kTopViewId), + PressButton(views::DialogClientView::kOkButtonElementId), + WaitForHide(SaveAddressProfileView::kTopViewId), + EnsureClosedWithDecision( + AutofillClient::SaveAddressProfileOfferUserDecision::kAccepted)); +} + +IN_PROC_BROWSER_TEST_F(SaveAddressProfileTest, SaveInEdit) { + RunTestSequence( + SetOnIncompatibleAction(OnIncompatibleAction::kIgnoreAndContinue, + kSuppressedScreenshotError), + ShowInitBubble(), PressButton(SaveAddressProfileView::kEditButtonViewId), + + InAnyContext( + Steps(WaitForShow(EditAddressProfileView::kTopViewId), + PressButton(views::DialogClientView::kOkButtonElementId))), + + EnsureClosedWithDecision( + AutofillClient::SaveAddressProfileOfferUserDecision::kEditAccepted)); +} + +IN_PROC_BROWSER_TEST_F(SaveAddressProfileTest, SaveCloseAndOpenAgain) { + RunTestSequence( + ShowInitBubble(), + SetOnIncompatibleAction(OnIncompatibleAction::kIgnoreAndContinue, + kSuppressedScreenshotError), + Screenshot(SaveAddressProfileView::kTopViewId, "save_popup", "4535916"), + + PressButton(views::BubbleFrameView::kCloseButtonElementId), + // Make sure the popup gets closed before subsequent reopening. + EnsureNotPresent(SaveAddressProfileView::kTopViewId), + + ShowInitBubble(), + Screenshot(SaveAddressProfileView::kTopViewId, "reopened_save_popup", + "4535916")); +} + +IN_PROC_BROWSER_TEST_F(SaveAddressProfileTest, NoCrashesOnTabClose) { + RunTestSequence( + ShowInitBubble(), EnsurePresent(SaveAddressProfileView::kTopViewId), + Do([this]() { + browser()->tab_strip_model()->GetActiveWebContents()->Close(); + })); +} + +/////////////////////////////////////////////////////////////////////////////// +// UpdateAddressProfileTest + +class UpdateAddressProfileTest + : public BaseSaveUpdateAddressProfileBubbleControllerImplTest { + protected: + void TriggerBubble() override { + autofill_client()->ConfirmSaveAddressProfile( + test::GetFullProfile(), &original_profile_, + AutofillClient::SaveAddressProfilePromptOptions{.show_prompt = true}, + base::BindOnce(&UpdateAddressProfileTest::OnUserDecision, + base::Unretained(this))); + } + + AutofillProfile original_profile_ = test::GetFullProfile2(); +}; + +IN_PROC_BROWSER_TEST_F(UpdateAddressProfileTest, UpdateThroughEdit) { + RunTestSequence( + ShowInitBubble(), + SetOnIncompatibleAction(OnIncompatibleAction::kIgnoreAndContinue, + kSuppressedScreenshotError), + Screenshot(UpdateAddressProfileView::kTopViewId, "update_popup", + "4535916"), + PressButton(UpdateAddressProfileView::kEditButtonViewId), + + // The editor popup resides in a different context on MacOS. + InAnyContext( + Steps(WaitForShow(EditAddressProfileView::kTopViewId), + Screenshot(EditAddressProfileView::kTopViewId, "edit_popup", + "4535916"), + PressButton(views::DialogClientView::kCancelButtonElementId))), + + WaitForShow(UpdateAddressProfileView::kTopViewId), + PressButton(views::DialogClientView::kOkButtonElementId), + WaitForHide(UpdateAddressProfileView::kTopViewId), + EnsureClosedWithDecision( + AutofillClient::SaveAddressProfileOfferUserDecision::kAccepted)); +} + +/////////////////////////////////////////////////////////////////////////////// +// UpdateAccountAddressProfileTest + +class UpdateAccountAddressProfileTest : public UpdateAddressProfileTest { + void TriggerBubble() override { + original_profile_.set_source_for_testing(AutofillProfile::Source::kAccount); + autofill_client()->ConfirmSaveAddressProfile( + test::GetFullProfile(), &original_profile_, + AutofillClient::SaveAddressProfilePromptOptions{.show_prompt = true}, + base::BindOnce(&UpdateAccountAddressProfileTest::OnUserDecision, + base::Unretained(this))); + } +}; + +IN_PROC_BROWSER_TEST_F(UpdateAccountAddressProfileTest, UpdateThroughEdit) { + RunTestSequence( + ShowInitBubble(), + SetOnIncompatibleAction(OnIncompatibleAction::kIgnoreAndContinue, + kSuppressedScreenshotError), + Screenshot(UpdateAddressProfileView::kTopViewId, "update_popup", + "4535916"), + PressButton(UpdateAddressProfileView::kEditButtonViewId), + + // The editor popup resides in a different context on MacOS. + InAnyContext( + Steps(WaitForShow(EditAddressProfileView::kTopViewId), + Screenshot(EditAddressProfileView::kTopViewId, "edit_popup", + "4535916"), + PressButton(views::DialogClientView::kCancelButtonElementId))), + + WaitForShow(UpdateAddressProfileView::kTopViewId), + PressButton(views::DialogClientView::kOkButtonElementId), + WaitForHide(UpdateAddressProfileView::kTopViewId), + EnsureClosedWithDecision( + AutofillClient::SaveAddressProfileOfferUserDecision::kAccepted)); +} + +/////////////////////////////////////////////////////////////////////////////// +// SaveAddressProfileTest + +class MigrateToProfileAddressProfileTest + : public BaseSaveUpdateAddressProfileBubbleControllerImplTest { + void TriggerBubble() override { + autofill_client()->ConfirmSaveAddressProfile( + test::GetFullProfile(), nullptr, + AutofillClient::SaveAddressProfilePromptOptions{ + .show_prompt = true, .is_migration_to_account = true}, + base::BindOnce(&MigrateToProfileAddressProfileTest::OnUserDecision, + base::Unretained(this))); + } +}; + +IN_PROC_BROWSER_TEST_F(MigrateToProfileAddressProfileTest, SaveDecline) { + RunTestSequence( + ShowInitBubble(), + PressButton(views::DialogClientView::kCancelButtonElementId), + EnsureClosedWithDecision( + AutofillClient::SaveAddressProfileOfferUserDecision::kNever)); +} + +IN_PROC_BROWSER_TEST_F(MigrateToProfileAddressProfileTest, SaveWithEdit) { + RunTestSequence( + ShowInitBubble(), + SetOnIncompatibleAction(OnIncompatibleAction::kIgnoreAndContinue, + kSuppressedScreenshotError), + Screenshot(SaveAddressProfileView::kTopViewId, "save_popup", "4535916"), + PressButton(SaveAddressProfileView::kEditButtonViewId), + + // The editor popup resides in a different context on MacOS. + InAnyContext( + Steps(WaitForShow(EditAddressProfileView::kTopViewId), + Screenshot(EditAddressProfileView::kTopViewId, "edit_popup", + "4535916"), + PressButton(views::DialogClientView::kCancelButtonElementId))), + + WaitForShow(SaveAddressProfileView::kTopViewId), + PressButton(views::DialogClientView::kOkButtonElementId), + WaitForHide(SaveAddressProfileView::kTopViewId), + EnsureClosedWithDecision( + AutofillClient::SaveAddressProfileOfferUserDecision::kAccepted)); +} + +} // namespace autofill
diff --git a/chrome/browser/ui/browser_list.cc b/chrome/browser/ui/browser_list.cc index c16e80d..ad1fe8c9 100644 --- a/chrome/browser/ui/browser_list.cc +++ b/chrome/browser/ui/browser_list.cc
@@ -54,7 +54,8 @@ } // namespace // static -base::LazyInstance<base::ObserverList<BrowserListObserver>>::Leaky +base::LazyInstance<base::ObserverList<BrowserListObserver>, + BrowserList::ObserverListTraits> BrowserList::observers_ = LAZY_INSTANCE_INITIALIZER; // static
diff --git a/chrome/browser/ui/browser_list.h b/chrome/browser/ui/browser_list.h index 9f1e9b5..75b0d49 100644 --- a/chrome/browser/ui/browser_list.h +++ b/chrome/browser/ui/browser_list.h
@@ -218,9 +218,21 @@ // A vector of the browsers that are currently in the closing state. BrowserSet currently_closing_browsers_; + // If an observer is added while iterating over them and notifying, it should + // not be notified as it probably already saw the Browser* being added/removed + // in the BrowserList. + struct ObserverListTraits : base::internal::LeakyLazyInstanceTraits< + base::ObserverList<BrowserListObserver>> { + static base::ObserverList<BrowserListObserver>* New(void* instance) { + return new (instance) base::ObserverList<BrowserListObserver>( + base::ObserverListPolicy::EXISTING_ONLY); + } + }; + // A list of observers which will be notified of every browser addition and // removal across all BrowserLists. - static base::LazyInstance<base::ObserverList<BrowserListObserver>>::Leaky + static base::LazyInstance<base::ObserverList<BrowserListObserver>, + ObserverListTraits> observers_; static BrowserList* instance_;
diff --git a/chrome/browser/ui/browser_list_unittest.cc b/chrome/browser/ui/browser_list_unittest.cc index bc463b7..07f0906 100644 --- a/chrome/browser/ui/browser_list_unittest.cc +++ b/chrome/browser/ui/browser_list_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/browser_list.h" #include <memory> +#include <set> #include "chrome/browser/ui/browser_finder.h" #include "chrome/test/base/browser_with_test_window_test.h" @@ -74,3 +75,85 @@ result = chrome::FindBrowserWithUiElementContext(ui::ElementContext(100)); EXPECT_EQ(nullptr, result); } + +// Class that tries to observe all pre-existing and newly created browsers. +// Ensures that for each browser there is a single OnBrowserAdded/Removed call +// or it already existed in BrowserList. +class BrowserObserverChild : public BrowserListObserver, TabStripModelObserver { + public: + explicit BrowserObserverChild(Browser* created_for_browser) + : created_for_browser_(created_for_browser) { + BrowserList* browser_list = BrowserList::GetInstance(); + for (Browser* browser : *browser_list) { + EXPECT_FALSE(base::Contains(observed_browsers_, browser)); + observed_browsers_.insert(browser); + browser->tab_strip_model()->AddObserver(this); + } + EXPECT_TRUE(base::Contains(observed_browsers_, created_for_browser_)); + browser_list->AddObserver(this); + } + + ~BrowserObserverChild() override { + BrowserList* browser_list = BrowserList::GetInstance(); + for (Browser* browser : *browser_list) { + EXPECT_TRUE(base::Contains(observed_browsers_, browser)); + observed_browsers_.erase(browser); + browser->tab_strip_model()->RemoveObserver(this); + } + browser_list->RemoveObserver(this); + } + + void OnBrowserAdded(Browser* browser) override { + EXPECT_NE(browser, created_for_browser_); + EXPECT_FALSE(base::Contains(observed_browsers_, browser)); + observed_browsers_.insert(browser); + browser->tab_strip_model()->AddObserver(this); + } + + void OnBrowserRemoved(Browser* browser) override { + browser->tab_strip_model()->RemoveObserver(this); + EXPECT_TRUE(base::Contains(observed_browsers_, browser)); + observed_browsers_.erase(browser); + } + + private: + std::set<Browser*> observed_browsers_; + raw_ptr<Browser> created_for_browser_; +}; + +// Class that creates BrowserObserverChild when a Browser is created; +class BrowserObserverParent : public BrowserListObserver { + public: + BrowserObserverParent() { BrowserList::GetInstance()->AddObserver(this); } + + void OnBrowserAdded(Browser* browser) override { + if (!child_observer_) { + child_observer_ = std::make_unique<BrowserObserverChild>(browser); + } + } + + ~BrowserObserverParent() override { + BrowserList::GetInstance()->RemoveObserver(this); + } + + protected: + std::unique_ptr<BrowserObserverChild> child_observer_; +}; + +TEST_F(BrowserListUnitTest, ObserverAddedInFlight) { + BrowserObserverParent parent_observer; + + const BrowserList* browser_list = BrowserList::GetInstance(); + EXPECT_EQ(1U, browser_list->size()); + + // Adding second browser should not trigger double-observation. + Browser::CreateParams native_params(profile(), true); + std::unique_ptr<Browser> browser2( + CreateBrowserWithTestWindowForParams(native_params)); + EXPECT_EQ(2U, browser_list->size()); + + // Create one more browser to trigger BrowserObserverChild::OnBrowserAdded. + std::unique_ptr<Browser> browser3( + CreateBrowserWithTestWindowForParams(native_params)); + EXPECT_EQ(3U, browser_list->size()); +}
diff --git a/chrome/browser/ui/content_settings/content_setting_image_model.cc b/chrome/browser/ui/content_settings/content_setting_image_model.cc index aad2654..0351510 100644 --- a/chrome/browser/ui/content_settings/content_setting_image_model.cc +++ b/chrome/browser/ui/content_settings/content_setting_image_model.cc
@@ -112,15 +112,9 @@ bool IsGeolocationAllowedOnASystemLevel(); bool IsGeolocationPermissionDetermined(); - void AppCeasesToUseGeolocation(); - void AppAttemptsToUseGeolocation(); - std::unique_ptr<ContentSettingBubbleModel> CreateBubbleModelImpl( ContentSettingBubbleModel::Delegate* delegate, WebContents* web_contents) override; - - private: - bool active_ = false; }; class ContentSettingRPHImageModel : public ContentSettingSimpleImageModel { @@ -522,9 +516,7 @@ ContentSettingGeolocationImageModel::ContentSettingGeolocationImageModel() : ContentSettingImageModel(ImageType::GEOLOCATION, kNotifyAccessibility) {} -ContentSettingGeolocationImageModel::~ContentSettingGeolocationImageModel() { - AppCeasesToUseGeolocation(); -} +ContentSettingGeolocationImageModel::~ContentSettingGeolocationImageModel() {} bool ContentSettingGeolocationImageModel::UpdateAndGetVisibility( WebContents* web_contents) { @@ -533,7 +525,6 @@ web_contents->GetPrimaryMainFrame()); set_should_auto_open_bubble(false); if (!content_settings) { - AppCeasesToUseGeolocation(); return false; } @@ -543,7 +534,6 @@ content_settings->IsContentBlocked(ContentSettingsType::GEOLOCATION); if (!is_allowed && !is_blocked) { - AppCeasesToUseGeolocation(); return false; } @@ -595,7 +585,6 @@ set_explanatory_string_id(IDS_GEOLOCATION_TURNED_OFF); #endif // BUILDFLAG(IS_MAC) } - AppAttemptsToUseGeolocation(); return true; } } @@ -607,7 +596,6 @@ set_tooltip(l10n_util::GetStringUTF16(message_id)); set_accessibility_string_id(message_id); - AppAttemptsToUseGeolocation(); return true; } @@ -640,30 +628,6 @@ #endif } -void ContentSettingGeolocationImageModel::AppAttemptsToUseGeolocation() { - if (!active_) { - active_ = true; -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS) - device::GeolocationManager* geolocation_manager = - g_browser_process->geolocation_manager(); - CHECK(geolocation_manager); - geolocation_manager->AppAttemptsToUseGeolocation(); -#endif - } -} - -void ContentSettingGeolocationImageModel::AppCeasesToUseGeolocation() { - if (active_) { - active_ = false; -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS) - device::GeolocationManager* geolocation_manager = - g_browser_process->geolocation_manager(); - CHECK(geolocation_manager); - geolocation_manager->AppCeasesToUseGeolocation(); -#endif - } -} - std::unique_ptr<ContentSettingBubbleModel> ContentSettingGeolocationImageModel::CreateBubbleModelImpl( ContentSettingBubbleModel::Delegate* delegate,
diff --git a/chrome/browser/ui/fast_checkout/DIR_METADATA b/chrome/browser/ui/fast_checkout/DIR_METADATA index aa2a9fdd5..0da2312 100644 --- a/chrome/browser/ui/fast_checkout/DIR_METADATA +++ b/chrome/browser/ui/fast_checkout/DIR_METADATA
@@ -1,4 +1,4 @@ monorail { - component: "UI>Browser>Autofill>Assistant" + component: "UI>Browser>Autofill" } team_email: "chrome-duplex@google.com"
diff --git a/chrome/browser/ui/views/autofill/edit_address_profile_view.cc b/chrome/browser/ui/views/autofill/edit_address_profile_view.cc index c0d6b18..216cf1af 100644 --- a/chrome/browser/ui/views/autofill/edit_address_profile_view.cc +++ b/chrome/browser/ui/views/autofill/edit_address_profile_view.cc
@@ -17,6 +17,7 @@ #include "ui/views/controls/label.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/fill_layout.h" +#include "ui/views/view_class_properties.h" namespace autofill { @@ -45,6 +46,7 @@ set_margins(ChromeLayoutProvider::Get()->GetInsetsMetric( views::InsetsMetric::INSETS_DIALOG)); + SetProperty(views::kElementIdentifierKey, kTopViewId); SetTitle(controller_->GetWindowTitle()); SetButtonLabel(ui::DIALOG_BUTTON_OK, controller_->GetOkButtonLabel()); SetButtonLabel(ui::DIALOG_BUTTON_CANCEL, @@ -117,4 +119,6 @@ SetButtonEnabled(ui::DIALOG_BUTTON_OK, is_valid); } +DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(EditAddressProfileView, kTopViewId); + } // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/edit_address_profile_view.h b/chrome/browser/ui/views/autofill/edit_address_profile_view.h index a603367..bec2e80 100644 --- a/chrome/browser/ui/views/autofill/edit_address_profile_view.h +++ b/chrome/browser/ui/views/autofill/edit_address_profile_view.h
@@ -25,6 +25,8 @@ class EditAddressProfileView : public AutofillBubbleBase, public views::DialogDelegateView { public: + DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kTopViewId); + explicit EditAddressProfileView( EditAddressProfileDialogController* controller);
diff --git a/chrome/browser/ui/views/autofill/save_address_profile_view.cc b/chrome/browser/ui/views/autofill/save_address_profile_view.cc index 35ee611d..4265b128 100644 --- a/chrome/browser/ui/views/autofill/save_address_profile_view.cc +++ b/chrome/browser/ui/views/autofill/save_address_profile_view.cc
@@ -161,6 +161,8 @@ // it would have been an update prompt. DCHECK(!controller_->GetOriginalProfile()); + set_close_on_deactivate(false); + // TODO(crbug.com/1167060): Accept action should consider the selected // nickname when saving the address. SetAcceptCallback(base::BindOnce( @@ -171,6 +173,7 @@ &SaveUpdateAddressProfileBubbleController::OnUserDecision, base::Unretained(controller_), controller_->GetCancelCallbackValue())); + SetProperty(views::kElementIdentifierKey, kTopViewId); SetTitle(controller_->GetWindowTitle()); SetButtonLabel(ui::DIALOG_BUTTON_OK, controller_->GetOkButtonLabel()); SetButtonLabel(ui::DIALOG_BUTTON_CANCEL, @@ -227,6 +230,7 @@ details_section->AddChildView(CreateEditButton(base::BindRepeating( &SaveUpdateAddressProfileBubbleController::OnEditButtonClicked, base::Unretained(controller_)))); + edit_button_->SetProperty(views::kElementIdentifierKey, kEditButtonViewId); std::u16string address = controller_->GetAddressSummary(); if (!address.empty()) { @@ -365,4 +369,8 @@ } } +DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(SaveAddressProfileView, kTopViewId); +DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(SaveAddressProfileView, + kEditButtonViewId); + } // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/save_address_profile_view.h b/chrome/browser/ui/views/autofill/save_address_profile_view.h index f9f682c..cce2512 100644 --- a/chrome/browser/ui/views/autofill/save_address_profile_view.h +++ b/chrome/browser/ui/views/autofill/save_address_profile_view.h
@@ -27,6 +27,9 @@ class SaveAddressProfileView : public AutofillBubbleBase, public LocationBarBubbleDelegateView { public: + DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kTopViewId); + DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kEditButtonViewId); + SaveAddressProfileView(views::View* anchor_view, content::WebContents* web_contents, SaveUpdateAddressProfileBubbleController* controller);
diff --git a/chrome/browser/ui/views/autofill/update_address_profile_view.cc b/chrome/browser/ui/views/autofill/update_address_profile_view.cc index 6d3663d..dc3d561 100644 --- a/chrome/browser/ui/views/autofill/update_address_profile_view.cc +++ b/chrome/browser/ui/views/autofill/update_address_profile_view.cc
@@ -123,6 +123,9 @@ if (are_new_values) { std::unique_ptr<views::ImageButton> edit_button = CreateEditButton(std::move(edit_button_callback)); + + edit_button->SetProperty(views::kElementIdentifierKey, + UpdateAddressProfileView::kEditButtonViewId); layout_view->AddChildView(std::move(edit_button)); } } @@ -168,6 +171,7 @@ base::Unretained(controller_), AutofillClient::SaveAddressProfileOfferUserDecision::kDeclined)); + SetProperty(views::kElementIdentifierKey, kTopViewId); SetTitle(controller_->GetWindowTitle()); SetButtonLabel(ui::DIALOG_BUTTON_OK, l10n_util::GetStringUTF16( @@ -294,4 +298,8 @@ controller_ = nullptr; } +DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(UpdateAddressProfileView, kTopViewId); +DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(UpdateAddressProfileView, + kEditButtonViewId); + } // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/update_address_profile_view.h b/chrome/browser/ui/views/autofill/update_address_profile_view.h index 55292e5..49618118 100644 --- a/chrome/browser/ui/views/autofill/update_address_profile_view.h +++ b/chrome/browser/ui/views/autofill/update_address_profile_view.h
@@ -25,6 +25,9 @@ class UpdateAddressProfileView : public AutofillBubbleBase, public LocationBarBubbleDelegateView { public: + DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kTopViewId); + DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kEditButtonViewId); + UpdateAddressProfileView( views::View* anchor_view, content::WebContents* web_contents,
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_cros.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_cros.cc index 34401fd1..7c747186 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_cros.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_cros.cc
@@ -2128,5 +2128,23 @@ helper_.CheckPlatformShortcutAndIcon(Site::kSubApp1); } +IN_PROC_BROWSER_TEST_F( + WebAppIntegration, + WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_28_12Standalone_7Standalone) { + // Test contents are generated by script. Please do not modify! + // See `docs/webapps/why-is-this-test-failing.md` or + // `docs/webapps/integration-testing-framework` for more info. + // Sheriffs: Disabling this test is supported. + helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); + helper_.CheckWindowCreated(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.CheckWindowControlsOverlayToggle(Site::kStandalone, + IsShown::kNotShown); + helper_.ClosePwa(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); +} + } // namespace } // namespace web_app::integration_tests
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac.cc index a9b15a5..2953d02 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac.cc
@@ -188,46 +188,6 @@ IN_PROC_BROWSER_TEST_F( WebAppIntegration, - WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_28_149Standalone_1Standalone_22One_163Standalone) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); - helper_.CheckWindowCreated(); - helper_.CheckAppInListWindowed(Site::kStandalone); - helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); - helper_.CheckWindowControlsOverlayToggle(Site::kStandalone, - IsShown::kNotShown); - helper_.ClosePwa(); - helper_.SetOpenInTabFromAppSettings(Site::kStandalone); - helper_.LaunchFromPlatformShortcut(Site::kStandalone); - helper_.CheckTabCreated(Number::kOne); - helper_.CheckAppLoadedInTab(Site::kStandalone); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_28_147Standalone_1Standalone_22One_163Standalone) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); - helper_.CheckWindowCreated(); - helper_.CheckAppInListWindowed(Site::kStandalone); - helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); - helper_.CheckWindowControlsOverlayToggle(Site::kStandalone, - IsShown::kNotShown); - helper_.ClosePwa(); - helper_.SetOpenInTabFromAppHome(Site::kStandalone); - helper_.LaunchFromPlatformShortcut(Site::kStandalone); - helper_.CheckTabCreated(Number::kOne); - helper_.CheckAppLoadedInTab(Site::kStandalone); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, WAI_31Standalone_24_12Standalone_7Standalone_112StandaloneNotShown_28_149Standalone_1Standalone_22One_163Standalone) { // Test contents are generated by script. Please do not modify! // See `docs/webapps/why-is-this-test-failing.md` or @@ -1244,72 +1204,6 @@ IN_PROC_BROWSER_TEST_F( WebAppIntegration, - WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_28_160Profile2_29StandaloneWindowed_164Standalone_1Standalone_165StandaloneOneProfile2) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); - helper_.CheckWindowCreated(); - helper_.CheckAppInListWindowed(Site::kStandalone); - helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); - helper_.CheckWindowControlsOverlayToggle(Site::kStandalone, - IsShown::kNotShown); - helper_.ClosePwa(); - helper_.SwitchActiveProfile(ProfileName::kProfile2); - helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); - helper_.QuitAppShim(Site::kStandalone); - helper_.LaunchFromPlatformShortcut(Site::kStandalone); - helper_.CheckPwaWindowCreatedInProfile(Site::kStandalone, Number::kOne, - ProfileName::kProfile2); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_28_160Profile2_31Standalone_164Standalone_1Standalone_165StandaloneOneProfile2) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); - helper_.CheckWindowCreated(); - helper_.CheckAppInListWindowed(Site::kStandalone); - helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); - helper_.CheckWindowControlsOverlayToggle(Site::kStandalone, - IsShown::kNotShown); - helper_.ClosePwa(); - helper_.SwitchActiveProfile(ProfileName::kProfile2); - helper_.InstallOmniboxIcon(InstallableSite::kStandalone); - helper_.QuitAppShim(Site::kStandalone); - helper_.LaunchFromPlatformShortcut(Site::kStandalone); - helper_.CheckPwaWindowCreatedInProfile(Site::kStandalone, Number::kOne, - ProfileName::kProfile2); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_28_160Profile2_47Standalone_164Standalone_1Standalone_165StandaloneOneProfile2) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); - helper_.CheckWindowCreated(); - helper_.CheckAppInListWindowed(Site::kStandalone); - helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); - helper_.CheckWindowControlsOverlayToggle(Site::kStandalone, - IsShown::kNotShown); - helper_.ClosePwa(); - helper_.SwitchActiveProfile(ProfileName::kProfile2); - helper_.InstallMenuOption(InstallableSite::kStandalone); - helper_.QuitAppShim(Site::kStandalone); - helper_.LaunchFromPlatformShortcut(Site::kStandalone); - helper_.CheckPwaWindowCreatedInProfile(Site::kStandalone, Number::kOne, - ProfileName::kProfile2); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_160Profile2_29StandaloneWindowed_164Standalone_1Standalone_165StandaloneOneDefault_165StandaloneOneProfile2) { // Test contents are generated by script. Please do not modify! // See `docs/webapps/why-is-this-test-failing.md` or @@ -2094,5 +1988,121 @@ ProfileName::kProfile2); } +IN_PROC_BROWSER_TEST_F( + WebAppIntegration, + WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_28_12Standalone_7Standalone_149Standalone_1Standalone_22One_163Standalone) { + // Test contents are generated by script. Please do not modify! + // See `docs/webapps/why-is-this-test-failing.md` or + // `docs/webapps/integration-testing-framework` for more info. + // Sheriffs: Disabling this test is supported. + helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); + helper_.CheckWindowCreated(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.CheckWindowControlsOverlayToggle(Site::kStandalone, + IsShown::kNotShown); + helper_.ClosePwa(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.SetOpenInTabFromAppSettings(Site::kStandalone); + helper_.LaunchFromPlatformShortcut(Site::kStandalone); + helper_.CheckTabCreated(Number::kOne); + helper_.CheckAppLoadedInTab(Site::kStandalone); +} + +IN_PROC_BROWSER_TEST_F( + WebAppIntegration, + WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_28_12Standalone_7Standalone_147Standalone_1Standalone_22One_163Standalone) { + // Test contents are generated by script. Please do not modify! + // See `docs/webapps/why-is-this-test-failing.md` or + // `docs/webapps/integration-testing-framework` for more info. + // Sheriffs: Disabling this test is supported. + helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); + helper_.CheckWindowCreated(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.CheckWindowControlsOverlayToggle(Site::kStandalone, + IsShown::kNotShown); + helper_.ClosePwa(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.SetOpenInTabFromAppHome(Site::kStandalone); + helper_.LaunchFromPlatformShortcut(Site::kStandalone); + helper_.CheckTabCreated(Number::kOne); + helper_.CheckAppLoadedInTab(Site::kStandalone); +} + +IN_PROC_BROWSER_TEST_F( + WebAppIntegration, + WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_28_12Standalone_7Standalone_160Profile2_29StandaloneWindowed_164Standalone_1Standalone_165StandaloneOneProfile2) { + // Test contents are generated by script. Please do not modify! + // See `docs/webapps/why-is-this-test-failing.md` or + // `docs/webapps/integration-testing-framework` for more info. + // Sheriffs: Disabling this test is supported. + helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); + helper_.CheckWindowCreated(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.CheckWindowControlsOverlayToggle(Site::kStandalone, + IsShown::kNotShown); + helper_.ClosePwa(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.SwitchActiveProfile(ProfileName::kProfile2); + helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); + helper_.QuitAppShim(Site::kStandalone); + helper_.LaunchFromPlatformShortcut(Site::kStandalone); + helper_.CheckPwaWindowCreatedInProfile(Site::kStandalone, Number::kOne, + ProfileName::kProfile2); +} + +IN_PROC_BROWSER_TEST_F( + WebAppIntegration, + WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_28_12Standalone_7Standalone_160Profile2_31Standalone_164Standalone_1Standalone_165StandaloneOneProfile2) { + // Test contents are generated by script. Please do not modify! + // See `docs/webapps/why-is-this-test-failing.md` or + // `docs/webapps/integration-testing-framework` for more info. + // Sheriffs: Disabling this test is supported. + helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); + helper_.CheckWindowCreated(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.CheckWindowControlsOverlayToggle(Site::kStandalone, + IsShown::kNotShown); + helper_.ClosePwa(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.SwitchActiveProfile(ProfileName::kProfile2); + helper_.InstallOmniboxIcon(InstallableSite::kStandalone); + helper_.QuitAppShim(Site::kStandalone); + helper_.LaunchFromPlatformShortcut(Site::kStandalone); + helper_.CheckPwaWindowCreatedInProfile(Site::kStandalone, Number::kOne, + ProfileName::kProfile2); +} + +IN_PROC_BROWSER_TEST_F( + WebAppIntegration, + WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_28_12Standalone_7Standalone_160Profile2_47Standalone_164Standalone_1Standalone_165StandaloneOneProfile2) { + // Test contents are generated by script. Please do not modify! + // See `docs/webapps/why-is-this-test-failing.md` or + // `docs/webapps/integration-testing-framework` for more info. + // Sheriffs: Disabling this test is supported. + helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); + helper_.CheckWindowCreated(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.CheckWindowControlsOverlayToggle(Site::kStandalone, + IsShown::kNotShown); + helper_.ClosePwa(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.SwitchActiveProfile(ProfileName::kProfile2); + helper_.InstallMenuOption(InstallableSite::kStandalone); + helper_.QuitAppShim(Site::kStandalone); + helper_.LaunchFromPlatformShortcut(Site::kStandalone); + helper_.CheckPwaWindowCreatedInProfile(Site::kStandalone, Number::kOne, + ProfileName::kProfile2); +} + } // namespace } // namespace web_app::integration_tests
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc index ceeb3f3..92a3c2c 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
@@ -12,6 +12,16 @@ // Manual tests: +IN_PROC_BROWSER_TEST_F(WebAppIntegrationTest, Testing_2) { + helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); + helper_.MaybeClosePwa(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.LaunchFromPlatformShortcut(Site::kStandalone); + helper_.CheckWindowCreated(); + helper_.CheckInstallIconNotShown(); +} + IN_PROC_BROWSER_TEST_F(WebAppIntegrationTest, LaunchFromPlatformShortcut) { helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); helper_.CheckWindowCreated(); @@ -5728,5 +5738,44 @@ helper_.CheckBrowserNavigationIsAppSettings(Site::kStandalone); } +IN_PROC_BROWSER_TEST_F( + WebAppIntegration, + WAI_29StandaloneBrowser_11Standalone_7Standalone_1Standalone_22One_31Standalone_165StandaloneOneDefault) { + // Test contents are generated by script. Please do not modify! + // See `docs/webapps/why-is-this-test-failing.md` or + // `docs/webapps/integration-testing-framework` for more info. + // Sheriffs: Disabling this test is supported. + helper_.CreateShortcut(Site::kStandalone, WindowOptions::kBrowser); + helper_.CheckAppInListTabbed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.LaunchFromPlatformShortcut(Site::kStandalone); + helper_.CheckTabCreated(Number::kOne); + helper_.InstallOmniboxIcon(InstallableSite::kStandalone); + helper_.CheckPwaWindowCreatedInProfile(Site::kStandalone, Number::kOne, + ProfileName::kDefault); +} + +IN_PROC_BROWSER_TEST_F( + WebAppIntegration, + WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_28_12Standalone_7Standalone_1Standalone_165StandaloneOneDefault_19) { + // Test contents are generated by script. Please do not modify! + // See `docs/webapps/why-is-this-test-failing.md` or + // `docs/webapps/integration-testing-framework` for more info. + // Sheriffs: Disabling this test is supported. + helper_.CreateShortcut(Site::kStandalone, WindowOptions::kWindowed); + helper_.CheckWindowCreated(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.CheckWindowControlsOverlayToggle(Site::kStandalone, + IsShown::kNotShown); + helper_.ClosePwa(); + helper_.CheckAppInListWindowed(Site::kStandalone); + helper_.CheckPlatformShortcutAndIcon(Site::kStandalone); + helper_.LaunchFromPlatformShortcut(Site::kStandalone); + helper_.CheckPwaWindowCreatedInProfile(Site::kStandalone, Number::kOne, + ProfileName::kDefault); + helper_.CheckLaunchIconNotShown(); +} + } // namespace } // namespace web_app::integration_tests
diff --git a/chrome/browser/ui/webui/ash/edu_account_login_handler_unittest.cc b/chrome/browser/ui/webui/ash/edu_account_login_handler_unittest.cc index f086755..e02b483 100644 --- a/chrome/browser/ui/webui/ash/edu_account_login_handler_unittest.cc +++ b/chrome/browser/ui/webui/ash/edu_account_login_handler_unittest.cc
@@ -275,9 +275,9 @@ // Simulate failed fetching of family members. handler()->OnListFamilyMembersFailure( - KidsExternalFetcherStatus::NetOrHttpError(net::ERR_IO_PENDING)); + KidsExternalFetcherStatus::HttpStatusOrNetError(net::ERR_IO_PENDING)); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); - VerifyJavascriptCallbackResolved(data, callback_id, false /*success*/); + VerifyJavascriptCallbackResolved(data, callback_id, /*success=*/false); ASSERT_EQ(base::Value::List(), *data.arg3()); }
diff --git a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc index 212f774..bd45226 100644 --- a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc +++ b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc
@@ -269,7 +269,7 @@ "chrome://connection-help", "chrome://connection-monitoring-detected", // TODO(crbug.com/1446612): Re-enable this test -#if !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS_LACROS) +#if !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS) "chrome://credits", #endif "chrome://customize-chrome-side-panel.top-chrome",
diff --git a/chrome/build/lacros64.pgo.txt b/chrome/build/lacros64.pgo.txt index 0b6a96d..9ea2e4c 100644 --- a/chrome/build/lacros64.pgo.txt +++ b/chrome/build/lacros64.pgo.txt
@@ -1 +1 @@ -chrome-chromeos-amd64-generic-main-1684727980-51662d2f1f6daef2312757edd2dffb5841d13efb.profdata +chrome-chromeos-amd64-generic-main-1684741965-9877198816133fde5c1e2b04561d5ea49365a2fb.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index dc93529..379d6bc0 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1684727980-0fd0c1177220325145c620a12d6fed55ccff088a.profdata +chrome-mac-arm-main-1684749276-3baf89d503def7b008db9225d5ba5149e86f5300.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 82f6ca4..d0a491d 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1684713069-d6dbd61c3725118a77b672bdb8468711f45ae782.profdata +chrome-mac-main-1684735120-b681ef3f762e90652c2a427d586e72382e8dca3a.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index ece5d468..2c228ca 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1684724274-6e95f936d76f98a2b96f8aa1501e17607cf9e5a3.profdata +chrome-win32-main-1684745810-e281aa73a34471fde8607f6aed8c228e9efbc681.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index bb0d47d0..698d92a6 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1684724274-88cd05cd95f5a6b07bf8ea8b3618abbc9f5bad19.profdata +chrome-win64-main-1684745810-b231356e5ab799996dbf86d8f839a83a4ffcd54b.profdata
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 6e85bb36..1409296 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2317,7 +2317,6 @@ "../browser/ui/autofill/payments/card_unmask_prompt_view_browsertest.cc", "../browser/ui/autofill/payments/save_card_bubble_controller_impl_browsertest.cc", "../browser/ui/autofill/payments/save_upi_bubble_controller_impl_browsertest.cc", - "../browser/ui/autofill/save_update_address_profile_bubble_controller_impl_browsertest.cc", "../browser/ui/blocked_content/popup_opener_tab_helper_browsertest.cc", "../browser/ui/blocked_content/popup_tracker_browsertest.cc", "../browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_browsertest.cc", @@ -3900,6 +3899,7 @@ "../browser/ash/arc/user_session/arc_user_session_service_browsertest.cc", "../browser/ash/base/locale_util_browsertest.cc", "../browser/ash/bluetooth/hats_bluetooth_revamp_trigger_impl_browsertest.cc", + "../browser/ash/bruschetta/bruschetta_download_browsertest.cc", "../browser/ash/child_accounts/family_user_device_metrics_browsertest.cc", "../browser/ash/child_accounts/parent_access_code/parent_access_service_browsertest.cc", "../browser/ash/child_accounts/screen_time_controller_browsertest.cc", @@ -10143,6 +10143,7 @@ if (toolkit_views) { sources += [ "../browser/media/webrtc/conditional_focus_browsertest.cc", + "../browser/ui/autofill/save_update_address_profile_bubble_controller_impl_interactive_uitest.cc", "../browser/ui/commerce/price_tracking/mock_shopping_list_ui_tab_helper.cc", "../browser/ui/commerce/price_tracking/mock_shopping_list_ui_tab_helper.h", "../browser/ui/toolbar/app_menu_fullscreen_interactive_uitest.cc",
diff --git a/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc b/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc index c4ef347..6ae78b3 100644 --- a/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc +++ b/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc
@@ -211,16 +211,12 @@ // to allow Chrome to write out all the net logs to the log path. kill_gracefully = kill_gracefully || command_.HasSwitch("log-net-log"); if (kill_gracefully) { - Status status{kOk}; - if (!devtools_websocket_client_->IsConnected()) - status = devtools_websocket_client_->Connect(); - if (status.IsOk()) { - status = devtools_websocket_client_->SendCommandAndIgnoreResponse( - "Browser.close", base::Value::Dict()); - // If status is not okay, we will try the old method of KillProcess - if (status.IsOk() && - process_.WaitForExitWithTimeout(base::Seconds(10), nullptr)) - return status; + Status status = devtools_websocket_client_->SendCommandAndIgnoreResponse( + "Browser.close", base::Value::Dict()); + // If status is not okay, we will try the old method of KillProcess + if (status.IsOk() && + process_.WaitForExitWithTimeout(base::Seconds(10), nullptr)) { + return status; } }
diff --git a/chrome/test/chromedriver/chrome/chrome_impl.cc b/chrome/test/chromedriver/chrome/chrome_impl.cc index d86ef40..66b8704b 100644 --- a/chrome/test/chromedriver/chrome/chrome_impl.cc +++ b/chrome/test/chromedriver/chrome/chrome_impl.cc
@@ -212,80 +212,11 @@ } *client = std::make_unique<DevToolsClientImpl>(id, session_id); - (*client)->SetFrontendCloserFunc(base::BindRepeating( - &ChromeImpl::CloseFrontends, base::Unretained(this), id)); (*client)->SetMainPage(true); return status; } -Status ChromeImpl::CloseFrontends(const std::string& for_client_id) { - WebViewsInfo views_info; - Status status = GetWebViewsInfo(&views_info); - if (status.IsError()) - return status; - - // Close frontends. Usually frontends are docked in the same page, although - // some may be in tabs (undocked, chrome://inspect, the DevTools - // discovery page, etc.). Tabs can be closed via the DevTools HTTP close - // URL, but docked frontends can only be closed, by design, by connecting - // to them and clicking the close button. Close the tab frontends first - // in case one of them is debugging a docked frontend, which would prevent - // the code from being able to connect to the docked one. - std::list<std::string> tab_frontend_ids; - std::list<std::string> docked_frontend_ids; - for (size_t i = 0; i < views_info.GetSize(); ++i) { - const WebViewInfo& view_info = views_info.Get(i); - if (view_info.IsFrontend()) { - if (view_info.type == WebViewInfo::kPage) - tab_frontend_ids.push_back(view_info.id); - else if (view_info.type == WebViewInfo::kOther) - docked_frontend_ids.push_back(view_info.id); - else - return Status(kUnknownError, "unknown type of DevTools frontend"); - } - } - - for (std::list<std::string>::const_iterator it = tab_frontend_ids.begin(); - it != tab_frontend_ids.end(); ++it) { - status = CloseWebView(*it); - if (status.IsError()) - return status; - } - - for (std::list<std::string>::const_iterator it = docked_frontend_ids.begin(); - it != docked_frontend_ids.end(); ++it) { - std::unique_ptr<DevToolsClientImpl> client; - status = CreateClient(*it, &client); - if (status.IsError()) - return status; - std::unique_ptr<WebViewImpl> web_view(new WebViewImpl( - *it, false, nullptr, devtools_http_client_->browser_info(), - std::move(client), absl::nullopt, page_load_strategy_)); - - DevToolsClientImpl* parent = - static_cast<DevToolsClientImpl*>(devtools_websocket_client_.get()); - status = web_view->AttachTo(parent); - if (status.IsError()) { - return status; - } - - status = CloseWebView(*it); - // Ignore disconnected error, because it may be closed already. - if (status.IsError() && status.code() != kDisconnected) - return status; - } - - status = GetWebViewsInfo(&views_info); - if (status.IsError()) - return status; - - const WebViewInfo* view_info = views_info.GetForId(for_client_id); - if (!view_info) - return Status(kNoSuchWindow, "window was already closed"); - return Status(kOk); -} - Status ChromeImpl::GetWindow(const std::string& target_id, Window* window) { base::Value::Dict params; params.Set("targetId", target_id);
diff --git a/chrome/test/chromedriver/chrome/chrome_impl.h b/chrome/test/chromedriver/chrome/chrome_impl.h index d81a71b2..af45b7d 100644 --- a/chrome/test/chromedriver/chrome/chrome_impl.h +++ b/chrome/test/chromedriver/chrome/chrome_impl.h
@@ -72,7 +72,6 @@ Status CreateClient(const std::string& id, std::unique_ptr<DevToolsClientImpl>* client); - Status CloseFrontends(const std::string& for_client_id); Status CloseTarget(const std::string& id); struct Window {
diff --git a/chrome/test/chromedriver/chrome/console_logger_unittest.cc b/chrome/test/chromedriver/chrome/console_logger_unittest.cc index 1ab92c6..86fa031 100644 --- a/chrome/test/chromedriver/chrome/console_logger_unittest.cc +++ b/chrome/test/chromedriver/chrome/console_logger_unittest.cc
@@ -25,7 +25,7 @@ public: explicit FakeDevToolsClient(const std::string& id) : id_(id), listener_(nullptr) {} - ~FakeDevToolsClient() override {} + ~FakeDevToolsClient() override = default; std::string PopSentCommand() { std::string command; @@ -41,9 +41,6 @@ return listener_->OnEvent(this, method, params); } - // Overridden from DevToolsClient: - Status Connect() override { return listener_->OnConnected(this); } - Status SendCommandAndGetResult(const std::string& method, const base::Value::Dict& params, base::Value::Dict* result) override {
diff --git a/chrome/test/chromedriver/chrome/devtools_client.h b/chrome/test/chromedriver/chrome/devtools_client.h index f30ea49..5715d34 100644 --- a/chrome/test/chromedriver/chrome/devtools_client.h +++ b/chrome/test/chromedriver/chrome/devtools_client.h
@@ -47,9 +47,6 @@ virtual bool IsConnected() const = 0; - // Connect to DevTools if the DevToolsClient is disconnected. - virtual Status Connect() = 0; - virtual Status PostBidiCommand(base::Value::Dict command) = 0; virtual Status SendCommand(const std::string& method,
diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl.cc b/chrome/test/chromedriver/chrome/devtools_client_impl.cc index 3bd5a68..607d091 100644 --- a/chrome/test/chromedriver/chrome/devtools_client_impl.cc +++ b/chrome/test/chromedriver/chrome/devtools_client_impl.cc
@@ -70,10 +70,6 @@ return Status(kOk); } -Status FakeCloseFrontends() { - return Status(kOk); -} - struct SessionId { explicit SessionId(const std::string session_id) : session_id_(session_id) {} std::string session_id_; @@ -187,13 +183,13 @@ namespace internal { -InspectorEvent::InspectorEvent() {} +InspectorEvent::InspectorEvent() = default; -InspectorEvent::~InspectorEvent() {} +InspectorEvent::~InspectorEvent() = default; -InspectorCommandResponse::InspectorCommandResponse() {} +InspectorCommandResponse::InspectorCommandResponse() = default; -InspectorCommandResponse::~InspectorCommandResponse() {} +InspectorCommandResponse::~InspectorCommandResponse() = default; } // namespace internal @@ -202,30 +198,9 @@ const char DevToolsClientImpl::kBidiChannelSuffix[] = "/bidi"; DevToolsClientImpl::DevToolsClientImpl(const std::string& id, - const std::string& session_id, - const std::string& url, - const SyncWebSocketFactory& factory) - : socket_(factory.Run()), - url_(url), - session_id_(session_id), - id_(id), - frontend_closer_func_(base::BindRepeating(&FakeCloseFrontends)), - parser_func_(base::BindRepeating(&internal::ParseInspectorMessage)) { - socket_->SetId(id_); - // If error happens during proactive event consumption we ignore it - // as there is no active user request where the error might be returned. - // Unretained 'this' won't cause any problems as we reset the callback in the - // .dtor. - socket_->SetNotificationCallback(base::BindRepeating( - base::IgnoreResult(&DevToolsClientImpl::HandleReceivedEvents), - base::Unretained(this))); -} - -DevToolsClientImpl::DevToolsClientImpl(const std::string& id, const std::string& session_id) : session_id_(session_id), id_(id), - frontend_closer_func_(base::BindRepeating(&FakeCloseFrontends)), parser_func_(base::BindRepeating(&internal::ParseInspectorMessage)) {} DevToolsClientImpl::~DevToolsClientImpl() { @@ -247,11 +222,6 @@ parser_func_ = parser_func; } -void DevToolsClientImpl::SetFrontendCloserFunc( - const FrontendCloserFunc& frontend_closer_func) { - frontend_closer_func_ = frontend_closer_func; -} - const std::string& DevToolsClientImpl::GetId() { return id_; } @@ -422,13 +392,8 @@ return Status{kUnknownError, "DevToolsClientImpl can be attached only to a root client"}; } - if (parent->IsNull()) { - // parent.IsNull <=> (parent.parent == null) && (parent.socket == null) - // As, basing on the checks above, we know that parent.parent == null is - // true The expression above can be simplified to parent.IsNull <=> - // parent.socket == null - return Status{kUnknownError, - "cannot attach to a parent that has no socket"}; + if (!parent->IsConnected()) { + return Status{kUnknownError, "cannot attach to a disconnected parent"}; } Status status{kOk}; @@ -445,25 +410,23 @@ return status; } -Status DevToolsClientImpl::Connect() { - if (stack_count_) - return Status(kUnknownError, "cannot connect when nested"); - if (!socket_) { - return Status(kUnknownError, "cannot connect without a socket"); +Status DevToolsClientImpl::SetSocket(std::unique_ptr<SyncWebSocket> socket) { + if (!socket) { + return Status{kUnknownError, "socket cannot be nullptr"}; } - if (socket_->IsConnected()) - return Status(kOk); - + if (!socket->IsConnected()) { + return Status{kUnknownError, "socket must be connected"}; + } ResetListeners(); - - if (!socket_->Connect(url_)) { - // Try to close devtools frontend and then reconnect. - Status status = frontend_closer_func_.Run(); - if (status.IsError()) - return status; - if (!socket_->Connect(url_)) - return Status(kDisconnected, "unable to connect to renderer"); - } + socket_ = std::move(socket); + socket_->SetId(id_); + // If error happens during proactive event consumption we ignore it + // as there is no active user request where the error might be returned. + // Unretained 'this' won't cause any problems as we reset the callback in the + // .dtor. + socket_->SetNotificationCallback(base::BindRepeating( + base::IgnoreResult(&DevToolsClientImpl::HandleReceivedEvents), + base::Unretained(this))); return OnConnected(); } @@ -723,7 +686,7 @@ DevToolsClientImpl::ResponseInfo::ResponseInfo(const std::string& method) : state(kWaiting), method(method) {} -DevToolsClientImpl::ResponseInfo::~ResponseInfo() {} +DevToolsClientImpl::ResponseInfo::~ResponseInfo() = default; DevToolsClient* DevToolsClientImpl::GetRootClient() { return parent_ ? parent_->GetRootClient() : this; @@ -901,7 +864,6 @@ bool log_timeout, const Timeout& timeout, DevToolsClientImpl* caller) { - ScopedIncrementer increment_stack_count(&stack_count_); if (!IsConnected()) { LOG(WARNING) << "Processing messages while being disconnected"; }
diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl.h b/chrome/test/chromedriver/chrome/devtools_client_impl.h index b0ac036..40338607 100644 --- a/chrome/test/chromedriver/chrome/devtools_client_impl.h +++ b/chrome/test/chromedriver/chrome/devtools_client_impl.h
@@ -58,13 +58,6 @@ static const char kCdpTunnelChannel[]; static const char kBidiChannelSuffix[]; - // Postcondition: !IsNull() - // Postcondition: !IsConnected() - DevToolsClientImpl(const std::string& id, - const std::string& session_id, - const std::string& url, - const SyncWebSocketFactory& factory); - typedef base::RepeatingCallback<Status()> FrontendCloserFunc; // Postcondition: IsNull() @@ -85,19 +78,26 @@ ~DevToolsClientImpl() override; void SetParserFuncForTesting(const ParserFunc& parser_func); - void SetFrontendCloserFunc(const FrontendCloserFunc& frontend_closer_func); // Make this DevToolsClient a child of 'parent'. // All the commands of the child are routed via the parent. // The parent demultiplexes the incoming events to the appropriate children. - // If the parent->IsConnected() this object changes its state to connected, - // it sets up the remote end and notifies the listeners about the connection. // Precondition: parent != nullptr + // Precondition: parent.IsConnected() // Precondition: IsNull() // The next precondition secures the class invariant about flat hierarchy // Precondition: parent->GetParentClient() == nullptr. // Postcondition: result.IsError() || !IsNull() + // Postcondition: result.IsError() || IsConnected() Status AttachTo(DevToolsClientImpl* parent); + // Set the socket for communication with the remote end. + // All listeners are notified about the connection. + // Precondition: socket != nullptr + // Precondition: socket.IsConnected() + // Precondition: IsNull() + // Postcondition: result.IsError() || IsConnected() + Status SetSocket(std::unique_ptr<SyncWebSocket> socket); + // Overridden from DevToolsClient: const std::string& GetId() override; // Session id used to annotate the CDP commands. @@ -121,13 +121,6 @@ bool IsNull() const override; bool IsConnected() const override; bool WasCrashed() override; - // Connect and configure the remote end. - // The children are also connected and their remote ends are configured. - // The listeners and the listeners of the children are notified appropriately. - // Does nothing if the connection is already established. - // Precondition: socket != nullptr - // Postcondition: result.IsError() || IsConnected() - Status Connect() override; Status PostBidiCommand(base::Value::Dict command) override; Status SendCommand(const std::string& method, const base::Value::Dict& params) override; @@ -223,7 +216,6 @@ Status SetUpDevTools(); std::unique_ptr<SyncWebSocket> socket_; - GURL url_; // WebViewImpl that owns this instance; nullptr for browser-wide DevTools. raw_ptr<WebViewImpl> owner_ = nullptr; const std::string session_id_; @@ -238,7 +230,6 @@ // For the top-level session, this is the target id. // For child sessions, it's the session id. const std::string id_; - FrontendCloserFunc frontend_closer_func_; ParserFunc parser_func_; std::list<DevToolsEventListener*> listeners_; std::list<DevToolsEventListener*> unnotified_connect_listeners_; @@ -248,7 +239,6 @@ scoped_refptr<ResponseInfo> unnotified_cmd_response_info_; std::map<int, scoped_refptr<ResponseInfo>> response_info_map_; int next_id_ = 1; // The id identifying a particular request. - int stack_count_ = 0; bool is_main_page_ = false; bool bidi_server_is_launched_ = false; // Event tunneling is temporarily disabled in production.
diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl_unittest.cc b/chrome/test/chromedriver/chrome/devtools_client_impl_unittest.cc index 3194bced..0ffbc46 100644 --- a/chrome/test/chromedriver/chrome/devtools_client_impl_unittest.cc +++ b/chrome/test/chromedriver/chrome/devtools_client_impl_unittest.cc
@@ -24,7 +24,6 @@ #include "chrome/test/chromedriver/chrome/devtools_event_listener.h" #include "chrome/test/chromedriver/chrome/status.h" #include "chrome/test/chromedriver/net/sync_websocket.h" -#include "chrome/test/chromedriver/net/sync_websocket_factory.h" #include "chrome/test/chromedriver/net/timeout.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -178,6 +177,211 @@ std::move(mapper_session_id), evt); } +class SyncWebSocketWrapper : public SyncWebSocket { + public: + explicit SyncWebSocketWrapper(SyncWebSocket* socket) : socket_(socket) {} + ~SyncWebSocketWrapper() override = default; + + bool IsConnected() override { return socket_->IsConnected(); } + + bool Connect(const GURL& url) override { return socket_->Connect(url); } + + bool Send(const std::string& message) override { + return socket_->Send(message); + } + + SyncWebSocket::StatusCode ReceiveNextMessage( + std::string* message, + const Timeout& timeout) override { + return socket_->ReceiveNextMessage(message, timeout); + } + + bool HasNextMessage() override { return socket_->HasNextMessage(); } + + private: + raw_ptr<SyncWebSocket> socket_; +}; + +template <typename TSocket> +class SocketHolder { + public: + template <typename... Args> + explicit SocketHolder(Args&&... args) : socket_{args...} {} + + std::unique_ptr<SyncWebSocket> Wrapper() { + return std::unique_ptr<SyncWebSocket>(new SyncWebSocketWrapper(&socket_)); + } + + TSocket& Socket() { return socket_; } + + bool ConnectSocket() { return socket_.Connect(GURL("http://url/")); } + + private: + TSocket socket_; +}; + +struct SessionState { + bool handshake_add_script_handled = false; + bool handshake_runtime_eval_handled = false; + bool connect_complete = false; +}; + +class MultiSessionMockSyncWebSocket : public SyncWebSocket { + public: + MultiSessionMockSyncWebSocket() = default; + ~MultiSessionMockSyncWebSocket() override = default; + + bool IsConnected() override { return connected_; } + + bool Connect(const GURL& url) override { + EXPECT_STREQ("http://url/", url.possibly_invalid_spec().c_str()); + connected_ = true; + return true; + } + + bool Send(const std::string& message) override { + EXPECT_TRUE(connected_); + int cmd_id; + std::string method; + base::Value::Dict params; + std::string session_id; + + if (!ParseMessage(message, &cmd_id, &method, ¶ms, &session_id)) { + return false; + } + + SessionState& session_state = sesison_states_[session_id]; + + if (session_state.connect_complete) { + return OnUserCommand(&session_state, cmd_id, std::move(method), + std::move(params), std::move(session_id)); + } else { + return EnqueueHandshakeResponse(&session_state, cmd_id, std::move(method), + std::move(session_id)); + } + } + + SyncWebSocket::StatusCode ReceiveNextMessage( + std::string* message, + const Timeout& timeout) override { + if (!HasNextMessage() && timeout.IsExpired()) { + return SyncWebSocket::StatusCode::kTimeout; + } + EXPECT_TRUE(HasNextMessage()); + if (PopMessage(message)) { + return SyncWebSocket::StatusCode::kOk; + } else { + return SyncWebSocket::StatusCode::kDisconnected; + } + } + + bool HasNextMessage() override { return !queued_response_.empty(); } + + virtual bool OnUserCommand(SessionState* session_state, + int cmd_id, + std::string method, + base::Value::Dict params, + std::string session_id) { + EXPECT_STREQ("method", method.c_str()); + base::Value::Dict response; + Status status = + CreateDefaultCdpResponse(cmd_id, std::move(method), std::move(params), + std::move(session_id), &response); + EXPECT_TRUE(status.IsOk()) << status.message(); + if (status.IsError()) { + return false; + } + std::string message; + status = SerializeAsJson(response, &message); + EXPECT_TRUE(status.IsOk()) << status.message(); + if (status.IsError()) { + return false; + } + queued_response_.push(std::move(message)); + return true; + } + + Status CreateDefaultCdpResponse(int cmd_id, + std::string method, + base::Value::Dict params, + std::string session_id, + base::Value::Dict* response) { + base::Value::Dict result; + absl::optional<int> ping = params.FindInt("ping"); + if (ping) { + result.Set("pong", *ping); + } else { + result.Set("param", 1); + } + + return CreateCdpResponse(cmd_id, std::move(result), std::move(session_id), + response); + } + + bool EnqueueHandshakeResponse(SessionState* session_state, + int cmd_id, + std::string method, + std::string session_id) { + if (method == "Page.addScriptToEvaluateOnNewDocument") { + EXPECT_FALSE(session_state->handshake_add_script_handled); + if (!session_state->handshake_add_script_handled) { + session_state->handshake_add_script_handled = true; + } else { + return false; + } + } else if (method == "Runtime.evaluate") { + EXPECT_FALSE(session_state->handshake_runtime_eval_handled); + if (!session_state->handshake_runtime_eval_handled) { + session_state->handshake_runtime_eval_handled = true; + } else { + return false; + } + } else { + // Unexpected handshake command + VLOG(0) << "unexpected handshake method: " << method; + ADD_FAILURE(); + return false; + } + + session_state->connect_complete = + session_state->handshake_add_script_handled && + session_state->handshake_runtime_eval_handled; + + base::Value::Dict result; + result.Set("param", 1); + base::Value::Dict response; + Status status = + CreateCdpResponse(cmd_id, std::move(result), session_id, &response); + EXPECT_TRUE(status.IsOk()) << status.message(); + if (status.IsError()) { + return false; + } + + std::string message; + status = SerializeAsJson(base::Value(std::move(response)), &message); + EXPECT_TRUE(status.IsOk()) << status.message(); + if (status.IsError()) { + return false; + } + queued_response_.push(std::move(message)); + return true; + } + + bool PopMessage(std::string* dest) { + if (queued_response_.empty()) { + return false; + } + *dest = std::move(queued_response_.front()); + queued_response_.pop(); + return true; + } + + protected: + bool connected_ = false; + std::map<std::string, SessionState> sesison_states_; + std::queue<std::string> queued_response_; +}; + class MockSyncWebSocket : public SyncWebSocket { public: MockSyncWebSocket() = default; @@ -290,11 +494,6 @@ std::queue<std::string> queued_response_; }; -template <typename T> -std::unique_ptr<SyncWebSocket> CreateMockSyncWebSocket() { - return std::unique_ptr<SyncWebSocket>(new T()); -} - class DevToolsClientImplTest : public testing::Test { protected: DevToolsClientImplTest() : long_timeout_(base::Minutes(5)) {} @@ -304,9 +503,7 @@ } // namespace -TEST_F(DevToolsClientImplTest, Ctor1) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket>); +TEST_F(DevToolsClientImplTest, Ctor) { const std::string expected_id = "E2F4"; const std::string expected_session_id = "BC80031"; DevToolsClientImpl client(expected_id, expected_session_id); @@ -323,56 +520,37 @@ EXPECT_EQ(&client, client.GetRootClient()); } -TEST_F(DevToolsClientImplTest, Ctor2) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket>); - const std::string expected_id = "E2F4"; - const std::string expected_session_id = "BC80031"; - DevToolsClientImpl client(expected_id, expected_session_id, "http://url", - factory); - EXPECT_EQ(expected_id, client.GetId()); - EXPECT_EQ(expected_session_id, client.SessionId()); - EXPECT_EQ(std::string(), client.TunnelSessionId()); - EXPECT_FALSE(client.IsMainPage()); - EXPECT_FALSE(client.IsConnected()); - EXPECT_FALSE(client.IsNull()); - EXPECT_FALSE(client.WasCrashed()); - EXPECT_EQ(1, client.NextMessageId()); - EXPECT_EQ(nullptr, client.GetOwner()); - EXPECT_EQ(nullptr, client.GetParentClient()); - EXPECT_EQ(&client, client.GetRootClient()); -} - TEST_F(DevToolsClientImplTest, SendCommand) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket>); - DevToolsClientImpl client("id", "", "http://url", factory); - ASSERT_EQ(kOk, client.Connect().code()); + SocketHolder<MockSyncWebSocket> socket_holder; + DevToolsClientImpl client("id", ""); + EXPECT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); base::Value::Dict params; params.Set("param", 1); - ASSERT_EQ(kOk, client.SendCommand("method", params).code()); + ASSERT_TRUE(StatusOk(client.SendCommand("method", params))); } TEST_F(DevToolsClientImplTest, SendCommandAndGetResult) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket>); - DevToolsClientImpl client("id", "", "http://url", factory); - ASSERT_EQ(kOk, client.Connect().code()); + SocketHolder<MockSyncWebSocket> socket_holder; + DevToolsClientImpl client("id", ""); + EXPECT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); base::Value::Dict params; params.Set("param", 1); base::Value::Dict result; - Status status = client.SendCommandAndGetResult("method", params, &result); - ASSERT_EQ(kOk, status.code()); + ASSERT_TRUE( + StatusOk(client.SendCommandAndGetResult("method", params, &result))); std::string json; base::JSONWriter::Write(base::Value(std::move(result)), &json); ASSERT_STREQ("{\"param\":1}", json.c_str()); } TEST_F(DevToolsClientImplTest, SetMainPage) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket>); - DevToolsClientImpl client("E2F4", "BC80031", "http://url", factory); + SocketHolder<MockSyncWebSocket> socket_holder; + DevToolsClientImpl client("E2F4", "BC80031"); client.SetMainPage(true); + EXPECT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); EXPECT_TRUE(client.IsMainPage()); } @@ -390,10 +568,9 @@ EXPECT_TRUE(client.SetTunnelSessionId("another_bidi_session").IsError()); } -TEST_F(DevToolsClientImplTest, ConnectWithoutSocket) { +TEST_F(DevToolsClientImplTest, SetNullSocket) { DevToolsClientImpl client("page_client", "page_session"); - Status status = client.Connect(); - EXPECT_TRUE(status.IsError()); + EXPECT_TRUE(client.SetSocket(nullptr).IsError()); } TEST_F(DevToolsClientImplTest, AttachToNull) { @@ -408,12 +585,14 @@ } TEST_F(DevToolsClientImplTest, AttachToAnotherRoot) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket>); - DevToolsClientImpl root_client1("root_client_1", "root_session_1", - "http://url1", factory); - DevToolsClientImpl root_client2("root_client_2", "root_session_2", - "http://url2", factory); + SocketHolder<MultiSessionMockSyncWebSocket> socket_holder1; + DevToolsClientImpl root_client1("root_client_1", "root_session_1"); + ASSERT_TRUE(socket_holder1.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client1.SetSocket(socket_holder1.Wrapper()))); + SocketHolder<MultiSessionMockSyncWebSocket> socket_holder2; + DevToolsClientImpl root_client2("root_client_2", "root_session_2"); + ASSERT_TRUE(socket_holder2.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client2.SetSocket(socket_holder2.Wrapper()))); DevToolsClientImpl client("page_client", "page_session"); ASSERT_TRUE(StatusOk(client.AttachTo(&root_client1))); // Client cannot be re-attached @@ -421,20 +600,22 @@ } TEST_F(DevToolsClientImplTest, AttachRootToRoot) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket>); - DevToolsClientImpl root_client1("root_client_1", "root_session_1", - "http://url1", factory); - DevToolsClientImpl root_client2("root_client_2", "root_session_2", - "http://url2", factory); + SocketHolder<MockSyncWebSocket> socket_holder1; + DevToolsClientImpl root_client1("root_client_1", "root_session_1"); + ASSERT_TRUE(socket_holder1.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client1.SetSocket(socket_holder1.Wrapper()))); + SocketHolder<MockSyncWebSocket> socket_holder2; + DevToolsClientImpl root_client2("root_client_2", "root_session_2"); + ASSERT_TRUE(socket_holder2.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client2.SetSocket(socket_holder2.Wrapper()))); EXPECT_TRUE(root_client2.AttachTo(&root_client1).IsError()); } TEST_F(DevToolsClientImplTest, AttachAsGrandChild) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket>); - DevToolsClientImpl root_client("root_client", "root_session", "http://url", - factory); + SocketHolder<MultiSessionMockSyncWebSocket> socket_holder; + DevToolsClientImpl root_client("root_client", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl child_client("child_client", "child_session"); ASSERT_TRUE(StatusOk(child_client.AttachTo(&root_client))); DevToolsClientImpl grand_child_client("grand_child_client", @@ -444,41 +625,6 @@ namespace { -class MockSyncWebSocket2 : public SyncWebSocket { - public: - MockSyncWebSocket2() = default; - ~MockSyncWebSocket2() override = default; - - bool IsConnected() override { return false; } - - bool Connect(const GURL& url) override { return false; } - - bool Send(const std::string& message) override { - EXPECT_TRUE(false); - return false; - } - - SyncWebSocket::StatusCode ReceiveNextMessage( - std::string* message, - const Timeout& timeout) override { - EXPECT_TRUE(false); - return SyncWebSocket::StatusCode::kDisconnected; - } - - bool HasNextMessage() override { return true; } -}; - -} // namespace - -TEST_F(DevToolsClientImplTest, ConnectIfNecessaryConnectFails) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket2>); - DevToolsClientImpl client("id", "", "http://url", factory); - ASSERT_EQ(kDisconnected, client.Connect().code()); -} - -namespace { - class MockSyncWebSocket3 : public MockSyncWebSocket { public: explicit MockSyncWebSocket3(bool send_returns_after_connect) @@ -529,27 +675,22 @@ bool send_returns_after_connect_; }; -template <typename T> -std::unique_ptr<SyncWebSocket> CreateMockSyncWebSocket_B(bool b1) { - return std::unique_ptr<SyncWebSocket>(new T(b1)); -} - } // namespace TEST_F(DevToolsClientImplTest, SendCommandSendFails) { - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_B<MockSyncWebSocket3>, false); - DevToolsClientImpl client("id", "", "http://url", factory); - ASSERT_EQ(kOk, client.Connect().code()); + SocketHolder<MockSyncWebSocket3> socket_holder{false}; + DevToolsClientImpl client("id", ""); + EXPECT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); base::Value::Dict params; ASSERT_TRUE(client.SendCommand("method", params).IsError()); } TEST_F(DevToolsClientImplTest, SendCommandReceiveNextMessageFails) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket_B<MockSyncWebSocket3>, true); - DevToolsClientImpl client("id", "", "http://url", factory); - ASSERT_EQ(kOk, client.Connect().code()); + SocketHolder<MockSyncWebSocket3> socket_holder{true}; + DevToolsClientImpl client("id", ""); + EXPECT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); base::Value::Dict params; ASSERT_TRUE(client.SendCommand("method", params).IsError()); } @@ -786,67 +927,67 @@ } // namespace -TEST_F(DevToolsClientImplTest, SendCommandOnlyConnectsOnce) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<FakeSyncWebSocket>); - DevToolsClientImpl client("id", "", "http://url", factory); +TEST_F(DevToolsClientImplTest, FakeSyncWebSocketSelfTest) { + SocketHolder<FakeSyncWebSocket> socket_holder; + DevToolsClientImpl client("id", ""); client.SetParserFuncForTesting(base::BindRepeating(&ReturnCommand)); - ASSERT_EQ(kOk, client.Connect().code()); + EXPECT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); base::Value::Dict params; - ASSERT_TRUE(client.SendCommand("method", params).IsOk()); - ASSERT_TRUE(client.SendCommand("method", params).IsOk()); + ASSERT_TRUE(StatusOk(client.SendCommand("method", params))); + ASSERT_TRUE(StatusOk(client.SendCommand("method", params))); } TEST_F(DevToolsClientImplTest, SendCommandBadResponse) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<FakeSyncWebSocket>); - DevToolsClientImpl client("id", "", "http://url", factory); - ASSERT_EQ(kOk, client.Connect().code()); + SocketHolder<FakeSyncWebSocket> socket_holder; + DevToolsClientImpl client("id", ""); + EXPECT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); client.SetParserFuncForTesting(base::BindRepeating(&ReturnBadResponse)); base::Value::Dict params; ASSERT_TRUE(client.SendCommand("method", params).IsError()); } TEST_F(DevToolsClientImplTest, SendCommandBadId) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<FakeSyncWebSocket>); - DevToolsClientImpl client("id", "", "http://url", factory); - ASSERT_EQ(kOk, client.Connect().code()); + SocketHolder<FakeSyncWebSocket> socket_holder; + DevToolsClientImpl client("id", ""); + EXPECT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); client.SetParserFuncForTesting(base::BindRepeating(&ReturnCommandBadId)); base::Value::Dict params; ASSERT_TRUE(client.SendCommand("method", params).IsError()); } TEST_F(DevToolsClientImplTest, SendCommandUnexpectedId) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<FakeSyncWebSocket>); bool first = true; - DevToolsClientImpl client("id", "", "http://url", factory); - ASSERT_EQ(kOk, client.Connect().code()); + SocketHolder<FakeSyncWebSocket> socket_holder; + DevToolsClientImpl client("id", ""); + EXPECT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); client.SetParserFuncForTesting( base::BindRepeating(&ReturnUnexpectedIdThenResponse, &first)); base::Value::Dict params; - ASSERT_TRUE(client.SendCommand("method", params).IsOk()); + ASSERT_TRUE(StatusOk(client.SendCommand("method", params))); } TEST_F(DevToolsClientImplTest, SendCommandResponseError) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<FakeSyncWebSocket>); - DevToolsClientImpl client("id", "", "http://url", factory); - ASSERT_EQ(kOk, client.Connect().code()); + SocketHolder<FakeSyncWebSocket> socket_holder; + DevToolsClientImpl client("id", ""); + EXPECT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); client.SetParserFuncForTesting(base::BindRepeating(&ReturnCommandError)); base::Value::Dict params; ASSERT_TRUE(client.SendCommand("method", params).IsError()); } TEST_F(DevToolsClientImplTest, SendCommandEventBeforeResponse) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<FakeSyncWebSocket>); MockListener listener; bool first = true; - DevToolsClientImpl client("id", "", "http://url", factory); + SocketHolder<FakeSyncWebSocket> socket_holder; + DevToolsClientImpl client("id", ""); client.AddListener(&listener); - ASSERT_EQ(kOk, client.Connect().code()); + EXPECT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); client.SetParserFuncForTesting( base::BindRepeating(&ReturnEventThenResponse, &first)); base::Value::Dict params; @@ -1314,11 +1455,11 @@ TEST_F(DevToolsClientImplTest, HandleEventsUntil) { MockListener listener; - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket>); - DevToolsClientImpl client("id", "", "http://url", factory); + SocketHolder<MockSyncWebSocket> socket_holder; + DevToolsClientImpl client("id", ""); client.AddListener(&listener); - ASSERT_EQ(kOk, client.Connect().code()); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); client.SetParserFuncForTesting(base::BindRepeating(&ReturnEvent)); Status status = client.HandleEventsUntil(base::BindRepeating(&AlwaysTrue), Timeout(long_timeout_)); @@ -1326,10 +1467,10 @@ } TEST_F(DevToolsClientImplTest, HandleEventsUntilTimeout) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket>); - DevToolsClientImpl client("id", "", "http://url", factory); - ASSERT_EQ(kOk, client.Connect().code()); + SocketHolder<MockSyncWebSocket> socket_holder; + DevToolsClientImpl client("id", ""); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); client.SetParserFuncForTesting(base::BindRepeating(&ReturnEvent)); Status status = client.HandleEventsUntil(base::BindRepeating(&AlwaysTrue), Timeout(base::TimeDelta())); @@ -1337,21 +1478,21 @@ } TEST_F(DevToolsClientImplTest, WaitForNextEventCommand) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket>); - DevToolsClientImpl client("id", "", "http://url", factory); + SocketHolder<MockSyncWebSocket> socket_holder; + DevToolsClientImpl client("id", ""); client.SetParserFuncForTesting(base::BindRepeating(&ReturnCommand)); - ASSERT_EQ(kOk, client.Connect().code()); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); Status status = client.HandleEventsUntil(base::BindRepeating(&AlwaysTrue), Timeout(long_timeout_)); ASSERT_EQ(kUnknownError, status.code()); } TEST_F(DevToolsClientImplTest, WaitForNextEventError) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket>); - DevToolsClientImpl client("id", "", "http://url", factory); - ASSERT_EQ(kOk, client.Connect().code()); + SocketHolder<MockSyncWebSocket> socket_holder; + DevToolsClientImpl client("id", ""); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); client.SetParserFuncForTesting(base::BindRepeating(&ReturnError)); Status status = client.HandleEventsUntil(base::BindRepeating(&AlwaysTrue), Timeout(long_timeout_)); @@ -1359,10 +1500,10 @@ } TEST_F(DevToolsClientImplTest, WaitForNextEventConditionalFuncReturnsError) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket>); - DevToolsClientImpl client("id", "", "http://url", factory); - ASSERT_EQ(kOk, client.Connect().code()); + SocketHolder<MockSyncWebSocket> socket_holder; + DevToolsClientImpl client("id", ""); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); client.SetParserFuncForTesting(base::BindRepeating(&ReturnEvent)); Status status = client.HandleEventsUntil(base::BindRepeating(&AlwaysError), Timeout(long_timeout_)); @@ -1370,11 +1511,11 @@ } TEST_F(DevToolsClientImplTest, NestedCommandsWithOutOfOrderResults) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket>); + SocketHolder<MockSyncWebSocket> socket_holder; int recurse_count = 0; - DevToolsClientImpl client("id", "", "http://url", factory); - ASSERT_EQ(kOk, client.Connect().code()); + DevToolsClientImpl client("id", ""); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); client.SetParserFuncForTesting( base::BindRepeating(&ReturnOutOfOrderResponses, &recurse_count, &client)); base::Value::Dict params; @@ -1394,7 +1535,7 @@ : method_(method), client_(client) { client_->AddListener(this); } - ~OnConnectedListener() override {} + ~OnConnectedListener() override = default; void VerifyCalled() { EXPECT_TRUE(on_connected_called_); @@ -1489,13 +1630,13 @@ } // namespace TEST_F(DevToolsClientImplTest, ProcessOnConnectedFirstOnCommand) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<OnConnectedSyncWebSocket>); - DevToolsClientImpl client("onconnected-id", "", "http://url", factory); + SocketHolder<OnConnectedSyncWebSocket> socket_holder; + DevToolsClientImpl client("onconnected-id", ""); OnConnectedListener listener1("DOM.getDocument", &client); OnConnectedListener listener2("Runtime.enable", &client); OnConnectedListener listener3("Page.enable", &client); - ASSERT_EQ(kOk, client.Connect().code()); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); base::Value::Dict params; EXPECT_EQ(kOk, client.SendCommand("Runtime.execute", params).code()); listener1.VerifyCalled(); @@ -1504,13 +1645,13 @@ } TEST_F(DevToolsClientImplTest, ProcessOnConnectedFirstOnHandleEventsUntil) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<OnConnectedSyncWebSocket>); - DevToolsClientImpl client("onconnected-id", "", "http://url", factory); + SocketHolder<OnConnectedSyncWebSocket> socket_holder; + DevToolsClientImpl client("onconnected-id", ""); OnConnectedListener listener1("DOM.getDocument", &client); OnConnectedListener listener2("Runtime.enable", &client); OnConnectedListener listener3("Page.enable", &client); - ASSERT_EQ(kOk, client.Connect().code()); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); EXPECT_EQ(kOk, client.HandleReceivedEvents().code()); listener1.VerifyCalled(); listener2.VerifyCalled(); @@ -1575,7 +1716,7 @@ OtherEventListener* other_listener) : client_(client), other_listener_(other_listener) {} - ~OnEventListener() override {} + ~OnEventListener() override = default; Status OnConnected(DevToolsClient* client) override { EXPECT_EQ(client_, client); @@ -1599,96 +1740,16 @@ } // namespace TEST_F(DevToolsClientImplTest, ProcessOnEventFirst) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket5>); - DevToolsClientImpl client("id", "", "http://url", factory); + SocketHolder<MockSyncWebSocket5> socket_holder; + DevToolsClientImpl client("id", ""); OtherEventListener listener2; OnEventListener listener1(&client, &listener2); client.AddListener(&listener1); client.AddListener(&listener2); - Status status = client.Connect(); - ASSERT_EQ(kOk, status.code()) << status.message(); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); base::Value::Dict params; - EXPECT_EQ(kOk, client.SendCommand("method", params).code()); -} - -namespace { - -class DisconnectedSyncWebSocket : public MockSyncWebSocket { - public: - DisconnectedSyncWebSocket() = default; - ~DisconnectedSyncWebSocket() override = default; - - bool Connect(const GURL& url) override { - connection_count_++; - connected_ = connection_count_ != 2; - return connected_; - } - - bool Send(const std::string& message) override { - EXPECT_TRUE(connected_); - int cmd_id; - std::string method; - base::Value::Dict params; - std::string session_id; - - if (!ParseMessage(message, &cmd_id, &method, ¶ms, &session_id)) { - return false; - } - - if (connect_complete_) { - command_count_++; - if (command_count_ == 1) { - connected_ = false; - handshake_add_script_handled_ = false; - handshake_runtime_eval_handled_ = false; - connect_complete_ = false; - while (!queued_response_.empty()) { - queued_response_.pop(); - } - return false; - } - return MockSyncWebSocket::Send(message); - } else { - EnqueueHandshakeResponse(cmd_id, method); - } - return true; - } - - private: - int connection_count_ = 0; - int command_count_ = 0; -}; - -Status CheckCloserFuncCalled(bool* is_called) { - *is_called = true; - return Status(kOk); -} - -} // namespace - -TEST_F(DevToolsClientImplTest, Reconnect) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<DisconnectedSyncWebSocket>); - bool is_called = false; - DevToolsClientImpl client("id", "", "http://url", factory); - client.SetFrontendCloserFunc( - base::BindRepeating(&CheckCloserFuncCalled, &is_called)); - ASSERT_FALSE(is_called); - ASSERT_EQ(kOk, client.Connect().code()); - ASSERT_FALSE(is_called); - base::Value::Dict params; - params.Set("param", 1); - is_called = false; - ASSERT_EQ(kDisconnected, client.SendCommand("method", params).code()); - ASSERT_FALSE(is_called); - ASSERT_EQ(kDisconnected, client.HandleReceivedEvents().code()); - ASSERT_FALSE(is_called); - ASSERT_EQ(kOk, client.Connect().code()); - ASSERT_TRUE(is_called); - is_called = false; - ASSERT_EQ(kOk, client.SendCommand("method", params).code()); - ASSERT_FALSE(is_called); + EXPECT_TRUE(StatusOk(client.SendCommand("method", params))); } namespace { @@ -1754,20 +1815,14 @@ int expected_blocked_id_ = -1; }; -std::unique_ptr<SyncWebSocket> CreateMockSyncWebSocket6( - std::list<std::string>* messages) { - return std::make_unique<MockSyncWebSocket6>(messages); -} - } // namespace TEST_F(DevToolsClientImplTest, BlockedByAlert) { std::list<std::string> msgs; - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket6, &msgs); - DevToolsClientImpl client("id", "", "http://url", factory); - Status status = client.Connect(); - ASSERT_EQ(kOk, status.code()) << status.message(); + SocketHolder<MockSyncWebSocket6> socket_holder{&msgs}; + DevToolsClientImpl client("id", ""); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); msgs.push_back( "{\"method\": \"Page.javascriptDialogOpening\", \"params\": {}}"); msgs.push_back("{\"id\": 2, \"result\": {}}"); @@ -1795,13 +1850,12 @@ // response for id5 // response for id6 std::list<std::string> msgs; - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket6, &msgs); - DevToolsClientImpl client("id", "", "http://url", factory); + SocketHolder<MockSyncWebSocket6> socket_holder{&msgs}; + DevToolsClientImpl client("id", ""); MockDevToolsEventListener listener; client.AddListener(&listener); - Status status = client.Connect(); - ASSERT_EQ(kOk, status.code()) << status.message(); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); int next_msg_id = client.NextMessageId(); msgs.push_back("{\"method\": \"FirstEvent\", \"params\": {}}"); msgs.push_back("{\"method\": \"SecondEvent\", \"params\": {}}"); @@ -1864,16 +1918,15 @@ TEST_F(DevToolsClientImplTest, ReceivesCommandResponse) { std::list<std::string> msgs; - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket6, &msgs); - DevToolsClientImpl client("id", "", "http://url", factory); + SocketHolder<MockSyncWebSocket6> socket_holder{&msgs}; + DevToolsClientImpl client("id", ""); MockCommandListener listener1; listener1.callback_ = base::BindRepeating(&HandleReceivedEvents); MockCommandListener listener2; client.AddListener(&listener1); client.AddListener(&listener2); - Status status = client.Connect(); - ASSERT_EQ(kOk, status.code()) << status.message(); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); int next_msg_id = client.NextMessageId(); msgs.push_back((std::stringstream() << "{\"id\": " << next_msg_id++ << ", \"result\": {}}") @@ -1886,68 +1939,11 @@ ASSERT_EQ("event", listener2.msgs_.back()); } -namespace { - -class MockSyncWebSocket7 : public SyncWebSocket { - public: - MockSyncWebSocket7() = default; - ~MockSyncWebSocket7() override = default; - - bool IsConnected() override { return true; } - - bool Connect(const GURL& url) override { return true; } - - bool Send(const std::string& message) override { - absl::optional<base::Value> value = base::JSONReader::Read(message); - base::Value::Dict* dict = value->GetIfDict(); - EXPECT_TRUE(dict); - if (!dict) - return false; - absl::optional<int> maybe_id = dict->FindInt("id"); - EXPECT_TRUE(maybe_id); - if (!maybe_id) - return false; - id_ = *maybe_id; - std::string* method = dict->FindString("method"); - EXPECT_TRUE(method); - EXPECT_STREQ("method", method->c_str()); - base::Value::Dict* params = dict->FindDict("params"); - if (!params) - return false; - sent_messages_++; - return true; - } - - SyncWebSocket::StatusCode ReceiveNextMessage( - std::string* message, - const Timeout& timeout) override { - EXPECT_LE(sent_responses_, 1); - EXPECT_EQ(sent_messages_, 2); - base::Value::Dict response; - response.Set("id", (sent_responses_ == 0) ? 1 : 2); - base::Value result{base::Value::Type::DICT}; - result.GetDict().Set("param", 1); - response.Set("result", result.Clone()); - base::JSONWriter::Write(base::Value(std::move(response)), message); - sent_responses_++; - return SyncWebSocket::StatusCode::kOk; - } - - bool HasNextMessage() override { return sent_messages_ > sent_responses_; } - - private: - int id_ = -1; - int sent_messages_ = 0; - int sent_responses_ = 0; -}; - -} // namespace - TEST_F(DevToolsClientImplTest, SendCommandAndIgnoreResponse) { - SyncWebSocketFactory factory = - base::BindRepeating(&CreateMockSyncWebSocket<MockSyncWebSocket7>); - DevToolsClientImpl client("id", "", "http://url", factory); - ASSERT_TRUE(StatusOk(client.Connect())); + SocketHolder<MultiSessionMockSyncWebSocket> socket_holder; + DevToolsClientImpl client("id", ""); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(client.SetSocket(socket_holder.Wrapper()))); base::Value::Dict params; params.Set("param", 1); ASSERT_TRUE(StatusOk(client.SendCommandAndIgnoreResponse("method", params))); @@ -1956,167 +1952,6 @@ namespace { -struct SessionState { - bool handshake_add_script_handled = false; - bool handshake_runtime_eval_handled = false; - bool connect_complete = false; -}; - -class MultiSessionMockSyncWebSocket : public SyncWebSocket { - public: - MultiSessionMockSyncWebSocket() = default; - ~MultiSessionMockSyncWebSocket() override = default; - - bool IsConnected() override { return connected_; } - - bool Connect(const GURL& url) override { - EXPECT_STREQ("http://url/", url.possibly_invalid_spec().c_str()); - connected_ = true; - return true; - } - - bool Send(const std::string& message) override { - EXPECT_TRUE(connected_); - int cmd_id; - std::string method; - base::Value::Dict params; - std::string session_id; - - if (!ParseMessage(message, &cmd_id, &method, ¶ms, &session_id)) { - return false; - } - - SessionState& session_state = sesison_states_[session_id]; - - if (session_state.connect_complete) { - return OnUserCommand(&session_state, cmd_id, std::move(method), - std::move(params), std::move(session_id)); - } else { - return EnqueueHandshakeResponse(&session_state, cmd_id, std::move(method), - std::move(session_id)); - } - } - - SyncWebSocket::StatusCode ReceiveNextMessage( - std::string* message, - const Timeout& timeout) override { - if (!HasNextMessage() && timeout.IsExpired()) - return SyncWebSocket::StatusCode::kTimeout; - EXPECT_TRUE(HasNextMessage()); - if (PopMessage(message)) { - return SyncWebSocket::StatusCode::kOk; - } else { - return SyncWebSocket::StatusCode::kDisconnected; - } - } - - bool HasNextMessage() override { return !queued_response_.empty(); } - - virtual bool OnUserCommand(SessionState* session_state, - int cmd_id, - std::string method, - base::Value::Dict params, - std::string session_id) { - EXPECT_STREQ("method", method.c_str()); - base::Value::Dict response; - Status status = - CreateDefaultCdpResponse(cmd_id, std::move(method), std::move(params), - std::move(session_id), &response); - EXPECT_TRUE(status.IsOk()) << status.message(); - if (status.IsError()) { - return false; - } - std::string message; - status = SerializeAsJson(response, &message); - EXPECT_TRUE(status.IsOk()) << status.message(); - if (status.IsError()) { - return false; - } - queued_response_.push(std::move(message)); - return true; - } - - Status CreateDefaultCdpResponse(int cmd_id, - std::string method, - base::Value::Dict params, - std::string session_id, - base::Value::Dict* response) { - base::Value::Dict result; - absl::optional<int> ping = params.FindInt("ping"); - if (ping) { - result.Set("pong", *ping); - } else { - result.Set("param", 1); - } - - return CreateCdpResponse(cmd_id, std::move(result), std::move(session_id), - response); - } - - bool EnqueueHandshakeResponse(SessionState* session_state, - int cmd_id, - std::string method, - std::string session_id) { - if (method == "Page.addScriptToEvaluateOnNewDocument") { - EXPECT_FALSE(session_state->handshake_add_script_handled); - if (!session_state->handshake_add_script_handled) { - session_state->handshake_add_script_handled = true; - } else { - return false; - } - } else if (method == "Runtime.evaluate") { - EXPECT_FALSE(session_state->handshake_runtime_eval_handled); - if (!session_state->handshake_runtime_eval_handled) { - session_state->handshake_runtime_eval_handled = true; - } else { - return false; - } - } else { - // Unexpected handshake command - VLOG(0) << "unexpected handshake method: " << method; - ADD_FAILURE(); - return false; - } - - session_state->connect_complete = - session_state->handshake_add_script_handled && - session_state->handshake_runtime_eval_handled; - - base::Value::Dict result; - result.Set("param", 1); - base::Value::Dict response; - Status status = - CreateCdpResponse(cmd_id, std::move(result), session_id, &response); - EXPECT_TRUE(status.IsOk()) << status.message(); - if (status.IsError()) { - return false; - } - - std::string message; - status = SerializeAsJson(base::Value(std::move(response)), &message); - EXPECT_TRUE(status.IsOk()) << status.message(); - if (status.IsError()) { - return false; - } - queued_response_.push(std::move(message)); - return true; - } - - bool PopMessage(std::string* dest) { - if (queued_response_.empty()) { - return false; - } - *dest = std::move(queued_response_.front()); - queued_response_.pop(); - return true; - } - - protected: - bool connected_ = false; - std::map<std::string, SessionState> sesison_states_; - std::queue<std::string> queued_response_; -}; - class PingingListener : public DevToolsEventListener { public: PingingListener() = default; @@ -2225,47 +2060,40 @@ std::string event_session_; }; -template <class T> -std::unique_ptr<SyncWebSocket> CreateMockSyncWebSocket_S( - const std::string& arg) { - return std::make_unique<T>(arg); -} - } // namespace TEST_F(DevToolsClientImplTest, AttachToConnected) { - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket<MultiSessionMockSyncWebSocket>); - DevToolsClientImpl root_client("root_client", "root_session", "http://url", - factory); + SocketHolder<MultiSessionMockSyncWebSocket> socket_holder; + DevToolsClientImpl root_client("root_client", "root_session"); DevToolsClientImpl client("page_client", "page_session"); - ASSERT_TRUE(StatusOk(root_client.Connect())); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); ASSERT_TRUE(root_client.IsConnected()); EXPECT_TRUE(StatusOk(client.AttachTo(&root_client))); EXPECT_TRUE(client.IsConnected()); } TEST_F(DevToolsClientImplTest, RoutingChildParent) { - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket<MultiSessionMockSyncWebSocket>); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<MultiSessionMockSyncWebSocket> socket_holder; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl client("child", "child_session"); ASSERT_TRUE(StatusOk(client.AttachTo(&root_client))); - ASSERT_TRUE(StatusOk(root_client.Connect())); base::Value::Dict params; params.Set("param", 1); ASSERT_TRUE(StatusOk(client.SendCommand("method", params))); } TEST_F(DevToolsClientImplTest, RoutingTwoChildren) { - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket<MultiSessionMockSyncWebSocket>); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<MultiSessionMockSyncWebSocket> socket_holder; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl red_client("red_client", "red_session"); DevToolsClientImpl blue_client("blue_client", "blue_session"); ASSERT_TRUE(StatusOk(red_client.AttachTo(&root_client))); ASSERT_TRUE(StatusOk(blue_client.AttachTo(&root_client))); - ASSERT_TRUE(StatusOk(root_client.Connect())); { base::Value::Dict params; params.Set("ping", 2); @@ -2286,19 +2114,19 @@ TEST_F(DevToolsClientImplTest, RoutingWithEvent) { const std::string blue_session = "blue_session"; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_S<MultiSessionMockSyncWebSocket2>, blue_session); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<MultiSessionMockSyncWebSocket2> socket_holder{blue_session}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl red_client("red_client", "red_session"); DevToolsClientImpl blue_client("blue_client", blue_session); - ASSERT_TRUE(StatusOk(red_client.AttachTo(&root_client))); - ASSERT_TRUE(StatusOk(blue_client.AttachTo(&root_client))); PingingListener blue_listener; blue_listener.SetPing(71); ASSERT_EQ(71, blue_listener.Ping()); ASSERT_NE(71, blue_listener.Pong()); blue_listener.AttachTo(&blue_client); - ASSERT_TRUE(StatusOk(root_client.Connect())); + ASSERT_TRUE(StatusOk(red_client.AttachTo(&root_client))); + ASSERT_TRUE(StatusOk(blue_client.AttachTo(&root_client))); { base::Value::Dict params; params.Set("ping", 12); @@ -2607,12 +2435,6 @@ raw_ptr<int> wrapped_ping_counter_ = nullptr; }; -template <typename T> -std::unique_ptr<SyncWebSocket> CreateMockSyncWebSocket_S_IPtr(std::string s, - int* iptr) { - return std::unique_ptr<SyncWebSocket>(new T(s, iptr)); -} - class BidiEventListener : public DevToolsEventListener { public: BidiEventListener() = default; @@ -2654,14 +2476,14 @@ TEST_F(DevToolsClientImplTest, BidiCommand) { std::string mapper_session = "mapper_session"; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_S<BidiMockSyncWebSocket>, mapper_session); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<BidiMockSyncWebSocket> socket_holder{mapper_session}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl mapper_client("mapper_client", mapper_session); BidiEventListener bidi_listener; mapper_client.AddListener(&bidi_listener); ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); - ASSERT_TRUE(StatusOk(root_client.Connect())); ASSERT_TRUE(StatusOk(mapper_client.AppointAsBidiServerForTesting())); base::Value::Dict params; params.Set("ping", 196); @@ -2683,14 +2505,14 @@ // In this test we check that the response ids are restored in accordance to // the original command ids. std::string mapper_session = "mapper_session"; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_S<BidiMockSyncWebSocket>, mapper_session); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<BidiMockSyncWebSocket> socket_holder{mapper_session}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl mapper_client("mapper_client", mapper_session); BidiEventListener bidi_listener; mapper_client.AddListener(&bidi_listener); ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); - ASSERT_TRUE(StatusOk(root_client.Connect())); ASSERT_TRUE(StatusOk(mapper_client.AppointAsBidiServerForTesting())); for (int cmd_id : {2, 3, 11, 1000021, 1000022, 1000023}) { @@ -2708,15 +2530,15 @@ TEST_F(DevToolsClientImplTest, CdpCommandTunneling) { int wrapped_counter = 0; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_S_IPtr<MultiSessionMockSyncWebSocket3>, - "mapper_session", &wrapped_counter); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<MultiSessionMockSyncWebSocket3> socket_holder{"mapper_session", + &wrapped_counter}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl page_client("page_client", "blue_session"); DevToolsClientImpl mapper_client("mapper_client", "mapper_session"); ASSERT_TRUE(StatusOk(page_client.AttachTo(&root_client))); ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); - ASSERT_TRUE(StatusOk(root_client.Connect())); // Set the tunnel session after all connections to avoid handshake mocking ASSERT_TRUE(StatusOk(mapper_client.AppointAsBidiServerForTesting())); ASSERT_TRUE( @@ -2875,15 +2697,14 @@ TEST_F(DevToolsClientImplTest, BidiEvent) { std::string mapper_session = "mapper_session"; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_S<MultiSessionMockSyncWebSocket4>, - mapper_session); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<MultiSessionMockSyncWebSocket4> socket_holder{mapper_session}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl mapper_client("mapper_client", mapper_session); BidiEventListener bidi_listener; mapper_client.AddListener(&bidi_listener); ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); - ASSERT_TRUE(StatusOk(root_client.Connect())); ASSERT_TRUE(StatusOk(mapper_client.AppointAsBidiServerForTesting())); base::Value::Dict bidi_cmd; ASSERT_TRUE(StatusOk(CreateBidiCommand(37, "method", base::Value::Dict(), @@ -2900,10 +2721,10 @@ TEST_F(DevToolsClientImplTest, BidiEventCrossRouting) { std::string mapper_session = "mapper_session"; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_S<MultiSessionMockSyncWebSocket4>, - mapper_session); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<MultiSessionMockSyncWebSocket4> socket_holder{mapper_session}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); // Green is the BiDiMapper in this test DevToolsClientImpl mapper_client("mapper_client", mapper_session); DevToolsClientImpl page_client("page_client", "blue_session"); @@ -2911,7 +2732,6 @@ mapper_client.AddListener(&bidi_listener); ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); ASSERT_TRUE(StatusOk(page_client.AttachTo(&root_client))); - ASSERT_TRUE(StatusOk(root_client.Connect())); ASSERT_TRUE(StatusOk(mapper_client.AppointAsBidiServerForTesting())); ASSERT_TRUE( StatusOk(page_client.SetTunnelSessionId(mapper_client.SessionId()))); @@ -2934,10 +2754,10 @@ TEST_F(DevToolsClientImplTest, CdpEventTunneling) { std::string mapper_session = "mapper_session"; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_S<MultiSessionMockSyncWebSocket4>, - mapper_session); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<MultiSessionMockSyncWebSocket4> socket_holder{mapper_session}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl page_client("page_client", "red_session"); DevToolsClientImpl mapper_client("mapper_client", mapper_session); BidiEventListener mapper_bidi_listener; @@ -2946,7 +2766,6 @@ page_client.AddListener(&red_cdp_listener); ASSERT_TRUE(StatusOk(page_client.AttachTo(&root_client))); ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); - ASSERT_TRUE(StatusOk(root_client.Connect())); ASSERT_TRUE(StatusOk(mapper_client.AppointAsBidiServerForTesting())); ASSERT_TRUE( StatusOk(page_client.SetTunnelSessionId(mapper_client.SessionId()))); @@ -2964,15 +2783,14 @@ TEST_F(DevToolsClientImplTest, BidiChannels) { // Corner cases for channels std::string mapper_session = "mapper_session"; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_S<MultiSessionMockSyncWebSocket4>, - mapper_session); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<MultiSessionMockSyncWebSocket4> socket_holder{mapper_session}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl mapper_client("mapper_client", mapper_session); BidiEventListener mapper_bidi_listener; mapper_client.AddListener(&mapper_bidi_listener); ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); - ASSERT_TRUE(StatusOk(root_client.Connect())); ASSERT_TRUE(StatusOk(mapper_client.AppointAsBidiServerForTesting())); for (std::string channel : {DevToolsClientImpl::kCdpTunnelChannel, @@ -3106,25 +2924,18 @@ raw_ptr<BidiMapperState> mapper_state_ = nullptr; }; -template <typename T> -std::unique_ptr<SyncWebSocket> CreateMockSyncWebSocket_BidiMapperState( - BidiMapperState* mapper_state) { - return std::unique_ptr<SyncWebSocket>(new T(mapper_state)); -} - } // namespace TEST_F(DevToolsClientImplTest, StartBidiServer) { BidiMapperState mapper_state; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_BidiMapperState<BidiServerMockSyncWebSocket>, - &mapper_state); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<BidiServerMockSyncWebSocket> socket_holder{&mapper_state}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl mapper_client("mapper_client", "mapper_session"); mapper_client.EnableEventTunnelingForTesting(); - ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); mapper_client.SetMainPage(true); - ASSERT_TRUE(StatusOk(root_client.Connect())); + ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); EXPECT_TRUE(StatusOk(mapper_client.StartBidiServer(kTestMapperScript))); EXPECT_TRUE(mapper_state.devtools_exposed); @@ -3137,15 +2948,14 @@ TEST_F(DevToolsClientImplTest, StartBidiServerWaitsForLaunched) { BidiMapperState mapper_state; mapper_state.emit_launched = false; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_BidiMapperState<BidiServerMockSyncWebSocket>, - &mapper_state); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<BidiServerMockSyncWebSocket> socket_holder{&mapper_state}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl mapper_client("mapper_client", "mapper_session"); mapper_client.EnableEventTunnelingForTesting(); - ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); mapper_client.SetMainPage(true); - ASSERT_TRUE(StatusOk(root_client.Connect())); + ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); EXPECT_EQ(kTimeout, mapper_client @@ -3155,44 +2965,40 @@ TEST_F(DevToolsClientImplTest, StartBidiServerNotConnected) { BidiMapperState mapper_state; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_BidiMapperState<BidiServerMockSyncWebSocket>, - &mapper_state); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<BidiServerMockSyncWebSocket> socket_holder{&mapper_state}; + DevToolsClientImpl root_client("root", "root_session"); DevToolsClientImpl mapper_client("mapper_client", "mapper_session"); mapper_client.EnableEventTunnelingForTesting(); - ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); mapper_client.SetMainPage(true); + ASSERT_TRUE(mapper_client.AttachTo(&root_client).IsError()); EXPECT_TRUE(mapper_client.StartBidiServer(kTestMapperScript).IsError()); } TEST_F(DevToolsClientImplTest, StartBidiServerNotAPageClient) { BidiMapperState mapper_state; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_BidiMapperState<BidiServerMockSyncWebSocket>, - &mapper_state); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<BidiServerMockSyncWebSocket> socket_holder{&mapper_state}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl mapper_client("mapper_client", "mapper_session"); mapper_client.EnableEventTunnelingForTesting(); ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); - ASSERT_TRUE(StatusOk(root_client.Connect())); EXPECT_TRUE(mapper_client.StartBidiServer(kTestMapperScript).IsError()); } TEST_F(DevToolsClientImplTest, StartBidiServerTunnelIsAlreadySet) { BidiMapperState mapper_state; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_BidiMapperState<BidiServerMockSyncWebSocket>, - &mapper_state); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<BidiServerMockSyncWebSocket> socket_holder{&mapper_state}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl pink_client("pink_client", "pink_session"); DevToolsClientImpl mapper_client("mapper_client", "mapper_session"); mapper_client.EnableEventTunnelingForTesting(); mapper_client.SetMainPage(true); ASSERT_TRUE(StatusOk(pink_client.AttachTo(&root_client))); - ASSERT_TRUE(StatusOk(root_client.Connect())); ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); mapper_client.SetTunnelSessionId(pink_client.SessionId()); @@ -3202,15 +3008,14 @@ TEST_F(DevToolsClientImplTest, StartBidiServerFailOnAddBidiResponseBinding) { BidiMapperState mapper_state; mapper_state.fail_on_add_bidi_response_binding = true; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_BidiMapperState<BidiServerMockSyncWebSocket>, - &mapper_state); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<BidiServerMockSyncWebSocket> socket_holder{&mapper_state}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl mapper_client("mapper_client", "mapper_session"); mapper_client.EnableEventTunnelingForTesting(); - ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); mapper_client.SetMainPage(true); - ASSERT_TRUE(StatusOk(root_client.Connect())); + ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); EXPECT_TRUE(mapper_client.StartBidiServer(kTestMapperScript).IsError()); } @@ -3218,15 +3023,14 @@ TEST_F(DevToolsClientImplTest, StartBidiServerFailOnSetSelfTarget) { BidiMapperState mapper_state; mapper_state.fail_on_set_self_target_id = true; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_BidiMapperState<BidiServerMockSyncWebSocket>, - &mapper_state); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<BidiServerMockSyncWebSocket> socket_holder{&mapper_state}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl mapper_client("mapper_client", "mapper_session"); mapper_client.EnableEventTunnelingForTesting(); - ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); mapper_client.SetMainPage(true); - ASSERT_TRUE(StatusOk(root_client.Connect())); + ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); EXPECT_TRUE(mapper_client.StartBidiServer(kTestMapperScript).IsError()); } @@ -3234,15 +3038,14 @@ TEST_F(DevToolsClientImplTest, StartBidiServerFailOnExposeDevTools) { BidiMapperState mapper_state; mapper_state.fail_on_expose_devtools = true; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_BidiMapperState<BidiServerMockSyncWebSocket>, - &mapper_state); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<BidiServerMockSyncWebSocket> socket_holder{&mapper_state}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl mapper_client("mapper_client", "mapper_session"); mapper_client.EnableEventTunnelingForTesting(); - ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); mapper_client.SetMainPage(true); - ASSERT_TRUE(StatusOk(root_client.Connect())); + ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); EXPECT_TRUE(mapper_client.StartBidiServer(kTestMapperScript).IsError()); } @@ -3250,15 +3053,14 @@ TEST_F(DevToolsClientImplTest, StartBidiServerFailOnMapper) { BidiMapperState mapper_state; mapper_state.fail_on_mapper = true; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_BidiMapperState<BidiServerMockSyncWebSocket>, - &mapper_state); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<BidiServerMockSyncWebSocket> socket_holder{&mapper_state}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl mapper_client("mapper_client", "mapper_session"); mapper_client.EnableEventTunnelingForTesting(); - ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); mapper_client.SetMainPage(true); - ASSERT_TRUE(StatusOk(root_client.Connect())); + ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); EXPECT_TRUE(mapper_client.StartBidiServer(kTestMapperScript).IsError()); } @@ -3266,15 +3068,14 @@ TEST_F(DevToolsClientImplTest, StartBidiServerFailOnSubscribeToCdp) { BidiMapperState mapper_state; mapper_state.fail_on_subscribe_to_cdp = true; - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket_BidiMapperState<BidiServerMockSyncWebSocket>, - &mapper_state); - DevToolsClientImpl root_client("root", "root_session", "http://url", factory); + SocketHolder<BidiServerMockSyncWebSocket> socket_holder{&mapper_state}; + DevToolsClientImpl root_client("root", "root_session"); + ASSERT_TRUE(socket_holder.ConnectSocket()); + ASSERT_TRUE(StatusOk(root_client.SetSocket(socket_holder.Wrapper()))); DevToolsClientImpl mapper_client("mapper_client", "mapper_session"); mapper_client.EnableEventTunnelingForTesting(); - ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); mapper_client.SetMainPage(true); - ASSERT_TRUE(StatusOk(root_client.Connect())); + ASSERT_TRUE(StatusOk(mapper_client.AttachTo(&root_client))); EXPECT_TRUE(mapper_client.StartBidiServer(kTestMapperScript).IsError()); }
diff --git a/chrome/test/chromedriver/chrome/stub_devtools_client.cc b/chrome/test/chromedriver/chrome/stub_devtools_client.cc index eac0988..98329e7 100644 --- a/chrome/test/chromedriver/chrome/stub_devtools_client.cc +++ b/chrome/test/chromedriver/chrome/stub_devtools_client.cc
@@ -48,11 +48,6 @@ return false; } -Status StubDevToolsClient::Connect() { - is_connected_ = true; - return Status(kOk); -} - Status StubDevToolsClient::PostBidiCommand(base::Value::Dict command) { return Status{kOk}; }
diff --git a/chrome/test/chromedriver/chrome/stub_devtools_client.h b/chrome/test/chromedriver/chrome/stub_devtools_client.h index a0d32f4..97a20c4 100644 --- a/chrome/test/chromedriver/chrome/stub_devtools_client.h +++ b/chrome/test/chromedriver/chrome/stub_devtools_client.h
@@ -28,7 +28,6 @@ bool IsNull() const override; bool WasCrashed() override; bool IsConnected() const override; - Status Connect() override; Status PostBidiCommand(base::Value::Dict command) override; Status SendCommand(const std::string& method, const base::Value::Dict& params) override;
diff --git a/chrome/test/chromedriver/chrome/web_view_impl_unittest.cc b/chrome/test/chromedriver/chrome/web_view_impl_unittest.cc index 1aa4647b..1904b8f4 100644 --- a/chrome/test/chromedriver/chrome/web_view_impl_unittest.cc +++ b/chrome/test/chromedriver/chrome/web_view_impl_unittest.cc
@@ -26,7 +26,6 @@ #include "chrome/test/chromedriver/chrome/status.h" #include "chrome/test/chromedriver/chrome/stub_devtools_client.h" #include "chrome/test/chromedriver/net/sync_websocket.h" -#include "chrome/test/chromedriver/net/sync_websocket_factory.h" #include "chrome/test/chromedriver/net/timeout.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -214,6 +213,49 @@ ASSERT_TRUE(result.empty()); } +class SyncWebSocketWrapper : public SyncWebSocket { + public: + explicit SyncWebSocketWrapper(SyncWebSocket* socket) : socket_(socket) {} + ~SyncWebSocketWrapper() override = default; + + bool IsConnected() override { return socket_->IsConnected(); } + + bool Connect(const GURL& url) override { return socket_->Connect(url); } + + bool Send(const std::string& message) override { + return socket_->Send(message); + } + + SyncWebSocket::StatusCode ReceiveNextMessage( + std::string* message, + const Timeout& timeout) override { + return socket_->ReceiveNextMessage(message, timeout); + } + + bool HasNextMessage() override { return socket_->HasNextMessage(); } + + private: + raw_ptr<SyncWebSocket> socket_; +}; + +template <typename TSocket> +class SocketHolder { + public: + template <typename... Args> + explicit SocketHolder(Args&&... args) : socket_{args...} {} + + std::unique_ptr<SyncWebSocket> Wrapper() { + return std::unique_ptr<SyncWebSocket>(new SyncWebSocketWrapper(&socket_)); + } + + TSocket& Socket() { return socket_; } + + bool ConnectSocket() { return socket_.Connect(GURL("http://url/")); } + + private: + TSocket socket_; +}; + } // namespace TEST(EvaluateScript, CommandError) { @@ -381,51 +423,20 @@ SyncWebSocket::StatusCode next_status_; }; -std::unique_ptr<SyncWebSocket> CreateMockSyncWebSocket( - SyncWebSocket::StatusCode next_status) { - return std::make_unique<MockSyncWebSocket>(next_status); -} - -class SyncWebSocketWrapper : public SyncWebSocket { - public: - explicit SyncWebSocketWrapper(SyncWebSocket* socket) : socket_(socket) {} - ~SyncWebSocketWrapper() override = default; - - bool IsConnected() override { return socket_->IsConnected(); } - - bool Connect(const GURL& url) override { return socket_->Connect(url); } - - bool Send(const std::string& message) override { - return socket_->Send(message); - } - - SyncWebSocket::StatusCode ReceiveNextMessage( - std::string* message, - const Timeout& timeout) override { - return socket_->ReceiveNextMessage(message, timeout); - } - - bool HasNextMessage() override { return socket_->HasNextMessage(); } - - private: - raw_ptr<SyncWebSocket> socket_; -}; - } // namespace TEST(CreateChild, MultiLevel) { - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket, SyncWebSocket::StatusCode::kOk); + SocketHolder<MockSyncWebSocket> socket_holder{SyncWebSocket::StatusCode::kOk}; // CreateChild relies on client_ being a DevToolsClientImpl, so no mocking std::unique_ptr<DevToolsClientImpl> client_uptr = - std::make_unique<DevToolsClientImpl>("id", "", "http://url", factory); + std::make_unique<DevToolsClientImpl>("id", ""); DevToolsClientImpl* client_ptr = client_uptr.get(); BrowserInfo browser_info; WebViewImpl level1(client_ptr->GetId(), true, nullptr, &browser_info, std::move(client_uptr), absl::nullopt, PageLoadStrategy::kEager); - Status status = client_ptr->Connect(); - ASSERT_EQ(kOk, status.code()) << status.message(); + EXPECT_TRUE(socket_holder.ConnectSocket()); + EXPECT_TRUE(StatusOk(client_ptr->SetSocket(socket_holder.Wrapper()))); std::string sessionid = "2"; std::unique_ptr<WebViewImpl> level2 = std::unique_ptr<WebViewImpl>(level1.CreateChild(sessionid, "1234")); @@ -441,18 +452,17 @@ } TEST(CreateChild, IsNonBlocking_NoErrors) { - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket, SyncWebSocket::StatusCode::kOk); + SocketHolder<MockSyncWebSocket> socket_holder{SyncWebSocket::StatusCode::kOk}; // CreateChild relies on client_ being a DevToolsClientImpl, so no mocking std::unique_ptr<DevToolsClientImpl> client_uptr = - std::make_unique<DevToolsClientImpl>("id", "", "http://url", factory); + std::make_unique<DevToolsClientImpl>("id", ""); DevToolsClientImpl* client_ptr = client_uptr.get(); BrowserInfo browser_info; WebViewImpl parent_view(client_ptr->GetId(), true, nullptr, &browser_info, std::move(client_uptr), absl::nullopt, PageLoadStrategy::kEager); - Status status = client_ptr->Connect(); - ASSERT_EQ(kOk, status.code()) << status.message(); + EXPECT_TRUE(socket_holder.ConnectSocket()); + EXPECT_TRUE(StatusOk(client_ptr->SetSocket(socket_holder.Wrapper()))); ASSERT_FALSE(parent_view.IsNonBlocking()); std::string sessionid = "2"; @@ -464,18 +474,17 @@ } TEST(CreateChild, Load_NoErrors) { - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket, SyncWebSocket::StatusCode::kOk); + SocketHolder<MockSyncWebSocket> socket_holder{SyncWebSocket::StatusCode::kOk}; // CreateChild relies on client_ being a DevToolsClientImpl, so no mocking std::unique_ptr<DevToolsClientImpl> client_uptr = - std::make_unique<DevToolsClientImpl>("id", "", "http://url", factory); + std::make_unique<DevToolsClientImpl>("id", ""); DevToolsClientImpl* client_ptr = client_uptr.get(); BrowserInfo browser_info; WebViewImpl parent_view(client_ptr->GetId(), true, nullptr, &browser_info, std::move(client_uptr), absl::nullopt, PageLoadStrategy::kNone); - Status status = client_ptr->Connect(); - ASSERT_EQ(kOk, status.code()) << status.message(); + EXPECT_TRUE(socket_holder.ConnectSocket()); + EXPECT_TRUE(StatusOk(client_ptr->SetSocket(socket_holder.Wrapper()))); std::string sessionid = "2"; std::unique_ptr<WebViewImpl> child_view = std::unique_ptr<WebViewImpl>(parent_view.CreateChild(sessionid, "1234")); @@ -485,47 +494,40 @@ } TEST(CreateChild, WaitForPendingNavigations_NoErrors) { - std::unique_ptr<MockSyncWebSocket> socket = - std::make_unique<MockSyncWebSocket>(SyncWebSocket::StatusCode::kOk); - SyncWebSocketFactory factory = base::BindRepeating( - [](SyncWebSocket* socket) { - return std::unique_ptr<SyncWebSocket>(new SyncWebSocketWrapper(socket)); - }, - socket.get()); + SocketHolder<MockSyncWebSocket> socket_holder{SyncWebSocket::StatusCode::kOk}; // CreateChild relies on client_ being a DevToolsClientImpl, so no mocking std::unique_ptr<DevToolsClientImpl> client_uptr = - std::make_unique<DevToolsClientImpl>("id", "", "http://url", factory); + std::make_unique<DevToolsClientImpl>("id", ""); DevToolsClientImpl* client_ptr = client_uptr.get(); BrowserInfo browser_info; WebViewImpl parent_view(client_ptr->GetId(), true, nullptr, &browser_info, std::move(client_uptr), absl::nullopt, PageLoadStrategy::kNone); - Status status = client_ptr->Connect(); - ASSERT_EQ(kOk, status.code()) << status.message(); + EXPECT_TRUE(socket_holder.ConnectSocket()); + EXPECT_TRUE(StatusOk(client_ptr->SetSocket(socket_holder.Wrapper()))); std::string sessionid = "2"; std::unique_ptr<WebViewImpl> child_view = std::unique_ptr<WebViewImpl>(parent_view.CreateChild(sessionid, "1234")); child_view->AttachTo(client_ptr); // child_view gets no socket... - socket->SetNexStatusCode(SyncWebSocket::StatusCode::kTimeout); + socket_holder.Socket().SetNexStatusCode(SyncWebSocket::StatusCode::kTimeout); ASSERT_NO_FATAL_FAILURE(child_view->WaitForPendingNavigations( "1234", Timeout(base::Milliseconds(10)), true)); } TEST(CreateChild, IsPendingNavigation_NoErrors) { - SyncWebSocketFactory factory = base::BindRepeating( - &CreateMockSyncWebSocket, SyncWebSocket::StatusCode::kOk); + SocketHolder<MockSyncWebSocket> socket_holder{SyncWebSocket::StatusCode::kOk}; // CreateChild relies on client_ being a DevToolsClientImpl, so no mocking std::unique_ptr<DevToolsClientImpl> client_uptr = - std::make_unique<DevToolsClientImpl>("id", "", "http://url", factory); + std::make_unique<DevToolsClientImpl>("id", ""); DevToolsClientImpl* client_ptr = client_uptr.get(); BrowserInfo browser_info; WebViewImpl parent_view(client_ptr->GetId(), true, nullptr, &browser_info, std::move(client_uptr), absl::nullopt, PageLoadStrategy::kNormal); - Status status = client_ptr->Connect(); - ASSERT_EQ(kOk, status.code()) << status.message(); + EXPECT_TRUE(socket_holder.ConnectSocket()); + EXPECT_TRUE(StatusOk(client_ptr->SetSocket(socket_holder.Wrapper()))); std::string sessionid = "2"; std::unique_ptr<WebViewImpl> child_view = std::unique_ptr<WebViewImpl>(parent_view.CreateChild(sessionid, "1234"));
diff --git a/chrome/test/chromedriver/chrome_launcher.cc b/chrome/test/chromedriver/chrome_launcher.cc index 2c5122b..9929294 100644 --- a/chrome/test/chromedriver/chrome_launcher.cc +++ b/chrome/test/chromedriver/chrome_launcher.cc
@@ -52,6 +52,8 @@ #include "chrome/test/chromedriver/log_replay/chrome_replay_impl.h" #include "chrome/test/chromedriver/log_replay/replay_http_client.h" #include "chrome/test/chromedriver/net/net_util.h" +#include "chrome/test/chromedriver/net/sync_websocket.h" +#include "chrome/test/chromedriver/net/sync_websocket_factory.h" #include "components/crx_file/crx_verifier.h" #include "components/embedder_support/switches.h" #include "crypto/rsa_private_key.h" @@ -343,9 +345,10 @@ if (url.length() == 0) { url = endpoint.GetBrowserDebuggerUrl(); } - std::unique_ptr<DevToolsClient> client( - new DevToolsClientImpl(DevToolsClientImpl::kBrowserwideDevToolsClientId, - "", url, socket_factory)); + std::unique_ptr<SyncWebSocket> socket = socket_factory.Run(); + SyncWebSocket* socket_ptr = socket.get(); + std::unique_ptr<DevToolsClientImpl> client(new DevToolsClientImpl( + DevToolsClientImpl::kBrowserwideDevToolsClientId, "")); for (const auto& listener : devtools_event_listeners) { // Only add listeners that subscribe to the browser-wide |DevToolsClient|. // Otherwise, listeners will think this client is associated with a webview, @@ -354,8 +357,12 @@ client->AddListener(listener.get()); } + DevToolsClientImpl* client_impl = client.get(); *browser_client = std::move(client); - return (*browser_client)->Connect(); + if (!socket_ptr->Connect(GURL(url))) { + return Status(kDisconnected, "unable to connect to renderer"); + } + return client_impl->SetSocket(std::move(socket)); } Status LaunchRemoteChromeSession(
diff --git a/chrome/test/chromedriver/net/sync_websocket.h b/chrome/test/chromedriver/net/sync_websocket.h index ac4c564..7f5109d 100644 --- a/chrome/test/chromedriver/net/sync_websocket.h +++ b/chrome/test/chromedriver/net/sync_websocket.h
@@ -17,7 +17,7 @@ public: enum class StatusCode { kOk = 0, kTimeout, kDisconnected }; - virtual ~SyncWebSocket() {} + virtual ~SyncWebSocket() = default; virtual void SetId(const std::string& socket_id) {}
diff --git a/chrome/test/chromedriver/net/websocket.h b/chrome/test/chromedriver/net/websocket.h index ec400d3..685237c5 100644 --- a/chrome/test/chromedriver/net/websocket.h +++ b/chrome/test/chromedriver/net/websocket.h
@@ -93,7 +93,7 @@ // WebSocket. class WebSocketListener { public: - virtual ~WebSocketListener() {} + virtual ~WebSocketListener() = default; // Called when a WebSocket message is received. virtual void OnMessageReceived(const std::string& message) = 0;
diff --git a/chrome/test/chromedriver/performance_logger_unittest.cc b/chrome/test/chromedriver/performance_logger_unittest.cc index 5a742bb..898644f 100644 --- a/chrome/test/chromedriver/performance_logger_unittest.cc +++ b/chrome/test/chromedriver/performance_logger_unittest.cc
@@ -30,7 +30,7 @@ : method(in_method) { params.reset(in_params); } - ~DevToolsCommand() {} + ~DevToolsCommand() = default; std::string method; std::unique_ptr<base::Value::Dict> params; @@ -38,9 +38,8 @@ class FakeDevToolsClient : public StubDevToolsClient { public: - explicit FakeDevToolsClient(const std::string& id) - : id_(id), listener_(nullptr), command_index_(0) {} - ~FakeDevToolsClient() override {} + explicit FakeDevToolsClient(const std::string& id) : id_(id) {} + ~FakeDevToolsClient() override = default; bool PopSentCommand(DevToolsCommand** out_command) { if (sent_commands_.size() > command_index_) { @@ -59,9 +58,6 @@ return TriggerEvent(method, base::Value::Dict()); } - // Overridden from DevToolsClient: - Status Connect() override { return listener_->OnConnected(this); } - Status SendCommandAndGetResult(const std::string& method, const base::Value::Dict& params, base::Value::Dict* result) override { @@ -87,9 +83,9 @@ const std::string id_; // WebView id. std::vector<std::unique_ptr<DevToolsCommand>> sent_commands_; // Commands that were sent. - raw_ptr<DevToolsEventListener> - listener_; // The fake allows only one event listener. - size_t command_index_; + raw_ptr<DevToolsEventListener> listener_ = + nullptr; // The fake allows only one event listener. + size_t command_index_ = 0; }; struct LogEntry { @@ -227,7 +223,7 @@ ExpectEnableDomains(&client1); ExpectEnableDomains(&client2); // OnConnected sends the enable command only to that client, not others. - client1.Connect(); + logger.OnConnected(&client1); ExpectEnableDomains(&client1); DevToolsCommand* cmd; ASSERT_FALSE(client2.PopSentCommand(&cmd)); @@ -267,9 +263,8 @@ class FakeBrowserwideClient : public FakeDevToolsClient { public: FakeBrowserwideClient() - : FakeDevToolsClient(DevToolsClientImpl::kBrowserwideDevToolsClientId), - events_handled_(false) {} - ~FakeBrowserwideClient() override {} + : FakeDevToolsClient(DevToolsClientImpl::kBrowserwideDevToolsClientId) {} + ~FakeBrowserwideClient() override = default; bool events_handled() const { return events_handled_; @@ -284,7 +279,7 @@ } private: - bool events_handled_; + bool events_handled_ = false; }; } // namespace
diff --git a/chrome/test/data/bruschetta/download_file.img b/chrome/test/data/bruschetta/download_file.img new file mode 100644 index 0000000..0e1a730 --- /dev/null +++ b/chrome/test/data/bruschetta/download_file.img
@@ -0,0 +1 @@ +The contents don't matter and neither do the points
diff --git a/chrome/test/webapps/coverage/coverage_cros.tsv b/chrome/test/webapps/coverage/coverage_cros.tsv index 72d347b..38e15b0 100644 --- a/chrome/test/webapps/coverage/coverage_cros.tsv +++ b/chrome/test/webapps/coverage/coverage_cros.tsv
@@ -157,6 +157,11 @@ install_policy_app_NotPromotable_WithShortcut_Browser_WebApp🌓 check_platform_shortcut_and_icon_NotPromotable🌓 create_shortcut_NotPromotable_Windowed🌕 check_platform_shortcut_and_icon_NotPromotable🌓 create_shortcut_NotPromotable_Browser🌕 check_platform_shortcut_and_icon_NotPromotable🌓 +create_shortcut_Standalone_Browser🌕 launch_from_platform_shortcut_Standalone🌑 check_tab_created_One🌑 +create_shortcut_Standalone_Browser🌕 launch_from_platform_shortcut_Standalone🌑 install_omnibox_icon_Standalone🌑 check_pwa_window_created_in_profile_Standalone_One_Default🌑 +create_shortcut_Standalone_Windowed🌕 check_window_created🌕 +create_shortcut_Standalone_Windowed🌕 close_pwa🌕 check_app_in_list_windowed_Standalone🌓 check_platform_shortcut_and_icon_Standalone🌓 +create_shortcut_Standalone_Windowed🌕 close_pwa🌕 launch_from_platform_shortcut_Standalone🌑 check_pwa_window_created_in_profile_Standalone_One_Default🌑 check_launch_icon_not_shown🌑 create_shortcut_Standalone_Browser🌕 uninstall_from_list_Standalone🌕 check_app_not_in_list_Standalone🌓 create_shortcut_Standalone_Browser🌕 uninstall_from_list_Standalone🌕 navigate_browser_Standalone🌕 check_install_icon_shown🌕 create_shortcut_Standalone_Browser🌕 uninstall_from_list_Standalone🌕 navigate_browser_Standalone🌕 check_launch_icon_not_shown🌕
diff --git a/chrome/test/webapps/coverage/coverage_linux.tsv b/chrome/test/webapps/coverage/coverage_linux.tsv index 19677957..e913eaa 100644 --- a/chrome/test/webapps/coverage/coverage_linux.tsv +++ b/chrome/test/webapps/coverage/coverage_linux.tsv
@@ -373,6 +373,11 @@ install_policy_app_NotPromotable_WithShortcut_Browser_WebApp🌓 check_platform_shortcut_and_icon_NotPromotable🌓 create_shortcut_NotPromotable_Windowed🌕 check_platform_shortcut_and_icon_NotPromotable🌓 create_shortcut_NotPromotable_Browser🌕 check_platform_shortcut_and_icon_NotPromotable🌓 +create_shortcut_Standalone_Browser🌕 launch_from_platform_shortcut_Standalone🌓 check_tab_created_One🌕 +create_shortcut_Standalone_Browser🌕 launch_from_platform_shortcut_Standalone🌓 install_omnibox_icon_Standalone🌕 check_pwa_window_created_in_profile_Standalone_One_Default🌕 +create_shortcut_Standalone_Windowed🌕 check_window_created🌕 +create_shortcut_Standalone_Windowed🌕 close_pwa🌕 check_app_in_list_windowed_Standalone🌕 check_platform_shortcut_and_icon_Standalone🌓 +create_shortcut_Standalone_Windowed🌕 close_pwa🌕 launch_from_platform_shortcut_Standalone🌓 check_pwa_window_created_in_profile_Standalone_One_Default🌕 check_launch_icon_not_shown🌕 create_shortcut_Standalone_Windowed🌕 uninstall_from_list_Standalone🌕 check_app_not_in_list_Standalone🌕 create_shortcut_Standalone_Windowed🌕 uninstall_from_menu_Standalone🌕 check_app_not_in_list_Standalone🌕 create_shortcut_Standalone_Windowed🌕 uninstall_from_os_Standalone🌑 check_app_not_in_list_Standalone🌑
diff --git a/chrome/test/webapps/coverage/coverage_mac.tsv b/chrome/test/webapps/coverage/coverage_mac.tsv index 61ec13d..ee6527c 100644 --- a/chrome/test/webapps/coverage/coverage_mac.tsv +++ b/chrome/test/webapps/coverage/coverage_mac.tsv
@@ -373,6 +373,11 @@ install_policy_app_NotPromotable_WithShortcut_Browser_WebApp🌓 check_platform_shortcut_and_icon_NotPromotable🌕 create_shortcut_NotPromotable_Windowed🌕 check_platform_shortcut_and_icon_NotPromotable🌕 create_shortcut_NotPromotable_Browser🌕 check_platform_shortcut_and_icon_NotPromotable🌕 +create_shortcut_Standalone_Browser🌕 launch_from_platform_shortcut_Standalone🌓 check_tab_created_One🌕 +create_shortcut_Standalone_Browser🌕 launch_from_platform_shortcut_Standalone🌓 install_omnibox_icon_Standalone🌕 check_pwa_window_created_in_profile_Standalone_One_Default🌕 +create_shortcut_Standalone_Windowed🌕 check_window_created🌕 +create_shortcut_Standalone_Windowed🌕 close_pwa🌕 check_app_in_list_windowed_Standalone🌕 check_platform_shortcut_and_icon_Standalone🌕 +create_shortcut_Standalone_Windowed🌕 close_pwa🌕 launch_from_platform_shortcut_Standalone🌓 check_pwa_window_created_in_profile_Standalone_One_Default🌕 check_launch_icon_not_shown🌕 create_shortcut_Standalone_Windowed🌕 uninstall_from_list_Standalone🌕 check_app_not_in_list_Standalone🌕 create_shortcut_Standalone_Windowed🌕 uninstall_from_menu_Standalone🌕 check_app_not_in_list_Standalone🌕 create_shortcut_Standalone_Windowed🌕 uninstall_from_os_Standalone🌑 check_app_not_in_list_Standalone🌑
diff --git a/chrome/test/webapps/coverage/coverage_win.tsv b/chrome/test/webapps/coverage/coverage_win.tsv index f056945..1fb6d68 100644 --- a/chrome/test/webapps/coverage/coverage_win.tsv +++ b/chrome/test/webapps/coverage/coverage_win.tsv
@@ -373,6 +373,11 @@ install_policy_app_NotPromotable_WithShortcut_Browser_WebApp🌓 check_platform_shortcut_and_icon_NotPromotable🌓 create_shortcut_NotPromotable_Windowed🌕 check_platform_shortcut_and_icon_NotPromotable🌓 create_shortcut_NotPromotable_Browser🌕 check_platform_shortcut_and_icon_NotPromotable🌓 +create_shortcut_Standalone_Browser🌕 launch_from_platform_shortcut_Standalone🌓 check_tab_created_One🌕 +create_shortcut_Standalone_Browser🌕 launch_from_platform_shortcut_Standalone🌓 install_omnibox_icon_Standalone🌕 check_pwa_window_created_in_profile_Standalone_One_Default🌕 +create_shortcut_Standalone_Windowed🌕 check_window_created🌕 +create_shortcut_Standalone_Windowed🌕 close_pwa🌕 check_app_in_list_windowed_Standalone🌕 check_platform_shortcut_and_icon_Standalone🌓 +create_shortcut_Standalone_Windowed🌕 close_pwa🌕 launch_from_platform_shortcut_Standalone🌓 check_pwa_window_created_in_profile_Standalone_One_Default🌕 check_launch_icon_not_shown🌕 create_shortcut_Standalone_Windowed🌕 uninstall_from_list_Standalone🌕 check_app_not_in_list_Standalone🌕 create_shortcut_Standalone_Windowed🌕 uninstall_from_menu_Standalone🌕 check_app_not_in_list_Standalone🌕 create_shortcut_Standalone_Windowed🌕 uninstall_from_os_Standalone🌕 check_app_not_in_list_Standalone🌕
diff --git a/chrome/test/webapps/data/critical_user_journeys.md b/chrome/test/webapps/data/critical_user_journeys.md index 473c77a..a01130e 100644 --- a/chrome/test/webapps/data/critical_user_journeys.md +++ b/chrome/test/webapps/data/critical_user_journeys.md
@@ -84,7 +84,11 @@ | WMLC | install_or_shortcut_windowed(NotPromotable) | navigate_browser(NotPromotable) | check_launch_icon_shown | | WMLC | install_or_shortcut_with_shortcut | check_platform_shortcut_and_icon | | WMLC | install_or_shortcut_with_shortcut(NotPromotable) | check_platform_shortcut_and_icon(NotPromotable) | - +| WMLC | install_or_shortcut_by_user_tabbed(Standalone) | launch_from_platform_shortcut(Standalone) | check_tab_created(One) | +| WMLC | install_or_shortcut_by_user_tabbed(Standalone) | launch_from_platform_shortcut(Standalone) | install_omnibox_icon(Standalone) | check_pwa_window_created_in_profile(Standalone, One, Default) +| WMLC | create_shortcut(Standalone, Windowed) | check_window_created | +| WMLC | create_shortcut(Standalone, Windowed) | close_pwa | check_app_in_list_windowed(Standalone) | check_platform_shortcut_and_icon(Standalone) | +| WMLC | create_shortcut(Standalone, Windowed) | close_pwa | launch_from_platform_shortcut(Standalone) | check_pwa_window_created_in_profile(Standalone, One, Default) | check_launch_icon_not_shown | ## Uninstallation | #Platforms | Test -> | | | | | | | | | | | | | | | | |
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn index 3be0c515..f19f4ab 100644 --- a/chrome/updater/BUILD.gn +++ b/chrome/updater/BUILD.gn
@@ -695,7 +695,7 @@ ] if (is_win) { sources += [ - # TODO(crbug.com/1402743) - eliminate the dependency on //chrome/test. + # TODO(crbug.com/1447274) - eliminate the dependency on //chrome/test. "//chrome/test/base/process_inspector_win.cc", "//chrome/test/base/process_inspector_win.h", ]
diff --git a/chrome/updater/activity_impl_win.cc b/chrome/updater/activity_impl_win.cc index 2216416..92a92be 100644 --- a/chrome/updater/activity_impl_win.cc +++ b/chrome/updater/activity_impl_win.cc
@@ -135,9 +135,7 @@ bool GetActiveBit(UpdaterScope scope, const std::string& id) { switch (scope) { case UpdaterScope::kUser: - // TODO(crbug/1159498): Standardize registry access. return GetUserActiveBit(id); - case UpdaterScope::kSystem: return GetSystemActiveBit(id); } @@ -146,10 +144,8 @@ void ClearActiveBit(UpdaterScope scope, const std::string& id) { switch (scope) { case UpdaterScope::kUser: - // TODO(crbug/1159498): Standardize registry access. ClearUserActiveBit(id); break; - case UpdaterScope::kSystem: ClearSystemActiveBit(id); break;
diff --git a/chrome/updater/app/app_install.cc b/chrome/updater/app/app_install.cc index 9aaf280f..31969ac 100644 --- a/chrome/updater/app/app_install.cc +++ b/chrome/updater/app/app_install.cc
@@ -8,7 +8,6 @@ #include <vector> #include "base/check.h" -#include "base/check_op.h" #include "base/command_line.h" #include "base/functional/bind.h" #include "base/functional/callback.h" @@ -131,8 +130,7 @@ const tagging::TagArgs tag_args = tag_parsing_result.tag_args.value_or(tagging::TagArgs()); if (!tag_args.apps.empty()) { - // TODO(crbug.com/1128631): support bundles. For now, assume one app. - CHECK_EQ(tag_args.apps.size(), size_t{1}); + // Assume only one app is present since bundles are not supported. const tagging::AppArgs& app_args = tag_args.apps.front(); app_id_ = app_args.app_id; app_name_ = app_args.app_name;
diff --git a/chrome/updater/app/app_wake.cc b/chrome/updater/app/app_wake.cc index b52c117..0e3a5ce 100644 --- a/chrome/updater/app/app_wake.cc +++ b/chrome/updater/app/app_wake.cc
@@ -29,12 +29,6 @@ }; void AppWake::FirstTaskRun() { - // The service creation might need task runners and the update service - // internal needs to be instantiated after the base class has initialized - // the thread pool. - // - // TODO(crbug.com/1113448) - consider initializing the thread pool in the - // constructor of the base class or earlier, in the updater main. update_service_internal_ = CreateUpdateServiceInternalProxy(updater_scope()); update_service_internal_->Run( base::BindOnce(&AppWake::Shutdown, this, kErrorOk));
diff --git a/chrome/updater/app/server/win/com_classes.h b/chrome/updater/app/server/win/com_classes.h index f3b8f9c..ac542b7 100644 --- a/chrome/updater/app/server/win/com_classes.h +++ b/chrome/updater/app/server/win/com_classes.h
@@ -15,15 +15,8 @@ #include "chrome/updater/update_service.h" #include "chrome/updater/util/win_util.h" -// Definitions for native COM updater classes. - namespace updater { -// TODO(crbug.com/1065712): these classes do not have to be visible in the -// updater namespace. Additionally, there is some code duplication for the -// registration and unregistration code in both server and service_main -// compilation units. -// // This class implements the IUpdateState interface and exposes it as a COM // object. The purpose of this class is to remote the state of the // |UpdateService|. Instances of this class are typically passed as arguments
diff --git a/chrome/updater/app/server/win/com_classes_legacy.cc b/chrome/updater/app/server/win/com_classes_legacy.cc index ddce9ba..3112378 100644 --- a/chrome/updater/app/server/win/com_classes_legacy.cc +++ b/chrome/updater/app/server/win/com_classes_legacy.cc
@@ -565,7 +565,7 @@ // compatibility. error_code = GOOPDATEINSTALL_E_INSTALLER_FAILED; - // TODO(1095133): this string needs localization. + // TODO(crbug.com/1447293): this string needs localization. completion_message = L"Installer failed."; installer_result_code = state_update_->extra_code1; }
diff --git a/chrome/updater/app/server/win/updater_legacy_idl.template b/chrome/updater/app/server/win/updater_legacy_idl.template index e043fe1..7a897e3 100644 --- a/chrome/updater/app/server/win/updater_legacy_idl.template +++ b/chrome/updater/app/server/win/updater_legacy_idl.template
@@ -21,8 +21,6 @@ STATE_DOWNLOAD_COMPLETE = 8, STATE_EXTRACTING = 9, STATE_APPLYING_DIFFERENTIAL_PATCH = 10, - // TODO(omaha3): Should we move STATE_DOWNLOAD_COMPLETE here and eliminate - // STATE_READY_TO_INSTALL? STATE_READY_TO_INSTALL = 11, STATE_WAITING_TO_INSTALL = 12, STATE_INSTALLING = 13, @@ -65,7 +63,6 @@ // Returns the count of the Packages in the AppVersion. [propget] HRESULT packageCount([out, retval] long* count); - // TODO(omaha3): Implement this after a security review. // Returns an IDispatch of the Package in the AppVersion at the specified // 0-based index. [propget] HRESULT packageWeb([in] long index, @@ -91,7 +88,6 @@ ] interface ICurrentState : IDispatch { // This interface is exposed to web clients! - // TODO(omaha3): Update valid comments once we settle on an implementation. // A value from the CurrentState enum. This value determines which of the // properties below are valid. @@ -120,8 +116,6 @@ [propget] HRESULT nextRetryTime([out, retval] ULONGLONG*); - // TODO(omaha 3): Need some way to indicate reconnecting, retrying, etc. - // The following two properties are only valid when stateValue is // STATE_INSTALLING or STATE_INSTALL_COMPLETE. @@ -147,12 +141,8 @@ // The following three properties are only valid when stateValue is // STATE_ERROR or STATE_INSTALL_COMPLETE. - // TODO(omaha3): If STATE_DOWNLOAD_COMPLETE or STATE_READY_TO_INSTALL becomes - // a terminal state, does it support completion messages? - + // // Completion message, localized in the specified language. - // TODO(omaha3): If we're going to have bundle error messages too, should the - // language be at bundle level? Should bundle have its own language setter? [propget] HRESULT completionMessage([out, retval] BSTR*); // Application installer result code. This is to be used as additional
diff --git a/chrome/updater/installer.cc b/chrome/updater/installer.cc index bf584f0a..c838e70 100644 --- a/chrome/updater/installer.cc +++ b/chrome/updater/installer.cc
@@ -32,14 +32,6 @@ namespace updater { namespace { -// This task joins a process, hence .WithBaseSyncPrimitives(). -// TODO(crbug.com/1376713) - implement a way to express priority for -// foreground/background installs. -static constexpr base::TaskTraits kTaskTraitsBlockWithSyncPrimitives = { - base::MayBlock(), base::WithBaseSyncPrimitives(), - base::TaskPriority::USER_VISIBLE, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}; - // Returns the full path to the installation directory for the application // identified by the |app_id|. absl::optional<base::FilePath> GetAppInstallDir(UpdaterScope scope, @@ -48,7 +40,6 @@ if (!app_install_dir) { return absl::nullopt; } - return app_install_dir->AppendASCII(kAppsDir).AppendASCII(app_id); } @@ -60,7 +51,6 @@ const base::Version& app_version, const base::FilePath& ecp) : scope(scope), app_id(app_id), ap(ap), version(app_version), ecp(ecp) {} - AppInfo::AppInfo(const AppInfo&) = default; AppInfo& AppInfo::operator=(const AppInfo&) = default; AppInfo::~AppInfo() = default; @@ -89,9 +79,7 @@ crx_verifier_format_(crx_verifier_format), usage_stats_enabled_(persisted_data->GetUsageStatsEnabled()) {} -Installer::~Installer() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -} +Installer::~Installer() = default; update_client::CrxComponent Installer::MakeCrxComponent() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -222,7 +210,10 @@ ProgressCallback progress_callback, Callback callback) { base::ThreadPool::PostTask( - FROM_HERE, kTaskTraitsBlockWithSyncPrimitives, + FROM_HERE, + {base::MayBlock(), base::WithBaseSyncPrimitives(), + base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, base::BindOnce(&Installer::InstallWithSyncPrimitives, this, unpack_path, std::move(install_params), std::move(progress_callback), std::move(callback)));
diff --git a/chrome/updater/linux/setup/setup.cc b/chrome/updater/linux/setup/setup.cc index d81f0b3..36bd5af 100644 --- a/chrome/updater/linux/setup/setup.cc +++ b/chrome/updater/linux/setup/setup.cc
@@ -19,8 +19,6 @@ #include "chrome/updater/util/util.h" #include "third_party/abseil-cpp/absl/types/optional.h" -// TODO(1382547): There is a overlap between the Mac and Linux setup functions. -// We should find a way to merge these. namespace updater { int Setup(UpdaterScope scope) {
diff --git a/chrome/updater/persisted_data.h b/chrome/updater/persisted_data.h index ba2f6a8..c5c193e 100644 --- a/chrome/updater/persisted_data.h +++ b/chrome/updater/persisted_data.h
@@ -34,11 +34,6 @@ // PersistedData uses the PrefService to persist updater data that outlives // the updater processes. -// -// This class has sequence affinity. -// -// A mechanism to remove apps or app versions from prefs is needed. -// TODO(sorin): crbug.com/1056450 class PersistedData : public base::RefCountedThreadSafe<PersistedData> { public: // Constructs a provider using the specified |pref_service|. @@ -158,7 +153,7 @@ SEQUENCE_CHECKER(sequence_checker_); const UpdaterScope scope_; - raw_ptr<PrefService> pref_service_ = nullptr; // Not owned by this class. + raw_ptr<PrefService> pref_service_ = nullptr; }; void RegisterPersistedDataPrefs(scoped_refptr<PrefRegistrySimple> registry);
diff --git a/chrome/updater/policy/mac/managed_preference_policy_manager_impl.h b/chrome/updater/policy/mac/managed_preference_policy_manager_impl.h index c0b2c2a3..71da42c 100644 --- a/chrome/updater/policy/mac/managed_preference_policy_manager_impl.h +++ b/chrome/updater/policy/mac/managed_preference_policy_manager_impl.h
@@ -9,9 +9,6 @@ #include "chrome/updater/policy/manager.h" -// TODO: crbug/1073980 -// Add a doc link for the managed preferences dictionary format. -// // An example of the managed preferences policy dictionary in plist format: // <dict> // <key>updatePolicies</key>
diff --git a/chrome/updater/protos/message_set.proto b/chrome/updater/protos/message_set.proto index 498e8f3..cb6f2b8 100644 --- a/chrome/updater/protos/message_set.proto +++ b/chrome/updater/protos/message_set.proto
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// TODO: crbug/1082836 +// TODO: crbug.com/1082836 // This file is currently manually tweaked for Chromium use. Find a // way to automatically sync from source and make the following necessary // changes:
diff --git a/chrome/updater/protos/omaha_settings.proto b/chrome/updater/protos/omaha_settings.proto index cc0b49c..5313cb9f6 100644 --- a/chrome/updater/protos/omaha_settings.proto +++ b/chrome/updater/protos/omaha_settings.proto
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// TODO: crbug/1082836 +// TODO: crbug.com/1082836 // This file is currently manually tweaked for Chromium use. Find a // way to automatically sync from source and make the following necessary // changes:
diff --git a/chrome/updater/run_all_unittests.cc b/chrome/updater/run_all_unittests.cc index a43532d..089b2c4 100644 --- a/chrome/updater/run_all_unittests.cc +++ b/chrome/updater/run_all_unittests.cc
@@ -169,10 +169,9 @@ VLOG(0) << "Process priority: " << base::Process::Current().GetPriority(); VLOG(0) << updater::GetUACState(); - // TODO(crbug.com/1245429): remove when the bug is fixed. - // Typically, the test suite runner expects the swarming task to run with - // normal priority but for some reason, on the updater bots with UAC on, the - // swarming task runs with a priority below normal. + // The test suite runner expects the swarming task to run with normal priority + // but for some reason, on the updater bots with UAC on, the swarming task + // runs with a priority below normal (see crbug.com/1245429). FixExecutionPriorities(); auto scoped_com_initializer =
diff --git a/chrome/updater/test/integration_tests.cc b/chrome/updater/test/integration_tests.cc index 252732e..ddb5c9b 100644 --- a/chrome/updater/test/integration_tests.cc +++ b/chrome/updater/test/integration_tests.cc
@@ -135,9 +135,6 @@ ExpectNoCrashes(); PrintLog(); - - // TODO(crbug.com/1159189): Use a specific test output directory - // because Uninstall() deletes the files under GetInstallDirectory(). CopyLog(); DMCleanup(); @@ -897,7 +894,6 @@ ASSERT_NO_FATAL_FAILURE(InstallApp("test1")); ASSERT_NO_FATAL_FAILURE(ExpectInstalled()); ASSERT_TRUE(WaitForUpdaterExit()); - // TODO(crbug.com/1287235): The test is flaky without the following line. ASSERT_NO_FATAL_FAILURE(SetServerStarts(24)); ASSERT_NO_FATAL_FAILURE(RunWake(0)); ASSERT_TRUE(WaitForUpdaterExit());
diff --git a/chrome/updater/test/integration_tests_impl.cc b/chrome/updater/test/integration_tests_impl.cc index 705959e..070c6036 100644 --- a/chrome/updater/test/integration_tests_impl.cc +++ b/chrome/updater/test/integration_tests_impl.cc
@@ -356,7 +356,6 @@ // each failed test. It is useful to capture a few logs from previous failures // instead of the log of the last run only. void CopyLog(const base::FilePath& src_dir) { - // TODO(crbug.com/1159189): copy other test artifacts. base::FilePath dest_dir = GetLogDestinationDir(); const base::FilePath log_path = src_dir.AppendASCII("updater.log"); if (!dest_dir.empty() && base::PathExists(dest_dir) &&
diff --git a/chrome/updater/test/integration_tests_win.cc b/chrome/updater/test/integration_tests_win.cc index 3a443239..2e55745 100644 --- a/chrome/updater/test/integration_tests_win.cc +++ b/chrome/updater/test/integration_tests_win.cc
@@ -671,7 +671,6 @@ } void SetActive(UpdaterScope /*scope*/, const std::string& id) { - // TODO(crbug.com/1159498): Standardize registry access. base::win::RegKey key; ASSERT_EQ(key.Create(HKEY_CURRENT_USER, GetAppClientStateKey(id).c_str(), Wow6432(KEY_WRITE)), @@ -680,7 +679,6 @@ } void ExpectActive(UpdaterScope /*scope*/, const std::string& id) { - // TODO(crbug.com/1159498): Standardize registry access. base::win::RegKey key; ASSERT_EQ(key.Open(HKEY_CURRENT_USER, GetAppClientStateKey(id).c_str(), Wow6432(KEY_READ)), @@ -691,7 +689,6 @@ } void ExpectNotActive(UpdaterScope /*scope*/, const std::string& id) { - // TODO(crbug.com/1159498): Standardize registry access. base::win::RegKey key; if (key.Open(HKEY_CURRENT_USER, GetAppClientStateKey(id).c_str(), Wow6432(KEY_READ)) == ERROR_SUCCESS) {
diff --git a/chrome/updater/update_block_check_win.cc b/chrome/updater/update_block_check_win.cc index a9b2e76..e2d0382c 100644 --- a/chrome/updater/update_block_check_win.cc +++ b/chrome/updater/update_block_check_win.cc
@@ -26,18 +26,16 @@ return true; } -// TODO(crbug.com/1254492): Protect against deadlocks in NLM. bool IsConnectionedMetered() { - // No NLM before Win 8.1. Connections will be considered non-metered. - // Also, NLM could deadlock in Win10 versions pre-RS5, so we don't run the - // code for those versions. + // No NLM before Win 8.1. Connections will be considered non-metered. Also, + // because NLM could deadlock in Win10 versions pre-RS5, don't run the code + // for those versions (see crbug.com/1254492). if (base::win::GetVersion() < base::win::Version::WIN10_RS5) return false; Microsoft::WRL::ComPtr<INetworkCostManager> network_cost_manager; - HRESULT hr = - ::CoCreateInstance(CLSID_NetworkListManager, nullptr, CLSCTX_ALL, - IID_INetworkCostManager, &network_cost_manager); + HRESULT hr = ::CoCreateInstance(CLSID_NetworkListManager, nullptr, CLSCTX_ALL, + IID_PPV_ARGS(&network_cost_manager)); if (FAILED(hr)) return false;
diff --git a/chrome/updater/updater_scope.cc b/chrome/updater/updater_scope.cc index 1c97af57..d5501249 100644 --- a/chrome/updater/updater_scope.cc +++ b/chrome/updater/updater_scope.cc
@@ -4,7 +4,6 @@ #include "chrome/updater/updater_scope.h" -#include "base/check_op.h" #include "base/command_line.h" #include "build/build_config.h" #include "chrome/updater/constants.h" @@ -45,12 +44,11 @@ return UpdaterScope::kSystem; } - // TODO(crbug.com/1128631): support bundles. For now, assume one app. + // Assume only one app is present since bundles are not supported. const absl::optional<tagging::TagArgs> tag_args = GetTagArgsForCommandLine(command_line).tag_args; if (tag_args && !tag_args->apps.empty() && tag_args->apps.front().needs_admin) { - CHECK_EQ(tag_args->apps.size(), size_t{1}); switch (*tag_args->apps.front().needs_admin) { case tagging::AppArgs::NeedsAdmin::kYes: return UpdaterScope::kSystem; @@ -62,9 +60,6 @@ : UpdaterScope::kSystem; } } - - // crbug.com(1214058): consider handling the elevation case by - // calling IsUserAdmin(). return UpdaterScope::kUser; #else return IsSystemProcessForCommandLine(command_line) ? UpdaterScope::kSystem
diff --git a/chromeos/components/kcer/kcer.h b/chromeos/components/kcer/kcer.h index dd64c464..488296f2 100644 --- a/chromeos/components/kcer/kcer.h +++ b/chromeos/components/kcer/kcer.h
@@ -72,6 +72,7 @@ kFailedToSign = 23, kFailedToSignBadSignatureLength = 24, kFailedToDerEncode = 25, + kInputTooLong = 26, }; // Handles for tokens on ChromeOS.
diff --git a/chromeos/components/kcer/kcer_impl.cc b/chromeos/components/kcer/kcer_impl.cc index 3a036021..e5a1d224 100644 --- a/chromeos/components/kcer/kcer_impl.cc +++ b/chromeos/components/kcer/kcer_impl.cc
@@ -258,7 +258,37 @@ void KcerImpl::SignRsaPkcs1Raw(PrivateKeyHandle key, DigestWithPrefix digest_with_prefix, SignCallback callback) { - // TODO(244408716): Implement. + if (key.GetTokenInternal().has_value()) { + return SignRsaPkcs1RawWithToken(std::move(digest_with_prefix), + std::move(callback), std::move(key)); + } + + auto on_find_key_done = base::BindOnce( + &KcerImpl::SignRsaPkcs1RawWithToken, weak_factory_.GetWeakPtr(), + std::move(digest_with_prefix), std::move(callback)); + return PopulateTokenForKey(std::move(key), std::move(on_find_key_done)); +} + +void KcerImpl::SignRsaPkcs1RawWithToken( + DigestWithPrefix digest_with_prefix, + SignCallback callback, + base::expected<PrivateKeyHandle, Error> key_or_error) { + if (!key_or_error.has_value()) { + return std::move(callback).Run(base::unexpected(key_or_error.error())); + } + PrivateKeyHandle key = std::move(key_or_error).value(); + + const base::WeakPtr<KcerToken>& kcer_token = + GetToken(key.GetTokenInternal().value()); + if (!kcer_token.MaybeValid()) { + return std::move(callback).Run( + base::unexpected(Error::kTokenIsNotAvailable)); + } + token_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&KcerToken::SignRsaPkcs1Raw, kcer_token, std::move(key), + std::move(digest_with_prefix), + base::BindPostTaskToCurrentDefault(std::move(callback)))); } base::flat_set<Token> KcerImpl::GetAvailableTokens() {
diff --git a/chromeos/components/kcer/kcer_impl.h b/chromeos/components/kcer/kcer_impl.h index 55c48723..72445d5 100644 --- a/chromeos/components/kcer/kcer_impl.h +++ b/chromeos/components/kcer/kcer_impl.h
@@ -123,6 +123,11 @@ SignCallback callback, base::expected<PrivateKeyHandle, Error> key_or_error); + void SignRsaPkcs1RawWithToken( + DigestWithPrefix digest_with_prefix, + SignCallback callback, + base::expected<PrivateKeyHandle, Error> key_or_error); + void GetKeyInfoWithToken( GetKeyInfoCallback callback, base::expected<PrivateKeyHandle, Error> key_or_error);
diff --git a/chromeos/components/kcer/kcer_token.h b/chromeos/components/kcer/kcer_token.h index 44607b2..a096418 100644 --- a/chromeos/components/kcer/kcer_token.h +++ b/chromeos/components/kcer/kcer_token.h
@@ -66,7 +66,6 @@ DataToSign data, Kcer::SignCallback callback) = 0; virtual void SignRsaPkcs1Raw(PrivateKeyHandle key, - SigningScheme signing_scheme, DigestWithPrefix digest_with_prefix, Kcer::SignCallback callback) = 0; virtual void GetTokenInfo(Kcer::GetTokenInfoCallback callback) = 0;
diff --git a/chromeos/profiles/arm-exp.afdo.newest.txt b/chromeos/profiles/arm-exp.afdo.newest.txt index 87f550f..5c8862e7 100644 --- a/chromeos/profiles/arm-exp.afdo.newest.txt +++ b/chromeos/profiles/arm-exp.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-arm-exp-115-5735.18-1684144513-benchmark-115.0.5784.0-r1-redacted.afdo.xz +chromeos-chrome-arm-exp-115-5735.18-1684144513-benchmark-115.0.5785.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/arm.afdo.newest.txt b/chromeos/profiles/arm.afdo.newest.txt index c9be1f2..51d3051 100644 --- a/chromeos/profiles/arm.afdo.newest.txt +++ b/chromeos/profiles/arm.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-arm-none-115-5735.18-1684150800-benchmark-115.0.5784.0-r1-redacted.afdo.xz +chromeos-chrome-arm-none-115-5735.18-1684150800-benchmark-115.0.5785.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt index bc9ce88..3e7010af 100644 --- a/chromeos/profiles/atom.afdo.newest.txt +++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-atom-115-5735.18-1684144513-benchmark-115.0.5784.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-atom-115-5735.18-1684144513-benchmark-115.0.5785.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt index bf5a5dc0..266d437 100644 --- a/chromeos/profiles/bigcore.afdo.newest.txt +++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-bigcore-115-5735.18-1684149627-benchmark-115.0.5784.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-bigcore-115-5735.18-1684149627-benchmark-115.0.5785.0-r1-redacted.afdo.xz
diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/components/autofill/content/browser/content_autofill_driver.cc index f236ca7..a790e09e 100644 --- a/components/autofill/content/browser/content_autofill_driver.cc +++ b/components/autofill/content/browser/content_autofill_driver.cc
@@ -64,7 +64,7 @@ ContentAutofillDriver::ContentAutofillDriver( content::RenderFrameHost* render_frame_host, ContentAutofillDriverFactory* owner) - : render_frame_host_(render_frame_host), + : render_frame_host_(*render_frame_host), owner_(*owner), suppress_showing_ime_callback_(base::BindRepeating( [](const ContentAutofillDriver* driver) { @@ -168,7 +168,7 @@ } bool ContentAutofillDriver::IsInAnyMainFrame() const { - return render_frame_host_->GetMainFrame() == render_frame_host_; + return render_frame_host_->GetMainFrame() == render_frame_host(); } bool ContentAutofillDriver::IsInFencedFrameRoot() const { @@ -353,8 +353,9 @@ void ContentAutofillDriver::SetFormToBeProbablySubmitted( const absl::optional<FormData>& form) { - if (!bad_message::CheckFrameNotPrerendering(render_frame_host_)) + if (!bad_message::CheckFrameNotPrerendering(render_frame_host())) { return; + } autofill_router().SetFormToBeProbablySubmitted( this, form ? absl::make_optional<FormData>( @@ -369,8 +370,9 @@ void ContentAutofillDriver::FormsSeen( const std::vector<FormData>& raw_updated_forms, const std::vector<FormRendererId>& raw_removed_forms) { - if (!bad_message::CheckFrameNotPrerendering(render_frame_host_)) + if (!bad_message::CheckFrameNotPrerendering(render_frame_host())) { return; + } std::vector<FormData> updated_forms = raw_updated_forms; for (FormData& form : updated_forms) SetFrameAndFormMetaData(form, nullptr); @@ -394,8 +396,9 @@ const FormData& raw_form, bool known_success, mojom::SubmissionSource submission_source) { - if (!bad_message::CheckFrameNotPrerendering(render_frame_host_)) + if (!bad_message::CheckFrameNotPrerendering(render_frame_host())) { return; + } autofill_router().FormSubmitted( this, GetFormWithFrameAndFormMetaData(raw_form), known_success, submission_source, @@ -420,8 +423,9 @@ const FormFieldData& raw_field, const gfx::RectF& bounding_box, base::TimeTicks timestamp) { - if (!bad_message::CheckFrameNotPrerendering(render_frame_host_)) + if (!bad_message::CheckFrameNotPrerendering(render_frame_host())) { return; + } FormData form = raw_form; FormFieldData field = raw_field; SetFrameAndFormMetaData(form, &field); @@ -439,8 +443,9 @@ void ContentAutofillDriver::TextFieldDidScroll(const FormData& raw_form, const FormFieldData& raw_field, const gfx::RectF& bounding_box) { - if (!bad_message::CheckFrameNotPrerendering(render_frame_host_)) + if (!bad_message::CheckFrameNotPrerendering(render_frame_host())) { return; + } FormData form = raw_form; FormFieldData field = raw_field; SetFrameAndFormMetaData(form, &field); @@ -458,8 +463,9 @@ const FormData& raw_form, const FormFieldData& raw_field, const gfx::RectF& bounding_box) { - if (!bad_message::CheckFrameNotPrerendering(render_frame_host_)) + if (!bad_message::CheckFrameNotPrerendering(render_frame_host())) { return; + } FormData form = raw_form; FormFieldData field = raw_field; SetFrameAndFormMetaData(form, &field); @@ -479,8 +485,9 @@ const gfx::RectF& bounding_box, AutoselectFirstSuggestion autoselect_first_suggestion, FormElementWasClicked form_element_was_clicked) { - if (!bad_message::CheckFrameNotPrerendering(render_frame_host_)) + if (!bad_message::CheckFrameNotPrerendering(render_frame_host())) { return; + } FormData form = raw_form; FormFieldData field = raw_field; SetFrameAndFormMetaData(form, &field); @@ -499,8 +506,9 @@ } void ContentAutofillDriver::HidePopup() { - if (!bad_message::CheckFrameNotPrerendering(render_frame_host_)) + if (!bad_message::CheckFrameNotPrerendering(render_frame_host())) { return; + } autofill_router().HidePopup(this, [](ContentAutofillDriver* target) { DCHECK(!target->IsPrerendering()) << "We should never affect UI while prerendering"; @@ -514,8 +522,9 @@ } void ContentAutofillDriver::FocusNoLongerOnForm(bool had_interacted_form) { - if (!bad_message::CheckFrameNotPrerendering(render_frame_host_)) + if (!bad_message::CheckFrameNotPrerendering(render_frame_host())) { return; + } autofill_router().FocusNoLongerOnForm( this, had_interacted_form, [](ContentAutofillDriver* target, bool had_interacted_form) { @@ -526,8 +535,9 @@ void ContentAutofillDriver::FocusOnFormField(const FormData& raw_form, const FormFieldData& raw_field, const gfx::RectF& bounding_box) { - if (!bad_message::CheckFrameNotPrerendering(render_frame_host_)) + if (!bad_message::CheckFrameNotPrerendering(render_frame_host())) { return; + } FormData form = raw_form; FormFieldData field = raw_field; SetFrameAndFormMetaData(form, &field); @@ -543,8 +553,9 @@ void ContentAutofillDriver::DidFillAutofillFormData(const FormData& raw_form, base::TimeTicks timestamp) { - if (!bad_message::CheckFrameNotPrerendering(render_frame_host_)) + if (!bad_message::CheckFrameNotPrerendering(render_frame_host())) { return; + } autofill_router().DidFillAutofillFormData( this, GetFormWithFrameAndFormMetaData(raw_form), timestamp, [](ContentAutofillDriver* target, const FormData& form, @@ -555,8 +566,9 @@ } void ContentAutofillDriver::DidPreviewAutofillFormData() { - if (!bad_message::CheckFrameNotPrerendering(render_frame_host_)) + if (!bad_message::CheckFrameNotPrerendering(render_frame_host())) { return; + } autofill_router().DidPreviewAutofillFormData( this, [](ContentAutofillDriver* target) { target->autofill_manager_->OnDidPreviewAutofillFormData(); @@ -564,8 +576,9 @@ } void ContentAutofillDriver::DidEndTextFieldEditing() { - if (!bad_message::CheckFrameNotPrerendering(render_frame_host_)) + if (!bad_message::CheckFrameNotPrerendering(render_frame_host())) { return; + } autofill_router().DidEndTextFieldEditing( this, [](ContentAutofillDriver* target) { target->autofill_manager_->OnDidEndTextFieldEditing(); @@ -574,8 +587,9 @@ void ContentAutofillDriver::SelectFieldOptionsDidChange( const FormData& raw_form) { - if (!bad_message::CheckFrameNotPrerendering(render_frame_host_)) + if (!bad_message::CheckFrameNotPrerendering(render_frame_host())) { return; + } autofill_router().SelectFieldOptionsDidChange( this, GetFormWithFrameAndFormMetaData(raw_form), [](ContentAutofillDriver* target, const FormData& form) { @@ -588,8 +602,9 @@ const FormData& raw_form, const FormFieldData& raw_field, const std::u16string& old_value) { - if (!bad_message::CheckFrameNotPrerendering(render_frame_host_)) + if (!bad_message::CheckFrameNotPrerendering(render_frame_host())) { return; + } FormData form = raw_form; FormFieldData field = raw_field; SetFrameAndFormMetaData(form, &field);
diff --git a/components/autofill/content/browser/content_autofill_driver.h b/components/autofill/content/browser/content_autofill_driver.h index 9576fba..9e9782e9 100644 --- a/components/autofill/content/browser/content_autofill_driver.h +++ b/components/autofill/content/browser/content_autofill_driver.h
@@ -131,7 +131,10 @@ } AutofillManager* autofill_manager() { return autofill_manager_.get(); } - content::RenderFrameHost* render_frame_host() { return render_frame_host_; } + content::RenderFrameHost* render_frame_host() { return &*render_frame_host_; } + const content::RenderFrameHost* render_frame_host() const { + return &*render_frame_host_; + } // Expose the events that originate from the browser and renderer processes, // respectively. @@ -312,9 +315,11 @@ // not be using the router if we're prerendering). ContentAutofillRouter& autofill_router(); - // Weak ref to the RenderFrameHost the driver is associated with. Should - // always be non-NULL and valid for lifetime of |this|. - const raw_ptr<content::RenderFrameHost> render_frame_host_ = nullptr; + // The frame/document to which this driver is associated. Outlives `this`. + // RFH is corresponds to neither a frame nor a document: it may survive + // navigations that documents don't, but it may not survive cross-origin + // navigations. + const raw_ref<content::RenderFrameHost> render_frame_host_; // The factory that created this driver. Outlives `this`. const raw_ref<ContentAutofillDriverFactory> owner_; @@ -328,8 +333,6 @@ // to avoid duplicates fired by AutofillAgent. std::set<FormGlobalId> submitted_forms_; - // AutofillManager instance via which this object drives the shared Autofill - // code. std::unique_ptr<AutofillManager> autofill_manager_ = nullptr; content::RenderWidgetHost::KeyPressEventCallback key_press_handler_;
diff --git a/components/autofill/content/browser/content_autofill_router.cc b/components/autofill/content/browser/content_autofill_router.cc index 784f6568..31b3cfa3 100644 --- a/components/autofill/content/browser/content_autofill_router.cc +++ b/components/autofill/content/browser/content_autofill_router.cc
@@ -191,9 +191,10 @@ // Calls TriggerReparse() on all ContentAutofillDrivers in |form_forest_| as // well as their ancestor ContentAutofillDrivers. // -// An ancestor might not be contained in the form tree itself: if the ancestor -// contained only invisible iframe(s) and no interesting fields, it would not be -// sent to the browser. In the meantime, these frames may have become visible. +// An ancestor might not be contained in the form tree known to FormForest: if +// the ancestor contained only invisible iframe(s) and no interesting fields, it +// would not be sent to the browser. In the meantime, these frames may have +// become visible. Therefore, we also call TriggerReparse() in all ancestors. // // The typical use case is that some frame triggers reparses on its own // initiative and triggers an event. Then ContentAutofillRouter's event handler @@ -201,16 +202,18 @@ void ContentAutofillRouter::TriggerReparseExcept( ContentAutofillDriver* exception) { DCHECK(base::FeatureList::IsEnabled(features::kAutofillAcrossIframes)); - base::flat_set<AutofillDriver*> already_triggered; ForEachFrame(form_forest_, [&](AutofillDriver* driver) mutable { do { - // Trigger reparse for |driver| and all its ancestors (as some ancestors - // may not be in the forest). - if (driver != exception && !base::Contains(already_triggered, driver)) { - driver->TriggerReparse(); - already_triggered.insert(driver); + if (!already_triggered.insert(driver).second) { + // An earlier invocation of this lambda has executed the rest of this + // loop's body for `driver` and hence also for all its ancestors. + break; } + if (driver == exception) { + continue; + } + driver->TriggerReparse(); } while ((driver = driver->GetParent()) != nullptr); }); }
diff --git a/components/autofill/content/browser/form_forest.cc b/components/autofill/content/browser/form_forest.cc index aab85c4e..3e5a529d 100644 --- a/components/autofill/content/browser/form_forest.cc +++ b/components/autofill/content/browser/form_forest.cc
@@ -619,19 +619,12 @@ auto it = field_type_map.find(field.global_id()); ServerFieldType field_type = it != field_type_map.end() ? it->second : UNKNOWN_TYPE; - if (features::kAutofillSharedAutofillRelaxedParam.Get()) { - return field.origin == triggered_origin || - (HasSharedAutofillPermission(renderer_form->host_frame) && - (field.origin != main_origin || - field_type != CREDIT_CARD_NUMBER)); - } else { - return field.origin == triggered_origin || - (field.origin == main_origin && - HasSharedAutofillPermission(renderer_form->host_frame) && - !IsSensitiveFieldType(field_type)) || - (triggered_origin == main_origin && - HasSharedAutofillPermission(renderer_form->host_frame)); - } + return field.origin == triggered_origin || + (field.origin == main_origin && + !IsSensitiveFieldType(field_type) && + HasSharedAutofillPermission(renderer_form->host_frame)) || + (triggered_origin == main_origin && + HasSharedAutofillPermission(renderer_form->host_frame)); }; renderer_form->fields.push_back(browser_field);
diff --git a/components/autofill/content/browser/form_forest.h b/components/autofill/content/browser/form_forest.h index d786f9104..771b908 100644 --- a/components/autofill/content/browser/form_forest.h +++ b/components/autofill/content/browser/form_forest.h
@@ -260,9 +260,8 @@ // The |field_type_map| should contain the field types of the fields in // |browser_form|. // - // There are two modes that determine whether a field is *safe to fill*. - // By default, a field is safe to fill iff at least one of the conditions - // (1–3) and additionally condition (4) hold: + // A field is *safe to fill* iff at least one of the conditions (1–3) and + // additionally condition (4) hold: // // (1) The field's origin is the |triggered_origin|. // (2) The field's origin is the main origin, the field's type in @@ -271,16 +270,8 @@ // frame. // (3) The |triggered_origin| is the main origin and the policy-controlled // feature shared-autofill is enabled in the field's frame. - // (4) No frame on the shortest path from the field on which Autofill was - // triggered to the field in question, except perhaps the shallowest - // frame, is a fenced frame. - // - // If the Finch parameter relax_shared_autofill is true, the restriction to - // the main origin in condition 3 is lifted. Thus, conditions (2) and (3) - // reduce to the following: - // - // (2+3) The policy-controlled feature shared-autofill is enabled in the - // field's document. + // (4) The field is in the same frame tree as the field on which Autofill was + // triggered. // // The *origin of a field* is the origin of the frame that contains the // corresponding form-control element.
diff --git a/components/autofill/content/browser/form_forest_unittest.cc b/components/autofill/content/browser/form_forest_unittest.cc index 8c1c6b3..d70f58c 100644 --- a/components/autofill/content/browser/form_forest_unittest.cc +++ b/components/autofill/content/browser/form_forest_unittest.cc
@@ -318,13 +318,6 @@ // FormForest::GetBrowserForm() for details). enum class Policy { kDefault, kSharedAutofill, kNoSharedAutofill }; - explicit FormForestTest(bool relax_shared_autofill = false) { - feature_list_.InitAndEnableFeatureWithParameters( - features::kAutofillSharedAutofill, - {{features::kAutofillSharedAutofillRelaxedParam.name, - relax_shared_autofill ? "true" : "false"}}); - } - void SetUp() override { RenderViewHostTestHarness::SetUp(); CHECK(kOpaqueOrigin.opaque()); @@ -423,7 +416,8 @@ /*matches_opaque_src=*/false)}; } - base::test::ScopedFeatureList feature_list_; + base::test::ScopedFeatureList feature_list_{ + features::kAutofillSharedAutofill}; test::AutofillUnitTestEnvironment autofill_test_environment_; TestAutofillClientInjector<TestContentAutofillClient> autofill_client_injector_; @@ -463,10 +457,6 @@ size_t count = base::dynamic_extent; }; - explicit FormForestTestWithMockedTree(bool relax_shared_autofill = false) - : FormForestTest( - /*relax_shared_autofill=*/relax_shared_autofill) {} - void TearDown() override { TestApi(mocked_forms_).Reset(); TestApi(flattened_forms_).Reset(); @@ -1445,11 +1435,6 @@ // Tests of FormForest::GetRendererFormsOfBrowserForm(). class FormForestTestUnflatten : public FormForestTestWithMockedTree { - public: - explicit FormForestTestUnflatten(bool relax_shared_autofill = false) - : FormForestTestWithMockedTree( - /*relax_shared_autofill=*/relax_shared_autofill) {} - protected: // The subject of this test fixture. std::vector<FormData> GetRendererFormsOfBrowserForm( @@ -1622,17 +1607,9 @@ } // Fixture for the shared-autofill policy tests. -// The parameter controls the value of relax_shared_autofill. class FormForestTestUnflattenSharedAutofillPolicy - : public FormForestTestUnflatten, - public ::testing::WithParamInterface<bool> { + : public FormForestTestUnflatten { public: - FormForestTestUnflattenSharedAutofillPolicy() - : FormForestTestUnflatten( - /*relax_shared_autofill=*/relax_shared_autofill()) {} - - bool relax_shared_autofill() const { return GetParam(); } - void SetUp() override { FormForestTestUnflatten::SetUp(); MockFormForest( @@ -1649,7 +1626,7 @@ }; // Tests filling into frames with shared-autofill policy from the main origin. -TEST_P(FormForestTestUnflattenSharedAutofillPolicy, FromMainOrigin) { +TEST_F(FormForestTestUnflattenSharedAutofillPolicy, FromMainOrigin) { MockFlattening({{"main"}, {"disallowed"}, {"allowed"}}); std::vector<FormData> expectation = { WithValues(GetMockedForm("main"), Profile(0)), @@ -1660,18 +1637,12 @@ } // Tests filling into frames with shared-autofill policy from the main origin. -TEST_P(FormForestTestUnflattenSharedAutofillPolicy, FromOtherOrigin) { +TEST_F(FormForestTestUnflattenSharedAutofillPolicy, FromOtherOrigin) { MockFlattening({{"main"}, {"disallowed"}, {"allowed"}}); - std::vector<FormData> expectation; - if (!relax_shared_autofill()) { - expectation = {WithoutValues(GetMockedForm("main")), - WithValues(GetMockedForm("disallowed"), Profile(1)), - WithoutValues(GetMockedForm("allowed"))}; - } else { - expectation = {WithValues(GetMockedForm("main"), Profile(0)), - WithValues(GetMockedForm("disallowed"), Profile(1)), - WithValues(GetMockedForm("allowed"), Profile(2))}; - } + std::vector<FormData> expectation = { + WithoutValues(GetMockedForm("main")), + WithValues(GetMockedForm("disallowed"), Profile(1)), + WithoutValues(GetMockedForm("allowed"))}; EXPECT_THAT(GetRendererFormsOfBrowserForm("main", Origin(kOtherUrl), {}), UnorderedArrayEquals(expectation)); } @@ -1746,10 +1717,6 @@ EXPECT_EQ(num_equals_calls_, GetParam().expected_comparisons); } -INSTANTIATE_TEST_SUITE_P(FormForestTest, - FormForestTestUnflattenSharedAutofillPolicy, - testing::Bool()); - INSTANTIATE_TEST_SUITE_P( FormForestTest, ForEachInSetDifferenceTest,
diff --git a/components/autofill/core/browser/autofill_external_delegate.cc b/components/autofill/core/browser/autofill_external_delegate.cc index bfce095..5d30b998 100644 --- a/components/autofill/core/browser/autofill_external_delegate.cc +++ b/components/autofill/core/browser/autofill_external_delegate.cc
@@ -200,7 +200,7 @@ // Only preview the data if it is a profile or a virtual card. if (frontend_id.as_int() > 0) { - FillAutofillFormData(frontend_id, true, + FillAutofillFormData(frontend_id, backend_id, true, AutofillTriggerSource::kKeyboardAccessory); } else if (frontend_id == PopupItemId::kAutocompleteEntry || frontend_id == PopupItemId::kIbanEntry || @@ -298,8 +298,9 @@ autofill_metrics::LogAutofillSuggestionAcceptedIndex( position, popup_type_, manager_->client()->IsOffTheRecord()); } - FillAutofillFormData(suggestion.frontend_id, false, - AutofillTriggerSource::kPopup); + FillAutofillFormData(suggestion.frontend_id, + suggestion.GetPayload<Suggestion::BackendId>(), + false, AutofillTriggerSource::kPopup); break; } @@ -321,16 +322,19 @@ bool AutofillExternalDelegate::GetDeletionConfirmationText( const std::u16string& value, Suggestion::FrontendId frontend_id, + Suggestion::BackendId backend_id, std::u16string* title, std::u16string* body) { - return manager_->GetDeletionConfirmationText(value, frontend_id, title, body); + return manager_->GetDeletionConfirmationText(value, frontend_id, backend_id, + title, body); } bool AutofillExternalDelegate::RemoveSuggestion( const std::u16string& value, - Suggestion::FrontendId frontend_id) { + Suggestion::FrontendId frontend_id, + Suggestion::BackendId backend_id) { if (frontend_id.as_int() > 0) { - return manager_->RemoveAutofillProfileOrCreditCard(frontend_id); + return manager_->RemoveAutofillProfileOrCreditCard(backend_id); } if (frontend_id == PopupItemId::kAutocompleteEntry) { @@ -386,12 +390,14 @@ } void AutofillExternalDelegate::FillAutofillFormData( - Suggestion::FrontendId unique_id, + Suggestion::FrontendId frontend_id, + Suggestion::BackendId backend_id, bool is_preview, const AutofillTriggerSource trigger_source) { // If the selected element is a warning we don't want to do anything. - if (IsAutofillWarningEntry(unique_id)) + if (IsAutofillWarningEntry(frontend_id)) { return; + } mojom::RendererFormDataAction renderer_action = is_preview ? mojom::RendererFormDataAction::kPreview @@ -400,7 +406,7 @@ DCHECK(driver_->RendererIsAvailable()); // Fill the values for the whole form. manager_->FillOrPreviewForm(renderer_action, query_form_, query_field_, - unique_id, trigger_source); + backend_id, trigger_source); } void AutofillExternalDelegate::PossiblyRemoveAutofillWarnings(
diff --git a/components/autofill/core/browser/autofill_external_delegate.h b/components/autofill/core/browser/autofill_external_delegate.h index 5dac03a..3798f420 100644 --- a/components/autofill/core/browser/autofill_external_delegate.h +++ b/components/autofill/core/browser/autofill_external_delegate.h
@@ -54,10 +54,12 @@ void DidAcceptSuggestion(const Suggestion& suggestion, int position) override; bool GetDeletionConfirmationText(const std::u16string& value, Suggestion::FrontendId frontend_id, + Suggestion::BackendId backend_id, std::u16string* title, std::u16string* body) override; bool RemoveSuggestion(const std::u16string& value, - Suggestion::FrontendId frontend_id) override; + Suggestion::FrontendId frontend_id, + Suggestion::BackendId backend_id) override; void ClearPreviewedForm() override; // Returns PopupType::kUnspecified for all popups prior to |onQuery|, or the @@ -125,11 +127,12 @@ void OnCreditCardScanned(const AutofillTriggerSource trigger_source, const CreditCard& card); - // Fills the form with the Autofill data corresponding to |unique_id|. - // If |is_preview| is true then this is just a preview to show the user what - // would be selected and if |is_preview| is false then the user has selected + // Fills the form with the Autofill data corresponding to `backend_id`. + // If `is_preview` is true then this is just a preview to show the user what + // would be selected and if `is_preview` is false then the user has selected // this data. - void FillAutofillFormData(Suggestion::FrontendId unique_id, + void FillAutofillFormData(Suggestion::FrontendId frontend_id, + Suggestion::BackendId backend_id, bool is_preview, const AutofillTriggerSource trigger_source);
diff --git a/components/autofill/core/browser/autofill_external_delegate_unittest.cc b/components/autofill/core/browser/autofill_external_delegate_unittest.cc index 28c1ce0..905baf6 100644 --- a/components/autofill/core/browser/autofill_external_delegate_unittest.cc +++ b/components/autofill/core/browser/autofill_external_delegate_unittest.cc
@@ -154,7 +154,7 @@ (mojom::RendererFormDataAction action, const FormData& form, const FormFieldData& field, - Suggestion::FrontendId unique_id, + Suggestion::BackendId backend_id, const AutofillTriggerSource trigger_source), (override)); MOCK_METHOD(void, @@ -684,9 +684,9 @@ EXPECT_CALL(autofill_client_, HideAutofillPopup(PopupHidingReason::kAcceptSuggestion)); std::u16string dummy_string(u"John Legend"); - EXPECT_CALL(*browser_autofill_manager_, - FillOrPreviewForm(mojom::RendererFormDataAction::kFill, _, _, - kAutofillProfileId, _)); + EXPECT_CALL( + *browser_autofill_manager_, + FillOrPreviewForm(mojom::RendererFormDataAction::kFill, _, _, _, _)); external_delegate_->DidAcceptSuggestion( test::CreateAutofillSuggestion(kAutofillProfileId, dummy_string),
diff --git a/components/autofill/core/browser/browser_autofill_manager.cc b/components/autofill/core/browser/browser_autofill_manager.cc index f8dbd93f..a8bc68d6 100644 --- a/components/autofill/core/browser/browser_autofill_manager.cc +++ b/components/autofill/core/browser/browser_autofill_manager.cc
@@ -80,6 +80,7 @@ #include "components/autofill/core/browser/suggestions_context.h" #include "components/autofill/core/browser/ui/payments/bubble_show_options.h" #include "components/autofill/core/browser/ui/popup_item_ids.h" +#include "components/autofill/core/browser/ui/suggestion.h" #include "components/autofill/core/browser/validation.h" #include "components/autofill/core/common/autocomplete_parsing_util.h" #include "components/autofill/core/common/autofill_clock.h" @@ -1341,7 +1342,7 @@ mojom::RendererFormDataAction action, const FormData& form, const FormFieldData& field, - Suggestion::FrontendId unique_id, + Suggestion::BackendId backend_id, const AutofillTriggerSource trigger_source) { if (!IsValidFormData(form) || !IsValidFormFieldData(field)) return; @@ -1351,8 +1352,8 @@ if (!RefreshDataModels() || !driver()->RendererIsAvailable()) return; - const AutofillProfile* profile = GetProfile(unique_id); - const CreditCard* credit_card = GetCreditCard(unique_id); + const AutofillProfile* profile = GetProfile(backend_id); + const CreditCard* credit_card = GetCreditCard(backend_id); if (credit_card) { FillOrPreviewCreditCardForm(action, form, field, credit_card, @@ -1566,6 +1567,7 @@ bool BrowserAutofillManager::GetDeletionConfirmationText( const std::u16string& value, Suggestion::FrontendId identifier, + Suggestion::BackendId backend_id, std::u16string* title, std::u16string* body) { if (identifier == PopupItemId::kAutocompleteEntry) { @@ -1583,8 +1585,8 @@ return false; } - const CreditCard* credit_card = GetCreditCard(identifier); - const AutofillProfile* profile = GetProfile(identifier); + const CreditCard* credit_card = GetCreditCard(backend_id); + const AutofillProfile* profile = GetProfile(backend_id); if (credit_card) { return credit_card_access_manager_->GetDeletionConfirmationText( @@ -1614,13 +1616,13 @@ } bool BrowserAutofillManager::RemoveAutofillProfileOrCreditCard( - Suggestion::FrontendId unique_id) { - const CreditCard* credit_card = GetCreditCard(unique_id); + Suggestion::BackendId backend_id) { + const CreditCard* credit_card = GetCreditCard(backend_id); if (credit_card) { return credit_card_access_manager_->DeleteCard(credit_card); } - const AutofillProfile* profile = GetProfile(unique_id); + const AutofillProfile* profile = GetProfile(backend_id); if (profile) { bool is_local = profile->record_type() == AutofillProfile::LOCAL_PROFILE; if (is_local) @@ -2134,19 +2136,14 @@ } CreditCard* BrowserAutofillManager::GetCreditCard( - Suggestion::FrontendId unique_id) { - Suggestion::BackendId credit_card_id = - suggestion_generator_->GetBackendIdFromFrontendId(unique_id); + Suggestion::BackendId unique_id) { return client()->GetPersonalDataManager()->GetCreditCardByGUID( - credit_card_id.value()); + unique_id.value()); } AutofillProfile* BrowserAutofillManager::GetProfile( - Suggestion::FrontendId unique_id) { - Suggestion::BackendId profile_id = - suggestion_generator_->GetBackendIdFromFrontendId(unique_id); - - std::string guid = profile_id.value(); + Suggestion::BackendId unique_id) { + std::string guid = unique_id.value(); if (base::Uuid::ParseCaseInsensitive(guid).is_valid()) { return client()->GetPersonalDataManager()->GetProfileByGUID(guid); }
diff --git a/components/autofill/core/browser/browser_autofill_manager.h b/components/autofill/core/browser/browser_autofill_manager.h index eecd7ab..4957fff 100644 --- a/components/autofill/core/browser/browser_autofill_manager.h +++ b/components/autofill/core/browser/browser_autofill_manager.h
@@ -147,7 +147,7 @@ virtual void FillOrPreviewForm(mojom::RendererFormDataAction action, const FormData& form, const FormFieldData& field, - Suggestion::FrontendId unique_id, + Suggestion::BackendId backend_id, const AutofillTriggerSource trigger_source); void FillCreditCardFormImpl(const FormData& form, const FormFieldData& field, @@ -190,12 +190,13 @@ // |title| and |body| with relevant user-facing text. bool GetDeletionConfirmationText(const std::u16string& value, Suggestion::FrontendId identifier, + Suggestion::BackendId backend_id, std::u16string* title, std::u16string* body); - // Remove the credit card or Autofill profile that matches |unique_id| + // Remove the credit card or Autofill profile that matches |backend_id| // from the database. Returns true if deletion is allowed. - bool RemoveAutofillProfileOrCreditCard(Suggestion::FrontendId unique_id); + bool RemoveAutofillProfileOrCreditCard(Suggestion::BackendId backend_id); // Remove the specified suggestion from single field filling. |frontend_id| is // the PopupItemId of the suggestion. @@ -523,15 +524,14 @@ // Returns false if Autofill is disabled or if no Autofill data is available. bool RefreshDataModels(); - // TODO(crbug.com/1249665): Change unique_id to frontend_id and move the - // functions to AutofillSuggestionGenerator. + // TODO(crbug.com/1249665): Move the functions to AutofillSuggestionGenerator. // Gets the card referred to by the guid |unique_id|. Returns |nullptr| if // card does not exist. - CreditCard* GetCreditCard(Suggestion::FrontendId unique_id); + CreditCard* GetCreditCard(Suggestion::BackendId unique_id); // Gets the profile referred to by the guid |unique_id|. Returns |nullptr| if // profile does not exist. - AutofillProfile* GetProfile(Suggestion::FrontendId unique_id); + AutofillProfile* GetProfile(Suggestion::BackendId unique_id); // Determines whether a fill on |form| initiated from |triggered_field| will // wind up filling a credit card number. This is useful to determine if we
diff --git a/components/autofill/core/browser/browser_autofill_manager_unittest.cc b/components/autofill/core/browser/browser_autofill_manager_unittest.cc index cd13cec4..7b32b21 100644 --- a/components/autofill/core/browser/browser_autofill_manager_unittest.cc +++ b/components/autofill/core/browser/browser_autofill_manager_unittest.cc
@@ -739,13 +739,13 @@ void FillAutofillFormData(const FormData& form, const FormFieldData& field, - Suggestion::FrontendId unique_id) { + std::string guid) { browser_autofill_manager_->OnAskForValuesToFill( form, field, {}, AutoselectFirstSuggestion(true), FormElementWasClicked(false)); browser_autofill_manager_->FillOrPreviewForm( - mojom::RendererFormDataAction::kFill, form, field, unique_id, - AutofillTriggerSource::kPopup); + mojom::RendererFormDataAction::kFill, form, field, + Suggestion::BackendId(guid), AutofillTriggerSource::kPopup); } // Calls |browser_autofill_manager_->OnFillAutofillFormData()| with the @@ -754,12 +754,12 @@ // parameter of that call into the |response_data| output parameter. void FillAutofillFormDataAndSaveResults(const FormData& input_form, const FormFieldData& input_field, - Suggestion::FrontendId unique_id, + std::string guid, FormData* response_data) { EXPECT_CALL(*autofill_driver_, FillOrPreviewForm(_, _, _, _)) .WillOnce(DoAll(testing::SaveArg<1>(response_data), testing::Return(std::vector<FieldGlobalId>{}))); - FillAutofillFormData(input_form, input_field, unique_id); + FillAutofillFormData(input_form, input_field, guid); } void PreviewVirtualCardDataAndSaveResults( @@ -2771,8 +2771,7 @@ FormData response_data; FillAutofillFormDataAndSaveResults(form, form.fields[index_of_trigger_field], - MakeFrontendId({.profile_id = guid}), - &response_data); + guid, &response_data); // Extract the sections into individual forms to reduce boiler plate code. size_t mid = response_data.fields.size() / 2; FormData section1 = response_data; @@ -3551,8 +3550,7 @@ EXPECT_NE(base::Time(), profile->use_date()); FormData response_data; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); ExpectFilledAddressFormElvis(response_data, false); @@ -3620,8 +3618,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000004"; FormData response_data; base::HistogramTester histogram_tester; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); // Cardholder name, card number, expiration data were autofilled but cvc was // not be autofilled. @@ -3637,8 +3634,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000004"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/false); } @@ -3661,8 +3657,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000008"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/false); } @@ -3686,8 +3681,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000009"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/false); } @@ -3711,8 +3705,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000007"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); ExpectFilledForm(response_data, /*address_fill_data=*/absl::nullopt, card_fill_data); @@ -3736,8 +3729,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000007"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); ExpectFilledForm(response_data, /*address_fill_data=*/absl::nullopt, card_fill_data); @@ -3762,8 +3754,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000007"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); ExpectFilledForm(response_data, /*address_fill_data=*/absl::nullopt, card_fill_data); @@ -3786,8 +3777,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000007"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); ExpectFilledForm(response_data, /*address_fill_data=*/absl::nullopt, card_fill_data); @@ -3823,8 +3813,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000004"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); ExpectFilledField("Card Name", "cardname", "Elvis", "text", response_data.fields[0]); @@ -3873,8 +3862,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000004"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); ExpectFilledField("Card Name", "cardname", "Elvis", "text", response_data.fields[0]); @@ -3922,8 +3910,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000004"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); ExpectFilledField("Card Name", "cardname", "Elvis", "text", response_data.fields[0]); @@ -3970,8 +3957,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000004"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); ExpectFilledField("Card Name", "cardname", "Elvis", "text", response_data.fields[0]); @@ -4045,8 +4031,7 @@ personal_data().AddProfile(profile); FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); // Verify the correct filling of the name entries. @@ -4095,8 +4080,7 @@ FormData response_data; { SCOPED_TRACE("Address"); - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); ExpectFilledAddressFormElvis(response_data, true); } @@ -4104,9 +4088,8 @@ // Now fill the credit card data. const char guid2[] = "00000000-0000-0000-0000-000000000004"; { - FillAutofillFormDataAndSaveResults( - form, form.fields.back(), MakeFrontendId({.credit_card_id = guid2}), - &response_data); + FillAutofillFormDataAndSaveResults(form, form.fields.back(), guid2, + &response_data); SCOPED_TRACE("Credit card"); ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/true); } @@ -4228,8 +4211,7 @@ FormData response_data; FillAutofillFormDataAndSaveResults( form, form.fields[0], - MakeFrontendId({.credit_card_id = params.cc_guid, - .profile_id = params.profile_guid}), + params.cc_guid.empty() ? params.profile_guid : params.cc_guid, &response_data); ASSERT_EQ(response_data.fields.size(), params.expected_form_fields.size()); @@ -4262,8 +4244,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000004"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); // All fields should be filled. @@ -4310,8 +4291,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000009"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); // The credit card name, type and number should be filled. @@ -4397,8 +4377,7 @@ // Fill the form const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); // All the visible fields should be filled as all the fields belong to the @@ -4433,8 +4412,7 @@ // Fill the first section. const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); { SCOPED_TRACE("Address 1"); @@ -4454,8 +4432,7 @@ const char guid2[] = "00000000-0000-0000-0000-000000000001"; ASSERT_LT(9U, kAddressFormSize); FillAutofillFormDataAndSaveResults(form, form.fields[kAddressFormSize + 9], - MakeFrontendId({.profile_id = guid2}), - &response_data); + guid2, &response_data); { SCOPED_TRACE("Address 2"); ASSERT_EQ(response_data.fields.size(), form.fields.size()); @@ -4538,8 +4515,7 @@ // Fill the unnamed section. const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, form.fields[1], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[1], guid, &response_data); { SCOPED_TRACE("Unnamed section"); @@ -4566,8 +4542,7 @@ // Fill the address portion of the billing section. const char guid2[] = "00000000-0000-0000-0000-000000000001"; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid2}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid2, &response_data); { SCOPED_TRACE("Billing address"); @@ -4594,8 +4569,7 @@ // Fill the credit card portion of the billing section. const char guid3[] = "00000000-0000-0000-0000-000000000004"; FillAutofillFormDataAndSaveResults(form, form.fields[form.fields.size() - 2], - MakeFrontendId({.credit_card_id = guid3}), - &response_data); + guid3, &response_data); { SCOPED_TRACE("Credit card"); EXPECT_EQ(u"MyForm", response_data.name); @@ -4634,8 +4608,7 @@ // Fill the form. const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); // The second email address should be filled. @@ -4662,8 +4635,7 @@ // First fill the address data. const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); { SCOPED_TRACE("Address"); @@ -4675,8 +4647,7 @@ // Now fill the credit card data. const char guid2[] = "00000000-0000-0000-0000-000000000004"; - FillAutofillFormDataAndSaveResults(form, form.fields.back(), - MakeFrontendId({.credit_card_id = guid2}), + FillAutofillFormDataAndSaveResults(form, form.fields.back(), guid2, &response_data); { SCOPED_TRACE("Credit card 1"); @@ -4690,8 +4661,7 @@ } FillAutofillFormDataAndSaveResults(form, form.fields[form.fields.size() - 2], - MakeFrontendId({.credit_card_id = guid2}), - &response_data); + guid2, &response_data); { SCOPED_TRACE("Credit card 2"); TestCardFillData expected_card_fill_data = kEmptyCardFillData; @@ -4719,8 +4689,7 @@ // First fill the address data. const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); { SCOPED_TRACE("Address"); @@ -4738,8 +4707,7 @@ // Now fill the credit card data. const char guid2[] = "00000000-0000-0000-0000-000000000004"; - FillAutofillFormDataAndSaveResults(form, form.fields.back(), - MakeFrontendId({.credit_card_id = guid2}), + FillAutofillFormDataAndSaveResults(form, form.fields.back(), guid2, &response_data); { SCOPED_TRACE("Credit card 1"); @@ -4770,8 +4738,7 @@ // First fill the address data. const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); { SCOPED_TRACE("Address"); @@ -4783,8 +4750,7 @@ // Now fill the credit card data. const char guid2[] = "00000000-0000-0000-0000-000000000004"; - FillAutofillFormDataAndSaveResults(form, form.fields.back(), - MakeFrontendId({.credit_card_id = guid2}), + FillAutofillFormDataAndSaveResults(form, form.fields.back(), guid2, &response_data); { SCOPED_TRACE("Credit card 1"); @@ -4849,8 +4815,7 @@ FormData response_data1; FillAutofillFormDataAndSaveResults( form_with_us_number_max_length, - *form_with_us_number_max_length.fields.begin(), - MakeFrontendId({.profile_id = guid}), &response_data1); + *form_with_us_number_max_length.fields.begin(), guid, &response_data1); ASSERT_EQ(5U, response_data1.fields.size()); EXPECT_EQ(u"1", response_data1.fields[0].value); @@ -4860,9 +4825,9 @@ EXPECT_EQ(std::u16string(), response_data1.fields[4].value); FormData response_data2; - FillAutofillFormDataAndSaveResults( - form_with_autocompletetype, *form_with_autocompletetype.fields.begin(), - MakeFrontendId({.profile_id = guid}), &response_data2); + FillAutofillFormDataAndSaveResults(form_with_autocompletetype, + *form_with_autocompletetype.fields.begin(), + guid, &response_data2); ASSERT_EQ(5U, response_data2.fields.size()); EXPECT_EQ(u"1", response_data2.fields[0].value); @@ -4877,8 +4842,7 @@ FormData response_data3; FillAutofillFormDataAndSaveResults( form_with_us_number_max_length, - *form_with_us_number_max_length.fields.begin(), - MakeFrontendId({.profile_id = guid}), &response_data3); + *form_with_us_number_max_length.fields.begin(), guid, &response_data3); ASSERT_EQ(5U, response_data3.fields.size()); EXPECT_EQ(u"4", response_data3.fields[0].value); @@ -4888,9 +4852,9 @@ EXPECT_EQ(std::u16string(), response_data3.fields[4].value); FormData response_data4; - FillAutofillFormDataAndSaveResults( - form_with_autocompletetype, *form_with_autocompletetype.fields.begin(), - MakeFrontendId({.profile_id = guid}), &response_data4); + FillAutofillFormDataAndSaveResults(form_with_autocompletetype, + *form_with_autocompletetype.fields.begin(), + guid, &response_data4); ASSERT_EQ(5U, response_data4.fields.size()); EXPECT_EQ(u"44", response_data4.fields[0].value); @@ -4945,8 +4909,8 @@ FormData response_data; FillAutofillFormDataAndSaveResults( form_with_multiple_componentized_phone_fields, - *form_with_multiple_componentized_phone_fields.fields.begin(), - MakeFrontendId({.profile_id = guid}), &response_data); + *form_with_multiple_componentized_phone_fields.fields.begin(), guid, + &response_data); // Verify only the first complete set of phone number fields are filled. ASSERT_EQ(8U, response_data.fields.size()); @@ -4991,8 +4955,8 @@ FormData response_data; FillAutofillFormDataAndSaveResults( form_with_multiple_whole_number_fields, - *form_with_multiple_whole_number_fields.fields.begin(), - MakeFrontendId({.profile_id = guid}), &response_data); + *form_with_multiple_whole_number_fields.fields.begin(), guid, + &response_data); // Verify only the first complete set of phone number fields are filled. ASSERT_EQ(4U, response_data.fields.size()); @@ -5048,8 +5012,8 @@ FormData response_data; FillAutofillFormDataAndSaveResults( form_with_multiple_componentized_phone_fields, - *form_with_multiple_componentized_phone_fields.fields.begin(), - MakeFrontendId({.profile_id = guid}), &response_data); + *form_with_multiple_componentized_phone_fields.fields.begin(), guid, + &response_data); // Verify only the first complete set of phone number fields are filled, // and phone components are not filled more than once. @@ -5105,8 +5069,7 @@ FormData response_data; FillAutofillFormDataAndSaveResults( form_with_misclassified_extension, - *form_with_misclassified_extension.fields.begin(), - MakeFrontendId({.profile_id = guid}), &response_data); + *form_with_misclassified_extension.fields.begin(), guid, &response_data); // Verify the misclassified extension field is not filled. ASSERT_EQ(5U, response_data.fields.size()); @@ -5154,8 +5117,7 @@ FormData response_data; FillAutofillFormDataAndSaveResults( form_with_no_complete_number, - *form_with_no_complete_number.fields.begin(), - MakeFrontendId({.profile_id = guid}), &response_data); + *form_with_no_complete_number.fields.begin(), guid, &response_data); // Verify when there is no complete phone number fields, we do best effort // filling. @@ -5202,8 +5164,7 @@ // Move it to point to "shipping number". std::advance(it, 3); FillAutofillFormDataAndSaveResults(form_with_multiple_whole_number_fields, - *it, MakeFrontendId({.profile_id = guid}), - &response_data); + *it, guid, &response_data); // Verify when the second phone number field is being focused, we fill // that field *AND* the first phone number field. @@ -5248,8 +5209,8 @@ FormData response_data; FillAutofillFormDataAndSaveResults( form_with_multiple_whole_number_fields, - *form_with_multiple_whole_number_fields.fields.begin(), - MakeFrontendId({.profile_id = guid}), &response_data); + *form_with_multiple_whole_number_fields.fields.begin(), guid, + &response_data); // Verify hidden/non-focusable phone field is set to only_fill_when_focused. ASSERT_EQ(4U, response_data.fields.size()); @@ -5309,8 +5270,7 @@ FormData response_data; base::HistogramTester histogram_tester; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); histogram_tester.ExpectTotalCount( "Autofill.HiddenOrPresentationalSelectFieldsFilled", 2); @@ -5373,7 +5333,7 @@ // Fill first sections. FillAutofillFormDataAndSaveResults( form_with_multiple_sections, *form_with_multiple_sections.fields.begin(), - MakeFrontendId({.profile_id = guid}), &response_data); + guid, &response_data); // Verify first section is filled with rationalization. ASSERT_EQ(9U, response_data.fields.size()); @@ -5391,8 +5351,7 @@ auto it = form_with_multiple_sections.fields.begin(); std::advance(it, 6); // Pointing to second section. - FillAutofillFormDataAndSaveResults(form_with_multiple_sections, *it, - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form_with_multiple_sections, *it, guid, &response_data); // Verify second section is filled with rationalization. @@ -5428,8 +5387,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); ExpectFilledAddressFormElvis(response_data, false); } @@ -5457,8 +5415,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); ExpectFilledAddressFormElvis(response_data, false); } @@ -5497,8 +5454,7 @@ // filled. const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); ASSERT_EQ(5U, response_data.fields.size()); @@ -5522,8 +5478,7 @@ FormData later_response_data; const char guid2[] = "00000000-0000-0000-0000-000000000002"; FillAutofillFormDataAndSaveResults(response_data, response_data.fields[4], - MakeFrontendId({.profile_id = guid2}), - &later_response_data); + guid2, &later_response_data); ASSERT_EQ(5U, later_response_data.fields.size()); ExpectFilledField("First Name", "first_name", "Elvis", "text", later_response_data.fields[0]); @@ -5547,8 +5502,7 @@ // Fill the form. const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); ExpectFilledAddressFormElvis(response_data, false); @@ -5568,8 +5522,7 @@ // Fill the form. const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); ExpectFilledAddressFormElvis(response_data, false); @@ -5683,8 +5636,7 @@ // Fill the form. const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); ExpectFilledAddressFormElvis(response_data, false); @@ -5764,8 +5716,7 @@ profile1.set_guid(guid); personal_data().AddProfile(profile1); FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); TestAddressFillData expected_address_fill_data = address_fill_data; @@ -5863,8 +5814,7 @@ profile1.set_guid(guid); personal_data().AddProfile(profile1); FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); TestAddressFillData expected_address_fill_data = address_fill_data; @@ -5874,8 +5824,7 @@ // Refill the address data with all the field values. const char guid2[] = "00000000-0000-0000-0000-000000000001"; FillAutofillFormDataAndSaveResults( - response_data, *response_data.fields.begin(), - MakeFrontendId({.profile_id = guid2}), &response_data); + response_data, *response_data.fields.begin(), guid2, &response_data); expected_address_fill_data.first = "Elvis"; expected_address_fill_data.phone = "12345678901"; @@ -5974,8 +5923,7 @@ // Fill the form. const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); ExpectFilledAddressFormElvis(response_data, false); @@ -6059,8 +6007,7 @@ // Fill the form by triggering the suggestion from "Name on Card" field. const char guid[] = "00000000-0000-0000-0000-000000000004"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &response_data); ExpectFilledCreditCardFormElvis(response_data, /*has_address_fields=*/false); @@ -6927,8 +6874,7 @@ // Fill the form. const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); ExpectFilledAddressFormElvis(response_data, false); @@ -6974,10 +6920,8 @@ // Fill the form. FormData response_data; - FillAutofillFormDataAndSaveResults( - form, form.fields[3], MakeFrontendId({.profile_id = kElvisProfileGuid}), - &response_data); - + FillAutofillFormDataAndSaveResults(form, form.fields[3], kElvisProfileGuid, + &response_data); // Set the address field's value back to the default value. response_data.fields[3].value = u"Enter your address"; @@ -7004,9 +6948,8 @@ // Fill the form. FormData response_data; - FillAutofillFormDataAndSaveResults( - form, form.fields[3], MakeFrontendId({.profile_id = kElvisProfileGuid}), - &response_data); + FillAutofillFormDataAndSaveResults(form, form.fields[3], kElvisProfileGuid, + &response_data); FormSubmitted(response_data); ASSERT_EQ(1, personal_data().num_times_save_imported_profile_called()); @@ -7834,9 +7777,8 @@ profile.set_guid(guid); personal_data().AddProfile(profile); - Suggestion::FrontendId id = MakeFrontendId({.profile_id = guid}); - - browser_autofill_manager_->RemoveAutofillProfileOrCreditCard(id); + browser_autofill_manager_->RemoveAutofillProfileOrCreditCard( + Suggestion::BackendId(guid)); EXPECT_FALSE(personal_data().GetProfileByGUID(guid)); } @@ -7848,9 +7790,8 @@ credit_card.set_guid(guid); personal_data().AddCreditCard(credit_card); - Suggestion::FrontendId id = MakeFrontendId({.credit_card_id = guid}); - - browser_autofill_manager_->RemoveAutofillProfileOrCreditCard(id); + browser_autofill_manager_->RemoveAutofillProfileOrCreditCard( + Suggestion::BackendId(guid)); EXPECT_FALSE(personal_data().GetCreditCardByGUID(guid)); } @@ -8216,8 +8157,7 @@ // Expect no fields filled, no form data sent to renderer. EXPECT_CALL(*autofill_driver_, FillOrPreviewForm(_, _, _, _)).Times(0); - FillAutofillFormData(form, *form.fields.begin(), - MakeFrontendId({.profile_id = guid})); + FillAutofillFormData(form, *form.fields.begin(), guid); } TEST_F(BrowserAutofillManagerTest, ProfileDisabledDoesNotSuggest) { @@ -8249,8 +8189,7 @@ // Expect no fields filled, no form data sent to renderer. EXPECT_CALL(*autofill_driver_, FillOrPreviewForm(_, _, _, _)).Times(0); - FillAutofillFormData(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid})); + FillAutofillFormData(form, *form.fields.begin(), guid); } TEST_F(BrowserAutofillManagerTest, CreditCardDisabledDoesNotSuggest) { @@ -10046,8 +9985,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); EXPECT_EQ(response_data.fields[0].value, u"Elvis Aaron Presley"); EXPECT_EQ(response_data.fields[1].value, u"Test City"); @@ -10094,8 +10032,7 @@ features.InitAndDisableFeature( autofill::features::kAutofillPreventOverridingPrefilledValues); - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); EXPECT_EQ(response_data.fields[0].value, u"Elvis Aaron Presley"); EXPECT_EQ(response_data.fields[1].value, u"Memphis"); @@ -10140,8 +10077,7 @@ const char guid[] = "00000000-0000-0000-0000-000000000001"; FormData response_data; - FillAutofillFormDataAndSaveResults(form, form.fields[0], - MakeFrontendId({.profile_id = guid}), + FillAutofillFormDataAndSaveResults(form, form.fields[0], guid, &response_data); EXPECT_EQ(response_data.fields[0].value, u"Elvis Aaron Presley"); EXPECT_EQ(response_data.fields[1].value, u"Test City"); @@ -10223,8 +10159,7 @@ AutofillProfile profile = test::GetFullProfile(); personal_data().AddProfile(profile); - FillAutofillFormData(form, form.fields[0], - MakeFrontendId({.profile_id = profile.guid()})); + FillAutofillFormData(form, form.fields[0], profile.guid()); FormStructure* form_structure = browser_autofill_manager_->FindCachedFormById(form.global_id()); @@ -10250,9 +10185,8 @@ profile1.ClearFields({EMAIL_ADDRESS}); personal_data().AddProfile(profile1); FormData response_data; - FillAutofillFormDataAndSaveResults( - form, form.fields[0], MakeFrontendId({.profile_id = profile1.guid()}), - &response_data); + FillAutofillFormDataAndSaveResults(form, form.fields[0], profile1.guid(), + &response_data); // Check that the email field has no filling source. FormStructure* form_structure = @@ -10265,9 +10199,8 @@ AutofillProfile profile2 = test::GetFullProfile(); personal_data().AddProfile(profile2); FormData later_response_data; - FillAutofillFormDataAndSaveResults( - response_data, form.fields[3], - MakeFrontendId({.profile_id = profile2.guid()}), &later_response_data); + FillAutofillFormDataAndSaveResults(response_data, form.fields[3], + profile2.guid(), &later_response_data); // Check that the first three fields have the first profile as filling source // and the last field has the second profile. @@ -10296,9 +10229,8 @@ AutofillProfile profile = test::GetFullProfile(); personal_data().AddProfile(profile); FormData response_data; - FillAutofillFormDataAndSaveResults( - form, form.fields[0], MakeFrontendId({.profile_id = profile.guid()}), - &response_data); + FillAutofillFormDataAndSaveResults(form, form.fields[0], profile.guid(), + &response_data); // Simulate editing the first field. response_data.fields[0].value = u"Michael"; @@ -10328,8 +10260,7 @@ AutofillProfile profile = test::GetFullProfile(); profile.ClearFields({EMAIL_ADDRESS}); personal_data().AddProfile(profile); - FillAutofillFormData(form, form.fields[0], - MakeFrontendId({.profile_id = profile.guid()})); + FillAutofillFormData(form, form.fields[0], profile.guid()); FormStructure* form_structure = browser_autofill_manager_->FindCachedFormById(form.global_id()); @@ -10951,8 +10882,7 @@ // Simulate filling and store the data to be filled in |first_fill_data|. const char guid[] = "00000000-0000-0000-0000-000000000004"; FormData first_fill_data; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &first_fill_data); ASSERT_EQ(3u, first_fill_data.fields.size()); ExpectFilledField("Name on Card", "nameoncard", "Elvis Presley", "text", @@ -11065,8 +10995,7 @@ // Simulate filling and store the data to be filled in `fill_data_`. const char guid[] = "00000000-0000-0000-0000-000000000004"; - FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), - MakeFrontendId({.credit_card_id = guid}), + FillAutofillFormDataAndSaveResults(form, *form.fields.begin(), guid, &fill_data_); ASSERT_EQ(3u, fill_data_.fields.size()); ExpectFilledField("Name on Card", "nameoncard", "Elvis Presley", "text",
diff --git a/components/autofill/core/browser/metrics/autofill_metrics.cc b/components/autofill/core/browser/metrics/autofill_metrics.cc index 8b9f82e9..e216004c 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics.cc +++ b/components/autofill/core/browser/metrics/autofill_metrics.cc
@@ -2046,8 +2046,7 @@ return field.origin != triggered_origin && (field.origin != main_origin || IsSensitiveFieldType(field.Type().GetStorableType())) && - (triggered_origin == main_origin || - features::kAutofillSharedAutofillRelaxedParam.Get()); + triggered_origin == main_origin; }; bool some_field_needs_shared_autofill = false;
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_test_base.h b/components/autofill/core/browser/metrics/autofill_metrics_test_base.h index 58811023..66f000f 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics_test_base.h +++ b/components/autofill/core/browser/metrics/autofill_metrics_test_base.h
@@ -168,8 +168,7 @@ void FillTestProfile(const FormData& form) { autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - MakeFrontendId({.profile_id = kTestProfileId}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kTestProfileId), AutofillTriggerSource::kPopup); } Suggestion::FrontendId MakeFrontendId(
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc index e79fe05..713107e 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc +++ b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
@@ -1948,8 +1948,7 @@ base::UserActionTester user_action_tester; autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - MakeFrontendId({.credit_card_id = kTestLocalCardId}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kTestLocalCardId), AutofillTriggerSource::kPopup); EXPECT_EQ(1, user_action_tester.GetActionCount( "Autofill_FilledCreditCardSuggestion")); } @@ -2638,7 +2637,7 @@ base::HistogramTester histogram_tester; autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields[2], - MakeFrontendId({.credit_card_id = kTestMaskedCardId}), + Suggestion::BackendId(kTestMaskedCardId), AutofillTriggerSource::kPopup); EXPECT_THAT( histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), @@ -2662,11 +2661,11 @@ base::HistogramTester histogram_tester; autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields[2], - MakeFrontendId({.credit_card_id = kTestMaskedCardId}), + Suggestion::BackendId(kTestMaskedCardId), AutofillTriggerSource::kPopup); autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields[2], - MakeFrontendId({.credit_card_id = kTestMaskedCardId}), + Suggestion::BackendId(kTestMaskedCardId), AutofillTriggerSource::kPopup); EXPECT_THAT( histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), @@ -2760,8 +2759,7 @@ base::HistogramTester histogram_tester; autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - MakeFrontendId({.credit_card_id = kTestLocalCardId}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kTestLocalCardId), AutofillTriggerSource::kPopup); EXPECT_THAT( histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), BucketsInclude(Bucket(FORM_EVENT_LOCAL_SUGGESTION_FILLED, 1), @@ -2807,7 +2805,7 @@ base::HistogramTester histogram_tester; autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.back(), - MakeFrontendId({.credit_card_id = kTestMaskedCardId}), + Suggestion::BackendId(kTestMaskedCardId), AutofillTriggerSource::kPopup); OnCreditCardFetchingSuccessful(u"6011000990139424"); SubmitForm(form); @@ -2840,7 +2838,7 @@ base::HistogramTester histogram_tester; autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - MakeFrontendId({.credit_card_id = kTestFullServerCardId}), + Suggestion::BackendId(kTestFullServerCardId), AutofillTriggerSource::kPopup); EXPECT_THAT( histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), @@ -2862,12 +2860,10 @@ base::HistogramTester histogram_tester; autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - MakeFrontendId({.credit_card_id = kTestLocalCardId}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kTestLocalCardId), AutofillTriggerSource::kPopup); autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - MakeFrontendId({.credit_card_id = kTestLocalCardId}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kTestLocalCardId), AutofillTriggerSource::kPopup); EXPECT_THAT( histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), BucketsInclude(Bucket(FORM_EVENT_LOCAL_SUGGESTION_FILLED, 2), @@ -2903,8 +2899,7 @@ base::HistogramTester histogram_tester; autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - MakeFrontendId({.credit_card_id = local_guid}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(local_guid), AutofillTriggerSource::kPopup); EXPECT_THAT( histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), @@ -2945,8 +2940,7 @@ // Local card with a duplicate server card present at index 0. autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - MakeFrontendId({.credit_card_id = local_guid}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(local_guid), AutofillTriggerSource::kPopup); EXPECT_THAT( histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), @@ -2988,7 +2982,7 @@ base::HistogramTester histogram_tester; autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.back(), - MakeFrontendId({.credit_card_id = kTestMaskedCardId}), + Suggestion::BackendId(kTestMaskedCardId), AutofillTriggerSource::kPopup); OnDidGetRealPan(AutofillClient::PaymentsRpcResult::kSuccess, "6011000990139424"); @@ -3012,7 +3006,7 @@ base::HistogramTester histogram_tester; autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.back(), - MakeFrontendId({.credit_card_id = kTestMaskedCardId}), + Suggestion::BackendId(kTestMaskedCardId), AutofillTriggerSource::kPopup); OnDidGetRealPan(AutofillClient::PaymentsRpcResult::kPermanentFailure, std::string()); @@ -3049,7 +3043,7 @@ base::HistogramTester histogram_tester; autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.back(), - MakeFrontendId({.credit_card_id = kTestMaskedCardId}), + Suggestion::BackendId(kTestMaskedCardId), AutofillTriggerSource::kPopup); OnDidGetRealPanWithNonHttpOkResponse(); histogram_tester.ExpectTotalCount( @@ -3327,8 +3321,7 @@ autofill_manager().OnAskForValuesToFillTest(form, form.fields[0]); autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.back(), - MakeFrontendId({.credit_card_id = kTestLocalCardId}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kTestLocalCardId), AutofillTriggerSource::kPopup); SubmitForm(form); EXPECT_THAT( @@ -3507,8 +3500,7 @@ autofill_manager().OnAskForValuesToFillTest(form, form.fields.back()); autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - MakeFrontendId({.credit_card_id = kTestLocalCardId}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kTestLocalCardId), AutofillTriggerSource::kPopup); SubmitForm(form); EXPECT_THAT( histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), @@ -3593,7 +3585,7 @@ autofill_manager().OnAskForValuesToFillTest(form, form.fields.back()); autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - MakeFrontendId({.credit_card_id = kTestFullServerCardId}), + Suggestion::BackendId(kTestFullServerCardId), AutofillTriggerSource::kPopup); SubmitForm(form); @@ -3634,7 +3626,7 @@ base::HistogramTester histogram_tester; autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.back(), - MakeFrontendId({.credit_card_id = kTestMaskedCardId}), + Suggestion::BackendId(kTestMaskedCardId), AutofillTriggerSource::kPopup); OnCreditCardFetchingSuccessful(u"6011000990139424"); SubmitForm(form); @@ -3880,8 +3872,7 @@ autofill_manager().OnAskForValuesToFillTest(form, form.fields[0]); autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - MakeFrontendId({.credit_card_id = kTestLocalCardId}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kTestLocalCardId), AutofillTriggerSource::kPopup); SubmitForm(form); EXPECT_THAT( histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), @@ -3933,7 +3924,7 @@ // Full server card. autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - MakeFrontendId({.credit_card_id = kTestFullServerCardId}), + Suggestion::BackendId(kTestFullServerCardId), AutofillTriggerSource::kPopup); SubmitForm(form); EXPECT_THAT( @@ -3956,7 +3947,7 @@ base::HistogramTester histogram_tester; autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.back(), - MakeFrontendId({.credit_card_id = kTestMaskedCardId}), + Suggestion::BackendId(kTestMaskedCardId), AutofillTriggerSource::kPopup); OnCreditCardFetchingSuccessful(u"6011000990139424"); EXPECT_THAT( @@ -4097,8 +4088,7 @@ form.fields.back()); autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - MakeFrontendId({.credit_card_id = kTestLocalCardId}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kTestLocalCardId), AutofillTriggerSource::kPopup); EXPECT_THAT( histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), BucketsInclude(Bucket(FORM_EVENT_SUGGESTIONS_SHOWN, 1), @@ -4145,7 +4135,7 @@ // Select the masked server card with the linked offer. autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.back(), - MakeFrontendId({.credit_card_id = kMaskedServerCardIds[0]}), + Suggestion::BackendId(kMaskedServerCardIds[0]), AutofillTriggerSource::kPopup); OnDidGetRealPan(AutofillClient::PaymentsRpcResult::kSuccess, "6011000990139424"); @@ -4193,7 +4183,7 @@ // sub-histogram because user has another masked server card with offer. autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.back(), - MakeFrontendId({.credit_card_id = kTestMaskedCardId}), + Suggestion::BackendId(kTestMaskedCardId), AutofillTriggerSource::kPopup); OnDidGetRealPan(AutofillClient::PaymentsRpcResult::kSuccess, "6011000990139424"); @@ -4247,7 +4237,7 @@ // since the offer is expired. autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.back(), - MakeFrontendId({.credit_card_id = kMaskedServerCardIds[1]}), + Suggestion::BackendId(kMaskedServerCardIds[1]), AutofillTriggerSource::kPopup); OnDidGetRealPan(AutofillClient::PaymentsRpcResult::kSuccess, "6011000990139424"); @@ -4313,7 +4303,7 @@ // Select the masked server card with the linked offer. autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.back(), - MakeFrontendId({.credit_card_id = kMaskedServerCardIds[2]}), + Suggestion::BackendId(kMaskedServerCardIds[2]), AutofillTriggerSource::kPopup); OnDidGetRealPan(AutofillClient::PaymentsRpcResult::kSuccess, "6011000990139424"); @@ -4367,7 +4357,7 @@ // check. autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.back(), - MakeFrontendId({.credit_card_id = kMaskedServerCardIds[2]}), + Suggestion::BackendId(kMaskedServerCardIds[2]), AutofillTriggerSource::kPopup); OnDidGetRealPan(AutofillClient::PaymentsRpcResult::kPermanentFailure, std::string()); @@ -4417,7 +4407,7 @@ form.fields.back()); autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.back(), - MakeFrontendId({.credit_card_id = kMaskedServerCardIds[2]}), + Suggestion::BackendId(kMaskedServerCardIds[2]), AutofillTriggerSource::kPopup); OnDidGetRealPan(AutofillClient::PaymentsRpcResult::kSuccess, "6011000990139424"); @@ -4428,8 +4418,7 @@ form.fields.back()); autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.back(), - MakeFrontendId({.credit_card_id = kTestLocalCardId}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kTestLocalCardId), AutofillTriggerSource::kPopup); SubmitForm(form); EXPECT_THAT( histogram_tester.GetAllSamples( @@ -5869,8 +5858,7 @@ base::HistogramTester histogram_tester; autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - MakeFrontendId({.credit_card_id = kTestLocalCardId}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kTestLocalCardId), AutofillTriggerSource::kPopup); SimulateUserChangedTextField(form, form.fields.front()); // Simulate a second keystroke; make sure we don't log the metric twice. SimulateUserChangedTextField(form, form.fields.front()); @@ -9023,8 +9011,7 @@ // Simulate filling the form. autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - is_cc_form ? MakeFrontendId({.credit_card_id = kTestLocalCardId}) - : MakeFrontendId({.profile_id = kTestProfileId}), + Suggestion::BackendId(is_cc_form ? kTestLocalCardId : kTestProfileId), AutofillTriggerSource::kPopup); if (GetParam().change_form_after_filling)
diff --git a/components/autofill/core/browser/metrics/form_events/address_form_event_logger_unittest.cc b/components/autofill/core/browser/metrics/form_events/address_form_event_logger_unittest.cc index 4bcffec..10cc0836 100644 --- a/components/autofill/core/browser/metrics/form_events/address_form_event_logger_unittest.cc +++ b/components/autofill/core/browser/metrics/form_events/address_form_event_logger_unittest.cc
@@ -98,8 +98,7 @@ autofill_manager().OnAskForValuesToFillTest(form, form.fields.front()); autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form, form.fields.front(), - MakeFrontendId({.profile_id = profile.guid()}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(profile.guid()), AutofillTriggerSource::kPopup); } protected:
diff --git a/components/autofill/core/browser/metrics/payments/DIR_METADATA b/components/autofill/core/browser/metrics/payments/DIR_METADATA new file mode 100644 index 0000000..d9bf029 --- /dev/null +++ b/components/autofill/core/browser/metrics/payments/DIR_METADATA
@@ -0,0 +1,3 @@ +monorail: { + component: "UI>Browser>Autofill>Payments" +}
diff --git a/components/autofill/core/browser/metrics/payments/card_metadata_metrics_unittest.cc b/components/autofill/core/browser/metrics/payments/card_metadata_metrics_unittest.cc index f72fc2c..c455b7de 100644 --- a/components/autofill/core/browser/metrics/payments/card_metadata_metrics_unittest.cc +++ b/components/autofill/core/browser/metrics/payments/card_metadata_metrics_unittest.cc
@@ -164,8 +164,7 @@ form(), form().fields.back()); autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form(), form().fields.back(), - MakeFrontendId({.credit_card_id = kCardGuid}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kCardGuid), AutofillTriggerSource::kPopup); const bool should_log_for_metadata = card_issuer_available() && card_metadata_available(); @@ -204,8 +203,7 @@ // Select the suggestion again. autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form(), form().fields.back(), - MakeFrontendId({.credit_card_id = kCardGuid}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kCardGuid), AutofillTriggerSource::kPopup); EXPECT_THAT( histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), @@ -234,8 +232,7 @@ // Simulate filling the card. autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form(), form().fields.back(), - MakeFrontendId({.credit_card_id = kCardGuid}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kCardGuid), AutofillTriggerSource::kPopup); autofill_manager().OnCreditCardFetchedForTest(CreditCardFetchResult::kSuccess, &card(), u"123"); @@ -267,8 +264,7 @@ autofill_manager().OnAskForValuesToFillTest(form(), form().fields.back()); autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form(), form().fields.back(), - MakeFrontendId({.credit_card_id = kCardGuid}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kCardGuid), AutofillTriggerSource::kPopup); autofill_manager().OnCreditCardFetchedForTest(CreditCardFetchResult::kSuccess, &card(), u"123"); SubmitForm(form()); @@ -384,8 +380,7 @@ test_clock.SetNowTicks(now + base::Seconds(2)); autofill_manager().FillOrPreviewForm( mojom::RendererFormDataAction::kFill, form(), form().fields.front(), - MakeFrontendId({.credit_card_id = kTestMaskedCardId}), - AutofillTriggerSource::kPopup); + Suggestion::BackendId(kTestMaskedCardId), AutofillTriggerSource::kPopup); std::string latency_histogram_prefix = "Autofill.CreditCard.SelectionLatencySinceShown.";
diff --git a/components/autofill/core/browser/payments/DIR_METADATA b/components/autofill/core/browser/payments/DIR_METADATA new file mode 100644 index 0000000..d9bf029 --- /dev/null +++ b/components/autofill/core/browser/payments/DIR_METADATA
@@ -0,0 +1,3 @@ +monorail: { + component: "UI>Browser>Autofill>Payments" +}
diff --git a/components/autofill/core/browser/ui/autofill_popup_delegate.h b/components/autofill/core/browser/ui/autofill_popup_delegate.h index 38b9173..9527c94f 100644 --- a/components/autofill/core/browser/ui/autofill_popup_delegate.h +++ b/components/autofill/core/browser/ui/autofill_popup_delegate.h
@@ -51,13 +51,15 @@ // fills out |title| and |body|. virtual bool GetDeletionConfirmationText(const std::u16string& value, Suggestion::FrontendId frontend_id, + Suggestion::BackendId backend_id, std::u16string* title, std::u16string* body) = 0; // Delete the described suggestion. Returns true if something was deleted, // or false if deletion is not allowed. virtual bool RemoveSuggestion(const std::u16string& value, - Suggestion::FrontendId frontend_id) = 0; + Suggestion::FrontendId frontend_id, + Suggestion::BackendId backend_id) = 0; // Informs the delegate that the Autofill previewed form should be cleared. virtual void ClearPreviewedForm() = 0;
diff --git a/components/autofill/core/browser/ui/mock_autofill_popup_delegate.h b/components/autofill/core/browser/ui/mock_autofill_popup_delegate.h index 03a808cc..bfef70f8 100644 --- a/components/autofill/core/browser/ui/mock_autofill_popup_delegate.h +++ b/components/autofill/core/browser/ui/mock_autofill_popup_delegate.h
@@ -37,12 +37,15 @@ GetDeletionConfirmationText, (const std::u16string& value, Suggestion::FrontendId frontend_id, + Suggestion::BackendId backend_id, std::u16string* title, std::u16string* body), (override)); MOCK_METHOD(bool, RemoveSuggestion, - (const std::u16string& value, Suggestion::FrontendId frontend_id), + (const std::u16string& value, + Suggestion::FrontendId frontend_id, + Suggestion::BackendId backend_id), (override)); MOCK_METHOD(void, ClearPreviewedForm, (), (override)); MOCK_METHOD(PopupType, GetPopupType, (), (const, override));
diff --git a/components/autofill/core/browser/ui/payments/DIR_METADATA b/components/autofill/core/browser/ui/payments/DIR_METADATA new file mode 100644 index 0000000..d9bf029 --- /dev/null +++ b/components/autofill/core/browser/ui/payments/DIR_METADATA
@@ -0,0 +1,3 @@ +monorail: { + component: "UI>Browser>Autofill>Payments" +}
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index c1a8848..2d9f9b7 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -465,10 +465,6 @@ BASE_FEATURE(kAutofillSharedAutofill, "AutofillSharedAutofill", base::FEATURE_DISABLED_BY_DEFAULT); -// Relaxes the conditions under which a field is safe to fill. -// See FormForest::GetRendererFormsOfBrowserForm() for details. -const base::FeatureParam<bool> kAutofillSharedAutofillRelaxedParam{ - &kAutofillSharedAutofill, "relax_shared_autofill", false}; // Controls whether to offer a delete button for Autocomplete entries in the // Autofill popup.
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index 44039b7..4bcfc73 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -164,8 +164,6 @@ extern const base::FeatureParam<int> kAutofillServerBehaviorsParam; COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillSharedAutofill); COMPONENT_EXPORT(AUTOFILL) -extern const base::FeatureParam<bool> kAutofillSharedAutofillRelaxedParam; -COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillShowAutocompleteDeleteButton); COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillShowManualFallbackInContextMenu);
diff --git a/components/autofill_payments_strings_grdp/DIR_METADATA b/components/autofill_payments_strings_grdp/DIR_METADATA index 4ed8abe..0fe0572 100644 --- a/components/autofill_payments_strings_grdp/DIR_METADATA +++ b/components/autofill_payments_strings_grdp/DIR_METADATA
@@ -1,4 +1,4 @@ monorail { - component: "UI>Browser>Autofill" + component: "UI>Browser>Autofill>Payments" } team_email: "payments-autofill-team@google.com"
diff --git a/components/content_settings/core/browser/cookie_settings.cc b/components/content_settings/core/browser/cookie_settings.cc index 7ce34161..da11f3b 100644 --- a/components/content_settings/core/browser/cookie_settings.cc +++ b/components/content_settings/core/browser/cookie_settings.cc
@@ -42,7 +42,8 @@ : host_content_settings_map_(host_content_settings_map), is_incognito_(is_incognito), extension_scheme_(extension_scheme), - block_third_party_cookies_(false) { + block_third_party_cookies_( + net::cookie_util::IsForceThirdPartyCookieBlockingEnabled()) { content_settings_observation_.Observe(host_content_settings_map_.get()); pref_change_registrar_.Init(prefs); pref_change_registrar_.Add( @@ -304,6 +305,10 @@ } #endif + if (net::cookie_util::IsForceThirdPartyCookieBlockingEnabled()) { + return true; + } + CookieControlsMode mode = static_cast<CookieControlsMode>( pref_change_registrar_.prefs()->GetInteger(prefs::kCookieControlsMode));
diff --git a/components/content_settings/core/browser/cookie_settings_unittest.cc b/components/content_settings/core/browser/cookie_settings_unittest.cc index abef87c3..5403568 100644 --- a/components/content_settings/core/browser/cookie_settings_unittest.cc +++ b/components/content_settings/core/browser/cookie_settings_unittest.cc
@@ -422,6 +422,41 @@ /*top_frame_origin=*/absl::nullopt, cookie_setting_overrides)); } +TEST_P(CookieSettingsTest, ForceThirdPartyCookieBlocking) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + net::features::kForceThirdPartyCookieBlocking); + + auto cookie_setting_overrides = GetCookieSettingOverrides(); + + // Build new CookieSettings since `cookie_settings_` was created before + // ForceThirdPartyCookieBlocking was enabled. + scoped_refptr<CookieSettings> cookie_settings = new CookieSettings( + settings_map_.get(), &prefs_, false, "chrome-extension"); + + EXPECT_TRUE(cookie_settings->ShouldBlockThirdPartyCookies()); + + EXPECT_EQ(cookie_settings->IsFullCookieAccessAllowed( + kBlockedSite, kFirstPartySiteForCookies, + /*top_frame_origin=*/absl::nullopt, cookie_setting_overrides), + IsForceAllowThirdPartyCookies()); + + // Test that ForceThirdPartyCookieBlocking overrides preference changes. + prefs_.SetInteger(prefs::kCookieControlsMode, + static_cast<int>(CookieControlsMode::kOff)); + EXPECT_EQ(cookie_settings->IsFullCookieAccessAllowed( + kBlockedSite, kFirstPartySiteForCookies, + /*top_frame_origin=*/absl::nullopt, cookie_setting_overrides), + IsForceAllowThirdPartyCookies()); + + // Test that ForceThirdPartyCookieBlocking can be overridden by site-specific + // content settings. + cookie_settings->SetCookieSetting(kBlockedSite, CONTENT_SETTING_ALLOW); + EXPECT_TRUE(cookie_settings->IsFullCookieAccessAllowed( + kBlockedSite, kFirstPartySiteForCookies, + /*top_frame_origin=*/absl::nullopt, cookie_setting_overrides)); +} + #if BUILDFLAG(IS_IOS) // Test fixture with ImprovedCookieControls disabled. class ImprovedCookieControlsDisabledCookieSettingsTest
diff --git a/components/history/core/browser/expire_history_backend_unittest.cc b/components/history/core/browser/expire_history_backend_unittest.cc index c1a8108..e2470662 100644 --- a/components/history/core/browser/expire_history_backend_unittest.cc +++ b/components/history/core/browser/expire_history_backend_unittest.cc
@@ -208,7 +208,8 @@ void NotifyURLsDeleted(DeletionInfo deletion_info) override { urls_deleted_notifications_.push_back(std::move(deletion_info)); } - void NotifyVisitUpdated(const VisitRow& visit) override {} + void NotifyVisitUpdated(const VisitRow& visit, + VisitUpdateReason reason) override {} void NotifyVisitDeleted(const VisitRow& visit) override {} };
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc index 3b3b358..7699904fe 100644 --- a/components/history/core/browser/history_backend.cc +++ b/components/history/core/browser/history_backend.cc
@@ -714,7 +714,7 @@ annotations.page_language = page_language; db_->AddContentAnnotationsForVisit(visit_id, annotations); } - NotifyVisitUpdated(visit_row); + NotifyVisitUpdated(visit_row, VisitUpdateReason::kSetPageLanguage); ScheduleCommit(); } } @@ -751,7 +751,7 @@ annotations.password_state = password_state; db_->AddContentAnnotationsForVisit(visit_id, annotations); } - NotifyVisitUpdated(visit_row); + NotifyVisitUpdated(visit_row, VisitUpdateReason::kSetPasswordState); ScheduleCommit(); } } @@ -890,7 +890,7 @@ ? end_ts - visit_row.visit_time : base::Microseconds(0); db_->UpdateVisitRow(visit_row); - NotifyVisitUpdated(visit_row); + NotifyVisitUpdated(visit_row, VisitUpdateReason::kUpdateVisitDuration); } } @@ -1078,7 +1078,7 @@ visit_row.transition = ui::PageTransitionFromInt( visit_row.transition & ~ui::PAGE_TRANSITION_CHAIN_END); db_->UpdateVisitRow(visit_row); - NotifyVisitUpdated(visit_row); + NotifyVisitUpdated(visit_row, VisitUpdateReason::kUpdateTransition); } extended_redirect_chain = GetCachedRecentRedirects(request.referrer); @@ -1807,7 +1807,7 @@ content_annotations->password_state); } - NotifyVisitUpdated(updated_row); + NotifyVisitUpdated(updated_row, VisitUpdateReason::kUpdateSyncedVisit); ScheduleCommit(); return updated_row.visit_id; } @@ -2147,7 +2147,7 @@ if (!db_ || !db_->GetRowForVisit(visit_id, &visit_row)) return; db_->AddContextAnnotationsForVisit(visit_id, visit_context_annotations); - NotifyVisitUpdated(visit_row); + NotifyVisitUpdated(visit_row, VisitUpdateReason::kAddContextAnnotations); ScheduleCommit(); } @@ -2169,7 +2169,8 @@ } else { db_->AddContextAnnotationsForVisit(visit_id, visit_context_annotations); } - NotifyVisitUpdated(visit_row); + NotifyVisitUpdated(visit_row, + VisitUpdateReason::kSetOnCloseContextAnnotations); ScheduleCommit(); } @@ -3532,9 +3533,10 @@ delegate_->NotifyURLsDeleted(std::move(deletion_info)); } -void HistoryBackend::NotifyVisitUpdated(const VisitRow& visit) { +void HistoryBackend::NotifyVisitUpdated(const VisitRow& visit, + VisitUpdateReason reason) { for (HistoryBackendObserver& observer : observers_) { - observer.OnVisitUpdated(visit); + observer.OnVisitUpdated(visit, reason); } }
diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h index 35b0dae2..a340a5d 100644 --- a/components/history/core/browser/history_backend.h +++ b/components/history/core/browser/history_backend.h
@@ -961,7 +961,8 @@ void NotifyURLsModified(const URLRows& changed_urls, bool is_from_expiration) override; void NotifyURLsDeleted(DeletionInfo deletion_info) override; - void NotifyVisitUpdated(const VisitRow& visit) override; + void NotifyVisitUpdated(const VisitRow& visit, + VisitUpdateReason reason) override; void NotifyVisitDeleted(const VisitRow& visit) override; // Deleting all history ------------------------------------------------------
diff --git a/components/history/core/browser/history_backend_notifier.h b/components/history/core/browser/history_backend_notifier.h index 039d4fb..2140730 100644 --- a/components/history/core/browser/history_backend_notifier.h +++ b/components/history/core/browser/history_backend_notifier.h
@@ -45,7 +45,8 @@ virtual void NotifyURLsDeleted(DeletionInfo deletion_info) = 0; // Called after a visit has been updated. - virtual void NotifyVisitUpdated(const VisitRow& visit) = 0; + virtual void NotifyVisitUpdated(const VisitRow& visit, + VisitUpdateReason reason) = 0; // Called after a visit has been deleted. virtual void NotifyVisitDeleted(const VisitRow& visit) = 0;
diff --git a/components/history/core/browser/history_backend_observer.h b/components/history/core/browser/history_backend_observer.h index d9efb019..a2e23e7d 100644 --- a/components/history/core/browser/history_backend_observer.h +++ b/components/history/core/browser/history_backend_observer.h
@@ -61,10 +61,10 @@ const URLRows& deleted_rows, const std::set<GURL>& favicon_urls) = 0; - // Called when a visit is updated. Typically this happens when the visit - // duration is updated, and in some redirect cases when the transition type - // is updated. - virtual void OnVisitUpdated(const VisitRow& visit) = 0; + // Called when a visit, or some of its annotations, are updated. `reason` + // specifies what specifically was updated. + virtual void OnVisitUpdated(const VisitRow& visit, + VisitUpdateReason reason) = 0; // Called when a visit is deleted - usually either due to expiry, or because // the user explicitly deleted it.
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h index 7284129..6430bbe 100644 --- a/components/history/core/browser/history_types.h +++ b/components/history/core/browser/history_types.h
@@ -174,6 +174,20 @@ // used by HistoryBackend::AddVisits() to create new visits for a URL. typedef std::pair<base::Time, ui::PageTransition> VisitInfo; +// Specifies the possible reasons a visit (or its annotations) can get updated. +// Used by HistoryBackendNotifier::NotifyVisitUpdated() and +// HistoryBackendObserver::OnVisitUpdated(). +// Only used internally and in memory (not persisted), so can be freely changed. +enum class VisitUpdateReason { + kSetPageLanguage, + kSetPasswordState, + kUpdateVisitDuration, + kUpdateTransition, + kUpdateSyncedVisit, + kAddContextAnnotations, + kSetOnCloseContextAnnotations +}; + // QueryResults ---------------------------------------------------------------- // Encapsulates the results of a history query. It supports an ordered list of
diff --git a/components/history/core/browser/sync/history_sync_bridge.cc b/components/history/core/browser/sync/history_sync_bridge.cc index 87daf3e8..f46fb47b 100644 --- a/components/history/core/browser/sync/history_sync_bridge.cc +++ b/components/history/core/browser/sync/history_sync_bridge.cc
@@ -376,6 +376,10 @@ // Add annotation fields. The last visit in the chain is the one that has // annotations attached (if any). + // NOTE: Currently only the "on_visit" fields of the context annotation are + // supported. When adding any non-"on_visit" field to sync, reconsider how + // VisitUpdateReason::kSetOnCloseContextAnnotations is handled (but mind + // additional traffic to the server!) const VisitContextAnnotations& context_annotations = redirect_visits.back().context_annotations; sync_pb::SyncEnums::BrowserType browser_type = @@ -389,6 +393,7 @@ history->set_root_task_id(context_annotations.on_visit.root_task_id); history->set_parent_task_id(context_annotations.on_visit.parent_task_id); history->set_http_response_code(context_annotations.on_visit.response_code); + // NOTE: Only "on_visit" fields are supported, see above. const VisitContentAnnotations& content_annotations = redirect_visits.back().content_annotations; @@ -792,9 +797,26 @@ UntrackAndClearMetadataForAllEntities(); } -void HistorySyncBridge::OnVisitUpdated(const VisitRow& visit_row) { +void HistorySyncBridge::OnVisitUpdated(const VisitRow& visit_row, + VisitUpdateReason reason) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + switch (reason) { + case VisitUpdateReason::kSetPageLanguage: + case VisitUpdateReason::kSetPasswordState: + case VisitUpdateReason::kUpdateVisitDuration: + case VisitUpdateReason::kUpdateTransition: + case VisitUpdateReason::kAddContextAnnotations: + // Standard case: These are all interesting, process this update. + break; + case VisitUpdateReason::kUpdateSyncedVisit: + CHECK(processing_syncer_changes_); + return; + case VisitUpdateReason::kSetOnCloseContextAnnotations: + // None of the on-close context annotations are synced, so ignore this. + return; + } + MaybeCommit(visit_row); }
diff --git a/components/history/core/browser/sync/history_sync_bridge.h b/components/history/core/browser/sync/history_sync_bridge.h index 9309932..ec581a9 100644 --- a/components/history/core/browser/sync/history_sync_bridge.h +++ b/components/history/core/browser/sync/history_sync_bridge.h
@@ -74,7 +74,8 @@ bool expired, const URLRows& deleted_rows, const std::set<GURL>& favicon_urls) override; - void OnVisitUpdated(const VisitRow& visit_row) override; + void OnVisitUpdated(const VisitRow& visit_row, + VisitUpdateReason reason) override; void OnVisitDeleted(const VisitRow& visit_row) override; void SetSyncTransportState(syncer::SyncService::TransportState state);
diff --git a/components/history/core/browser/sync/history_sync_bridge_unittest.cc b/components/history/core/browser/sync/history_sync_bridge_unittest.cc index 65c6057b..52fb8de 100644 --- a/components/history/core/browser/sync/history_sync_bridge_unittest.cc +++ b/components/history/core/browser/sync/history_sync_bridge_unittest.cc
@@ -920,7 +920,7 @@ const base::TimeDelta visit_duration = base::Seconds(10); visit_row.visit_duration = visit_duration; ASSERT_TRUE(backend()->UpdateVisit(visit_row)); - bridge()->OnVisitUpdated(visit_row); + bridge()->OnVisitUpdated(visit_row, VisitUpdateReason::kUpdateVisitDuration); // The updated data should have been sent to the processor. EXPECT_EQ(processor()->GetEntities().size(), 1u); @@ -931,6 +931,41 @@ visit_duration); } +TEST_F(HistorySyncBridgeTest, IgnoresUninterestingVisitUpdate) { + // Start syncing (with no data yet). + ApplyInitialSyncChanges({}); + + // Visit a URL and notify the bridge. + auto [url_row, visit_row] = AddVisitToBackendAndAdvanceClock( + GURL("https://www.url.com"), ui::PAGE_TRANSITION_TYPED); + bridge()->OnURLVisited( + /*history_backend=*/nullptr, url_row, visit_row); + + const std::string storage_key = + HistorySyncMetadataDatabase::StorageKeyFromVisitTime( + visit_row.visit_time); + + // The visit should've been sent to the processor. Mark it as "synced", + // simulating that it was sent to the server. + ASSERT_TRUE(processor()->IsEntityUnsynced(storage_key)); + processor()->MarkEntitySynced(storage_key); + ASSERT_FALSE(processor()->IsEntityUnsynced(storage_key)); + + // Notify the bridge about an uninteresting visit update (uninteresting since + // none of the on-close context annotation fields are synced). + bridge()->OnVisitUpdated(visit_row, + VisitUpdateReason::kSetOnCloseContextAnnotations); + + // This should *not* have been sent to the processor, so the entity should not + // be unsynced now. + EXPECT_FALSE(processor()->IsEntityUnsynced(storage_key)); + + // Sanity check: Some other visit update *should* be sent to the processor. + bridge()->OnVisitUpdated(visit_row, + VisitUpdateReason::kAddContextAnnotations); + EXPECT_TRUE(processor()->IsEntityUnsynced(storage_key)); +} + TEST_F(HistorySyncBridgeTest, DoesNotUploadUpdatedForeignVisit) { sync_pb::HistorySpecifics remote_entity = CreateSpecifics(base::Time::Now() - base::Minutes(1), "remote_cache_guid", @@ -961,7 +996,7 @@ // might do it (probably mistakenly). visit_row.visit_duration = base::Seconds(10); ASSERT_TRUE(backend()->UpdateVisit(visit_row)); - bridge()->OnVisitUpdated(visit_row); + bridge()->OnVisitUpdated(visit_row, VisitUpdateReason::kUpdateVisitDuration); // The updated visit should *not* have been sent to the processor - the entity // in the processor should *not* be unsynced, and its visit duration should @@ -1141,7 +1176,7 @@ ASSERT_TRUE(backend()->UpdateVisit(visit_row2)); // The bridge gets notified about the updated visit, but this should have no // effect since it's not a chain end anymore. - bridge()->OnVisitUpdated(visit_row2); + bridge()->OnVisitUpdated(visit_row2, VisitUpdateReason::kUpdateTransition); // Two more visits get appended to the chain. URLRow url_row3(GURL("https://url3.com")); @@ -1245,7 +1280,7 @@ ASSERT_TRUE(backend()->UpdateVisit(visit_row1)); // The bridge gets notified about the updated visit, but this should have no // effect since it's not a chain end anymore. - bridge()->OnVisitUpdated(visit_row1); + bridge()->OnVisitUpdated(visit_row1, VisitUpdateReason::kUpdateTransition); // A visit gets appended to the chain. AdvanceClock(); @@ -1287,7 +1322,7 @@ visit_row2.transition = ui::PageTransitionFromInt( visit_row2.transition & ~ui::PAGE_TRANSITION_CHAIN_END); ASSERT_TRUE(backend()->UpdateVisit(visit_row2)); - bridge()->OnVisitUpdated(visit_row2); + bridge()->OnVisitUpdated(visit_row2, VisitUpdateReason::kUpdateTransition); // A visit gets appended to the chain. AdvanceClock();
diff --git a/components/history/core/browser/sync/typed_url_sync_bridge.cc b/components/history/core/browser/sync/typed_url_sync_bridge.cc index b78d8cc..67bbc6a3 100644 --- a/components/history/core/browser/sync/typed_url_sync_bridge.cc +++ b/components/history/core/browser/sync/typed_url_sync_bridge.cc
@@ -478,7 +478,8 @@ } } -void TypedURLSyncBridge::OnVisitUpdated(const VisitRow& visit) {} +void TypedURLSyncBridge::OnVisitUpdated(const VisitRow& visit, + VisitUpdateReason reason) {} void TypedURLSyncBridge::OnVisitDeleted(const VisitRow& visit) {}
diff --git a/components/history/core/browser/sync/typed_url_sync_bridge.h b/components/history/core/browser/sync/typed_url_sync_bridge.h index a93bb23..8c270e5 100644 --- a/components/history/core/browser/sync/typed_url_sync_bridge.h +++ b/components/history/core/browser/sync/typed_url_sync_bridge.h
@@ -66,7 +66,7 @@ bool expired, const std::vector<URLRow>& deleted_rows, const std::set<GURL>& favicon_urls) override; - void OnVisitUpdated(const VisitRow& visit) override; + void OnVisitUpdated(const VisitRow& visit, VisitUpdateReason reason) override; void OnVisitDeleted(const VisitRow& visit) override; // Must be called after creation and before any operations.
diff --git a/components/password_manager/core/browser/built_in_backend_to_android_backend_migrator.cc b/components/password_manager/core/browser/built_in_backend_to_android_backend_migrator.cc index d7a17b0..0c8ca41 100644 --- a/components/password_manager/core/browser/built_in_backend_to_android_backend_migrator.cc +++ b/components/password_manager/core/browser/built_in_backend_to_android_backend_migrator.cc
@@ -29,13 +29,19 @@ // clients from spamming GMS Core API. constexpr base::TimeDelta kMigrationThreshold = base::Days(1); +// The required migration version. If the version saved in +// `prefs::kCurrentMigrationVersionToGoogleMobileServices` is lower than +// 'kRequiredMigrationVersion', passwords will be re-uploaded. Currently set to +// the initial migration version. +constexpr int kRequiredMigrationVersion = 1; + // Returns true if the initial migration to the android backend has happened. // The pref is updated after any type of migration, but the initial migration // happens first. bool HasMigratedToTheAndroidBackend(PrefService* prefs) { - return features::kMigrationVersion.Get() <= - prefs->GetInteger( - prefs::kCurrentMigrationVersionToGoogleMobileServices); + return prefs->GetInteger( + prefs::kCurrentMigrationVersionToGoogleMobileServices) >= + kRequiredMigrationVersion; } bool IsBlacklistedFormWithValues(const PasswordForm& form) { @@ -183,7 +189,7 @@ // pref. } prefs_->SetInteger(prefs::kCurrentMigrationVersionToGoogleMobileServices, - features::kMigrationVersion.Get()); + kRequiredMigrationVersion); } BuiltInBackendToAndroidBackendMigrator::MigrationType @@ -199,13 +205,17 @@ return MigrationType::kInitialForSyncUsers; } + // TODO(crbug.com/1445497): Re-evaluate migration code for local passwords. + bool upm_for_local_active = base::FeatureList::IsEnabled( + password_manager::features::kUnifiedPasswordManagerLocalPasswordsAndroid); + // If the user enables or disables password sync, the new active backend needs // non-syncable data from the previously active backend, as logins are // already transmitted through sync. // Once the local storage is supported, android backend becomes the only // active backend and there is no need to do this migration. if (prefs_->GetBoolean(prefs::kRequiresMigrationAfterSyncStatusChange) && - !features::ManagesLocalPasswordsInUnifiedPasswordManager()) { + !upm_for_local_active) { return IsPasswordSyncEnabled(sync_service_) ? MigrationType::kNonSyncableToAndroidBackend : MigrationType::kNonSyncableToBuiltInBackend; @@ -213,8 +223,9 @@ // Once the local storage is supported, the migration to ensure the // consistency of the two backends is needed. - if (features::ManagesLocalPasswordsInUnifiedPasswordManager()) + if (upm_for_local_active) { return MigrationType::kForLocalUsers; + } // No other migration should be executed. return MigrationType::kNone;
diff --git a/components/password_manager/core/browser/built_in_backend_to_android_backend_migrator_unittest.cc b/components/password_manager/core/browser/built_in_backend_to_android_backend_migrator_unittest.cc index 5821d4ef3..6bef4d8 100644 --- a/components/password_manager/core/browser/built_in_backend_to_android_backend_migrator_unittest.cc +++ b/components/password_manager/core/browser/built_in_backend_to_android_backend_migrator_unittest.cc
@@ -131,9 +131,6 @@ TEST_F(BuiltInBackendToAndroidBackendMigratorTest, CurrentMigrationVersionIsUpdatedWhenMigrationIsNeeded_SyncOn) { - feature_list().InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "0"}}); Init(); InitSyncService(/*is_password_sync_enabled=*/true); @@ -150,9 +147,6 @@ TEST_F(BuiltInBackendToAndroidBackendMigratorTest, PrefsUnchangedWhenMigrationIsNeeded_SyncOff) { - feature_list().InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "0"}}); Init(); InitSyncService(/*is_password_sync_enabled=*/false); @@ -169,9 +163,8 @@ TEST_F(BuiltInBackendToAndroidBackendMigratorTest, AllPrefsAreUpdatedWhenMigrationIsNeeded_SyncOff) { - feature_list().InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "3"}}); + feature_list().InitAndEnableFeature( + features::kUnifiedPasswordManagerLocalPasswordsAndroid); Init(); InitSyncService(/*is_password_sync_enabled=*/false); @@ -189,9 +182,6 @@ TEST_F(BuiltInBackendToAndroidBackendMigratorTest, PrefsUnchangedWhenAttemptedMigrationEarlierToday) { - feature_list().InitAndEnableFeatureWithParameters( - features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "0"}}); Init(); prefs()->SetDouble(password_manager::prefs::kTimeOfLastMigrationAttempt, @@ -210,11 +200,6 @@ TEST_F(BuiltInBackendToAndroidBackendMigratorTest, LastAttemptUnchangedWhenRollingMigrationDisabled) { - // Setup the pref to indicate that the initial migration has happened already. - feature_list().InitWithFeaturesAndParameters( - /*enabled_features=*/{{features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "0"}}}}, - /*disabled_features=*/{}); Init(/*current_migration_version=*/1); migrator()->StartMigrationIfNecessary( @@ -230,10 +215,8 @@ TEST_F(BuiltInBackendToAndroidBackendMigratorTest, LastAttemptUpdatedInPrefsWhenRollingMigrationEnabled) { // Setup the pref to indicate that the initial migration has happened already. - feature_list().InitWithFeaturesAndParameters( - /*enabled_features=*/{{features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "3"}}}}, - /*disabled_features=*/{}); + feature_list().InitAndEnableFeature( + features::kUnifiedPasswordManagerLocalPasswordsAndroid); Init(/*current_migration_version=*/1); migrator()->StartMigrationIfNecessary( @@ -252,10 +235,6 @@ base::HistogramTester histogram_tester; const char kMigrationFinishedMetric[] = "PasswordManager.UnifiedPasswordManager.WasMigrationDone"; - - feature_list().InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "0"}}); Init(); histogram_tester.ExpectTotalCount(kMigrationFinishedMetric, 1); @@ -268,36 +247,13 @@ const char kMigrationFinishedMetric[] = "PasswordManager.UnifiedPasswordManager.WasMigrationDone"; - feature_list().InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "0"}}); Init(/*current_migration_version=*/1); histogram_tester.ExpectUniqueSample(kMigrationFinishedMetric, true, 1); } TEST_F(BuiltInBackendToAndroidBackendMigratorTest, - InitialMigrationNeedsRestartMetrics) { - base::HistogramTester histogram_tester; - const char kMigrationFinishedMetric[] = - "PasswordManager.UnifiedPasswordManager.WasMigrationDone"; - - feature_list().InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "2"}, {"stage", "0"}}); - - Init(/*current_migration_version=*/1); - - histogram_tester.ExpectTotalCount(kMigrationFinishedMetric, 1); - histogram_tester.ExpectBucketCount(kMigrationFinishedMetric, false, 1); -} - -TEST_F(BuiltInBackendToAndroidBackendMigratorTest, MigrationForSyncingUserShouldMoveLocalOnlyDataToAndroidBackend) { - feature_list().InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "0"}}); - Init(); InitSyncService(/*is_password_sync_enabled=*/true); @@ -326,9 +282,6 @@ TEST_F(BuiltInBackendToAndroidBackendMigratorTest, MigrationUserAfterSyncDisablingShouldMoveLocalOnlyDataToBuiltInBackend) { - feature_list().InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "0"}}); Init(); // Simulate sync being recently disabled. @@ -362,10 +315,6 @@ // values from the built in backlend before writing to the Android backend. TEST_F(BuiltInBackendToAndroidBackendMigratorTest, MigrationClearsBlocklistedCredentials) { - feature_list().InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "0"}}); - Init(); InitSyncService(/*is_password_sync_enabled=*/true); @@ -397,10 +346,6 @@ // non-blocklisted entries. TEST_F(BuiltInBackendToAndroidBackendMigratorTest, MigrationDoesNotClearNonBlocklistedCredentials) { - feature_list().InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "0"}}); - Init(); InitSyncService(/*is_password_sync_enabled=*/true); @@ -435,10 +380,6 @@ TEST_F(BuiltInBackendToAndroidBackendMigratorTest, ReenrollmentAttemptShouldMoveLocalOnlyDataToAndroidBackend) { - feature_list().InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "0"}}); - Init(); InitSyncService(/*is_password_sync_enabled=*/true); @@ -546,10 +487,6 @@ InitSyncService(/*is_password_sync_enabled=*/true); - feature_list().InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "0"}}); - const MigrationParam& p = GetParam(); for (const auto& login : p.GetBuiltInLogins()) { @@ -588,9 +525,8 @@ InitSyncService(/*is_password_sync_enabled=*/false); - feature_list().InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "3"}}); + feature_list().InitAndEnableFeature( + features::kUnifiedPasswordManagerLocalPasswordsAndroid); const MigrationParam& p = GetParam(); @@ -619,10 +555,8 @@ RollingMigration) { // Setup the pref to indicate that the initial migration has happened already. // This implies that rolling migration will take place! - feature_list().InitWithFeaturesAndParameters( - /*enabled_features=*/{{features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "3"}}}}, - /*disabled_features=*/{}); + feature_list().InitAndEnableFeature( + features::kUnifiedPasswordManagerLocalPasswordsAndroid); BuiltInBackendToAndroidBackendMigratorTest::Init( /*current_migration_version=*/1); @@ -723,10 +657,10 @@ prefs()->registry()->RegisterIntegerPref( prefs::kTimesAttemptedToReenrollToGoogleMobileServices, 0); - // Enable UPM on the stage 'kEnableForSyncingUsers'. - feature_list().InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "2"}}); + // // Enable UPM on the stage 'kEnableForSyncingUsers'. + // feature_list().InitAndEnableFeatureWithParameters( + // /*feature=*/features::kUnifiedPasswordManagerAndroid, {{"stage", + // "2"}}); if (GetParam().migration_ran_before) { // Setup the pref to indicate that the initial migration has happened @@ -873,8 +807,7 @@ prefs()->registry()->RegisterBooleanPref( prefs::kRequiresMigrationAfterSyncStatusChange, false); feature_list().InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "0"}}); + /*feature=*/features::kUnifiedPasswordManagerAndroid, {{"stage", "0"}}); CreateMigrator(&built_in_backend_, &android_backend_, prefs()); } @@ -921,9 +854,8 @@ TEST_F(BuiltInBackendToAndroidBackendMigratorWithMockAndroidBackendTest, DoesNotCompleteMigrationWhenWritingToAndroidBackendFails_SyncOff) { base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "3"}}); + scoped_feature_list.InitAndEnableFeature( + features::kUnifiedPasswordManagerLocalPasswordsAndroid); // Sync state doesn't affect this test, run it arbitrarily for non-sync'ing // users. @@ -965,10 +897,6 @@ TEST_F(BuiltInBackendToAndroidBackendMigratorWithMockAndroidBackendTest, SecondMigrationCannotStartWhileTheFirstOneHasNotCompleted) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeatureWithParameters( - /*feature=*/features::kUnifiedPasswordManagerAndroid, - {{"migration_version", "1"}, {"stage", "0"}}); InitSyncService(/*is_password_sync_enabled=*/true); // Add a form to the built-in backend to have something to migrate.
diff --git a/components/password_manager/core/browser/password_autofill_manager.cc b/components/password_manager/core/browser/password_autofill_manager.cc index 559b4223..d29b92b 100644 --- a/components/password_manager/core/browser/password_autofill_manager.cc +++ b/components/password_manager/core/browser/password_autofill_manager.cc
@@ -540,6 +540,7 @@ bool PasswordAutofillManager::GetDeletionConfirmationText( const std::u16string& value, autofill::Suggestion::FrontendId frontend_id, + autofill::Suggestion::BackendId backend_id, std::u16string* title, std::u16string* body) { return false; @@ -547,7 +548,8 @@ bool PasswordAutofillManager::RemoveSuggestion( const std::u16string& value, - autofill::Suggestion::FrontendId frontend_id) { + autofill::Suggestion::FrontendId frontend_id, + autofill::Suggestion::BackendId backend_id) { // Password suggestions cannot be deleted this way. // See http://crbug.com/329038#c15 return false;
diff --git a/components/password_manager/core/browser/password_autofill_manager.h b/components/password_manager/core/browser/password_autofill_manager.h index 21d0608..b51c358 100644 --- a/components/password_manager/core/browser/password_autofill_manager.h +++ b/components/password_manager/core/browser/password_autofill_manager.h
@@ -62,10 +62,12 @@ int position) override; bool GetDeletionConfirmationText(const std::u16string& value, autofill::Suggestion::FrontendId frontend_id, + autofill::Suggestion::BackendId backend_id, std::u16string* title, std::u16string* body) override; bool RemoveSuggestion(const std::u16string& value, - autofill::Suggestion::FrontendId frontend_id) override; + autofill::Suggestion::FrontendId frontend_id, + autofill::Suggestion::BackendId backend_id) override; void ClearPreviewedForm() override; autofill::PopupType GetPopupType() const override; absl::variant<autofill::AutofillDriver*, PasswordManagerDriver*> GetDriver()
diff --git a/components/password_manager/core/browser/sync_credentials_filter.cc b/components/password_manager/core/browser/sync_credentials_filter.cc index 2b54c984..b6f1492e 100644 --- a/components/password_manager/core/browser/sync_credentials_filter.cc +++ b/components/password_manager/core/browser/sync_credentials_filter.cc
@@ -39,30 +39,43 @@ const signin::IdentityManager* identity_manager = client_->GetIdentityManager(); - if (base::FeatureList::IsEnabled(features::kEnablePasswordsAccountStorage)) { - // If kEnablePasswordsAccountStorage is enabled, then don't allow saving the - // password if it corresponds to the primary account. Note that if the user - // is just signing in to the first Gaia account, then IdentityManager might - // not know about the account yet. - if (sync_util::IsGaiaCredentialPage(form.signon_realm)) { - CoreAccountInfo primary_account = identity_manager->GetPrimaryAccountInfo( - signin::ConsentLevel::kSignin); - if (primary_account.IsEmpty() || - gaia::AreEmailsSame(base::UTF16ToUTF8(form.username_value), - primary_account.email)) { - return false; - } - } - } else { + if (!base::FeatureList::IsEnabled(features::kEnablePasswordsAccountStorage)) { + // Legacy code path, subject to clean-up. // If kEnablePasswordsAccountStorage is NOT enabled, then don't allow saving // the password for the sync account specifically. - if (sync_util::IsSyncAccountCredential(form.url, form.username_value, - sync_service, identity_manager)) { - return false; - } + return !sync_util::IsSyncAccountCredential(form.url, form.username_value, + sync_service, identity_manager); } - return true; + if (!sync_util::IsGaiaCredentialPage(form.signon_realm)) { + return true; + } + + // The requirement to fulfill is "don't offer to save a Gaia password inside + // its own account". + // Let's assume that if the browser is signed-in, new passwords are saved to + // the primary signed-in account. Per sync_util::GetAccountForSaving(), that's + // not always true, but let's not overcomplicate. + CoreAccountInfo primary_account = + identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin); + if (!primary_account.IsEmpty()) { + // This returns false when `primary_account` just signed-in on the web and + // already made it to the IdentityManager. + return !gaia::AreEmailsSame(base::UTF16ToUTF8(form.username_value), + primary_account.email); + } + + // The browser is signed-out and the web just signed-in. On desktop, this + // immediately leads to browser sign-in, so don't offer saving. + // TODO(crbug.com/1446361): The above is false if the user disabled browser + // sign-in. Return true then. Currently these users can't save Gaia passwords. + + // On mobile, sign-in via the web page doesn't lead to browser sign-in, so + // offer saving. + // (Navigating to the Gaia web page opens Chrome UI which must be accepted to + // perform browser+web sign-in. The code path here is only hit if that UI was + // suppressed/ dismissed and the user interacted directly with the page.) + return BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS); } bool SyncCredentialsFilter::ShouldSaveGaiaPasswordHash(
diff --git a/components/password_manager/core/browser/sync_credentials_filter_unittest.cc b/components/password_manager/core/browser/sync_credentials_filter_unittest.cc index fbc1513..90b307e1 100644 --- a/components/password_manager/core/browser/sync_credentials_filter_unittest.cc +++ b/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
@@ -230,14 +230,15 @@ ->GetPrimaryAccountInfo(signin::ConsentLevel::kSync) .IsEmpty()); SetSyncingPasswords(false); - // If kEnablePasswordsAccountStorage is enabled, then Chrome shouldn't offer - // to save the password for the primary account. If there is no primary - // account yet, then the just-signed-in account will *become* the primary - // account immediately, so it shouldn't be saved either. + // See comments inside ShouldSave() for the justification. +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) + EXPECT_TRUE(filter_->ShouldSave(form)); +#else if (base::FeatureList::IsEnabled(features::kEnablePasswordsAccountStorage)) EXPECT_FALSE(filter_->ShouldSave(form)); else EXPECT_TRUE(filter_->ShouldSave(form)); +#endif } TEST_P(CredentialsFilterTest, ShouldSave_NotSyncCredential) {
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc index 65759d9..fc030b18 100644 --- a/components/password_manager/core/common/password_manager_features.cc +++ b/components/password_manager/core/common/password_manager_features.cc
@@ -308,10 +308,6 @@ base::FEATURE_DISABLED_BY_DEFAULT); #if BUILDFLAG(IS_ANDROID) -// Current migration version to Google Mobile Services. If version saved in pref -// is lower than 'kMigrationVersion' passwords will be re-uploaded. -extern const base::FeatureParam<int> kMigrationVersion = { - &kUnifiedPasswordManagerAndroid, "migration_version", 1}; // The string version to use for the save/update password prompts when the user // is syncing passwords. Version 1 is outdated, so the only supported versions @@ -380,23 +376,6 @@ return false; } -bool ManagesLocalPasswordsInUnifiedPasswordManager() { - if (!base::FeatureList::IsEnabled(kUnifiedPasswordManagerAndroid)) { - return false; - } - UpmExperimentVariation variation = kUpmExperimentVariationParam.Get(); - switch (variation) { - case UpmExperimentVariation::kEnableForSyncingUsers: - case UpmExperimentVariation::kShadowSyncingUsers: - case UpmExperimentVariation::kEnableOnlyBackendForSyncingUsers: - return false; - case UpmExperimentVariation::kEnableForAllUsers: - return true; - } - NOTREACHED() - << "Define explicitly whether local password management is supported!"; - return false; -} #endif // IS_ANDROID #if BUILDFLAG(IS_IOS)
diff --git a/components/password_manager/core/common/password_manager_features.h b/components/password_manager/core/common/password_manager_features.h index 79b4739..ef7c190 100644 --- a/components/password_manager/core/common/password_manager_features.h +++ b/components/password_manager/core/common/password_manager_features.h
@@ -136,7 +136,6 @@ &kPasswordStrengthIndicator, "strength_indicator_minimized", false}; #if BUILDFLAG(IS_ANDROID) -extern const base::FeatureParam<int> kMigrationVersion; // Current list of the GMS Core API error codes that should be ignored and not // result in user eviction. @@ -200,10 +199,6 @@ // that requires migrating existing credentials. Independent of // whether only non-syncable data needs to be migrated or full credentials. bool RequiresMigrationForUnifiedPasswordManager(); - -// Returns true if the unified password manager feature is active and in a stage -// that uses the unified storage for passwords that remain local on the device. -bool ManagesLocalPasswordsInUnifiedPasswordManager(); #endif // IS_ANDROID #if BUILDFLAG(IS_IOS)
diff --git a/components/policy/core/common/cloud/cloud_policy_constants.h b/components/policy/core/common/cloud/cloud_policy_constants.h index 4bd421db..c16e1dfa 100644 --- a/components/policy/core/common/cloud/cloud_policy_constants.h +++ b/components/policy/core/common/cloud/cloud_policy_constants.h
@@ -153,6 +153,8 @@ DM_STATUS_SERVICE_ILLEGAL_ACCOUNT_FOR_PACKAGED_EDU_LICENSE = 908, // Service error: Packaged license device can't enroll KIOSK. DM_STATUS_SERVICE_INVALID_PACKAGED_DEVICE_FOR_KIOSK = 909, + // TODO(b/265923216): Convert to enum class and rename this to kMaxValue. + DM_STATUS_SERVICE_MAX = DM_STATUS_SERVICE_INVALID_PACKAGED_DEVICE_FOR_KIOSK }; // List of modes that the device can be locked into.
diff --git a/components/policy/core/common/cloud/enterprise_metrics.cc b/components/policy/core/common/cloud/enterprise_metrics.cc index 95799e3..17ff6e1 100644 --- a/components/policy/core/common/cloud/enterprise_metrics.cc +++ b/components/policy/core/common/cloud/enterprise_metrics.cc
@@ -208,4 +208,58 @@ const char kUMASuffixInitialEnrollment[] = ".InitialEnrollment"; const char kUMASuffixFRE[] = ".ForcedReenrollment"; +const char kUMAStateDeterminationDeviceIdentifierStatus[] = + "Enterprise.StateDetermination.DeviceIdentifierStatus"; +const char kUMAStateDeterminationEnabled[] = + "Enterprise.StateDetermination.Enabled"; +const char kUMAStateDeterminationEmbargoDatePassed[] = + "Enterprise.StateDetermination.EmbargoDatePassed"; +const char kUMAStateDeterminationKillSwitchFetchNetworkErrorCode[] = + "Enterprise.StateDetermination.KillSwitchFetch.NetworkErrorCode"; +const char kUMAStateDeterminationKillSwitchFetchNumTries[] = + "Enterprise.StateDetermination.KillSwitchFetch.NumTries"; +const char kUMAStateDeterminationOnFlex[] = + "Enterprise.StateDetermination.OnFlex"; +const char kUMAStateDeterminationOwnershipStatus[] = + "Enterprise.StateDetermination.OwnershipStatus"; +const char kUMAStateDeterminationPsmReportedAvailableState[] = + "Enterprise.StateDetermination.PsmReportedAvailableState"; +const char kUMAStateDeterminationPsmRlweOprfRequestDmStatusCode[] = + "Enterprise.StateDetermination.PsmRlweOprfRequest.DmStatusCode"; +const char kUMAStateDeterminationPsmRlweOprfRequestNetworkErrorCode[] = + "Enterprise.StateDetermination.PsmRlweOprfRequest.NetworkErrorCode"; +const char kUMAStateDeterminationPsmRlweQueryRequestDmStatusCode[] = + "Enterprise.StateDetermination.PsmRlweQueryRequest.DmStatusCode"; +const char kUMAStateDeterminationPsmRlweQueryRequestNetworkErrorCode[] = + "Enterprise.StateDetermination.PsmRlweQueryRequest.NetworkErrorCode"; +const char kUMAStateDeterminationStateKeysRetrieved[] = + "Enterprise.StateDetermination.StateKeysRetrieved"; +const char kUMAStateDeterminationStateRequestDmStatusCode[] = + "Enterprise.StateDetermination.StateRequest.DmStatusCode"; +const char kUMAStateDeterminationStateRequestNetworkErrorCode[] = + "Enterprise.StateDetermination.StateRequest.NetworkErrorCode"; +const char kUMAStateDeterminationStateReturned[] = + "Enterprise.StateDetermination.StateReturned"; +const char kUMAStateDeterminationStepDuration[] = + "Enterprise.StateDetermination.StepDuration"; +const char kUMAStateDeterminationSystemClockSynchronized[] = + "Enterprise.StateDetermination.SystemClockSynchronized"; +const char kUMAStateDeterminationTotalDurationByState[] = + "Enterprise.StateDetermination.TotalDurationByState"; +const char kUMAStateDeterminationTotalDuration[] = + "Enterprise.StateDetermination.TotalDuration"; + +const char kUMASuffixConnectionError[] = ".ConnectionError"; +const char kUMASuffixDisabled[] = ".Disabled"; +const char kUMASuffixEnrollment[] = ".Enrollment"; +const char kUMASuffixNoEnrollment[] = ".NoEnrollment"; +const char kUMASuffixServerError[] = ".ServerError"; + +const char kUMASuffixOPRFRequest[] = ".OPRFRequest"; +const char kUMASuffixOwnershipCheck[] = ".OwnershipCheck"; +const char kUMASuffixQueryRequest[] = ".QueryRequest"; +const char kUMASuffixStateKeyRetrieval[] = ".StateKeyRetrieval"; +const char kUMASuffixStateRequest[] = ".StateRequest"; +const char kUMASuffixSystemClockSync[] = ".SystemClockSync"; + } // namespace policy
diff --git a/components/policy/core/common/cloud/enterprise_metrics.h b/components/policy/core/common/cloud/enterprise_metrics.h index bfb9a922..be67a039 100644 --- a/components/policy/core/common/cloud/enterprise_metrics.h +++ b/components/policy/core/common/cloud/enterprise_metrics.h
@@ -279,6 +279,51 @@ // Suffix for Forced Re-Enrollment. POLICY_EXPORT extern const char kUMASuffixFRE[]; +// Histograpms for the unified state determination. +POLICY_EXPORT extern const char kUMAStateDeterminationDeviceIdentifierStatus[]; +POLICY_EXPORT extern const char kUMAStateDeterminationEmbargoDatePassed[]; +POLICY_EXPORT extern const char kUMAStateDeterminationEnabled[]; +POLICY_EXPORT extern const char + kUMAStateDeterminationKillSwitchFetchNetworkErrorCode[]; +POLICY_EXPORT extern const char kUMAStateDeterminationKillSwitchFetchNumTries[]; +POLICY_EXPORT extern const char kUMAStateDeterminationOnFlex[]; +POLICY_EXPORT extern const char kUMAStateDeterminationOwnershipStatus[]; +POLICY_EXPORT extern const char + kUMAStateDeterminationPsmReportedAvailableState[]; +POLICY_EXPORT extern const char + kUMAStateDeterminationPsmRlweOprfRequestDmStatusCode[]; +POLICY_EXPORT extern const char + kUMAStateDeterminationPsmRlweOprfRequestNetworkErrorCode[]; +POLICY_EXPORT extern const char + kUMAStateDeterminationPsmRlweQueryRequestDmStatusCode[]; +POLICY_EXPORT extern const char + kUMAStateDeterminationPsmRlweQueryRequestNetworkErrorCode[]; +POLICY_EXPORT extern const char kUMAStateDeterminationStateKeysRetrieved[]; +POLICY_EXPORT extern const char + kUMAStateDeterminationStateRequestDmStatusCode[]; +POLICY_EXPORT extern const char + kUMAStateDeterminationStateRequestNetworkErrorCode[]; +POLICY_EXPORT extern const char kUMAStateDeterminationStateReturned[]; +POLICY_EXPORT extern const char kUMAStateDeterminationStepDuration[]; +POLICY_EXPORT extern const char kUMAStateDeterminationSystemClockSynchronized[]; +POLICY_EXPORT extern const char kUMAStateDeterminationTotalDurationByState[]; +POLICY_EXPORT extern const char kUMAStateDeterminationTotalDuration[]; + +// Suffixes added to kUMAStateDeterminationTotalDurationByState. +POLICY_EXPORT extern const char kUMASuffixConnectionError[]; +POLICY_EXPORT extern const char kUMASuffixDisabled[]; +POLICY_EXPORT extern const char kUMASuffixEnrollment[]; +POLICY_EXPORT extern const char kUMASuffixNoEnrollment[]; +POLICY_EXPORT extern const char kUMASuffixServerError[]; + +// Suffixes added to kUMAStateDeterminationStepDuration. +POLICY_EXPORT extern const char kUMASuffixOPRFRequest[]; +POLICY_EXPORT extern const char kUMASuffixOwnershipCheck[]; +POLICY_EXPORT extern const char kUMASuffixQueryRequest[]; +POLICY_EXPORT extern const char kUMASuffixStateKeyRetrieval[]; +POLICY_EXPORT extern const char kUMASuffixStateRequest[]; +POLICY_EXPORT extern const char kUMASuffixSystemClockSync[]; + } // namespace policy #endif // COMPONENTS_POLICY_CORE_COMMON_CLOUD_ENTERPRISE_METRICS_H_
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/DataLeakPreventionRulesList.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/DataLeakPreventionRulesList.yaml index 14935185..5a6ff7a 100644 --- a/components/policy/resources/templates/policy_definitions/Miscellaneous/DataLeakPreventionRulesList.yaml +++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/DataLeakPreventionRulesList.yaml
@@ -99,6 +99,7 @@ - PLUGIN_VM - DRIVE - USB + - ONEDRIVE type: string type: array urls:
diff --git a/components/supervised_user/core/browser/kids_external_fetcher.cc b/components/supervised_user/core/browser/kids_external_fetcher.cc index fb74b34..ea287fe 100644 --- a/components/supervised_user/core/browser/kids_external_fetcher.cc +++ b/components/supervised_user/core/browser/kids_external_fetcher.cc
@@ -66,12 +66,16 @@ net::HTTP_OK; } -int CombineNetAndHttpErrors(const network::SimpleURLLoader& loader) { - if (loader.NetError() != net::OK || !loader.ResponseInfo() || - !loader.ResponseInfo()->headers) { - return loader.NetError(); +// Return HTTP status if available, or net::Error otherwise. HTTP status takes +// precedence to avoid masking it by net::ERR_HTTP_RESPONSE_CODE_FAILURE. +// Returned value is positive for HTTP status and negative for net::Error, +// consistent with +// tools/metrics/histograms/enums.xml://enum[@name='CombinedHttpResponseAndNetErrorCode'] +int HttpStatusOrNetError(const network::SimpleURLLoader& loader) { + if (loader.ResponseInfo() && loader.ResponseInfo()->headers) { + return loader.ResponseInfo()->headers->response_code(); } - return loader.ResponseInfo()->headers->response_code(); + return loader.NetError(); } std::string CreateAuthorizationHeader( @@ -148,9 +152,10 @@ RecordStabilityMetrics(latency, status); // Record additional metrics for various failures. - if (status.state() == KidsExternalFetcherStatus::State::NET_OR_HTTP_ERROR) { - UmaHistogramSparse(GetMetricKey("NetOrHttpStatus"), - status.net_or_http_error_code().value()); + if (status.state() == + KidsExternalFetcherStatus::State::HTTP_STATUS_OR_NET_ERROR) { + UmaHistogramSparse(GetMetricKey("HttpStatusOrNetError"), + status.http_status_or_net_error().value()); } DCHECK( @@ -207,8 +212,8 @@ std::unique_ptr<std::string> response_body) { if (!IsLoadingSuccessful(*simple_url_loader_) || !HasHttpOkResponse(*simple_url_loader_)) { - std::move(callback).Run(KidsExternalFetcherStatus::NetOrHttpError( - CombineNetAndHttpErrors(*simple_url_loader_)), + std::move(callback).Run(KidsExternalFetcherStatus::HttpStatusOrNetError( + HttpStatusOrNetError(*simple_url_loader_)), nullptr); return; } @@ -244,8 +249,9 @@ DCHECK(state != State::GOOGLE_SERVICE_AUTH_ERROR); } KidsExternalFetcherStatus::KidsExternalFetcherStatus( - NetOrHttpErrorType error_code) - : state_(State::NET_OR_HTTP_ERROR), net_or_http_error_code_(error_code) {} + HttpStatusOrNetErrorType http_status_or_net_error) + : state_(State::HTTP_STATUS_OR_NET_ERROR), + http_status_or_net_error_(http_status_or_net_error) {} KidsExternalFetcherStatus::KidsExternalFetcherStatus( class GoogleServiceAuthError google_service_auth_error) : KidsExternalFetcherStatus(GOOGLE_SERVICE_AUTH_ERROR, @@ -263,9 +269,10 @@ class GoogleServiceAuthError error) { return KidsExternalFetcherStatus(error); } -KidsExternalFetcherStatus KidsExternalFetcherStatus::NetOrHttpError( - int net_or_http_error_code) { - return KidsExternalFetcherStatus(NetOrHttpErrorType(net_or_http_error_code)); +KidsExternalFetcherStatus KidsExternalFetcherStatus::HttpStatusOrNetError( + int http_status_or_net_error) { + return KidsExternalFetcherStatus( + HttpStatusOrNetErrorType(http_status_or_net_error)); } KidsExternalFetcherStatus KidsExternalFetcherStatus::InvalidResponse() { return KidsExternalFetcherStatus(State::INVALID_RESPONSE); @@ -278,7 +285,7 @@ return state_ == State::OK; } bool KidsExternalFetcherStatus::IsTransientError() const { - if (state_ == State::NET_OR_HTTP_ERROR) { + if (state_ == State::HTTP_STATUS_OR_NET_ERROR) { return true; } if (state_ == State::GOOGLE_SERVICE_AUTH_ERROR) { @@ -304,11 +311,13 @@ case KidsExternalFetcherStatus::OK: return "KidsExternalFetcherStatus::OK"; case KidsExternalFetcherStatus::GOOGLE_SERVICE_AUTH_ERROR: - return StrCat({"KidsExternalFetcherStatus::GOOGLE_SERVICE_AUTH_ERROR: ", - google_service_auth_error().ToString()}); - case KidsExternalFetcherStatus::NET_OR_HTTP_ERROR: - return StringPrintf("KidsExternalFetcherStatus::NET_OR_HTTP_ERROR: %d", - net_or_http_error_code_.value()); + return base::StrCat( + {"KidsExternalFetcherStatus::GOOGLE_SERVICE_AUTH_ERROR: ", + google_service_auth_error().ToString()}); + case KidsExternalFetcherStatus::HTTP_STATUS_OR_NET_ERROR: + return base::StringPrintf( + "KidsExternalFetcherStatus::HTTP_STATUS_OR_NET_ERROR: %d", + http_status_or_net_error_.value()); case KidsExternalFetcherStatus::INVALID_RESPONSE: return "KidsExternalFetcherStatus::INVALID_RESPONSE"; case KidsExternalFetcherStatus::DATA_ERROR: @@ -317,18 +326,18 @@ } // The returned value must match one of the labels in -// chromium/src/tools/metrics/histograms/enums.xml/histogram-configuration/enums/enum[@name='KidsExternalFetcherStatus'], +// chromium/src/tools/metrics/histograms/enums.xml://enum[@name='KidsExternalFetcherStatus'], // and should be reflected in tokens in histogram defined for this fetcher. // See example at -// chromium/src/tools/metrics/histograms/metadata/signin/histograms.xml/histogram-configuration/histograms/histogram[@name='Signin.ListFamilyMembersRequest.{Status}.*'] +// tools/metrics/histograms/metadata/signin/histograms.xml://histogram[@name='Signin.ListFamilyMembersRequest.{Status}.*'] std::string KidsExternalFetcherStatus::ToMetricEnumLabel() const { switch (state_) { case KidsExternalFetcherStatus::OK: return "NoError"; case KidsExternalFetcherStatus::GOOGLE_SERVICE_AUTH_ERROR: return "AuthError"; - case KidsExternalFetcherStatus::NET_OR_HTTP_ERROR: - return "HttpError"; + case KidsExternalFetcherStatus::HTTP_STATUS_OR_NET_ERROR: + return "HttpStatusOrNetError"; case KidsExternalFetcherStatus::INVALID_RESPONSE: return "ParseError"; case KidsExternalFetcherStatus::DATA_ERROR: @@ -339,9 +348,9 @@ KidsExternalFetcherStatus::State KidsExternalFetcherStatus::state() const { return state_; } -KidsExternalFetcherStatus::NetOrHttpErrorType -KidsExternalFetcherStatus::net_or_http_error_code() const { - return net_or_http_error_code_; +KidsExternalFetcherStatus::HttpStatusOrNetErrorType +KidsExternalFetcherStatus::http_status_or_net_error() const { + return http_status_or_net_error_; } const GoogleServiceAuthError&
diff --git a/components/supervised_user/core/browser/kids_external_fetcher.h b/components/supervised_user/core/browser/kids_external_fetcher.h index 92a0859..b8f4b18 100644 --- a/components/supervised_user/core/browser/kids_external_fetcher.h +++ b/components/supervised_user/core/browser/kids_external_fetcher.h
@@ -44,17 +44,18 @@ // numeric values should never be reused. class KidsExternalFetcherStatus { public: - using NetOrHttpErrorType = base::StrongAlias<class NetOrHttpErrorTag, int>; + using HttpStatusOrNetErrorType = + base::StrongAlias<class HttpStatusOrNetErrorTag, int>; enum State { OK = 0, GOOGLE_SERVICE_AUTH_ERROR = 1, // Error occurred during the access token // fetching phase. See // GetGoogleServiceAuthError for details. - NET_OR_HTTP_ERROR = 2, // The request was performed, but network or http - // returned errors. This is default chromium - // approach to combine those two error domains. - INVALID_RESPONSE = 3, // The request was performed without error, but http + HTTP_STATUS_OR_NET_ERROR = + 2, // The request was performed, but network or http returned errors. + // This is default chromium approach to combine those two domains. + INVALID_RESPONSE = 3, // The request was performed without error, but http // response could not be processed or was unexpected. DATA_ERROR = 4, // The request was parsed, but did not contain all required // data. Not signalled by this fetcher itself, but might be @@ -77,9 +78,9 @@ GoogleServiceAuthError error); // The copy follows the interface of // https://source.chromium.org/chromium/chromium/src/+/main:components/signin/public/identity_manager/primary_account_access_token_fetcher.h;l=241;drc=8ba1bad80dc22235693a0dd41fe55c0fd2dbdabd - static KidsExternalFetcherStatus NetOrHttpError( - int error_code = 0); // Either net::Error (negative numbers, 0 denotes - // success) or HTTP error (standard error codes). + static KidsExternalFetcherStatus HttpStatusOrNetError( + int value = 0); // Either net::Error (negative numbers, 0 denotes + // success) or HTTP status. static KidsExternalFetcherStatus InvalidResponse(); static KidsExternalFetcherStatus DataError(); @@ -100,13 +101,14 @@ std::string ToMetricEnumLabel() const; State state() const; - NetOrHttpErrorType net_or_http_error_code() const; + HttpStatusOrNetErrorType http_status_or_net_error() const; const class GoogleServiceAuthError& google_service_auth_error() const; private: // Disallows impossible states. explicit KidsExternalFetcherStatus(State state); - explicit KidsExternalFetcherStatus(NetOrHttpErrorType error_code); + explicit KidsExternalFetcherStatus( + HttpStatusOrNetErrorType http_status_or_net_error); explicit KidsExternalFetcherStatus( class GoogleServiceAuthError google_service_auth_error); // Implies State == @@ -116,8 +118,8 @@ class GoogleServiceAuthError google_service_auth_error); State state_; - NetOrHttpErrorType net_or_http_error_code_{ - 0}; // Meaningful iff state_ == NET_OR_HTTP_ERROR + HttpStatusOrNetErrorType http_status_or_net_error_{ + 0}; // Meaningful iff state_ == HTTP_STATUS_OR_NET_ERROR class GoogleServiceAuthError google_service_auth_error_; };
diff --git a/components/supervised_user/core/browser/kids_external_fetcher_unittest.cc b/components/supervised_user/core/browser/kids_external_fetcher_unittest.cc index 515a369a..c48aa17 100644 --- a/components/supervised_user/core/browser/kids_external_fetcher_unittest.cc +++ b/components/supervised_user/core/browser/kids_external_fetcher_unittest.cc
@@ -213,10 +213,10 @@ net::HTTP_BAD_REQUEST); EXPECT_FALSE(receiver.GetResult().has_value()); EXPECT_EQ(receiver.GetResult().error().state(), - KidsExternalFetcherStatus::State::NET_OR_HTTP_ERROR); - EXPECT_EQ(receiver.GetResult().error().net_or_http_error_code(), - KidsExternalFetcherStatus::NetOrHttpErrorType( - net::ERR_HTTP_RESPONSE_CODE_FAILURE)); + KidsExternalFetcherStatus::State::HTTP_STATUS_OR_NET_ERROR); + EXPECT_EQ(receiver.GetResult().error().http_status_or_net_error(), + KidsExternalFetcherStatus::HttpStatusOrNetErrorType( + net::HTTP_BAD_REQUEST)); } } // namespace
diff --git a/components/sync/engine/sync_engine_host.h b/components/sync/engine/sync_engine_host.h index f971f5d..bcd6242 100644 --- a/components/sync/engine/sync_engine_host.h +++ b/components/sync/engine/sync_engine_host.h
@@ -55,6 +55,9 @@ // Called when invalidations are enabled or disabled. virtual void OnInvalidationStatusChanged() = 0; + + // Called when there are new data types with pending invalidations. + virtual void OnNewInvalidatedDataTypes() = 0; }; } // namespace syncer
diff --git a/components/sync/engine/sync_manager_impl.cc b/components/sync/engine/sync_manager_impl.cc index c9365b73d..0d7788c 100644 --- a/components/sync/engine/sync_manager_impl.cc +++ b/components/sync/engine/sync_manager_impl.cc
@@ -372,6 +372,8 @@ bool has_pending_invalidations) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); scheduler_->SetHasPendingInvalidations(type, has_pending_invalidations); + sync_status_tracker_->SetHasPendingInvalidations(type, + has_pending_invalidations); } void SyncManagerImpl::NotifySyncStatusChanged(const SyncStatus& status) {
diff --git a/components/sync/engine/sync_manager_impl_unittest.cc b/components/sync/engine/sync_manager_impl_unittest.cc index 08e48df..0fad75a 100644 --- a/components/sync/engine/sync_manager_impl_unittest.cc +++ b/components/sync/engine/sync_manager_impl_unittest.cc
@@ -48,6 +48,8 @@ #include "url/gurl.h" using testing::_; +using testing::SaveArg; +using testing::Sequence; using testing::StrictMock; namespace syncer { @@ -133,6 +135,7 @@ ModelTypeSet types_to_download, base::OnceClosure ready_task), (override)); + MOCK_METHOD(void, SetHasPendingInvalidations, (ModelType, bool), (override)); }; class ComponentsFactory : public TestEngineComponentsFactory { @@ -206,6 +209,7 @@ SyncManagerImpl* sync_manager() { return &sync_manager_; } MockSyncScheduler* scheduler() { return scheduler_; } + SyncManagerObserverMock* manager_observer() { return &manager_observer_; } private: base::test::SingleThreadTaskEnvironment task_environment_; @@ -238,6 +242,29 @@ SyncManager::SyncFeatureState::ON, ready_task.Get()); } +TEST_F(SyncManagerImplTest, ShouldSetHasPendingInvalidations) { + Sequence s1; + EXPECT_CALL(*scheduler(), + SetHasPendingInvalidations(BOOKMARKS, /*has_invalidation=*/true)) + .InSequence(s1); + EXPECT_CALL(*scheduler(), + SetHasPendingInvalidations(BOOKMARKS, /*has_invalidation=*/false)) + .InSequence(s1); + SyncStatus status; + EXPECT_CALL(*manager_observer(), OnSyncStatusChanged) + .Times(2) + .WillRepeatedly(SaveArg<0>(&status)); + + sync_manager()->SetHasPendingInvalidations( + BOOKMARKS, /*has_pending_invalidations=*/true); + EXPECT_EQ(status.invalidated_data_types.Size(), 1u); + EXPECT_TRUE(status.invalidated_data_types.Has(BOOKMARKS)); + + sync_manager()->SetHasPendingInvalidations( + BOOKMARKS, /*has_pending_invalidations=*/false); + EXPECT_TRUE(status.invalidated_data_types.Empty()); +} + } // namespace } // namespace syncer
diff --git a/components/sync/engine/sync_status.h b/components/sync/engine/sync_status.h index 5f182e2..dad92dce 100644 --- a/components/sync/engine/sync_status.h +++ b/components/sync/engine/sync_status.h
@@ -75,6 +75,9 @@ // The unique identifier for the invalidation client. std::string invalidator_client_id; + // Data types having pending invalidations. + ModelTypeSet invalidated_data_types; + // Time of next retry if sync scheduler is throttled or in backoff. base::Time retry_time;
diff --git a/components/sync/engine/sync_status_tracker.cc b/components/sync/engine/sync_status_tracker.cc index 38075db..a13ef09 100644 --- a/components/sync/engine/sync_status_tracker.cc +++ b/components/sync/engine/sync_status_tracker.cc
@@ -171,6 +171,18 @@ status_changed_callback_.Run(status_); } +void SyncStatusTracker::SetHasPendingInvalidations( + ModelType type, + bool has_pending_invalidations) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (has_pending_invalidations) { + status_.invalidated_data_types.Put(type); + } else { + status_.invalidated_data_types.Remove(type); + } + status_changed_callback_.Run(status_); +} + void SyncStatusTracker::SetLocalBackendFolder(const std::string& folder) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); status_.local_sync_folder = folder;
diff --git a/components/sync/engine/sync_status_tracker.h b/components/sync/engine/sync_status_tracker.h index df6b9651..78e478f4 100644 --- a/components/sync/engine/sync_status_tracker.h +++ b/components/sync/engine/sync_status_tracker.h
@@ -64,6 +64,8 @@ void SetCacheGuid(const std::string& cache_guid); void SetInvalidatorClientId(const std::string& invalidator_client_id); + void SetHasPendingInvalidations(ModelType type, + bool has_pending_invalidations); void SetLocalBackendFolder(const std::string& folder);
diff --git a/components/sync/model/client_tag_based_model_type_processor_unittest.cc b/components/sync/model/client_tag_based_model_type_processor_unittest.cc index 485fe46..8f80c03 100644 --- a/components/sync/model/client_tag_based_model_type_processor_unittest.cc +++ b/components/sync/model/client_tag_based_model_type_processor_unittest.cc
@@ -200,13 +200,10 @@ base::OnceClosure GetDataCallback() { return std::move(data_callback_); } - void SetInitialSyncDone(bool is_done) { + void SetInitialSyncState( + sync_pb::ModelTypeState::InitialSyncState initial_sync_state) { ModelTypeState model_type_state(db().model_type_state()); - model_type_state.set_initial_sync_state( - is_done - ? sync_pb::ModelTypeState_InitialSyncState_INITIAL_SYNC_DONE - : sync_pb:: - ModelTypeState_InitialSyncState_INITIAL_SYNC_STATE_UNSPECIFIED); + model_type_state.set_initial_sync_state(initial_sync_state); model_type_state.set_cache_guid(kCacheGuid); model_type_state.mutable_progress_marker()->set_data_type_id( GetSpecificsFieldNumberFromModelType(type())); @@ -344,9 +341,12 @@ histogram_tester_ = std::make_unique<base::HistogramTester>(); } - void InitializeToMetadataLoaded(bool set_initial_sync_done = true) { - if (set_initial_sync_done) { - bridge()->SetInitialSyncDone(true); + void InitializeToMetadataLoaded( + sync_pb::ModelTypeState::InitialSyncState initial_sync_state = + sync_pb::ModelTypeState::INITIAL_SYNC_DONE) { + if (initial_sync_state != + sync_pb::ModelTypeState::INITIAL_SYNC_STATE_UNSPECIFIED) { + bridge()->SetInitialSyncState(initial_sync_state); } ModelReadyToSync(); } @@ -756,7 +756,7 @@ // Test that subsequent starts don't call MergeFullSyncData. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldApplyIncrementalUpdates) { - // This sets initial_sync_done to true. + // This sets initial_sync_state to "done". InitializeToMetadataLoaded(); // Write an item before sync connects. @@ -2072,7 +2072,8 @@ // storage" for historical reasons) result in reporting setup duration. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldReportEphemeralConfigurationTime) { - InitializeToMetadataLoaded(/*set_initial_sync_done=*/false); + InitializeToMetadataLoaded( + sync_pb::ModelTypeState::INITIAL_SYNC_STATE_UNSPECIFIED); OnSyncStarting(kDefaultAuthenticatedAccountId, kCacheGuid, SyncMode::kTransportOnly); @@ -2097,7 +2098,8 @@ // for historical reasons) do not result in reporting setup duration. TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldReportPersistentConfigurationTime) { - InitializeToMetadataLoaded(/*set_initial_sync_done=*/false); + InitializeToMetadataLoaded( + sync_pb::ModelTypeState::INITIAL_SYNC_STATE_UNSPECIFIED); OnSyncStarting(); base::HistogramTester histogram_tester; @@ -2166,7 +2168,8 @@ // for historical reasons) result in reporting setup duration. TEST_F(FullUpdateClientTagBasedModelTypeProcessorTest, ShouldReportEphemeralConfigurationTimeOnlyForFirstFullUpdate) { - InitializeToMetadataLoaded(/*set_initial_sync_done=*/false); + InitializeToMetadataLoaded( + sync_pb::ModelTypeState::INITIAL_SYNC_STATE_UNSPECIFIED); OnSyncStarting(kDefaultAuthenticatedAccountId, kCacheGuid, SyncMode::kTransportOnly); @@ -2489,7 +2492,7 @@ ResetState(/*keep_db=*/true); // A new processor loads the metadata after changing the cache GUID. - bridge()->SetInitialSyncDone(true); + bridge()->SetInitialSyncState(sync_pb::ModelTypeState::INITIAL_SYNC_DONE); std::unique_ptr<MetadataBatch> metadata_batch = db()->CreateMetadataBatch(); sync_pb::ModelTypeState model_type_state(metadata_batch->GetModelTypeState()); @@ -2523,7 +2526,7 @@ ResetState(/*keep_db=*/true); // A new processor loads the metadata after changing the data type id. - bridge()->SetInitialSyncDone(true); + bridge()->SetInitialSyncState(sync_pb::ModelTypeState::INITIAL_SYNC_DONE); std::unique_ptr<MetadataBatch> metadata_batch = db()->CreateMetadataBatch(); sync_pb::ModelTypeState model_type_state(metadata_batch->GetModelTypeState()); @@ -2974,26 +2977,23 @@ ShouldResetForEntityMetadataWithoutInitialSyncDone) { base::HistogramTester histogram_tester; - const syncer::ClientTagHash kClientTagHash = - ClientTagHash::FromUnhashed(AUTOFILL, "tag"); sync_pb::EntityMetadata entity_metadata1; - entity_metadata1.set_client_tag_hash(kClientTagHash.value()); + entity_metadata1.set_client_tag_hash( + ClientTagHash::FromUnhashed(GetModelType(), "tag1").value()); entity_metadata1.set_creation_time(0); sync_pb::EntityMetadata entity_metadata2; - entity_metadata2.set_client_tag_hash(kClientTagHash.value()); + entity_metadata2.set_client_tag_hash( + ClientTagHash::FromUnhashed(GetModelType(), "tag2").value()); entity_metadata2.set_creation_time(0); - sync_pb::EntityMetadata entity_metadata3; - entity_metadata3.set_client_tag_hash(kClientTagHash.value()); - entity_metadata3.set_creation_time(0); db()->PutMetadata(kKey1, std::move(entity_metadata1)); db()->PutMetadata(kKey2, std::move(entity_metadata2)); - db()->PutMetadata(kKey3, std::move(entity_metadata3)); - InitializeToMetadataLoaded(/*set_initial_sync_done=*/false); + InitializeToMetadataLoaded( + sync_pb::ModelTypeState::INITIAL_SYNC_STATE_UNSPECIFIED); OnSyncStarting(); - // Since initial_sync_done was false, metadata should have been cleared. + // Since initial_sync_state was not set, metadata should have been cleared. EXPECT_EQ(0U, db()->metadata_count()); EXPECT_EQ(0U, ProcessorEntityCount()); EXPECT_FALSE(type_processor()->IsTrackingMetadata()); @@ -3001,20 +3001,50 @@ worker()->UpdateFromServer(); EXPECT_TRUE(type_processor()->IsTrackingMetadata()); - // There were three entities with the same client-tag-hash which indicates - // that two of them were metadata oprhans. histogram_tester.ExpectBucketCount( "Sync.ModelTypeEntityMetadataWithoutInitialSync", /*sample=*/ModelTypeHistogramValue(GetModelType()), /*expected_count=*/1); } +// Regression test for crbug.com/1427000. +TEST_F(ClientTagBasedModelTypeProcessorTest, + ShouldNotResetWhenInitialSyncPartiallyDone) { + base::HistogramTester histogram_tester; + + sync_pb::EntityMetadata entity_metadata1; + entity_metadata1.set_client_tag_hash( + ClientTagHash::FromUnhashed(GetModelType(), "tag1").value()); + entity_metadata1.set_creation_time(0); + sync_pb::EntityMetadata entity_metadata2; + entity_metadata2.set_client_tag_hash( + ClientTagHash::FromUnhashed(GetModelType(), "tag2").value()); + entity_metadata2.set_creation_time(0); + + db()->PutMetadata(kKey1, std::move(entity_metadata1)); + db()->PutMetadata(kKey2, std::move(entity_metadata2)); + + InitializeToMetadataLoaded( + sync_pb::ModelTypeState::INITIAL_SYNC_PARTIALLY_DONE); + OnSyncStarting(); + + // The initial_sync_state was *partially* done, which is enough to keep the + // (meta)data and carry on. + EXPECT_EQ(2U, db()->metadata_count()); + EXPECT_EQ(2U, ProcessorEntityCount()); + EXPECT_TRUE(type_processor()->IsTrackingMetadata()); + + histogram_tester.ExpectTotalCount( + "Sync.ModelTypeEntityMetadataWithoutInitialSync", + /*expected_count=*/0); +} + TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldResetForDuplicateClientTagHash) { base::HistogramTester histogram_tester; const syncer::ClientTagHash kClientTagHash = - ClientTagHash::FromUnhashed(AUTOFILL, "tag"); + ClientTagHash::FromUnhashed(GetModelType(), "tag"); sync_pb::EntityMetadata entity_metadata1; entity_metadata1.set_client_tag_hash(kClientTagHash.value()); entity_metadata1.set_creation_time(0); @@ -3069,7 +3099,8 @@ TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldNotProcessInvalidRemoteFullUpdate) { - InitializeToMetadataLoaded(/*set_initial_sync_done=*/false); + InitializeToMetadataLoaded( + sync_pb::ModelTypeState::INITIAL_SYNC_STATE_UNSPECIFIED); OnSyncStarting(); UpdateResponseDataList updates; @@ -3240,7 +3271,8 @@ TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldNotClearMetadataWhileStoppedWithoutMetadataInitially) { - InitializeToMetadataLoaded(/*set_initial_sync_done=*/false); + InitializeToMetadataLoaded( + sync_pb::ModelTypeState::INITIAL_SYNC_STATE_UNSPECIFIED); ASSERT_FALSE(type_processor()->IsTrackingMetadata()); base::HistogramTester histogram_tester; @@ -3260,7 +3292,8 @@ // Called before ModelReadyToSync(). type_processor()->ClearMetadataWhileStopped(); - InitializeToMetadataLoaded(/*set_initial_sync_done=*/false); + InitializeToMetadataLoaded( + sync_pb::ModelTypeState::INITIAL_SYNC_STATE_UNSPECIFIED); ASSERT_FALSE(type_processor()->IsTrackingMetadata()); // Nothing recorded to the histograms. histogram_tester.ExpectTotalCount(
diff --git a/components/sync/service/data_type_manager.h b/components/sync/service/data_type_manager.h index 8edc969..f6f0b790 100644 --- a/components/sync/service/data_type_manager.h +++ b/components/sync/service/data_type_manager.h
@@ -109,6 +109,10 @@ // actively ongoing or queued). virtual ModelTypeSet GetTypesWithPendingDownloadForInitialSync() const = 0; + // Returns the datatypes with datatype errors (e.g. errors while loading from + // the disk). + virtual ModelTypeSet GetDataTypesWithPermanentErrors() const = 0; + // The current state of the data type manager. virtual State state() const = 0; };
diff --git a/components/sync/service/data_type_manager_impl.cc b/components/sync/service/data_type_manager_impl.cc index 8f16709..1103f1a 100644 --- a/components/sync/service/data_type_manager_impl.cc +++ b/components/sync/service/data_type_manager_impl.cc
@@ -735,6 +735,10 @@ return Difference(GetEnabledTypes(), downloaded_types_); } +ModelTypeSet DataTypeManagerImpl::GetDataTypesWithPermanentErrors() const { + return data_type_status_table_.GetFatalErrorTypes(); +} + ModelTypeSet DataTypeManagerImpl::GetPurgedDataTypes() const { ModelTypeSet purged_types;
diff --git a/components/sync/service/data_type_manager_impl.h b/components/sync/service/data_type_manager_impl.h index a0939ec..9d446c3 100644 --- a/components/sync/service/data_type_manager_impl.h +++ b/components/sync/service/data_type_manager_impl.h
@@ -48,8 +48,9 @@ ModelTypeSet GetActiveDataTypes() const override; ModelTypeSet GetPurgedDataTypes() const override; ModelTypeSet GetActiveProxyDataTypes() const override; - State state() const override; ModelTypeSet GetTypesWithPendingDownloadForInitialSync() const override; + ModelTypeSet GetDataTypesWithPermanentErrors() const override; + State state() const override; // `ModelLoadManagerDelegate` implementation. void OnAllDataTypesReadyForConfigure() override;
diff --git a/components/sync/service/glue/sync_engine_impl.cc b/components/sync/service/glue/sync_engine_impl.cc index 53af193..4e80ec8 100644 --- a/components/sync/service/glue/sync_engine_impl.cc +++ b/components/sync/service/glue/sync_engine_impl.cc
@@ -546,6 +546,9 @@ (status.backed_off_types != cached_status_.backed_off_types); const bool invalidation_status_changed = (status.notifications_enabled != cached_status_.notifications_enabled); + const bool has_new_invalidated_data_types = + !cached_status_.invalidated_data_types.HasAll( + status.invalidated_data_types); cached_status_ = status; if (backed_off_types_changed) { host_->OnBackedOffTypesChanged(); @@ -553,6 +556,13 @@ if (invalidation_status_changed) { host_->OnInvalidationStatusChanged(); } + if (has_new_invalidated_data_types) { + // Notify about any new data types having pending invalidations. When there + // are less such data types, this basically means that sync cycle has been + // finished, and |host_| will be notified via OnSyncCycleCompleted(), so + // there is no point in duplicating it. + host_->OnNewInvalidatedDataTypes(); + } } void SyncEngineImpl::OnCookieJarChanged(bool account_mismatch,
diff --git a/components/sync/service/glue/sync_engine_impl_unittest.cc b/components/sync/service/glue/sync_engine_impl_unittest.cc index cb3290b7..04e6c40 100644 --- a/components/sync/service/glue/sync_engine_impl_unittest.cc +++ b/components/sync/service/glue/sync_engine_impl_unittest.cc
@@ -50,6 +50,7 @@ using testing::ByMove; using testing::NiceMock; using testing::Return; +using testing::Sequence; namespace syncer { @@ -84,6 +85,7 @@ (override)); MOCK_METHOD(void, OnBackedOffTypesChanged, (), (override)); MOCK_METHOD(void, OnInvalidationStatusChanged, (), (override)); + MOCK_METHOD(void, OnNewInvalidatedDataTypes, (), (override)); }; class FakeSyncManagerFactory : public SyncManagerFactory { @@ -885,6 +887,34 @@ EXPECT_NE(kTestBirthday, transport_data_prefs.GetBirthday()); } +TEST_F(SyncEngineImplTest, ShouldNotifyOnNewInvalidatedDataTypes) { + InitializeBackend(); + ConfigureDataTypes(); + + // Use OnInvalidationStatusChanged() to verify that + // OnNewInvalidatedDataTypes() is caled only once in the beginning, and all + // the next invalidated data types updates should not notify. + Sequence seq; + EXPECT_CALL(mock_host_, OnNewInvalidatedDataTypes).InSequence(seq); + EXPECT_CALL(mock_host_, OnInvalidationStatusChanged).InSequence(seq); + + SyncStatus sync_status; + sync_status.invalidated_data_types.Put(BOOKMARKS); + fake_manager_->NotifySyncStatusChanged(sync_status); + fake_manager_->WaitForSyncThread(); + + // Turn on notifications to trigger OnInvalidationStatusChanged(). + sync_status.notifications_enabled = true; + fake_manager_->NotifySyncStatusChanged(sync_status); + fake_manager_->WaitForSyncThread(); + + // Removing an invalidated data type shouldn't invoke + // OnNewInvalidatedDataTypes(). + sync_status.invalidated_data_types.Remove(BOOKMARKS); + fake_manager_->NotifySyncStatusChanged(sync_status); + fake_manager_->WaitForSyncThread(); +} + } // namespace } // namespace syncer
diff --git a/components/sync/service/sync_service_impl.cc b/components/sync/service/sync_service_impl.cc index 57ae025..9bd4b87 100644 --- a/components/sync/service/sync_service_impl.cc +++ b/components/sync/service/sync_service_impl.cc
@@ -696,6 +696,8 @@ result.Put(DISABLE_REASON_ENTERPRISE_POLICY); } if (!IsSignedIn()) { + // TODO(crbug.com/1447377): additionally, check for refresh tokens to be + // loaded. result.Put(DISABLE_REASON_NOT_SIGNED_IN); } } @@ -1040,6 +1042,10 @@ NotifyObservers(); } +void SyncServiceImpl::OnNewInvalidatedDataTypes() { + NotifyObservers(); +} + void SyncServiceImpl::OnConfigureDone( const DataTypeManager::ConfigureResult& result) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -1838,8 +1844,43 @@ SyncService::ModelTypeDownloadStatus SyncServiceImpl::GetDownloadStatusFor( ModelType type) const { - NOTREACHED() << "Download status API is not implemented."; - return ModelTypeDownloadStatus::kWaitingForUpdates; + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (!auth_manager_->IsActiveAccountInfoFullyLoaded()) { + // Wait for refresh tokens to be loaded from the disk. GetDisableReasons() + // won't be empty until then. + return ModelTypeDownloadStatus::kWaitingForUpdates; + } + + // TODO(crbug.com/1425026): check whether this works when local sync is + // enabled. + if (!GetDisableReasons().Empty() || !GetDataTypesToConfigure().Has(type)) { + // Sync is disabled hence updates won't be downloaded from the server. + return ModelTypeDownloadStatus::kError; + } + + if (!data_type_manager_) { + // Wait for the sync engine to be fully initialized. + return ModelTypeDownloadStatus::kWaitingForUpdates; + } + CHECK(engine_); + + if (data_type_manager_->GetDataTypesWithPermanentErrors().Has(type)) { + return ModelTypeDownloadStatus::kError; + } + + if (!GetActiveDataTypes().Has(type) || + !engine_->GetDetailedStatus().notifications_enabled) { + return ModelTypeDownloadStatus::kWaitingForUpdates; + } + + if (engine_->GetDetailedStatus().invalidated_data_types.Has(type)) { + return ModelTypeDownloadStatus::kWaitingForUpdates; + } + + // TODO(crbug.com/1425026): check for upcoming polling request. + NOTREACHED() << "Download status API is not fully implemented yet."; + return ModelTypeDownloadStatus::kUpToDate; } CoreAccountInfo SyncServiceImpl::GetAccountInfo() const {
diff --git a/components/sync/service/sync_service_impl.h b/components/sync/service/sync_service_impl.h index 178027f..28a0bed 100644 --- a/components/sync/service/sync_service_impl.h +++ b/components/sync/service/sync_service_impl.h
@@ -161,6 +161,7 @@ void OnActionableProtocolError(const SyncProtocolError& error) override; void OnBackedOffTypesChanged() override; void OnInvalidationStatusChanged() override; + void OnNewInvalidatedDataTypes() override; // DataTypeManagerObserver implementation. void OnConfigureDone(const DataTypeManager::ConfigureResult& result) override;
diff --git a/components/sync/service/sync_service_impl_unittest.cc b/components/sync/service/sync_service_impl_unittest.cc index 0d0572fb..b5b6286 100644 --- a/components/sync/service/sync_service_impl_unittest.cc +++ b/components/sync/service/sync_service_impl_unittest.cc
@@ -52,6 +52,8 @@ using testing::AtLeast; using testing::ByMove; using testing::Eq; +using testing::Invoke; +using testing::IsNull; using testing::Not; using testing::Return; @@ -65,6 +67,11 @@ constexpr char kTestUser[] = "test_user@gmail.com"; +class MockSyncServiceObserver : public SyncServiceObserver { + public: + MOCK_METHOD(void, OnStateChanged, (SyncService * sync), (override)); +}; + class TestSyncServiceObserver : public SyncServiceObserver { public: TestSyncServiceObserver() = default; @@ -1351,5 +1358,104 @@ EXPECT_EQ(1, get_controller(BOOKMARKS)->model()->clear_metadata_call_count()); } +TEST_F(SyncServiceImplTest, ShouldReturnErrorDownloadStatus) { + SignIn(); + CreateService(); + InitializeForNthSync(); + + data_type_manager()->OnSingleDataTypeWillStop( + syncer::BOOKMARKS, + SyncError(FROM_HERE, SyncError::ErrorType::DATATYPE_ERROR, + "Data type failure", syncer::BOOKMARKS)); + EXPECT_EQ(service()->GetDownloadStatusFor(syncer::BOOKMARKS), + SyncService::ModelTypeDownloadStatus::kError); +} + +TEST_F(SyncServiceImplTest, ShouldReturnErrorDownloadStatusWhenSyncDisabled) { + prefs()->SetManagedPref(prefs::internal::kSyncManaged, base::Value(true)); + SignIn(); + CreateService(); + InitializeForNthSync(); + + EXPECT_EQ(service()->GetDownloadStatusFor(syncer::BOOKMARKS), + SyncService::ModelTypeDownloadStatus::kError); +} + +TEST_F(SyncServiceImplTest, ShouldReturnWaitingDownloadStatus) { + SignIn(); + CreateService(); + + ASSERT_THAT(data_type_manager(), IsNull()); + + bool met_configuring_data_type_manager = false; + testing::NiceMock<MockSyncServiceObserver> mock_sync_service_observer; + ON_CALL(mock_sync_service_observer, OnStateChanged) + .WillByDefault(Invoke([this, &met_configuring_data_type_manager]( + SyncService* service) { + // TODO(crbug.com/1425026): verify that there are no errors during + // backend initialization. + if (!data_type_manager()) { + return; + } + if (data_type_manager()->state() == + DataTypeManager::State::CONFIGURING) { + met_configuring_data_type_manager = true; + EXPECT_EQ(service->GetDownloadStatusFor(syncer::BOOKMARKS), + SyncService::ModelTypeDownloadStatus::kWaitingForUpdates); + } + })); + + // Observers must be added after initialization has been started. + InitializeForNthSync(false); + + // GetDownloadStatusFor() must be called only after Initialize(), see + // SyncServiceImpl::Initialize(). + EXPECT_EQ(service()->GetDownloadStatusFor(syncer::BOOKMARKS), + SyncService::ModelTypeDownloadStatus::kWaitingForUpdates); + + service()->AddObserver(&mock_sync_service_observer); + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(met_configuring_data_type_manager); + // TODO(crbug.com/1425026): add check for up-to-date status. + service()->RemoveObserver(&mock_sync_service_observer); +} + +TEST_F(SyncServiceImplTest, ShouldReturnErrorWhenDataTypeDisabled) { + SignIn(); + CreateService(); + InitializeForNthSync(/*run_until_idle=*/false); + + UserSelectableTypeSet enabled_types = + service()->GetUserSettings()->GetSelectedTypes(); + enabled_types.Remove(UserSelectableType::kBookmarks); + service()->GetUserSettings()->SetSelectedTypes(/*sync_everything=*/false, + enabled_types); + + EXPECT_EQ(service()->GetDownloadStatusFor(syncer::BOOKMARKS), + SyncService::ModelTypeDownloadStatus::kError); + + // Finish initialization and double check that the status hasn't changed. + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(service()->GetDownloadStatusFor(syncer::BOOKMARKS), + SyncService::ModelTypeDownloadStatus::kError); +} + +TEST_F(SyncServiceImplTest, ShouldWaitUntilNoInvalidations) { + SignIn(); + CreateService(); + InitializeForNthSync(); + + SyncStatus status; + status.invalidated_data_types.Put(BOOKMARKS); + engine()->SetDetailedStatus(status); + + EXPECT_EQ(service()->GetDownloadStatusFor(syncer::BOOKMARKS), + SyncService::ModelTypeDownloadStatus::kWaitingForUpdates); + // TODO(crbug.com/1425026): uncomment once up-to-date status is supported. + // EXPECT_EQ(service()->GetDownloadStatusFor(syncer::PASSWORDS), + // SyncService::ModelTypeDownloadStatus::kUpToDate); +} + } // namespace } // namespace syncer
diff --git a/components/sync/test/data_type_manager_mock.h b/components/sync/test/data_type_manager_mock.h index 29a0cbe..05838c5 100644 --- a/components/sync/test/data_type_manager_mock.h +++ b/components/sync/test/data_type_manager_mock.h
@@ -30,6 +30,10 @@ GetTypesWithPendingDownloadForInitialSync, (), (const override)); + MOCK_METHOD(ModelTypeSet, + GetDataTypesWithPermanentErrors, + (), + (const override)); MOCK_METHOD(State, state, (), (const override)); private:
diff --git a/components/sync/test/fake_sync_engine.cc b/components/sync/test/fake_sync_engine.cc index fbbe117..bd05182 100644 --- a/components/sync/test/fake_sync_engine.cc +++ b/components/sync/test/fake_sync_engine.cc
@@ -35,6 +35,10 @@ host_->OnEngineInitialized(success, is_first_time_sync_configure_); } +void FakeSyncEngine::SetDetailedStatus(const SyncStatus& status) { + sync_status_ = status; +} + void FakeSyncEngine::Initialize(InitParams params) { DCHECK(params.host); @@ -112,7 +116,7 @@ void FakeSyncEngine::SetProxyTabsDatatypeEnabled(bool enabled) {} const SyncStatus& FakeSyncEngine::GetDetailedStatus() const { - return default_sync_status_; + return sync_status_; } void FakeSyncEngine::HasUnsyncedItemsForTest(
diff --git a/components/sync/test/fake_sync_engine.h b/components/sync/test/fake_sync_engine.h index 6bf1e85..335017a 100644 --- a/components/sync/test/fake_sync_engine.h +++ b/components/sync/test/fake_sync_engine.h
@@ -47,6 +47,8 @@ // in the constructor. void TriggerInitializationCompletion(bool success); + void SetDetailedStatus(const SyncStatus& status); + // Immediately calls params.host->OnEngineInitialized. void Initialize(InitParams params) override; @@ -114,7 +116,7 @@ // DanglingUntriaged because it is assigned a DanglingUntriaged pointer. raw_ptr<SyncEngineHost, DanglingUntriaged> host_ = nullptr; bool initialized_ = false; - const SyncStatus default_sync_status_; + SyncStatus sync_status_; CoreAccountId authenticated_account_id_; bool started_handling_invalidations_ = false; };
diff --git a/components/sync/test/fake_sync_manager.cc b/components/sync/test/fake_sync_manager.cc index d54cc90..988c444a 100644 --- a/components/sync/test/fake_sync_manager.cc +++ b/components/sync/test/fake_sync_manager.cc
@@ -27,7 +27,9 @@ : initial_sync_ended_types_(initial_sync_ended_types), progress_marker_types_(progress_marker_types), configure_fail_types_(configure_fail_types), - last_configure_reason_(CONFIGURE_REASON_UNKNOWN) {} + last_configure_reason_(CONFIGURE_REASON_UNKNOWN) { + sync_task_runner_ = base::SequencedTaskRunner::GetCurrentDefault(); +} FakeSyncManager::~FakeSyncManager() = default; @@ -61,8 +63,20 @@ run_loop.Run(); } +void FakeSyncManager::NotifySyncStatusChanged(const SyncStatus& status) { + sync_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&FakeSyncManager::DoNotifySyncStatusChanged, + base::Unretained(this), status)); +} + +void FakeSyncManager::DoNotifySyncStatusChanged(const SyncStatus& status) { + DCHECK(sync_task_runner_->RunsTasksInCurrentSequence()); + for (Observer& observer : observers_) { + observer.OnSyncStatusChanged(status); + } +} + void FakeSyncManager::Init(InitArgs* args) { - sync_task_runner_ = base::SequencedTaskRunner::GetCurrentDefault(); cache_guid_ = args->cache_guid; birthday_ = args->birthday; bag_of_chips_ = args->bag_of_chips; @@ -113,10 +127,12 @@ } void FakeSyncManager::AddObserver(Observer* observer) { + DCHECK(sync_task_runner_->RunsTasksInCurrentSequence()); observers_.AddObserver(observer); } void FakeSyncManager::RemoveObserver(Observer* observer) { + DCHECK(sync_task_runner_->RunsTasksInCurrentSequence()); observers_.RemoveObserver(observer); }
diff --git a/components/sync/test/fake_sync_manager.h b/components/sync/test/fake_sync_manager.h index 1462f9bb..e01ef9c9 100644 --- a/components/sync/test/fake_sync_manager.h +++ b/components/sync/test/fake_sync_manager.h
@@ -68,6 +68,9 @@ bool IsInvalidatorEnabled() const { return invalidator_enabled_; } + // Notifies all observers about the changed |status|. + void NotifySyncStatusChanged(const SyncStatus& status); + // SyncManager implementation. // Note: we treat whatever message loop this is called from as the sync // loop for purposes of callbacks. @@ -105,6 +108,8 @@ ActiveDevicesInvalidationInfo active_devices_invalidation_info) override; private: + void DoNotifySyncStatusChanged(const SyncStatus& status); + scoped_refptr<base::SequencedTaskRunner> sync_task_runner_; base::ObserverList<SyncManager::Observer>::Unchecked observers_;
diff --git a/components/webauthn/android/webauthn_cred_man_delegate.cc b/components/webauthn/android/webauthn_cred_man_delegate.cc index 5fe069e..6b03cc1 100644 --- a/components/webauthn/android/webauthn_cred_man_delegate.cc +++ b/components/webauthn/android/webauthn_cred_man_delegate.cc
@@ -6,6 +6,7 @@ #include <memory> #include <utility> +#include "base/android/build_info.h" #include "base/functional/callback.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" @@ -62,7 +63,8 @@ // static bool WebAuthnCredManDelegate::IsCredManEnabled() { - return base::FeatureList::IsEnabled(device::kWebAuthnAndroidCredMan); + return base::android::BuildInfo::GetInstance()->is_at_least_u() && + base::FeatureList::IsEnabled(device::kWebAuthnAndroidCredMan); } // static
diff --git a/components/webdata/common/web_database.cc b/components/webdata/common/web_database.cc index e22a8e0..d60a819 100644 --- a/components/webdata/common/web_database.cc +++ b/components/webdata/common/web_database.cc
@@ -225,6 +225,9 @@ return FailedMigrationTo(next_version); } } + base::UmaHistogramExactLinear("WebDatabase.SucceededMigrationToVersion", + next_version, + WebDatabase::kCurrentVersionNumber + 1); } return sql::INIT_OK; }
diff --git a/content/browser/back_forward_cache_no_store_browsertest.cc b/content/browser/back_forward_cache_no_store_browsertest.cc index 4d9d46a..e1b4dbdd 100644 --- a/content/browser/back_forward_cache_no_store_browsertest.cc +++ b/content/browser/back_forward_cache_no_store_browsertest.cc
@@ -102,8 +102,9 @@ protected: void SetUpCommandLine(base::CommandLine* command_line) override { EnableFeatureAndSetParams(features::kBackForwardCache, "", ""); - EnableFeatureAndSetParams(kCacheControlNoStoreEnterBackForwardCache, - "level", "store-and-evict"); + EnableFeatureAndSetParams( + features::kCacheControlNoStoreEnterBackForwardCache, "level", + "store-and-evict"); BackForwardCacheBrowserTest::SetUpCommandLine(command_line); } }; @@ -937,8 +938,9 @@ protected: void SetUpCommandLine(base::CommandLine* command_line) override { EnableFeatureAndSetParams(features::kBackForwardCache, "", ""); - EnableFeatureAndSetParams(kCacheControlNoStoreEnterBackForwardCache, - "level", "restore-unless-cookie-change"); + EnableFeatureAndSetParams( + features::kCacheControlNoStoreEnterBackForwardCache, "level", + "restore-unless-cookie-change"); BackForwardCacheBrowserTest::SetUpCommandLine(command_line); } }; @@ -1426,9 +1428,9 @@ protected: void SetUpCommandLine(base::CommandLine* command_line) override { EnableFeatureAndSetParams(features::kBackForwardCache, "", ""); - EnableFeatureAndSetParams(kCacheControlNoStoreEnterBackForwardCache, - "level", - "restore-unless-http-only-cookie-change"); + EnableFeatureAndSetParams( + features::kCacheControlNoStoreEnterBackForwardCache, "level", + "restore-unless-http-only-cookie-change"); BackForwardCacheBrowserTest::SetUpCommandLine(command_line); } };
diff --git a/content/browser/geolocation/geolocation_service_impl.cc b/content/browser/geolocation/geolocation_service_impl.cc index efaa068f..e0fc994f 100644 --- a/content/browser/geolocation/geolocation_service_impl.cc +++ b/content/browser/geolocation/geolocation_service_impl.cc
@@ -12,6 +12,7 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "mojo/public/cpp/bindings/callback_helpers.h" +#include "services/device/public/cpp/geolocation/geolocation_manager.h" #include "third_party/blink/public/common/permissions/permission_utils.h" #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom.h" @@ -58,12 +59,24 @@ DCHECK(render_frame_host); } -GeolocationServiceImpl::~GeolocationServiceImpl() {} +GeolocationServiceImpl::~GeolocationServiceImpl() { + if (device::GeolocationManager* geolocation_manager = + device::GeolocationManager::GetInstance(); + geolocation_manager) { + // One call here is enough as the calls are grouped by app name + geolocation_manager->AppCeasesToUseGeolocation(); + } +} void GeolocationServiceImpl::Bind( mojo::PendingReceiver<blink::mojom::GeolocationService> receiver) { receiver_set_.Add(this, std::move(receiver), std::make_unique<GeolocationServiceImplContext>()); + if (device::GeolocationManager* geolocation_manager = + device::GeolocationManager::GetInstance(); + geolocation_manager) { + geolocation_manager->AppAttemptsToUseGeolocation(); + } } void GeolocationServiceImpl::CreateGeolocation(
diff --git a/content/browser/renderer_host/back_forward_cache_impl.cc b/content/browser/renderer_host/back_forward_cache_impl.cc index 9615a72..c47ecf3 100644 --- a/content/browser/renderer_host/back_forward_cache_impl.cc +++ b/content/browser/renderer_host/back_forward_cache_impl.cc
@@ -381,7 +381,7 @@ "restore-unless-http-only-cookie-change"}, }; const base::FeatureParam<CacheControlNoStoreExperimentLevel> - cache_control_level{&kCacheControlNoStoreEnterBackForwardCache, + cache_control_level{&features::kCacheControlNoStoreEnterBackForwardCache, kCacheControlNoStoreExperimentLevelName, CacheControlNoStoreExperimentLevel::kDoNotStore, &cache_control_levels}; @@ -389,7 +389,7 @@ CacheControlNoStoreExperimentLevel GetCacheControlNoStoreLevel() { if (!IsBackForwardCacheEnabled() || !base::FeatureList::IsEnabled( - kCacheControlNoStoreEnterBackForwardCache)) { + features::kCacheControlNoStoreEnterBackForwardCache)) { return CacheControlNoStoreExperimentLevel::kDoNotStore; } return cache_control_level.Get();
diff --git a/content/browser/renderer_host/back_forward_cache_impl.h b/content/browser/renderer_host/back_forward_cache_impl.h index 73511d5..2350280 100644 --- a/content/browser/renderer_host/back_forward_cache_impl.h +++ b/content/browser/renderer_host/back_forward_cache_impl.h
@@ -57,14 +57,6 @@ "BackForwardCacheNoTimeEviction", base::FEATURE_DISABLED_BY_DEFAULT); -// Allows pages with cache-control:no-store to enter the back/forward cache. -// Feature params can specify whether pages with cache-control:no-store can be -// restored if cookies change / if HTTPOnly cookies change. -// TODO(crbug.com/1228611): Enable this feature. -BASE_FEATURE(kCacheControlNoStoreEnterBackForwardCache, - "CacheControlNoStoreEnterBackForwardCache", - base::FEATURE_DISABLED_BY_DEFAULT); - CONTENT_EXPORT BASE_DECLARE_FEATURE(kBackForwardCacheSize); CONTENT_EXPORT extern const base::FeatureParam<int> kBackForwardCacheSizeCacheSize;
diff --git a/content/browser/utility_process_host.cc b/content/browser/utility_process_host.cc index c2231384..cf3c0c18 100644 --- a/content/browser/utility_process_host.cc +++ b/content/browser/utility_process_host.cc
@@ -307,6 +307,7 @@ // Browser command-line switches to propagate to the utility process. static const char* const kSwitchNames[] = { network::switches::kAdditionalTrustTokenKeyCommitments, + network::switches::kBlockThirdPartyCookies, network::switches::kForceEffectiveConnectionType, network::switches::kHostResolverRules, network::switches::kIgnoreCertificateErrorsSPKIList,
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 0c8a8ad..eef5b0b 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -225,6 +225,14 @@ "BrowserVerifiedUserActivationMouse", base::FEATURE_DISABLED_BY_DEFAULT); +// Allows pages with cache-control:no-store to enter the back/forward cache. +// Feature params can specify whether pages with cache-control:no-store can be +// restored if cookies change / if HTTPOnly cookies change. +// TODO(crbug.com/1228611): Enable this feature. +BASE_FEATURE(kCacheControlNoStoreEnterBackForwardCache, + "CacheControlNoStoreEnterBackForwardCache", + base::FEATURE_DISABLED_BY_DEFAULT); + // If Canvas2D Image Chromium is allowed, this feature controls whether it is // enabled. BASE_FEATURE(kCanvas2DImageChromium,
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 281c0c57..338d0c9 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -51,6 +51,7 @@ kBrokerFileOperationsOnDiskCacheInNetworkService); CONTENT_EXPORT BASE_DECLARE_FEATURE(kBrowserVerifiedUserActivationKeyboard); CONTENT_EXPORT BASE_DECLARE_FEATURE(kBrowserVerifiedUserActivationMouse); +CONTENT_EXPORT BASE_DECLARE_FEATURE(kCacheControlNoStoreEnterBackForwardCache); CONTENT_EXPORT BASE_DECLARE_FEATURE(kCanvas2DImageChromium); CONTENT_EXPORT BASE_DECLARE_FEATURE( kClearCrossSiteCrossBrowsingContextGroupWindowName);
diff --git a/content/public/common/content_switch_dependent_feature_overrides.cc b/content/public/common/content_switch_dependent_feature_overrides.cc index 24f3169c0..ff9dbe7 100644 --- a/content/public/common/content_switch_dependent_feature_overrides.cc +++ b/content/public/common/content_switch_dependent_feature_overrides.cc
@@ -119,6 +119,11 @@ std::cref(net::features::kPartitionedCookies), base::FeatureList::OVERRIDE_ENABLE_FEATURE}, + // Override third-party cookie blocking. + {network::switches::kBlockThirdPartyCookies, + std::cref(net::features::kForceThirdPartyCookieBlocking), + base::FeatureList::OVERRIDE_ENABLE_FEATURE}, + // Overrides for --isolation-by-default. {switches::kIsolationByDefault, std::cref(features::kEmbeddingRequiresOptIn),
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc index 9443923..1bfd5fb 100644 --- a/extensions/browser/api/web_request/web_request_api.cc +++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -2807,8 +2807,9 @@ rules_registry->ready().Post( FROM_HERE, base::BindOnce(&ExtensionWebRequestEventRouter::OnRulesRegistryReady, - base::Unretained(this), browser_context, event_name, - request->id, request_stage)); + base::Unretained(this), + base::UnsafeDanglingUntriaged(browser_context), + event_name, request->id, request_stage)); BlockedRequest& blocked_request = blocked_requests_[request->id]; blocked_request.num_handlers_blocking++; blocked_request.request = request;
diff --git a/infra/config/generated/builders/webrtc/WebRTC Chromium Mac Builder/properties.json b/infra/config/generated/builders/webrtc/WebRTC Chromium Mac Builder/properties.json index 9f57f19..689c3dc2 100644 --- a/infra/config/generated/builders/webrtc/WebRTC Chromium Mac Builder/properties.json +++ b/infra/config/generated/builders/webrtc/WebRTC Chromium Mac Builder/properties.json
@@ -95,5 +95,5 @@ "builder_group": "chromium.webrtc", "perf_dashboard_machine_group": "ChromiumWebRTC", "recipe": "chromium", - "xcode_build_version": "14c18" + "xcode_build_version": "14e222b" } \ No newline at end of file
diff --git a/infra/config/generated/builders/webrtc/WebRTC Chromium Mac Tester/properties.json b/infra/config/generated/builders/webrtc/WebRTC Chromium Mac Tester/properties.json index 5c6c749..c8eb757 100644 --- a/infra/config/generated/builders/webrtc/WebRTC Chromium Mac Tester/properties.json +++ b/infra/config/generated/builders/webrtc/WebRTC Chromium Mac Tester/properties.json
@@ -87,5 +87,5 @@ "builder_group": "chromium.webrtc", "perf_dashboard_machine_group": "ChromiumWebRTC", "recipe": "chromium", - "xcode_build_version": "14c18" + "xcode_build_version": "14e222b" } \ No newline at end of file
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 478a465..af0c72c 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -89795,8 +89795,8 @@ '}' execution_timeout_secs: 7200 caches { - name: "xcode_ios_14c18" - path: "xcode_ios_14c18.app" + name: "xcode_ios_14e222b" + path: "xcode_ios_14e222b.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -89845,8 +89845,8 @@ '}' execution_timeout_secs: 7200 caches { - name: "xcode_ios_14c18" - path: "xcode_ios_14c18.app" + name: "xcode_ios_14e222b" + path: "xcode_ios_14e222b.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/infra/config/generated/testing/gn_isolate_map.pyl b/infra/config/generated/testing/gn_isolate_map.pyl index c22943e..566f4b93 100644 --- a/infra/config/generated/testing/gn_isolate_map.pyl +++ b/infra/config/generated/testing/gn_isolate_map.pyl
@@ -207,14 +207,6 @@ "label": "//android_webview/support_library/boundary_interfaces:boundary_interface_example_apk", "type": "additional_compile_target", }, - "devtools_web_tests": { - "label": "//:devtools_web_tests", - "type": "generated_script", - "args": [ - "--results-directory", - "${ISOLATED_OUTDIR}", - ], - }, "boringssl_crypto_tests": { "label": "//third_party/boringssl:boringssl_crypto_tests", "type": "console_test_launcher",
diff --git a/infra/config/subprojects/webrtc/webrtc.star b/infra/config/subprojects/webrtc/webrtc.star index f1a78a4..f8c494d 100644 --- a/infra/config/subprojects/webrtc/webrtc.star +++ b/infra/config/subprojects/webrtc/webrtc.star
@@ -155,7 +155,7 @@ build_gs_bucket = "chromium-webrtc", ), os = os.MAC_ANY, - xcode = xcode.x14main, + xcode = xcode.x14betabots, ) builder( @@ -176,7 +176,7 @@ ), build_gs_bucket = "chromium-webrtc", ), - xcode = xcode.x14main, + xcode = xcode.x14betabots, ) builder(
diff --git a/infra/config/targets/targets.star b/infra/config/targets/targets.star index e5edd09..d5f82194 100644 --- a/infra/config/targets/targets.star +++ b/infra/config/targets/targets.star
@@ -259,15 +259,6 @@ # executable = "browser_tests", # ) -targets.generated_script( - name = "devtools_web_tests", - label = "//:devtools_web_tests", - args = [ - "--results-directory", - "${ISOLATED_OUTDIR}", - ], -) - targets.console_test_launcher( name = "boringssl_crypto_tests", label = "//third_party/boringssl:boringssl_crypto_tests",
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index 4da0677..d3a18cb 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -1483,6 +1483,10 @@ flag_descriptions::kAutofillEnableCardArtImageDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(autofill::features::kAutofillEnableCardArtImage)}, + {"replace-sync-promos-with-sign-in-promos", + flag_descriptions::kReplaceSyncPromosWithSignInPromosName, + flag_descriptions::kReplaceSyncPromosWithSignInPromosDescription, + flags_ui::kOsIos, FEATURE_VALUE_TYPE(kReplaceSyncPromosWithSignInPromos)}, }; bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index 0e92e4a9..aa86f0f 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -848,6 +848,11 @@ "When enabled, extra tabs with the New Tab Page open and no navigation " "history will be removed."; +const char kReplaceSyncPromosWithSignInPromosName[] = + "Replace all sync-related UI with sign-in ones"; +const char kReplaceSyncPromosWithSignInPromosDescription[] = + "When enabled, all sync-related promos will be replaced by sign-in ones."; + const char kRestoreSessionFromCacheName[] = "Use native WKWebView sesion restoration (iOS15 only)."; const char kRestoreSessionFromCacheDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index 40aa629..cc4d396 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -751,6 +751,11 @@ extern const char kRemoveExcessNTPsExperimentName[]; extern const char kRemoveExcessNTPsExperimentDescription[]; +// Title and description for the flag to replace all sync-related UI with +// sign-in ones. +extern const char kReplaceSyncPromosWithSignInPromosName[]; +extern const char kReplaceSyncPromosWithSignInPromosDescription[]; + // Title and description for the flag that makes Safe Browsing available. extern const char kSafeBrowsingAvailableName[]; extern const char kSafeBrowsingAvailableDescription[];
diff --git a/ios/chrome/browser/history/history_client_impl.cc b/ios/chrome/browser/history/history_client_impl.cc index 5aab8bf3..2c3f6ebc2 100644 --- a/ios/chrome/browser/history/history_client_impl.cc +++ b/ios/chrome/browser/history/history_client_impl.cc
@@ -65,12 +65,14 @@ std::unique_ptr<history::HistoryBackendClient> HistoryClientImpl::CreateBackendClient() { std::vector<scoped_refptr<bookmarks::ModelLoader>> model_loaders; - if (local_or_syncable_bookmark_model_ && - local_or_syncable_bookmark_model_->model_loader()) { - model_loaders.push_back(local_or_syncable_bookmark_model_->model_loader()); - } - if (account_bookmark_model_ && account_bookmark_model_->model_loader()) { - model_loaders.push_back(account_bookmark_model_->model_loader()); + for (bookmarks::BookmarkModel* model : + {local_or_syncable_bookmark_model_, account_bookmark_model_}) { + if (!model) { + continue; + } + scoped_refptr<bookmarks::ModelLoader> loader = model->model_loader(); + CHECK(loader); + model_loaders.push_back(std::move(loader)); } return std::make_unique<HistoryBackendClientImpl>(std::move(model_loaders)); }
diff --git a/ios/chrome/browser/shared/public/features/features.h b/ios/chrome/browser/shared/public/features/features.h index d63a5d5..b4347797 100644 --- a/ios/chrome/browser/shared/public/features/features.h +++ b/ios/chrome/browser/shared/public/features/features.h
@@ -191,4 +191,7 @@ // synchronous clipboard access will always return nil/false. BASE_DECLARE_FEATURE(kOnlyAccessClipboardAsync); +// Feature flag to replace all sync-related UI with sign-in ones. +BASE_DECLARE_FEATURE(kReplaceSyncPromosWithSignInPromos); + #endif // IOS_CHROME_BROWSER_SHARED_PUBLIC_FEATURES_FEATURES_H_
diff --git a/ios/chrome/browser/shared/public/features/features.mm b/ios/chrome/browser/shared/public/features/features.mm index ee43fea..9051f8a 100644 --- a/ios/chrome/browser/shared/public/features/features.mm +++ b/ios/chrome/browser/shared/public/features/features.mm
@@ -171,6 +171,10 @@ base::FEATURE_DISABLED_BY_DEFAULT); bool IsTabGridSortedByRecency() { + if (ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET) { + return false; + } + return base::FeatureList::IsEnabled(kTabGridRecencySort); } @@ -251,3 +255,7 @@ BASE_FEATURE(kOnlyAccessClipboardAsync, "OnlyAccessClipboardAsync", base::FEATURE_DISABLED_BY_DEFAULT); + +BASE_FEATURE(kReplaceSyncPromosWithSignInPromos, + "ReplaceSyncPromosWithSignInPromos", + base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm index b7d3887..e6683d542 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
@@ -919,8 +919,7 @@ [ChromeEarlGrey clearBrowsingHistory]; // Clear the pasteboard in case there is a URL copied. - UIPasteboard* pasteboard = UIPasteboard.generalPasteboard; - [pasteboard setValue:@"" forPasteboardType:UIPasteboardNameGeneral]; + [ChromeEarlGrey clearPasteboard]; } // Copy button should be hidden when the omnibox is empty otherwise it should be @@ -934,13 +933,6 @@ EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 15."); } -#if !TARGET_IPHONE_SIMULATOR - // TODO(crbug.com/1446075): This test fails on iOS 16.4 devices too. - if (@available(iOS 16.4, *)) { - EARL_GREY_TEST_DISABLED(@"crbug.com/1446075: Fails on iOS 16.4+ devices."); - } -#endif - // Focus omnibox. [self focusFakebox]; [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()] @@ -1036,13 +1028,6 @@ // If the selected text is the entire omnibox field, select & SelectAll button // should be hidden. - (void)testSelection { -#if !TARGET_IPHONE_SIMULATOR - // TODO(crbug.com/1446075): This test fails on iOS 16.4 devices. - if (@available(iOS 16.4, *)) { - EARL_GREY_TEST_DISABLED(@"crbug.com/1446075: Fails on iOS 16.4+ devices."); - } -#endif - // Focus omnibox. [self focusFakebox]; [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()] @@ -1072,12 +1057,24 @@ [[EarlGrey selectElementWithMatcher:SelectAllButton()] assertWithMatcher:grey_notNil()]; + // Wait for UIMenuController to appear or timeout after 2 seconds. + GREYCondition* CopyButtonIsDisplayed = [GREYCondition + conditionWithName:@"Copy button display condition" + block:^BOOL { + NSError* error = nil; + [[EarlGrey selectElementWithMatcher: + chrome_test_util:: + SystemSelectionCalloutCopyButton()] + assertWithMatcher:grey_notNil() + error:&error]; + return error == nil; + }]; // Pressing select should allow copy. // select should be hidden. [[EarlGrey selectElementWithMatcher:SelectButton()] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:chrome_test_util:: - SystemSelectionCalloutCopyButton()] - assertWithMatcher:grey_notNil()]; + GREYAssertTrue([CopyButtonIsDisplayed + waitWithTimeout:kWaitForUIElementTimeout.InSecondsF()], + @"Copy button display failed"); [[EarlGrey selectElementWithMatcher:SelectButton()] assertWithMatcher:grey_nil()]; @@ -1085,9 +1082,9 @@ // selectAll should be hidden. [[EarlGrey selectElementWithMatcher:SelectAllButton()] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:chrome_test_util:: - SystemSelectionCalloutCopyButton()] - assertWithMatcher:grey_notNil()]; + GREYAssertTrue([CopyButtonIsDisplayed + waitWithTimeout:kWaitForUIElementTimeout.InSecondsF()], + @"Copy button display failed"); [[EarlGrey selectElementWithMatcher:SelectAllButton()] assertWithMatcher:grey_nil()]; } @@ -1099,28 +1096,12 @@ EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 15."); } -#if !TARGET_IPHONE_SIMULATOR - // TODO(crbug.com/1446075): This test fails on iOS 16.4 devices too. - if (@available(iOS 16.4, *)) { - EARL_GREY_TEST_DISABLED(@"crbug.com/1446075: Fails on iOS 16.4+ devices."); - } -#endif - NSString* copiedText = @"test no default match1"; // Put some text in pasteboard. - UIPasteboard.generalPasteboard.string = copiedText; + [ChromeEarlGrey copyTextToPasteboard:copiedText]; - // Copying can take a while, wait for it to happen. - GREYCondition* copyCondition = - [GREYCondition conditionWithName:@"test text copied condition" - block:^BOOL { - return [UIPasteboard.generalPasteboard.string - isEqualToString:copiedText]; - }]; - // Wait for copy to happen or timeout after 5 seconds. - GREYAssertTrue([copyCondition waitWithTimeout:5], - @"Copying test text failed"); + [ChromeEarlGrey verifyStringCopied:copiedText]; // Focus the omnibox. [self focusFakebox];
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm index f1a6b724..a2a7059 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm
@@ -114,12 +114,7 @@ tracker:feature_engagement::TrackerFactory:: GetForBrowserState( self.browser->GetBrowserState())]; - // TODO(crbug.com/1045047): Use HandlerForProtocol after commands protocol - // clean up. - self.mediator.dispatcher = - static_cast<id<BrowserCommands>>(self.browser->GetCommandDispatcher()); - self.mediator.webStateList = self.browser->GetWebStateList(); TemplateURLService* templateURLService = ios::TemplateURLServiceFactory::GetForBrowserState( self.browser->GetBrowserState());
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.h index 822c260..14225e5 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.h +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.h
@@ -21,7 +21,6 @@ #import "ui/base/window_open_disposition.h" @protocol ApplicationCommands; -@protocol BrowserCommands; @class BrowserActionFactory; @class CarouselItem; @protocol CarouselItemConsumer; @@ -31,16 +30,15 @@ @class OmniboxPopupMediator; @class OmniboxPopupPresenter; @protocol SnackbarCommands; -class WebStateList; class AutocompleteController; namespace image_fetcher { class ImageDataFetcher; -} // namespace +} // namespace image_fetcher namespace feature_engagement { class Tracker; -} +} // namespace feature_engagement class OmniboxPopupMediatorDelegate { public: @@ -91,7 +89,6 @@ - (void)setSemanticContentAttribute: (UISemanticContentAttribute)semanticContentAttribute; -@property(nonatomic, weak) id<BrowserCommands> dispatcher; @property(nonatomic, weak) id<AutocompleteResultConsumer> consumer; /// Consumer for debug info. @property(nonatomic, weak) id<PopupDebugInfoConsumer, @@ -108,8 +105,6 @@ /// Presenter for the popup, handling the positioning and the presentation /// animations. @property(nonatomic, strong) OmniboxPopupPresenter* presenter; -/// The web state list this mediator is handling. -@property(nonatomic, assign) WebStateList* webStateList; /// Whether the default search engine is Google impacts which icon is used in /// some cases @property(nonatomic, assign) BOOL defaultSearchEngineIsGoogle;
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm index 960ab596..eea096d 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm
@@ -30,7 +30,6 @@ #import "ios/chrome/browser/net/crurl.h" #import "ios/chrome/browser/ntp/new_tab_page_util.h" #import "ios/chrome/browser/shared/coordinator/default_browser_promo/non_modal_default_browser_promo_scheduler_scene_agent.h" -#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h" #import "ios/chrome/browser/shared/public/commands/application_commands.h" #import "ios/chrome/browser/shared/public/commands/open_new_tab_command.h" #import "ios/chrome/browser/shared/ui/util/pasteboard_util.h"
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_pedal_egtest.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_pedal_egtest.mm index 696dd23..5ca944a2 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_pedal_egtest.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_pedal_egtest.mm
@@ -284,6 +284,39 @@ [ChromeEarlGrey closeCurrentTab]; } +// Tests that safety check pedal is present and it opens the safety check page. +- (void)testSafetyCheckPedal { + // Focus omnibox from Web. + [ChromeEarlGrey loadURL:GURL("about:blank")]; + [ChromeEarlGreyUI focusOmniboxAndType:@"pedalsafetycheck"]; + + NSString* safetyCheckPedalString = l10n_util::GetNSString( + IDS_IOS_OMNIBOX_PEDAL_SUBTITLE_RUN_CHROME_SAFETY_CHECK); + + // Matcher for safety check pedal suggestion. + id<GREYMatcher> safetyCheckPedal = popupRowWithString(safetyCheckPedalString); + + // Safety check pedal should be visible. + [ChromeEarlGrey waitForUIElementToAppearWithMatcher:safetyCheckPedal]; + + // Tap on safety check pedal. + [[EarlGrey selectElementWithMatcher:safetyCheckPedal] + performAction:grey_tap()]; + + // Safety check page should be displayed. + [ChromeEarlGrey waitForUIElementToAppearWithMatcher: + chrome_test_util::SafetyCheckTableViewMatcher()]; + + // Close the safety check page. + [[EarlGrey + selectElementWithMatcher:chrome_test_util::NavigationBarDoneButton()] + performAction:grey_tap()]; + [ChromeEarlGrey waitForUIElementToDisappearWithMatcher: + chrome_test_util::SafetyCheckTableViewMatcher()]; + + [ChromeEarlGrey closeCurrentTab]; +} + // Tests that the dino pedal does not appear when the search suggestion is below // the top 3. - (void)testNoPedal {
diff --git a/ios/chrome/test/data/omnibox/fake_suggestions_pedal.json b/ios/chrome/test/data/omnibox/fake_suggestions_pedal.json index dc03e89a..30888a3 100644 --- a/ios/chrome/test/data/omnibox/fake_suggestions_pedal.json +++ b/ios/chrome/test/data/omnibox/fake_suggestions_pedal.json
@@ -333,5 +333,46 @@ "google:verbatimrelevance": 1300 } ], + [ + "pedalsafetycheck", + [ + "Run Chrome Safety Check", + "nopedal1", + "nopedal2" + ], + [ + "", + "", + "", + ], + [], + { + "google:clientdata": { + "bpc": false, + "tlw": false + }, + "google:suggestdetail": [ + {}, + {}, + {}, + ], + "google:suggestrelevance": [ + 1253, + 1252, + 1251, + ], + "google:suggestsubtypes": [ + [], + [], + [], + ], + "google:suggesttype": [ + "QUERY", + "QUERY", + "QUERY", + ], + "google:verbatimrelevance": 1300 + } + ], ]
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.h b/ios/chrome/test/earl_grey/chrome_matchers.h index 5acf13fe..fb18f32056 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers.h +++ b/ios/chrome/test/earl_grey/chrome_matchers.h
@@ -578,6 +578,9 @@ // Returns a mather for default browser settings table view. id<GREYMatcher> DefaultBrowserSettingsTableViewMatcher(); +// Returns a matcher for safety check table view. +id<GREYMatcher> SafetyCheckTableViewMatcher(); + #pragma mark - Promo style view controller // Returns matcher for the primary action button.
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.mm b/ios/chrome/test/earl_grey/chrome_matchers.mm index acd7a3d..440caaa 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers.mm +++ b/ios/chrome/test/earl_grey/chrome_matchers.mm
@@ -717,6 +717,10 @@ return [ChromeMatchersAppInterface defaultBrowserSettingsTableViewMatcher]; } +id<GREYMatcher> SafetyCheckTableViewMatcher() { + return [ChromeMatchersAppInterface safetyCheckTableViewMatcher]; +} + #pragma mark - Overflow Menu Destinations id<GREYMatcher> BookmarksDestinationButton() {
diff --git a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.h b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.h index 24e9f9bb..10149b7 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.h +++ b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.h
@@ -544,6 +544,9 @@ // Returns a matcher to default browser settings table view. + (id<GREYMatcher>)defaultBrowserSettingsTableViewMatcher; +// Returns a matcher to safety check table view. ++ (id<GREYMatcher>)safetyCheckTableViewMatcher; + #pragma mark - Overflow Menu Destinations // Returns matcher for the bookmarks destination button in the overflow menu
diff --git a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm index cad9f41..7f1c646 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm +++ b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm
@@ -1096,6 +1096,11 @@ return grey_accessibilityID(kDefaultBrowserSettingsTableViewId); } ++ (id<GREYMatcher>)safetyCheckTableViewMatcher { + return grey_accessibilityID( + SafetyCheckTableViewController.accessibilityIdentifier); +} + #pragma mark - Overflow Menu Destinations + (id<GREYMatcher>)bookmarksDestinationButton {
diff --git a/net/base/features.cc b/net/base/features.cc index b50811b4..c1f7597 100644 --- a/net/base/features.cc +++ b/net/base/features.cc
@@ -365,4 +365,9 @@ "EnableSchemeBoundCookies", base::FEATURE_DISABLED_BY_DEFAULT); +// Enable third-party cookie blocking from the command line. +BASE_FEATURE(kForceThirdPartyCookieBlocking, + "ForceThirdPartyCookieBlockingEnabled", + base::FEATURE_DISABLED_BY_DEFAULT); + } // namespace net::features
diff --git a/net/base/features.h b/net/base/features.h index 168fea0..e29fc8e4 100644 --- a/net/base/features.h +++ b/net/base/features.h
@@ -383,6 +383,9 @@ // Enables binding of cookies to the scheme that originally set them. NET_EXPORT BASE_DECLARE_FEATURE(kEnableSchemeBoundCookies); +// Enables enabling third-party cookie blocking from the command line. +NET_EXPORT BASE_DECLARE_FEATURE(kForceThirdPartyCookieBlocking); + } // namespace net::features #endif // NET_BASE_FEATURES_H_
diff --git a/net/cookies/cookie_util.cc b/net/cookies/cookie_util.cc index 683eabd..edc57c10 100644 --- a/net/cookies/cookie_util.cc +++ b/net/cookies/cookie_util.cc
@@ -1002,4 +1002,8 @@ base::ranges::is_sorted(included_cookies, CookieWithAccessResultSorter)); } +NET_EXPORT bool IsForceThirdPartyCookieBlockingEnabled() { + return base::FeatureList::IsEnabled(features::kForceThirdPartyCookieBlocking); +} + } // namespace net::cookie_util
diff --git a/net/cookies/cookie_util.h b/net/cookies/cookie_util.h index d02b6177..8c7ecff 100644 --- a/net/cookies/cookie_util.h +++ b/net/cookies/cookie_util.h
@@ -331,6 +331,11 @@ const CookieAccessResultList& included_cookies, const CookieAccessResultList& excluded_cookies); +// Returns the default third-party cookie blocking setting, which is false +// unless you enable ForceThirdPartyCookieBlocking with the command line switch +// --block-third-party-cookies. +NET_EXPORT bool IsForceThirdPartyCookieBlockingEnabled(); + } // namespace cookie_util } // namespace net
diff --git a/remoting/host/chromeos/features.cc b/remoting/host/chromeos/features.cc index 3cf69ec6..a2ce667 100644 --- a/remoting/host/chromeos/features.cc +++ b/remoting/host/chromeos/features.cc
@@ -16,10 +16,6 @@ "EnableCrdAdminRemoteAccessV2", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kForceCrdAdminRemoteAccess, - "ForceCrdAdminRemoteAccess", - base::FEATURE_DISABLED_BY_DEFAULT); - BASE_FEATURE(kEnableFrameSinkDesktopCapturerInCrd, "EnableFrameSinkDesktopCapturerInCrd", base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/remoting/host/chromeos/features.h b/remoting/host/chromeos/features.h index 2db3232..b299a50 100644 --- a/remoting/host/chromeos/features.h +++ b/remoting/host/chromeos/features.h
@@ -17,11 +17,6 @@ // to GA. BASE_DECLARE_FEATURE(kEnableCrdAdminRemoteAccessV2); -// Force all enterprise remote connections to be remote access connections. -// Only used for local testing until the DPanel UI supports sending remote -// access requests. -BASE_DECLARE_FEATURE(kForceCrdAdminRemoteAccess); - // Enable to allow FrameSinkDesktopCapturer to be used for CRD video streaming. BASE_DECLARE_FEATURE(kEnableFrameSinkDesktopCapturerInCrd);
diff --git a/services/device/public/cpp/geolocation/geolocation_manager.cc b/services/device/public/cpp/geolocation/geolocation_manager.cc index 8774e41..15a0d940 100644 --- a/services/device/public/cpp/geolocation/geolocation_manager.cc +++ b/services/device/public/cpp/geolocation/geolocation_manager.cc
@@ -47,6 +47,14 @@ #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_CHROMEOS) +void GeolocationManager::AppAttemptsToUseGeolocation() { + system_geolocation_source_->AppAttemptsToUseGeolocation(); +} + +void GeolocationManager::AppCeasesToUseGeolocation() { + system_geolocation_source_->AppCeasesToUseGeolocation(); +} + GeolocationManager::GeolocationManager( std::unique_ptr<SystemGeolocationSource> system_geolocation_source) : system_geolocation_source_(std::move(system_geolocation_source)), @@ -97,18 +105,16 @@ return observers_; } -void GeolocationManager::AppAttemptsToUseGeolocation() { - system_geolocation_source_->AppAttemptsToUseGeolocation(); -} - -void GeolocationManager::AppCeasesToUseGeolocation() { - system_geolocation_source_->AppCeasesToUseGeolocation(); -} - SystemGeolocationSource& GeolocationManager::SystemGeolocationSourceForTest() { return *system_geolocation_source_; } +#else + +void GeolocationManager::AppAttemptsToUseGeolocation() {} + +void GeolocationManager::AppCeasesToUseGeolocation() {} + #endif } // namespace device
diff --git a/services/device/public/cpp/geolocation/geolocation_manager.h b/services/device/public/cpp/geolocation/geolocation_manager.h index 796840c6..3550912e 100644 --- a/services/device/public/cpp/geolocation/geolocation_manager.h +++ b/services/device/public/cpp/geolocation/geolocation_manager.h
@@ -33,6 +33,9 @@ // Sets the global instance of the Geolocation Manager. static void SetInstance(std::unique_ptr<GeolocationManager> manager); + void AppAttemptsToUseGeolocation(); + void AppCeasesToUseGeolocation(); + #if !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_CHROMEOS) // Default empty implementation of Geolocation Manager. It is used on operation // systems for which we don't support system-level geolocation. A separate class @@ -77,9 +80,6 @@ // Returns the list of permission observers. scoped_refptr<PermissionObserverList> GetObserverList() const; - void AppAttemptsToUseGeolocation(); - void AppCeasesToUseGeolocation(); - #if BUILDFLAG(IS_APPLE) // Starts the system level process for watching position updates. These // updates will trigger a call to and observers in the |position_observers_|
diff --git a/services/network/cookie_settings.h b/services/network/cookie_settings.h index 3db52b6..c15cf6f 100644 --- a/services/network/cookie_settings.h +++ b/services/network/cookie_settings.h
@@ -17,6 +17,7 @@ #include "net/base/network_delegate.h" #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_setting_override.h" +#include "net/cookies/cookie_util.h" #include "net/first_party_sets/first_party_set_metadata.h" #include "services/network/public/cpp/session_cookie_delete_predicate.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -247,7 +248,8 @@ const GURL& first_party_url) const; ContentSettingsForOneType content_settings_; - bool block_third_party_cookies_ = false; + bool block_third_party_cookies_ = + net::cookie_util::IsForceThirdPartyCookieBlockingEnabled(); std::set<std::string> secure_origin_cookies_allowed_schemes_; std::set<std::string> matching_scheme_cookies_allowed_schemes_; std::set<std::string> third_party_cookies_allowed_schemes_;
diff --git a/services/network/cookie_settings_unittest.cc b/services/network/cookie_settings_unittest.cc index 384ea9b9..a53131c0 100644 --- a/services/network/cookie_settings_unittest.cc +++ b/services/network/cookie_settings_unittest.cc
@@ -5,6 +5,7 @@ #include "services/network/cookie_settings.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "components/content_settings/core/common/content_settings.h" #include "net/base/features.h" @@ -1288,6 +1289,15 @@ EXPECT_THAT(excluded_cookies, IsEmpty()); } +TEST_P(CookieSettingsTest, ForceThirdPartyCookieBlocking) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + net::features::kForceThirdPartyCookieBlocking); + + CookieSettings settings; + EXPECT_TRUE(settings.are_third_party_cookies_blocked()); +} + INSTANTIATE_TEST_SUITE_P( /* no prefix */, CookieSettingsTest,
diff --git a/services/network/public/cpp/network_switches.cc b/services/network/public/cpp/network_switches.cc index 38cab2d..c1f7f6ef 100644 --- a/services/network/public/cpp/network_switches.cc +++ b/services/network/public/cpp/network_switches.cc
@@ -6,6 +6,8 @@ namespace network::switches { +const char kBlockThirdPartyCookies[] = "block-third-party-cookies"; + // Forces Network Quality Estimator (NQE) to return a specific effective // connection type. const char kForceEffectiveConnectionType[] = "force-effective-connection-type";
diff --git a/services/network/public/cpp/network_switches.h b/services/network/public/cpp/network_switches.h index cd7b482..3b3f067 100644 --- a/services/network/public/cpp/network_switches.h +++ b/services/network/public/cpp/network_switches.h
@@ -11,6 +11,7 @@ namespace switches { +COMPONENT_EXPORT(NETWORK_CPP) extern const char kBlockThirdPartyCookies[]; COMPONENT_EXPORT(NETWORK_CPP) extern const char kForceEffectiveConnectionType[]; COMPONENT_EXPORT(NETWORK_CPP) extern const char kHostResolverRules[];
diff --git a/testing/buildbot/chromium.devtools-frontend.json b/testing/buildbot/chromium.devtools-frontend.json index 9d7a2cc..ac8cf94 100644 --- a/testing/buildbot/chromium.devtools-frontend.json +++ b/testing/buildbot/chromium.devtools-frontend.json
@@ -116,36 +116,6 @@ "shards": 7 }, "test_id_prefix": "ninja://:blink_wpt_tests/" - }, - { - "args": [ - "--num-retries=3", - "--layout-tests-directory=../../third_party/devtools-frontend/src/test/webtests/", - "http/tests/devtools" - ], - "isolate_name": "devtools_web_tests", - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "webkit_layout_from_devtools", - "resultdb": { - "enable": true - }, - "results_handler": "layout tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Ubuntu-18.04" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 4 - }, - "test_id_prefix": "ninja://:devtools_web_tests/" } ] }
diff --git a/testing/buildbot/client.devtools-frontend.integration.json b/testing/buildbot/client.devtools-frontend.integration.json index 897a801e..bb8c8c1 100644 --- a/testing/buildbot/client.devtools-frontend.integration.json +++ b/testing/buildbot/client.devtools-frontend.integration.json
@@ -104,36 +104,6 @@ "shards": 7 }, "test_id_prefix": "ninja://:blink_wpt_tests/" - }, - { - "args": [ - "--num-retries=3", - "--layout-tests-directory=../../third_party/devtools-frontend/src/test/webtests/", - "http/tests/devtools" - ], - "isolate_name": "devtools_web_tests", - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "webkit_layout_from_devtools", - "resultdb": { - "enable": true - }, - "results_handler": "layout tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Ubuntu-18.04" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 4 - }, - "test_id_prefix": "ninja://:devtools_web_tests/" } ] }, @@ -240,36 +210,6 @@ "shards": 7 }, "test_id_prefix": "ninja://:blink_wpt_tests/" - }, - { - "args": [ - "--num-retries=3", - "--layout-tests-directory=../../third_party/devtools-frontend/src/test/webtests/", - "http/tests/devtools" - ], - "isolate_name": "devtools_web_tests", - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "webkit_layout_from_devtools", - "resultdb": { - "enable": true - }, - "results_handler": "layout tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Ubuntu-18.04" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 4 - }, - "test_id_prefix": "ninja://:devtools_web_tests/" } ] }
diff --git a/testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter b/testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter index 89f8bf9..dc5b42d 100644 --- a/testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter +++ b/testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter
@@ -130,3 +130,6 @@ # TODO(b/256212431): Re-enable when linux-lacros-rel support # signin::MakePrimaryAccountAvailable(). -AccessCodeCastHandlerBrowserTest.ExpectProfileSynErrorWhenNoSync + +# TODO(1447067): Autofill account migration popup, investigate the flakiness +-MigrateToProfileAddressProfileTest.SaveWithEdit
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index c22943e..566f4b93 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -207,14 +207,6 @@ "label": "//android_webview/support_library/boundary_interfaces:boundary_interface_example_apk", "type": "additional_compile_target", }, - "devtools_web_tests": { - "label": "//:devtools_web_tests", - "type": "generated_script", - "args": [ - "--results-directory", - "${ISOLATED_OUTDIR}", - ], - }, "boringssl_crypto_tests": { "label": "//third_party/boringssl:boringssl_crypto_tests", "type": "console_test_launcher",
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 82f2a42e..075d433 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -2036,31 +2036,6 @@ 'shards': 7, } }, - 'webkit_layout_from_devtools': { - # TODO(crbug.com/816629) - Move these args into //BUILD.gn . - # layout test failures are retried 3 times when '--test-list' is not - # passed, but 0 times when '--test-list' is passed. We want to always - # retry 3 times, so we explicitly specify it. - 'args': [ - '--num-retries=3', - '--layout-tests-directory=../../third_party/devtools-frontend/src/test/webtests/', - 'http/tests/devtools', - ], - 'isolate_name': 'devtools_web_tests', - 'merge': { - 'args': [ - '--verbose', - ], - 'script': '//third_party/blink/tools/merge_web_test_results.py', - }, - 'resultdb': { - 'enable': True, - }, - 'results_handler': 'layout tests', - 'swarming': { - 'shards': 4, - } - }, }, 'devtools_webkit_isolated_scripts': { @@ -2118,31 +2093,6 @@ 'shards': 7, } }, - 'webkit_layout_from_devtools': { - # TODO(crbug.com/816629) - Move these args into //BUILD.gn . - # layout test failures are retried 3 times when '--test-list' is not - # passed, but 0 times when '--test-list' is passed. We want to always - # retry 3 times, so we explicitly specify it. - 'args': [ - '--num-retries=3', - '--layout-tests-directory=../../third_party/devtools-frontend/src/test/webtests/', - 'http/tests/devtools', - ], - 'isolate_name': 'devtools_web_tests', - 'merge': { - 'args': [ - '--verbose', - ], - 'script': '//third_party/blink/tools/merge_web_test_results.py', - }, - 'resultdb': { - 'enable': True, - }, - 'results_handler': 'layout tests', - 'swarming': { - 'shards': 4, - } - }, }, 'fieldtrial_android_tests': {
diff --git a/testing/buildbot/tryserver.devtools-frontend.json b/testing/buildbot/tryserver.devtools-frontend.json index c6f6724..76571be 100644 --- a/testing/buildbot/tryserver.devtools-frontend.json +++ b/testing/buildbot/tryserver.devtools-frontend.json
@@ -55,36 +55,6 @@ "shards": 2 }, "test_id_prefix": "ninja://:blink_web_tests/" - }, - { - "args": [ - "--num-retries=3", - "--layout-tests-directory=../../third_party/devtools-frontend/src/test/webtests/", - "http/tests/devtools" - ], - "isolate_name": "devtools_web_tests", - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "webkit_layout_from_devtools", - "resultdb": { - "enable": true - }, - "results_handler": "layout tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Ubuntu-18.04" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 4 - }, - "test_id_prefix": "ninja://:devtools_web_tests/" } ] }, @@ -142,36 +112,6 @@ "shards": 2 }, "test_id_prefix": "ninja://:blink_web_tests/" - }, - { - "args": [ - "--num-retries=3", - "--layout-tests-directory=../../third_party/devtools-frontend/src/test/webtests/", - "http/tests/devtools" - ], - "isolate_name": "devtools_web_tests", - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "webkit_layout_from_devtools", - "resultdb": { - "enable": true - }, - "results_handler": "layout tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Ubuntu-18.04" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 4 - }, - "test_id_prefix": "ninja://:devtools_web_tests/" } ] }, @@ -236,36 +176,6 @@ "shards": 7 }, "test_id_prefix": "ninja://:blink_wpt_tests/" - }, - { - "args": [ - "--num-retries=3", - "--layout-tests-directory=../../third_party/devtools-frontend/src/test/webtests/", - "http/tests/devtools" - ], - "isolate_name": "devtools_web_tests", - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "webkit_layout_from_devtools", - "resultdb": { - "enable": true - }, - "results_handler": "layout tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Ubuntu-18.04" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 4 - }, - "test_id_prefix": "ninja://:devtools_web_tests/" } ] }
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 090af124..549191c 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -10653,7 +10653,7 @@ { "name": "DriftEnabled", "params": { - "ClockDriftSampleDistance": "2s", + "ClockDriftSampleDistance": "3600s", "ClockDriftSamples": "2", "FetchBehavior": "background-and-on-demand", "RandomQueryProbability": "0.0394"
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 39b6563..72e14c2 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -1382,6 +1382,20 @@ string text # Value range in the underlying resource (if available). optional SourceRange range + # Specificity of the selector. + experimental optional Specificity specificity + + # Specificity: + # https://drafts.csswg.org/selectors/#specificity-rules + experimental type Specificity extends object + properties + # The a component, which represents the number of ID selectors. + integer a + # The b component, which represents the number of class selectors, attributes selectors, and + # pseudo-classes. + integer b + # The c component, which represents the number of type selectors and pseudo-elements. + integer c # Selector list data. type SelectorList extends object
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom index 363f0f6..261dbd5 100644 --- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom +++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -3823,7 +3823,7 @@ kExecutedEmptyJavaScriptURLFromFrame = 4483, kExecutedJavaScriptURLFromFrame = 4484, kServiceWorkerBypassFetchHandlerForSubResource = 4485, - kCSSAtRuleInitial = 4486, + kCSSAtRuleStartingStyle = 4486, kPrivateAggregationApiFledgeExtensions = 4487, kDeprecatedInterestGroupDailyUpdateUrl = 4488, kCSSColorGradientColorSpace = 4489,
diff --git a/third_party/blink/renderer/bindings/IDLExtendedAttributes.md b/third_party/blink/renderer/bindings/IDLExtendedAttributes.md index 58a178a..f2e79e1 100644 --- a/third_party/blink/renderer/bindings/IDLExtendedAttributes.md +++ b/third_party/blink/renderer/bindings/IDLExtendedAttributes.md
@@ -1319,44 +1319,11 @@ } ``` -### [CheckSecurity] _(i, m, a)_ +### [CheckSecurity] _(m, a)_ Summary: Check whether a given access is allowed or not in terms of the same-origin security policy. -*** note -It is very important to use this attribute for interfaces and properties that -are exposed cross-origin! -*** - -Usage for interfaces: `[CheckSecurity=Receiver]` enables a security check for -all methods of an interface. The security check verifies that the caller still -has access to the receiver object of the method when it is invoked. This is -security-critical for interfaces that can be returned cross-origin, such as the -Location or Window interface. - -```webidl -[ - CheckSecurity=Receiver -] interface DOMWindow { - Selection? getSelection(); -}; -``` - -Forgetting this attribute would make it possible to cache a method reference and -invoke it on a cross-origin object: - -```js -var iframe = document.body.appendChild(document.createElement('iframe')); -var addEventListenerMethod = iframe.contentWindow.addEventListener; -iframe.src = 'https://example.com'; -iframe.onload = function () { - addEventListenerMethod('pointermove', function (event) { - event.target.ownerDocument.body.innerText = 'Text from a different origin.'; - }); -}; -``` - Usage for attributes and methods: `[CheckSecurity=ReturnValue]` enables a security check on that property. The security check verifies that the caller is allowed to access the returned value. If access is denied, the return value will
diff --git a/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt b/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt index 7848421..0a8a963 100644 --- a/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt +++ b/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt
@@ -38,7 +38,7 @@ CachedAccessor=* CachedAttribute=* CallWith=ExecutionContext|Isolate|ScriptState|ThisValue -CheckSecurity=Receiver|ReturnValue +CheckSecurity=ReturnValue Clamp Constructor ContextEnabled=*
diff --git a/third_party/blink/renderer/bindings/generated_in_core.gni b/third_party/blink/renderer/bindings/generated_in_core.gni index a0efdde..7eb9994 100644 --- a/third_party/blink/renderer/bindings/generated_in_core.gni +++ b/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -695,8 +695,6 @@ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_image_value.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_import_rule.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_import_rule.h", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_initial_rule.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_initial_rule.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_keyframe_rule.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_keyframe_rule.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_keyframes_rule.cc", @@ -761,6 +759,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_skew_x.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_skew_y.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_skew_y.h", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_starting_style_rule.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_starting_style_rule.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_style_declaration.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_style_declaration.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_style_rule.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_core.gni b/third_party/blink/renderer/bindings/idl_in_core.gni index 0c727f2..ad7d76a 100644 --- a/third_party/blink/renderer/bindings/idl_in_core.gni +++ b/third_party/blink/renderer/bindings/idl_in_core.gni
@@ -44,7 +44,6 @@ "//third_party/blink/renderer/core/css/css_font_feature_values_rule.idl", "//third_party/blink/renderer/core/css/css_grouping_rule.idl", "//third_party/blink/renderer/core/css/css_import_rule.idl", - "//third_party/blink/renderer/core/css/css_initial_rule.idl", "//third_party/blink/renderer/core/css/css_keyframe_rule.idl", "//third_party/blink/renderer/core/css/css_keyframes_rule.idl", "//third_party/blink/renderer/core/css/css_layer_block_rule.idl", @@ -57,6 +56,7 @@ "//third_party/blink/renderer/core/css/css_rule.idl", "//third_party/blink/renderer/core/css/css_rule_list.idl", "//third_party/blink/renderer/core/css/css_scope_rule.idl", + "//third_party/blink/renderer/core/css/css_starting_style_rule.idl", "//third_party/blink/renderer/core/css/css_style_declaration.idl", "//third_party/blink/renderer/core/css/css_style_rule.idl", "//third_party/blink/renderer/core/css/css_style_sheet.idl",
diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc index 4f665c3..078a4e2 100644 --- a/third_party/blink/renderer/core/animation/animation.cc +++ b/third_party/blink/renderer/core/animation/animation.cc
@@ -892,6 +892,13 @@ effect->Affects(PropertyHandle(property)); } +AnimationTimeline* Animation::timeline() { + if (AnimationTimeline* timeline = TimelineInternal()) { + return timeline->ExposedTimeline(); + } + return nullptr; +} + void Animation::setTimeline(AnimationTimeline* timeline) { // https://www.w3.org/TR/web-animations-1/#setting-the-timeline @@ -1158,8 +1165,8 @@ new_effect->Attach(this); // Resolve timeline offsets for new effect. - ResolveTimelineOffsets(timeline() ? timeline()->GetTimelineRange() - : TimelineRange()); + ResolveTimelineOffsets(timeline_ ? timeline_->GetTimelineRange() + : TimelineRange()); SetOutdated(); @@ -1960,7 +1967,7 @@ // Set animation's start time to the result of evaluating: // associated effect end - start time bool preserve_current_time = - timeline() && timeline()->IsMonotonicallyIncreasing(); + timeline_ && timeline_->IsMonotonicallyIncreasing(); bool reversal = (EffectivePlaybackRate() < 0) != (playback_rate < 0); pending_playback_rate_ = absl::nullopt; @@ -1970,7 +1977,7 @@ setCurrentTime(previous_current_time, exception_state); } - if (timeline() && !timeline()->IsMonotonicallyIncreasing() && reversal && + if (timeline_ && !timeline_->IsMonotonicallyIncreasing() && reversal && start_time_) { start_time_ = EffectEnd() - start_time_.value(); }
diff --git a/third_party/blink/renderer/core/animation/animation.h b/third_party/blink/renderer/core/animation/animation.h index 96a2204..da57ba7 100644 --- a/third_party/blink/renderer/core/animation/animation.h +++ b/third_party/blink/renderer/core/animation/animation.h
@@ -201,9 +201,16 @@ double playbackRate() const; void setPlaybackRate(double, ExceptionState& = ASSERT_NO_EXCEPTION); - // TODO(crbug.com/1425939): Do not expose DeferredTimelines here. - AnimationTimeline* timeline() { return timeline_; } - AnimationTimeline* timeline() const { return timeline_; } + + AnimationTimeline* TimelineInternal() { return timeline_; } + AnimationTimeline* TimelineInternal() const { return timeline_; } + + // Note that this function returns the *exposed* timeline, which may be + // different from the the timeline the Animation is actually attached to. + // + // See AnimationTimeline::ExposedTimeline. + AnimationTimeline* timeline(); + virtual void setTimeline(AnimationTimeline* timeline); // Animation options for ViewTimelines.
diff --git a/third_party/blink/renderer/core/animation/animation_effect.cc b/third_party/blink/renderer/core/animation/animation_effect.cc index fb0ee51f..40f2e43c 100644 --- a/third_party/blink/renderer/core/animation/animation_effect.cc +++ b/third_party/blink/renderer/core/animation/animation_effect.cc
@@ -67,7 +67,7 @@ AnimationTimeDelta AnimationEffect::IntrinsicIterationDuration() const { if (auto* animation = GetAnimation()) { - auto* timeline = animation->timeline(); + auto* timeline = animation->TimelineInternal(); if (timeline) { return timeline->CalculateIntrinsicIterationDuration(animation, timing_); } @@ -259,8 +259,8 @@ void AnimationEffect::updateTiming(OptionalEffectTiming* optional_timing, ExceptionState& exception_state) { - if (GetAnimation() && GetAnimation()->timeline() && - GetAnimation()->timeline()->IsProgressBased()) { + if (GetAnimation() && GetAnimation()->TimelineInternal() && + GetAnimation()->TimelineInternal()->IsProgressBased()) { if (optional_timing->hasDuration()) { if (optional_timing->duration()->IsUnrestrictedDouble()) { double duration =
diff --git a/third_party/blink/renderer/core/animation/animation_test.cc b/third_party/blink/renderer/core/animation/animation_test.cc index 3e9577e..5793221 100644 --- a/third_party/blink/renderer/core/animation/animation_test.cc +++ b/third_party/blink/renderer/core/animation/animation_test.cc
@@ -2467,7 +2467,7 @@ // The no-effect animation doesn't count. The one animation is // AnimationAnimationTestCompositing::animation_. - EXPECT_EQ(1u, animation->timeline()->AnimationsNeedingUpdateCount()); + EXPECT_EQ(1u, animation->TimelineInternal()->AnimationsNeedingUpdateCount()); // The next effect change should be at the end because the animation does not // tick while hidden. @@ -2485,7 +2485,7 @@ CompositorAnimations::kNoFailure); EXPECT_FALSE(animation->CompositorPropertyAnimationsHaveNoEffectForTesting()); EXPECT_FALSE(animation->AnimationHasNoEffect()); - EXPECT_EQ(2u, animation->timeline()->AnimationsNeedingUpdateCount()); + EXPECT_EQ(2u, animation->TimelineInternal()->AnimationsNeedingUpdateCount()); // The next effect change should be at the end because the animation is // running on the compositor.
diff --git a/third_party/blink/renderer/core/animation/animation_timeline.h b/third_party/blink/renderer/core/animation/animation_timeline.h index b21a1e6e..1df4d69 100644 --- a/third_party/blink/renderer/core/animation/animation_timeline.h +++ b/third_party/blink/renderer/core/animation/animation_timeline.h
@@ -58,6 +58,10 @@ virtual bool IsScrollTimeline() const { return false; } virtual bool IsViewTimeline() const { return false; } + // Determines which AnimationTimeline instance we should return + // from Animation.timeline. + virtual AnimationTimeline* ExposedTimeline() { return this; } + virtual bool IsActive() const = 0; virtual bool IsResolved() const { return true; } virtual AnimationTimeDelta ZeroTime() = 0;
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc index c3fafb2d..6cadd1ed 100644 --- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc +++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -2372,7 +2372,7 @@ EXPECT_TRUE(animation.GetCompositorAnimation()); cc::AnimationTimeline* compositor_timeline = - animation.timeline()->CompositorTimeline(); + animation.TimelineInternal()->CompositorTimeline(); ASSERT_TRUE(compositor_timeline); int id = compositor_timeline->id(); ASSERT_TRUE(host->GetTimelineById(id));
diff --git a/third_party/blink/renderer/core/animation/css/css_animations.cc b/third_party/blink/renderer/core/animation/css/css_animations.cc index e094100..648e630 100644 --- a/third_party/blink/renderer/core/animation/css/css_animations.cc +++ b/third_party/blink/renderer/core/animation/css/css_animations.cc
@@ -199,7 +199,7 @@ // In most cases, current time is preserved on an animation update. inherited_time = animation->UnlimitedCurrentTime(); - previous_timeline = animation->timeline(); + previous_timeline = animation->TimelineInternal(); resets_current_time_on_resume = animation->ResetsCurrentTimeOnResume(); } @@ -1413,14 +1413,14 @@ if (!element) return nullptr; const TimelineData* timeline_data = GetTimelineData(*element); - if (ViewTimeline* timeline = - FindTimelineForElement<ViewTimeline>(name, timeline_data, update)) { - return timeline; - } if (ScrollTimeline* timeline = FindTimelineForElement<ScrollTimeline>(name, timeline_data, update)) { return timeline; } + if (ViewTimeline* timeline = + FindTimelineForElement<ViewTimeline>(name, timeline_data, update)) { + return timeline; + } return FindTimelineForElement<DeferredTimeline>(name, timeline_data, update); } @@ -2209,7 +2209,7 @@ effect->UpdateSpecifiedTiming(entry.effect->SpecifiedTiming()); } CSSAnimation& css_animation = To<CSSAnimation>(*entry.animation); - if (css_animation.timeline() != entry.timeline) { + if (css_animation.TimelineInternal() != entry.timeline) { css_animation.setTimeline(entry.timeline); css_animation.ResetIgnoreCSSTimeline(); } @@ -2705,11 +2705,11 @@ << "Should always pass nullptr instead of ensured styles"; const ComputedStyle* scope_old_style = PostStyleUpdateScope::GetOldStyle(animating_element); - bool is_initial_style = old_style && old_style->IsPseudoInitialStyle(); - DCHECK(old_style == scope_old_style || !scope_old_style && is_initial_style) + bool is_starting_style = old_style && old_style->IsStartingStyle(); + DCHECK(old_style == scope_old_style || !scope_old_style && is_starting_style) << "The old_style passed in should be the style for the element at the " - "beginning of the lifecycle update, or a style based on the :initial " - "style"; + "beginning of the lifecycle update, or a style based on the " + "@starting-style style"; #endif if (!animation_style_recalc && old_style) {
diff --git a/third_party/blink/renderer/core/animation/css/css_animations.h b/third_party/blink/renderer/core/animation/css/css_animations.h index d67ca7b..006898d 100644 --- a/third_party/blink/renderer/core/animation/css/css_animations.h +++ b/third_party/blink/renderer/core/animation/css/css_animations.h
@@ -154,7 +154,9 @@ style_rule_version(new_animation.style_rule_version), play_state_list(new_animation.play_state_list) {} - AnimationTimeline* Timeline() const { return animation->timeline(); } + AnimationTimeline* Timeline() const { + return animation->TimelineInternal(); + } const absl::optional<TimelineOffset>& RangeStart() const { return animation->GetRangeStartInternal(); }
diff --git a/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc b/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc index 49346e45..3454f71 100644 --- a/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc +++ b/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc
@@ -96,16 +96,22 @@ // The animations associated with anim1 and anim2 should share the same // timeline instance, also across elements. - EXPECT_EQ(animations1[0]->timeline(), animations1[1]->timeline()); - EXPECT_EQ(animations1[1]->timeline(), animations2[0]->timeline()); - EXPECT_EQ(animations2[0]->timeline(), animations2[1]->timeline()); + EXPECT_EQ(animations1[0]->TimelineInternal(), + animations1[1]->TimelineInternal()); + EXPECT_EQ(animations1[1]->TimelineInternal(), + animations2[0]->TimelineInternal()); + EXPECT_EQ(animations2[0]->TimelineInternal(), + animations2[1]->TimelineInternal()); // The animation associated with anim3 uses a different timeline // from anim1/2. - EXPECT_EQ(animations1[2]->timeline(), animations2[2]->timeline()); + EXPECT_EQ(animations1[2]->TimelineInternal(), + animations2[2]->TimelineInternal()); - EXPECT_NE(animations2[2]->timeline(), animations1[0]->timeline()); - EXPECT_NE(animations2[2]->timeline(), animations1[1]->timeline()); + EXPECT_NE(animations2[2]->TimelineInternal(), + animations1[0]->TimelineInternal()); + EXPECT_NE(animations2[2]->TimelineInternal(), + animations1[1]->TimelineInternal()); } TEST_F(CSSScrollTimelineTest, MultipleLifecyclePasses) { @@ -228,7 +234,8 @@ absl::optional<ScrollTimeline::ScrollAxis> GetTimelineAxis( const Animation& animation) { - if (auto* scroll_timeline = DynamicTo<ScrollTimeline>(animation.timeline())) { + if (auto* scroll_timeline = + DynamicTo<ScrollTimeline>(animation.TimelineInternal())) { return scroll_timeline->GetAxis(); } return absl::nullopt;
diff --git a/third_party/blink/renderer/core/animation/deferred_timeline.h b/third_party/blink/renderer/core/animation/deferred_timeline.h index 1a0093a..7169252 100644 --- a/third_party/blink/renderer/core/animation/deferred_timeline.h +++ b/third_party/blink/renderer/core/animation/deferred_timeline.h
@@ -17,6 +17,10 @@ public: explicit DeferredTimeline(Document*); + AnimationTimeline* ExposedTimeline() override { + return SingleAttachedTimeline(); + } + void AttachTimeline(ScrollSnapshotTimeline*); void DetachTimeline(ScrollSnapshotTimeline*);
diff --git a/third_party/blink/renderer/core/animation/keyframe_effect.cc b/third_party/blink/renderer/core/animation/keyframe_effect.cc index 50a7ac5..d4e70ff 100644 --- a/third_party/blink/renderer/core/animation/keyframe_effect.cc +++ b/third_party/blink/renderer/core/animation/keyframe_effect.cc
@@ -302,7 +302,7 @@ ScriptState* script_state) { if (Animation* animation = GetAnimation()) { animation->FlushPendingUpdates(); - if (AnimationTimeline* timeline = animation->timeline()) { + if (AnimationTimeline* timeline = animation->TimelineInternal()) { animation->ResolveTimelineOffsets(timeline->GetTimelineRange()); } } @@ -775,8 +775,8 @@ } absl::optional<AnimationTimeDelta> KeyframeEffect::TimelineDuration() const { - if (GetAnimation() && GetAnimation()->timeline()) { - return GetAnimation()->timeline()->GetDuration(); + if (GetAnimation() && GetAnimation()->TimelineInternal()) { + return GetAnimation()->TimelineInternal()->GetDuration(); } return absl::nullopt; }
diff --git a/third_party/blink/renderer/core/animation/pending_animations.cc b/third_party/blink/renderer/core/animation/pending_animations.cc index 5f641693..7441621 100644 --- a/third_party/blink/renderer/core/animation/pending_animations.cc +++ b/third_party/blink/renderer/core/animation/pending_animations.cc
@@ -81,19 +81,22 @@ started_synchronized_on_compositor = true; } - if (!animation->timeline() || !animation->timeline()->IsActive()) + if (!animation->TimelineInternal() || + !animation->TimelineInternal()->IsActive()) { continue; + } if (animation->Playing() && !animation->StartTimeInternal()) { waiting_for_start_time.push_back(animation.Get()); } else if (animation->PendingInternal()) { - DCHECK(animation->timeline()->IsActive() && - animation->timeline()->CurrentTime()); + DCHECK(animation->TimelineInternal()->IsActive() && + animation->TimelineInternal()->CurrentTime()); // A pending animation that is not waiting on a start time does not need // to be synchronized with animations that are starting up. Nonetheless, // it needs to notify the animation to resolve the ready promise and // commit the pending state. - animation->NotifyReady(animation->timeline()->CurrentTime().value()); + animation->NotifyReady( + animation->TimelineInternal()->CurrentTime().value()); } } else { deferred.push_back(animation); @@ -110,9 +113,10 @@ } else { for (auto& animation : waiting_for_start_time) { DCHECK(!animation->StartTimeInternal()); - DCHECK(animation->timeline()->IsActive() && - animation->timeline()->CurrentTime()); - animation->NotifyReady(animation->timeline()->CurrentTime().value()); + DCHECK(animation->TimelineInternal()->IsActive() && + animation->TimelineInternal()->CurrentTime()); + animation->NotifyReady( + animation->TimelineInternal()->CurrentTime().value()); } } @@ -156,7 +160,8 @@ for (auto animation : animations) { if (animation->StartTimeInternal() || !animation->PendingInternal() || - !animation->timeline() || !animation->timeline()->IsActive()) { + !animation->TimelineInternal() || + !animation->TimelineInternal()->IsActive()) { // Already started or no longer relevant. continue; } @@ -165,13 +170,14 @@ waiting_for_compositor_animation_start_.push_back(animation); continue; } - if (!animation->timeline()->IsMonotonicallyIncreasing()) { + if (!animation->TimelineInternal()->IsMonotonicallyIncreasing()) { animation->NotifyReady( - animation->timeline()->CurrentTime().value_or(AnimationTimeDelta())); + animation->TimelineInternal()->CurrentTime().value_or( + AnimationTimeDelta())); } else { animation->NotifyReady( ANIMATION_TIME_DELTA_FROM_SECONDS(monotonic_animation_start_time) - - animation->timeline()->ZeroTime()); + animation->TimelineInternal()->ZeroTime()); } } } @@ -200,9 +206,11 @@ for (auto& animation : animations) { if (animation->HasActiveAnimationsOnCompositor()) { waiting_for_compositor_animation_start_.push_back(animation); - } else if (animation->timeline() && animation->timeline()->IsActive() && - animation->timeline()->CurrentTime().has_value()) { - animation->NotifyReady(animation->timeline()->CurrentTime().value()); + } else if (animation->TimelineInternal() && + animation->TimelineInternal()->IsActive() && + animation->TimelineInternal()->CurrentTime().has_value()) { + animation->NotifyReady( + animation->TimelineInternal()->CurrentTime().value()); } } }
diff --git a/third_party/blink/renderer/core/css/build.gni b/third_party/blink/renderer/core/css/build.gni index 08dadd5..af4ee00 100644 --- a/third_party/blink/renderer/core/css/build.gni +++ b/third_party/blink/renderer/core/css/build.gni
@@ -165,8 +165,6 @@ "css_inherited_value.h", "css_initial_color_value.cc", "css_initial_color_value.h", - "css_initial_rule.cc", - "css_initial_rule.h", "css_initial_value.cc", "css_initial_value.h", "css_invalid_variable_value.cc", @@ -263,6 +261,8 @@ "css_selector_watch.h", "css_shadow_value.cc", "css_shadow_value.h", + "css_starting_style_rule.cc", + "css_starting_style_rule.h", "css_string_value.cc", "css_string_value.h", "css_style_declaration.cc",
diff --git a/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc b/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc index 1719623e..563d818 100644 --- a/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc +++ b/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc
@@ -206,4 +206,52 @@ WebFeature::kCSSGetComputedWebkitFontSmoothingAnimationDurationZero)); } +TEST_F(CSSComputedStyleDeclarationTest, ScrollTimelineShorthandWithAttachment) { + { + ScopedScrollTimelineAttachmentForTest enabled(false); + GetDocument().body()->SetInlineStyleProperty(CSSPropertyID::kScrollTimeline, + "--foo inline"); + UpdateAllLifecyclePhasesForTest(); + auto* style = + MakeGarbageCollected<CSSComputedStyleDeclaration>(GetDocument().body()); + EXPECT_EQ("--foo inline", + style->GetPropertyValue(CSSPropertyID::kScrollTimeline)); + } + + { + ScopedScrollTimelineAttachmentForTest enabled(true); + GetDocument().body()->SetInlineStyleProperty(CSSPropertyID::kScrollTimeline, + "--foo inline defer"); + UpdateAllLifecyclePhasesForTest(); + auto* style = + MakeGarbageCollected<CSSComputedStyleDeclaration>(GetDocument().body()); + EXPECT_EQ("--foo inline defer", + style->GetPropertyValue(CSSPropertyID::kScrollTimeline)); + } +} + +TEST_F(CSSComputedStyleDeclarationTest, ViewTimelineShorthandWithAttachment) { + { + ScopedScrollTimelineAttachmentForTest enabled(false); + GetDocument().body()->SetInlineStyleProperty(CSSPropertyID::kViewTimeline, + "--foo inline"); + UpdateAllLifecyclePhasesForTest(); + auto* style = + MakeGarbageCollected<CSSComputedStyleDeclaration>(GetDocument().body()); + EXPECT_EQ("--foo inline", + style->GetPropertyValue(CSSPropertyID::kViewTimeline)); + } + + { + ScopedScrollTimelineAttachmentForTest enabled(true); + GetDocument().body()->SetInlineStyleProperty(CSSPropertyID::kViewTimeline, + "--foo inline defer"); + UpdateAllLifecyclePhasesForTest(); + auto* style = + MakeGarbageCollected<CSSComputedStyleDeclaration>(GetDocument().body()); + EXPECT_EQ("--foo inline defer", + style->GetPropertyValue(CSSPropertyID::kViewTimeline)); + } +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_initial_rule.h b/third_party/blink/renderer/core/css/css_initial_rule.h deleted file mode 100644 index e10d416e..0000000 --- a/third_party/blink/renderer/core/css/css_initial_rule.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_INITIAL_RULE_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_INITIAL_RULE_H_ - -#include "third_party/blink/renderer/core/css/css_condition_rule.h" -#include "third_party/blink/renderer/platform/wtf/casting.h" - -namespace blink { - -class StyleRuleInitial; - -class CSSInitialRule final : public CSSConditionRule { - DEFINE_WRAPPERTYPEINFO(); - - public: - CSSInitialRule(StyleRuleInitial*, CSSStyleSheet*); - ~CSSInitialRule() override = default; - - String cssText() const override; - - private: - CSSRule::Type GetType() const override { return kInitialRule; } -}; - -template <> -struct DowncastTraits<CSSInitialRule> { - static bool AllowFrom(const CSSRule& rule) { - return rule.GetType() == CSSRule::kInitialRule; - } -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_INITIAL_RULE_H_
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5 index 73cbb11b..d0fe5b7 100644 --- a/third_party/blink/renderer/core/css/css_properties.json5 +++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -4561,7 +4561,7 @@ type_name: "Vector<TimelineAttachment>", converter: "ConvertViewTimelineAttachment", separator: ",", - runtime_flag: "ScrollTimeline", + runtime_flag: "ScrollTimelineAttachment", }, { name: "scroll-timeline-axis", @@ -5345,7 +5345,7 @@ type_name: "Vector<TimelineAttachment>", converter: "ConvertViewTimelineAttachment", separator: ",", - runtime_flag: "ScrollTimeline", + runtime_flag: "ScrollTimelineAttachment", }, { name: "view-timeline-axis",
diff --git a/third_party/blink/renderer/core/css/css_property_value_set_test.cc b/third_party/blink/renderer/core/css/css_property_value_set_test.cc index 91f5744..6ba42458 100644 --- a/third_party/blink/renderer/core/css/css_property_value_set_test.cc +++ b/third_party/blink/renderer/core/css/css_property_value_set_test.cc
@@ -84,8 +84,8 @@ StyleRule* rule = RuleAt(style_sheet, 0); EXPECT_EQ( - "offset-position: initial; offset-distance: initial; " - "offset-rotate: reverse 2turn; offset-anchor: initial; " + "offset-position: auto; offset-distance: 0px; " + "offset-rotate: reverse 2turn; offset-anchor: auto; " "offset-path: initial;", rule->Properties().AsText()); }
diff --git a/third_party/blink/renderer/core/css/css_rule.h b/third_party/blink/renderer/core/css/css_rule.h index ca20dce..764ba2a 100644 --- a/third_party/blink/renderer/core/css/css_rule.h +++ b/third_party/blink/renderer/core/css/css_rule.h
@@ -79,7 +79,7 @@ kPositionFallbackRule = 22, kTryRule = 23, kFontFeatureRule = 24, - kInitialRule = 25, + kStartingStyleRule = 25, }; virtual Type GetType() const = 0;
diff --git a/third_party/blink/renderer/core/css/css_selector.cc b/third_party/blink/renderer/core/css/css_selector.cc index a27aa87..c9d836b 100644 --- a/third_party/blink/renderer/core/css/css_selector.cc +++ b/third_party/blink/renderer/core/css/css_selector.cc
@@ -96,14 +96,8 @@ } unsigned CSSSelector::Specificity() const { - // make sure the result doesn't overflow - static const unsigned kMaxValueMask = 0xffffff; - static const unsigned kIdMask = 0xff0000; - static const unsigned kClassMask = 0x00ff00; - static const unsigned kElementMask = 0x0000ff; - if (IsForPage()) { - return SpecificityForPage() & kMaxValueMask; + return SpecificityForPage() & CSSSelector::kMaxValueMask; } unsigned total = 0; @@ -126,6 +120,16 @@ return total; } +std::array<uint8_t, 3> CSSSelector::SpecificityTuple() const { + unsigned specificity = Specificity(); + + uint8_t a = (specificity & kIdMask) >> 16; + uint8_t b = (specificity & kClassMask) >> 8; + uint8_t c = (specificity & kElementMask); + + return {a, b, c}; +} + inline unsigned CSSSelector::SpecificityForOneSelector() const { // FIXME: Pseudo-elements and pseudo-classes do not have the same specificity. // This function isn't quite correct.
diff --git a/third_party/blink/renderer/core/css/css_selector.h b/third_party/blink/renderer/core/css/css_selector.h index 95d637cd..ab38689b 100644 --- a/third_party/blink/renderer/core/css/css_selector.h +++ b/third_party/blink/renderer/core/css/css_selector.h
@@ -130,9 +130,16 @@ static constexpr unsigned kClassLikeSpecificity = 0x000100; static constexpr unsigned kTagSpecificity = 0x000001; + static constexpr unsigned kMaxValueMask = 0xffffff; + static constexpr unsigned kIdMask = 0xff0000; + static constexpr unsigned kClassMask = 0x00ff00; + static constexpr unsigned kElementMask = 0x0000ff; + // http://www.w3.org/TR/css3-selectors/#specificity // We use 256 as the base of the specificity number system. unsigned Specificity() const; + // Returns specificity components in decreasing order of significance. + std::array<uint8_t, 3> SpecificityTuple() const; /* how the attribute value has to match.... Default is Exact */ enum MatchType {
diff --git a/third_party/blink/renderer/core/css/css_initial_rule.cc b/third_party/blink/renderer/core/css/css_starting_style_rule.cc similarity index 61% rename from third_party/blink/renderer/core/css/css_initial_rule.cc rename to third_party/blink/renderer/core/css/css_starting_style_rule.cc index 6e17545..1923d01e 100644 --- a/third_party/blink/renderer/core/css/css_initial_rule.cc +++ b/third_party/blink/renderer/core/css/css_starting_style_rule.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/core/css/css_initial_rule.h" +#include "third_party/blink/renderer/core/css/css_starting_style_rule.h" #include "third_party/blink/renderer/core/css/css_rule.h" #include "third_party/blink/renderer/core/css/css_style_sheet.h" @@ -11,14 +11,15 @@ namespace blink { -CSSInitialRule::CSSInitialRule(StyleRuleInitial* initial_rule, - CSSStyleSheet* parent) - : CSSConditionRule(initial_rule, parent) {} +CSSStartingStyleRule::CSSStartingStyleRule( + StyleRuleStartingStyle* starting_style_rule, + CSSStyleSheet* parent) + : CSSConditionRule(starting_style_rule, parent) {} -String CSSInitialRule::cssText() const { +String CSSStartingStyleRule::cssText() const { StringBuilder result; - result.Append("@initial "); + result.Append("@starting-style "); AppendCSSTextForItems(result); return result.ReleaseString();
diff --git a/third_party/blink/renderer/core/css/css_starting_style_rule.h b/third_party/blink/renderer/core/css/css_starting_style_rule.h new file mode 100644 index 0000000..fdb2917 --- /dev/null +++ b/third_party/blink/renderer/core/css/css_starting_style_rule.h
@@ -0,0 +1,37 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_STARTING_STYLE_RULE_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_STARTING_STYLE_RULE_H_ + +#include "third_party/blink/renderer/core/css/css_condition_rule.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" + +namespace blink { + +class StyleRuleStartingStyle; + +class CSSStartingStyleRule final : public CSSConditionRule { + DEFINE_WRAPPERTYPEINFO(); + + public: + CSSStartingStyleRule(StyleRuleStartingStyle*, CSSStyleSheet*); + ~CSSStartingStyleRule() override = default; + + String cssText() const override; + + private: + CSSRule::Type GetType() const override { return kStartingStyleRule; } +}; + +template <> +struct DowncastTraits<CSSStartingStyleRule> { + static bool AllowFrom(const CSSRule& rule) { + return rule.GetType() == CSSRule::kStartingStyleRule; + } +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_STARTING_STYLE_RULE_H_
diff --git a/third_party/blink/renderer/core/css/css_initial_rule.idl b/third_party/blink/renderer/core/css/css_starting_style_rule.idl similarity index 78% rename from third_party/blink/renderer/core/css/css_initial_rule.idl rename to third_party/blink/renderer/core/css/css_starting_style_rule.idl index e25e88b..f26dd4b8 100644 --- a/third_party/blink/renderer/core/css/css_initial_rule.idl +++ b/third_party/blink/renderer/core/css/css_starting_style_rule.idl
@@ -4,5 +4,5 @@ [ Exposes=Window, RuntimeEnabled = CSSInitialPseudo -] interface CSSInitialRule : CSSConditionRule { +] interface CSSStartingStyleRule : CSSConditionRule { };
diff --git a/third_party/blink/renderer/core/css/css_style_declaration_test.cc b/third_party/blink/renderer/core/css/css_style_declaration_test.cc index 9d176faf..1c523ac7 100644 --- a/third_party/blink/renderer/core/css/css_style_declaration_test.cc +++ b/third_party/blink/renderer/core/css/css_style_declaration_test.cc
@@ -103,4 +103,60 @@ } } +TEST(CSSStyleDeclarationTest, ScrollTimelineShorthandWithAttachment) { + V8TestingScope v8_testing_scope; + + { + ScopedScrollTimelineAttachmentForTest enabled(false); + const CSSPropertyValueSet* set = css_test_helpers::ParseDeclarationBlock( + "scroll-timeline: --foo inline"); + ASSERT_TRUE(set); + auto* style = static_cast<CSSStyleDeclaration*>( + MakeGarbageCollected<PropertySetCSSStyleDeclaration>( + v8_testing_scope.GetExecutionContext(), *set->MutableCopy())); + EXPECT_EQ(AtomicString("--foo inline"), + style->getPropertyValue("scroll-timeline")); + } + + { + ScopedScrollTimelineAttachmentForTest enabled(true); + const CSSPropertyValueSet* set = css_test_helpers::ParseDeclarationBlock( + "scroll-timeline: --foo inline defer"); + ASSERT_TRUE(set); + auto* style = static_cast<CSSStyleDeclaration*>( + MakeGarbageCollected<PropertySetCSSStyleDeclaration>( + v8_testing_scope.GetExecutionContext(), *set->MutableCopy())); + EXPECT_EQ(AtomicString("--foo inline defer"), + style->getPropertyValue("scroll-timeline")); + } +} + +TEST(CSSStyleDeclarationTest, ViewTimelineShorthandWithAttachment) { + V8TestingScope v8_testing_scope; + + { + ScopedScrollTimelineAttachmentForTest enabled(false); + const CSSPropertyValueSet* set = + css_test_helpers::ParseDeclarationBlock("view-timeline: --foo inline"); + ASSERT_TRUE(set); + auto* style = static_cast<CSSStyleDeclaration*>( + MakeGarbageCollected<PropertySetCSSStyleDeclaration>( + v8_testing_scope.GetExecutionContext(), *set->MutableCopy())); + EXPECT_EQ(AtomicString("--foo inline"), + style->getPropertyValue("view-timeline")); + } + + { + ScopedScrollTimelineAttachmentForTest enabled(true); + const CSSPropertyValueSet* set = css_test_helpers::ParseDeclarationBlock( + "view-timeline: --foo inline defer"); + ASSERT_TRUE(set); + auto* style = static_cast<CSSStyleDeclaration*>( + MakeGarbageCollected<PropertySetCSSStyleDeclaration>( + v8_testing_scope.GetExecutionContext(), *set->MutableCopy())); + EXPECT_EQ(AtomicString("--foo inline defer"), + style->getPropertyValue("view-timeline")); + } +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/css/element_rule_collector.cc b/third_party/blink/renderer/core/css/element_rule_collector.cc index fefaf81..3832de1 100644 --- a/third_party/blink/renderer/core/css/element_rule_collector.cc +++ b/third_party/blink/renderer/core/css/element_rule_collector.cc
@@ -472,7 +472,7 @@ selector_statistics_collector.EndCollectionForCurrentRule(); selector_statistics_collector.BeginCollectionForRule(&rule_data); } - if (!is_initial && rule_data.IsInitial()) { + if (!is_initial && rule_data.IsStartingStyle()) { continue; } if (can_use_fast_reject_ && @@ -985,8 +985,9 @@ for (unsigned i = 0; i < matched_rules_.size(); i++) { const MatchedRule& matched_rule = matched_rules_[i]; const RuleData* rule_data = matched_rule.GetRuleData(); - if (rule_data->IsInitial()) { - result_.AddFlags(static_cast<MatchFlags>(MatchFlag::kAffectedByInitial)); + if (rule_data->IsStartingStyle()) { + result_.AddFlags( + static_cast<MatchFlags>(MatchFlag::kAffectedByStartingStyle)); } result_.AddMatchedProperties( &rule_data->Rule()->Properties(),
diff --git a/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc b/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc index 38d848a..cf73579 100644 --- a/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc +++ b/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc
@@ -295,7 +295,7 @@ case StyleRule::kSupports: case StyleRule::kPositionFallback: case StyleRule::kTry: - case StyleRule::kInitial: + case StyleRule::kStartingStyle: // TODO(andruud): Handle other descriptor types here. NOTREACHED(); return nullptr;
diff --git a/third_party/blink/renderer/core/css/parser/css_at_rule_id.cc b/third_party/blink/renderer/core/css/parser/css_at_rule_id.cc index 2d19761..e84f46d 100644 --- a/third_party/blink/renderer/core/css/parser/css_at_rule_id.cc +++ b/third_party/blink/renderer/core/css/parser/css_at_rule_id.cc
@@ -112,9 +112,9 @@ } return CSSAtRuleID::kCSSAtRuleInvalid; } - if (EqualIgnoringASCIICase(name, "initial")) { + if (EqualIgnoringASCIICase(name, "starting-style")) { if (RuntimeEnabledFeatures::CSSInitialPseudoEnabled()) { - return CSSAtRuleID::kCSSAtRuleInitial; + return CSSAtRuleID::kCSSAtRuleStartingStyle; } return CSSAtRuleID::kCSSAtRuleInvalid; } @@ -142,8 +142,6 @@ return WebFeature::kCSSAtRuleFontFeatureValues; case CSSAtRuleID::kCSSAtRuleImport: return WebFeature::kCSSAtRuleImport; - case CSSAtRuleID::kCSSAtRuleInitial: - return WebFeature::kCSSAtRuleInitial; case CSSAtRuleID::kCSSAtRuleKeyframes: return WebFeature::kCSSAtRuleKeyframes; case CSSAtRuleID::kCSSAtRuleLayer: @@ -164,6 +162,8 @@ return WebFeature::kCSSAtRuleOrnaments; case CSSAtRuleID::kCSSAtRuleScope: return WebFeature::kCSSAtRuleScope; + case CSSAtRuleID::kCSSAtRuleStartingStyle: + return WebFeature::kCSSAtRuleStartingStyle; case CSSAtRuleID::kCSSAtRuleStyleset: return WebFeature::kCSSAtRuleStylistic; case CSSAtRuleID::kCSSAtRuleStylistic:
diff --git a/third_party/blink/renderer/core/css/parser/css_at_rule_id.h b/third_party/blink/renderer/core/css/parser/css_at_rule_id.h index dbf1f14..9978b20 100644 --- a/third_party/blink/renderer/core/css/parser/css_at_rule_id.h +++ b/third_party/blink/renderer/core/css/parser/css_at_rule_id.h
@@ -17,7 +17,6 @@ kCSSAtRuleFontFace, kCSSAtRuleFontPaletteValues, kCSSAtRuleImport, - kCSSAtRuleInitial, kCSSAtRuleKeyframes, kCSSAtRuleLayer, kCSSAtRuleMedia, @@ -28,6 +27,7 @@ kCSSAtRuleContainer, kCSSAtRuleCounterStyle, kCSSAtRuleScope, + kCSSAtRuleStartingStyle, kCSSAtRuleSupports, kCSSAtRuleTry, kCSSAtRuleWebkitKeyframes,
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc index e319704..3d55b1ac 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc +++ b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
@@ -677,7 +677,7 @@ if (id != CSSAtRuleID::kCSSAtRuleMedia && // [css-conditional-3] id != CSSAtRuleID::kCSSAtRuleSupports && // [css-conditional-3] id != CSSAtRuleID::kCSSAtRuleContainer && // [css-contain-3] - id != CSSAtRuleID::kCSSAtRuleInitial) { + id != CSSAtRuleID::kCSSAtRuleStartingStyle) { ConsumeErroneousAtRule(stream); return nullptr; } @@ -743,9 +743,9 @@ case CSSAtRuleID::kCSSAtRuleSupports: return ConsumeSupportsRule(stream, nesting_type, parent_rule_for_nesting); - case CSSAtRuleID::kCSSAtRuleInitial: - return ConsumeInitialRule(stream, nesting_type, - parent_rule_for_nesting); + case CSSAtRuleID::kCSSAtRuleStartingStyle: + return ConsumeStartingStyleRule(stream, nesting_type, + parent_rule_for_nesting); case CSSAtRuleID::kCSSAtRuleFontFace: return ConsumeFontFaceRule(stream); case CSSAtRuleID::kCSSAtRuleFontPaletteValues: @@ -1104,7 +1104,7 @@ std::move(rules)); } -StyleRuleInitial* CSSParserImpl::ConsumeInitialRule( +StyleRuleStartingStyle* CSSParserImpl::ConsumeStartingStyleRule( CSSParserTokenStream& stream, CSSNestingType nesting_type, StyleRule* parent_rule_for_nesting) { @@ -1117,11 +1117,11 @@ CSSParserTokenStream::BlockGuard guard(stream); if (!prelude.AtEnd()) { - return nullptr; // Parse error; @initial prelude should be empty + return nullptr; // Parse error; @starting-style prelude should be empty } if (observer_) { - observer_->StartRuleHeader(StyleRule::kInitial, prelude_offset_start); + observer_->StartRuleHeader(StyleRule::kStartingStyle, prelude_offset_start); observer_->EndRuleHeader(prelude_offset_end); observer_->StartRuleBody(stream.Offset()); } @@ -1153,7 +1153,7 @@ // NOTE: There will be a copy of rules here, to deal with the different inline // size. - return MakeGarbageCollected<StyleRuleInitial>(std::move(rules)); + return MakeGarbageCollected<StyleRuleStartingStyle>(std::move(rules)); } StyleRuleFontFace* CSSParserImpl::ConsumeFontFaceRule(
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_impl.h b/third_party/blink/renderer/core/css/parser/css_parser_impl.h index ea6843c..8af8676 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_impl.h +++ b/third_party/blink/renderer/core/css/parser/css_parser_impl.h
@@ -206,9 +206,10 @@ StyleRuleSupports* ConsumeSupportsRule(CSSParserTokenStream& stream, CSSNestingType, StyleRule* parent_rule_for_nesting); - StyleRuleInitial* ConsumeInitialRule(CSSParserTokenStream& stream, - CSSNestingType, - StyleRule* parent_rule_for_nesting); + StyleRuleStartingStyle* ConsumeStartingStyleRule( + CSSParserTokenStream& stream, + CSSNestingType, + StyleRule* parent_rule_for_nesting); StyleRuleFontFace* ConsumeFontFaceRule(CSSParserTokenStream&); StyleRuleFontPaletteValues* ConsumeFontPaletteValuesRule( CSSParserTokenStream&);
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 e448c58..3241de82 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
@@ -6415,7 +6415,8 @@ wind_rule); } -CSSValue* ConsumePathFunction(CSSParserTokenRange& range) { +CSSValue* ConsumePathFunction(CSSParserTokenRange& range, + EmptyPathStringHandling empty_handling) { // FIXME: Add support for <url>, <basic-shape>, <geometry-box>. if (range.Peek().FunctionId() != CSSValueID::kPath) { return nullptr; @@ -6429,10 +6430,19 @@ return nullptr; } - range = function_range; + // https://drafts.csswg.org/css-shapes-1/#funcdef-basic-shape-path + // A path data string that does not conform to the to the grammar + // and parsing rules of SVG 1.1, or that does conform but defines + // an empty path, is invalid and causes the entire path() to be invalid. if (byte_stream->IsEmpty()) { - return CSSIdentifierValue::Create(CSSValueID::kNone); + if (empty_handling == EmptyPathStringHandling::kTreatAsNone) { + range = function_range; + return CSSIdentifierValue::Create(CSSValueID::kNone); + } + return nullptr; } + range = function_range; + return MakeGarbageCollected<cssvalue::CSSPathValue>(std::move(byte_stream)); } @@ -6592,7 +6602,7 @@ offset_path = ConsumeUrl(range, context); } if (!offset_path) { - offset_path = ConsumePathFunction(range); + offset_path = ConsumePathFunction(range, EmptyPathStringHandling::kFailure); } if (!coord_box && RuntimeEnabledFeatures::CSSOffsetPathCoordBoxEnabled()) { @@ -6623,7 +6633,7 @@ return ConsumeIdent(range); } - return ConsumePathFunction(range); + return ConsumePathFunction(range, EmptyPathStringHandling::kTreatAsNone); } CSSValue* ConsumeOffsetRotate(CSSParserTokenRange& range,
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.h b/third_party/blink/renderer/core/css/properties/css_parsing_utils.h index 2585a3e8..85466b4 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.h +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.h
@@ -61,6 +61,7 @@ }; enum class UnitlessQuirk { kAllow, kForbid }; enum class AllowedColorKeywords { kAllowSystemColor, kNoSystemColor }; +enum class EmptyPathStringHandling { kFailure, kTreatAsNone }; using ConsumeAnimationItemValue = CSSValue* (*)(CSSPropertyID, CSSParserTokenRange&,
diff --git a/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc b/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc index 4afca3d..b8376d7 100644 --- a/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc +++ b/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
@@ -2655,7 +2655,7 @@ } else if (RuntimeEnabledFeatures::CSSOffsetPositionAnchorEnabled()) { css_parsing_utils::AddProperty( CSSPropertyID::kOffsetPosition, CSSPropertyID::kOffset, - *CSSInitialValue::Create(), important, + *CSSIdentifierValue::Create(CSSValueID::kAuto), important, css_parsing_utils::IsImplicitProperty::kNotImplicit, properties); } @@ -2667,7 +2667,7 @@ } else { css_parsing_utils::AddProperty( CSSPropertyID::kOffsetPath, CSSPropertyID::kOffset, - *CSSInitialValue::Create(), important, + *CSSIdentifierValue::Create(CSSValueID::kNone), important, css_parsing_utils::IsImplicitProperty::kNotImplicit, properties); } @@ -2679,8 +2679,10 @@ } else { css_parsing_utils::AddProperty( CSSPropertyID::kOffsetDistance, CSSPropertyID::kOffset, - *CSSInitialValue::Create(), important, - css_parsing_utils::IsImplicitProperty::kNotImplicit, properties); + *CSSNumericLiteralValue::Create(0, + CSSPrimitiveValue::UnitType::kPixels), + important, css_parsing_utils::IsImplicitProperty::kNotImplicit, + properties); } if (offset_rotate) { @@ -2691,7 +2693,7 @@ } else { css_parsing_utils::AddProperty( CSSPropertyID::kOffsetRotate, CSSPropertyID::kOffset, - *CSSInitialValue::Create(), important, + *CSSIdentifierValue::Create(CSSValueID::kAuto), important, css_parsing_utils::IsImplicitProperty::kNotImplicit, properties); } @@ -2703,7 +2705,7 @@ } else if (RuntimeEnabledFeatures::CSSOffsetPositionAnchorEnabled()) { css_parsing_utils::AddProperty( CSSPropertyID::kOffsetAnchor, CSSPropertyID::kOffset, - *CSSInitialValue::Create(), important, + *CSSIdentifierValue::Create(CSSValueID::kAuto), important, css_parsing_utils::IsImplicitProperty::kNotImplicit, properties); } @@ -3220,8 +3222,11 @@ if (!axis && (axis = ConsumeSingleTimelineAxis(range))) { continue; } - if (!attachment && (attachment = ConsumeSingleTimelineAttachment(range))) { - continue; + if (RuntimeEnabledFeatures::ScrollTimelineAttachmentEnabled()) { + if (!attachment && + (attachment = ConsumeSingleTimelineAttachment(range))) { + continue; + } } break; } @@ -3251,8 +3256,6 @@ using css_parsing_utils::ConsumeCommaIncludingWhitespace; using css_parsing_utils::IsImplicitProperty; - DCHECK_EQ(3u, shorthand.length()); - CSSValueList* name_list = CSSValueList::CreateCommaSeparated(); CSSValueList* axis_list = CSSValueList::CreateCommaSeparated(); CSSValueList* attachment_list = CSSValueList::CreateCommaSeparated(); @@ -3270,13 +3273,17 @@ DCHECK_EQ(name_list->length(), axis_list->length()); DCHECK_EQ(name_list->length(), attachment_list->length()); + DCHECK_GE(shorthand.length(), 2u); AddProperty(shorthand.properties()[0]->PropertyID(), shorthand_id, *name_list, important, IsImplicitProperty::kNotImplicit, properties); AddProperty(shorthand.properties()[1]->PropertyID(), shorthand_id, *axis_list, important, IsImplicitProperty::kNotImplicit, properties); - AddProperty(shorthand.properties()[2]->PropertyID(), shorthand_id, - *attachment_list, important, IsImplicitProperty::kNotImplicit, - properties); + if (RuntimeEnabledFeatures::ScrollTimelineAttachmentEnabled()) { + DCHECK_EQ(shorthand.length(), 3u); + AddProperty(shorthand.properties()[2]->PropertyID(), shorthand_id, + *attachment_list, important, IsImplicitProperty::kNotImplicit, + properties); + } return range.AtEnd(); } @@ -3409,7 +3416,10 @@ : HeapVector<Member<const ScopedCSSName>>{}; const Vector<TimelineAxis>& axis_vector = style.ScrollTimelineAxis(); const Vector<TimelineAttachment>& attachment_vector = - style.ScrollTimelineAttachment(); + RuntimeEnabledFeatures::ScrollTimelineAttachmentEnabled() + ? style.ScrollTimelineAttachment() + : Vector<TimelineAttachment>(name_vector.size(), + TimelineAttachment::kLocal); return CSSValueForTimelineShorthand(name_vector, axis_vector, attachment_vector); } @@ -3577,7 +3587,10 @@ : HeapVector<Member<const ScopedCSSName>>{}; const Vector<TimelineAxis>& axis_vector = style.ViewTimelineAxis(); const Vector<TimelineAttachment>& attachment_vector = - style.ViewTimelineAttachment(); + RuntimeEnabledFeatures::ScrollTimelineAttachmentEnabled() + ? style.ViewTimelineAttachment() + : Vector<TimelineAttachment>(name_vector.size(), + TimelineAttachment::kLocal); return CSSValueForTimelineShorthand(name_vector, axis_vector, attachment_vector); }
diff --git a/third_party/blink/renderer/core/css/resolver/match_flags.h b/third_party/blink/renderer/core/css/resolver/match_flags.h index 2f30915..acd8d2c 100644 --- a/third_party/blink/renderer/core/css/resolver/match_flags.h +++ b/third_party/blink/renderer/core/css/resolver/match_flags.h
@@ -22,8 +22,8 @@ kAffectedByHover = 1 << 2, // :active kAffectedByActive = 1 << 3, - // :initial - kAffectedByInitial = 1 << 4, + // @starting-style + kAffectedByStartingStyle = 1 << 4, }; using MatchFlags = uint8_t;
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 e523a71..a208420 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
@@ -1837,6 +1837,12 @@ const CSSValue& value) { StyleOffsetRotation result(0, OffsetRotationType::kFixed); + if (auto* identifier = DynamicTo<CSSIdentifierValue>(value)) { + DCHECK_EQ(identifier->GetValueID(), CSSValueID::kAuto); + result.type = OffsetRotationType::kAuto; + return result; + } + const auto& list = To<CSSValueList>(value); DCHECK(list.length() == 1 || list.length() == 2); for (const auto& item : list) {
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc index deb512c..f969535 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -1447,8 +1447,8 @@ if (match_result.HasFlag(MatchFlag::kAffectedByActive)) { state.StyleBuilder().SetAffectedByActive(); } - if (match_result.HasFlag(MatchFlag::kAffectedByInitial)) { - state.StyleBuilder().SetIsPseudoInitialStyle(); + if (match_result.HasFlag(MatchFlag::kAffectedByStartingStyle)) { + state.StyleBuilder().SetIsStartingStyle(); } if (match_result.DependsOnSizeContainerQueries()) { state.StyleBuilder().SetDependsOnSizeContainerQueries(true);
diff --git a/third_party/blink/renderer/core/css/rule_set.cc b/third_party/blink/renderer/core/css/rule_set.cc index 6f9472b..4cae142 100644 --- a/third_party/blink/renderer/core/css/rule_set.cc +++ b/third_party/blink/renderer/core/css/rule_set.cc
@@ -123,7 +123,7 @@ is_entirely_covered_by_bucketing_( false), // Will be computed in ComputeEntirelyCoveredByBucketing(). is_easy_(false), // Ditto. - is_initial_((add_rule_flags & kRuleIsInitial) != 0), + is_starting_style_((add_rule_flags & kRuleIsStartingStyle) != 0), descendant_selector_identifier_hashes_() {} void RuleData::ComputeEntirelyCoveredByBucketing() { @@ -697,9 +697,9 @@ } AddChildRules(scope_rule->ChildRules(), medium, add_rule_flags, container_query, cascade_layer, inner_style_scope); - } else if (auto* initial_rule = DynamicTo<StyleRuleInitial>(rule)) { + } else if (auto* initial_rule = DynamicTo<StyleRuleStartingStyle>(rule)) { AddChildRules(initial_rule->ChildRules(), medium, - add_rule_flags | kRuleIsInitial, container_query, + add_rule_flags | kRuleIsStartingStyle, container_query, cascade_layer, style_scope); } }
diff --git a/third_party/blink/renderer/core/css/rule_set.h b/third_party/blink/renderer/core/css/rule_set.h index 67e1004..a28fad8 100644 --- a/third_party/blink/renderer/core/css/rule_set.h +++ b/third_party/blink/renderer/core/css/rule_set.h
@@ -50,7 +50,7 @@ enum AddRuleFlag { kRuleHasNoSpecialState = 0, kRuleIsVisitedDependent = 1 << 0, - kRuleIsInitial = 1 << 1, + kRuleIsStartingStyle = 1 << 1, }; // Some CSS properties do not apply to certain pseudo-elements, and need to be @@ -127,7 +127,7 @@ void ComputeEntirelyCoveredByBucketing(); void ResetEntirelyCoveredByBucketing(); bool SelectorIsEasy() const { return is_easy_; } - bool IsInitial() const { return is_initial_; } + bool IsStartingStyle() const { return is_starting_style_; } bool ContainsUncommonAttributeSelector() const { return contains_uncommon_attribute_selector_; @@ -197,8 +197,8 @@ unsigned link_match_type_ : 2; unsigned valid_property_filter_ : 3; unsigned is_entirely_covered_by_bucketing_ : 1; - unsigned is_easy_ : 1; // See EasySelectorChecker. - unsigned is_initial_ : 1; // Inside @initial {}. + unsigned is_easy_ : 1; // See EasySelectorChecker. + unsigned is_starting_style_ : 1; // Inside @starting-style {}. // 32 bits above union { // Used by RuleMap before compaction, to hold what bucket this RuleData
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc index bae7e3d..8aa7b184 100644 --- a/third_party/blink/renderer/core/css/style_engine_test.cc +++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -6095,12 +6095,138 @@ EXPECT_EQ("0s", ComputedValue(target3, "animation-duration")->CssText()); } +TEST_F(StyleEngineTest, ScrollTimelineAttachmentFlags) { + String css = "scroll-timeline-attachment: initial"; + { + ScopedScrollTimelineAttachmentForTest enabled(false); + const CSSPropertyValueSet* set = + css_test_helpers::ParseDeclarationBlock(css); + ASSERT_TRUE(set); + EXPECT_EQ(0u, set->PropertyCount()); + } + { + ScopedScrollTimelineAttachmentForTest enabled(true); + const CSSPropertyValueSet* set = + css_test_helpers::ParseDeclarationBlock(css); + ASSERT_TRUE(set); + EXPECT_EQ(1u, set->PropertyCount()); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kScrollTimelineAttachment)); + } +} + +TEST_F(StyleEngineTest, ViewTimelineAttachmentFlags) { + String css = "view-timeline-attachment: initial"; + { + ScopedScrollTimelineAttachmentForTest enabled(false); + const CSSPropertyValueSet* set = + css_test_helpers::ParseDeclarationBlock(css); + ASSERT_TRUE(set); + EXPECT_EQ(0u, set->PropertyCount()); + } + { + ScopedScrollTimelineAttachmentForTest enabled(true); + const CSSPropertyValueSet* set = + css_test_helpers::ParseDeclarationBlock(css); + ASSERT_TRUE(set); + EXPECT_EQ(1u, set->PropertyCount()); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kViewTimelineAttachment)); + } +} + +TEST_F(StyleEngineTest, ScrollTimelineShorthandFlagsInitial) { + String css = "scroll-timeline: initial"; + { + ScopedScrollTimelineAttachmentForTest enabled(false); + const CSSPropertyValueSet* set = + css_test_helpers::ParseDeclarationBlock(css); + ASSERT_TRUE(set); + EXPECT_EQ(2u, set->PropertyCount()); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kScrollTimelineName)); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kScrollTimelineAxis)); + } + { + ScopedScrollTimelineAttachmentForTest enabled(true); + const CSSPropertyValueSet* set = + css_test_helpers::ParseDeclarationBlock(css); + ASSERT_TRUE(set); + EXPECT_EQ(3u, set->PropertyCount()); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kScrollTimelineName)); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kScrollTimelineAxis)); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kScrollTimelineAttachment)); + } +} + +TEST_F(StyleEngineTest, ScrollTimelineShorthandFlags) { + String css = "scroll-timeline: --foo block defer"; + { + ScopedScrollTimelineAttachmentForTest enabled(false); + const CSSPropertyValueSet* set = + css_test_helpers::ParseDeclarationBlock(css); + ASSERT_TRUE(set); + EXPECT_EQ(0u, set->PropertyCount()); + } + { + ScopedScrollTimelineAttachmentForTest enabled(true); + const CSSPropertyValueSet* set = + css_test_helpers::ParseDeclarationBlock(css); + ASSERT_TRUE(set); + EXPECT_EQ(3u, set->PropertyCount()); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kScrollTimelineName)); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kScrollTimelineAxis)); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kScrollTimelineAttachment)); + } +} + +TEST_F(StyleEngineTest, ViewTimelineShorthandFlagsInitial) { + String css = "view-timeline: initial"; + { + ScopedScrollTimelineAttachmentForTest enabled(false); + const CSSPropertyValueSet* set = + css_test_helpers::ParseDeclarationBlock(css); + ASSERT_TRUE(set); + EXPECT_EQ(2u, set->PropertyCount()); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kViewTimelineName)); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kViewTimelineAxis)); + } + { + ScopedScrollTimelineAttachmentForTest enabled(true); + const CSSPropertyValueSet* set = + css_test_helpers::ParseDeclarationBlock(css); + ASSERT_TRUE(set); + EXPECT_EQ(3u, set->PropertyCount()); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kViewTimelineName)); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kViewTimelineAxis)); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kViewTimelineAttachment)); + } +} + +TEST_F(StyleEngineTest, ViewTimelineShorthandFlags) { + String css = "view-timeline: --foo block defer"; + { + ScopedScrollTimelineAttachmentForTest enabled(false); + const CSSPropertyValueSet* set = + css_test_helpers::ParseDeclarationBlock(css); + ASSERT_TRUE(set); + EXPECT_EQ(0u, set->PropertyCount()); + } + { + ScopedScrollTimelineAttachmentForTest enabled(true); + const CSSPropertyValueSet* set = + css_test_helpers::ParseDeclarationBlock(css); + ASSERT_TRUE(set); + EXPECT_EQ(3u, set->PropertyCount()); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kViewTimelineName)); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kViewTimelineAxis)); + EXPECT_TRUE(set->HasProperty(CSSPropertyID::kViewTimelineAttachment)); + } +} + TEST_F(StyleEngineTest, InitialStyle_Recalc) { GetDocument().body()->setInnerHTML(R"HTML( <style> #target { background-color: green; - @initial { background-color: red; } + @starting-style { background-color: red; } } </style> <div id="target"></div> @@ -6118,12 +6244,12 @@ UpdateAllLifecyclePhasesForTest(); EXPECT_EQ(GetStyleEngine().StyleForElementCount() - before_count, 1u) - << "The style recalc should not do a separate @initial pass since the " - "element already has a style"; + << "The style recalc should not do a separate @starting-style pass since " + "the element already has a style"; EXPECT_EQ(target->ComputedStyleRef().VisitedDependentColor( GetCSSPropertyBackgroundColor()), green) - << "Make sure @initial rules do not apply for the second pass"; + << "Make sure @starting-style rules do not apply for the second pass"; EXPECT_EQ( target->ComputedStyleRef().VisitedDependentColor(GetCSSPropertyColor()), lime) @@ -6135,7 +6261,7 @@ <style> #target { background-color: green; - @initial { background-color: red; } + @starting-style { background-color: red; } } </style> <div id="target" style="display:none"></div> @@ -6153,11 +6279,11 @@ EXPECT_EQ(GetStyleEngine().StyleForElementCount() - before_count, 2u) << "The style recalc needs to do two passes because the element was " - "display:none and @initial styles are matching"; + "display:none and @starting-style styles are matching"; EXPECT_EQ(target->ComputedStyleRef().VisitedDependentColor( GetCSSPropertyBackgroundColor()), green) - << "Make sure @initial do not apply for the second pass"; + << "Make sure @starting-style do not apply for the second pass"; } TEST_F(StyleEngineTest, InitialStyleCount_EnsureComputedStyle) { @@ -6166,7 +6292,7 @@ #target { background-color: green; transition: background-color 100s step-end; - @initial { background-color: red; } + @starting-style { background-color: red; } } </style> <div id="target" style="display:none"></div> @@ -6186,12 +6312,12 @@ ASSERT_TRUE(none_style); EXPECT_EQ(GetStyleEngine().StyleForElementCount() - before_count, 1u) - << "No @initial pass for EnsureComputedStyle"; + << "No @starting-style pass for EnsureComputedStyle"; EXPECT_EQ(target->ComputedStyleRef().VisitedDependentColor( GetCSSPropertyBackgroundColor()), green) - << "Transitions are not started and @initial does not apply in " + << "Transitions are not started and @starting-style does not apply in " "display:none"; }
diff --git a/third_party/blink/renderer/core/css/style_property_serializer.cc b/third_party/blink/renderer/core/css/style_property_serializer.cc index 95962f2d..a0968e1 100644 --- a/third_party/blink/renderer/core/css/style_property_serializer.cc +++ b/third_party/blink/renderer/core/css/style_property_serializer.cc
@@ -396,7 +396,6 @@ case CSSPropertyID::kGridArea: case CSSPropertyID::kGap: case CSSPropertyID::kListStyle: - case CSSPropertyID::kOffset: case CSSPropertyID::kTextDecoration: case CSSPropertyID::kTextEmphasis: case CSSPropertyID::kWebkitMask: @@ -870,18 +869,31 @@ return list; } +// TODO(crbug.com/1446702): Remove scroll/view-timeline-attachment. +CSSValueList* DefaultAttachments(wtf_size_t size) { + CSSValueList* list = CSSValueList::CreateCommaSeparated(); + for (wtf_size_t i = 0; i < size; ++i) { + list->Append(*CSSIdentifierValue::Create(CSSValueID::kLocal)); + } + return list; +} + } // namespace String StylePropertySerializer::TimelineValue( const StylePropertyShorthand& shorthand) const { - CHECK_EQ(shorthand.length(), 3u); + CHECK_EQ(shorthand.length(), + RuntimeEnabledFeatures::ScrollTimelineAttachmentEnabled() ? 3u : 2u); const CSSValueList& name_list = To<CSSValueList>( *property_set_.GetPropertyCSSValue(*shorthand.properties()[0])); const CSSValueList& axis_list = To<CSSValueList>( *property_set_.GetPropertyCSSValue(*shorthand.properties()[1])); - const CSSValueList& attachment_list = To<CSSValueList>( - *property_set_.GetPropertyCSSValue(*shorthand.properties()[2])); + const CSSValueList& attachment_list = + RuntimeEnabledFeatures::ScrollTimelineAttachmentEnabled() + ? *To<CSSValueList>( + property_set_.GetPropertyCSSValue(*shorthand.properties()[2])) + : *DefaultAttachments(name_list.length()); // The scroll/view-timeline shorthand can not expand to longhands of two // different lengths, so we can also not contract two different-longhands @@ -903,24 +915,30 @@ } String StylePropertySerializer::ScrollTimelineValue() const { - CHECK_EQ(scrollTimelineShorthand().length(), 3u); + CHECK_GE(scrollTimelineShorthand().length(), 2u); CHECK_EQ(scrollTimelineShorthand().properties()[0], &GetCSSPropertyScrollTimelineName()); CHECK_EQ(scrollTimelineShorthand().properties()[1], &GetCSSPropertyScrollTimelineAxis()); - CHECK_EQ(scrollTimelineShorthand().properties()[2], - &GetCSSPropertyScrollTimelineAttachment()); + if (RuntimeEnabledFeatures::ScrollTimelineAttachmentEnabled()) { + CHECK_EQ(scrollTimelineShorthand().length(), 3u); + CHECK_EQ(scrollTimelineShorthand().properties()[2], + &GetCSSPropertyScrollTimelineAttachment()); + } return TimelineValue(scrollTimelineShorthand()); } String StylePropertySerializer::ViewTimelineValue() const { - CHECK_EQ(viewTimelineShorthand().length(), 3u); + CHECK_GE(viewTimelineShorthand().length(), 2u); CHECK_EQ(viewTimelineShorthand().properties()[0], &GetCSSPropertyViewTimelineName()); CHECK_EQ(viewTimelineShorthand().properties()[1], &GetCSSPropertyViewTimelineAxis()); - CHECK_EQ(viewTimelineShorthand().properties()[2], - &GetCSSPropertyViewTimelineAttachment()); + if (RuntimeEnabledFeatures::ScrollTimelineAttachmentEnabled()) { + CHECK_EQ(viewTimelineShorthand().length(), 3u); + CHECK_EQ(viewTimelineShorthand().properties()[2], + &GetCSSPropertyViewTimelineAttachment()); + } return TimelineValue(viewTimelineShorthand()); } @@ -1342,44 +1360,72 @@ } String StylePropertySerializer::OffsetValue() const { - StringBuilder result; - if (RuntimeEnabledFeatures::CSSOffsetPositionAnchorEnabled()) { - const CSSValue* position = - property_set_.GetPropertyCSSValue(GetCSSPropertyOffsetPosition()); - if (!position->IsInitialValue()) { - result.Append(position->CssText()); - } - } + const CSSValue* position = + property_set_.GetPropertyCSSValue(GetCSSPropertyOffsetPosition()); const CSSValue* path = property_set_.GetPropertyCSSValue(GetCSSPropertyOffsetPath()); const CSSValue* distance = property_set_.GetPropertyCSSValue(GetCSSPropertyOffsetDistance()); const CSSValue* rotate = property_set_.GetPropertyCSSValue(GetCSSPropertyOffsetRotate()); - if (!path->IsInitialValue()) { + const CSSValue* anchor = + property_set_.GetPropertyCSSValue(GetCSSPropertyOffsetAnchor()); + + auto is_initial_identifier_value = [](const CSSValue* value, CSSValueID id) { + return value->IsIdentifierValue() && + DynamicTo<CSSIdentifierValue>(value)->GetValueID() == id; + }; + + bool use_distance = + !(distance->IsNumericLiteralValue() && + To<CSSNumericLiteralValue>(*distance).DoubleValue() == 0.0); + const auto* rotate_list_value = DynamicTo<CSSValueList>(rotate); + bool is_rotate_auto = rotate_list_value && rotate_list_value->length() == 1 && + is_initial_identifier_value(&rotate_list_value->First(), + CSSValueID::kAuto); + bool is_rotate_zero = + rotate_list_value && rotate_list_value->length() == 1 && + rotate_list_value->First().IsNumericLiteralValue() && + (To<CSSNumericLiteralValue>(rotate_list_value->First()).DoubleValue() == + 0.0); + bool is_rotate_auto_zero = + rotate_list_value && rotate_list_value->length() == 2 && + rotate_list_value->Item(1).IsNumericLiteralValue() && + (To<CSSNumericLiteralValue>(rotate_list_value->Item(1)).DoubleValue() == + 0.0) && + is_initial_identifier_value(&rotate_list_value->Item(0), + CSSValueID::kAuto); + bool use_rotate = (use_distance && is_rotate_zero) || + (!is_initial_identifier_value(rotate, CSSValueID::kAuto) && + !is_rotate_auto && !is_rotate_auto_zero); + bool use_path = use_rotate || use_distance || + !is_initial_identifier_value(path, CSSValueID::kNone); + bool use_position = + !use_path || !is_initial_identifier_value(position, CSSValueID::kAuto); + bool use_anchor = !is_initial_identifier_value(anchor, CSSValueID::kAuto); + + StringBuilder result; + if (RuntimeEnabledFeatures::CSSOffsetPositionAnchorEnabled()) { + if (use_position) { + result.Append(position->CssText()); + } + } + if (use_path) { if (!result.empty()) { result.Append(" "); } result.Append(path->CssText()); - if (!distance->IsInitialValue()) { - result.Append(" "); - result.Append(distance->CssText()); - } - if (!rotate->IsInitialValue()) { - result.Append(" "); - result.Append(rotate->CssText()); - } - } else { - // The longhand values cannot be serialized as a valid shorthand value. - // Serialize them as individual longhands instead. - if (!distance->IsInitialValue() || !rotate->IsInitialValue()) { - return String(); - } + } + if (use_distance) { + result.Append(" "); + result.Append(distance->CssText()); + } + if (use_rotate) { + result.Append(" "); + result.Append(rotate->CssText()); } if (RuntimeEnabledFeatures::CSSOffsetPositionAnchorEnabled()) { - const CSSValue* anchor = - property_set_.GetPropertyCSSValue(GetCSSPropertyOffsetAnchor()); - if (!anchor->IsInitialValue()) { + if (use_anchor) { result.Append(" / "); result.Append(anchor->CssText()); }
diff --git a/third_party/blink/renderer/core/css/style_recalc_context.h b/third_party/blink/renderer/core/css/style_recalc_context.h index 4413f700..e550f016 100644 --- a/third_party/blink/renderer/core/css/style_recalc_context.h +++ b/third_party/blink/renderer/core/css/style_recalc_context.h
@@ -65,7 +65,8 @@ StyleScopeFrame* style_scope_frame = nullptr; // The style for the element at the start of the lifecycle update, or the - // :initial styles for the second pass when transitioning from display:none. + // @starting-style styles for the second pass when transitioning from + // display:none. const ComputedStyle* old_style = nullptr; // If true, something about the parent's style (e.g., that it has
diff --git a/third_party/blink/renderer/core/css/style_rule.cc b/third_party/blink/renderer/core/css/style_rule.cc index 0853a47..a03dfae 100644 --- a/third_party/blink/renderer/core/css/style_rule.cc +++ b/third_party/blink/renderer/core/css/style_rule.cc
@@ -29,7 +29,6 @@ #include "third_party/blink/renderer/core/css/css_font_palette_values_rule.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" #include "third_party/blink/renderer/core/css/css_import_rule.h" -#include "third_party/blink/renderer/core/css/css_initial_rule.h" #include "third_party/blink/renderer/core/css/css_keyframes_rule.h" #include "third_party/blink/renderer/core/css/css_layer_block_rule.h" #include "third_party/blink/renderer/core/css/css_layer_statement_rule.h" @@ -39,6 +38,7 @@ #include "third_party/blink/renderer/core/css/css_position_fallback_rule.h" #include "third_party/blink/renderer/core/css/css_property_rule.h" #include "third_party/blink/renderer/core/css/css_scope_rule.h" +#include "third_party/blink/renderer/core/css/css_starting_style_rule.h" #include "third_party/blink/renderer/core/css/css_style_rule.h" #include "third_party/blink/renderer/core/css/css_supports_rule.h" #include "third_party/blink/renderer/core/css/css_try_rule.h" @@ -141,8 +141,8 @@ case kTry: To<StyleRuleTry>(this)->TraceAfterDispatch(visitor); return; - case kInitial: - To<StyleRuleInitial>(this)->TraceAfterDispatch(visitor); + case kStartingStyle: + To<StyleRuleStartingStyle>(this)->TraceAfterDispatch(visitor); return; } NOTREACHED(); @@ -213,8 +213,8 @@ case kTry: To<StyleRuleTry>(this)->~StyleRuleTry(); return; - case kInitial: - To<StyleRuleInitial>(this)->~StyleRuleInitial(); + case kStartingStyle: + To<StyleRuleStartingStyle>(this)->~StyleRuleStartingStyle(); return; } NOTREACHED(); @@ -264,8 +264,8 @@ return To<StyleRuleCounterStyle>(this)->Copy(); case kPositionFallback: return To<StyleRulePositionFallback>(this)->Copy(); - case kInitial: - return To<StyleRuleInitial>(this)->Copy(); + case kStartingStyle: + return To<StyleRuleStartingStyle>(this)->Copy(); case kTry: NOTREACHED(); return nullptr; @@ -348,9 +348,9 @@ rule = MakeGarbageCollected<CSSPositionFallbackRule>( To<StyleRulePositionFallback>(self), parent_sheet); break; - case kInitial: - rule = MakeGarbageCollected<CSSInitialRule>(To<StyleRuleInitial>(self), - parent_sheet); + case kStartingStyle: + rule = MakeGarbageCollected<CSSStartingStyleRule>( + To<StyleRuleStartingStyle>(self), parent_sheet); break; case kFontFeature: case kTry: @@ -483,7 +483,7 @@ case kContainer: case kMedia: case kSupports: - case kInitial: + case kStartingStyle: for (StyleRuleBase* child : DynamicTo<StyleRuleGroup>(this)->ChildRules()) { child->Reparent(old_parent, new_parent); @@ -766,7 +766,8 @@ StyleRuleCondition::TraceAfterDispatch(visitor); } -StyleRuleInitial::StyleRuleInitial(HeapVector<Member<StyleRuleBase>> rules) - : StyleRuleCondition(kInitial, "", std::move(rules)) {} +StyleRuleStartingStyle::StyleRuleStartingStyle( + HeapVector<Member<StyleRuleBase>> rules) + : StyleRuleCondition(kStartingStyle, "", std::move(rules)) {} } // namespace blink
diff --git a/third_party/blink/renderer/core/css/style_rule.h b/third_party/blink/renderer/core/css/style_rule.h index 1c2a8ab..6710c8d 100644 --- a/third_party/blink/renderer/core/css/style_rule.h +++ b/third_party/blink/renderer/core/css/style_rule.h
@@ -67,7 +67,7 @@ kSupports, kPositionFallback, kTry, - kInitial, + kStartingStyle, }; // Name of a cascade layer as given by an @layer rule, split at '.' into a @@ -103,10 +103,10 @@ bool IsImportRule() const { return GetType() == kImport; } bool IsPositionFallbackRule() const { return GetType() == kPositionFallback; } bool IsTryRule() const { return GetType() == kTry; } - bool IsInitialRule() const { return GetType() == kInitial; } + bool IsStartingStyleRule() const { return GetType() == kStartingStyle; } bool IsConditionRule() const { return GetType() == kContainer || GetType() == kMedia || - GetType() == kSupports || GetType() == kInitial; + GetType() == kSupports || GetType() == kStartingStyle; } StyleRuleBase* Copy() const; @@ -539,14 +539,14 @@ Member<ContainerQuery> container_query_; }; -class StyleRuleInitial : public StyleRuleCondition { +class StyleRuleStartingStyle : public StyleRuleCondition { public: - explicit StyleRuleInitial(HeapVector<Member<StyleRuleBase>> rules); - StyleRuleInitial(const StyleRuleInitial&) = default; + explicit StyleRuleStartingStyle(HeapVector<Member<StyleRuleBase>> rules); + StyleRuleStartingStyle(const StyleRuleStartingStyle&) = default; bool ConditionIsSupported() const { return true; } - StyleRuleInitial* Copy() const { - return MakeGarbageCollected<StyleRuleInitial>(*this); + StyleRuleStartingStyle* Copy() const { + return MakeGarbageCollected<StyleRuleStartingStyle>(*this); } void SetConditionText(const ExecutionContext*, String); @@ -652,9 +652,9 @@ }; template <> -struct DowncastTraits<StyleRuleInitial> { +struct DowncastTraits<StyleRuleStartingStyle> { static bool AllowFrom(const StyleRuleBase& rule) { - return rule.IsInitialRule(); + return rule.IsStartingStyleRule(); } };
diff --git a/third_party/blink/renderer/core/css/style_sheet_contents.cc b/third_party/blink/renderer/core/css/style_sheet_contents.cc index 9dfd55a..13b44799 100644 --- a/third_party/blink/renderer/core/css/style_sheet_contents.cc +++ b/third_party/blink/renderer/core/css/style_sheet_contents.cc
@@ -628,7 +628,7 @@ case StyleRuleBase::kMedia: case StyleRuleBase::kLayerBlock: case StyleRuleBase::kScope: - case StyleRuleBase::kInitial: + case StyleRuleBase::kStartingStyle: if (ChildRulesHaveFailedOrCanceledSubresources( To<StyleRuleGroup>(rule)->ChildRules())) { return true;
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index a6ab227..fb304a3 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -3053,10 +3053,10 @@ DCHECK(IsPseudoElement()); return nullptr; } - if (style->IsPseudoInitialStyle()) { - // @initial pseudo styles matched. We need to compute the style a second - // time to compute the actual style and trigger transitions using the - // starting from the :initial style. + if (style->IsStartingStyle()) { + // @starting-style styles matched. We need to compute the style a second + // time to compute the actual style and trigger transitions starting from + // style with @starting-style applied. new_style_recalc_context.old_style = style->Display() == EDisplay::kNone ? nullptr : style.get(); style = HasCustomStyleCallbacks()
diff --git a/third_party/blink/renderer/core/dom/events/event_target.idl b/third_party/blink/renderer/core/dom/events/event_target.idl index f80e0071..a3944cb 100644 --- a/third_party/blink/renderer/core/dom/events/event_target.idl +++ b/third_party/blink/renderer/core/dom/events/event_target.idl
@@ -21,7 +21,6 @@ // https://dom.spec.whatwg.org/#interface-eventtarget [ - CheckSecurity=Receiver, Exposed=(Window,Worker,AudioWorklet), ImmutablePrototype ] interface EventTarget {
diff --git a/third_party/blink/renderer/core/frame/frame_serializer.cc b/third_party/blink/renderer/core/frame/frame_serializer.cc index 948d8bd..d82e399 100644 --- a/third_party/blink/renderer/core/frame/frame_serializer.cc +++ b/third_party/blink/renderer/core/frame/frame_serializer.cc
@@ -437,7 +437,7 @@ case CSSRule::kContainerRule: case CSSRule::kLayerBlockRule: case CSSRule::kScopeRule: - case CSSRule::kInitialRule: { + case CSSRule::kStartingStyleRule: { CSSRuleList* rule_list = rule->cssRules(); for (unsigned i = 0; i < rule_list->length(); ++i) SerializeCSSRule(rule_list->item(i));
diff --git a/third_party/blink/renderer/core/frame/location.idl b/third_party/blink/renderer/core/frame/location.idl index de03a720..62e5480 100644 --- a/third_party/blink/renderer/core/frame/location.idl +++ b/third_party/blink/renderer/core/frame/location.idl
@@ -29,7 +29,6 @@ // https://html.spec.whatwg.org/C/#the-location-interface [ - CheckSecurity=Receiver, Exposed=Window ] interface Location { [CallWith=Isolate, RaisesException, LegacyUnforgeable] void assign(USVString url);
diff --git a/third_party/blink/renderer/core/frame/window.idl b/third_party/blink/renderer/core/frame/window.idl index 4e4acc6..1770002 100644 --- a/third_party/blink/renderer/core/frame/window.idl +++ b/third_party/blink/renderer/core/frame/window.idl
@@ -28,7 +28,6 @@ // FIXME: explain all uses of [CrossOrigin] [ - CheckSecurity=Receiver, ImplementedAs=DOMWindow, Global=Window, Exposed=Window
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index e2348c37..b6c83c3 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -648,6 +648,11 @@ bool HTMLMediaElement::ShouldReusePlayer(Document& old_document, Document& new_document) const { + // A NULL frame implies a NULL domWindow, so just check one of them + if (!old_document.GetFrame() || !new_document.GetFrame()) { + return false; + } + // Don't reuse player if the Document Picture-in-Picture API is disabled for // both documents. if (!RuntimeEnabledFeatures::DocumentPictureInPictureAPIEnabled( @@ -657,10 +662,6 @@ return false; } - if (!old_document.GetFrame() || !new_document.GetFrame()) { - return false; - } - auto* new_origin = new_document.GetFrame() ->LocalFrameRoot() .GetSecurityContext()
diff --git a/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc b/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc index c65eeac2..309c603 100644 --- a/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc
@@ -247,7 +247,7 @@ animation = it->value; *current_time = Timing::NullValue(); - if (animation->Paused() || !animation->timeline()->IsActive()) { + if (animation->Paused() || !animation->TimelineInternal()->IsActive()) { absl::optional<AnimationTimeDelta> animation_current_time = animation->CurrentTimeInternal(); if (animation_current_time) { @@ -259,7 +259,7 @@ animation->StartTimeInternal(); if (animation_start_time) { absl::optional<AnimationTimeDelta> timeline_time = - animation->timeline()->CurrentTime(); + animation->TimelineInternal()->CurrentTime(); // TODO(crbug.com/916117): Handle NaN values for scroll linked animations. if (timeline_time) { *current_time = timeline_time.value().InMillisecondsF() - @@ -286,14 +286,14 @@ if (paused && !clone->Paused()) { // Ensure we restore a current time if the animation is limited. absl::optional<AnimationTimeDelta> current_time; - if (!clone->timeline()->IsActive()) { + if (!clone->TimelineInternal()->IsActive()) { current_time = clone->CurrentTimeInternal(); } else { absl::optional<AnimationTimeDelta> start_time = clone->StartTimeInternal(); if (start_time) { absl::optional<AnimationTimeDelta> timeline_time = - clone->timeline()->CurrentTime(); + clone->TimelineInternal()->CurrentTime(); // TODO(crbug.com/916117): Handle NaN values. if (timeline_time) { current_time = timeline_time.value() - start_time.value(); @@ -344,7 +344,7 @@ old_effect->EffectTarget(), new_model, old_effect->SpecifiedTiming()); is_cloning_ = true; blink::Animation* clone = - blink::Animation::Create(new_effect, animation->timeline()); + blink::Animation::Create(new_effect, animation->TimelineInternal()); is_cloning_ = false; id_to_animation_clone_.Set(id, clone); id_to_animation_.Set(String::Number(clone->SequenceNumber()), clone); @@ -572,7 +572,8 @@ time_ms = start_time.value().InMillisecondsF(); } - auto* document_timeline = DynamicTo<DocumentTimeline>(animation.timeline()); + auto* document_timeline = + DynamicTo<DocumentTimeline>(animation.TimelineInternal()); if (document_timeline) { if (ReferenceTimeline().PlaybackRate() == 0) { time_ms += ReferenceTimeline().CurrentTimeMilliseconds().value_or(
diff --git a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc index b82939f..e95aba0 100644 --- a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc +++ b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
@@ -1808,12 +1808,16 @@ std::unique_ptr<protocol::Array<protocol::CSS::Value>> InspectorStyleSheet::SelectorsFromSource(CSSRuleSourceData* source_data, - const String& sheet_text) { + const String& sheet_text, + CSSStyleRule* rule) { auto* comment = MakeGarbageCollected<ScriptRegexp>( "/\\*[^]*?\\*/", kTextCaseSensitive, MultilineMode::kMultilineEnabled); auto result = std::make_unique<protocol::Array<protocol::CSS::Value>>(); const Vector<SourceRange>& ranges = source_data->selector_ranges; - for (wtf_size_t i = 0, size = ranges.size(); i < size; ++i) { + const CSSSelector* obj_selector = rule->GetStyleRule()->FirstSelector(); + + for (wtf_size_t i = 0, size = ranges.size(); i < size && obj_selector; + ++i, obj_selector = CSSSelectorList::Next(*obj_selector)) { const SourceRange& range = ranges.at(i); String selector = sheet_text.Substring(range.start, range.length()); @@ -1829,6 +1833,14 @@ .setText(selector.StripWhiteSpace()) .build(); simple_selector->setRange(BuildSourceRangeObject(range)); + + std::array<uint8_t, 3> specificity_tuple = obj_selector->SpecificityTuple(); + simple_selector->setSpecificity(protocol::CSS::Specificity::create() + .setA(specificity_tuple[0]) + .setB(specificity_tuple[1]) + .setC(specificity_tuple[2]) + .build()); + result->emplace_back(std::move(simple_selector)); } return result; @@ -1844,14 +1856,27 @@ String selector_text = rule->selectorText(); if (source_data) { - selectors = SelectorsFromSource(source_data, text_); + selectors = SelectorsFromSource(source_data, text_, rule); } else { selectors = std::make_unique<protocol::Array<protocol::CSS::Value>>(); for (const CSSSelector* selector = rule->GetStyleRule()->FirstSelector(); selector; selector = CSSSelectorList::Next(*selector)) { - selectors->emplace_back(protocol::CSS::Value::create() - .setText(selector->SelectorText()) - .build()); + std::array<uint8_t, 3> specificity_tuple = selector->SpecificityTuple(); + + std::unique_ptr<protocol::CSS::Specificity> reworked_specificity = + protocol::CSS::Specificity::create() + .setA(specificity_tuple[0]) + .setB(specificity_tuple[1]) + .setC(specificity_tuple[2]) + .build(); + + std::unique_ptr<protocol::CSS::Value> simple_selector = + protocol::CSS::Value::create() + .setText(selector->SelectorText()) + .setSpecificity(std::move(reworked_specificity)) + .build(); + + selectors->emplace_back(std::move(simple_selector)); } } return protocol::CSS::SelectorList::create()
diff --git a/third_party/blink/renderer/core/inspector/inspector_style_sheet.h b/third_party/blink/renderer/core/inspector/inspector_style_sheet.h index 1e19ce7..ba090c21 100644 --- a/third_party/blink/renderer/core/inspector/inspector_style_sheet.h +++ b/third_party/blink/renderer/core/inspector/inspector_style_sheet.h
@@ -242,9 +242,9 @@ bool InspectorStyleSheetText(String* result); String CollectStyleSheetRules(); bool CSSOMStyleSheetText(String* result); - std::unique_ptr<protocol::Array<protocol::CSS::Value>> SelectorsFromSource( - CSSRuleSourceData*, - const String&); + std::unique_ptr<protocol::Array<protocol::CSS::Value>> + SelectorsFromSource(CSSRuleSourceData*, const String&, CSSStyleRule*); + Vector<const CSSSelector*> SelectorsFromRule(CSSStyleRule* rule); String Url(); bool HasSourceURL(); bool StartsAtZero();
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h index e8caca4b..f840a03 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h
@@ -106,6 +106,9 @@ bool IsBisectLineBreakDisabled() const { return Data().IsBisectLineBreakDisabled(); } + // True if this node can't use the `NGScorehLineBreaker`, that can be + // determined by `CollectInlines`. Conditions that can change without + // `CollectInlines` are in `NGLineBreaker::ShouldDisableScoreLineBreak()`. bool IsScoreLineBreakDisabled() const { return Data().IsScoreLineBreakDisabled(); }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h index 0d83c17..c3cba8eb 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h
@@ -32,6 +32,9 @@ bool IsBisectLineBreakDisabled() const { return is_bisect_line_break_disabled_; } + // True if this node can't use the `NGScorehLineBreaker`, that can be + // determined by `CollectInlines`. Conditions that can change without + // `CollectInlines` are in `NGLineBreaker::ShouldDisableScoreLineBreak()`. bool IsScoreLineBreakDisabled() const { return is_score_line_break_disabled_; }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc index 376504d7..e2fcea5e 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
@@ -547,6 +547,7 @@ for (const NGInlineItem* item : open_items) { if (item->Style()->BoxDecorationBreak() == EBoxDecorationBreak::kClone) { has_cloned_box_decorations_ = true; + disable_score_line_break_ = true; ++cloned_box_decorations_count_; NGInlineItemResult item_result; ComputeOpenTagResult(*item, constraint_space_, is_svg_text_, @@ -691,6 +692,8 @@ // regardless of 'text-indent'. position_ = line_info->TextIndent(); + disable_score_line_break_ = false; + has_cloned_box_decorations_ = false; if (UNLIKELY((break_token_ && break_token_->HasClonedBoxDecorations()) || cloned_box_decorations_count_)) @@ -2875,6 +2878,7 @@ if (UNLIKELY(style.BoxDecorationBreak() == EBoxDecorationBreak::kClone)) { // Compute even when no margins/borders/padding to ensure correct counting. has_cloned_box_decorations_ = true; + disable_score_line_break_ = true; ++cloned_box_decorations_count_; cloned_box_decorations_end_size_ += item_result->margins.inline_end + item_result->borders.inline_end + @@ -3080,8 +3084,12 @@ // Reaching here means that the rewind point was not found. if (!override_break_anywhere_ && has_break_anywhere_if_overflow) { + // Overflow occurred but `overflow-wrap` is set. Change the break type and + // retry the line breaking. override_break_anywhere_ = true; break_iterator_.SetBreakType(LineBreakType::kBreakCharacter); + // `NGScoreLineBreaker` doesn't support multi-pass line breaking. + disable_score_line_break_ = true; state_ = LineBreakState::kContinue; // TODO(kojii): Not all items need to rewind, but such case is rare and // rewinding all items simplifes the code. @@ -3094,6 +3102,12 @@ // Let this line overflow. line_info->SetHasOverflow(); + // TODO(kojii): `NGScoreLineBreaker::ComputeScores` gets confused if there're + // overflowing lines. Disable the score line break for now. E.g.: + // css2.1/t1601-c547-indent-01-d.html + // virtual/text-antialias/international/bdi-neutral-wrapped.html + disable_score_line_break_ = true; + // Restore the hyphenation states to before the loop if needed. DCHECK(!HasHyphen()); if (UNLIKELY(hyphen_index_before)) @@ -3408,6 +3422,7 @@ if (style.ShouldBreakSpaces()) { break_iterator_.SetBreakSpace(BreakSpaceType::kAfterEverySpace); + disable_score_line_break_ = true; } break_iterator_.SetLocale(style.LocaleForLineBreakIterator());
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h index ac186df..b9791c15 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h
@@ -63,6 +63,12 @@ bool IsFinished() const { return current_.item_index >= Items().size(); } + // True if there are items that `NGScoreLineBreaker` doesn't support. + // Conditions that can be determined by `CollectInlines` are done by + // `NGInlineNode::IsScoreLineBreakDisabled()`, but some conditions can change + // withoiut `CollectInlines`. They are determined by this. + bool ShouldDisableScoreLineBreak() const { return disable_score_line_break_; } + // Override the available width to compute line breaks. This is reset after // each `NextLine`. void OverrideAvailableWidth(LayoutUnit available_width); @@ -304,6 +310,8 @@ // True when breaking at soft hyphens (U+00AD) is allowed. bool enable_soft_hyphen_ = true; + bool disable_score_line_break_ = false; + // True when the line should be non-empty if |IsLastLine|.. bool force_non_empty_if_last_line_ = false;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_score_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_score_line_breaker.cc index de2e66a77..259419c 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_score_line_breaker.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_score_line_breaker.cc
@@ -47,6 +47,10 @@ for (;;) { NGLineInfo& line_info = line_info_list.Append(); line_breaker.NextLine(&line_info); + if (UNLIKELY(line_breaker.ShouldDisableScoreLineBreak())) { + context.SuspendUntilConsumed(); + return; + } if (!line_info.BreakToken() || line_info.HasForcedBreak()) { context.SuspendUntilConsumed(); break;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_score_line_breaker_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_score_line_breaker_test.cc index a47d4be6..31ecf59e 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_score_line_breaker_test.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_score_line_breaker_test.cc
@@ -138,4 +138,118 @@ EXPECT_NE(line_info_list.Size(), 3u); } +struct DisabledByLineBreakerData { + bool disabled; + const char* html; +} disabled_by_line_breaker_data[] = { + // Normal, should not be disabled. + {false, R"HTML( + <div id="target"> + 0123 5678 + 1234 6789 + 234 67890 + 45 + </div> + )HTML"}, + // Overflowing lines should disable. + {true, R"HTML( + <div id="target"> + 0123 5678 + 123456789012 + 23 567 90 + 45 + </div> + )HTML"}, + // `overflow-wrap` should be ok, except... + {false, R"HTML( + <div id="target" style="overflow-wrap: anywhere"> + 0123 5678 + 1234 6789 + 23 567 90 + 45 + </div> + )HTML"}, + {false, R"HTML( + <div id="target" style="overflow-wrap: break-word"> + 0123 5678 + 1234 6789 + 23 567 90 + 45 + </div> + )HTML"}, + // ...when there're overflows. + {true, R"HTML( + <div id="target" style="overflow-wrap: anywhere"> + 0123 5678 + 123456789012 + 23 567 90 + 45 + </div> + )HTML"}, + {true, R"HTML( + <div id="target" style="overflow-wrap: break-word"> + 0123 5678 + 123456789012 + 23 567 90 + 45 + </div> + )HTML"}, + // `break-sapces` is not supported. + {true, R"HTML( + <div id="target" style="white-space: break-spaces"> + 0123 5678 + 1234 6789 + 23 567 90 + 45 + </div> + )HTML"}, + // `box-decoration-break: clone` is not supported. + {true, R"HTML( + <div id="target"> + 0123 5678 + 1234 6789 + 23 <span style="-webkit-box-decoration-break: clone">567</span> 90 + 45 + </div> + )HTML"}}; + +class DisabledByLineBreakerTest + : public NGScoreLineBreakerTest, + public testing::WithParamInterface<DisabledByLineBreakerData> {}; + +INSTANTIATE_TEST_SUITE_P(NGScoreLineBreakerTest, + DisabledByLineBreakerTest, + testing::ValuesIn(disabled_by_line_breaker_data)); + +TEST_P(DisabledByLineBreakerTest, Data) { + const auto& data = GetParam(); + LoadAhem(); + SetBodyInnerHTML(String(R"HTML( + <!DOCTYPE html> + <style> + #target { + font-family: Ahem; + font-size: 10px; + width: 10ch; + } + </style> + )HTML") + data.html); + const NGInlineNode node = GetInlineNodeByElementId("target"); + const NGPhysicalBoxFragment* fragment = + node.GetLayoutBox()->GetPhysicalFragment(0); + const LayoutUnit width = fragment->Size().width; + NGConstraintSpace space = ConstraintSpaceForAvailableSize(width); + NGLineLayoutOpportunity line_opportunity(width); + NGScoreLineBreakContext context; + NGScoreLineBreaker optimizer(node, space, line_opportunity); + const NGInlineBreakToken* break_token = nullptr; + optimizer.OptimalBreakPoints(break_token, context); + EXPECT_FALSE(context.IsActive()); + if (data.disabled) { + EXPECT_EQ(context.LineBreakPoints().size(), 0u); + } else { + EXPECT_NE(context.LineBreakPoints().size(), 0u); + } +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 index f2b78ed..750c9a4 100644 --- a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 +++ b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
@@ -1174,7 +1174,7 @@ default_value: "false", }, { - name: "IsPseudoInitialStyle", + name: "IsStartingStyle", field_template: "monotonic_flag", type_name: "bool", field_group: "*",
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 15055e8c..51886f1 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -3100,6 +3100,20 @@ implied_by: ["AnimationWorklet", "ScrollTimelineCurrentTime"] }, { + // Support for scroll/view-timeline-attachment. + // + // This feature was intially specified in scroll-animations-1, + // but was since removed by a resolution in Issue 7759. + // + // The properties will remain available behind this flag until + // all WPTs are adjusted to the new API (see feature TimelineScope). + // + // https://github.com/w3c/csswg-drafts/issues/7759 + // https://crbug.com/1446702 + name: "ScrollTimelineAttachment", + status: "test" + }, + { // Separate flag for crbug.com/1426506 (getCurrentTime API change) which // is expected to land after the initial launch of ScrollTimeline. name: "ScrollTimelineCurrentTime",
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests index 423989b..5a3ec79 100644 --- a/third_party/blink/web_tests/SlowTests +++ b/third_party/blink/web_tests/SlowTests
@@ -346,7 +346,8 @@ crbug.com/1081534 [ Mac10.15 Release ] virtual/oopr-canvas2d/fast/canvas/canvas-composite-transformclip.html [ Slow ] crbug.com/1081534 [ Mac11 Release ] virtual/oopr-canvas2d/fast/canvas/canvas-composite-transformclip.html [ Slow ] crbug.com/1081534 [ Mac12 ] virtual/oopr-canvas2d/fast/canvas/canvas-composite-transformclip.html [ Slow ] -crbug.com/1081534 [ Mac ] virtual/oopr-canvas2d/fast/canvas/canvas-composite-video-shadow.html [ Slow ] +crbug.com/1081534 [ Debug Mac12 ] virtual/oopr-canvas2d/fast/canvas/canvas-composite-video-shadow.html [ Slow ] +crbug.com/1081534 [ Mac10.14 Release ] virtual/oopr-canvas2d/fast/canvas/canvas-composite-video-shadow.html [ Slow ] crbug.com/1081534 [ Mac ] virtual/oopr-canvas2d/fast/canvas/canvas-composite-video.html [ Slow ] crbug.com/1081534 [ Debug Mac12 ] virtual/oopr-canvas2d/fast/canvas/canvas-blending-gradient-over-image.html [ Slow ] crbug.com/1081534 [ Mac ] virtual/oopr-canvas2d/fast/canvas/canvas-blending-gradient-over-pattern.html [ Slow ] @@ -1038,7 +1039,6 @@ crbug.com/886566 [ Mac11 Release ] http/tests/csspaint/invalidation-background-image.html [ Slow ] crbug.com/886566 [ Mac12 ] http/tests/csspaint/invalidation-background-image.html [ Slow ] crbug.com/886566 [ Mac12-arm64 Release ] http/tests/csspaint/invalidation-background-image.html [ Slow ] -crbug.com/886566 [ Debug Mac13-arm64 ] http/tests/csspaint/invalidation-content-image.html [ Slow ] crbug.com/886566 [ Linux ] http/tests/csspaint/invalidation-content-image.html [ Slow ] crbug.com/886566 [ Mac10.15 Release ] http/tests/csspaint/invalidation-content-image.html [ Slow ] crbug.com/886566 [ Mac11 Release ] http/tests/csspaint/invalidation-content-image.html [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 86657ef..bd6ee2b 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -883,7 +883,6 @@ crbug.com/1042783 external/wpt/css/css-backgrounds/background-size/background-size-near-zero-svg.html [ Failure ] # Passes with the WPT runner but not the internal one. (???) -crbug.com/1175040 external/wpt/css/css-backgrounds/background-repeat-space-1c.html [ Failure Pass ] crbug.com/1175040 external/wpt/css/css-backgrounds/background-repeat-space-4.html [ Failure Pass ] # Off-by-one in some components. @@ -1824,7 +1823,7 @@ # Popover test timeout/flakiness crbug.com/1416284 external/wpt/html/semantics/popovers/popover-attribute-basic.html [ Pass Timeout ] -crbug.com/1443372 external/wpt/html/semantics/popovers/popover-hover-hide.tentative.html [ Failure Pass ] +crbug.com/1443372 [ Mac ] external/wpt/html/semantics/popovers/popover-hover-hide.tentative.html [ Failure Pass ] # Only virtual/threaded version of these tests pass (or running them with --enable-threaded-compositing). crbug.com/936891 fast/scrolling/document-level-touchmove-event-listener-passive-by-default.html [ Failure ] @@ -2061,7 +2060,6 @@ crbug.com/1218716 external/wpt/trust-tokens/trust-token-parameter-validation.tentative.https.html [ Failure ] crbug.com/1218716 external/wpt/feature-policy/experimental-features/trust-token-redemption-default-feature-policy.tentative.https.sub.html [ Failure ] crbug.com/1218716 external/wpt/feature-policy/experimental-features/trust-token-redemption-supported-by-feature-policy.tentative.html [ Failure ] -crbug.com/1218716 external/wpt/permissions-policy/experimental-features/trust-token-redemption-default-permissions-policy.tentative.https.sub.html [ Failure ] # Sheriff 2020-02-06 @@ -2898,6 +2896,8 @@ crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Mac12 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/css/animation-timeline-view-functional-notation.tentative.html [ Timeout ] +crbug.com/626703 [ Mac12 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/css/scroll-timeline-dynamic.tentative.html [ Timeout ] crbug.com/626703 [ Mac13 ] external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-video.html [ Failure ] crbug.com/626703 external/wpt/html/rendering/non-replaced-elements/tables/table-bordercolor-001.html [ Failure ] crbug.com/626703 [ Mac13 ] external/wpt/html/semantics/embedded-content/media-elements/ready-states/autoplay-hidden.optional.html [ Timeout ] @@ -5380,7 +5380,9 @@ # Sheriff 2021-11-29 crbug.com/1274458 external/wpt/audio-output/selectAudioOutput-permissions-policy.https.sub.html [ Failure Pass ] -crbug.com/1239485 [ Mac ] fast/frames/iframe-plugin-load-remove-document-crash.html [ Failure Pass ] +crbug.com/1239485 [ Debug Mac12 ] fast/frames/iframe-plugin-load-remove-document-crash.html [ Failure Pass ] +crbug.com/1239485 [ Debug Mac13-arm64 ] fast/frames/iframe-plugin-load-remove-document-crash.html [ Failure Pass ] +crbug.com/1239485 [ Mac Release ] fast/frames/iframe-plugin-load-remove-document-crash.html [ Failure Pass ] # Sheriff 2021-12-01 crbug.com/1275658 http/tests/misc/script-after-slow-stylesheet-removed.html [ Failure Pass ] @@ -5438,8 +5440,7 @@ # Sheriff 2022-01-17 crbug.com/1233938 http/tests/notifications/click-shared-worker.html [ Pass Timeout ] -# Temporarily disable test to allow fixing of devtools path escaping -crbug.com/1094436 http/tests/devtools/overrides/project-added-with-existing-files-bind.js [ Failure Timeout ] +crbug.com/1094436 [ Win ] http/tests/devtools/overrides/project-added-with-existing-files-bind.js [ Failure Timeout ] crbug.com/1256763 virtual/gpu-rasterization/images/color-profile-background-image-cover.html [ Failure Pass ] # Sheriff 2022-01-18 @@ -5998,7 +5999,7 @@ crbug.com/1370050 http/tests/devtools/sources/debugger-ui/debugger-save-to-temp-var.js [ Crash Failure Pass Timeout ] -crbug.com/1279220 [ Win ] virtual/percent-based-scrolling/fast/scrolling/scrollbars/touch-scrolling-on-root-scrollbar.html [ Pass Timeout ] +crbug.com/1279220 [ Win10.20h2 ] virtual/percent-based-scrolling/fast/scrolling/scrollbars/touch-scrolling-on-root-scrollbar.html [ Pass Timeout ] crbug.com/1279220 [ Linux ] fast/scrolling/non-composited-scroller-in-position-fixed-scroller.html [ Failure Pass ] # Sheriff 2022-10-12
diff --git a/third_party/blink/web_tests/css-parser/offset-path-parsing.html b/third_party/blink/web_tests/css-parser/offset-path-parsing.html index 29618b0..9a55d372 100644 --- a/third_party/blink/web_tests/css-parser/offset-path-parsing.html +++ b/third_party/blink/web_tests/css-parser/offset-path-parsing.html
@@ -8,7 +8,7 @@ assert_valid_value("offset-path", "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 300 300 Z')", "path(\"M 0 0 L 100 100 M 100 200 L 200 200 Z L 300 300 Z\")"); assert_valid_value("offset-path", "none"); -assert_valid_value("offset-path", "path('')", "none"); +assert_invalid_value("offset-path", "path('')"); assert_invalid_value("offset-path", "path('M 20 30 A 60 70 80')"); assert_valid_value("offset-path", "ray(45deg closest-side)", "ray(45deg)");
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 7c296af..f274d3f4 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
@@ -272644,11 +272644,11 @@ "support": { ".cache": { "gitignore2.json": [ - "42968047be3e44ee65274686cc2e3a1bb5fa8606", + "d4c040145f13b144ecaf45886be5b591f643219f", [] ], "mtime.json": [ - "d6f12464231664ed4dc4e35783d2404b911d0c25", + "e78affcda8cd07af74fcd2f203c9dd53682c577b", [] ] }, @@ -287812,7 +287812,7 @@ [] ], "mix-blend-mode-blended-element-overflow-scroll.html.ini": [ - "053f4729ef2a7f1d42253a93d30aea86716f659e", + "568f0e7abc4646cd0566dce948867e0bc0dc9273", [] ], "mix-blend-mode-blended-with-3D-transform.html.ini": [ @@ -293058,6 +293058,10 @@ "a8157aa752192e39da0911705d61fb863dba20df", [] ], + "at-supports-005.html.ini": [ + "66b03e7c3776b2a7f3e188e78c27ba437b9e6d1f", + [] + ], "at-supports-020.html.ini": [ "7e3b32f278a62b45cd7587c3f7aca705c2f5bef1", [] @@ -329884,7 +329888,7 @@ [] ], "kind-of-widget-fallback-color-input-border-left-width-001.html.ini": [ - "790ec0a2515cffe6f8324353c2a9273a6a1ebb11", + "08861083c05fd6e1fb2d809a3e5e8dddb53b63a6", [] ], "kind-of-widget-fallback-color-input-border-right-width-001.html.ini": [ @@ -330036,7 +330040,7 @@ [] ], "kind-of-widget-fallback-input-reset-border-inline-end-color-001.html.ini": [ - "57c6eb8f88bb60ce4dac4ee4d4727c8597a0c812", + "66c7da025d0886badcf669df11d4f89fe7ea4e98", [] ], "kind-of-widget-fallback-input-reset-border-inline-end-style-001.html.ini": [ @@ -330360,7 +330364,7 @@ [] ], "kind-of-widget-fallback-input-submit-border-end-end-radius-001.html.ini": [ - "1b2c05ec9c382ccf8393e5320fc0a5827c88ab81", + "9fb5aa8b0650b8c93494d521c3bb94d17e6b018e", [] ], "kind-of-widget-fallback-input-submit-border-end-start-radius-001.html.ini": [ @@ -337613,7 +337617,7 @@ [] ], "css-backdrop-filters-animation-invert.html.ini": [ - "492c00de3346a4aef908b76632552234314f2ef7", + "ec644098dbfc8d1054429c056933ed78e5ff623e", [] ], "css-backdrop-filters-animation-opacity-ref.html": [ @@ -368814,6 +368818,14 @@ "9354d4270305882f80a7110aa1fd6adb2ffc7295", [] ], + "script-type-whitespace-expected.txt": [ + "9fbeb3c045a2c82913225ff58e231d9a1860e0f8", + [] + ], + "script-type-whitespace.html.ini": [ + "d929799f1482dce79f4a9a5eee916ba7d1829003", + [] + ], "serve-json-then-js.py": [ "9610734d4449794d1eb10032a1bac75cd4523b40", [] @@ -380422,7 +380434,7 @@ [] ], "modulepreload-as.html.ini": [ - "344d5e663f13d94b5326ee18fcd7f2ac344a97c6", + "acb7550601585efe5b4d6502a95624d4556562c7", [] ], "modulepreload-expected.txt": [ @@ -561252,6 +561264,13 @@ {} ] ], + "script-type-whitespace.html": [ + "5e8acb1a17bace7ad5f55ac9a3545bbb1220ae10", + [ + null, + {} + ] + ], "scripting-enabled.html": [ "a2671a78f69c1f0065892fbeba81e872163c756e", [
diff --git a/third_party/blink/web_tests/external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-overflow-scroll.html.ini b/third_party/blink/web_tests/external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-overflow-scroll.html.ini index 053f4729..568f0e7 100644 --- a/third_party/blink/web_tests/external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-overflow-scroll.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-blended-element-overflow-scroll.html.ini
@@ -1,6 +1,7 @@ [mix-blend-mode-blended-element-overflow-scroll.html] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-conditional/at-supports-005.html.ini b/third_party/blink/web_tests/external/wpt/css/css-conditional/at-supports-005.html.ini new file mode 100644 index 0000000..66b03e7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-conditional/at-supports-005.html.ini
@@ -0,0 +1,3 @@ +[at-supports-005.html] + expected: + if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-color-input-border-left-width-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-color-input-border-left-width-001.html.ini index 790ec0a..0886108 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-color-input-border-left-width-001.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-color-input-border-left-width-001.html.ini
@@ -1,3 +1,4 @@ [kind-of-widget-fallback-color-input-border-left-width-001.html] expected: + if (product == "content_shell") and (os == "linux"): FAIL if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-reset-border-inline-end-color-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-reset-border-inline-end-color-001.html.ini index 57c6eb8f..66c7da0 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-reset-border-inline-end-color-001.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-reset-border-inline-end-color-001.html.ini
@@ -1,3 +1,4 @@ [kind-of-widget-fallback-input-reset-border-inline-end-color-001.html] expected: + if (product == "content_shell") and (os == "win") and (port == "win11"): FAIL if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-end-end-radius-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-end-end-radius-001.html.ini index 1b2c05e..9fb5aa8 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-end-end-radius-001.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-end-end-radius-001.html.ini
@@ -1,3 +1,3 @@ [kind-of-widget-fallback-input-submit-border-end-end-radius-001.html] expected: - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): FAIL + if (product == "content_shell") and (os == "win"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-invert.html.ini b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-invert.html.ini index 492c00de..ec64409 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-invert.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-invert.html.ini
@@ -1,4 +1,5 @@ [css-backdrop-filters-animation-invert.html] expected: + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/motion/parsing/offset-parsing-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/motion/parsing/offset-parsing-valid-expected.txt index 973c0d1..82b61e30 100644 --- a/third_party/blink/web_tests/external/wpt/css/motion/parsing/offset-parsing-valid-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/motion/parsing/offset-parsing-valid-expected.txt
@@ -1,7 +1,7 @@ This is a testharness.js-based test. PASS e.style['offset'] = "100px none auto 90deg" should set the property value PASS e.style['offset'] = "100px" should set the property value -FAIL e.style['offset'] = "auto none reverse" should set the property value assert_equals: serialization should be canonical expected "none reverse" but got "auto none reverse" +PASS e.style['offset'] = "auto none reverse" should set the property value PASS e.style['offset'] = "auto" should set the property value PASS e.style['offset'] = "center bottom path(\"M 1 2 V 3 Z\")" should set the property value PASS e.style['offset'] = "center center path(\"M 0 0 L 100 100 M 100 200 L 200 200 Z L 300 300 Z\") 100% 90deg / left bottom" should set the property value @@ -9,18 +9,18 @@ PASS e.style['offset'] = "left top" should set the property value PASS e.style['offset'] = "none 30deg reverse" should set the property value PASS e.style['offset'] = "none 50px reverse 30deg" should set the property value -FAIL e.style['offset'] = "none calc(10px + 20%) auto" should set the property value assert_equals: serialization should be canonical expected "none calc(20% + 10px)" but got "none calc(10px + 20%) auto" +FAIL e.style['offset'] = "none calc(10px + 20%) auto" should set the property value assert_equals: serialization should be canonical expected "none calc(20% + 10px)" but got "none calc(10px + 20%)" PASS e.style['offset'] = "none reverse" should set the property value -FAIL e.style['offset'] = "path(\"M 0 0 H 1\") -200% auto" should set the property value assert_equals: serialization should be canonical expected "path(\"M 0 0 H 1\") -200%" but got "path(\"M 0 0 H 1\") -200% auto" +PASS e.style['offset'] = "path(\"M 0 0 H 1\") -200% auto" should set the property value PASS e.style['offset'] = "path(\"M 0 0 H 1\") -200%" should set the property value PASS e.style['offset'] = "path('M 0 0 H 1') 50px" should set the property value -FAIL e.style['offset'] = "path(\"M 0 0 H 1\") auto" should set the property value assert_equals: serialization should be canonical expected "path(\"M 0 0 H 1\")" but got "path(\"M 0 0 H 1\") auto" -FAIL e.style['offset'] = "path(\"M 0 0 H 1\") auto 0deg" should set the property value assert_equals: serialization should be canonical expected "path(\"M 0 0 H 1\")" but got "path(\"M 0 0 H 1\") auto 0deg" -FAIL e.style['offset'] = "path(\"M 0 0 H 1\") auto 0rad" should set the property value assert_equals: serialization should be canonical expected "path(\"M 0 0 H 1\")" but got "path(\"M 0 0 H 1\") auto 0rad" +PASS e.style['offset'] = "path(\"M 0 0 H 1\") auto" should set the property value +PASS e.style['offset'] = "path(\"M 0 0 H 1\") auto 0deg" should set the property value +PASS e.style['offset'] = "path(\"M 0 0 H 1\") auto 0rad" should set the property value PASS e.style['offset'] = "path(\"M 0 0 H 1\") auto 0.5turn" should set the property value PASS e.style['offset'] = "path('M 0 0 H 1') reverse 30deg 50px" should set the property value PASS e.style['offset'] = "path(\"M 0 0 H 1\")" should set the property value -FAIL e.style['offset'] = "path('m 20 0 h 100') -7rad 8px / auto" should set the property value assert_equals: serialization should be canonical expected "path(\"m 20 0 h 100\") 8px -7rad" but got "path(\"m 20 0 h 100\") 8px -7rad / auto" +PASS e.style['offset'] = "path('m 20 0 h 100') -7rad 8px / auto" should set the property value PASS e.style['offset'] = "path('m 0 30 v 100') -7rad 8px / left top" should set the property value PASS e.style['offset'] = "path('m 0 0 h 100') -7rad 8px" should set the property value PASS e.style['offset'] = "path(\"M 0 0 H 100\") 100px 0deg" should set the property value
diff --git a/third_party/blink/web_tests/external/wpt/css/motion/parsing/offset-path-parsing-invalid-expected.txt b/third_party/blink/web_tests/external/wpt/css/motion/parsing/offset-path-parsing-invalid-expected.txt deleted file mode 100644 index e59f46f7..0000000 --- a/third_party/blink/web_tests/external/wpt/css/motion/parsing/offset-path-parsing-invalid-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ -This is a testharness.js-based test. -PASS e.style['offset-path'] = "path(\"M 20 30 A 60 70 80\")" should not set the property value -FAIL e.style['offset-path'] = "path(\"\")" should not set the property value assert_equals: expected "" but got "none" -FAIL e.style['offset-path'] = "path(\" \")" should not set the property value assert_equals: expected "" but got "none" -PASS e.style['offset-path'] = "ray(0 sides)" should not set the property value -PASS e.style['offset-path'] = "ray(closest-side)" should not set the property value -PASS e.style['offset-path'] = "ray(closest-side 0deg closest-side)" should not set the property value -PASS e.style['offset-path'] = "ray(0deg closest-side 0deg)" should not set the property value -PASS e.style['offset-path'] = "ray(contain 0deg closest-side contain)" should not set the property value -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/motion/parsing/offset-shorthand-expected.txt b/third_party/blink/web_tests/external/wpt/css/motion/parsing/offset-shorthand-expected.txt deleted file mode 100644 index f588c32..0000000 --- a/third_party/blink/web_tests/external/wpt/css/motion/parsing/offset-shorthand-expected.txt +++ /dev/null
@@ -1,21 +0,0 @@ -This is a testharness.js-based test. -PASS e.style['offset'] = "left bottom ray(0rad closest-corner) 10px auto 30deg / right bottom" should set offset-anchor -PASS e.style['offset'] = "left bottom ray(0rad closest-corner) 10px auto 30deg / right bottom" should set offset-distance -PASS e.style['offset'] = "left bottom ray(0rad closest-corner) 10px auto 30deg / right bottom" should set offset-path -PASS e.style['offset'] = "left bottom ray(0rad closest-corner) 10px auto 30deg / right bottom" should set offset-position -PASS e.style['offset'] = "left bottom ray(0rad closest-corner) 10px auto 30deg / right bottom" should set offset-rotate -PASS e.style['offset'] = "left bottom ray(0rad closest-corner) 10px auto 30deg / right bottom" should not set unrelated longhands -PASS e.style['offset'] = "top right / top left" should set offset-anchor -FAIL e.style['offset'] = "top right / top left" should set offset-distance assert_equals: offset-distance should be canonical expected "0px" but got "initial" -FAIL e.style['offset'] = "top right / top left" should set offset-path assert_equals: offset-path should be canonical expected "none" but got "initial" -PASS e.style['offset'] = "top right / top left" should set offset-position -FAIL e.style['offset'] = "top right / top left" should set offset-rotate assert_equals: offset-rotate should be canonical expected "auto" but got "initial" -PASS e.style['offset'] = "top right / top left" should not set unrelated longhands -FAIL e.style['offset'] = "path(\"M 0 0 H 2\") reverse 50%" should set offset-anchor assert_equals: offset-anchor should be canonical expected "auto" but got "initial" -PASS e.style['offset'] = "path(\"M 0 0 H 2\") reverse 50%" should set offset-distance -PASS e.style['offset'] = "path(\"M 0 0 H 2\") reverse 50%" should set offset-path -FAIL e.style['offset'] = "path(\"M 0 0 H 2\") reverse 50%" should set offset-position assert_equals: offset-position should be canonical expected "auto" but got "initial" -PASS e.style['offset'] = "path(\"M 0 0 H 2\") reverse 50%" should set offset-rotate -PASS e.style['offset'] = "path(\"M 0 0 H 2\") reverse 50%" should not set unrelated longhands -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/script-type-whitespace-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/script-type-whitespace-expected.txt new file mode 100644 index 0000000..9fbeb3c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/script-type-whitespace-expected.txt
@@ -0,0 +1,8 @@ +This is a testharness.js-based test. +FAIL Script shouldn't run with type="text/javascript" (parser-inserted) assert_false: expected false got true +PASS Script shouldn't run with type="text/javascript…" (parser-inserted) +PASS Script shouldn't run with type="text/javascript " (parser-inserted) +FAIL Script shouldn't run with type="text/javascript " (parser-inserted) assert_false: expected false got true +FAIL Script shouldn't run with type="text/javascript " (parser-inserted) assert_false: expected false got true +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/script-type-whitespace.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/script-type-whitespace.html new file mode 100644 index 0000000..5e8acb1a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/script-type-whitespace.html
@@ -0,0 +1,27 @@ +<!doctype html> +<title><script type> non-ASCII whitespace handling</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> +function testParserInsertedDidNotRun(description) { + test(() => assert_false(window.ran), + "Script shouldn't run with " + description + " (parser-inserted)"); + window.ran = false; +} +</script> + +<script>window.ran = false;</script> +<script type="text/javascript">window.ran = true;</script> +<script>testParserInsertedDidNotRun("type=\"text/javascript\"");</script> + +<script type="text/javascript…">window.ran = true;</script> +<script>testParserInsertedDidNotRun("type=\"text/javascript…\"");</script> + +<script type="text/javascript ">window.ran = true;</script> +<script>testParserInsertedDidNotRun("type=\"text/javascript \"");</script> + +<script type="text/javascript ">window.ran = true;</script> +<script>testParserInsertedDidNotRun("type=\"text/javascript \"");</script> + +<script type="text/javascript ">window.ran = true;</script> +<script>testParserInsertedDidNotRun("type=\"text/javascript \"");</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/script-type-whitespace.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/script-type-whitespace.html.ini new file mode 100644 index 0000000..d929799 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/script-type-whitespace.html.ini
@@ -0,0 +1,9 @@ +[script-type-whitespace.html] + [Script shouldn't run with type="text/javascript" (parser-inserted)] + expected: FAIL + + [Script shouldn't run with type="text/javascript " (parser-inserted)] + expected: FAIL + + [Script shouldn't run with type="text/javascript " (parser-inserted)] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini b/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini index 344d5e6..acb7550 100644 --- a/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini +++ b/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini
@@ -1,174 +1,171 @@ [modulepreload-as.html] expected: + if (product == "content_shell") and (os == "win") and (port == "win11"): [TIMEOUT, ERROR] if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): TIMEOUT - if (product == "content_shell") and (os == "mac") and (port == "mac11"): OK if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): OK if (product == "content_shell") and (os == "mac") and (port == "mac12"): OK - if product == "chrome": [ERROR, TIMEOUT] + if (product == "content_shell") and (os == "mac") and (port == "mac11"): OK + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [ERROR, OK] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [ERROR, TIMEOUT] ERROR - [Modulepreload with as=""] - expected: - if product == "chrome": [PASS, TIMEOUT] - [Modulepreload with as="audio"] expected: - if product == "chrome": [FAIL, NOTRUN] + if (product == "content_shell") and (os == "win") and (port == "win11"): [FAIL, PASS] FAIL [Modulepreload with as="audioworklet"] - expected: - if product == "chrome": [FAIL, NOTRUN] - FAIL + expected: FAIL [Modulepreload with as="document"] expected: - if product == "chrome": [FAIL, NOTRUN] + if (product == "content_shell") and (os == "win") and (port == "win11"): [FAIL, PASS] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS] FAIL [Modulepreload with as="embed"] expected: - if (product == "content_shell") and (os == "linux"): PASS - if product == "chrome": [FAIL, NOTRUN, PASS] + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS] FAIL [Modulepreload with as="fetch"] expected: - if (product == "content_shell") and (os == "win") and (port == "win11"): PASS - if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): PASS + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL] if (product == "content_shell") and (os == "linux"): PASS - if product == "chrome": [PASS, NOTRUN] + if product == "chrome": PASS FAIL [Modulepreload with as="font"] expected: + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS - if product == "chrome": [PASS, NOTRUN, FAIL] + if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL] + if product == "chrome": PASS FAIL [Modulepreload with as="frame"] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL - if product == "chrome": [PASS, NOTRUN, FAIL] + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS + if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL] + if product == "chrome": PASS + FAIL [Modulepreload with as="iMaGe"] expected: + if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL] + if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL] + if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL - if product == "chrome": [PASS, NOTRUN] [Modulepreload with as="iframe"] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS - if (product == "content_shell") and (os == "win") and (port == "win11"): PASS if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS - if product == "chrome": [PASS, NOTRUN] + if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL] + if product == "chrome": PASS FAIL [Modulepreload with as="image"] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL - if product == "chrome": [PASS, NOTRUN] + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS + if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL] + if product == "chrome": PASS + FAIL [Modulepreload with as="invalid-dest"] - expected: - if product == "chrome": [FAIL, NOTRUN] - FAIL + expected: FAIL [Modulepreload with as="manifest"] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL - if product == "chrome": [PASS, NOTRUN] + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS + if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL] + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS + if product == "chrome": PASS + FAIL [Modulepreload with as="object"] expected: if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL] + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL - if product == "chrome": [PASS, NOTRUN] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] + if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL] [Modulepreload with as="paintworklet"] - expected: - if product == "chrome": [FAIL, NOTRUN] - FAIL + expected: FAIL [Modulepreload with as="report"] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL - if product == "chrome": [PASS, NOTRUN] - - [Modulepreload with as="sCrIpT"] - expected: - if product == "chrome": [PASS, NOTRUN] - - [Modulepreload with as="script"] - expected: - if product == "chrome": [PASS, NOTRUN] + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL] [Modulepreload with as="serviceworker"] - expected: - if product == "chrome": [FAIL, NOTRUN] - FAIL + expected: FAIL [Modulepreload with as="sharedworker"] - expected: - if product == "chrome": [FAIL, NOTRUN] - FAIL + expected: FAIL [Modulepreload with as="style"] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "win") and (port == "win11"): [FAIL, PASS] if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS - if product == "chrome": [PASS, NOTRUN, FAIL] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] + if product == "chrome": PASS FAIL [Modulepreload with as="track"] expected: - if (product == "content_shell") and (os == "win") and (port == "win11"): PASS - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS - if product == "chrome": [PASS, NOTRUN] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] + if (product == "content_shell") and (os == "win") and (port == "win11"): [FAIL, PASS] + if product == "chrome": PASS FAIL [Modulepreload with as="video"] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS - if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS - if product == "chrome": [PASS, NOTRUN] + if (product == "content_shell") and (os == "win") and (port == "win11"): [FAIL, PASS] + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "linux"): PASS + if product == "chrome": PASS FAIL [Modulepreload with as="webidentity"] expected: - if (product == "content_shell") and (os == "win") and (port == "win11"): PASS + if (product == "content_shell") and (os == "win") and (port == "win11"): [FAIL, PASS] + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] if (product == "content_shell") and (os == "linux"): PASS - if product == "chrome": [PASS, NOTRUN] + if product == "chrome": PASS FAIL [Modulepreload with as="worker"] - expected: - if product == "chrome": [FAIL, NOTRUN] - FAIL + expected: FAIL [Modulepreload with as="xslt"] expected: - if (product == "content_shell") and (os == "win") and (port == "win11"): PASS + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "win") and (port == "win11"): [FAIL, PASS] if (product == "content_shell") and (os == "linux"): PASS - if product == "chrome": [PASS, NOTRUN] + if product == "chrome": PASS FAIL
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/css/animation-timeline-deferred.html b/third_party/blink/web_tests/external/wpt/scroll-animations/css/animation-timeline-deferred.html new file mode 100644 index 0000000..d0671e5f2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/css/animation-timeline-deferred.html
@@ -0,0 +1,109 @@ +<!DOCTYPE html> +<title>Deferred timelines via Animation.timeline</title> +<link rel="help" src="https://github.com/w3c/csswg-drafts/issues/7759"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/web-animations/testcommon.js"></script> + +<main id=main></main> +<script> + function inflate(t, template) { + t.add_cleanup(() => main.replaceChildren()); + main.append(template.content.cloneNode(true)); + main.offsetTop; + } + + async function scrollTop(e, value) { + e.scrollTop = value; + await waitForNextFrame(); + } +</script> +<style> + @keyframes anim { + from { width: 0px; } + to { width: 200px; } + } + .scroller { + overflow-y: hidden; + width: 200px; + height: 200px; + } + .scroller > .content { + margin: 400px 0px; + width: 100px; + height: 100px; + background-color: green; + } + .animating { + background-color: coral; + width: 0px; + animation: anim auto linear; + animation-timeline: --t1; + } + .timeline { + scroll-timeline-name: --t1; + } + .scope { + timeline-scope: --t1; + } +</style> + +<template id=animation_timeline_attached> + <div class="scope"> + <div class=animating>Test</div> + <div class="scroller timeline"> + <div class="content animating"></div> + </div> + </div> +</template> +<script> + promise_test(async (t) => { + inflate(t, animation_timeline_attached); + let scroller = main.querySelector('.scroller'); + let animating = Array.from(main.querySelectorAll('.animating')); + + assert_equals(animating.length, 2); + let animations = animating.map((e) => e.getAnimations()[0]); + assert_equals(animations.length, 2); + + // animations[0] is attached via deferred timeline (timeline-scope), + // and animations[1] is attached directly. + assert_equals(animations[0].timeline, animations[1].timeline); + }, 'Animation.timeline returns attached timeline'); +</script> + +<template id=animation_timeline_inactive> + <div class="scope"> + <div class=animating>Test</div> + </div> +</template> +<script> + promise_test(async (t) => { + inflate(t, animation_timeline_inactive); + let scroller = main.querySelector('.scroller'); + let animating = main.querySelector('.animating'); + + assert_equals(animating.getAnimations()[0].timeline, null); + }, 'Animation.timeline returns null for inactive deferred timeline'); +</script> + +<template id=animation_timeline_overattached> + <div class="scope"> + <div class=animating>Test</div> + <div class="scroller timeline"> + <div class="content"></div> + </div> + <div class="scroller timeline"> + <div class="content"></div> + </div> + </div> +</template> +<script> + promise_test(async (t) => { + inflate(t, animation_timeline_overattached); + let scroller = main.querySelector('.scroller'); + let animating = main.querySelector('.animating'); + + assert_equals(animating.getAnimations()[0].timeline, null); + }, 'Animation.timeline returns null for inactive (overattached) deferred timeline'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/css/view-timeline-lookup-expected.txt b/third_party/blink/web_tests/external/wpt/scroll-animations/css/view-timeline-lookup-expected.txt deleted file mode 100644 index 90b79f2..0000000 --- a/third_party/blink/web_tests/external/wpt/scroll-animations/css/view-timeline-lookup-expected.txt +++ /dev/null
@@ -1,10 +0,0 @@ -This is a testharness.js-based test. -PASS view-timeline on self -PASS view-timeline on preceding sibling -PASS view-timeline on ancestor -PASS view-timeline on ancestor sibling -PASS view-timeline on ancestor sibling, conflict remains unresolved -PASS view-timeline on ancestor sibling, closer timeline wins -FAIL view-timeline on ancestor sibling, scroll-timeline wins on same element assert_equals: expected "0" but got "75" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/protocol/bundle.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/protocol/bundle.https-expected.txt index 60a94de..488fa40 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/protocol/bundle.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc/protocol/bundle.https-expected.txt
@@ -2,6 +2,6 @@ PASS not negotiating BUNDLE creates two separate ice and dtls transports PASS bundles on the first transport and closes the second FAIL max-bundle with an offer without bundle only negotiates the first m-line promise_test: Unhandled rejection with value: object "InvalidAccessError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to set remote offer sdp: max-bundle is used but no bundle group found." -FAIL sRD(offer) works with no transport attributes in a bundle-only m-section promise_test: Unhandled rejection with value: object "InvalidAccessError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to set remote offer sdp: rtcp-mux must be enabled when BUNDLE is enabled." +PASS sRD(offer) works with no transport attributes in a bundle-only m-section Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/protocol/bundle.https.html b/third_party/blink/web_tests/external/wpt/webrtc/protocol/bundle.https.html index 3d2b835..73ea477 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/protocol/bundle.https.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/protocol/bundle.https.html
@@ -135,7 +135,7 @@ a=mid:audio a=rtpmap:111 opus/48000/2 a=setup:actpass -m=video 9 UDP/TLS/RTP/SAVPF 100 +m=video 0 UDP/TLS/RTP/SAVPF 100 c=IN IP4 0.0.0.0 a=bundle-only a=sendonly
diff --git a/third_party/blink/web_tests/http/tests/devtools/overrides/can-edit-iframe-html.js b/third_party/blink/web_tests/http/tests/devtools/overrides/can-edit-iframe-html.js index b40618c..f3ab5ea3 100644 --- a/third_party/blink/web_tests/http/tests/devtools/overrides/can-edit-iframe-html.js +++ b/third_party/blink/web_tests/http/tests/devtools/overrides/can-edit-iframe-html.js
@@ -2,9 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {TestRunner} from 'test_runner'; +import {BindingsTestRunner} from 'bindings_test_runner'; + (async function() { TestRunner.addResult(`Ensures iframes are overridable if overrides are setup.\n`); - await TestRunner.loadTestModule('bindings_test_runner'); await TestRunner.loadLegacyModule('sources'); await TestRunner.loadLegacyModule('sources');
diff --git a/third_party/blink/web_tests/http/tests/devtools/overrides/files-save-without-hash.js b/third_party/blink/web_tests/http/tests/devtools/overrides/files-save-without-hash.js index 12d6edc..d667cc0 100644 --- a/third_party/blink/web_tests/http/tests/devtools/overrides/files-save-without-hash.js +++ b/third_party/blink/web_tests/http/tests/devtools/overrides/files-save-without-hash.js
@@ -2,9 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {TestRunner} from 'test_runner'; +import {BindingsTestRunner} from 'bindings_test_runner'; + (async function() { TestRunner.addResult(`Ensures iframes are overridable if overrides are setup.\n`); - await TestRunner.loadTestModule('bindings_test_runner'); await TestRunner.loadLegacyModule('sources'); var fileSystemPath = 'file:///tmp/';
diff --git a/third_party/blink/web_tests/http/tests/devtools/overrides/project-added-with-existing-files-bind-expected.txt b/third_party/blink/web_tests/http/tests/devtools/overrides/project-added-with-existing-files-bind-expected.txt index cbd5468..0cc8165 100644 --- a/third_party/blink/web_tests/http/tests/devtools/overrides/project-added-with-existing-files-bind-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/overrides/project-added-with-existing-files-bind-expected.txt
@@ -1,6 +1,6 @@ Ensures that when a project is added with already existing files they bind. Bound Files: -http://127.0.0.1:8000/devtools/network/resources/empty.html <=> file:///tmp/127.0.0.1%3a8000/devtools/network/resources/empty.html +http://127.0.0.1:8000/devtools/network/resources/empty.html <=> file:///tmp/127.0.0.1:8000/devtools/network/resources/empty.html
diff --git a/third_party/blink/web_tests/http/tests/devtools/overrides/project-added-with-existing-files-bind.js b/third_party/blink/web_tests/http/tests/devtools/overrides/project-added-with-existing-files-bind.js index 43a1847..78a6457a 100644 --- a/third_party/blink/web_tests/http/tests/devtools/overrides/project-added-with-existing-files-bind.js +++ b/third_party/blink/web_tests/http/tests/devtools/overrides/project-added-with-existing-files-bind.js
@@ -2,9 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {TestRunner} from 'test_runner'; +import {BindingsTestRunner} from 'bindings_test_runner'; + (async function() { TestRunner.addResult(`Ensures that when a project is added with already existing files they bind.\n`); - await TestRunner.loadTestModule('bindings_test_runner'); await TestRunner.navigatePromise('http://127.0.0.1:8000/devtools/network/resources/empty.html'); @@ -17,7 +19,7 @@ }); const { testFileSystem } = await BindingsTestRunner.createOverrideProject('file:///tmp'); - testFileSystem.addFile('127.0.0.1%3a8000/devtools/network/resources/empty.html', 'New Content'); + testFileSystem.addFile('127.0.0.1:8000/devtools/network/resources/empty.html', 'New Content'); BindingsTestRunner.setOverridesEnabled(true); })();
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-expected.txt b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-expected.txt deleted file mode 100644 index 155f9a6..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-expected.txt +++ /dev/null
@@ -1,108 +0,0 @@ -Tests the Timeline API instrumentation of a network resource load - - -ResourceSendRequest Properties: -{ - data : { - frame : <string> - priority : "VeryHigh" - requestId : <string> - requestMethod : "GET" - url : .../devtools/tracing/resources/hello.html - } - endTime : <number> - frameId : <string> - startTime : <number> - type : "ResourceSendRequest" -} -Text details for ResourceSendRequest: hello.html - -ResourceReceiveResponse Properties: -{ - data : { - encodedDataLength : <number> - frame : <string> - fromCache : false - fromServiceWorker : false - mimeType : "text/html" - requestId : <string> - responseTime : <number> - statusCode : 200 - timing : <object> - } - endTime : <number> - frameId : <string> - startTime : <number> - type : "ResourceReceiveResponse" -} -Text details for ResourceReceiveResponse: hello.html - -ResourceFinish Properties: -{ - data : { - decodedBodyLength : 20 - didFail : false - encodedDataLength : <number> - finishTime : <number> - requestId : <string> - } - endTime : <number> - startTime : <number> - type : "ResourceFinish" -} -Text details for ResourceFinish: hello.html - -ResourceSendRequest Properties: -{ - data : { - frame : <string> - priority : "Low" - renderBlocking : "non_blocking" - requestId : <string> - requestMethod : "GET" - stackTrace : <object> - url : .../devtools/tracing/resources/timeline-network-resource.js - } - endTime : <number> - frameId : <string> - stackTrace : <object> - startTime : <number> - type : "ResourceSendRequest" -} -Text details for ResourceSendRequest: timeline-network-resource.js - -ResourceReceiveResponse Properties: -{ - data : { - encodedDataLength : <number> - frame : <string> - fromCache : false - fromServiceWorker : false - mimeType : "application/x-javascript" - requestId : <string> - responseTime : <number> - statusCode : 200 - timing : <object> - } - endTime : <number> - frameId : <string> - startTime : <number> - type : "ResourceReceiveResponse" -} -Text details for ResourceReceiveResponse: timeline-network-resource.js - -ResourceFinish Properties: -{ - data : { - decodedBodyLength : 223 - didFail : false - encodedDataLength : <number> - finishTime : <number> - requestId : <string> - } - endTime : <number> - startTime : <number> - type : "ResourceFinish" -} -Text details for ResourceFinish: timeline-network-resource.js -
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource.js b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource.js deleted file mode 100644 index ac83908d..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource.js +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright 2017 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -(async function() { - TestRunner.addResult(`Tests the Timeline API instrumentation of a network resource load\n`); - await TestRunner.loadLegacyModule('timeline'); await TestRunner.loadTestModule('performance_test_runner'); - await TestRunner.showPanel('timeline'); - await TestRunner.NetworkAgent.setCacheDisabled(true); - - await PerformanceTestRunner.startTimeline(); - await TestRunner.navigatePromise('http://127.0.0.1:8000/devtools/tracing/resources/hello.html'); - await TestRunner.evaluateInPagePromise(` - var scriptUrl = "timeline-network-resource.js"; - - function performActions() - { - var promise = new Promise((fulfill) => window.timelineNetworkResourceEvaluated = fulfill); - var script = document.createElement("script"); - script.src = scriptUrl; - document.body.appendChild(script); - return promise; - } - `); - - var requestId; - var scriptUrl = 'timeline-network-resource.js'; - - await TestRunner.callFunctionInPageAsync('performActions'); - await PerformanceTestRunner.stopTimeline(); - - const sendRequests = PerformanceTestRunner.mainTrackEvents(). - filter(e => e.name === TimelineModel.TimelineModel.RecordType.ResourceSendRequest); - for (let event of sendRequests) { - await printEvent(event); - await printEventsWithId(event.args['data'].requestId); - } - TestRunner.completeTest(); - - async function printEventsWithId(id) { - var model = PerformanceTestRunner.timelineModel(); - for (const event of PerformanceTestRunner.mainTrackEvents()) { - if (event.name !== TimelineModel.TimelineModel.RecordType.ResourceReceiveResponse && - event.name !== TimelineModel.TimelineModel.RecordType.ResourceFinish) { - continue; - } - if (event.args['data'].requestId !== id) - continue; - await printEvent(event); - } - } - - async function printEvent(event) { - TestRunner.addResult(''); - PerformanceTestRunner.printTraceEventProperties(event); - TestRunner.addResult( - `Text details for ${event.name}: ` + await Timeline.TimelineUIUtils.buildDetailsTextForTraceEvent(event)); - } -})();
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/css/selector-specificity-information-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/css/selector-specificity-information-expected.txt new file mode 100644 index 0000000..2ee235d --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/css/selector-specificity-information-expected.txt
@@ -0,0 +1,5 @@ +Test that specificity information is passed to DevTools. +body: 0,0,1 +.class: 0,1,0 +#id: 1,0,0 +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/css/selector-specificity-information.js b/third_party/blink/web_tests/http/tests/inspector-protocol/css/selector-specificity-information.js new file mode 100644 index 0000000..a38dae22 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/css/selector-specificity-information.js
@@ -0,0 +1,44 @@ +(async function(testRunner) { + const {dp} = await testRunner.startHTML(` + <style> + body { + color: red; + } + .class { + color: red; + } + #id { + color: red; + } + </style> + <body> + <span class="class"></span> + <span id="id"></span> + </body> + `, 'Test that specificity information is passed to DevTools.'); + + await dp.DOM.enable(); + await dp.CSS.enable(); + + async function requestDocumentNodeId() { + const {result} = await dp.DOM.getDocument({}); + return result.root.nodeId; + } + async function requestNodeId(nodeId, selector) { + const {result} = await dp.DOM.querySelector({nodeId, selector}); + return result.nodeId; + } + + const documentNodeId = await requestDocumentNodeId(); + + for (const selector of ['body', '.class', '#id']) { + const nodeId = await requestNodeId(documentNodeId, selector); + const { result: matchedStylesForNode } = await dp.CSS.getMatchedStylesForNode({ nodeId }); + + const specificity = matchedStylesForNode.matchedCSSRules[0].rule.selectorList.selectors[0].specificity; + testRunner.log(`${selector}: ${specificity.a},${specificity.b},${specificity.c}`); + } + + testRunner.completeTest(); +}); +
diff --git a/third_party/blink/web_tests/printing/numberOfPages-expected.txt b/third_party/blink/web_tests/printing/numberOfPages-expected.txt index b821e78..95cd5dc 100644 --- a/third_party/blink/web_tests/printing/numberOfPages-expected.txt +++ b/third_party/blink/web_tests/printing/numberOfPages-expected.txt
@@ -4,7 +4,7 @@ PASS: number of pages is 2 -PASS: number of pages is 1 +PASS: number of pages is 2 All tests passed PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/printing/resources/paged-media-test-utils.js b/third_party/blink/web_tests/printing/resources/paged-media-test-utils.js index 73745af7..9ae76a9 100644 --- a/third_party/blink/web_tests/printing/resources/paged-media-test-utils.js +++ b/third_party/blink/web_tests/printing/resources/paged-media-test-utils.js
@@ -60,17 +60,11 @@ output.appendChild(resultElement); } -function ratioToPageHeightToPixels(heightInRatioToPageHeight) -{ - var pageHeightInPixels = 600 * 1.333; - return Math.floor(pageHeightInPixels * heightInRatioToPageHeight); -} - function createBlockWithRatioToPageHeight(id, heightInRatioToPageHeight) { var element = document.createElement("div"); element.id = id; - element.style.height = ratioToPageHeightToPixels(heightInRatioToPageHeight) + "px"; + element.style.height = (heightInRatioToPageHeight * 100) + "vh"; document.getElementById("sandbox").appendChild(element); return element; } @@ -84,7 +78,7 @@ element.appendChild(document.createElement("br")); } // Make sure that one page has about 20 lines. - element.style.lineHeight = ratioToPageHeightToPixels(0.05) + "px"; + element.style.lineHeight = "5vh"; document.getElementById("sandbox").appendChild(element); return element; }
diff --git a/third_party/blink/web_tests/printing/script-tests/numberOfPages.js b/third_party/blink/web_tests/printing/script-tests/numberOfPages.js index 55efa87d..69ca749 100644 --- a/third_party/blink/web_tests/printing/script-tests/numberOfPages.js +++ b/third_party/blink/web_tests/printing/script-tests/numberOfPages.js
@@ -6,7 +6,7 @@ createBlockWithRatioToPageHeight("secondPage", 0.6); numberOfPagesShouldBe(2); - numberOfPagesShouldBe(1, 1000, 10000); + numberOfPagesShouldBe(2, 1000, 10000); document.body.removeChild(document.getElementById("sandbox")); }
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt index 4c3f690..75daf80 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt
@@ -375,7 +375,6 @@ scrollSnapStop scrollSnapType scrollTimeline -scrollTimelineAttachment scrollTimelineAxis scrollTimelineName scrollbarGutter @@ -447,7 +446,6 @@ vectorEffect verticalAlign viewTimeline -viewTimelineAttachment viewTimelineAxis viewTimelineInset viewTimelineName
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/css-property-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/css-property-listing-expected.txt index 54e2e2e..87ee971 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/css-property-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/css-property-listing-expected.txt
@@ -329,7 +329,6 @@ scroll-snap-align scroll-snap-stop scroll-snap-type - scroll-timeline-attachment scroll-timeline-axis scroll-timeline-name scrollbar-gutter @@ -388,7 +387,6 @@ user-select vector-effect vertical-align - view-timeline-attachment view-timeline-axis view-timeline-inset view-timeline-name @@ -751,7 +749,6 @@ scroll-padding-inline-end scroll-padding-inline-start scroll-timeline - scroll-timeline-attachment scroll-timeline-axis scroll-timeline-name text-decoration @@ -768,7 +765,6 @@ transition-property transition-timing-function view-timeline - view-timeline-attachment view-timeline-axis view-timeline-name white-space
diff --git a/third_party/blink/web_tests/virtual/view-transition-wide-gamut/inspector-protocol/css/css-get-styles-for-view-transition-expected.txt b/third_party/blink/web_tests/virtual/view-transition-wide-gamut/inspector-protocol/css/css-get-styles-for-view-transition-expected.txt index 06724605..fd1429b 100644 --- a/third_party/blink/web_tests/virtual/view-transition-wide-gamut/inspector-protocol/css/css-get-styles-for-view-transition-expected.txt +++ b/third_party/blink/web_tests/virtual/view-transition-wide-gamut/inspector-protocol/css/css-get-styles-for-view-transition-expected.txt
@@ -42,6 +42,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html } ] @@ -78,6 +83,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 0 + } text : :root } ] @@ -119,6 +129,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition } ] @@ -180,6 +195,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -224,6 +244,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -264,6 +289,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-group(root) } ] @@ -310,6 +340,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -354,6 +389,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -394,6 +434,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-group(shared) } ] @@ -442,6 +487,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-group(shared) } ] @@ -500,6 +550,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-image-pair() } ] @@ -556,6 +611,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-image-pair() } ] @@ -596,6 +656,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-image-pair(root) } ] @@ -638,6 +703,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-image-pair() } ] @@ -694,6 +764,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-image-pair() } ] @@ -734,6 +809,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-image-pair(shared) } ] @@ -776,9 +856,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -827,6 +917,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-old() } ] @@ -871,6 +966,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-old(root) } ] @@ -913,6 +1013,11 @@ startColumn : 1 startLine : 0 } + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old(*) } ] @@ -1059,9 +1164,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -1110,6 +1225,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-old() } ] @@ -1154,6 +1274,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-old(shared) } ] @@ -1196,6 +1321,11 @@ startColumn : 1 startLine : 0 } + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old(*) } ] @@ -1342,9 +1472,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -1393,6 +1533,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-new() } ] @@ -1437,6 +1582,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-new(root) } ] @@ -1479,9 +1629,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -1530,6 +1690,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-new() } ] @@ -1574,6 +1739,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-new(shared) } ] @@ -1616,6 +1786,11 @@ startColumn : 1 startLine : 0 } + specificity : { + a : 0 + b : 1 + c : 0 + } text : ::view-transition-new(shared) } ] @@ -1688,6 +1863,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition } ] @@ -1754,6 +1934,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -1798,6 +1983,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -1838,6 +2028,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-group(root) } ] @@ -1888,6 +2083,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-image-pair() } ] @@ -1944,6 +2144,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-image-pair() } ] @@ -1984,6 +2189,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-image-pair(root) } ] @@ -2030,9 +2240,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -2081,6 +2301,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-old() } ] @@ -2125,6 +2350,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-old(root) } ] @@ -2167,6 +2397,11 @@ startColumn : 1 startLine : 0 } + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old(*) } ] @@ -2317,9 +2552,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -2368,6 +2613,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-new() } ] @@ -2412,6 +2662,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-new(root) } ] @@ -2458,6 +2713,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -2502,6 +2762,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -2542,6 +2807,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-group(shared) } ] @@ -2590,6 +2860,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-group(shared) } ] @@ -2652,6 +2927,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-image-pair() } ] @@ -2708,6 +2988,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-image-pair() } ] @@ -2748,6 +3033,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-image-pair(shared) } ] @@ -2794,9 +3084,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -2845,6 +3145,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-old() } ] @@ -2889,6 +3194,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-old(shared) } ] @@ -2931,6 +3241,11 @@ startColumn : 1 startLine : 0 } + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old(*) } ] @@ -3081,9 +3396,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -3132,6 +3457,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-new() } ] @@ -3176,6 +3506,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-new(shared) } ] @@ -3218,6 +3553,11 @@ startColumn : 1 startLine : 0 } + specificity : { + a : 0 + b : 1 + c : 0 + } text : ::view-transition-new(shared) } ]
diff --git a/third_party/blink/web_tests/virtual/view-transition/inspector-protocol/css/css-get-styles-for-view-transition-expected.txt b/third_party/blink/web_tests/virtual/view-transition/inspector-protocol/css/css-get-styles-for-view-transition-expected.txt index 06724605..fd1429b 100644 --- a/third_party/blink/web_tests/virtual/view-transition/inspector-protocol/css/css-get-styles-for-view-transition-expected.txt +++ b/third_party/blink/web_tests/virtual/view-transition/inspector-protocol/css/css-get-styles-for-view-transition-expected.txt
@@ -42,6 +42,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html } ] @@ -78,6 +83,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 0 + } text : :root } ] @@ -119,6 +129,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition } ] @@ -180,6 +195,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -224,6 +244,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -264,6 +289,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-group(root) } ] @@ -310,6 +340,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -354,6 +389,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -394,6 +434,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-group(shared) } ] @@ -442,6 +487,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-group(shared) } ] @@ -500,6 +550,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-image-pair() } ] @@ -556,6 +611,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-image-pair() } ] @@ -596,6 +656,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-image-pair(root) } ] @@ -638,6 +703,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-image-pair() } ] @@ -694,6 +764,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-image-pair() } ] @@ -734,6 +809,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-image-pair(shared) } ] @@ -776,9 +856,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -827,6 +917,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-old() } ] @@ -871,6 +966,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-old(root) } ] @@ -913,6 +1013,11 @@ startColumn : 1 startLine : 0 } + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old(*) } ] @@ -1059,9 +1164,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -1110,6 +1225,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-old() } ] @@ -1154,6 +1274,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-old(shared) } ] @@ -1196,6 +1321,11 @@ startColumn : 1 startLine : 0 } + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old(*) } ] @@ -1342,9 +1472,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -1393,6 +1533,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-new() } ] @@ -1437,6 +1582,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-new(root) } ] @@ -1479,9 +1629,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -1530,6 +1690,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-new() } ] @@ -1574,6 +1739,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-new(shared) } ] @@ -1616,6 +1786,11 @@ startColumn : 1 startLine : 0 } + specificity : { + a : 0 + b : 1 + c : 0 + } text : ::view-transition-new(shared) } ] @@ -1688,6 +1863,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition } ] @@ -1754,6 +1934,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -1798,6 +1983,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -1838,6 +2028,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-group(root) } ] @@ -1888,6 +2083,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-image-pair() } ] @@ -1944,6 +2144,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-image-pair() } ] @@ -1984,6 +2189,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-image-pair(root) } ] @@ -2030,9 +2240,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -2081,6 +2301,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-old() } ] @@ -2125,6 +2350,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-old(root) } ] @@ -2167,6 +2397,11 @@ startColumn : 1 startLine : 0 } + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old(*) } ] @@ -2317,9 +2552,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -2368,6 +2613,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-new() } ] @@ -2412,6 +2662,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-new(root) } ] @@ -2458,6 +2713,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -2502,6 +2762,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-group() } ] @@ -2542,6 +2807,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-group(shared) } ] @@ -2590,6 +2860,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-group(shared) } ] @@ -2652,6 +2927,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-image-pair() } ] @@ -2708,6 +2988,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-image-pair() } ] @@ -2748,6 +3033,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-image-pair(shared) } ] @@ -2794,9 +3084,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -2845,6 +3145,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-old() } ] @@ -2889,6 +3194,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-old(shared) } ] @@ -2931,6 +3241,11 @@ startColumn : 1 startLine : 0 } + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old(*) } ] @@ -3081,9 +3396,19 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-new() } [1] : { + specificity : { + a : 0 + b : 0 + c : 0 + } text : ::view-transition-old() } ] @@ -3132,6 +3457,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 0 + c : 1 + } text : html::view-transition-new() } ] @@ -3176,6 +3506,11 @@ selectorList : { selectors : [ [0] : { + specificity : { + a : 0 + b : 1 + c : 1 + } text : html::view-transition-new(shared) } ] @@ -3218,6 +3553,11 @@ startColumn : 1 startLine : 0 } + specificity : { + a : 0 + b : 1 + c : 0 + } text : ::view-transition-new(shared) } ]
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-transitions/initial-rule-basic.html b/third_party/blink/web_tests/wpt_internal/css/css-transitions/starting-style-rule-basic.html similarity index 87% rename from third_party/blink/web_tests/wpt_internal/css/css-transitions/initial-rule-basic.html rename to third_party/blink/web_tests/wpt_internal/css/css-transitions/starting-style-rule-basic.html index 7bb9ddf..828f7b0 100644 --- a/third_party/blink/web_tests/wpt_internal/css/css-transitions/initial-rule-basic.html +++ b/third_party/blink/web_tests/wpt_internal/css/css-transitions/starting-style-rule-basic.html
@@ -12,7 +12,7 @@ color: green; background-color: white; } - @initial { + @starting-style { #target { background-color: black; } @@ -27,7 +27,7 @@ assert_equals(getComputedStyle(target).color, "rgb(0, 128, 0)", "No transition of color"); assert_equals(getComputedStyle(target).backgroundColor, "rgb(128, 128, 128)", - "Background transition from @initial value black to white"); + "Background transition from @starting-style value black to white"); }, "Triggered transition from first style update"); promise_test(async t => { @@ -42,7 +42,7 @@ target.style.display = "block"; await waitForAnimationFrames(2); assert_equals(getComputedStyle(target).backgroundColor, "rgb(128, 128, 128)", - "Background transition from @initial value black to white"); + "Background transition from @starting-style value black to white"); }, "Triggered transition from display:none to display:block"); promise_test(async t => { @@ -52,6 +52,6 @@ document.body.appendChild(removed); await waitForAnimationFrames(2); assert_equals(getComputedStyle(target).backgroundColor, "rgb(128, 128, 128)", - "Background transition from @initial value black to white"); + "Background transition from @starting-style value black to white"); }, "Triggered transition on DOM insertion"); </script>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-transitions/initial-rule-none.html b/third_party/blink/web_tests/wpt_internal/css/css-transitions/starting-style-rule-none.html similarity index 81% rename from third_party/blink/web_tests/wpt_internal/css/css-transitions/initial-rule-none.html rename to third_party/blink/web_tests/wpt_internal/css/css-transitions/starting-style-rule-none.html index 8c7d650..c1d56e5eb 100644 --- a/third_party/blink/web_tests/wpt_internal/css/css-transitions/initial-rule-none.html +++ b/third_party/blink/web_tests/wpt_internal/css/css-transitions/starting-style-rule-none.html
@@ -11,7 +11,7 @@ transition-timing-function: steps(2, start); background-color: green; } - @initial { + @starting-style { #target { display: none; background-color: red; @@ -22,6 +22,6 @@ promise_test(async t => { await waitForAnimationFrames(2); assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 128, 0)", - "No transition of background-color when @initial display is 'none'"); - }, "@initial with display:none"); + "No transition of background-color when @starting-style display is 'none'"); + }, "@starting-style with display:none"); </script>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-transitions/initial-rule-pseudo-elements.html b/third_party/blink/web_tests/wpt_internal/css/css-transitions/starting-style-rule-pseudo-elements.html similarity index 88% rename from third_party/blink/web_tests/wpt_internal/css/css-transitions/initial-rule-pseudo-elements.html rename to third_party/blink/web_tests/wpt_internal/css/css-transitions/starting-style-rule-pseudo-elements.html index af50a05d..9816155 100644 --- a/third_party/blink/web_tests/wpt_internal/css/css-transitions/initial-rule-pseudo-elements.html +++ b/third_party/blink/web_tests/wpt_internal/css/css-transitions/starting-style-rule-pseudo-elements.html
@@ -13,7 +13,7 @@ background-color: white; content: ""; } - @initial { + @starting-style { #target::before { background-color: black; } @@ -28,7 +28,7 @@ assert_equals(getComputedStyle(target, "::before").color, "rgb(0, 128, 0)", "No transition of color"); assert_equals(getComputedStyle(target, "::before").backgroundColor, "rgb(128, 128, 128)", - "Background transition from @initial value black to white"); + "Background transition from @starting-style value black to white"); }, "Triggered transition from first style update"); promise_test(async t => { @@ -43,7 +43,7 @@ target.style.display = "block"; await waitForAnimationFrames(2); assert_equals(getComputedStyle(target, "::before").backgroundColor, "rgb(128, 128, 128)", - "Background transition from @initial value black to white"); + "Background transition from @starting-style value black to white"); }, "Triggered transition from display:none to display:block"); promise_test(async t => { @@ -53,6 +53,6 @@ document.body.appendChild(removed); await waitForAnimationFrames(2); assert_equals(getComputedStyle(target, "::before").backgroundColor, "rgb(128, 128, 128)", - "Background transition from @initial value black to white"); + "Background transition from @starting-style value black to white"); }, "Triggered transition on DOM insertion"); </script>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index a58e309c..f4eff444 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -26225,6 +26225,13 @@ <int value="2" label="Error - Video Capturer Service crashed"/> </enum> +<enum name="DeviceIdentifierStatus"> + <int value="0" label="all device identifiers are present"/> + <int value="1" label="serial number is missing"/> + <int value="2" label="rlz_brand_code is missing"/> + <int value="3" label="all device identifiers are missing"/> +</enum> + <enum name="DeviceIdMismatch"> <int value="0" label="BOTH_NONEMPTY"/> <int value="1" label="SYNC_EMPTY"/> @@ -27392,6 +27399,19 @@ <int value="10" label="Selector from context menu"/> </enum> +<enum name="DevToolsSwatchActivated"> + <int value="0" label="Variable link"/> + <int value="1" label="Animation name link"/> + <int value="2" label="Color"/> + <int value="3" label="Animation timing"/> + <int value="4" label="Shadow"/> + <int value="5" label="Grid editor"/> + <int value="6" label="Flex editor"/> + <int value="7" label="Angle"/> + <int value="8" label="Length"/> + <int value="9" label="Position fallback link"/> +</enum> + <enum name="DevToolsSyncSetting"> <int value="1" label="Chrome Sync disabled"/> <int value="2" label="Chrome Sync 'Settings' ModelType disabled"/> @@ -42453,7 +42473,7 @@ <int value="4483" label="ExecutedEmptyJavaScriptURLFromFrame"/> <int value="4484" label="ExecutedJavaScriptURLFromFrame"/> <int value="4485" label="ServiceWorkerBypassFetchHandlerForSubResource"/> - <int value="4486" label="CSSAtRuleInitial"/> + <int value="4486" label="CSSAtRuleStartingStyle"/> <int value="4487" label="PrivateAggregationApiFledgeExtensions"/> <int value="4488" label="DeprecatedInterestGroupDailyUpdateUrl"/> <int value="4489" label="CSSColorGradientColorSpace"/> @@ -55900,7 +55920,7 @@ <enum name="KidsExternalFetcherStatus"> <int value="0" label="NoError"/> <int value="1" label="AuthError"/> - <int value="2" label="HttpError"/> + <int value="2" label="HttpStatusOrNetError"/> <int value="3" label="ParseError"/> <int value="4" label="DataError"/> </enum> @@ -79021,6 +79041,12 @@ <int value="26" label="StoredPolicyFail">Failed to store policies.</int> </enum> +<enum name="OwnershipStatus"> + <int value="0" label="ownership unknown"/> + <int value="1" label="not yet owned"/> + <int value="2" label="ownership taken"/> +</enum> + <enum name="P2PLookupResult"> <int value="0" label="Found"/> <int value="1" label="Not Found"/>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml index c897b3c7..e055aa4 100644 --- a/tools/metrics/histograms/metadata/ash/histograms.xml +++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -964,6 +964,26 @@ </summary> </histogram> +<histogram name="Ash.BrowserDataMigrator.MoveMigrator.ExtraDiskSpaceOccupied" + units="MB" expires_after="M121"> + <owner>ythjkt@chromium.org</owner> + <owner>hidehiko@chromium.org</owner> + <summary> + The size of disk space occupied by files/dirs created during the migration. + </summary> +</histogram> + +<histogram + name="Ash.BrowserDataMigrator.MoveMigrator.ExtraDiskSpaceOccupied.DiffWithEstimate" + units="MB" expires_after="M121"> + <owner>ythjkt@chromium.org</owner> + <owner>hidehiko@chromium.org</owner> + <summary> + The difference between the estimate and the actual size of disk space + occupied by files/dirs created during the migration. + </summary> +</histogram> + <histogram name="Ash.BrowserDataMigrator.MoveMigrator.ExtraSpaceRequiredMB" units="MB" expires_after="M121"> <owner>ythjkt@chromium.org</owner> @@ -1089,6 +1109,24 @@ </summary> </histogram> +<histogram name="Ash.BrowserDataMigrator.MoveMigrator.TmpProfileDirSize" + units="MB" expires_after="M121"> + <owner>ythjkt@chromium.org</owner> + <owner>hidehiko@chromium.org</owner> + <summary> + The size of temporary profile directory created during the migration. + </summary> +</histogram> + +<histogram name="Ash.BrowserDataMigrator.MoveMigrator.TmpSplitDirSize" + units="MB" expires_after="M121"> + <owner>ythjkt@chromium.org</owner> + <owner>hidehiko@chromium.org</owner> + <summary> + The size of temporary split directory created during the migration. + </summary> +</histogram> + <histogram name="Ash.BrowserDataMigrator.NoCopyDataSizeMB" units="MB" expires_after="M121"> <owner>ythjkt@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/dev/histograms.xml b/tools/metrics/histograms/metadata/dev/histograms.xml index 4026ce6..bbc1b9b 100644 --- a/tools/metrics/histograms/metadata/dev/histograms.xml +++ b/tools/metrics/histograms/metadata/dev/histograms.xml
@@ -490,6 +490,14 @@ <summary>Recorded when certain style text is copied in DevTools.</summary> </histogram> +<histogram name="DevTools.SwatchActivated" enum="DevToolsSwatchActivated" + expires_after="2023-12-01"> + <owner>ergunsh@chromium.org</owner> + <owner>changhaohan@chromium.org</owner> + <owner>bmeurer@chromium.org</owner> + <summary>Records the swatch usages in the Styles pane.</summary> +</histogram> + <histogram name="DevTools.SyncSetting" enum="DevToolsSyncSetting" expires_after="2023-12-01"> <owner>bmeurer@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/enterprise/histograms.xml b/tools/metrics/histograms/metadata/enterprise/histograms.xml index 478d461..858cb3d 100644 --- a/tools/metrics/histograms/metadata/enterprise/histograms.xml +++ b/tools/metrics/histograms/metadata/enterprise/histograms.xml
@@ -22,6 +22,14 @@ <histograms> +<variants name="AutoEnrollmentStates"> + <variant name="ConnectionError" summary="connection error"/> + <variant name="Disabled" summary="disabled"/> + <variant name="Enrollment" summary="enrollment"/> + <variant name="NoEnrollment" summary="no enrollment"/> + <variant name="ServerError" summary="server error"/> +</variants> + <variants name="CleanupHandler"> <variant name="Browser" summary="Handler for open browser windows and browsing data"/> @@ -99,6 +107,21 @@ <variant name="Recommended" summary="Recommended Policy"/> </variants> +<variants name="StateDeterminationDmRequestTypes"> + <variant name="PsmRlweOprf" summary="PSM RLWE OPRF"/> + <variant name="PsmRlweQuery" summary="PSM RLWE Query"/> + <variant name="State" summary="state"/> +</variants> + +<variants name="StateDeterminationSteps"> + <variant name="OPRFRequest" summary="PSM OPRF request"/> + <variant name="OwnershipCheck" summary="ownership check"/> + <variant name="QueryRequest" summary="PSM Query request"/> + <variant name="StateKeyRetrieval" summary="state key retrieval"/> + <variant name="StateRequest" summary="state request"/> + <variant name="SystemClockSync" summary="system clock sync"/> +</variants> + <variants name="WmiSystemSignal"> <variant name="AntiVirus" summary="AntiVirus info"/> <variant name="Hotfixes" summary="Hotfix info"/> @@ -2501,6 +2524,157 @@ </summary> </histogram> +<histogram name="Enterprise.StateDetermination.DeviceIdentifierStatus" + enum="DeviceIdentifierStatus" expires_after="2024-05-10"> + <owner>sergiyb@google.com</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary> + Captures state of device identifiers during state determination. + </summary> +</histogram> + +<histogram name="Enterprise.StateDetermination.EmbargoDatePassed" + enum="Boolean" expires_after="2024-05-10"> + <owner>sergiyb@google.com</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary> + Tracks whether embargo date has passed during state determination. + </summary> +</histogram> + +<histogram name="Enterprise.StateDetermination.Enabled" enum="Boolean" + expires_after="2024-05-10"> + <owner>sergiyb@google.com</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary>Captures situations when state determination is enabled.</summary> +</histogram> + +<histogram + name="Enterprise.StateDetermination.KillSwitchFetch.NetworkErrorCode" + enum="NetErrorCodes" expires_after="2024-05-10"> + <owner>sergiyb@chromium.org</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary> + Network error code for unified state determination kill switch config + requests. + </summary> +</histogram> + +<histogram name="Enterprise.StateDetermination.KillSwitchFetch.NumTries" + enum="NetErrorCodes" expires_after="2024-05-10"> + <owner>sergiyb@chromium.org</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary> + Number of tries for fetching unified state determination kill switch config. + </summary> +</histogram> + +<histogram name="Enterprise.StateDetermination.OnFlex" enum="Boolean" + expires_after="2024-05-10"> + <owner>sergiyb@google.com</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary> + Captures situations when state determination takes place on Flex devices. + </summary> +</histogram> + +<histogram name="Enterprise.StateDetermination.OwnershipStatus" + enum="OwnershipStatus" expires_after="2024-05-10"> + <owner>sergiyb@google.com</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary> + Captures ownership state of device during state determination. + </summary> +</histogram> + +<histogram name="Enterprise.StateDetermination.PsmReportedAvailableState" + enum="Boolean" expires_after="2024-05-10"> + <owner>sergiyb@google.com</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary> + Tracks whether PSM has reported that state is available during state + determination. + </summary> +</histogram> + +<histogram name="Enterprise.StateDetermination.StateKeysRetrieved" + enum="Boolean" expires_after="2024-05-10"> + <owner>sergiyb@google.com</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary> + Tracks whether state keys were retrieved during state determination. + </summary> +</histogram> + +<histogram name="Enterprise.StateDetermination.StateReturned" enum="Boolean" + expires_after="2024-05-10"> + <owner>sergiyb@google.com</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary> + Tracks whether state request returned state during state determination. + </summary> +</histogram> + +<histogram name="Enterprise.StateDetermination.StepDuration.{Step}" units="ms" + expires_after="2024-05-10"> + <owner>sergiyb@google.com</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary> + Tracks the duration of the {Step} as part of state determination. + </summary> + <token key="Step" variants="StateDeterminationSteps"/> +</histogram> + +<histogram name="Enterprise.StateDetermination.SystemClockSynchronized" + enum="Boolean" expires_after="2024-05-10"> + <owner>sergiyb@google.com</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary> + Tracks whether system clock was synchronized during state determination. + </summary> +</histogram> + +<histogram name="Enterprise.StateDetermination.TotalDuration" units="ms" + expires_after="2024-05-10"> + <owner>sergiyb@google.com</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary>Tracks the total duration of state determination.</summary> +</histogram> + +<histogram name="Enterprise.StateDetermination.TotalDurationByState.{State}" + units="ms" expires_after="2024-05-10"> + <owner>sergiyb@google.com</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary> + Tracks the total duration of state determination when it results in {State} + state. + </summary> + <token key="State" variants="AutoEnrollmentStates"/> +</histogram> + +<histogram + name="Enterprise.StateDetermination.{RequestType}Request.DmStatusCode" + enum="EnterpriseDeviceManagementStatus" expires_after="2024-05-10"> + <owner>sergiyb@chromium.org</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary> + Device management server request status for {RequestType} requests to Device + Management server. + </summary> + <token key="RequestType" variants="StateDeterminationDmRequestTypes"/> +</histogram> + +<histogram + name="Enterprise.StateDetermination.{RequestType}Request.NetworkErrorCode" + enum="NetErrorCodes" expires_after="2024-05-10"> + <owner>sergiyb@chromium.org</owner> + <owner>chromeos-commercial-remote-management@google.com</owner> + <summary> + Network error code for {RequestType} requests to Device Management server. + </summary> + <token key="RequestType" variants="StateDeterminationDmRequestTypes"/> +</histogram> + <histogram name="Enterprise.SystemFeaturesDisableList" enum="SystemFeature" expires_after="2023-06-01"> <owner>ayaelattar@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index edbf12e2..59c33ec 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -14267,6 +14267,16 @@ </summary> </histogram> +<histogram name="WebDatabase.SucceededMigrationToVersion" units="version" + expires_after="2023-12-01"> + <owner>battre@chromium.org</owner> + <owner>fleimgruber@google.com</owner> + <summary> + If a migration to a new WebDatabase schema succeeds, this histogram records + the target version to which the migration failed. + </summary> +</histogram> + <histogram name="WebFont.BlankTextShownTime" units="ms" expires_after="2023-10-01"> <owner>kenjibaheux@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/signin/histograms.xml b/tools/metrics/histograms/metadata/signin/histograms.xml index 720d41a23f..af52280 100644 --- a/tools/metrics/histograms/metadata/signin/histograms.xml +++ b/tools/metrics/histograms/metadata/signin/histograms.xml
@@ -832,14 +832,7 @@ </summary> </histogram> -<histogram name="Signin.ListFamilyMembersRequest.Latency" units="ms" - expires_after="2023-11-01"> - <owner>tju@google.com</owner> - <owner>chrome-kids-eng@google.com</owner> - <summary>Tracks the latency of calls to the Kids Management API.</summary> -</histogram> - -<histogram name="Signin.ListFamilyMembersRequest.NetOrHttpStatus" +<histogram name="Signin.ListFamilyMembersRequest.HttpStatusOrNetError" enum="CombinedHttpResponseAndNetErrorCode" expires_after="2023-11-01"> <owner>tju@google.com</owner> <owner>chrome-kids-eng@google.com</owner> @@ -850,6 +843,13 @@ </summary> </histogram> +<histogram name="Signin.ListFamilyMembersRequest.Latency" units="ms" + expires_after="2023-11-01"> + <owner>tju@google.com</owner> + <owner>chrome-kids-eng@google.com</owner> + <summary>Tracks the latency of calls to the Kids Management API.</summary> +</histogram> + <histogram name="Signin.ListFamilyMembersRequest.Status" enum="KidsExternalFetcherStatus" expires_after="2023-11-01"> <owner>tju@google.com</owner> @@ -870,7 +870,8 @@ <variant name="DataError" summary="contract error (data in the response missing despite succesful parsing)"/> - <variant name="HttpError" summary="transport error"/> + <variant name="HttpStatusOrNetError" + summary="transport error or HTTP status"/> <variant name="NoError" summary="no error recorded"/> <variant name="ParseError" summary="parsing error"/> </token>
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index bb9451a3..f435d4c 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -383,7 +383,7 @@ <item id="password_sync_token_fetcher" added_in_milestone="110" content_hash_code="0268c983" os_list="chromeos" file_path="chrome/browser/ash/login/saml/password_sync_token_fetcher.cc" /> <item id="projector_xhr_loader" added_in_milestone="110" content_hash_code="07e102c2" os_list="chromeos" file_path="ash/webui/projector_app/projector_xhr_sender.cc" /> <item id="cloud_speech_recognition" added_in_milestone="110" content_hash_code="00d56fd8" os_list="linux,windows,chromeos" file_path="components/live_caption/live_translate_controller.cc" /> - <item id="bruschetta_installer_download" added_in_milestone="110" content_hash_code="073f0263" os_list="chromeos" file_path="chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc" /> + <item id="bruschetta_installer_download" added_in_milestone="110" content_hash_code="073f0263" os_list="chromeos" file_path="chrome/browser/ash/bruschetta/bruschetta_download.cc" /> <item id="quick_start_session_auth_requester" added_in_milestone="110" content_hash_code="08353e70" os_list="chromeos" file_path="chrome/browser/ash/login/oobe_quick_start/second_device_auth_broker.cc" /> <item id="network_diagnostics_routines" added_in_milestone="110" content_hash_code="0007b237" os_list="chromeos" file_path="chrome/browser/ash/net/network_diagnostics/http_request_manager.cc" /> <item id="trial_group_lookup" added_in_milestone="110" content_hash_code="047aeeca" os_list="chromeos" file_path="chromeos/ash/components/trial_group/trial_group_checker.cc" />
diff --git a/ui/chromeos/file_manager_strings.grdp b/ui/chromeos/file_manager_strings.grdp index 2991fb9..660f419f 100644 --- a/ui/chromeos/file_manager_strings.grdp +++ b/ui/chromeos/file_manager_strings.grdp
@@ -1740,6 +1740,9 @@ <message name="IDS_FILE_BROWSER_DLP_COMPONENT_VM" desc="PluginVM component label."> virtual machine </message> + <message name="IDS_FILE_BROWSER_DLP_COMPONENT_MICROSOFT_ONEDRIVE" desc="Microsoft OneDrive component label."> + Microsoft OneDrive + </message> <message name="IDS_FILE_BROWSER_ONE_DRIVE_MOVED_FILE_NUDGE" desc="Educational text that appears in the navigation tree when a file is automatically moved to OneDrive by the Office Cloud Upload feature/dialog."> Recently opened Microsoft files have moved to OneDrive </message> @@ -1779,6 +1782,9 @@ <message name="IDS_FILE_BROWSER_BULK_PINNING_TURN_ON" desc="Text in the Continue button of the dialog offering the Google Drive bulk pinning feature"> Turn on </message> + <message name="IDS_FILE_BROWSER_BULK_PINNING_PREPARING_TO_SYNC" desc="Text in the progress panel indicating the bulk pinning operations is preparing files to sync"> + Preparing to sync Drive files... + </message> <!-- TODO(b/276126188): Remove the translateable="false" when the copy has been landed on. --> <message name="IDS_FILE_BROWSER_BULK_PINNING_OFFLINE_LABEL" translateable="false" desc="The text used when the device is in an offline mode and has paused syncing."> You are currently offline. Sync will resume when the connection is back on.
diff --git a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_BULK_PINNING_PREPARING_TO_SYNC.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_BULK_PINNING_PREPARING_TO_SYNC.png.sha1 new file mode 100644 index 0000000..abf2ccf --- /dev/null +++ b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_BULK_PINNING_PREPARING_TO_SYNC.png.sha1
@@ -0,0 +1 @@ +8798e73adf8e8a5e820f29aad31803959137b565 \ No newline at end of file
diff --git a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_DLP_COMPONENT_MICROSOFT_ONEDRIVE.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_DLP_COMPONENT_MICROSOFT_ONEDRIVE.png.sha1 new file mode 100644 index 0000000..b621f16 --- /dev/null +++ b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_DLP_COMPONENT_MICROSOFT_ONEDRIVE.png.sha1
@@ -0,0 +1 @@ +c76e33e8ec69f5b2fa9849be0fa567a6d4ed783a \ No newline at end of file
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_grid.js b/ui/file_manager/file_manager/foreground/js/ui/file_grid.js index 2f3cc4d..3ab15d8 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_grid.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_grid.js
@@ -825,7 +825,9 @@ checkmark.className = 'detail-checkmark'; detailIcon.appendChild(checkmark); bottom.appendChild(detailIcon); - bottom.appendChild(filelist.renderIconBadge(li.ownerDocument)); + if (util.isDriveShortcutsEnabled()) { + bottom.appendChild(filelist.renderIconBadge(li.ownerDocument)); + } bottom.appendChild( filelist.renderFileNameLabel(li.ownerDocument, entry, locationInfo)); frame.appendChild(bottom);
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table.js b/ui/file_manager/file_manager/foreground/js/ui/file_table.js index 7eede5955..cb36ae4 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_table.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_table.js
@@ -823,8 +823,9 @@ } icon.appendChild(this.renderCheckmark_()); label.appendChild(icon); - label.appendChild(filelist.renderIconBadge(this.ownerDocument)); - + if (util.isDriveShortcutsEnabled()) { + label.appendChild(filelist.renderIconBadge(this.ownerDocument)); + } label.entry = entry; label.className = 'detail-name'; label.appendChild(
diff --git a/ui/file_manager/file_manager/widgets/xf_cloud_panel.ts b/ui/file_manager/file_manager/widgets/xf_cloud_panel.ts index 6499547..90f9ed8 100644 --- a/ui/file_manager/file_manager/widgets/xf_cloud_panel.ts +++ b/ui/file_manager/file_manager/widgets/xf_cloud_panel.ts
@@ -169,6 +169,9 @@ override render() { return html`<cr-action-menu> <div class="body"> + <div class="static progress" id="progress-preparing"> + ${str('DRIVE_PREPARING_TO_SYNC')} + </div> <div id="progress-state"> <div class="progress">${ this.items && this.items > 1 ? @@ -224,6 +227,7 @@ :host(:not([items][percentage])) #progress-state, :host([percentage="100"]) #progress-state, + :host([percentage="0"]) #progress-state, :host([type]) #progress-state { display: none; } @@ -233,6 +237,11 @@ display: none; } + :host(:not([items][percentage="0"])) #progress-preparing, + :host([type]) #progress-preparing { + display: none; + } + :host(:not([type="offline"])) #progress-offline { display: none; } @@ -302,6 +311,11 @@ width: calc(100% - 32px); } + #progress-preparing { + align-self: start; + padding-bottom: 20px; + } + progress::-webkit-progress-bar { background-color: var(--cros-sys-primary_container); border-radius: 10px;
diff --git a/ui/file_manager/file_manager/widgets/xf_dlp_restriction_details_dialog.ts b/ui/file_manager/file_manager/widgets/xf_dlp_restriction_details_dialog.ts index c3531ad..8261476 100644 --- a/ui/file_manager/file_manager/widgets/xf_dlp_restriction_details_dialog.ts +++ b/ui/file_manager/file_manager/widgets/xf_dlp_restriction_details_dialog.ts
@@ -198,6 +198,8 @@ return str('DLP_COMPONENT_PLAY'); case chrome.fileManagerPrivate.VolumeType.GUEST_OS: return str('DLP_COMPONENT_VM'); + case chrome.fileManagerPrivate.VolumeType.DOCUMENTS_PROVIDER: + return str('DLP_COMPONENT_MICROSOFT_ONEDRIVE'); default: console.warn(`Got unexpected VolumeType value ${component}.`); return '';
diff --git a/ui/file_manager/integration_tests/file_manager/drive_specific.js b/ui/file_manager/integration_tests/file_manager/drive_specific.js index 289f366..979da600 100644 --- a/ui/file_manager/integration_tests/file_manager/drive_specific.js +++ b/ui/file_manager/integration_tests/file_manager/drive_specific.js
@@ -737,8 +737,11 @@ await remoteCall.waitUntilSelected(appId, 'G'); await remoteCall.waitForElement(appId, '.table-row[selected]'); - // Ensure the "G" directory has the shortcut class applied. - await remoteCall.waitForElement(appId, '#file-list [file-name="G"].shortcut'); + if ((await sendTestMessage({name: 'isDriveShortcutsEnabled'})) === 'true') { + // Ensure the "G" directory has the shortcut class applied. + await remoteCall.waitForElement( + appId, '#file-list [file-name="G"].shortcut'); + } // Open the link chrome.test.assertTrue(
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc index db8cb1f..2c2554ab 100644 --- a/ui/views/bubble/bubble_frame_view.cc +++ b/ui/views/bubble/bubble_frame_view.cc
@@ -111,6 +111,7 @@ Widget::ClosedReason::kCloseButtonClicked); }, this)); + close->SetProperty(views::kElementIdentifierKey, kCloseButtonElementId); close->SetVisible(false); close_ = AddChildView(std::move(close)); @@ -121,6 +122,7 @@ view->GetWidget()->Minimize(); }, this)); + minimize->SetProperty(views::kElementIdentifierKey, kMinimizeButtonElementId); minimize->SetVisible(false); minimize_ = AddChildView(std::move(minimize)); @@ -1127,4 +1129,8 @@ ADD_PROPERTY_METADATA(SkColor, BackgroundColor, ui::metadata::SkColorConverter) END_METADATA +DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(BubbleFrameView, + kMinimizeButtonElementId); +DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(BubbleFrameView, kCloseButtonElementId); + } // namespace views
diff --git a/ui/views/bubble/bubble_frame_view.h b/ui/views/bubble/bubble_frame_view.h index 9bd59e7..469d0d0 100644 --- a/ui/views/bubble/bubble_frame_view.h +++ b/ui/views/bubble/bubble_frame_view.h
@@ -59,6 +59,9 @@ public: METADATA_HEADER(BubbleFrameView); + DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kMinimizeButtonElementId); + DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kCloseButtonElementId); + enum class PreferredArrowAdjustment { kMirror, kOffset }; BubbleFrameView(const gfx::Insets& title_margins,
diff --git a/ui/views/window/dialog_client_view.cc b/ui/views/window/dialog_client_view.cc index e57e76d8..22f5e5a 100644 --- a/ui/views/window/dialog_client_view.cc +++ b/ui/views/window/dialog_client_view.cc
@@ -12,8 +12,10 @@ #include "base/memory/raw_ptr.h" #include "base/ranges/algorithm.h" #include "build/build_config.h" +#include "ui/base/interaction/element_identifier.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/base/ui_base_types.h" #include "ui/color/color_id.h" #include "ui/color/color_provider.h" #include "ui/events/keycodes/keyboard_codes.h" @@ -27,6 +29,7 @@ #include "ui/views/layout/table_layout.h" #include "ui/views/metadata/view_factory.h" #include "ui/views/style/platform_style.h" +#include "ui/views/view_class_properties.h" #include "ui/views/view_observer.h" #include "ui/views/view_tracker.h" #include "ui/views/view_utils.h" @@ -55,6 +58,19 @@ size1.height() + size2.height()); } +constexpr ui::ElementIdentifier kNoElementId; + +ui::ElementIdentifier GetButtonId(ui::DialogButton type) { + switch (type) { + case ui::DialogButton::DIALOG_BUTTON_OK: + return DialogClientView::kOkButtonElementId; + case ui::DialogButton::DIALOG_BUTTON_CANCEL: + return DialogClientView::kCancelButtonElementId; + default: + return kNoElementId; + } +} + } // namespace // Simple container to bubble child view changes up the view hierarchy. @@ -292,6 +308,7 @@ .SetCallback(base::BindRepeating(&DialogClientView::ButtonPressed, base::Unretained(this), type)) .SetText(title) + .SetProperty(views::kElementIdentifierKey, GetButtonId(type)) .SetStyle(style) .SetProminent(is_default) .SetIsDefault(is_default) @@ -478,4 +495,7 @@ BEGIN_METADATA(DialogClientView, ClientView) END_METADATA +DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(DialogClientView, kOkButtonElementId); +DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(DialogClientView, kCancelButtonElementId); + } // namespace views
diff --git a/ui/views/window/dialog_client_view.h b/ui/views/window/dialog_client_view.h index ebddfcd2..4a546b70 100644 --- a/ui/views/window/dialog_client_view.h +++ b/ui/views/window/dialog_client_view.h
@@ -11,6 +11,7 @@ #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" #include "base/memory/raw_ptr_exclusion.h" +#include "ui/base/interaction/element_identifier.h" #include "ui/base/ui_base_types.h" #include "ui/views/input_event_activation_protector.h" #include "ui/views/metadata/view_factory.h" @@ -41,6 +42,9 @@ public: METADATA_HEADER(DialogClientView); + DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kOkButtonElementId); + DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kCancelButtonElementId); + DialogClientView(Widget* widget, View* contents_view); DialogClientView(const DialogClientView&) = delete;
diff --git a/weblayer/BUILD.gn b/weblayer/BUILD.gn index 5fabf301..d66ec98 100644 --- a/weblayer/BUILD.gn +++ b/weblayer/BUILD.gn
@@ -186,6 +186,11 @@ "browser/bluetooth/weblayer_bluetooth_delegate_impl_client.h", "browser/browser_context_impl.cc", "browser/browser_context_impl.h", + "browser/browser_fragment_impl.cc", + "browser/browser_fragment_impl.h", + "browser/browser_fragment_list.cc", + "browser/browser_fragment_list.h", + "browser/browser_fragment_list_observer.h", "browser/browser_impl.cc", "browser/browser_impl.h", "browser/browser_list.cc",
diff --git a/weblayer/browser/android/metrics/metrics_browsertest.cc b/weblayer/browser/android/metrics/metrics_browsertest.cc index c0c5e86..7c20a13 100644 --- a/weblayer/browser/android/metrics/metrics_browsertest.cc +++ b/weblayer/browser/android/metrics/metrics_browsertest.cc
@@ -16,6 +16,7 @@ #include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h" #include "weblayer/browser/android/metrics/metrics_test_helper.h" #include "weblayer/browser/android/metrics/weblayer_metrics_service_client.h" +#include "weblayer/browser/browser_fragment_list.h" #include "weblayer/browser/browser_list.h" #include "weblayer/browser/profile_impl.h" #include "weblayer/public/navigation_controller.h" @@ -220,7 +221,8 @@ IsInForegroundWhenConsentGiven) { // There should be at least one browser which is resumed. This is the trigger // for whether the MetricsService is considered in the foreground. - EXPECT_TRUE(BrowserList::GetInstance()->HasAtLeastOneResumedBrowser()); + EXPECT_TRUE( + BrowserFragmentList::GetInstance()->HasAtLeastOneResumedBrowser()); RunConsentCallback(true); // RunConsentCallback() should trigger the MetricsService to start. EXPECT_TRUE(WebLayerMetricsServiceClient::GetInstance()
diff --git a/weblayer/browser/android/metrics/weblayer_metrics_service_client.cc b/weblayer/browser/android/metrics/weblayer_metrics_service_client.cc index 86d9d00..f21298a8 100644 --- a/weblayer/browser/android/metrics/weblayer_metrics_service_client.cc +++ b/weblayer/browser/android/metrics/weblayer_metrics_service_client.cc
@@ -20,7 +20,7 @@ #include "content/public/browser/browser_context.h" #include "google_apis/google_api_keys.h" #include "weblayer/browser/browser_context_impl.h" -#include "weblayer/browser/browser_list.h" +#include "weblayer/browser/browser_fragment_list.h" #include "weblayer/browser/browser_process.h" #include "weblayer/browser/java/jni/MetricsServiceClient_jni.h" #include "weblayer/browser/system_network_context_manager.h" @@ -82,11 +82,11 @@ WebLayerMetricsServiceClient::WebLayerMetricsServiceClient() { ProfileImpl::AddProfileObserver(this); - BrowserList::GetInstance()->AddObserver(this); + BrowserFragmentList::GetInstance()->AddObserver(this); } WebLayerMetricsServiceClient::~WebLayerMetricsServiceClient() { - BrowserList::GetInstance()->RemoveObserver(this); + BrowserFragmentList::GetInstance()->RemoveObserver(this); ProfileImpl::RemoveProfileObserver(this); } @@ -199,7 +199,7 @@ void WebLayerMetricsServiceClient::ApplyForegroundStateToServices() { const bool is_in_foreground = - BrowserList::GetInstance()->HasAtLeastOneResumedBrowser(); + BrowserFragmentList::GetInstance()->HasAtLeastOneResumedBrowser(); if (auto* metrics_service = WebLayerMetricsServiceClient::GetInstance() ->GetMetricsServiceIfStarted()) { if (is_in_foreground) @@ -224,8 +224,8 @@ UpdateUkmService(); } -void WebLayerMetricsServiceClient::OnHasAtLeastOneResumedBrowserStateChanged( - bool new_value) { +void WebLayerMetricsServiceClient:: + OnHasAtLeastOneResumedBrowserFragmentStateChanged(bool new_value) { ApplyForegroundStateToServices(); }
diff --git a/weblayer/browser/android/metrics/weblayer_metrics_service_client.h b/weblayer/browser/android/metrics/weblayer_metrics_service_client.h index 4461e81e..da8469b 100644 --- a/weblayer/browser/android/metrics/weblayer_metrics_service_client.h +++ b/weblayer/browser/android/metrics/weblayer_metrics_service_client.h
@@ -16,7 +16,7 @@ #include "components/metrics/metrics_service_client.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" -#include "weblayer/browser/browser_list_observer.h" +#include "weblayer/browser/browser_fragment_list_observer.h" #include "weblayer/browser/profile_impl.h" namespace weblayer { @@ -24,7 +24,7 @@ class WebLayerMetricsServiceClient : public ::metrics::AndroidMetricsServiceClient, public ProfileImpl::ProfileObserver, - public BrowserListObserver { + public BrowserFragmentListObserver { friend class base::NoDestructor<WebLayerMetricsServiceClient>; public: @@ -71,7 +71,8 @@ void ProfileDestroyed(ProfileImpl* profile) override; // BrowserListObserver: - void OnHasAtLeastOneResumedBrowserStateChanged(bool new_value) override; + void OnHasAtLeastOneResumedBrowserFragmentStateChanged( + bool new_value) override; std::vector<base::OnceClosure> post_start_tasks_; };
diff --git a/weblayer/browser/browser_fragment_impl.cc b/weblayer/browser/browser_fragment_impl.cc new file mode 100644 index 0000000..5d44518 --- /dev/null +++ b/weblayer/browser/browser_fragment_impl.cc
@@ -0,0 +1,47 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "weblayer/browser/browser_fragment_impl.h" + +#include "weblayer/browser/browser_fragment_list.h" +#include "weblayer/browser/java/jni/BrowserFragmentImpl_jni.h" + +namespace weblayer { + +BrowserFragmentImpl::BrowserFragmentImpl() { + BrowserFragmentList::GetInstance()->AddBrowserFragment(this); +} + +BrowserFragmentImpl::~BrowserFragmentImpl() { + BrowserFragmentList::GetInstance()->RemoveBrowserFragment(this); +} + +void BrowserFragmentImpl::OnFragmentResume(JNIEnv* env) { + UpdateFragmentResumedState(true); +} + +void BrowserFragmentImpl::OnFragmentPause(JNIEnv* env) { + UpdateFragmentResumedState(false); +} + +void BrowserFragmentImpl::DeleteBrowserFragment(JNIEnv* env) { + delete this; +} + +void BrowserFragmentImpl::UpdateFragmentResumedState(bool state) { + const bool old_has_at_least_one_active_browser = + BrowserFragmentList::GetInstance()->HasAtLeastOneResumedBrowser(); + fragment_resumed_ = state; + if (old_has_at_least_one_active_browser != + BrowserFragmentList::GetInstance()->HasAtLeastOneResumedBrowser()) { + BrowserFragmentList::GetInstance() + ->NotifyHasAtLeastOneResumedBrowserFragmentChanged(); + } +} + +static jlong JNI_BrowserFragmentImpl_CreateBrowserFragment(JNIEnv* env) { + return reinterpret_cast<intptr_t>(new BrowserFragmentImpl()); +} + +} // namespace weblayer
diff --git a/weblayer/browser/browser_fragment_impl.h b/weblayer/browser/browser_fragment_impl.h new file mode 100644 index 0000000..5e158f9e --- /dev/null +++ b/weblayer/browser/browser_fragment_impl.h
@@ -0,0 +1,34 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBLAYER_BROWSER_BROWSER_FRAGMENT_IMPL_H_ +#define WEBLAYER_BROWSER_BROWSER_FRAGMENT_IMPL_H_ + +#include "base/android/jni_android.h" + +namespace weblayer { + +class BrowserFragmentImpl { + public: + BrowserFragmentImpl(); + ~BrowserFragmentImpl(); + BrowserFragmentImpl(const BrowserFragmentImpl&) = delete; + BrowserFragmentImpl& operator=(const BrowserFragmentImpl&) = delete; + + void OnFragmentResume(JNIEnv* env); + void OnFragmentPause(JNIEnv* env); + + void DeleteBrowserFragment(JNIEnv* env); + + bool fragment_resumed() { return fragment_resumed_; } + + private: + void UpdateFragmentResumedState(bool state); + + bool fragment_resumed_ = false; +}; + +} // namespace weblayer + +#endif // WEBLAYER_BROWSER_BROWSER_FRAGMENT_IMPL_H_
diff --git a/weblayer/browser/browser_fragment_list.cc b/weblayer/browser/browser_fragment_list.cc new file mode 100644 index 0000000..b54cda2b3 --- /dev/null +++ b/weblayer/browser/browser_fragment_list.cc
@@ -0,0 +1,55 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "weblayer/browser/browser_fragment_list.h" + +#include "base/no_destructor.h" +#include "weblayer/browser/browser_fragment_impl.h" +#include "weblayer/browser/browser_fragment_list_observer.h" + +namespace weblayer { + +inline BrowserFragmentList::BrowserFragmentList() = default; +inline BrowserFragmentList::~BrowserFragmentList() = default; + +// static +BrowserFragmentList* BrowserFragmentList::GetInstance() { + static base::NoDestructor<BrowserFragmentList> browser_fragment_list; + return browser_fragment_list.get(); +} + +void BrowserFragmentList::AddBrowserFragment( + BrowserFragmentImpl* browser_fragment) { + CHECK(!browser_fragments_.contains(browser_fragment)); + browser_fragments_.insert(browser_fragment); +} + +void BrowserFragmentList::RemoveBrowserFragment( + BrowserFragmentImpl* browser_fragment) { + CHECK(browser_fragments_.contains(browser_fragment)); + browser_fragments_.erase(browser_fragment); +} + +void BrowserFragmentList::AddObserver(BrowserFragmentListObserver* observer) { + observers_.AddObserver(observer); +} + +void BrowserFragmentList::RemoveObserver( + BrowserFragmentListObserver* observer) { + observers_.RemoveObserver(observer); +} + +bool BrowserFragmentList::HasAtLeastOneResumedBrowser() { + return base::ranges::any_of(browser_fragments_, + &BrowserFragmentImpl::fragment_resumed); +} + +void BrowserFragmentList::NotifyHasAtLeastOneResumedBrowserFragmentChanged() { + const bool value = HasAtLeastOneResumedBrowser(); + for (BrowserFragmentListObserver& observer : observers_) { + observer.OnHasAtLeastOneResumedBrowserFragmentStateChanged(value); + } +} + +} // namespace weblayer
diff --git a/weblayer/browser/browser_fragment_list.h b/weblayer/browser/browser_fragment_list.h new file mode 100644 index 0000000..740ee1a --- /dev/null +++ b/weblayer/browser/browser_fragment_list.h
@@ -0,0 +1,54 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBLAYER_BROWSER_BROWSER_FRAGMENT_LIST_H_ +#define WEBLAYER_BROWSER_BROWSER_FRAGMENT_LIST_H_ + +#include "base/containers/flat_set.h" +#include "base/no_destructor.h" +#include "base/observer_list.h" + +namespace weblayer { + +class BrowserFragmentImpl; +class BrowserFragmentListObserver; + +// Tracks the set of browsers. +class BrowserFragmentList { + public: + BrowserFragmentList(); + ~BrowserFragmentList(); + + BrowserFragmentList(const BrowserFragmentList&) = delete; + BrowserFragmentList& operator=(const BrowserFragmentList&) = delete; + + static BrowserFragmentList* GetInstance(); + + const base::flat_set<BrowserFragmentImpl*>& browser_fragments() { + return browser_fragments_; + } + + // Returns true if there is at least one BrowserFragmentImpl in a resumed + // state. + bool HasAtLeastOneResumedBrowser(); + + void AddObserver(BrowserFragmentListObserver* observer); + void RemoveObserver(BrowserFragmentListObserver* observer); + + private: + friend class BrowserFragmentImpl; + friend class base::NoDestructor<BrowserFragmentList>; + + void AddBrowserFragment(BrowserFragmentImpl* browser_fragment); + void RemoveBrowserFragment(BrowserFragmentImpl* browser_fragment); + + void NotifyHasAtLeastOneResumedBrowserFragmentChanged(); + + base::flat_set<BrowserFragmentImpl*> browser_fragments_; + base::ObserverList<BrowserFragmentListObserver> observers_; +}; + +} // namespace weblayer + +#endif // WEBLAYER_BROWSER_BROWSER_FRAGMENT_LIST_H_
diff --git a/weblayer/browser/browser_fragment_list_observer.h b/weblayer/browser/browser_fragment_list_observer.h new file mode 100644 index 0000000..86e7acd --- /dev/null +++ b/weblayer/browser/browser_fragment_list_observer.h
@@ -0,0 +1,26 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBLAYER_BROWSER_BROWSER_FRAGMENT_LIST_OBSERVER_H_ +#define WEBLAYER_BROWSER_BROWSER_FRAGMENT_LIST_OBSERVER_H_ + +#include "base/observer_list_types.h" +#include "build/build_config.h" + +namespace weblayer { + +class BrowserFragmentListObserver : public base::CheckedObserver { + public: + // Called when the value of BrowserFragmentList::HasAtLeastOneResumedBrowser() + // changes. + virtual void OnHasAtLeastOneResumedBrowserFragmentStateChanged( + bool new_value) {} + + protected: + ~BrowserFragmentListObserver() override = default; +}; + +} // namespace weblayer + +#endif // WEBLAYER_BROWSER_BROWSER_FRAGMENT_LIST_OBSERVER_H_
diff --git a/weblayer/browser/browser_impl.cc b/weblayer/browser/browser_impl.cc index 91b532e..6bfccd1e 100644 --- a/weblayer/browser/browser_impl.cc +++ b/weblayer/browser/browser_impl.cc
@@ -24,7 +24,6 @@ #include "weblayer/public/browser_observer.h" #include "weblayer/public/browser_restore_observer.h" -#if BUILDFLAG(IS_ANDROID) #include "base/android/callback_android.h" #include "base/android/jni_array.h" #include "base/android/jni_string.h" @@ -36,11 +35,9 @@ using base::android::AttachCurrentThread; using base::android::JavaParamRef; using base::android::ScopedJavaLocalRef; -#endif namespace weblayer { -#if BUILDFLAG(IS_ANDROID) // This MUST match the values defined in // org.chromium.weblayer_private.interfaces.DarkModeStrategy. enum class DarkModeStrategy { @@ -48,7 +45,6 @@ kUserAgentDarkeningOnly = 1, kPreferWebThemeOverUserAgentDarkening = 2, }; -#endif // static constexpr char BrowserImpl::kPersistenceFilePrefix[]; @@ -61,25 +57,22 @@ base::WrapUnique(new BrowserImpl(static_cast<ProfileImpl*>(profile))); if (persistence_info) browser->RestoreStateIfNecessary(*persistence_info); + + DCHECK(FeatureListCreator::GetInstance()); + FeatureListCreator::GetInstance()->OnBrowserCreated(); + return browser; } BrowserImpl::~BrowserImpl() { -#if BUILDFLAG(IS_ANDROID) // Android side should always remove tabs first (because the Java Tab class // owns the C++ Tab). See BrowserImpl.destroy() (in the Java BrowserImpl // class). DCHECK(tabs_.empty()); -#else - while (!tabs_.empty()) - DestroyTab(tabs_.back().get()); -#endif BrowserList::GetInstance()->RemoveBrowser(this); -#if BUILDFLAG(IS_ANDROID) if (BrowserList::GetInstance()->browsers().empty()) BrowserProcess::GetInstance()->StopSafeBrowsingService(); -#endif } TabImpl* BrowserImpl::CreateTabForSessionRestore( @@ -92,10 +85,8 @@ } std::unique_ptr<TabImpl> tab = std::make_unique<TabImpl>(profile_, std::move(web_contents), guid); -#if BUILDFLAG(IS_ANDROID) Java_BrowserImpl_createJavaTabForNativeTab( AttachCurrentThread(), java_impl_, reinterpret_cast<jlong>(tab.get())); -#endif return AddTab(std::move(tab)); } @@ -104,7 +95,6 @@ return CreateTabForSessionRestore(std::move(web_contents), std::string()); } -#if BUILDFLAG(IS_ANDROID) bool BrowserImpl::CompositorHasSurface() { return Java_BrowserImpl_compositorHasSurface(AttachCurrentThread(), java_impl_); @@ -161,24 +151,7 @@ OnWebPreferenceChanged(std::string()); } -void BrowserImpl::OnFragmentStart(JNIEnv* env) { - // FeatureListCreator is created before any Browsers. - DCHECK(FeatureListCreator::GetInstance()); - FeatureListCreator::GetInstance()->OnBrowserFragmentStarted(); -} - -void BrowserImpl::OnFragmentResume(JNIEnv* env) { - UpdateFragmentResumedState(true); -} - -void BrowserImpl::OnFragmentPause(JNIEnv* env) { - UpdateFragmentResumedState(false); -} - -#endif - void BrowserImpl::SetWebPreferences(blink::web_pref::WebPreferences* prefs) { -#if BUILDFLAG(IS_ANDROID) PrefService* pref_service = profile()->GetBrowserContext()->pref_service(); prefs->password_echo_enabled = Java_BrowserImpl_getPasswordEchoEnabled( AttachCurrentThread(), java_impl_); @@ -219,16 +192,13 @@ prefs->preferred_color_scheme = blink::mojom::PreferredColorScheme::kLight; prefs->force_dark_mode_enabled = false; } -#endif } -#if BUILDFLAG(IS_ANDROID) void BrowserImpl::RemoveTabBeforeDestroyingFromJava(Tab* tab) { // The java side owns the Tab, and is going to delete it shortly. See // JNI_TabImpl_DeleteTab. RemoveTab(tab).release(); } -#endif void BrowserImpl::AddTab(Tab* tab) { DCHECK(tab); @@ -242,13 +212,9 @@ } void BrowserImpl::DestroyTab(Tab* tab) { -#if BUILDFLAG(IS_ANDROID) // Route destruction through the java side. Java_BrowserImpl_destroyTabImpl(AttachCurrentThread(), java_impl_, static_cast<TabImpl*>(tab)->GetJavaTab()); -#else - RemoveTab(tab); -#endif } void BrowserImpl::SetActiveTab(Tab* tab) { @@ -259,11 +225,9 @@ // TODO: currently the java side sets visibility, this code likely should // too and it should be removed from the java side. active_tab_ = static_cast<TabImpl*>(tab); -#if BUILDFLAG(IS_ANDROID) Java_BrowserImpl_onActiveTabChanged( AttachCurrentThread(), java_impl_, active_tab_ ? active_tab_->GetJavaTab() : nullptr); -#endif VisibleSecurityStateOfActiveTabChanged(); for (BrowserObserver& obs : browser_observers_) obs.OnActiveTabChanged(active_tab_); @@ -289,9 +253,7 @@ void BrowserImpl::OnRestoreCompleted() { for (BrowserRestoreObserver& obs : browser_restore_observers_) obs.OnRestoreCompleted(); -#if BUILDFLAG(IS_ANDROID) Java_BrowserImpl_onRestoreCompleted(AttachCurrentThread(), java_impl_); -#endif } void BrowserImpl::PrepareForShutdown() { @@ -327,16 +289,13 @@ if (visible_security_state_changed_callback_for_tests_) std::move(visible_security_state_changed_callback_for_tests_).Run(); -#if BUILDFLAG(IS_ANDROID) JNIEnv* env = base::android::AttachCurrentThread(); Java_BrowserImpl_onVisibleSecurityStateOfActiveTabChanged(env, java_impl_); -#endif } BrowserImpl::BrowserImpl(ProfileImpl* profile) : profile_(profile) { BrowserList::GetInstance()->AddBrowser(this); -#if BUILDFLAG(IS_ANDROID) profile_pref_change_registrar_.Init( profile_->GetBrowserContext()->pref_service()); auto pref_change_callback = base::BindRepeating( @@ -345,7 +304,6 @@ pref_change_callback); profile_pref_change_registrar_.Add(browser_ui::prefs::kWebKitForceEnableZoom, pref_change_callback); -#endif } void BrowserImpl::RestoreStateIfNecessary( @@ -362,10 +320,8 @@ DCHECK(!tab_impl->browser()); tabs_.push_back(std::move(tab)); tab_impl->set_browser(this); -#if BUILDFLAG(IS_ANDROID) Java_BrowserImpl_onTabAdded(AttachCurrentThread(), java_impl_, tab_impl->GetJavaTab()); -#endif for (BrowserObserver& obs : browser_observers_) obs.OnTabAdded(tab_impl); return tab_impl; @@ -383,10 +339,8 @@ if (active_tab_changed) SetActiveTab(nullptr); -#if BUILDFLAG(IS_ANDROID) Java_BrowserImpl_onTabRemoved(AttachCurrentThread(), java_impl_, tab ? tab_impl->GetJavaTab() : nullptr); -#endif for (BrowserObserver& obs : browser_observers_) obs.OnTabRemoved(tab, active_tab_changed); return owned_tab; @@ -404,17 +358,6 @@ } } -#if BUILDFLAG(IS_ANDROID) -void BrowserImpl::UpdateFragmentResumedState(bool state) { - const bool old_has_at_least_one_active_browser = - BrowserList::GetInstance()->HasAtLeastOneResumedBrowser(); - fragment_resumed_ = state; - if (old_has_at_least_one_active_browser != - BrowserList::GetInstance()->HasAtLeastOneResumedBrowser()) { - BrowserList::GetInstance()->NotifyHasAtLeastOneResumedBrowserChanged(); - } -} - // This function is friended. JNI_BrowserImpl_CreateBrowser can not be // friended, as it requires browser_impl.h to include BrowserImpl_jni.h, which // is problematic (meaning not really supported and generates compile errors). @@ -446,6 +389,5 @@ static void JNI_BrowserImpl_DeleteBrowser(JNIEnv* env, jlong browser) { delete reinterpret_cast<BrowserImpl*>(browser); } -#endif } // namespace weblayer
diff --git a/weblayer/browser/browser_impl.h b/weblayer/browser/browser_impl.h index ab513fab..b58cdcb7 100644 --- a/weblayer/browser/browser_impl.h +++ b/weblayer/browser/browser_impl.h
@@ -15,9 +15,7 @@ #include "components/prefs/pref_change_registrar.h" #include "weblayer/public/browser.h" -#if BUILDFLAG(IS_ANDROID) #include "base/android/scoped_java_ref.h" -#endif namespace base { class FilePath; @@ -64,7 +62,6 @@ const std::string& GetPackageName() { return package_name_; } -#if BUILDFLAG(IS_ANDROID) bool CompositorHasSurface(); base::android::ScopedJavaGlobalRef<jobject> java_browser() { @@ -85,16 +82,11 @@ JNIEnv* env, const base::android::JavaParamRef<jstring>& j_persistence_id); void WebPreferencesChanged(JNIEnv* env); - void OnFragmentStart(JNIEnv* env); - void OnFragmentResume(JNIEnv* env); - void OnFragmentPause(JNIEnv* env); + bool IsRestoringPreviousState(JNIEnv* env) { return IsRestoringPreviousState(); } - bool fragment_resumed() { return fragment_resumed_; } -#endif - // Used in tests to specify a non-default max (0 means use the default). std::vector<uint8_t> GetMinimalPersistenceState(int max_navigations_per_tab, int max_size_in_bytes); @@ -109,13 +101,11 @@ bool GetPasswordEchoEnabled(); void SetWebPreferences(blink::web_pref::WebPreferences* prefs); -#if BUILDFLAG(IS_ANDROID) // On Android the Java Tab class owns the C++ Tab. DestroyTab() calls to the // Java Tab class to initiate deletion. This function is called from the Java // side to remove the tab from the browser and shortly followed by deleting // the tab. void RemoveTabBeforeDestroyingFromJava(Tab* tab); -#endif // Browser: void AddTab(Tab* tab) override; @@ -137,12 +127,10 @@ // For creation. friend class Browser; -#if BUILDFLAG(IS_ANDROID) friend BrowserImpl* CreateBrowserForAndroid( ProfileImpl*, const std::string&, const base::android::JavaParamRef<jobject>&); -#endif explicit BrowserImpl(ProfileImpl* profile); @@ -156,12 +144,7 @@ void OnWebPreferenceChanged(const std::string& pref_name); -#if BUILDFLAG(IS_ANDROID) - void UpdateFragmentResumedState(bool state); - - bool fragment_resumed_ = false; base::android::ScopedJavaGlobalRef<jobject> java_impl_; -#endif base::ObserverList<BrowserObserver> browser_observers_; base::ObserverList<BrowserRestoreObserver> browser_restore_observers_; const raw_ptr<ProfileImpl> profile_;
diff --git a/weblayer/browser/browser_list.cc b/weblayer/browser/browser_list.cc index 76bb2436..5ab5a16 100644 --- a/weblayer/browser/browser_list.cc +++ b/weblayer/browser/browser_list.cc
@@ -12,9 +12,7 @@ #include "weblayer/browser/browser_impl.h" #include "weblayer/browser/browser_list_observer.h" -#if BUILDFLAG(IS_ANDROID) #include "weblayer/browser/browser_list_proxy.h" -#endif namespace weblayer { @@ -24,12 +22,6 @@ return browser_list.get(); } -#if BUILDFLAG(IS_ANDROID) -bool BrowserList::HasAtLeastOneResumedBrowser() { - return base::ranges::any_of(browsers_, &BrowserImpl::fragment_resumed); -} -#endif - void BrowserList::AddObserver(BrowserListObserver* observer) { observers_.AddObserver(observer); } @@ -39,24 +31,16 @@ } BrowserList::BrowserList() { -#if BUILDFLAG(IS_ANDROID) browser_list_proxy_ = std::make_unique<BrowserListProxy>(); AddObserver(browser_list_proxy_.get()); -#endif } BrowserList::~BrowserList() { -#if BUILDFLAG(IS_ANDROID) RemoveObserver(browser_list_proxy_.get()); -#endif } void BrowserList::AddBrowser(BrowserImpl* browser) { DCHECK(!browsers_.contains(browser)); -#if BUILDFLAG(IS_ANDROID) - // Browsers should not start out resumed. - DCHECK(!browser->fragment_resumed()); -#endif browsers_.insert(browser); for (BrowserListObserver& observer : observers_) observer.OnBrowserCreated(browser); @@ -64,22 +48,10 @@ void BrowserList::RemoveBrowser(BrowserImpl* browser) { DCHECK(browsers_.contains(browser)); -#if BUILDFLAG(IS_ANDROID) - // Browsers should not be resumed when being destroyed. - DCHECK(!browser->fragment_resumed()); -#endif browsers_.erase(browser); for (BrowserListObserver& observer : observers_) observer.OnBrowserDestroyed(browser); } -#if BUILDFLAG(IS_ANDROID) -void BrowserList::NotifyHasAtLeastOneResumedBrowserChanged() { - const bool value = HasAtLeastOneResumedBrowser(); - for (BrowserListObserver& observer : observers_) - observer.OnHasAtLeastOneResumedBrowserStateChanged(value); -} -#endif - } // namespace weblayer
diff --git a/weblayer/browser/browser_list.h b/weblayer/browser/browser_list.h index 5c5e786..cb07546c 100644 --- a/weblayer/browser/browser_list.h +++ b/weblayer/browser/browser_list.h
@@ -15,9 +15,7 @@ class BrowserImpl; class BrowserListObserver; -#if BUILDFLAG(IS_ANDROID) class BrowserListProxy; -#endif // Tracks the set of browsers. class BrowserList { @@ -53,9 +51,7 @@ base::flat_set<BrowserImpl*> browsers_; base::ObserverList<BrowserListObserver> observers_; -#if BUILDFLAG(IS_ANDROID) std::unique_ptr<BrowserListProxy> browser_list_proxy_; -#endif }; } // namespace weblayer
diff --git a/weblayer/browser/browser_list_observer.h b/weblayer/browser/browser_list_observer.h index 20cedd6c..5cfbb1d 100644 --- a/weblayer/browser/browser_list_observer.h +++ b/weblayer/browser/browser_list_observer.h
@@ -14,12 +14,6 @@ class BrowserListObserver : public base::CheckedObserver { public: -#if BUILDFLAG(IS_ANDROID) - // Called when the value of BrowserList::HasAtLeastOneResumedBrowser() - // changes. - virtual void OnHasAtLeastOneResumedBrowserStateChanged(bool new_value) {} -#endif - virtual void OnBrowserCreated(Browser* browser) {} virtual void OnBrowserDestroyed(Browser* browser) {}
diff --git a/weblayer/browser/feature_list_creator.cc b/weblayer/browser/feature_list_creator.cc index 082f6012..c353807 100644 --- a/weblayer/browser/feature_list_creator.cc +++ b/weblayer/browser/feature_list_creator.cc
@@ -72,17 +72,18 @@ #endif } -void FeatureListCreator::OnBrowserFragmentStarted() { - if (has_browser_fragment_started_) +void FeatureListCreator::OnBrowserCreated() { + if (has_browser_created_) { return; + } - has_browser_fragment_started_ = true; + has_browser_created_ = true; // It is expected this is called after SetUpFieldTrials(). DCHECK(variations_service_); - // This function is called any time a BrowserFragment is started. + // This function is called any time a Browser is started. // OnAppEnterForeground() really need only be called once, and because our - // notion of a fragment doesn't really map to the Application as a whole, + // notion of a browser doesn't really map to the Application as a whole, // call this function once. variations_service_->OnAppEnterForeground(); }
diff --git a/weblayer/browser/feature_list_creator.h b/weblayer/browser/feature_list_creator.h index 8965f6e..8ed788a5 100644 --- a/weblayer/browser/feature_list_creator.h +++ b/weblayer/browser/feature_list_creator.h
@@ -45,7 +45,7 @@ void PerformPreMainMessageLoopStartup(); // Calls through to the VariationService. - void OnBrowserFragmentStarted(); + void OnBrowserCreated(); variations::VariationsService* variations_service() const { return variations_service_.get(); @@ -64,8 +64,8 @@ WebLayerFieldTrials weblayer_field_trials_; - // Set to true the first time OnBrowserFragmentStarted() is called. - bool has_browser_fragment_started_ = false; + // Set to true the first time OnBrowserCreated() is called. + bool has_browser_created_ = false; }; } // namespace weblayer
diff --git a/weblayer/browser/java/BUILD.gn b/weblayer/browser/java/BUILD.gn index 766e456..8544319 100644 --- a/weblayer/browser/java/BUILD.gn +++ b/weblayer/browser/java/BUILD.gn
@@ -442,6 +442,7 @@ sources = [ "org/chromium/weblayer_private/ApplicationInfoHelper.java", "org/chromium/weblayer_private/AutocompleteSchemeClassifierImpl.java", + "org/chromium/weblayer_private/BrowserFragmentImpl.java", "org/chromium/weblayer_private/BrowserImpl.java", "org/chromium/weblayer_private/BrowserList.java", "org/chromium/weblayer_private/ContentViewRenderView.java",
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/BrowserFragmentImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/BrowserFragmentImpl.java index dc43aa6..0062a03 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/BrowserFragmentImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/BrowserFragmentImpl.java
@@ -20,6 +20,8 @@ import androidx.annotation.RequiresApi; import org.chromium.base.ContextUtils; +import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.annotations.NativeMethods; import org.chromium.base.metrics.RecordHistogram; import org.chromium.components.embedder_support.application.ClassLoaderContextWrapperFactory; import org.chromium.components.embedder_support.view.ContentView; @@ -31,7 +33,10 @@ /** * Implementation of RemoteFragmentImpl which provides the Fragment implementation for BrowserImpl. */ +@JNINamespace("weblayer") public class BrowserFragmentImpl extends FragmentHostingRemoteFragmentImpl { + private long mNativeBrowserFragmentImpl; + private static int sResumedCount; private static long sSessionStartTimeMs; @@ -72,6 +77,8 @@ mBrowser = browser; mWindowAndroid = new FragmentWindowAndroid(getWebLayerContext(), this); + + mNativeBrowserFragmentImpl = BrowserFragmentImplJni.get().createBrowserFragment(); } private void createAttachmentState(Context embedderContext) { @@ -107,7 +114,6 @@ protected void onStart() { StrictModeWorkaround.apply(); super.onStart(); - mBrowser.notifyFragmentInit(); mBrowser.updateAllTabs(); } @@ -119,7 +125,7 @@ long deltaMs = SystemClock.uptimeMillis() - sSessionStartTimeMs; RecordHistogram.recordLongTimesHistogram("Session.TotalDuration", deltaMs); } - mBrowser.notifyFragmentPause(); + BrowserFragmentImplJni.get().onFragmentPause(mNativeBrowserFragmentImpl); } @Override @@ -127,7 +133,8 @@ super.onResume(); sResumedCount++; if (sResumedCount == 1) sSessionStartTimeMs = SystemClock.uptimeMillis(); - mBrowser.notifyFragmentResume(); + WebLayerAccessibilityUtil.get().onBrowserResumed(mBrowser.getProfile()); + BrowserFragmentImplJni.get().onFragmentResume(mNativeBrowserFragmentImpl); } @Override @@ -280,6 +287,7 @@ mWindowAndroid.destroy(); mWindowAndroid = null; } + BrowserFragmentImplJni.get().deleteBrowserFragment(mNativeBrowserFragmentImpl); } @Override @@ -290,4 +298,12 @@ new ContextThemeWrapper(wrappedContext, R.style.Theme_WebLayer_Settings); return new FragmentHostingRemoteFragmentImpl.RemoteFragmentContext(themedContext); } + + @NativeMethods + interface Natives { + long createBrowserFragment(); + void onFragmentResume(long nativeBrowserFragmentImpl); + void onFragmentPause(long nativeBrowserFragmentImpl); + void deleteBrowserFragment(long nativeBrowserFragmentImpl); + } }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java index a99b3a4..71d9168 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
@@ -126,8 +126,6 @@ mNativeBrowser = BrowserImplJni.get().createBrowser( mProfile.getNativeProfile(), serviceContext.getPackageName(), this); mPasswordEchoEnabled = null; - - notifyFragmentInit(); // TODO(swestphal): Perhaps move to createBrowserFragmentImpl()? } @Override @@ -298,20 +296,6 @@ return ids; } - void notifyFragmentInit() { - // TODO(crbug.com/1378606): rename this. - BrowserImplJni.get().onFragmentStart(mNativeBrowser); - } - - void notifyFragmentResume() { - WebLayerAccessibilityUtil.get().onBrowserResumed(mProfile); - BrowserImplJni.get().onFragmentResume(mNativeBrowser); - } - - void notifyFragmentPause() { - BrowserImplJni.get().onFragmentPause(mNativeBrowser); - } - boolean isExternalIntentsEnabled() { return mIsExternalIntentsEnabled; } @@ -449,9 +433,6 @@ void prepareForShutdown(long nativeBrowserImpl); void restoreStateIfNecessary(long nativeBrowserImpl, String persistenceId); void webPreferencesChanged(long nativeBrowserImpl); - void onFragmentStart(long nativeBrowserImpl); - void onFragmentResume(long nativeBrowserImpl); - void onFragmentPause(long nativeBrowserImpl); boolean isRestoringPreviousState(long nativeBrowserImpl); } }