diff --git a/.gitmodules b/.gitmodules index 1862419..2f894c4 100644 --- a/.gitmodules +++ b/.gitmodules
@@ -199,10 +199,6 @@ [submodule "third_party/crossbench"] path = third_party/crossbench url = https://chromium.googlesource.com/crossbench -[submodule "third_party/crubit/src"] - path = third_party/crubit/src - url = https://chromium.googlesource.com/external/github.com/google/crubit - gclient-condition = checkout_crubit [submodule "third_party/depot_tools"] path = third_party/depot_tools url = https://chromium.googlesource.com/chromium/tools/depot_tools
diff --git a/DEPS b/DEPS index c31cf6f..c3284ca 100644 --- a/DEPS +++ b/DEPS
@@ -152,19 +152,6 @@ # Fetch clangd into the same bin/ directory as our clang binary. 'checkout_clangd': False, - # Fetch prebuilt and prepackaged Bazel binary/executable. Bazel is currently - # only needed by `chromium/src/tools/rust/build_crubit.py` and therefore - # shouldn't be used outside of Chromium Rust Experiments project. - # Furthermore note that Bazel is only needed when building Crubit during Rust - # toolchain build (and is *not* needed during regular Chromium builds). - 'checkout_bazel': False, - - # Fetch Crubit support libraries in order to build ..._rs_api.rs and - # ..._rs_api_impl.cc that are generated by prebuilt (see - # tools/rust/build_crubit.py) Crubit tools during Chromium build (see - # also //build/rust/rs_bindings_from_cc.gni). - 'checkout_crubit': False, - # By default checkout the OpenXR loader library only on Windows and Android. # The OpenXR backend for VR in Chromium is currently only supported for these # platforms, but support for other platforms may be added in the future. @@ -204,12 +191,6 @@ # qemu on linux-arm64 machines. 'checkout_fuchsia_for_arm64_host': False, - # Revision of Crubit (trunk on 2022-10-15). This should typically be the - # same as the revision specified in CRUBIT_REVISION in - # tools/rust/update_rust.py. More details and roll instructions can be - # found in tools/rust/README.md. - 'crubit_revision': 'f5cbdf4b54b0e6b9f63a4464a2c901c82e0f0209', - # By default, download the fuchsia sdk from the public sdk directory. 'fuchsia_sdk_cipd_prefix': 'fuchsia/sdk/core/', @@ -300,11 +281,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'src_internal_revision': 'ee6b0d656f2c6feb3d3e4b3a7371439443e87957', + 'src_internal_revision': '882104e8ef00c37b322eb765dca65f7220a7a854', # 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': '5218f67ec716edb39f5d005ddaf6e9d70eca7cc9', + 'skia_revision': '5fb36dd08a257623ee0738747286de09662e4591', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -312,7 +293,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '0040cda1170f9d481135a95d2fbff616120f404b', + 'angle_revision': 'cc44090d3483efdbae0dacf9c3fdb6c5d5a950fa', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -320,7 +301,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'fba5ab2f1c9c9b66b61e94d00662f9c12fcb692b', + 'pdfium_revision': 'cd4887caa580fe6b54be2fd5abe87dc3fb4de27e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -396,7 +377,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': '5fea877e0b17578765cd4520857b5b3b172b5199', + 'devtools_frontend_revision': 'b40634d52b0f5dcde839e73c8bdac4909458217a', # 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. @@ -420,7 +401,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': '690b037a7532f18b68e4907ddb0ddff6b1a8f1e7', + 'dawn_revision': '9d1b7b42eb282d2ce24e329a8bf41c89fdd67973', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -488,7 +469,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. - 'libunwind_revision': 'b7cdacaadbc4d121081ad6b146c7e94acec4c7ff', + 'libunwind_revision': '37c7d984b0b8520a0f99c6e6bbb0514e9996edc8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -952,31 +933,31 @@ 'bucket': 'chromium-browser-clang', 'objects': [ { - 'object_name': 'Linux_x64/rust-toolchain-009e73825af0e59ad4fc603562e038b3dbd6593a-22-llvmorg-20-init-3847-g69c43468.tar.xz', - 'sha256sum': '28f91ad46cce2750da95a6de305909a7f3904878cb1294de530ea962d19ccf19', - 'size_bytes': 115038168, - 'generation': 1727459972380358, + 'object_name': 'Linux_x64/rust-toolchain-009e73825af0e59ad4fc603562e038b3dbd6593a-23-llvmorg-20-init-3847-g69c43468.tar.xz', + 'sha256sum': 'a6c4e006002fd396331d77a1ccc8d2ab41fcfd0df5d3df7a6660b6aa7dc6f961', + 'size_bytes': 123945520, + 'generation': 1727798075788514, 'condition': 'host_os == "linux" and non_git_source', }, { - 'object_name': 'Mac/rust-toolchain-009e73825af0e59ad4fc603562e038b3dbd6593a-22-llvmorg-20-init-3847-g69c43468.tar.xz', - 'sha256sum': '7aa67826a75a39344a0eb1a7ca0ce439c811eb0318a7e1229cff1b4771d51a84', - 'size_bytes': 108381448, - 'generation': 1727459977622304, + 'object_name': 'Mac/rust-toolchain-009e73825af0e59ad4fc603562e038b3dbd6593a-23-llvmorg-20-init-3847-g69c43468.tar.xz', + 'sha256sum': '15927f50613ea0740e3fd7ff1fa40c255dcd4d7e7cd2a48fc85e6723ff9362fa', + 'size_bytes': 117066196, + 'generation': 1727798077728157, 'condition': 'host_os == "mac" and host_cpu == "x64"', }, { - 'object_name': 'Mac_arm64/rust-toolchain-009e73825af0e59ad4fc603562e038b3dbd6593a-22-llvmorg-20-init-3847-g69c43468.tar.xz', - 'sha256sum': '5b7399445e48c0cf87d4c56a577505ab7f03f936fc3d9eb538f3a5545d740497', - 'size_bytes': 97828296, - 'generation': 1727459981528990, + 'object_name': 'Mac_arm64/rust-toolchain-009e73825af0e59ad4fc603562e038b3dbd6593a-23-llvmorg-20-init-3847-g69c43468.tar.xz', + 'sha256sum': 'fb8daa448ed50eea88ac9c25c871332213a5c12a7c9beff0261478a6195b994d', + 'size_bytes': 103504896, + 'generation': 1727798079645218, 'condition': 'host_os == "mac" and host_cpu == "arm64"', }, { - 'object_name': 'Win/rust-toolchain-009e73825af0e59ad4fc603562e038b3dbd6593a-22-llvmorg-20-init-3847-g69c43468.tar.xz', - 'sha256sum': 'b518511a6278bbd7673c4eb42c3650160655ab3a6b8eeaefe0640de879123585', - 'size_bytes': 172446400, - 'generation': 1727459983614492, + 'object_name': 'Win/rust-toolchain-009e73825af0e59ad4fc603562e038b3dbd6593a-23-llvmorg-20-init-3847-g69c43468.tar.xz', + 'sha256sum': '139fbd7092526abcb91d5df67d4fc472a2bdae9a6487fcf3ec122c8ac112b4f8', + 'size_bytes': 178572296, + 'generation': 1727798081586976, 'condition': 'host_os == "win"', }, ], @@ -1295,7 +1276,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '59c00202c7c9270d760bf9a57ffd242ef6b0f271', + '4120c4d811f4c534ae4be631037163de6f797935', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1733,7 +1714,7 @@ # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'f834f05d9e79b960930b90da2d6e8f824c85a9b1', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c621276d4f2ec43ef4346a40f5dd328aa8bcbaaf', 'condition': 'checkout_chromeos', }, @@ -1762,19 +1743,14 @@ Var('chromium_git') + '/crossbench.git' + '@' + Var('crossbench_revision'), - 'src/third_party/crubit/src': { - 'url': Var('chromium_git') + '/external/github.com/google/crubit.git' + '@' + Var('crubit_revision'), - 'condition': 'checkout_crubit', - }, - 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '6dec85272d23ae587984cdd78eae428ce3b2ad9b', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'cc39a5681f48f42e8f0d16b9979bd3085c93de0a', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '51db6cf38207673d6bfa25c8e136277c3cfb6e9c', + 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '84c1220a80b203163a2c3d124ca103f63580d8ce', 'condition': 'checkout_src_internal', }, @@ -2240,7 +2216,7 @@ Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '478e5ab3eca30e600006d5a0a08b176fd34d3bd1', 'src/third_party/openscreen/src': - Var('chromium_git') + '/openscreen' + '@' + '6508900f6f6cbe87a61abdc337fcdfc289c43cea', + Var('chromium_git') + '/openscreen' + '@' + '1335531d0d7847625b52e9365902d7fcba82f3c6', 'src/third_party/openxr/src': { 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '288d3a7ebc1ad959f62d51da75baa3d27438c499', @@ -2266,7 +2242,7 @@ Var('pdfium_git') + '/pdfium.git' + '@' + Var('pdfium_revision'), 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '077bb360edecb33551e88c8097035e4b8cef245b', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '226197a61ac2b08b3860b5c73f8411ba0ba43947', 'src/base/tracing/test/data': { 'bucket': 'perfetto', @@ -2554,7 +2530,7 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@fb8f0127fca4d687f0584b62183572ed39ffc198', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@0828416b3eae17db848880d486e5c7f0038e46b0', 'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@a729c86d78552ec7e05e3748448e7a99f6f2a696', 'src/third_party/spirv-cross/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3', 'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@ec59c77a3bb5c747a369931ef101ac7c14823f2f', @@ -2603,7 +2579,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '9d029d337ae1832b5a7b9bf049a87076c12f749d', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '8569a0d5346330eb6641512df65b864bbaed11e9', + Var('webrtc_git') + '/src.git' + '@' + '076eb6cdf236cd6125ab126df2340ca3ee265425', # 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. @@ -2743,7 +2719,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'RlxrAZbJURNWeJnj9fybs_LDcbvjGjPa82Jx5_rz6K8C', + 'version': 'swnHsMK93RsqwT2pV61xuuotI2-ti-_np8j5BSXvmpoC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -2754,7 +2730,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'uLcuCv4vP-zbrrt6V9EDkeKSlPWvYejOMIU3WfWaDcQC', + 'version': 'xlRQrk5SDu4Nzw6mU6FfUm0VlXN1RlAz6CynFnVnnRgC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -4068,42 +4044,6 @@ 'dep_type': 'cipd', }, - 'src/tools/bazel/linux-amd64': { - 'packages': [{ - 'package': 'infra/3pp/tools/bazel_bootstrap/linux-amd64', - 'version': 'version:2@5.3.2.1', - }], - 'dep_type': 'cipd', - 'condition': 'host_os == "linux" and checkout_bazel and non_git_source', - }, - - 'src/tools/bazel/mac-amd64': { - 'packages': [{ - 'package': 'infra/3pp/tools/bazel_bootstrap/mac-amd64', - 'version': 'version:2@5.3.2.1', - }], - 'dep_type': 'cipd', - 'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_bazel', - }, - - 'src/tools/bazel/mac-arm64': { - 'packages': [{ - 'package': 'infra/3pp/tools/bazel_bootstrap/mac-arm64', - 'version': 'version:2@5.3.2.1', - }], - 'dep_type': 'cipd', - 'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_bazel', - }, - - 'src/tools/bazel/windows-amd64': { - 'packages': [{ - 'package': 'infra/3pp/tools/bazel_bootstrap/windows-amd64', - 'version': 'version:2@5.3.2', - }], - 'dep_type': 'cipd', - 'condition': 'host_os == "win" and checkout_bazel', - }, - # Dependencies from src_internal 'src/chromeos/ash/resources/internal': { 'url': Var('chrome_git') + '/chrome/chromeos/ash/resources/internal.git' + '@' + @@ -4396,7 +4336,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - 'c7ca556bc732c861810971db63ceffa352c2442e', + '028fcf85bcfd643709d3174307c2e4303e76fcd7', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/WATCHLISTS b/WATCHLISTS index 96b45f5..acdd7cc 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -2144,6 +2144,12 @@ 'content/browser/tab_contents/|'\ 'chrome/browser/ui/tab_contents/', }, + 'tab_group_infra': { + 'filepath': 'chrome/browser/data_sharing/'\ + '|chrome/browser/tab_group_sync/'\ + '|components/data_sharing/'\ + '|components/saved_tab_groups/' + }, 'tab_interface': { 'filepath': 'chrome/browser/tab/' }, @@ -3271,6 +3277,7 @@ 'tab_contents': ['ajwong+watch@chromium.org', 'avi@chromium.org', 'creis+watch@chromium.org'], + 'tab_group_infra' : [ 'chrome-tab-group-eng-leads+watch-infra@google.com' ], 'tab_interface': ['jinsukkim+watch@chromium.org'], 'tab_ui_and_start_surface': ['meiliang+watch@chromium.org', 'yuezhanggg+watch@chromium.org',
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java index bc446b4..efdb190 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java
@@ -491,11 +491,13 @@ ChromeComponent expected) { return new TypeSafeMatcher<ChromeComponent>() { @Override + @SuppressWarnings("LiteProtoToString") public void describeTo(Description description) { description.appendText(expected.toString()); } @Override + @SuppressWarnings("LiteProtoToString") protected void describeMismatchSafely( ChromeComponent item, Description mismatchDescription) { mismatchDescription.appendText("Doesn't match " + item.toString());
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/ClientHintsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/ClientHintsTest.java index 6e296e8..f8c33ad 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/ClientHintsTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/ClientHintsTest.java
@@ -810,8 +810,7 @@ "fake_platform", customUserAgentMetadata.get(AwUserAgentMetadata.MetadataKeys.PLATFORM)); Assert.assertEquals( - new Boolean(true), - customUserAgentMetadata.get(AwUserAgentMetadata.MetadataKeys.WOW64)); + true, customUserAgentMetadata.get(AwUserAgentMetadata.MetadataKeys.WOW64)); Assert.assertEquals( Arrays.deepToString(overrideBrands), Arrays.deepToString( @@ -835,8 +834,7 @@ Assert.assertEquals( "Android", customUserAgentMetadata.get(AwUserAgentMetadata.MetadataKeys.PLATFORM)); Assert.assertEquals( - new Boolean(false), - customUserAgentMetadata.get(AwUserAgentMetadata.MetadataKeys.WOW64)); + false, customUserAgentMetadata.get(AwUserAgentMetadata.MetadataKeys.WOW64)); String[][] actualOverrideBrands = (String[][])
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java index 4d74af7..b7087c5 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java
@@ -301,7 +301,7 @@ mWebServer.getBaseUrl(), null); } catch (UnsupportedEncodingException e) { - Assert.fail(); + throw new RuntimeException(e); } }); expectTitle(testString);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/devui/FlagsFragmentTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/devui/FlagsFragmentTest.java index a8355f48..86a4a97 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/devui/FlagsFragmentTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/devui/FlagsFragmentTest.java
@@ -572,10 +572,10 @@ return flagInteraction; } + /** Verify if the baseFeature flag contains only "Default", "Enabled" , "Disabled" states. */ @Test @MediumTest @Feature({"AndroidWebView"}) - /** Verify if the baseFeature flag contains only "Default", "Enabled" , "Disabled" states. */ public void testFlagStates_baseFeature() throws Throwable { ListView flagsList = mRule.getActivity().findViewById(R.id.flags_list); @@ -594,10 +594,10 @@ testFlagStatesHelper(firstBaseFeaturePosition); } + /** Verify if the commandline flag contains only "Default", "Enabled" states. */ @Test @MediumTest @Feature({"AndroidWebView"}) - /** Verify if the commandline flag contains only "Default", "Enabled" states. */ public void testFlagStates_commandLineFlag() throws Throwable { ListView flagsList = mRule.getActivity().findViewById(R.id.flags_list);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/services/JsSandboxServiceTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/services/JsSandboxServiceTest.java index 4e5f301..68dac32 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/services/JsSandboxServiceTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/services/JsSandboxServiceTest.java
@@ -465,7 +465,7 @@ // Invalid offset extending beyond end of file. // Note that file contains only ascii characters for testing purposes, hence we // can assume the length of the string to be the number of bytes it contains. - long offsetBeyondEof = fileContent.length() + 10; + long offsetBeyondEof = (long) fileContent.length() + 10; try (AssetFileDescriptor afd = new AssetFileDescriptor(pfd, offsetBeyondEof, fileContent.length())) { ListenableFuture<JavaScriptSandbox> jsSandboxFuture = @@ -532,7 +532,7 @@ // Read only up to call to `hello(); // File contains only ascii characters for testing purposes, hence we can predict the // number of bytes to remove from the end. - long length = fileContent.length() - "bye();".length(); + long length = (long) fileContent.length() - "bye();".length(); try (AssetFileDescriptor afd = new AssetFileDescriptor(pfd, 0, length)) { ListenableFuture<JavaScriptSandbox> jsSandboxFuture = JavaScriptSandbox.createConnectedInstanceForTestingAsync(context); @@ -588,7 +588,7 @@ // Declare length beyond EOF. // Note that file contains only ascii characters for testing purposes, hence we // can assume the length of the string to be the number of bytes it contains. - long length = fileContent.length() + 10; + long length = (long) fileContent.length() + 10; try (AssetFileDescriptor afd = new AssetFileDescriptor(pfd, 0, length)) { ListenableFuture<JavaScriptSandbox> jsSandboxFuture = JavaScriptSandbox.createConnectedInstanceForTestingAsync(context);
diff --git a/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java b/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java index 4579269..4dab588 100644 --- a/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java +++ b/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java
@@ -192,10 +192,8 @@ onData(new MenuItemMatcher(equalTo(name))).inRoot(rootMatcher).perform(click()); } - /** - * After select all action is clicked, the PopUp Menu may disappear - * briefly due to selection change, wait for the menu to reappear - */ + // After select all action is clicked, the PopUp Menu may disappear briefly due to selection + // change, wait for the menu to reappear if (name.equals(SELECT_ALL_ACTION)) { assertTrue(mWebViewActivityRule.waitForActionBarPopup()); }
diff --git a/ash/auth/active_session_auth_controller_impl.cc b/ash/auth/active_session_auth_controller_impl.cc index 2e6d9807..ed524273 100644 --- a/ash/auth/active_session_auth_controller_impl.cc +++ b/ash/auth/active_session_auth_controller_impl.cc
@@ -141,6 +141,52 @@ } // namespace +// This class manages the closing process after successful fingerprint +// authentication. It listens for two signals: +// 1. The completion of the successful authentication animation. +// 2. The authentication callback from cryptohome. +// Once both signals are received, the class triggers the closing process. +class ActiveSessionAuthControllerImpl::FingerprintAuthTracker { + public: + explicit FingerprintAuthTracker(ActiveSessionAuthControllerImpl* owner) + : owner_(owner) { + CHECK(owner_); + } + + void OnAuthenticationFinished( + std::unique_ptr<UserContext> user_context, + std::optional<AuthenticationError> authentication_error) { + CHECK_EQ(authentication_finished_, false); + authentication_finished_ = true; + if (authentication_error.has_value()) { + LOG(ERROR) << "Authentication error during OnFingerprintSuccess code: " + << authentication_error->get_cryptohome_code(); + } + owner_->user_context_ = std::move(user_context); + MaybeNotifyOwner(); + } + + void OnAnimationFinished() { + VLOG(1) << "OnAnimationFinished"; + CHECK_EQ(animation_finished_, false); + animation_finished_ = true; + MaybeNotifyOwner(); + } + + void MaybeNotifyOwner() { + if (authentication_finished_ && animation_finished_) { + owner_->StartClose(); + } + CHECK(owner_); + CHECK(owner_->fp_auth_tracker_); + } + + private: + const raw_ptr<ActiveSessionAuthControllerImpl> owner_; + bool animation_finished_ = false; + bool authentication_finished_ = false; +}; + ActiveSessionAuthControllerImpl::TestApi::TestApi( ActiveSessionAuthControllerImpl* controller) : controller_(controller) {} @@ -207,6 +253,9 @@ auth_performer_ = std::make_unique<AuthPerformer>(UserDataAuthClient::Get()); account_id_ = Shell::Get()->session_controller()->GetActiveAccountId(); + fingerprint_animation_finished_ = false; + fingerprint_authentication_finished_ = false; + user_manager::User* active_user = user_manager::UserManager::Get()->GetActiveUser(); auto user_context = std::make_unique<UserContext>(*active_user); @@ -299,6 +348,7 @@ LOG(ERROR) << "Failed to start fingerprint auth session - only " "non-fingerprint factors will be available."; } else { + fp_auth_tracker_ = std::make_unique<FingerprintAuthTracker>(this); available_factors_.Put(AuthInputType::kFingerprint); } std::move(on_auth_factors_ready).Run(std::move(user_context)); @@ -319,6 +369,9 @@ } switch (scan_result) { case FingerprintAuthScanResult::kSuccess: + contents_view_->NotifyFingerprintAuthSuccess( + base::BindOnce(&FingerprintAuthTracker::OnAnimationFinished, + base::Unretained(fp_auth_tracker_.get()))); if (state_ == ActiveSessionAuthState::kPasswordAuthStarted || state_ == ActiveSessionAuthState::kPinAuthStarted) { SetState(ActiveSessionAuthState::kFingerprintAuthSucceededWaiting); @@ -346,25 +399,14 @@ NOTREACHED(); } -void ActiveSessionAuthControllerImpl::OnFingerprintSuccess( - std::unique_ptr<UserContext> user_context, - std::optional<AuthenticationError> authentication_error) { - if (authentication_error.has_value()) { - LOG(ERROR) << "Authentication error during OnFingerprintSuccess code: " - << authentication_error->get_cryptohome_code(); - } - user_context_ = std::move(user_context); - StartClose(); -} - void ActiveSessionAuthControllerImpl::HandleFingerprintAuthSuccess() { CHECK(user_context_); uma_recorder_.RecordAuthSucceeded(AuthInputType::kFingerprint); SetState(ActiveSessionAuthState::kFingerprintAuthSucceeded); auth_performer_->AuthenticateWithLegacyFingerprint( std::move(user_context_), - base::BindOnce(&ActiveSessionAuthControllerImpl::OnFingerprintSuccess, - weak_ptr_factory_.GetWeakPtr())); + base::BindOnce(&FingerprintAuthTracker::OnAuthenticationFinished, + base::Unretained(fp_auth_tracker_.get()))); } void ActiveSessionAuthControllerImpl::InitUi() { @@ -410,12 +452,14 @@ auth_performer_->InvalidateCurrentAttempts(); if (fp_client_ && available_factors_.Has(AuthInputType::kFingerprint)) { + CHECK(fp_auth_tracker_); fp_client_->TerminateFingerprintAuth( std::move(user_context_), base::BindOnce(&ActiveSessionAuthControllerImpl::CompleteClose, weak_ptr_factory_.GetWeakPtr())); return; } + CHECK(!fp_auth_tracker_); CompleteClose(std::move(user_context_), std::nullopt); } @@ -441,7 +485,7 @@ title_.clear(); description_.clear(); - + fp_auth_tracker_.reset(); widget_.reset(); }
diff --git a/ash/auth/active_session_auth_controller_impl.h b/ash/auth/active_session_auth_controller_impl.h index fcc26595..3a8e3fc 100644 --- a/ash/auth/active_session_auth_controller_impl.h +++ b/ash/auth/active_session_auth_controller_impl.h
@@ -115,6 +115,7 @@ void OnFingerprintTerminated( std::unique_ptr<UserContext> user_context, std::optional<AuthenticationError> authentication_error); + void OnFingerprintAnimationFinished(); // Tracks the authentication flow for the active session. enum class ActiveSessionAuthState { @@ -136,6 +137,9 @@ }; private: + class FingerprintAuthTracker; + friend class FingerprintAuthTracker; + using AuthFactorsReadyCallback = base::OnceCallback<void(std::unique_ptr<UserContext>)>; @@ -197,7 +201,11 @@ std::unique_ptr<AuthRequest> auth_request_; + bool fingerprint_animation_finished_ = false; + bool fingerprint_authentication_finished_ = false; + raw_ptr<ActiveSessionFingerprintClient> fp_client_; + std::unique_ptr<FingerprintAuthTracker> fp_auth_tracker_; ActiveSessionAuthMetricsRecorder uma_recorder_;
diff --git a/ash/auth/views/active_session_auth_view.cc b/ash/auth/views/active_session_auth_view.cc index e1e2b04..62bfc1f1 100644 --- a/ash/auth/views/active_session_auth_view.cc +++ b/ash/auth/views/active_session_auth_view.cc
@@ -290,6 +290,12 @@ auth_container_->SetFingerprintState(state); } +void ActiveSessionAuthView::NotifyFingerprintAuthSuccess( + base::OnceClosure on_success_animation_finished) { + auth_container_->NotifyFingerprintAuthSuccess( + std::move(on_success_animation_finished)); +} + void ActiveSessionAuthView::NotifyFingerprintAuthFailure() { auth_container_->NotifyFingerprintAuthFailure(); }
diff --git a/ash/auth/views/active_session_auth_view.h b/ash/auth/views/active_session_auth_view.h index a6dc9f60..2ab4ed4 100644 --- a/ash/auth/views/active_session_auth_view.h +++ b/ash/auth/views/active_session_auth_view.h
@@ -118,6 +118,8 @@ // FingerprintView actions: void SetFingerprintState(FingerprintState state); + void NotifyFingerprintAuthSuccess( + base::OnceClosure on_success_animation_finished); void NotifyFingerprintAuthFailure(); private:
diff --git a/ash/auth/views/auth_container_view.cc b/ash/auth/views/auth_container_view.cc index 2f23fdb..10ad61e 100644 --- a/ash/auth/views/auth_container_view.cc +++ b/ash/auth/views/auth_container_view.cc
@@ -330,6 +330,13 @@ fingerprint_view_->SetState(state); } +void AuthContainerView::NotifyFingerprintAuthSuccess( + base::OnceCallback<void()> on_success_animation_finished) { + CHECK(fingerprint_view_); + fingerprint_view_->NotifyAuthSuccess( + std::move(on_success_animation_finished)); +} + void AuthContainerView::NotifyFingerprintAuthFailure() { CHECK(fingerprint_view_); fingerprint_view_->NotifyAuthFailure();
diff --git a/ash/auth/views/auth_container_view.h b/ash/auth/views/auth_container_view.h index 967876e..8561cc14 100644 --- a/ash/auth/views/auth_container_view.h +++ b/ash/auth/views/auth_container_view.h
@@ -127,6 +127,8 @@ // FingerprintView actions: void SetFingerprintState(FingerprintState state); + void NotifyFingerprintAuthSuccess( + base::OnceClosure on_success_animation_finished); void NotifyFingerprintAuthFailure(); private:
diff --git a/ash/auth/views/fingerprint_view.cc b/ash/auth/views/fingerprint_view.cc index 86fd725..f0f4271 100644 --- a/ash/auth/views/fingerprint_view.cc +++ b/ash/auth/views/fingerprint_view.cc
@@ -5,8 +5,10 @@ #include "ash/auth/views/fingerprint_view.h" #include <memory> +#include <optional> #include <string> #include <string_view> +#include <vector> #include "ash/auth/views/auth_common.h" #include "ash/login/resources/grit/login_resources.h" @@ -18,6 +20,7 @@ #include "ash/style/ash_color_id.h" #include "base/check.h" #include "base/check_op.h" +#include "base/containers/flat_tree.h" #include "base/functional/bind.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" @@ -28,7 +31,9 @@ #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/resource/resource_bundle.h" #include "ui/chromeos/styles/cros_tokens_color_mappings.h" +#include "ui/color/color_provider.h" #include "ui/gfx/geometry/size.h" +#include "ui/lottie/animation.h" #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/controls/label.h" #include "ui/views/layout/box_layout.h" @@ -68,6 +73,34 @@ constexpr ui::ColorId kFingerprintIconDisabledColorId = cros_tokens::kCrosSysDisabled; +constexpr float kCheckmarkAnimationPlaybackSpeed = 2.25; + +std::unique_ptr<lottie::Animation> GetCheckmarkAnimation( + ui::ColorProvider* color_provider) { + std::optional<std::vector<uint8_t>> lottie_data = + ui::ResourceBundle::GetSharedInstance().GetLottieData( + IDR_LOGIN_ARROW_CHECKMARK_ANIMATION); + CHECK(lottie_data.has_value()); + + cc::SkottieColorMap color_map = cc::SkottieColorMap{ + cc::SkottieMapColor( + "cros.sys.illo.color2", + color_provider->GetColor(cros_tokens::kCrosSysPositive)), + cc::SkottieMapColor( + "cros.sys.app_base_shaded", + color_provider->GetColor(cros_tokens::kCrosSysOnSurface)), + }; + + std::unique_ptr<lottie::Animation> animation = + std::make_unique<lottie::Animation>( + cc::SkottieWrapper::UnsafeCreateSerializable(lottie_data.value()), + std::move(color_map)); + + animation->SetPlaybackSpeed(kCheckmarkAnimationPlaybackSpeed); + + return animation; +} + } // namespace //----------------------- FingerprintView Test API ------------------------ @@ -125,6 +158,12 @@ gfx::Size(kFingerprintIconSizeDp, kFingerprintIconSizeDp), 0 /*corner_radius*/)); + lottie_animation_view_ = + AddChildView(std::make_unique<views::AnimatedImageView>()); + lottie_animation_view_->SetImageSize( + gfx::Size(kFingerprintIconSizeDp, kFingerprintIconSizeDp)); + lottie_animation_view_->SetVisible(false); + label_ = AddChildView(std::make_unique<views::Label>()); label_->SetSubpixelRenderingEnabled(false); label_->SetAutoColorReadabilityEnabled(false); @@ -141,6 +180,8 @@ FingerprintView::~FingerprintView() { icon_ = nullptr; + scoped_animation_observer_.Reset(); + lottie_animation_view_ = nullptr; label_ = nullptr; } @@ -148,6 +189,11 @@ if (state_ == state) { return; } + + if (has_success_) { + return; + } + reset_state_.Stop(); state_ = state; DisplayCurrentState(); @@ -158,11 +204,39 @@ return; } + if (has_success_) { + return; + } + has_pin_ = has_pin; DisplayCurrentState(); } +void FingerprintView::NotifyAuthSuccess( + base::OnceClosure on_success_animation_finished) { + has_success_ = true; + CHECK(on_success_animation_finished_.is_null()); + on_success_animation_finished_ = std::move(on_success_animation_finished); + CHECK(GetColorProvider()); + std::unique_ptr<lottie::Animation> animation = + GetCheckmarkAnimation(GetColorProvider()); + CHECK(animation); + auto playback_config = lottie::Animation::PlaybackConfig::CreateWithStyle( + lottie::Animation::Style::kLinear, *animation); + // Observe animation to know when it finishes playing. + scoped_animation_observer_.Observe(animation.get()); + lottie_animation_view_->SetAnimatedImage(std::move(animation)); + lottie_animation_view_->Play(playback_config); + + icon_->SetVisible(false); + lottie_animation_view_->SetVisible(true); +} + void FingerprintView::NotifyAuthFailure() { + if (has_success_) { + return; + } + SetState(FingerprintState::AVAILABLE_WITH_FAILED_ATTEMPT); reset_state_.Start( FROM_HERE, kResetToDefaultIconDelay, @@ -171,9 +245,14 @@ } void FingerprintView::OnGestureEvent(ui::GestureEvent* event) { + if (has_success_) { + return; + } + if (event->type() != ui::EventType::kGestureTap) { return; } + if (state_ == FingerprintState::AVAILABLE_DEFAULT || state_ == FingerprintState::AVAILABLE_WITH_TOUCH_SENSOR_WARNING || state_ == FingerprintState::AVAILABLE_WITH_FAILED_ATTEMPT) { @@ -186,6 +265,7 @@ } void FingerprintView::DisplayCurrentState() { + CHECK(!has_success_); if (state_ == FingerprintState::UNAVAILABLE) { SetVisible(false); return; @@ -198,6 +278,7 @@ } void FingerprintView::SetIcon() { + CHECK(!has_success_); switch (state_) { case FingerprintState::AVAILABLE_DEFAULT: case FingerprintState::AVAILABLE_WITH_TOUCH_SENSOR_WARNING: @@ -222,6 +303,7 @@ } ui::ColorId FingerprintView::GetIconColorIdFromState() const { + CHECK(!has_success_); switch (state_) { case FingerprintState::AVAILABLE_DEFAULT: case FingerprintState::AVAILABLE_WITH_TOUCH_SENSOR_WARNING: @@ -236,6 +318,7 @@ } int FingerprintView::GetTextIdFromState() const { + CHECK(!has_success_); switch (state_) { case FingerprintState::AVAILABLE_DEFAULT: case FingerprintState::AVAILABLE_WITH_FAILED_ATTEMPT: @@ -255,6 +338,7 @@ } int FingerprintView::GetA11yTextIdFromState() const { + CHECK(!has_success_); switch (state_) { case FingerprintState::AVAILABLE_DEFAULT: case FingerprintState::AVAILABLE_WITH_FAILED_ATTEMPT: @@ -284,6 +368,15 @@ return gfx::Size(kTextLineWidthDp, preferred_height); } +void FingerprintView::AnimationCycleEnded(const lottie::Animation* animation) { + CHECK(has_success_); + scoped_animation_observer_.Reset(); + + if (on_success_animation_finished_) { + std::move(on_success_animation_finished_).Run(); + } +} + BEGIN_METADATA(FingerprintView) END_METADATA
diff --git a/ash/auth/views/fingerprint_view.h b/ash/auth/views/fingerprint_view.h index dfff9f9..887aeac 100644 --- a/ash/auth/views/fingerprint_view.h +++ b/ash/auth/views/fingerprint_view.h
@@ -11,10 +11,13 @@ #include "ash/style/ash_color_id.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/scoped_observation.h" #include "base/timer/timer.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/gfx/geometry/size.h" +#include "ui/lottie/animation_observer.h" +#include "ui/views/controls/animated_image_view.h" #include "ui/views/controls/label.h" #include "ui/views/view.h" @@ -23,7 +26,8 @@ // FingerprintView is a view displaying a fingerprint icon and label, // dynamically adapting based on fingerprint availability, // authentication state, and the presence of a PIN. -class ASH_EXPORT FingerprintView : public views::View { +class ASH_EXPORT FingerprintView : public views::View, + public lottie::AnimationObserver { METADATA_HEADER(FingerprintView, views::View) public: class TestApi { @@ -66,6 +70,9 @@ // Indicates if a PIN is set, potentially influencing the label text. void SetHasPin(bool has_pin); + // Triggers a brief animation to signal an authentication success. + void NotifyAuthSuccess(base::OnceClosure on_success_animation_finished); + // Triggers a brief animation to signal an authentication failure. void NotifyAuthFailure(); @@ -74,6 +81,9 @@ gfx::Size CalculatePreferredSize( const views::SizeBounds& available_size) const override; + // lottie::AnimationObserver: + void AnimationCycleEnded(const lottie::Animation* animation) override; + private: // Updates the visual elements to reflect the current state and PIN // availability. @@ -90,6 +100,16 @@ raw_ptr<views::Label> label_ = nullptr; raw_ptr<AnimatedRoundedImageView> icon_ = nullptr; + // A green checkmark animation shown when NotifyAuthSuccess called. + raw_ptr<views::AnimatedImageView> lottie_animation_view_; + + base::ScopedObservation<lottie::Animation, lottie::AnimationObserver> + scoped_animation_observer_{this}; + + base::OnceClosure on_success_animation_finished_; + + bool has_success_ = false; + // State: FingerprintState state_ = FingerprintState::UNAVAILABLE; bool has_pin_ = false;
diff --git a/ash/capture_mode/base_capture_mode_session.h b/ash/capture_mode/base_capture_mode_session.h index ff704734..e7a16ec 100644 --- a/ash/capture_mode/base_capture_mode_session.h +++ b/ash/capture_mode/base_capture_mode_session.h
@@ -10,6 +10,7 @@ #include "ash/capture_mode/capture_mode_controller.h" #include "ash/shell_observer.h" #include "ui/compositor/layer_owner.h" +#include "ui/views/controls/button/button.h" namespace ash { @@ -154,6 +155,11 @@ // the captured region as `image`. virtual void ShowSearchResultsPanel(const gfx::ImageSkia& image) = 0; + // Adds an action button below the selected region during an active session. + virtual void AddActionButton(views::Button::PressedCallback callback, + std::u16string text, + const gfx::VectorIcon* icon) = 0; + // ShellObserver: void OnRootWindowWillShutdown(aura::Window* root_window) override;
diff --git a/ash/capture_mode/capture_mode_session.cc b/ash/capture_mode/capture_mode_session.cc index c9e2c6c..3648816 100644 --- a/ash/capture_mode/capture_mode_session.cc +++ b/ash/capture_mode/capture_mode_session.cc
@@ -32,12 +32,14 @@ #include "ash/keyboard/ui/keyboard_ui_controller.h" #include "ash/public/cpp/resources/grit/ash_public_unscaled_resources.h" #include "ash/public/cpp/shell_window_ids.h" +#include "ash/resources/vector_icons/vector_icons.h" #include "ash/root_window_controller.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/style/ash_color_id.h" #include "ash/style/color_util.h" #include "ash/style/icon_button.h" +#include "ash/style/pill_button.h" #include "ash/style/tab_slider_button.h" #include "ash/utility/cursor_setter.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" @@ -188,6 +190,9 @@ // The horizontal distance between action buttons in a row. constexpr int kActionButtonSpacing = 10; +// The corner radius for an action button. +constexpr int kActionButtonRadius = 18; + // Mouse cursor warping is disabled when the capture source is a custom region. // Sets the mouse warp status to |enable| and return the original value. bool SetMouseWarpEnabled(bool enable) { @@ -484,6 +489,59 @@ return widget_bounds; } +class ActionButtonView : public PillButton { + METADATA_HEADER(ActionButtonView, PillButton) + + public: + ActionButtonView(views::Button::PressedCallback callback, + std::u16string text, + const gfx::VectorIcon* icon) + : PillButton(std::move(callback), + text, + Type::kDefaultLargeWithIconLeading, + icon), + // Since this view has fully circular rounded corners, we can't use a + // nine patch layer for the shadow. We have to use the + // `ShadowOnTextureLayer`. For more info, see https://crbug.com/1308800. + shadow_(SystemShadow::CreateShadowOnTextureLayer( + SystemShadow::Type::kElevation12)) { + shadow_->SetRoundedCornerRadius(kActionButtonRadius); + capture_mode_util::SetHighlightBorder( + this, kActionButtonRadius, + views::HighlightBorder::Type::kHighlightBorderNoShadow); + } + ActionButtonView(const ActionButtonView&) = delete; + ActionButtonView& operator=(const ActionButtonView&) = delete; + ~ActionButtonView() override = default; + + // views::View: + void AddedToWidget() override { + PillButton::AddedToWidget(); + + // Attach the shadow at the bottom of the widget layer. + auto* shadow_layer = shadow_->GetLayer(); + auto* widget_layer = GetWidget()->GetLayer(); + widget_layer->Add(shadow_layer); + widget_layer->StackAtBottom(shadow_layer); + + // Make the shadow observe the color provider source change to update the + // colors. + shadow_->ObserveColorProviderSource(GetWidget()); + } + + void OnBoundsChanged(const gfx::Rect& previous_bounds) override { + // The shadow layer is a sibling of this view's layer, and should have the + // same bounds. + shadow_->SetContentBounds(layer()->bounds()); + } + + private: + std::unique_ptr<SystemShadow> shadow_; +}; + +BEGIN_METADATA(ActionButtonView) +END_METADATA + } // namespace // ----------------------------------------------------------------------------- @@ -1306,10 +1364,6 @@ void CaptureModeSession::ShowSearchResultsPanel(const gfx::ImageSkia& image) { DCHECK_EQ(active_behavior()->behavior_type(), BehaviorType::kSunfish); - // When we show the panel, we also want to update the action button container - // and any buttons that might be visible. - UpdateActionContainerWidget(); - if (!search_results_panel_widget_) { search_results_panel_widget_ = SearchResultsPanel::CreateWidget(current_root()); @@ -1320,6 +1374,27 @@ auto* search_results_panel = views::AsViewClass<SearchResultsPanel>( search_results_panel_widget_->GetContentsView()); search_results_panel->SetSearchBoxImage(image); + + UpdateActionContainerWidget(); +} + +void CaptureModeSession::AddActionButton( + views::Button::PressedCallback callback, + std::u16string text, + const gfx::VectorIcon* icon) { + // Another process may try to add an action button before the container is + // created, or while it is invalid. In these cases, we don't want to do + // anything. + if (!action_container_widget_) { + return; + } + + // TODO(http://b/368674223): Add a ranking when the button is added. + CHECK(action_container_view_); + action_container_view_->AddChildView(std::make_unique<ActionButtonView>( + std::move(callback), text, &kCaptureModeImageIcon)); + + UpdateActionContainerWidget(); } void CaptureModeSession::OnPaintLayer(const ui::PaintContext& context) { @@ -2202,6 +2277,10 @@ fine_tune_position_ = GetFineTunePosition(screen_location, is_touch); + // The capture region will be changing, so remove any existing action buttons, + // if any, as they will no longer be applicable. + RemoveAllActionButtons(); + if (fine_tune_position_ == FineTunePosition::kNone) { // If the point is outside the capture region and not on the capture bar or // settings menu, restart to the select phase. @@ -2664,62 +2743,6 @@ return capture_label_view_->ShouldHandleEvent(); } -// TODO(http://b/363069895): Upload strings for translation. -void CaptureModeSession::UpdateActionContainerWidget() { - CHECK(features::IsSunfishFeatureEnabled()); - - if (!action_container_widget_) { - action_container_widget_ = std::make_unique<views::Widget>(); - auto* parent = GetParentContainer(current_root_); - action_container_widget_->Init( - CreateWidgetParams(parent, gfx::Rect(), "ActionButtonsContainer")); - - action_container_widget_->SetContentsView( - views::Builder<views::BoxLayoutView>() - .CopyAddressTo(&action_container_view_) - .SetOrientation(views::BoxLayout::Orientation::kHorizontal) - .SetBetweenChildSpacing(kActionButtonSpacing) - .SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kCenter) - .SetCrossAxisAlignment( - views::BoxLayout::CrossAxisAlignment::kStretch) - .Build()); - - action_container_widget_->Show(); - } - - UpdateActionContainerWidgetBounds(); -} - -void CaptureModeSession::UpdateActionContainerWidgetBounds() { - DCHECK(action_container_widget_); - - const gfx::Rect bounds = CalculateActionContainerWidgetBounds(); - const gfx::Rect old_bounds = - action_container_widget_->GetNativeWindow()->GetBoundsInScreen(); - if (old_bounds == bounds) { - return; - } - - action_container_widget_->SetBounds(bounds); -} - -gfx::Rect CaptureModeSession::CalculateActionContainerWidgetBounds() const { - DCHECK(action_container_widget_); - - const gfx::Size preferred_size = action_container_view_->GetPreferredSize(); - const gfx::Rect capture_bar_bounds = - action_container_widget_->GetNativeWindow()->bounds(); - - gfx::Rect bounds(current_root_->bounds()); - const gfx::Rect capture_region = controller_->user_capture_region(); - bounds = CalculateRegionEdgeBounds(preferred_size, capture_bar_bounds, - capture_region, current_root_); - - // User capture bounds are in root window coordinates so convert them here. - wm::ConvertRectToScreen(current_root_, &bounds); - return bounds; -} - void CaptureModeSession::UpdateRootWindowDimmers() { root_window_dimmers_.clear(); @@ -2955,6 +2978,65 @@ selected_window); } +// TODO(http://b/363069895): Upload strings for translation. +void CaptureModeSession::UpdateActionContainerWidget() { + DCHECK_EQ(active_behavior()->behavior_type(), BehaviorType::kSunfish); + + if (!action_container_widget_) { + action_container_widget_ = std::make_unique<views::Widget>(); + auto* parent = GetParentContainer(current_root_); + action_container_widget_->Init( + CreateWidgetParams(parent, gfx::Rect(), "ActionButtonsContainer")); + + action_container_widget_->SetContentsView( + views::Builder<views::BoxLayoutView>() + .CopyAddressTo(&action_container_view_) + .SetOrientation(views::BoxLayout::Orientation::kHorizontal) + .SetBetweenChildSpacing(kActionButtonSpacing) + .SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kCenter) + .SetCrossAxisAlignment( + views::BoxLayout::CrossAxisAlignment::kStretch) + .Build()); + + action_container_widget_->Show(); + } + + UpdateActionContainerWidgetBounds(); +} + +void CaptureModeSession::UpdateActionContainerWidgetBounds() { + DCHECK(action_container_widget_); + + const gfx::Rect bounds = CalculateActionContainerWidgetBounds(); + if (bounds != action_container_widget_->GetWindowBoundsInScreen()) { + action_container_widget_->SetBounds(bounds); + } +} + +gfx::Rect CaptureModeSession::CalculateActionContainerWidgetBounds() const { + DCHECK(action_container_widget_); + + const gfx::Size preferred_size = action_container_view_->GetPreferredSize(); + const gfx::Rect capture_bar_bounds = + action_container_widget_->GetNativeWindow()->bounds(); + + const gfx::Rect capture_region = controller_->user_capture_region(); + gfx::Rect bounds = CalculateRegionEdgeBounds( + preferred_size, capture_bar_bounds, capture_region, current_root_); + + // User capture bounds are in root window coordinates so convert them here. + wm::ConvertRectToScreen(current_root_, &bounds); + return bounds; +} + +void CaptureModeSession::RemoveAllActionButtons() { + // Remove all children from the action button container, if the widget exists. + if (action_container_widget_) { + CHECK(action_container_view_); + action_container_view_->RemoveAllChildViews(); + } +} + void CaptureModeSession::InitInternal() { layer()->set_delegate(this); auto* parent = GetParentContainer(current_root_);
diff --git a/ash/capture_mode/capture_mode_session.h b/ash/capture_mode/capture_mode_session.h index 6e42a3b1..253c53f 100644 --- a/ash/capture_mode/capture_mode_session.h +++ b/ash/capture_mode/capture_mode_session.h
@@ -179,6 +179,9 @@ bool root_window_will_shutdown) override; std::set<aura::Window*> GetWindowsToIgnoreFromWidgets() override; void ShowSearchResultsPanel(const gfx::ImageSkia& image) override; + void AddActionButton(views::Button::PressedCallback callback, + std::u16string text, + const gfx::VectorIcon* icon) override; // ui::LayerDelegate: void OnPaintLayer(const ui::PaintContext& context) override; @@ -329,17 +332,6 @@ // child is visible. bool ShouldCaptureLabelHandleEvent(aura::Window* event_target); - // Creates the the action container widget if it wasn't previously created, - // and updates the widget's bounds. - void UpdateActionContainerWidget(); - - // Updates the action container widget's bounds. - void UpdateActionContainerWidgetBounds(); - - // Calculates the targeted action container widget bounds in screen - // coordinates. - gfx::Rect CalculateActionContainerWidgetBounds() const; - // Updates |root_window_dimmers_| to dim the correct root windows. void UpdateRootWindowDimmers(); @@ -401,6 +393,21 @@ // capturable window at `screen_point`. Returns false otherwise. bool IsPointOverSelectedWindow(const gfx::Point& screen_point) const; + // Creates the the action container widget if it wasn't previously created, + // and updates the widget's bounds. + void UpdateActionContainerWidget(); + + // Updates the action container widget's bounds. + void UpdateActionContainerWidgetBounds(); + + // Calculates the targeted action container widget bounds in screen + // coordinates. + gfx::Rect CalculateActionContainerWidgetBounds() const; + + // Removes any existing action buttons from `action_container_view_` if the + // `action_container_widget_` exists, + void RemoveAllActionButtons(); + // BaseCaptureModeSession: void InitInternal() override; void ShutdownInternal() override;
diff --git a/ash/capture_mode/capture_mode_session_test_api.cc b/ash/capture_mode/capture_mode_session_test_api.cc index 50a2363..11231a5 100644 --- a/ash/capture_mode/capture_mode_session_test_api.cc +++ b/ash/capture_mode/capture_mode_session_test_api.cc
@@ -8,6 +8,9 @@ #include "ash/capture_mode/capture_mode_session.h" #include "ash/capture_mode/capture_mode_types.h" #include "ash/capture_mode/recording_type_menu_view.h" +#include "ash/style/pill_button.h" +#include "ui/views/layout/box_layout_view.h" +#include "ui/views/view_utils.h" namespace ash { @@ -118,4 +121,20 @@ return session_->GetSelectedWindowTargetBounds(); } +std::vector<PillButton*> CaptureModeSessionTestApi::GetActionButtons() const { + std::vector<PillButton*> action_buttons; + + // The action container widget, and thus the container view, may not have been + // created yet when this function is called. In this case, return an empty + // vector. + if (session_->action_container_widget_) { + CHECK(session_->action_container_view_); + for (views::View* button : session_->action_container_view_->children()) { + action_buttons.emplace_back(views::AsViewClass<PillButton>(button)); + } + } + + return action_buttons; +} + } // namespace ash
diff --git a/ash/capture_mode/capture_mode_session_test_api.h b/ash/capture_mode/capture_mode_session_test_api.h index cf563cd..e382440 100644 --- a/ash/capture_mode/capture_mode_session_test_api.h +++ b/ash/capture_mode/capture_mode_session_test_api.h
@@ -19,6 +19,7 @@ class CaptureModeBarView; class CaptureModeSettingsView; class MagnifierGlass; +class PillButton; class RecordingTypeMenuView; class UserNudgeController; @@ -77,6 +78,10 @@ gfx::Rect GetSelectedWindowTargetBounds(); + // A vector of the current action buttons for a Sunfish session. Will return + // an empty vector if there are no buttons or there is no selected region. + std::vector<PillButton*> GetActionButtons() const; + private: const raw_ptr<CaptureModeSession, DanglingUntriaged> session_; };
diff --git a/ash/capture_mode/capture_mode_util.cc b/ash/capture_mode/capture_mode_util.cc index 19c20ee..3dd5a40 100644 --- a/ash/capture_mode/capture_mode_util.cc +++ b/ash/capture_mode/capture_mode_util.cc
@@ -585,4 +585,13 @@ return result; } +void AddActionButton(views::Button::PressedCallback callback, + std::u16string text, + const gfx::VectorIcon* icon) { + if (auto* controller = CaptureModeController::Get(); controller->IsActive()) { + controller->capture_mode_session()->AddActionButton(std::move(callback), + text, icon); + } +} + } // namespace ash::capture_mode_util
diff --git a/ash/capture_mode/capture_mode_util.h b/ash/capture_mode/capture_mode_util.h index 12657bc..f8d205b1 100644 --- a/ash/capture_mode/capture_mode_util.h +++ b/ash/capture_mode/capture_mode_util.h
@@ -14,6 +14,7 @@ #include "ui/gfx/animation/tween.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/size.h" +#include "ui/views/controls/button/button.h" #include "ui/views/highlight_border.h" namespace aura { @@ -236,6 +237,13 @@ const gfx::Rect& partial_region_bounds, aura::Window* root_window); +// TODO(http://b/368674223): Add some type of ordering mechanism to the API. +// Adds a new action button to a sunfish capture session if the session is +// active. +ASH_EXPORT void AddActionButton(views::Button::PressedCallback callback, + std::u16string text, + const gfx::VectorIcon* icon); + } // namespace capture_mode_util } // namespace ash
diff --git a/ash/capture_mode/null_capture_mode_session.cc b/ash/capture_mode/null_capture_mode_session.cc index a28b735f..cebc847 100644 --- a/ash/capture_mode/null_capture_mode_session.cc +++ b/ash/capture_mode/null_capture_mode_session.cc
@@ -116,6 +116,11 @@ void NullCaptureModeSession::ShowSearchResultsPanel( const gfx::ImageSkia& image) {} +void NullCaptureModeSession::AddActionButton( + views::Button::PressedCallback callback, + std::u16string text, + const gfx::VectorIcon* icon) {} + void NullCaptureModeSession::InitInternal() { layer()->SetName("NullCaptureModeSession"); }
diff --git a/ash/capture_mode/null_capture_mode_session.h b/ash/capture_mode/null_capture_mode_session.h index de1e67b..42b4120 100644 --- a/ash/capture_mode/null_capture_mode_session.h +++ b/ash/capture_mode/null_capture_mode_session.h
@@ -49,6 +49,9 @@ bool root_window_will_shutdown) override; std::set<aura::Window*> GetWindowsToIgnoreFromWidgets() override; void ShowSearchResultsPanel(const gfx::ImageSkia& image) override; + void AddActionButton(views::Button::PressedCallback callback, + std::u16string text, + const gfx::VectorIcon* icon) override; private: // CaptureModeSession:
diff --git a/ash/capture_mode/sunfish_unittest.cc b/ash/capture_mode/sunfish_unittest.cc index 105217a9e..66b0c63 100644 --- a/ash/capture_mode/sunfish_unittest.cc +++ b/ash/capture_mode/sunfish_unittest.cc
@@ -10,16 +10,20 @@ #include "ash/capture_mode/capture_mode_session.h" #include "ash/capture_mode/capture_mode_session_test_api.h" #include "ash/capture_mode/capture_mode_test_util.h" +#include "ash/capture_mode/capture_mode_util.h" #include "ash/capture_mode/search_results_panel.h" #include "ash/capture_mode/sunfish_capture_bar_view.h" #include "ash/capture_mode/test_capture_mode_delegate.h" #include "ash/constants/ash_features.h" #include "ash/constants/ash_switches.h" #include "ash/public/cpp/capture_mode/capture_mode_test_api.h" +#include "ash/resources/vector_icons/vector_icons.h" #include "ash/scanner/scanner_controller.h" #include "ash/shell.h" #include "ash/style/icon_button.h" +#include "ash/style/pill_button.h" #include "ash/test/ash_test_base.h" +#include "ash/test/ash_test_util.h" #include "ash/test/test_ash_web_view_factory.h" #include "base/auto_reset.h" #include "base/test/bind.h" @@ -108,7 +112,7 @@ // Immediately upon region selection, `PerformImageSearch()` and // `OnCaptureImageAttempted()` will be called once. SelectCaptureModeRegion(GetEventGenerator(), gfx::Rect(100, 100, 600, 500), - /*release_mouse=*/true, /*proceed=*/true); + /*release_mouse=*/true, /*verify_region=*/true); ASSERT_FALSE(capture_button->GetVisible()); ASSERT_FALSE(capture_label->GetVisible()); auto* test_delegate = @@ -131,7 +135,7 @@ CaptureModeSessionTestApi test_api(session); SelectCaptureModeRegion(GetEventGenerator(), gfx::Rect(100, 100, 600, 500), - /*release_mouse=*/true, /*proceed=*/true); + /*release_mouse=*/true, /*verify_region=*/true); WaitForImageCapturedForSearch(); EXPECT_TRUE(session->search_results_panel_widget()); @@ -192,7 +196,7 @@ // Tests after selecting a region, the session is ended. auto* event_generator = GetEventGenerator(); SelectCaptureModeRegion(event_generator, gfx::Rect(100, 100, 600, 500), - /*release_mouse=*/true, /*proceed=*/false); + /*release_mouse=*/true, /*verify_region=*/false); EXPECT_FALSE(controller->IsActive()); test_delegate->set_is_allowed_by_dlp(true); } @@ -434,7 +438,7 @@ // Test we can select a region and show the search results panel. SelectCaptureModeRegion(GetEventGenerator(), gfx::Rect(100, 100, 600, 500), - /*release_mouse=*/true, /*proceed=*/true); + /*release_mouse=*/true, /*verify_region=*/true); WaitForImageCapturedForSearch(); EXPECT_TRUE(session->search_results_panel_widget()); @@ -467,6 +471,52 @@ VerifyActiveBehavior(BehaviorType::kSunfish); } +// Tests that while a sunfish session has a region selected, calling the API +// will successfully create a new action button. +TEST_F(SunfishTest, AddActionButton) { + auto* controller = CaptureModeController::Get(); + controller->StartSunfishSession(); + ASSERT_TRUE(controller->IsActive()); + auto* session = + static_cast<CaptureModeSession*>(controller->capture_mode_session()); + + CaptureModeSessionTestApi session_test_api( + controller->capture_mode_session()); + EXPECT_EQ(session_test_api.GetActionButtons().size(), 0u); + + // Attempt to add a new action button using the API. + capture_mode_util::AddActionButton(views::Button::PressedCallback(), + u"Do not show", &kCaptureModeImageIcon); + + // The region has not been selected yet, so attempting to add a button should + // do nothing. + EXPECT_EQ(session_test_api.GetActionButtons().size(), 0u); + + // Select a region on the far left of the screen so we have space for the + // button between it and the search results panel. + SelectCaptureModeRegion(GetEventGenerator(), gfx::Rect(0, 0, 50, 200), + /*release_mouse=*/true, /*verify_region=*/true); + WaitForImageCapturedForSearch(); + EXPECT_TRUE(session->search_results_panel_widget()); + + // Create another action button that, when clicked, will change the value of a + // bool that can be verified later. + bool pressed = false; + capture_mode_util::AddActionButton( + base::BindLambdaForTesting([&]() { pressed = true; }), u"Test", + &kCaptureModeImageIcon); + + // There should only be one valid button in the session. + const std::vector<PillButton*> action_buttons = + session_test_api.GetActionButtons(); + EXPECT_EQ(action_buttons.size(), 1u); + + // Clicking the button should successfully run the callback, and change the + // value of the bool. + LeftClickOn(action_buttons[0]); + ASSERT_TRUE(pressed); +} + class SunfishWithScannerTest : public SunfishTest { public: SunfishWithScannerTest() = default;
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 0804a09..49763b4 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -381,10 +381,8 @@ // shortcut and feature tile. BASE_FEATURE(kCaptureModeEducation, "CaptureModeEducation", - base::FEATURE_ENABLED_BY_DEFAULT); + base::FEATURE_DISABLED_BY_DEFAULT); -// TODO(hewer): Remove the unused paths after at least one milestone after -// Capture Mode Education has been enabled by default. // Determines how we educate the user to the screen capture entry points. constexpr base::FeatureParam<CaptureModeEducationParam>::Option capture_mode_education_type_options[] = {
diff --git a/ash/webui/common/resources/BUILD.gn b/ash/webui/common/resources/BUILD.gn index 45342ff8..1461c2f0 100644 --- a/ash/webui/common/resources/BUILD.gn +++ b/ash/webui/common/resources/BUILD.gn
@@ -47,7 +47,6 @@ "network/network_property_list_mojo.js", "network/network_proxy_exclusions.js", "network/network_proxy_input.js", - "network/network_proxy.js", "network/network_select.js", "network/sim_lock_dialogs.js", "network/apn_detail_dialog.js", @@ -113,6 +112,7 @@ "bluetooth/bluetooth_pairing_ui.ts", "bluetooth/bluetooth_spinner_page.ts", "network/network_nameservers.ts", + "network/network_proxy.ts", "network/network_siminfo.ts", "network_health/network_diagnostics.ts", "network_health/network_health_container.ts", @@ -454,6 +454,7 @@ "network/network_config_element_behavior.js", "network/network_listener_behavior.js", "network/network_nameservers.html.js", + "network/network_proxy.html.js", "network/network_proxy_exclusions.html.js", "network/network_proxy_exclusions.js", "network/network_proxy_input.html.js", @@ -546,7 +547,6 @@ "network/network_list_types.d.ts", "network/network_password_input.d.ts", "network/network_property_list_mojo.d.ts", - "network/network_proxy.d.ts", "network/network_select.d.ts", "network/sim_lock_dialogs.d.ts",
diff --git a/ash/webui/common/resources/network/BUILD.gn b/ash/webui/common/resources/network/BUILD.gn index 7ffe5e5..64cd0322 100644 --- a/ash/webui/common/resources/network/BUILD.gn +++ b/ash/webui/common/resources/network/BUILD.gn
@@ -35,7 +35,6 @@ ":network_listener_behavior", ":network_password_input", ":network_property_list_mojo", - ":network_proxy", ":network_proxy_exclusions", ":network_proxy_input", ":network_select", @@ -312,24 +311,6 @@ ] } -js_library("network_proxy") { - deps = [ - ":cr_policy_network_behavior_mojo", - ":network_proxy_exclusions", - ":network_proxy_input", - ":onc_mojo", - "//ash/webui/common/resources:assert", - "//ash/webui/common/resources:i18n_behavior", - "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout-classes", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - ] - externs_list = [ - "//ash/webui/common/resources/cr_elements/cr_button/cr_button_externs.js", - "//ash/webui/common/resources/cr_elements/cr_input/cr_input_externs.js", - "//ash/webui/common/resources/cr_elements/cr_toggle/cr_toggle_externs.js", - ] -} - js_library("network_proxy_exclusions") { deps = [ "//ash/webui/common/resources:i18n_behavior",
diff --git a/ash/webui/common/resources/network/network_proxy.d.ts b/ash/webui/common/resources/network/network_proxy.d.ts deleted file mode 100644 index c567313..0000000 --- a/ash/webui/common/resources/network/network_proxy.d.ts +++ /dev/null
@@ -1,10 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import {LegacyElementMixin} from '//resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js'; -interface NetworkProxyElement extends LegacyElementMixin, HTMLElement { - editable: boolean; - reset(): void; -} -export {NetworkProxyElement};
diff --git a/ash/webui/common/resources/network/network_proxy.html b/ash/webui/common/resources/network/network_proxy.html index 10f636c0..121a8ed 100644 --- a/ash/webui/common/resources/network/network_proxy.html +++ b/ash/webui/common/resources/network/network_proxy.html
@@ -40,7 +40,7 @@ hidden$="[[!matches_(proxy_.type.activeValue, 'PAC')]]"> <cr-input id="pacInput" class="flex" label="[[i18n('networkProxyAutoConfig')]]" - value="{{proxy_.pac.activeValue}}" on-change="onPACChange_" + value="{{proxy_.pac.activeValue}}" on-change="onPacChange_" disabled="[[!isEditable_('pac', managedProperties, editable, useSharedProxies)]]"> </cr-input> @@ -120,7 +120,7 @@ aria-label="[[i18n('networkProxyExceptionInputA11yLabel')]]" on-keypress="onAddProxyExclusionKeypress_"> <cr-button id="proxyExclusionButton" - on-click="onAddProxyExclusionTap_" + on-click="onAddProxyExclusionClicked_" slot="suffix" disabled="[[shouldProxyExclusionButtonBeDisabled_( proxyExclusionInputValue_)]]"> @@ -131,7 +131,7 @@ </div> <cr-button id="saveManualProxy" - on-click="onSaveProxyTap_" class="action-button" + on-click="onSaveProxyClicked_" class="action-button" disabled="[[!isSaveManualProxyEnabled_(managedProperties, proxyIsUserModified_, proxy_.*)]]"> [[i18n('save')]]
diff --git a/ash/webui/common/resources/network/network_proxy.js b/ash/webui/common/resources/network/network_proxy.ts similarity index 66% rename from ash/webui/common/resources/network/network_proxy.js rename to ash/webui/common/resources/network/network_proxy.ts index b37a9a7f..432f8e70 100644 --- a/ash/webui/common/resources/network/network_proxy.js +++ b/ash/webui/common/resources/network/network_proxy.ts
@@ -17,30 +17,35 @@ import './network_proxy_input.js'; import './network_shared.css.js'; -import {assert} from '//resources/ash/common/assert.js'; -import {I18nBehavior, I18nBehaviorInterface} from '//resources/ash/common/i18n_behavior.js'; -import {ManagedManualProxySettings, ManagedProperties, ManagedProxyLocation, ManagedProxySettings, ManagedStringList, ProxyLocation, ProxySettings} from '//resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js'; -import {IPConfigType, OncSource, PolicySource} from '//resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js'; -import {mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {microTask} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {I18nMixin, I18nMixinInterface} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; +import {assert} from 'chrome://resources/js/assert.js'; +import {ManagedManualProxySettings, ManagedProperties, ManagedProxyLocation, ManagedProxySettings, ManagedStringList, ManualProxySettings, ProxyLocation, ProxySettings} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js'; +import {IPConfigType, OncSource, PolicySource} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js'; +import {microTask, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {CrPolicyNetworkBehaviorMojo, CrPolicyNetworkBehaviorMojoInterface} from './cr_policy_network_behavior_mojo.js'; import {getTemplate} from './network_proxy.html.js'; import {OncMojo} from './onc_mojo.js'; -/** - * @constructor - * @extends {PolymerElement} - * @implements {I18nBehaviorInterface} - * @implements {CrPolicyNetworkBehaviorMojoInterface} - */ -const NetworkProxyElementBase = - mixinBehaviors([CrPolicyNetworkBehaviorMojo, I18nBehavior], PolymerElement); +function createDefaultProxySettings(): ManagedProxySettings { + return { + type: OncMojo.createManagedString('Direct'), + manual: undefined, + excludeDomains: undefined, + pac: undefined, + }; +} -/** @polymer */ -class NetworkProxyElement extends NetworkProxyElementBase { +type Constructor<T> = new (...args: any[]) => T; + +const NetworkProxyElementBase = + mixinBehaviors([CrPolicyNetworkBehaviorMojo], I18nMixin(PolymerElement)) as + Constructor<PolymerElement&I18nMixinInterface& + CrPolicyNetworkBehaviorMojoInterface>; + +export class NetworkProxyElement extends NetworkProxyElementBase { static get is() { - return 'network-proxy'; + return 'network-proxy' as const; } static get template() { @@ -55,7 +60,6 @@ value: false, }, - /** @type {!ManagedProperties|undefined} */ managedProperties: { type: Object, observer: 'managedPropertiesChanged_', @@ -70,18 +74,16 @@ /** * UI visible / edited proxy configuration. - * @private {!ManagedProxySettings} */ proxy_: { type: Object, value() { - return this.createDefaultProxySettings_(); + return createDefaultProxySettings(); }, }, /** * The Web Proxy Auto Discovery URL extracted from managedProperties. - * @private */ wpad_: { type: String, @@ -90,7 +92,6 @@ /** * Whether or not to use the same manual proxy for all protocols. - * @private */ useSameProxy_: { type: Boolean, @@ -100,8 +101,6 @@ /** * Array of proxy configuration types. - * @private {!Array<string>} - * @const */ proxyTypes_: { type: Array, @@ -111,7 +110,6 @@ /** * The current value of the proxy exclusion input. - * @private */ proxyExclusionInputValue_: { type: String, @@ -121,7 +119,6 @@ /** * Set to true while modifying proxy values so that an update does not * override the edited values. - * @private {boolean} */ proxyIsUserModified_: { type: Boolean, @@ -131,23 +128,30 @@ }; } - /** @override */ - connectedCallback() { + editable: boolean; + managedProperties: ManagedProperties|undefined; + useSharedProxies: boolean; + private proxy_: ManagedProxySettings; + private wpad_: string; + private useSameProxy_: boolean; + private proxyTypes_: []; + private proxyExclusionInputValue_: string; + private proxyIsUserModified_: boolean; + + /** + * Saved ExcludeDomains properties so that switching to a non-Manual type + * does not loose any set exclusions while the UI is open. + */ + private savedManual_: ManagedManualProxySettings|undefined = undefined; + + /** + * Saved Manual properties so that switching to another type does not loose + * any set properties while the UI is open. + */ + private savedExcludeDomains_: ManagedStringList|undefined = undefined; + + override connectedCallback() { super.connectedCallback(); - - /** - * Saved ExcludeDomains properties so that switching to a non-Manual type - * does not loose any set exclusions while the UI is open. - * @private {!ManagedManualProxySettings|undefined} - */ - this.savedManual_ = undefined; - - /** - * Saved Manual properties so that switching to another type does not loose - * any set properties while the UI is open. - * @private {!ManagedStringList|undefined} - */ - this.savedExcludeDomains_ = undefined; this.reset(); } @@ -160,12 +164,9 @@ this.updateProxy_(); } - /** - * @param {!ManagedProperties|undefined} newValue - * @param {!ManagedProperties|undefined} oldValue - * @private - */ - managedPropertiesChanged_(newValue, oldValue) { + private managedPropertiesChanged_( + newValue: ManagedProperties|undefined, + oldValue: ManagedProperties|undefined) { if ((newValue && newValue.guid) !== (oldValue && oldValue.guid)) { // Clear saved manual properties and exclude domains if we're updating // to show a different network. @@ -181,15 +182,11 @@ this.updateProxy_(); } - /** - * @return {boolean} True if any input elements are currently being edited. - * @private - */ - isInputEditInProgress_() { + private isInputEditInProgress_(): boolean { if (!this.editable) { return false; } - const activeElement = this.shadowRoot.activeElement; + const activeElement = this.shadowRoot!.activeElement; if (!activeElement) { return false; } @@ -219,23 +216,14 @@ return this.isEditable_(property); } - /** - * @param {?ManagedProxyLocation|undefined} a - * @param {?ManagedProxyLocation|undefined} b - * @return {boolean} - * @private - */ - proxyMatches_(a, b) { + private proxyMatches_( + a: ManagedProxyLocation|undefined|null, + b: ManagedProxyLocation|undefined|null): boolean { return !!a && !!b && a.host.activeValue === b.host.activeValue && a.port.activeValue === b.port.activeValue; } - /** - * @param {number} port - * @return {!ManagedProxyLocation} - * @private - */ - createDefaultProxyLocation_(port) { + private createDefaultProxyLocation_(port: number): ManagedProxyLocation { return { host: OncMojo.createManagedString(''), port: OncMojo.createManagedInt(port), @@ -244,20 +232,19 @@ /** * Returns a copy of |inputProxy| with all required properties set correctly. - * @param {!ManagedProxySettings} inputProxy - * @return {!ManagedProxySettings} - * @private */ - validateProxy_(inputProxy) { - const proxy = - /** @type {!ManagedProxySettings} */ (Object.assign({}, inputProxy)); + private validateProxy_(inputProxy: ManagedProxySettings): + ManagedProxySettings { + const proxy = {...inputProxy}; const type = proxy.type.activeValue; if (type === 'PAC') { if (!proxy.pac) { proxy.pac = OncMojo.createManagedString(''); } } else if (type === 'Manual') { - proxy.manual = proxy.manual || this.savedManual_ || {}; + proxy.manual = + proxy.manual || this.savedManual_ || new ManagedManualProxySettings(); + assert(proxy.manual); if (!proxy.manual.httpProxy) { proxy.manual.httpProxy = this.createDefaultProxyLocation_(80); } @@ -271,13 +258,13 @@ proxy.excludeDomains || this.savedExcludeDomains_ || { activeValue: [], policySource: PolicySource.kNone, + policyValue: undefined, }; } return proxy; } - /** @private */ - updateProxy_() { + private updateProxy_(): void { if (!this.managedProperties) { return; } @@ -288,11 +275,11 @@ // settings and use the default value. if (this.isShared_() && proxySettings && !this.isControlled(proxySettings.type) && !this.useSharedProxies) { - proxySettings = null; // Ignore proxy settings. + proxySettings = undefined; // Ignore proxy settings. } const proxy = proxySettings ? this.validateProxy_(proxySettings) : - this.createDefaultProxySettings_(); + createDefaultProxySettings(); if (proxy.type.activeValue === 'WPAD') { // Set the Web Proxy Auto Discovery URL for display purposes. @@ -308,11 +295,7 @@ microTask.run(() => this.setProxy_(proxy)); } - /** - * @param {!ManagedProxySettings} proxy - * @private - */ - setProxy_(proxy) { + private setProxy_(proxy: ManagedProxySettings): void { this.proxy_ = proxy; if (proxy.manual) { const manual = proxy.manual; @@ -322,8 +305,8 @@ // If all four proxies match, enable the 'use same proxy' toggle. this.useSameProxy_ = true; } else if ( - !manual.secureHttpProxy.host.activeValue && - !manual.socks.host.activeValue) { + !manual.secureHttpProxy?.host?.activeValue && + !manual.socks?.host?.activeValue) { // Otherwise if no proxies other than http have a host value, also // enable the 'use same proxy' toggle. this.useSameProxy_ = true; @@ -332,28 +315,12 @@ this.proxyIsUserModified_ = false; } - /** @private */ - useSameProxyChanged_() { + private useSameProxyChanged_(): void { this.proxyIsUserModified_ = true; } - /** - * @return {!ManagedProxySettings} - * @private - */ - createDefaultProxySettings_() { - return { - type: OncMojo.createManagedString('Direct'), - }; - } - - /** - * @param {?ManagedProxyLocation|undefined} - * location - * @return {!ProxyLocation|undefined} - * @private - */ - getProxyLocation_(location) { + private getProxyLocation_(location: ManagedProxyLocation|undefined| + null): ProxyLocation|undefined { if (!location) { return undefined; } @@ -365,43 +332,38 @@ /** * Called when the proxy changes in the UI. - * @private */ - sendProxyChange_() { + private sendProxyChange_(): void { const proxyType = OncMojo.getActiveString(this.proxy_.type); if (!proxyType || (proxyType === 'PAC' && !this.proxy_.pac)) { return; } - const proxy = /** @type {!ProxySettings} */ ({ - type: proxyType, - excludeDomains: OncMojo.getActiveValue(this.proxy_.excludeDomains), - }); + const proxy = new ProxySettings(); + proxy.type = proxyType; + proxy.excludeDomains = + OncMojo.getActiveValue(this.proxy_.excludeDomains) as string[] | + undefined; if (proxyType === 'Manual') { - let manual = {}; + let manual = new ManualProxySettings(); if (this.proxy_.manual) { - this.savedManual_ = - /** @type{!ManagedManualProxySettings}*/ ( - Object.assign({}, this.proxy_.manual)); + this.savedManual_ = {...this.proxy_.manual}; manual = { httpProxy: this.getProxyLocation_(this.proxy_.manual.httpProxy), secureHttpProxy: this.getProxyLocation_(this.proxy_.manual.secureHttpProxy), + ftpProxy: undefined, socks: this.getProxyLocation_(this.proxy_.manual.socks), }; } if (this.proxy_.excludeDomains) { - this.savedExcludeDomains_ = - /** @type{!ManagedStringList}*/ ( - Object.assign({}, this.proxy_.excludeDomains)); + this.savedExcludeDomains_ = {...this.proxy_.excludeDomains}; } const defaultProxy = manual.httpProxy || {host: '', port: 80}; if (this.useSameProxy_) { - manual.secureHttpProxy = - /** @type {!ProxyLocation} */ (Object.assign({}, defaultProxy)); - manual.socks = - /** @type {!ProxyLocation} */ (Object.assign({}, defaultProxy)); + manual.secureHttpProxy = {...defaultProxy}; + manual.socks = {...defaultProxy}; } else { // Remove properties with empty hosts to unset them. if (manual.httpProxy && !manual.httpProxy.host) { @@ -428,14 +390,12 @@ /** * Event triggered when the selected proxy type changes. - * @param {!Event} event - * @private */ - onTypeChange_(event) { + private onTypeChange_(event: Event): void { if (!this.proxy_ || !this.proxy_.type) { return; } - const target = /** @type {!HTMLSelectElement} */ (event.target); + const target = event.target as HTMLSelectElement; const type = target.value; this.proxy_.type.activeValue = type; this.set('proxy_', this.validateProxy_(this.proxy_)); @@ -448,7 +408,7 @@ proxyTypeChangeIsReady = true; break; case 'PAC': - elementToFocus = this.shadowRoot.querySelector('#pacInput'); + elementToFocus = this.shadowRoot!.querySelector('#pacInput'); // If a PAC is already set, send the type change now, otherwise wait // until the user provides a PAC value. proxyTypeChangeIsReady = !!OncMojo.getActiveString(this.proxy_.pac); @@ -458,7 +418,7 @@ // until the 'send' button is clicked. proxyTypeChangeIsReady = false; elementToFocus = - this.shadowRoot.querySelector('#manualProxy network-proxy-input'); + this.shadowRoot!.querySelector('#manualProxy network-proxy-input'); break; } @@ -476,18 +436,15 @@ } } - /** @private */ - onPACChange_() { + private onPacChange_(): void { this.sendProxyChange_(); } - /** @private */ - onProxyInputChange_() { + private onProxyInputChange_(): void { this.proxyIsUserModified_ = true; } - /** @private */ - onAddProxyExclusionTap_() { + private onAddProxyExclusionClicked_(): void { assert(this.proxyExclusionInputValue_); this.push( 'proxy_.excludeDomains.activeValue', this.proxyExclusionInputValue_); @@ -496,47 +453,31 @@ this.proxyIsUserModified_ = true; } - /** - * @param {!Event} event - * @private - */ - onAddProxyExclusionKeypress_(event) { + private onAddProxyExclusionKeypress_(event: KeyboardEvent): void { if (event.key !== 'Enter') { return; } event.stopPropagation(); - this.onAddProxyExclusionTap_(); + this.onAddProxyExclusionClicked_(); } - /** - * @param {string} proxyExclusionInputValue - * @return {boolean} - * @private - */ - shouldProxyExclusionButtonBeDisabled_(proxyExclusionInputValue) { + private shouldProxyExclusionButtonBeDisabled_(proxyExclusionInputValue: + string): boolean { return !proxyExclusionInputValue; } /** * Event triggered when the proxy exclusion list changes. - * @param {!Event} event The remove proxy exclusions change event. - * @private */ - onProxyExclusionsChange_(event) { + private onProxyExclusionsChange_(): void { this.proxyIsUserModified_ = true; } - /** @private */ - onSaveProxyTap_() { + private onSaveProxyClicked_(): void { this.sendProxyChange_(); } - /** - * @param {string} proxyType The proxy type. - * @return {string} The description for |proxyType|. - * @private - */ - getProxyTypeDesc_(proxyType) { + private getProxyTypeDesc_(proxyType: string): string { if (proxyType === 'Manual') { return this.i18n('networkProxyTypeManual'); } @@ -549,38 +490,25 @@ return this.i18n('networkProxyTypeDirect'); } - /** - * @param {string} propertyName - * @return {boolean} Whether the named property setting is editable. - * @private - */ - isEditable_(propertyName) { + private isEditable_(propertyName: string): boolean { if (!this.editable || (this.isShared_() && !this.useSharedProxies)) { return false; } - const property = /** @type {!OncMojo.ManagedProperty|undefined} */ ( - this.get('proxySettings.' + propertyName, this.managedProperties)); + const property = + this.get('proxySettings.' + propertyName, this.managedProperties); if (!property) { return true; // Default to editable if property is not defined. } return this.isPropertyEditable_(property); } - /** - * @param {!OncMojo.ManagedProperty|undefined} property - * @return {boolean} Whether |property| is editable. - * @private - */ - isPropertyEditable_(property) { + private isPropertyEditable_(property: OncMojo.ManagedProperty| + undefined): boolean { return !!property && !this.isNetworkPolicyEnforced(property) && !this.isExtensionControlled(property); } - /** - * @return {boolean} - * @private - */ - isShared_() { + private isShared_(): boolean { if (!this.managedProperties) { return false; } @@ -588,11 +516,7 @@ return source === OncSource.kDevice || source === OncSource.kDevicePolicy; } - /** - * @return {boolean} - * @private - */ - isSaveManualProxyEnabled_() { + private isSaveManualProxyEnabled_(): boolean { if (!this.proxyIsUserModified_) { return false; } @@ -606,13 +530,7 @@ !!this.get('socks.host.activeValue', manual); } - /** - * @param {string} property The property to test - * @param {string} value The value to test against - * @return {boolean} True if property === value - * @private - */ - matches_(property, value) { + private matches_(property: string, value: string): boolean { return property === value; } }
diff --git a/ash/webui/demo_mode_app_ui/resources/demo_mode_metrics_service.js b/ash/webui/demo_mode_app_ui/resources/demo_mode_metrics_service.js index 914b5d2..5eee8a8 100644 --- a/ash/webui/demo_mode_app_ui/resources/demo_mode_metrics_service.js +++ b/ash/webui/demo_mode_app_ui/resources/demo_mode_metrics_service.js
@@ -81,6 +81,11 @@ // Enum shared between CB & CBX are: BATTERY, GOOGLE_APPS, NEARBY_SHARE, // MESSAGING, BUILT_IN_SECURITY,MS_365_APPS, SWITCHING, COMPARISON + + // New in 2024 Cycle 2 refresh + // CBX: + HELP_ME_READ: 'HelpMeRead', + LIVE_TRANSLATE: 'LiveTranslate', }; /**
diff --git a/base/allocator/partition_allocator/partition_alloc.gni b/base/allocator/partition_allocator/partition_alloc.gni index b78f042..423c081 100644 --- a/base/allocator/partition_allocator/partition_alloc.gni +++ b/base/allocator/partition_allocator/partition_alloc.gni
@@ -286,12 +286,21 @@ # PartitionAlloc at all. If `use_partition_alloc` is false, we jam all # related args to `false`. # +# We also disable PA-Everywhere and PA-based features in two types of +# toolchains: +# - Toolchains that disable PA-Everywhere explicitly. +# - The rust host build tools toochain, which builds DLLs to dlopen into the +# compiler for proc macros. We would want any allocations to use the same +# paths as the compiler. +# # Do not clear the following, as they can function outside of PartitionAlloc # - has_64_bit_pointers # - has_memory_tagging if (!use_partition_alloc || (defined(toolchain_allows_use_partition_alloc_as_malloc) && - !toolchain_allows_use_partition_alloc_as_malloc)) { + !toolchain_allows_use_partition_alloc_as_malloc) || + (defined(toolchain_for_rust_host_build_tools) && + toolchain_for_rust_host_build_tools)) { use_partition_alloc_as_malloc = false glue_core_pools = false enable_backup_ref_ptr_support = false
diff --git a/base/android/javatests/src/org/chromium/base/task/ChainedTasksTest.java b/base/android/javatests/src/org/chromium/base/task/ChainedTasksTest.java index e60442c..9c0b5df 100644 --- a/base/android/javatests/src/org/chromium/base/task/ChainedTasksTest.java +++ b/base/android/javatests/src/org/chromium/base/task/ChainedTasksTest.java
@@ -132,7 +132,7 @@ secondTaskFinished.notifyCalled(); waitForHighPriorityTask.waitForOnly(); } catch (TimeoutException e) { - Assert.fail(); + throw new RuntimeException(e); } }); tasks.add(TaskTraits.UI_DEFAULT, new TestRunnable(messages, "Third"));
diff --git a/base/android/junit/src/org/chromium/base/UnownedUserDataKeyTest.java b/base/android/junit/src/org/chromium/base/UnownedUserDataKeyTest.java index 69431443..66ad3c1 100644 --- a/base/android/junit/src/org/chromium/base/UnownedUserDataKeyTest.java +++ b/base/android/junit/src/org/chromium/base/UnownedUserDataKeyTest.java
@@ -124,6 +124,7 @@ mHost2 = null; } + @SuppressWarnings({"SelfAssertion", "JUnitIncompatibleType"}) @Test public void testKeyEquality() { assertEquals(Foo.KEY, Foo.KEY);
diff --git a/base/hash/sha1_boringssl.cc b/base/hash/sha1_boringssl.cc index 957ee47..90eeac7 100644 --- a/base/hash/sha1_boringssl.cc +++ b/base/hash/sha1_boringssl.cc
@@ -36,7 +36,7 @@ SHA1_Init(&context); } -void SHA1Update(const std::string_view data, SHA1Context& context) { +void SHA1Update(std::string_view data, SHA1Context& context) { SHA1_Update(&context, data.data(), data.size()); }
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc index 633a4875..99cf980 100644 --- a/base/test/launcher/test_launcher.cc +++ b/base/test/launcher/test_launcher.cc
@@ -962,7 +962,7 @@ // Truncates a snippet in the middle to the given byte limit. byte_limit should // be at least 30. -std::string TruncateSnippet(const std::string_view snippet, size_t byte_limit) { +std::string TruncateSnippet(std::string_view snippet, size_t byte_limit) { if (snippet.length() <= byte_limit) { return std::string(snippet); } @@ -2385,7 +2385,7 @@ return snippet; } -std::string TruncateSnippetFocused(const std::string_view snippet, +std::string TruncateSnippetFocused(std::string_view snippet, size_t byte_limit) { // Find the start of anything that looks like a fatal log message. // We want to preferentially preserve these from truncation as we
diff --git a/base/test/launcher/test_launcher.h b/base/test/launcher/test_launcher.h index 3d71a6f..ffae4e7 100644 --- a/base/test/launcher/test_launcher.h +++ b/base/test/launcher/test_launcher.h
@@ -393,8 +393,7 @@ // Truncates a snippet to approximately the allowed length, while trying to // retain fatal messages. Exposed for testing only. -std::string TruncateSnippetFocused(const std::string_view snippet, - size_t byte_limit); +std::string TruncateSnippetFocused(std::string_view snippet, size_t byte_limit); } // namespace base
diff --git a/base/test/scoped_feature_list_unittest.cc b/base/test/scoped_feature_list_unittest.cc index b98223b..60fe222 100644 --- a/base/test/scoped_feature_list_unittest.cc +++ b/base/test/scoped_feature_list_unittest.cc
@@ -39,7 +39,7 @@ EXPECT_EQ(disabled_features, actual_disabled_features); } -std::string GetActiveFieldTrialGroupName(const std::string trial_name) { +std::string GetActiveFieldTrialGroupName(const std::string& trial_name) { FieldTrial::ActiveGroups groups; FieldTrialList::GetActiveFieldTrialGroups(&groups); for (const auto& group : groups) {
diff --git a/base/test/test_proto_loader.cc b/base/test/test_proto_loader.cc index 8ee91dfd..01acd65a 100644 --- a/base/test/test_proto_loader.cc +++ b/base/test/test_proto_loader.cc
@@ -63,7 +63,7 @@ TestProtoSetLoader::~TestProtoSetLoader() = default; std::string TestProtoSetLoader::ParseFromText( - const std::string_view type_name, + std::string_view type_name, const std::string& proto_text) const { // Create a message of the given type, parse, and return. std::unique_ptr<google::protobuf::Message> message = @@ -74,7 +74,7 @@ } std::string TestProtoSetLoader::PrintToText( - const std::string_view type_name, + std::string_view type_name, const std::string& serialized_message) const { // Create a message of the given type, read the serialized message, and // print to text format.
diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc index da4cd52a2..6b9f562 100644 --- a/base/trace_event/memory_dump_manager_unittest.cc +++ b/base/trace_event/memory_dump_manager_unittest.cc
@@ -241,7 +241,7 @@ mdm_->SetupForTracing(TraceConfig::MemoryDumpConfig()); } - void EnableForTracingWithTraceConfig(const std::string trace_config_string) { + void EnableForTracingWithTraceConfig(const std::string& trace_config_string) { TraceConfig trace_config(trace_config_string); mdm_->SetupForTracing(trace_config.memory_dump_config()); }
diff --git a/third_party/crubit/BUILD.gn b/build/rust/crubit/BUILD.gn similarity index 90% rename from third_party/crubit/BUILD.gn rename to build/rust/crubit/BUILD.gn index a14822b..2bc6eb0 100644 --- a/third_party/crubit/BUILD.gn +++ b/build/rust/crubit/BUILD.gn
@@ -2,11 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/rust.gni") import("//build/rust/rust_macro.gni") import("//build/rust/rust_static_library.gni") # Common constants. -_support_dir = "src/rs_bindings_from_cc/support" +_support_dir = "{rust_sysroot}/lib/crubit" # Dependencies of ..._rs_api.rs files generated by Crubit's # `bin/rs_bindings_from_cc` tool. See also `deps_for_generated_rs_file` in @@ -31,6 +32,8 @@ ] } +# TODO: crbug.com/40226863 - Crubit should publish a Cargo.toml for these +# crates, then we can generate rules for them dynamically with gnrt. rust_static_library("ctor") { crate_root = "${_support_dir}/ctor.rs" sources = [ "${_support_dir}/ctor.rs" ]
diff --git a/build/rust/rustc_wrapper.py b/build/rust/rustc_wrapper.py index b8e490d..8f2096dfe 100755 --- a/build/rust/rustc_wrapper.py +++ b/build/rust/rustc_wrapper.py
@@ -177,6 +177,7 @@ # Work around for "-l<foo>.lib", where ".lib" suffix is undesirable. # Full fix will come from https://gn-review.googlesource.com/c/gn/+/12480 rsp_args = [remove_lib_suffix_from_l_args(arg) for arg in rsp_args] + rustc_args = [remove_lib_suffix_from_l_args(arg) for arg in rustc_args] out_rsp = str(args.rsp) + ".rsp" with open(out_rsp, 'w') as rspfile: # rustc needs the rsp file to be separated by newlines. Note that GN
diff --git a/cc/slim/frame_sink.cc b/cc/slim/frame_sink.cc index d780a9d..1287001 100644 --- a/cc/slim/frame_sink.cc +++ b/cc/slim/frame_sink.cc
@@ -6,9 +6,12 @@ #include <utility> +#include "base/feature_list.h" #include "base/memory/ptr_util.h" #include "cc/slim/delayed_scheduler.h" #include "cc/slim/frame_sink_impl.h" +#include "cc/slim/simple_scheduler.h" +#include "components/viz/common/features.h" namespace cc::slim { @@ -23,6 +26,15 @@ // Parameters below only used when wrapping cc. gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, base::PlatformThreadId io_thread_id) { +#if BUILDFLAG(IS_ANDROID) + if (base::FeatureList::IsEnabled(features::kAndroidBcivWithSimpleScheduler)) { + return base::WrapUnique<FrameSink>(new FrameSinkImpl( + std::move(task_runner), + std::move(compositor_frame_sink_associated_remote), + std::move(client_receiver), std::move(context_provider), io_thread_id, + std::make_unique<SimpleScheduler>())); + } +#endif return base::WrapUnique<FrameSink>( new FrameSinkImpl(std::move(task_runner), std::move(compositor_frame_sink_associated_remote),
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 33c1c45..f0559ab 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -293,7 +293,6 @@ java_group("delegate_public_impl_java") { deps = [ "//chrome/android/modules/readaloud/public:provider_public_java", - "//chrome/browser/lens:delegate_public_impl_java", "//chrome/browser/locale:delegate_public_impl_java", "//chrome/browser/supervised_user:parent_auth_delegate_impl_java", "//chrome/browser/touch_to_fill/password_manager/android/internal:resource_provider_public_impl_java", @@ -1067,7 +1066,6 @@ "//chrome/browser/incognito:java", "//chrome/browser/language/android:java", "//chrome/browser/language/android:junit", - "//chrome/browser/lens:delegate_public_impl_java", "//chrome/browser/lens:java", "//chrome/browser/loading_modal/android:junit", "//chrome/browser/locale:java", @@ -2592,6 +2590,7 @@ "//base:base_java", "//base:base_java_test_support", "//build/android:build_java", + "//chrome/browser/autofill/test:test_support_java", "//chrome/browser/download/android:java", "//chrome/browser/prefetch/android:java", "//chrome/browser/profiles/android:java", @@ -2624,6 +2623,7 @@ ":test_support_jni_headers", "//chrome/browser", "//chrome/browser:browser_process", + "//chrome/browser/autofill/test:test_support", "//chrome/browser/sync", "//chrome/browser/thumbnail:test_support", "//components/offline_pages/core/background:test_support",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java index 1549000..a2bc9ba 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
@@ -41,7 +41,6 @@ import org.chromium.chrome.browser.tab.TabSelectionType; import org.chromium.chrome.browser.tab_group_sync.TabGroupSyncFeatures; import org.chromium.chrome.browser.tab_group_sync.TabGroupSyncServiceFactory; -import org.chromium.chrome.browser.tab_group_sync.TabGroupSyncUtils; import org.chromium.chrome.browser.tab_ui.RecyclerViewPosition; import org.chromium.chrome.browser.tab_ui.TabUiThemeUtils; import org.chromium.chrome.browser.tabmodel.TabCreatorManager; @@ -69,7 +68,6 @@ import org.chromium.components.browser_ui.widget.gesture.BackPressHandler; import org.chromium.components.data_sharing.DataSharingService; import org.chromium.components.signin.identitymanager.IdentityManager; -import org.chromium.components.tab_group_sync.LocalTabGroupId; import org.chromium.components.tab_group_sync.TabGroupSyncService; import org.chromium.components.tab_groups.TabGroupColorId; import org.chromium.ui.KeyboardVisibilityDelegate; @@ -989,10 +987,7 @@ mModel.set(TabGridDialogProperties.IS_SHARE_SHEET_VISIBLE, true); String tabGroupDisplayName = mModel.get(TabGridDialogProperties.HEADER_TITLE); - TabGroupModelFilter filter = (TabGroupModelFilter) mCurrentTabModelFilterSupplier.get(); - Tab tab = filter.getTabModel().getTabById(mCurrentTabId); - LocalTabGroupId localTabGroupId = TabGroupSyncUtils.getLocalTabGroupId(tab); TabUiUtils.startShareTabGroupFlow( mActivity, @@ -1082,7 +1077,8 @@ String originalTitle = TabGroupTitleEditor.getDefaultTitle(mActivity, tabsCount); mModel.set( TabGridDialogProperties.COLLAPSE_BUTTON_CONTENT_DESCRIPTION, - mActivity.getResources() + mActivity + .getResources() .getQuantityString( R.plurals.accessibility_dialog_back_button, tabsCount,
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java index d79192e6..bdf5572 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
@@ -481,14 +481,14 @@ mRecyclerView.setRecyclerViewPosition(recyclerViewPosition); } - void initWithNative(@NonNull Profile profile) { + void initWithNative(@NonNull Profile originalProfile) { if (mIsInitialized) return; try (TraceEvent e = TraceEvent.scoped("TabListCoordinator.initWithNative")) { mIsInitialized = true; - assert !profile.isOffTheRecord() : "Expecting a non-incognito profile."; - mMediator.initWithNative(profile); + assert !originalProfile.isOffTheRecord() : "Expecting a non-incognito profile."; + mMediator.initWithNative(originalProfile); } }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java index aa6c4cc..38e61ae 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -363,7 +363,7 @@ private boolean mActionsOnAllRelatedTabs; private String mComponentName; private @TabActionState int mTabActionState; - private @Nullable Profile mProfile; + private @Nullable Profile mOriginalProfile; private TabListGroupMenuCoordinator mTabListGroupMenuCoordinator; private Size mDefaultGridCardSize; private ComponentCallbacks mComponentCallbacks; @@ -912,7 +912,6 @@ mActionConfirmationManager = actionConfirmationManager; mOnTabGroupCreation = onTabGroupCreation; - mProfile = mCurrentTabModelFilterSupplier.get().getTabModel().getProfile(); mTabModelObserver = new TabModelObserver() { @Override @@ -1282,10 +1281,10 @@ } } - public void initWithNative(Profile profile) { - assert !profile.isOffTheRecord() : "Expecting a non-incognito profile."; - mProfile = profile; - mTabListFaviconProvider.initWithNative(profile); + public void initWithNative(Profile originalProfile) { + assert !originalProfile.isOffTheRecord() : "Expecting a non-incognito profile."; + mOriginalProfile = originalProfile; + mTabListFaviconProvider.initWithNative(originalProfile); mOnTabModelFilterChanged.onResult( mCurrentTabModelFilterSupplier.addObserver(mOnTabModelFilterChanged)); @@ -1335,7 +1334,7 @@ // switcher. if (mMode == TabListMode.GRID && mTabActionState != TabActionState.SELECTABLE - && PriceTrackingFeatures.isPriceTrackingEnabled(profile)) { + && PriceTrackingFeatures.isPriceTrackingEnabled(originalProfile)) { mListObserver = new ListObserver<Void>() { @Override @@ -1552,10 +1551,11 @@ void hardCleanup() { assert !mShowingTabs; - if (mProfile != null - && PriceTrackingUtilities.isTrackPricesOnTabsEnabled(mProfile) - && (PriceTrackingFeatures.isPriceDropIphEnabled(mProfile) - || PriceTrackingFeatures.isPriceDropBadgeEnabled(mProfile))) { + if (!mCurrentTabModelFilterSupplier.get().isIncognitoBranded() + && mOriginalProfile != null + && PriceTrackingUtilities.isTrackPricesOnTabsEnabled(mOriginalProfile) + && (PriceTrackingFeatures.isPriceDropIphEnabled(mOriginalProfile) + || PriceTrackingFeatures.isPriceDropBadgeEnabled(mOriginalProfile))) { saveSeenPriceDrops(); } sViewedTabIds.clear(); @@ -1726,11 +1726,12 @@ void registerOnScrolledListener(RecyclerView recyclerView) { // For InstantStart, this can be called before native is initialized, so ensure the Profile // is available before proceeding. - if (mProfile == null) return; + if (mOriginalProfile == null) return; - if (PriceTrackingUtilities.isTrackPricesOnTabsEnabled(mProfile) - && (PriceTrackingFeatures.isPriceDropIphEnabled(mProfile) - || PriceTrackingFeatures.isPriceDropBadgeEnabled(mProfile))) { + if (!mCurrentTabModelFilterSupplier.get().isIncognitoBranded() + && PriceTrackingUtilities.isTrackPricesOnTabsEnabled(mOriginalProfile) + && (PriceTrackingFeatures.isPriceDropIphEnabled(mOriginalProfile) + || PriceTrackingFeatures.isPriceDropBadgeEnabled(mOriginalProfile))) { mRecyclerView = recyclerView; mOnScrollListener = new OnScrollListener() { @@ -1882,17 +1883,18 @@ private TabListMediator.TabActionListener getTabGroupOverflowMenuClickListener() { if (mTabListGroupMenuCoordinator == null) { - boolean isTabGroupSyncEnabled = TabGroupSyncFeatures.isTabGroupSyncEnabled(mProfile); - TabModel tabModel = mCurrentTabModelFilterSupplier.get().getTabModel(); - Profile profile = tabModel.getProfile().getOriginalProfile(); + boolean isTabGroupSyncEnabled = + !mCurrentTabModelFilterSupplier.get().isIncognitoBranded() + && TabGroupSyncFeatures.isTabGroupSyncEnabled(mOriginalProfile); IdentityManager identityManager = null; TabGroupSyncService tabGroupSyncService = null; DataSharingService dataSharingService = null; if (isTabGroupSyncEnabled && ChromeFeatureList.isEnabled(ChromeFeatureList.DATA_SHARING)) { - identityManager = IdentityServicesProvider.get().getIdentityManager(profile); - tabGroupSyncService = TabGroupSyncServiceFactory.getForProfile(profile); - dataSharingService = DataSharingServiceFactory.getForProfile(profile); + identityManager = + IdentityServicesProvider.get().getIdentityManager(mOriginalProfile); + tabGroupSyncService = TabGroupSyncServiceFactory.getForProfile(mOriginalProfile); + dataSharingService = DataSharingServiceFactory.getForProfile(mOriginalProfile); } mTabListGroupMenuCoordinator = new TabListGroupMenuCoordinator( @@ -2230,8 +2232,8 @@ private void setupPersistedTabDataFetcherForTab(Tab tab, int index) { PropertyModel model = mModel.get(index).model; if (mMode == TabListMode.GRID && !tab.isIncognito()) { - assert mProfile != null; - if (PriceTrackingUtilities.isTrackPricesOnTabsEnabled(mProfile) + assert mOriginalProfile != null; + if (PriceTrackingUtilities.isTrackPricesOnTabsEnabled(mOriginalProfile) && !isTabInTabGroup(tab)) { model.set( TabProperties.SHOPPING_PERSISTED_TAB_DATA_FETCHER, @@ -2386,8 +2388,9 @@ void updateLayout() { // Right now we need to update layout only if there is a price welcome message card in tab // switcher. - if (mProfile == null - || !PriceTrackingUtilities.isPriceWelcomeMessageCardEnabled(mProfile)) { + if (mOriginalProfile == null + || !PriceTrackingUtilities.isPriceWelcomeMessageCardEnabled(mOriginalProfile) + || mCurrentTabModelFilterSupplier.get().isIncognitoBranded()) { return; } assert mGridLayoutManager != null; @@ -2424,9 +2427,10 @@ @VisibleForTesting void recordPriceAnnotationsEnabledMetrics() { if (mMode != TabListMode.GRID + || mCurrentTabModelFilterSupplier.get().isIncognitoBranded() || !mActionsOnAllRelatedTabs - || mProfile == null - || !PriceTrackingFeatures.isPriceTrackingEligible(mProfile)) { + || mOriginalProfile == null + || !PriceTrackingFeatures.isPriceTrackingEligible(mOriginalProfile)) { return; } SharedPreferencesManager preferencesManager = ChromeSharedPreferences.getInstance(); @@ -2438,7 +2442,7 @@ >= PriceTrackingFeatures.getAnnotationsEnabledMetricsWindowDurationMilliSeconds()) { RecordHistogram.recordBooleanHistogram( "Commerce.PriceDrop.AnnotationsEnabled", - PriceTrackingUtilities.isTrackPricesOnTabsEnabled(mProfile)); + PriceTrackingUtilities.isTrackPricesOnTabsEnabled(mOriginalProfile)); preferencesManager.writeLong( ChromePreferenceKeys.PRICE_TRACKING_ANNOTATIONS_ENABLED_METRICS_TIMESTAMP, System.currentTimeMillis()); @@ -2768,7 +2772,9 @@ @VisibleForTesting void onMenuItemClicked(@IdRes int menuId, int tabId, @Nullable String collaborationId) { - boolean isSyncEnabled = TabGroupSyncFeatures.isTabGroupSyncEnabled(mProfile); + boolean isSyncEnabled = + !mCurrentTabModelFilterSupplier.get().isIncognitoBranded() + && TabGroupSyncFeatures.isTabGroupSyncEnabled(mOriginalProfile); if (menuId == R.id.close_tab || menuId == R.id.delete_tab) { boolean hideTabGroups = menuId == R.id.close_tab; if (hideTabGroups) { @@ -2949,8 +2955,7 @@ @Nullable TabGroupSyncService tabGroupSyncService = null; if (TabGroupSyncFeatures.isTabGroupSyncEnabled(tab.getProfile())) { - tabGroupSyncService = - TabGroupSyncServiceFactory.getForProfile(tab.getProfile().getOriginalProfile()); + tabGroupSyncService = TabGroupSyncServiceFactory.getForProfile(mOriginalProfile); } @Nullable String collaborationId =
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewBinder.java index 0d67b13..370a260 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewBinder.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewBinder.java
@@ -272,7 +272,7 @@ } private static void setTabGroupColorIcon(ViewGroup view, PropertyModel model) { - ImageView colorIconView = view.findViewById(R.id.icon); + ImageView colorIconView = view.findViewById(R.id.before_title_icon); if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { colorIconView.setVisibility(View.VISIBLE);
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewBinderTest.java index 005cd26..d45be3a 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewBinderTest.java
@@ -192,9 +192,9 @@ assertNull(mTabGridDialogView.getBindingToken()); String title = "1024 tabs"; - assertNotEquals(title, mTitleTextView.getText()); + assertNotEquals(title, mTitleTextView.getText().toString()); mModel.set(TabGridDialogProperties.HEADER_TITLE, title); - assertNotEquals(title, mTitleTextView.getText()); + assertNotEquals(title, mTitleTextView.getText().toString()); mModel.set(TabGridDialogProperties.BINDING_TOKEN, 4); assertEquals(mTabGridDialogView.getBindingToken().intValue(), 4); @@ -240,7 +240,7 @@ @UiThreadTest public void testSetHeaderTitle() { String title = "1024 tabs"; - assertNotEquals(title, mTitleTextView.getText()); + assertNotEquals(title, mTitleTextView.getText().toString()); mModel.set(TabGridDialogProperties.HEADER_TITLE, title);
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java index 1d02880..ac8d0c15 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java
@@ -1027,7 +1027,7 @@ final int colorId = TabGroupColorId.BLUE; final int colorLayer = 1; - ImageView colorIconView = mTabListView.findViewById(R.id.icon); + ImageView colorIconView = mTabListView.findViewById(R.id.before_title_icon); assertNull(colorIconView.getBackground()); mGridModel.set(TabProperties.TAB_GROUP_COLOR_ID, colorId); @@ -1059,7 +1059,7 @@ mGridModel.set(TabProperties.TAB_GROUP_COLOR_ID, colorId1); - ImageView colorIconView = mTabListView.findViewById(R.id.icon); + ImageView colorIconView = mTabListView.findViewById(R.id.before_title_icon); assertEquals(colorIconView.getVisibility(), View.VISIBLE); assertNotNull(colorIconView.getBackground());
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java index ddf89a8..8a6a654c 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -77,8 +77,9 @@ import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.mockito.stubbing.Answer; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @@ -201,7 +202,7 @@ @LooperMode(LooperMode.Mode.LEGACY) @DisableFeatures(ChromeFeatureList.DATA_SHARING) public class TabListMediatorUnitTest { - + @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public JniMocker mMocker = new JniMocker(); private static final String TAB1_TITLE = "Tab1"; @@ -362,7 +363,6 @@ @Before public void setUp() { - MockitoAnnotations.initMocks(this); mMocker.mock(UrlUtilitiesJni.TEST_HOOKS, mUrlUtilitiesJniMock); mMocker.mock( OptimizationGuideBridgeFactoryJni.TEST_HOOKS, @@ -655,7 +655,7 @@ } @Test - public void updatesFaviconFetcher_SingleTab_GTS() { + public void updatesFaviconFetcher_SingleTab_Gts() { mModel.get(0).model.set(TabProperties.FAVICON_FETCHER, null); assertNull(mModel.get(0).model.get(TabProperties.FAVICON_FETCHER)); @@ -676,7 +676,7 @@ @Test @DisableFeatures(ChromeFeatureList.TAB_GROUP_PARITY_ANDROID) - public void updatesFaviconFetcher_SingleTabGroup_GTS() { + public void updatesFaviconFetcher_SingleTabGroup_Gts() { mModel.get(0).model.set(TabProperties.FAVICON_FETCHER, null); assertNull(mModel.get(0).model.get(TabProperties.FAVICON_FETCHER)); @@ -691,7 +691,7 @@ } @Test - public void updatesFaviconFetcher_SingleTab_NonGTS() { + public void updatesFaviconFetcher_SingleTab_NonGts() { mModel.get(0).model.set(TabProperties.FAVICON_FETCHER, null); assertNull(mModel.get(0).model.get(TabProperties.FAVICON_FETCHER)); @@ -712,7 +712,7 @@ @Test @DisableFeatures(ChromeFeatureList.TAB_GROUP_PARITY_ANDROID) - public void updatesFaviconFetcher_TabGroup_GTS() { + public void updatesFaviconFetcher_TabGroup_Gts() { assertNotNull(mModel.get(0).model.get(TabProperties.FAVICON_FETCHER)); mModel.get(0).model.set(TabProperties.FAVICON_FETCHER, null); // Assert that tab1 is in a group. @@ -730,7 +730,7 @@ } @Test - public void updatesFaviconFetcher_TabGroup_ListGTS() { + public void updatesFaviconFetcher_TabGroup_ListGts() { setUpTabListMediator(TabListMediatorType.TAB_SWITCHER, TabListMode.LIST); assertNotNull(mModel.get(0).model.get(TabProperties.FAVICON_FETCHER)); @@ -748,7 +748,7 @@ } @Test - public void updatesFaviconFetcher_TabGroup_ListGTS_SingleTab() { + public void updatesFaviconFetcher_TabGroup_ListGts_SingleTab() { setUpTabListMediator(TabListMediatorType.TAB_SWITCHER, TabListMode.LIST); assertNotNull(mModel.get(0).model.get(TabProperties.FAVICON_FETCHER)); @@ -1208,7 +1208,7 @@ } @Test - public void tabAddition_GTS() { + public void tabAddition_Gts() { Tab newTab = prepareTab(TAB3_ID, TAB3_TITLE, TAB3_URL); doReturn(mTab1).when(mTabGroupModelFilter).getTabAt(0); doReturn(mTab2).when(mTabGroupModelFilter).getTabAt(1); @@ -1231,7 +1231,7 @@ } @Test - public void tabAddition_GTS_delayAdd() { + public void tabAddition_Gts_delayAdd() { mMediator.setComponentNameForTesting(TabSwitcherPaneCoordinator.COMPONENT_NAME); initAndAssertAllProperties(); @@ -1285,7 +1285,7 @@ } @Test - public void tabAddition_GTS_delayAdd_WithUnexpectedUpdate() { + public void tabAddition_Gts_delayAdd_WithUnexpectedUpdate() { mMediator.setComponentNameForTesting(TabSwitcherPaneCoordinator.COMPONENT_NAME); initAndAssertAllProperties(); @@ -1345,7 +1345,7 @@ } @Test - public void tabAddition_GTS_Skip() { + public void tabAddition_Gts_Skip() { // Add a new tab to the group with mTab2. Tab newTab = prepareTab(TAB3_ID, TAB3_TITLE, TAB3_URL); doReturn(mTab1).when(mTabGroupModelFilter).getTabAt(0); @@ -1368,7 +1368,7 @@ } @Test - public void tabAddition_GTS_Middle() { + public void tabAddition_Gts_Middle() { Tab newTab = prepareTab(TAB3_ID, TAB3_TITLE, TAB3_URL); doReturn(mTab1).when(mTabGroupModelFilter).getTabAt(0); doReturn(newTab).when(mTabGroupModelFilter).getTabAt(1); @@ -1758,7 +1758,7 @@ } @Test - public void tabMoveOutOfGroup_GTS_Moved_Tab_Selected() { + public void tabMoveOutOfGroup_Gts_Moved_Tab_Selected() { // Assume that two tabs are in the same group before ungroup. List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab2)); mMediator.resetWithListOfTabs(tabs, false); @@ -1787,7 +1787,7 @@ } @Test - public void tabMoveOutOfGroup_GTS_Origin_Tab_Selected() { + public void tabMoveOutOfGroup_Gts_Origin_Tab_Selected() { // Assume that two tabs are in the same group before ungroup. List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1)); mMediator.resetWithListOfTabs(tabs, false); @@ -1813,7 +1813,7 @@ } @Test - public void tabMoveOutOfGroup_GTS_LastTab() { + public void tabMoveOutOfGroup_Gts_LastTab() { // Assume that tab1 is a single tab group that became a single tab. List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1)); mMediator.resetWithListOfTabs(tabs, false); @@ -1835,7 +1835,7 @@ } @Test - public void tabMoveOutOfGroup_GTS_TabAdditionWithSameId() { + public void tabMoveOutOfGroup_Gts_TabAdditionWithSameId() { // Assume that two tabs are in the same group before ungroup. List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1)); mMediator.resetWithListOfTabs(tabs, false); @@ -2566,7 +2566,7 @@ } @Test - public void getLatestTitle_NotGTS() { + public void getLatestTitle_NotGts() { setUpTabListMediator(TabListMediatorType.TAB_GRID_DIALOG, TabListMode.GRID); // Mock that we have a stored title stored with reference to root ID of tab1. @@ -2585,7 +2585,7 @@ } @Test - public void getLatestTitle_SingleTabGroupSupported_GTS() { + public void getLatestTitle_SingleTabGroupSupported_Gts() { // Mock that we have a stored title stored with reference to root ID of tab1. mTabGroupModelFilter.setTabGroupTitle(mTab1.getRootId(), CUSTOMIZED_DIALOG_TITLE1); assertThat( @@ -2603,7 +2603,7 @@ } @Test - public void getLatestTitle_SingleTabGroupNotSupported_GTS() { + public void getLatestTitle_SingleTabGroupNotSupported_Gts() { // Mock that we have a stored title stored with reference to root ID of tab1. mTabGroupModelFilter.setTabGroupTitle(mTab1.getRootId(), CUSTOMIZED_DIALOG_TITLE1); assertThat( @@ -2621,7 +2621,7 @@ } @Test - public void getLatestTitle_Stored_GTS() { + public void getLatestTitle_Stored_Gts() { // Mock that we have a stored title stored with reference to root ID of tab1. mTabGroupModelFilter.setTabGroupTitle(mTab1.getRootId(), CUSTOMIZED_DIALOG_TITLE1); assertThat( @@ -2638,7 +2638,7 @@ } @Test - public void getLatestTitle_Default_GTS() { + public void getLatestTitle_Default_Gts() { // Mock that tab1 and tab2 are in the same group and group root id is TAB1_ID. List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2)); createTabGroup(tabs, TAB1_ID, TAB_GROUP_ID); @@ -2648,7 +2648,7 @@ } @Test - public void getLatestTitle_NoDefault_GTS() { + public void getLatestTitle_NoDefault_Gts() { // Mock that tab1 and tab2 are in the same group and group root id is TAB1_ID. List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2)); createTabGroup(tabs, TAB1_ID, TAB_GROUP_ID); @@ -2658,7 +2658,7 @@ @Test @DisableFeatures(ChromeFeatureList.TAB_GROUP_PARITY_ANDROID) - public void updateTabGroupTitle_GTS() { + public void updateTabGroupTitle_Gts() { setUpTabGroupCardDescriptionString(); String targetString = "Expand tab group with 2 tabs."; assertThat(mModel.get(POSITION1).model.get(TabProperties.TITLE), equalTo(TAB1_TITLE)); @@ -2682,7 +2682,7 @@ @Test @DisableFeatures(ChromeFeatureList.TAB_GROUP_PARITY_ANDROID) - public void updateTabGroupTitle_SingleTab_GTS() { + public void updateTabGroupTitle_SingleTab_Gts() { setUpTabGroupCardDescriptionString(); String targetString = "Expand tab group with 1 tab."; assertThat(mModel.get(POSITION1).model.get(TabProperties.TITLE), equalTo(TAB1_TITLE)); @@ -2821,7 +2821,7 @@ } @Test - public void testUrlUpdated_forSingleTab_GTS() { + public void testUrlUpdated_forSingleTab_Gts() { assertNotEquals(mNewDomain, mModel.get(POSITION1).model.get(TabProperties.URL_DOMAIN)); doReturn(mNewDomain) @@ -2836,7 +2836,7 @@ } @Test - public void testUrlUpdated_forGroup_GTS() { + public void testUrlUpdated_forGroup_Gts() { List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2)); createTabGroup(tabs, TAB1_ID, TAB_GROUP_ID); doReturn(POSITION1).when(mTabGroupModelFilter).indexOf(mTab1);
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java index 8835864..10aca33a 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java
@@ -550,8 +550,7 @@ mSigninManager.getIdentityManager().addObserver(this); mSectionHeaderModel.set(SectionHeaderListProperties.MENU_MODEL_LIST_KEY, mFeedMenuModel); - mSectionHeaderModel.set( - SectionHeaderListProperties.MENU_DELEGATE_KEY, this::onItemSelected); + mSectionHeaderModel.set(SectionHeaderListProperties.MENU_DELEGATE_KEY, this); setUpWebFeedTab();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index f2c63db..7e914be 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -2209,11 +2209,7 @@ }; mUndoBarPopupController = - new UndoBarController( - this, - mTabModelSelector, - this::getSnackbarManager, - dialogVisibilitySupplier); + new UndoBarController(this, mTabModelSelector, this, dialogVisibilitySupplier); if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { TabModelUtils.runOnTabStateInitialized(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillCreditCardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillCreditCardEditor.java index 89a389b..8b5fe2f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillCreditCardEditor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillCreditCardEditor.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.autofill.settings; -import android.os.Build; import android.os.Bundle; import android.text.TextUtils; import android.view.LayoutInflater; @@ -46,14 +45,6 @@ LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = super.onCreateView(inflater, container, savedInstanceState); - // Do not use autofill for the fields. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - getActivity() - .getWindow() - .getDecorView() - .setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS); - } - // Populate the billing address dropdown. ArrayAdapter<AutofillProfile> profilesAdapter = new ArrayAdapter<AutofillProfile>(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalIbanEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalIbanEditor.java index 87c478f..5d36f48 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalIbanEditor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalIbanEditor.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.autofill.settings; -import android.os.Build; import android.os.Bundle; import android.text.Editable; import android.view.LayoutInflater; @@ -60,14 +59,6 @@ LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = super.onCreateView(inflater, container, savedInstanceState); - // Do not use autofill for the fields. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - getActivity() - .getWindow() - .getDecorView() - .setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS); - } - PersonalDataManager personalDataManager = PersonalDataManagerFactory.getForProfile(getProfile()); mIban = personalDataManager.getIban(mGUID);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java index d03a16c..b1b7572 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -32,7 +32,6 @@ import androidx.core.view.ViewCompat; import androidx.core.view.WindowCompat; import androidx.core.view.WindowInsetsCompat; -import androidx.core.view.accessibility.AccessibilityEventCompat; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import androidx.customview.widget.ExploreByTouchHelper; @@ -1632,12 +1631,7 @@ @Override public void invalidateAccessibilityProvider() { - if (mNodeProvider != null) { - mNodeProvider.sendEventForVirtualView( - mNodeProvider.getAccessibilityFocusedVirtualViewId(), - AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); - mNodeProvider.invalidateRoot(); - } + if (mNodeProvider != null) mNodeProvider.invalidateRoot(); } // ChromeAccessibilityUtil.Observer
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java index 45a2635a..2e19bcc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java
@@ -280,7 +280,7 @@ @Override public void getVirtualViews(List<VirtualView> views) { - if (isCollapsed()) return; + if (isCollapsed() || mIsDying) return; super.getVirtualViews(views); if (mShowingCloseButton) mCloseButton.getVirtualViews(views); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabGroupContextMenuCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabGroupContextMenuCoordinator.java index 30e7ed70..9ee571a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabGroupContextMenuCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabGroupContextMenuCoordinator.java
@@ -31,7 +31,6 @@ import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.tab_group_sync.TabGroupSyncFeatures; import org.chromium.chrome.browser.tab_group_sync.TabGroupSyncServiceFactory; -import org.chromium.chrome.browser.tab_group_sync.TabGroupSyncUtils; import org.chromium.chrome.browser.tabmodel.TabCreator; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter; @@ -49,7 +48,6 @@ import org.chromium.components.data_sharing.DataSharingService; import org.chromium.components.data_sharing.DataSharingService.GroupDataOrFailureOutcome; import org.chromium.components.signin.identitymanager.IdentityManager; -import org.chromium.components.tab_group_sync.LocalTabGroupId; import org.chromium.components.tab_group_sync.TabGroupSyncService; import org.chromium.components.tab_groups.TabGroupColorId; import org.chromium.ui.KeyboardVisibilityDelegate; @@ -224,9 +222,6 @@ tabGroupModelFilter, tabCreator, tabId, TabLaunchType.FROM_TAB_GROUP_UI); recordUserAction("NewTabInGroup"); } else if (menuId == org.chromium.chrome.R.id.share_group) { - LocalTabGroupId localTabGroupId = - TabGroupSyncUtils.getLocalTabGroupId(tabGroupModelFilter, tabId); - // Get user assigned group title or the default title "N tabs" if no title is // assigned. String tabGroupDisplayName =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/AuthTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/AuthTabIntentDataProvider.java index b74b580..b045a0d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/AuthTabIntentDataProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/AuthTabIntentDataProvider.java
@@ -80,6 +80,8 @@ GURL redirectUrl = new GURL(UrlConstants.HTTPS_URL_PREFIX + host + path); mRedirectHost = redirectUrl.getHost(); mRedirectPath = redirectUrl.getPath(); + + logFeatureUsage(); } @Override @@ -166,4 +168,25 @@ public String getAuthRedirectScheme() { return mRedirectScheme; } + + /** + * Logs the usage of Auth Tab features to a large enum histogram in order to track usage by + * apps. + */ + private void logFeatureUsage() { + if (!CustomTabsFeatureUsage.isEnabled()) return; + CustomTabsFeatureUsage featureUsage = new CustomTabsFeatureUsage(); + + // Ordering: Log all the features ordered by enum, when they apply. + featureUsage.log(CustomTabsFeatureUsage.CustomTabsFeature.EXTRA_LAUNCH_AUTH_TAB); + if (mRedirectScheme != null) { + featureUsage.log(CustomTabsFeatureUsage.CustomTabsFeature.EXTRA_REDIRECT_SCHEME); + } + if (mRedirectHost != null) { + featureUsage.log(CustomTabsFeatureUsage.CustomTabsFeature.EXTRA_HTTPS_REDIRECT_HOST); + } + if (mRedirectPath != null) { + featureUsage.log(CustomTabsFeatureUsage.CustomTabsFeature.EXTRA_HTTPS_REDIRECT_PATH); + } + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsFeatureUsage.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsFeatureUsage.java index fbf1ae5..11e24b1f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsFeatureUsage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsFeatureUsage.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.customtabs; import androidx.annotation.IntDef; +import androidx.annotation.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -15,6 +16,9 @@ /** Records a histogram that tracks usage of all the CCT features of interest. */ public class CustomTabsFeatureUsage { + @VisibleForTesting + public static final String CUSTOM_TABS_FEATURE_USAGE_HISTOGRAM = "CustomTabs.FeatureUsage"; + // NOTE: This must be kept in sync with the definition |CustomTabsFeatureUsed| // in tools/metrics/histograms/enums.xml. @IntDef({ @@ -76,6 +80,10 @@ CustomTabsFeature.EXTRA_ENABLE_GOOGLE_BOTTOM_BAR, CustomTabsFeature.EXTRA_GOOGLE_BOTTOM_BAR_BUTTONS, CustomTabsFeature.EXTRA_NETWORK, + CustomTabsFeature.EXTRA_LAUNCH_AUTH_TAB, + CustomTabsFeature.EXTRA_REDIRECT_SCHEME, + CustomTabsFeature.EXTRA_HTTPS_REDIRECT_HOST, + CustomTabsFeature.EXTRA_HTTPS_REDIRECT_PATH, CustomTabsFeature.COUNT }) @Retention(RetentionPolicy.SOURCE) @@ -140,9 +148,13 @@ int EXTRA_ENABLE_GOOGLE_BOTTOM_BAR = 56; int EXTRA_GOOGLE_BOTTOM_BAR_BUTTONS = 57; int EXTRA_NETWORK = 58; + int EXTRA_LAUNCH_AUTH_TAB = 59; + int EXTRA_REDIRECT_SCHEME = 60; + int EXTRA_HTTPS_REDIRECT_HOST = 61; + int EXTRA_HTTPS_REDIRECT_PATH = 62; /** Total count of entries. */ - int COUNT = 59; + int COUNT = 63; } // Whether flag-enabled or not. @@ -178,6 +190,6 @@ mUsed.set(feature); RecordHistogram.recordEnumeratedHistogram( - "CustomTabs.FeatureUsage", feature, CustomTabsFeature.COUNT); + CUSTOM_TABS_FEATURE_USAGE_HISTOGRAM, feature, CustomTabsFeature.COUNT); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java index 00dac51..642383f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
@@ -82,7 +82,6 @@ .getDimensionPixelSize(R.dimen.history_item_remove_button_lateral_padding), getPaddingBottom()); - findViewById(R.id.chip_description).setVisibility(View.VISIBLE); mChipView = findViewById(R.id.chip); mChipView.getPrimaryTextView().setEllipsize(TextUtils.TruncateAt.END); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbarTest.java index 509e56a..f1601b3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkToolbarTest.java
@@ -247,7 +247,6 @@ for (int menuId : applicableMenuIds) { boolean isVisible = !hiddenIdSet.contains(menuId); MenuItem menuItem = mBookmarkToolbar.getMenu().findItem(menuId); - assertNotNull(menuId); assertEquals( "Mismatched visibility for menu item " + menuItem, isVisible, @@ -259,7 +258,6 @@ for (int menuId : applicableMenuIds) { boolean isEnabled = !disabledIds.contains(menuId); MenuItem menuItem = mBookmarkToolbar.getMenu().findItem(menuId); - assertNotNull(menuId); assertEquals( "Mismatched enabled state for menu item " + menuItem, isEnabled,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsTest.java index dea9caa16..489cbae9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsTest.java
@@ -198,7 +198,7 @@ try { Assert.assertNotEquals("null", exec(variable)); } catch (TimeoutException e) { - Assert.fail(); + throw new RuntimeException(e); } }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabActivityTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabActivityTestRule.java index 44be8db..7997a83 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabActivityTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabActivityTestRule.java
@@ -69,7 +69,7 @@ try { createNewCustomTabSessionForIntent(intent); } catch (TimeoutException e) { - Assert.fail(); + throw new RuntimeException(e); } } super.startCustomTabActivityWithIntent(intent);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationTransitionsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationTransitionsTest.java index 0ccebe21..77118cb 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationTransitionsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationTransitionsTest.java
@@ -8,6 +8,9 @@ import android.graphics.Bitmap; import android.graphics.Color; +import android.os.Build; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; import androidx.activity.BackEventCompat; import androidx.test.core.app.ApplicationProvider; @@ -33,6 +36,7 @@ import org.chromium.base.test.util.CriteriaNotSatisfiedException; import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.Features.EnableFeatures; +import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.browser.ViewportTestUtils; import org.chromium.chrome.browser.back_press.BackPressManager; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; @@ -50,9 +54,13 @@ import org.chromium.net.test.EmbeddedTestServer; import org.chromium.ui.base.BackGestureEventSwipeEdge; import org.chromium.ui.base.UiAndroidFeatures; +import org.chromium.ui.modaldialog.ModalDialogManager; +import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; +import org.chromium.ui.modelutil.PropertyModel; import java.util.Arrays; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; /** @@ -67,6 +75,7 @@ @CommandLineFlags.Add({ ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-features=BackForwardTransitions,BackGestureRefactorAndroid", + "force-prefers-no-reduced-motion", // Resampling can make scroll offsets non-deterministic so turn it off. "disable-features=ResamplingScrollEvents", "hide-scrollbars" @@ -225,7 +234,6 @@ () -> { invokeNavigateGesture(edge); }); - waitForTransitionFinished(); } private void waitForTransitionFinished() { @@ -244,6 +252,50 @@ CriteriaHelper.DEFAULT_POLLING_INTERVAL); } + private void waitForModalDialogShown() { + CriteriaHelper.pollUiThread( + () -> { + try { + Criteria.checkThat(getDialogManager().isShowing(), Matchers.is(true)); + } catch (Throwable e) { + throw new CriteriaNotSatisfiedException(e); + } + }, + TEST_TIMEOUT, + CriteriaHelper.DEFAULT_POLLING_INTERVAL); + } + + private void runJavaScriptOnTab(String script) { + ThreadUtils.runOnUiThreadBlocking( + () -> { + getWebContents().evaluateJavaScriptForTests(script, null); + }); + } + + private ModalDialogManager getDialogManager() { + return mActivityTestRule.getActivity().getWindowAndroid().getModalDialogManager(); + } + + private int numSuspendedDialogs(@ModalDialogType int dialogType) { + var dialogs = getDialogManager().getPendingDialogsForTest(dialogType); + if (dialogs == null) return 0; + return dialogs.size(); + } + + private void waitForNumSuspendedDialogs(@ModalDialogType int dialogType, int numSuspended) { + CriteriaHelper.pollUiThread( + () -> { + try { + Criteria.checkThat( + numSuspendedDialogs(dialogType), Matchers.is(numSuspended)); + } catch (Throwable e) { + throw new CriteriaNotSatisfiedException(e); + } + }, + TEST_TIMEOUT, + CriteriaHelper.DEFAULT_POLLING_INTERVAL); + } + /** * Basic smoke test of transition back navigation. * @@ -253,6 +305,9 @@ @Test @MediumTest public void smokeTest() throws Throwable { + if (mTestNavigationMode == NAVIGATION_MODE_GESTURAL + && VERSION.SDK_INT < VERSION_CODES.UPSIDE_DOWN_CAKE) return; + // Put "blue.html" and then "green.html" in the session history. String url1 = mTestServer.getURL("/chrome/test/data/android/blue.html"); String url2 = mTestServer.getURL("/chrome/test/data/android/green.html"); @@ -265,6 +320,7 @@ // Perform a back gesture transition from the left edge. performNavigationTransition(url2, BackEventCompat.EDGE_LEFT); + waitForTransitionFinished(); Assert.assertEquals(url2, getCurrentUrl()); @@ -272,9 +328,11 @@ // button mode this goes forward, in gestural mode this goes back. if (mTestNavigationMode == NAVIGATION_MODE_THREE_BUTTON) { performNavigationTransition(url3, BackEventCompat.EDGE_RIGHT); + waitForTransitionFinished(); Assert.assertEquals(url3, getCurrentUrl()); } else { performNavigationTransition(url1, BackEventCompat.EDGE_RIGHT); + waitForTransitionFinished(); Assert.assertEquals(url1, getCurrentUrl()); } } @@ -288,6 +346,9 @@ @Test @MediumTest public void testInputAfterBackTransition() throws Throwable { + if (mTestNavigationMode == NAVIGATION_MODE_GESTURAL + && VERSION.SDK_INT < VERSION_CODES.UPSIDE_DOWN_CAKE) return; + // Put "blue.html" and then "green.html" in the session history. String url1 = mTestServer.getURL("/chrome/test/data/android/blue.html"); String url2 = mTestServer.getURL("/chrome/test/data/android/green.html"); @@ -296,6 +357,7 @@ WebContentsUtils.waitForCopyableViewInWebContents(getWebContents()); performNavigationTransition(url1, BackEventCompat.EDGE_LEFT); + waitForTransitionFinished(); JavaScriptUtils.executeJavaScriptAndWaitForResult( getWebContents(), @@ -326,6 +388,9 @@ @MediumTest @EnableFeatures({UiAndroidFeatures.MIRROR_BACK_FORWARD_GESTURES_IN_RTL}) public void testBackNavInRTL() throws Throwable { + if (mTestNavigationMode == NAVIGATION_MODE_GESTURAL + && VERSION.SDK_INT < VERSION_CODES.UPSIDE_DOWN_CAKE) return; + setRtlForTesting(true); // Put "blue.html" and then "green.html" in the session history. @@ -338,6 +403,7 @@ WebContentsUtils.waitForCopyableViewInWebContents(getWebContents()); performNavigationTransition(url2, BackEventCompat.EDGE_RIGHT); + waitForTransitionFinished(); Assert.assertEquals(url2, getCurrentUrl()); // Perform an edge gesture transition from the left edge (semantically @@ -345,9 +411,11 @@ // forward, in gestural mode this goes back (without a transition). if (mTestNavigationMode == NAVIGATION_MODE_THREE_BUTTON) { performNavigationTransition(url3, BackEventCompat.EDGE_LEFT); + waitForTransitionFinished(); Assert.assertEquals(url3, getCurrentUrl()); } else { performNavigationTransition(url1, BackEventCompat.EDGE_LEFT); + waitForTransitionFinished(); Assert.assertEquals(url1, getCurrentUrl()); } } @@ -360,6 +428,9 @@ @Test @MediumTest public void startBackNavWithTopControlHidden() throws Throwable { + if (mTestNavigationMode == NAVIGATION_MODE_GESTURAL + && VERSION.SDK_INT < VERSION_CODES.UPSIDE_DOWN_CAKE) return; + // The top control's offset is -top_controls_height when controls are fully hidden, 0 when // fully shown. final AtomicInteger topControlOffsetDuringGesture = new AtomicInteger(Integer.MAX_VALUE); @@ -399,6 +470,7 @@ // Perform a back gesture transition. mViewportTestUtils.hideBrowserControls(); performNavigationTransition(url1, BackEventCompat.EDGE_LEFT); + waitForTransitionFinished(); Assert.assertEquals(url1, getCurrentUrl()); @@ -406,4 +478,123 @@ topControlOffsetDuringGesture.get() > -mViewportTestUtils.getTopControlsHeightPx()); mViewportTestUtils.waitForBrowserControlsState(/* shown= */ true); } + + /** + * Test that the modal dialogs are suspended during the transition but resumed after the + * transition. + */ + @Test + @MediumTest + @MinAndroidSdkLevel(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + public void alertSuspendedDuringTransition() throws Throwable { + // Skip for three button mode because `TouchCommon.performWallClockDrag` blocks (it sleeps + // between each touch event). It's okay to skip because the dialog suspension is navigation + // mode agnostic. + if (mTestNavigationMode == NAVIGATION_MODE_THREE_BUTTON) return; + + // Put "blue.html" and then "green.html" in the session history. + String url1 = mTestServer.getURL("/chrome/test/data/android/blue.html"); + String url2 = mTestServer.getURL("/chrome/test/data/android/green.html"); + mActivityTestRule.loadUrl(url1); + mActivityTestRule.loadUrl(url2); + + WebContentsUtils.waitForCopyableViewInWebContents(getWebContents()); + + final AtomicBoolean dialogQueuedToShow = new AtomicBoolean(false); + ThreadUtils.runOnUiThreadBlocking( + () -> { + getDialogManager() + .addObserver( + new ModalDialogManager.ModalDialogManagerObserver() { + @Override + public void onDialogAdded(PropertyModel model) { + dialogQueuedToShow.set(true); + } + }); + }); + + ThreadUtils.runOnUiThreadBlocking( + () -> { + BackPressManager manager = + mActivityTestRule.getActivity().getBackPressManagerForTesting(); + var backEvent = new BackEventCompat(0, 0, 0, BackEventCompat.EDGE_LEFT); + manager.getCallback().handleOnBackStarted(backEvent); + }); + runJavaScriptOnTab("window.alert('during transition');"); + waitForNumSuspendedDialogs(ModalDialogType.TAB, 1); + Assert.assertFalse(dialogQueuedToShow.get()); + ThreadUtils.runOnUiThreadBlocking( + () -> { + BackPressManager manager = + mActivityTestRule.getActivity().getBackPressManagerForTesting(); + var backEvent = new BackEventCompat(1, 0, 0.8f, BackEventCompat.EDGE_LEFT); + manager.getCallback().handleOnBackProgressed(backEvent); + manager.getCallback().handleOnBackPressed(); + }); + + waitForTransitionFinished(); + Assert.assertEquals(0, numSuspendedDialogs(ModalDialogType.TAB)); + Assert.assertFalse(dialogQueuedToShow.get()); + + // After the transition, dialogs are resumed. + runJavaScriptOnTab("window.alert('after transition');"); + waitForModalDialogShown(); + Assert.assertTrue(dialogQueuedToShow.get()); + } + + /** + * Test that the modal dialogs are suspended during the transition but resumed after the + * transition is cancelled. + */ + @Test + @MediumTest + @MinAndroidSdkLevel(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + public void alertResumedAfterGestureCancelled() throws Throwable { + // TouchCommon.java doesn't have a "cancel gesture". + if (mTestNavigationMode == NAVIGATION_MODE_THREE_BUTTON) return; + + // Put "blue.html" and then "green.html" in the session history. + String url1 = mTestServer.getURL("/chrome/test/data/android/blue.html"); + String url2 = mTestServer.getURL("/chrome/test/data/android/green.html"); + mActivityTestRule.loadUrl(url1); + mActivityTestRule.loadUrl(url2); + + final AtomicBoolean dialogQueuedToShow = new AtomicBoolean(false); + ThreadUtils.runOnUiThreadBlocking( + () -> { + getDialogManager() + .addObserver( + new ModalDialogManager.ModalDialogManagerObserver() { + @Override + public void onDialogAdded(PropertyModel model) { + dialogQueuedToShow.set(true); + } + }); + }); + + ThreadUtils.runOnUiThreadBlocking( + () -> { + BackPressManager manager = + mActivityTestRule.getActivity().getBackPressManagerForTesting(); + var backEvent = new BackEventCompat(0, 0, 0, BackEventCompat.EDGE_LEFT); + manager.getCallback().handleOnBackStarted(backEvent); + }); + runJavaScriptOnTab("window.alert('shown after transition');"); + waitForNumSuspendedDialogs(ModalDialogType.TAB, 1); + Assert.assertFalse(dialogQueuedToShow.get()); + ThreadUtils.runOnUiThreadBlocking( + () -> { + BackPressManager manager = + mActivityTestRule.getActivity().getBackPressManagerForTesting(); + var backEvent = new BackEventCompat(1, 0, .8f, BackEventCompat.EDGE_LEFT); + manager.getCallback().handleOnBackProgressed(backEvent); + manager.getCallback().handleOnBackCancelled(); + }); + waitForTransitionFinished(); + Assert.assertEquals(0, numSuspendedDialogs(ModalDialogType.TAB)); + + // After the transition is finished, the dialog is resumed. + waitForModalDialogShown(); + Assert.assertTrue(dialogQueuedToShow.get()); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java index 04fa7150..5cd87fe 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java
@@ -101,7 +101,7 @@ Assert.assertEquals(UrlConstants.NTP_URL, url); // Check that the NTP is actually displayed. - Assert.assertNotNull(tab.getNativePage() instanceof NewTabPage); + Assert.assertTrue(tab.getNativePage() instanceof NewTabPage); } /** Tests navigating to the tab switcher from the NTP. */
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillDeletePaymentMethodConfirmationDialogTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillDeletePaymentMethodConfirmationDialogTest.java index c92b8fbf..9d56955 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillDeletePaymentMethodConfirmationDialogTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillDeletePaymentMethodConfirmationDialogTest.java
@@ -2,6 +2,8 @@ // 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.autofill.settings; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.verify; @@ -24,7 +26,6 @@ import org.chromium.base.Callback; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.R; -import org.chromium.chrome.browser.autofill.settings.AutofillDeletePaymentMethodConfirmationDialog; import org.chromium.ui.modaldialog.DialogDismissalCause; import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; import org.chromium.ui.modaldialog.ModalDialogProperties;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerMediatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerMediatorTest.java index 1eae022e..39d58b6 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerMediatorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerMediatorTest.java
@@ -852,7 +852,6 @@ assertEquals(mBookmarkItem21.getTitle(), model.get(ImprovedBookmarkRowProperties.TITLE)); assertEquals(EXAMPLE_URL_FORMATTED, model.get(ImprovedBookmarkRowProperties.DESCRIPTION)); assertNotNull(model.get(ImprovedBookmarkRowProperties.START_ICON_DRAWABLE)); - assertNotNull(model.get(ImprovedBookmarkRowProperties.START_AREA_BACKGROUND_COLOR)); assertNull(model.get(ImprovedBookmarkRowProperties.START_ICON_TINT)); assertNotNull(model.get(ImprovedBookmarkRowProperties.POPUP_LISTENER)); assertEquals(false, model.get(ImprovedBookmarkRowProperties.SELECTION_ACTIVE)); @@ -927,7 +926,6 @@ assertEquals(mBookmarkItem21.getTitle(), model.get(ImprovedBookmarkRowProperties.TITLE)); assertEquals(EXAMPLE_URL_FORMATTED, model.get(ImprovedBookmarkRowProperties.DESCRIPTION)); assertNotNull(model.get(ImprovedBookmarkRowProperties.START_ICON_DRAWABLE)); - assertNotNull(model.get(ImprovedBookmarkRowProperties.START_AREA_BACKGROUND_COLOR)); assertNull(model.get(ImprovedBookmarkRowProperties.START_ICON_TINT)); assertNotNull(model.get(ImprovedBookmarkRowProperties.START_ICON_DRAWABLE)); assertNotNull(model.get(ImprovedBookmarkRowProperties.POPUP_LISTENER)); @@ -1013,7 +1011,6 @@ ImageVisibility.DRAWABLE, model.get(ImprovedBookmarkRowProperties.START_IMAGE_VISIBILITY)); assertNotNull(model.get(ImprovedBookmarkRowProperties.START_ICON_DRAWABLE)); - assertNotNull(model.get(ImprovedBookmarkRowProperties.START_AREA_BACKGROUND_COLOR)); assertNotNull(model.get(ImprovedBookmarkRowProperties.START_ICON_TINT)); assertNotNull(model.get(ImprovedBookmarkRowProperties.POPUP_LISTENER)); assertEquals(false, model.get(ImprovedBookmarkRowProperties.SELECTION_ACTIVE)); @@ -1075,7 +1072,6 @@ assertEquals( mFolderItem2.getTitle() + " (1)", model.get(ImprovedBookmarkRowProperties.TITLE)); assertNotNull(model.get(ImprovedBookmarkRowProperties.START_ICON_DRAWABLE)); - assertNotNull(model.get(ImprovedBookmarkRowProperties.START_AREA_BACKGROUND_COLOR)); assertNotNull(model.get(ImprovedBookmarkRowProperties.START_ICON_TINT)); assertNotNull(model.get(ImprovedBookmarkRowProperties.POPUP_LISTENER)); assertEquals(false, model.get(ImprovedBookmarkRowProperties.SELECTION_ACTIVE));
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/ImprovedBookmarkRowCoordinatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/ImprovedBookmarkRowCoordinatorTest.java index 359653a..b3ef4a52 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/ImprovedBookmarkRowCoordinatorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/bookmarks/ImprovedBookmarkRowCoordinatorTest.java
@@ -269,7 +269,6 @@ PropertyModel model = mCoordinator.createBasePropertyModel(READING_LIST_BOOKMARK_ID); assertFalse(mCoordinator.shouldShowImagesForFolder(READING_LIST_BOOKMARK_ID)); - assertNotNull(model.get(ImprovedBookmarkRowProperties.FOLDER_START_AREA_BACKGROUND_COLOR)); assertNotNull(model.get(ImprovedBookmarkRowProperties.FOLDER_START_ICON_TINT)); assertNotNull(model.get(ImprovedBookmarkRowProperties.FOLDER_START_ICON_DRAWABLE)); assertEquals(0, model.get(ImprovedBookmarkRowProperties.FOLDER_CHILD_COUNT));
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java index 3625b04..2b3122f 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManagerTest.java
@@ -45,7 +45,8 @@ import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.Robolectric; import org.robolectric.annotation.Config; @@ -105,6 +106,7 @@ @DisableFeatures(ChromeFeatureList.TAB_STRIP_INCOGNITO_MIGRATION) public class StripLayoutHelperManagerTest { @Rule public JniMocker mJniMocker = new JniMocker(); + @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); @Mock private TabStripSceneLayer.Natives mTabStripSceneMock; @Mock private TabStripSceneLayer mTabStripTreeProvider; @Mock private LayoutManagerHost mManagerHost; @@ -150,17 +152,16 @@ @Before public void beforeTest() { - MockitoAnnotations.initMocks(this); mJniMocker.mock(TabStripSceneLayerJni.TEST_HOOKS, mTabStripSceneMock); mActivity = Robolectric.buildActivity(Activity.class).setup().get(); mActivity.setTheme(R.style.Theme_BrowserUI_DayNight); - when(mToolbarContainerView.getContext()).thenReturn(mActivity); - when(mToolbarManager.getStatusBarColorController()).thenReturn(mStatusBarColorController); - TabStripSceneLayer.setTestFlag(true); + when(mToolbarContainerView.getContext()).thenReturn(mActivity); + when(mToolbarManager.getStatusBarColorController()).thenReturn(mStatusBarColorController); when(mDesktopWindowStateProvider.isInUnfocusedDesktopWindow()).thenReturn(false); when(mWindowAndroid.getActivity()).thenReturn(new WeakReference<>(mActivity)); + initializeTest(); } @@ -347,7 +348,7 @@ @Test @DisableFeatures(ChromeFeatureList.TAB_STRIP_LAYOUT_OPTIMIZATION) - public void testModelSelectorButtonXPosition() { + public void testModelSelectorButtonDrawX() { // Set model selector button position. mStripLayoutHelperManager.setModelSelectorButtonVisibleForTesting(true); mStripLayoutHelperManager.onSizeChanged( @@ -364,7 +365,7 @@ @Test @DisableFeatures(ChromeFeatureList.TAB_STRIP_LAYOUT_OPTIMIZATION) - public void testModelSelectorButtonXPosition_RTL() { + public void testModelSelectorButtonDrawX_Rtl() { // Set model selector button position. LocalizationUtils.setRtlForTesting(true); mStripLayoutHelperManager.setModelSelectorButtonVisibleForTesting(true); @@ -380,7 +381,7 @@ } @Test - public void testModelSelectorButtonYPosition() { + public void testModelSelectorButtonDrawY() { // Set model selector button position. mStripLayoutHelperManager.onSizeChanged( SCREEN_WIDTH, SCREEN_HEIGHT, VISIBLE_VIEWPORT_Y, ORIENTATION); @@ -540,7 +541,7 @@ } @Test - public void testFadeDrawable_Left_RTL_ModelSelectorButtonVisible() { + public void testFadeDrawable_Left_Rtl_ModelSelectorButtonVisible() { // setup mStripLayoutHelperManager.setModelSelectorButtonVisibleForTesting(true); LocalizationUtils.setRtlForTesting(true); @@ -553,7 +554,7 @@ } @Test - public void testFadeDrawable_Left_RTL() { + public void testFadeDrawable_Left_Rtl() { // setup LocalizationUtils.setRtlForTesting(true); @@ -565,7 +566,7 @@ } @Test - public void testFadeDrawable_Right_RTL() { + public void testFadeDrawable_Right_Rtl() { // setup mStripLayoutHelperManager.setModelSelectorButtonVisibleForTesting(true); LocalizationUtils.setRtlForTesting(true);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java index f743e90..d79b371 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java
@@ -3924,13 +3924,16 @@ // Verify. StripLayoutTab[] tabs = mStripLayoutHelper.getStripLayoutTabsForTesting(); assertTrue("Should be in reorder mode.", mStripLayoutHelper.getInReorderModeForTesting()); - assertNotEquals("Should be tab margin after tab 0.", 0, tabs[0].getTrailingMargin()); + assertEquals( + "Should not be tab margin after tab 0.", 0, tabs[0].getTrailingMargin(), EPSILON); assertEquals( "Should not be tab margin after tab 1.", 0, tabs[1].getTrailingMargin(), EPSILON); - assertNotEquals("Should be tab margin after tab 2.", 0, tabs[2].getTrailingMargin()); + assertEquals( + "Should not be tab margin after tab 2.", 0, tabs[2].getTrailingMargin(), EPSILON); assertEquals( "Should not be tab margin after tab 3.", 0, tabs[3].getTrailingMargin(), EPSILON); - assertNotEquals("Should be tab margin after tab 4.", 0, tabs[4].getTrailingMargin()); + assertNotEquals( + "Should be tab margin after tab 4.", 0, tabs[4].getTrailingMargin(), EPSILON); assertEquals( "TouchableRect does not match. Touch size should match the strip during drag.", @@ -3962,22 +3965,26 @@ StripLayoutTab[] tabs = mStripLayoutHelper.getStripLayoutTabsForTesting(); assertEquals( "Should not be tab margin after tab 0.", 0, tabs[0].getTrailingMargin(), EPSILON); - assertNotEquals("Should be tab margin after tab 1.", 0, tabs[1].getTrailingMargin()); + assertEquals( + "Should not be tab margin after tab 1.", 0, tabs[1].getTrailingMargin(), EPSILON); assertEquals( "Should not be tab margin after tab 2.", 0, tabs[2].getTrailingMargin(), EPSILON); - assertNotEquals("Should be tab margin after tab 3.", 0, tabs[3].getTrailingMargin()); + assertNotEquals( + "Should be tab margin after tab 3.", 0, tabs[3].getTrailingMargin(), EPSILON); // Now hover between 1st and 2nd tab: // tabWidth(265) - overlapWidth(28) = 237 mStripLayoutHelper.updateReorderPositionForTabDrop(237.f); // Verify. - assertNotEquals("Should be tab margin after tab 0.", 0, tabs[0].getTrailingMargin()); + assertEquals( + "Should not be tab margin after tab 0.", 0, tabs[0].getTrailingMargin(), EPSILON); assertEquals( "Should not be tab margin after tab 1.", 0, tabs[1].getTrailingMargin(), EPSILON); assertEquals( "Should not be tab margin after tab 2.", 0, tabs[2].getTrailingMargin(), EPSILON); - assertNotEquals("Should be tab margin after tab 3.", 0, tabs[3].getTrailingMargin()); + assertNotEquals( + "Should be tab margin after tab 3.", 0, tabs[3].getTrailingMargin(), EPSILON); } @Test @@ -4007,7 +4014,8 @@ "Should not be tab margin after tab 0.", 0, tabs[0].getTrailingMargin(), EPSILON); assertEquals( "Should not be tab margin after tab 1.", 0, tabs[1].getTrailingMargin(), EPSILON); - assertNotEquals("Should be tab margin after tab 2.", 0, tabs[2].getTrailingMargin()); + assertNotEquals( + "Should be tab margin after tab 2.", 0, tabs[2].getTrailingMargin(), EPSILON); // Hover in end gap: mStripLayoutHelper.updateReorderPositionForTabDrop(1100); @@ -4017,7 +4025,8 @@ "Should not be tab margin after tab 0.", 0, tabs[0].getTrailingMargin(), EPSILON); assertEquals( "Should not be tab margin after tab 1.", 0, tabs[1].getTrailingMargin(), EPSILON); - assertNotEquals("Should be tab margin after tab 2.", 0, tabs[2].getTrailingMargin()); + assertNotEquals( + "Should be tab margin after tab 2.", 0, tabs[2].getTrailingMargin(), EPSILON); } @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/AuthTabIntentDataProviderUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/AuthTabIntentDataProviderUnitTest.java index 044f65a..6ecfc95 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/AuthTabIntentDataProviderUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/AuthTabIntentDataProviderUnitTest.java
@@ -8,6 +8,11 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.chromium.chrome.browser.customtabs.AuthTabIntentDataProvider.EXTRA_HTTPS_REDIRECT_HOST; +import static org.chromium.chrome.browser.customtabs.AuthTabIntentDataProvider.EXTRA_HTTPS_REDIRECT_PATH; +import static org.chromium.chrome.browser.customtabs.CustomTabsFeatureUsage.CUSTOM_TABS_FEATURE_USAGE_HISTOGRAM; +import static org.chromium.chrome.browser.flags.ChromeFeatureList.CCT_FEATURE_USAGE; + import android.app.Activity; import android.content.Intent; import android.net.Uri; @@ -25,6 +30,8 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.Batch; +import org.chromium.base.test.util.Features; +import org.chromium.base.test.util.HistogramWatcher; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider.CustomTabsUiType; import org.chromium.chrome.browser.flags.ActivityType; @@ -33,6 +40,7 @@ @RunWith(BaseRobolectricTestRunner.class) @Batch(Batch.UNIT_TESTS) @Config(manifest = Config.NONE) +@Features.EnableFeatures(CCT_FEATURE_USAGE) public class AuthTabIntentDataProviderUnitTest { @Rule public ActivityScenarioRule<TestActivity> mActivityScenario = @@ -41,6 +49,8 @@ private static final String PACKAGE = "com.example.package.app"; private static final String URL = "https://www.google.com"; private static final String SCHEME = "myscheme"; + private static final String HOST = "www.host.com"; + private static final String PATH = "/path/auth"; private Activity mActivity; private Intent mIntent; @@ -52,16 +62,15 @@ mIntent = new Intent(Intent.ACTION_VIEW); mIntent.setData(Uri.parse(URL)); mIntent.putExtra(AuthTabIntent.EXTRA_LAUNCH_AUTH_TAB, true); - mIntent.putExtra(AuthTabIntent.EXTRA_REDIRECT_SCHEME, SCHEME); mIntent.putExtra(IntentHandler.EXTRA_CALLING_ACTIVITY_PACKAGE, PACKAGE); Bundle bundle = new Bundle(); bundle.putBinder(CustomTabsIntent.EXTRA_SESSION, null); mIntent.putExtras(bundle); - mIntentDataProvider = new AuthTabIntentDataProvider(mIntent, mActivity); } @Test public void testOverriddenDefaults() { + mIntentDataProvider = new AuthTabIntentDataProvider(mIntent, mActivity); assertEquals( "ActivityType should be AUTH_TAB.", ActivityType.AUTH_TAB, @@ -86,9 +95,53 @@ @Test public void testIntentData() { + var histogramWatcher = + HistogramWatcher.newBuilder() + .expectIntRecord( + CUSTOM_TABS_FEATURE_USAGE_HISTOGRAM, + CustomTabsFeatureUsage.CustomTabsFeature.EXTRA_LAUNCH_AUTH_TAB) + .allowExtraRecordsForHistogramsAbove() + .build(); + mIntentDataProvider = new AuthTabIntentDataProvider(mIntent, mActivity); + assertEquals("Intent doesn't match expectation.", mIntent, mIntentDataProvider.getIntent()); assertEquals("Wrong package name", PACKAGE, mIntentDataProvider.getClientPackageName()); assertEquals("Wrong URL", URL, mIntentDataProvider.getUrlToLoad()); + histogramWatcher.assertExpected(); + } + + @Test + public void testIntentData_customScheme() { + var histogramWatcher = + HistogramWatcher.newBuilder() + .expectIntRecord( + CUSTOM_TABS_FEATURE_USAGE_HISTOGRAM, + CustomTabsFeatureUsage.CustomTabsFeature.EXTRA_REDIRECT_SCHEME) + .allowExtraRecordsForHistogramsAbove() + .build(); + mIntent.putExtra(AuthTabIntent.EXTRA_REDIRECT_SCHEME, SCHEME); + mIntentDataProvider = new AuthTabIntentDataProvider(mIntent, mActivity); + assertEquals("Wrong redirect scheme.", SCHEME, mIntentDataProvider.getAuthRedirectScheme()); + histogramWatcher.assertExpected(); + } + + @Test + public void testIntentData_https() { + var histogramWatcher = + HistogramWatcher.newBuilder() + .expectIntRecords( + CUSTOM_TABS_FEATURE_USAGE_HISTOGRAM, + CustomTabsFeatureUsage.CustomTabsFeature.EXTRA_HTTPS_REDIRECT_HOST, + CustomTabsFeatureUsage.CustomTabsFeature.EXTRA_HTTPS_REDIRECT_PATH) + .allowExtraRecordsForHistogramsAbove() + .build(); + mIntent.putExtra(EXTRA_HTTPS_REDIRECT_HOST, HOST); + mIntent.putExtra(EXTRA_HTTPS_REDIRECT_PATH, PATH); + mIntentDataProvider = new AuthTabIntentDataProvider(mIntent, mActivity); + + assertEquals("Wrong https redirect host.", HOST, mIntentDataProvider.getAuthRedirectHost()); + assertEquals("Wrong https redirect path.", PATH, mIntentDataProvider.getAuthRedirectPath()); + histogramWatcher.assertExpected(); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationUnitTest.java index e54fece..89ce823 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationUnitTest.java
@@ -98,7 +98,7 @@ activityClass = (Class<? extends Activity>) Class.forName(intent.getComponent().getClassName()); } catch (ClassNotFoundException e) { - Assert.fail(); + throw new RuntimeException(e); } createActivity(activityClass, intent); }
diff --git a/chrome/android/webapk/libs/runtime_library/javatests/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImplTest.java b/chrome/android/webapk/libs/runtime_library/javatests/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImplTest.java index ac7c904..475d1ba5 100644 --- a/chrome/android/webapk/libs/runtime_library/javatests/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImplTest.java +++ b/chrome/android/webapk/libs/runtime_library/javatests/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImplTest.java
@@ -103,9 +103,8 @@ context.getPackageName(), PackageManager.GET_META_DATA); return appInfo.uid; } catch (Exception e) { - Assert.fail(); + throw new RuntimeException(e); } - return -1; } /**
diff --git a/chrome/android/webapk/shell_apk/javatests/src/org/chromium/webapk/shell_apk/h2o/SplashUtilsTest.java b/chrome/android/webapk/shell_apk/javatests/src/org/chromium/webapk/shell_apk/h2o/SplashUtilsTest.java index 9b9d27b..f5f16543 100644 --- a/chrome/android/webapk/shell_apk/javatests/src/org/chromium/webapk/shell_apk/h2o/SplashUtilsTest.java +++ b/chrome/android/webapk/shell_apk/javatests/src/org/chromium/webapk/shell_apk/h2o/SplashUtilsTest.java
@@ -51,7 +51,7 @@ try { bitmap.getPixels(pixels, 0, width, 0, 0, width, height); } catch (Exception e) { - Assert.fail(); + throw new RuntimeException(e); } int firstColor = pixels[0]; for (int i = 1; i < pixels.length; ++i) {
diff --git a/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/HostBrowserClassLoaderTest.java b/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/HostBrowserClassLoaderTest.java index 288fa26c..40259bc 100644 --- a/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/HostBrowserClassLoaderTest.java +++ b/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/HostBrowserClassLoaderTest.java
@@ -23,6 +23,7 @@ import java.io.ByteArrayInputStream; import java.io.File; +import java.io.IOException; import java.io.InputStream; /** Tests HostBrowserClassLoader. */ @@ -47,7 +48,7 @@ private DexLoader mMockDexLoader; @Before - public void setUp() { + public void setUp() throws Exception { mContext = RuntimeEnvironment.application; mPackageManager = mContext.getPackageManager(); setRemoteVersionCode(REMOTE_VERSION_CODE); @@ -65,7 +66,7 @@ /** Test upgrading to a new runtime dex version. */ @Test - public void testNewRuntimeDexVersion() { + public void testNewRuntimeDexVersion() throws Exception { HostBrowserClassLoader.createClassLoader(mContext, mRemoteContext, mMockDexLoader, null); String expectedDexName = WebApkCommonUtils.getRuntimeDexName(REMOTE_DEX_VERSION); @@ -139,13 +140,9 @@ * Sets the version of the current runtime library dex stored in the remote host browser's * assets. */ - public void setRemoteDexVersion(int dexVersion) { - try { - Mockito.when(mRemoteAssetManager.open("webapk_dex_version.txt")) - .thenReturn(createIntInputStream(dexVersion)); - } catch (Exception e) { - Assert.fail(); - } + public void setRemoteDexVersion(int dexVersion) throws IOException { + Mockito.when(mRemoteAssetManager.open("webapk_dex_version.txt")) + .thenReturn(createIntInputStream(dexVersion)); } /**
diff --git a/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/h2o/LaunchTest.java b/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/h2o/LaunchTest.java index 220bbf4..af35406 100644 --- a/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/h2o/LaunchTest.java +++ b/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/h2o/LaunchTest.java
@@ -791,7 +791,7 @@ (Class<? extends Activity>) Class.forName(startedActivityIntent.getComponent().getClassName()); } catch (ClassNotFoundException e) { - Assert.fail(); + throw new RuntimeException(e); } buildActivityFully(startedActivityClass, startedActivityIntent); }
diff --git a/chrome/app/password_manager_ui_strings.grdp b/chrome/app/password_manager_ui_strings.grdp index cecc390..472b4689 100644 --- a/chrome/app/password_manager_ui_strings.grdp +++ b/chrome/app/password_manager_ui_strings.grdp
@@ -3,6 +3,9 @@ <message name="IDS_PASSWORD_MANAGER_UI_TITLE" desc="Title of the Password Manager page"> Password Manager </message> + <message name="IDS_PASSWORD_MANAGER_UI_DESCRIPTION" desc="A description of the application."> + Keep track of your passwords and manage them in one place. + </message> <message name="IDS_PASSWORD_MANAGER_UI_SEARCH_PROMPT" desc="Placeholder in the search field."> Search passwords </message>
diff --git a/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_DESCRIPTION.png.sha1 b/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..fea542d1 --- /dev/null +++ b/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +2cf2992540345256c40454c85504ea2c3e6bd17c \ No newline at end of file
diff --git a/chrome/browser/ash/accessibility/service/automation_client_impl.cc b/chrome/browser/ash/accessibility/service/automation_client_impl.cc index cd8d8fe..f6db723aa 100644 --- a/chrome/browser/ash/accessibility/service/automation_client_impl.cc +++ b/chrome/browser/ash/accessibility/service/automation_client_impl.cc
@@ -3,10 +3,12 @@ // found in the LICENSE file. #include "chrome/browser/ash/accessibility/service/automation_client_impl.h" + #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h" #include "extensions/browser/api/automation_internal/automation_event_router.h" #include "extensions/browser/api/automation_internal/automation_internal_api.h" #include "mojo/public/cpp/bindings/pending_associated_remote.h" +#include "ui/accessibility/ax_location_and_scroll_updates.h" namespace ash { @@ -55,8 +57,8 @@ } void AutomationClientImpl::DispatchAccessibilityLocationChange( - const ui::AXLocationChanges& details) { - ui::AXTreeID tree_id = details.ax_tree_id; + const ui::AXTreeID& tree_id, + const ui::AXLocationChange& details) { if (tree_id == ui::AXTreeIDUnknown()) return; for (auto& remote : automation_remotes_) {
diff --git a/chrome/browser/ash/accessibility/service/automation_client_impl.h b/chrome/browser/ash/accessibility/service/automation_client_impl.h index 3588d42..74f4b104 100644 --- a/chrome/browser/ash/accessibility/service/automation_client_impl.h +++ b/chrome/browser/ash/accessibility/service/automation_client_impl.h
@@ -11,6 +11,7 @@ #include "mojo/public/cpp/bindings/remote_set.h" #include "services/accessibility/public/mojom/automation.mojom.h" #include "services/accessibility/public/mojom/automation_client.mojom.h" +#include "ui/accessibility/ax_location_and_scroll_updates.h" namespace ash { @@ -51,7 +52,8 @@ const gfx::Point& mouse_location, const std::vector<ui::AXEvent>& events) override; void DispatchAccessibilityLocationChange( - const ui::AXLocationChanges& details) override; + const ui::AXTreeID& tree_id, + const ui::AXLocationChange& details) override; void DispatchTreeDestroyedEvent(ui::AXTreeID tree_id) override; void DispatchActionResult(const ui::AXActionData& data, bool result,
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc index 733b30a..871e611 100644 --- a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc +++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc
@@ -62,7 +62,8 @@ const std::vector<ui::AXEvent>& events) override {} void DispatchAccessibilityLocationChange( - const ui::AXLocationChanges& details) override {} + const ui::AXTreeID& tree_id, + const ui::AXLocationChange& details) override {} void DispatchTreeDestroyedEvent(ui::AXTreeID tree_id) override {}
diff --git a/chrome/browser/ash/crosapi/automation_ash.cc b/chrome/browser/ash/crosapi/automation_ash.cc index 65711581..e1b9ac39 100644 --- a/chrome/browser/ash/crosapi/automation_ash.cc +++ b/chrome/browser/ash/crosapi/automation_ash.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/ash/crosapi/automation_ash.h" +#include "ui/accessibility/ax_location_and_scroll_updates.h" +#include "ui/accessibility/ax_tree_id.h" + namespace crosapi { AutomationAsh::AutomationAsh() { @@ -63,12 +66,12 @@ const base::UnguessableToken& tree_id, int32_t node_id, const ui::AXRelativeBounds& bounds) { - ui::AXLocationChanges details; - details.ax_tree_id = ui::AXTreeID::FromToken(tree_id); + ui::AXLocationChange details; details.id = node_id; details.new_location = bounds; + ui::AXTreeID ui_tree_id = ui::AXTreeID::FromToken(tree_id); extensions::AutomationEventRouter::GetInstance() - ->DispatchAccessibilityLocationChange(details); + ->DispatchAccessibilityLocationChange(ui_tree_id, details); } void AutomationAsh::DispatchTreeDestroyedEvent(
diff --git a/chrome/browser/ash/crostini/crostini_export_import.cc b/chrome/browser/ash/crostini/crostini_export_import.cc index 45d6cd8..962f33e 100644 --- a/chrome/browser/ash/crostini/crostini_export_import.cc +++ b/chrome/browser/ash/crostini/crostini_export_import.cc
@@ -367,7 +367,12 @@ std::move(callback))); break; case ExportImportType::IMPORT_DISK_IMAGE: - LOG(ERROR) << "Importing disk images is currently unimplemented"; + crostini::CrostiniManager::GetForProfile(profile_)->StopVm( + operation_data->container_id.vm_name, + base::BindOnce(&CrostiniExportImport::ImportDiskImage, + weak_ptr_factory_.GetWeakPtr(), + operation_data->container_id, path, + std::move(callback))); break; } } @@ -399,12 +404,44 @@ CrostiniManager::GetForProfile(profile_)->ExportDiskImage( container_id, user->username_hash(), path, /*force=*/false, - base::BindOnce(&CrostiniExportImport::AfterExportDiskImage, + base::BindOnce(&CrostiniExportImport::AfterDiskImageOperation, weak_ptr_factory_.GetWeakPtr(), container_id, std::move(callback))); } -void CrostiniExportImport::AfterExportDiskImage( +void CrostiniExportImport::ImportDiskImage( + const guest_os::GuestId& container_id, + const base::FilePath& path, + CrostiniManager::CrostiniResultCallback callback, + CrostiniResult result) { + if (result == CrostiniResult::VM_STOP_FAILED) { + LOG(ERROR) << "Unable to stop VM, cannot import disk image"; + std::move(callback).Run(CrostiniResult::DISK_IMAGE_FAILED); + return; + } + + ash::ProfileHelper* profile_helper = ash::ProfileHelper::Get(); + if (!profile_helper) { + LOG(ERROR) << "Unable to get profile helper"; + std::move(callback).Run(CrostiniResult::DISK_IMAGE_FAILED); + return; + } + user_manager::User* user = profile_helper->GetUserByProfile(profile_); + + if (!user) { + LOG(ERROR) << "Unable to get user"; + std::move(callback).Run(CrostiniResult::DISK_IMAGE_FAILED); + return; + } + + CrostiniManager::GetForProfile(profile_)->ImportDiskImage( + container_id, user->username_hash(), path, + base::BindOnce(&CrostiniExportImport::AfterDiskImageOperation, + weak_ptr_factory_.GetWeakPtr(), container_id, + std::move(callback))); +} + +void CrostiniExportImport::AfterDiskImageOperation( const guest_os::GuestId& container_id, CrostiniManager::CrostiniResultCallback callback, CrostiniResult result) { @@ -858,6 +895,7 @@ manager.CancelImportLxdContainer(std::move(container_id)); return; case ExportImportType::EXPORT_DISK_IMAGE: + case ExportImportType::IMPORT_DISK_IMAGE: manager.CancelDiskImageOp(std::move(container_id)); return; default:
diff --git a/chrome/browser/ash/crostini/crostini_export_import.h b/chrome/browser/ash/crostini/crostini_export_import.h index e30a963..be22348 100644 --- a/chrome/browser/ash/crostini/crostini_export_import.h +++ b/chrome/browser/ash/crostini/crostini_export_import.h
@@ -202,6 +202,11 @@ FRIEND_TEST_ALL_PREFIXES(CrostiniExportImportTest, TestExportDiskImageFail); FRIEND_TEST_ALL_PREFIXES(CrostiniExportImportTest, TestExportDiskImageCancelled); + FRIEND_TEST_ALL_PREFIXES(CrostiniExportImportTest, + TestImportDiskImageSuccess); + FRIEND_TEST_ALL_PREFIXES(CrostiniExportImportTest, TestImportDiskImageFail); + FRIEND_TEST_ALL_PREFIXES(CrostiniExportImportTest, + TestImportDiskImageCancelled); void FillOperationData(ExportImportType type, guest_os::GuestId id, @@ -255,9 +260,14 @@ CrostiniManager::CrostiniResultCallback callback, CrostiniResult result); - void AfterExportDiskImage(const guest_os::GuestId& container_id, - CrostiniManager::CrostiniResultCallback callback, - CrostiniResult result); + void ImportDiskImage(const guest_os::GuestId& container_id, + const base::FilePath& path, + CrostiniManager::CrostiniResultCallback callback, + CrostiniResult result); + + void AfterDiskImageOperation(const guest_os::GuestId& container_id, + CrostiniManager::CrostiniResultCallback callback, + CrostiniResult result); void ExportAfterSharing(const guest_os::GuestId& container_id, const base::FilePath& path,
diff --git a/chrome/browser/ash/crostini/crostini_export_import_status_tracker.cc b/chrome/browser/ash/crostini/crostini_export_import_status_tracker.cc index 9685a77..e300ae7 100644 --- a/chrome/browser/ash/crostini/crostini_export_import_status_tracker.cc +++ b/chrome/browser/ash/crostini/crostini_export_import_status_tracker.cc
@@ -18,7 +18,8 @@ base::FilePath path) : type_(type), path_(path) { DCHECK(type == ExportImportType::EXPORT || type == ExportImportType::IMPORT || - type == ExportImportType::EXPORT_DISK_IMAGE); + type == ExportImportType::EXPORT_DISK_IMAGE || + type == ExportImportType::IMPORT_DISK_IMAGE); } CrostiniExportImportStatusTracker::~CrostiniExportImportStatusTracker() =
diff --git a/chrome/browser/ash/crostini/crostini_export_import_unittest.cc b/chrome/browser/ash/crostini/crostini_export_import_unittest.cc index 550f9329..e65b5a3 100644 --- a/chrome/browser/ash/crostini/crostini_export_import_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_export_import_unittest.cc
@@ -28,6 +28,7 @@ #include "chromeos/ash/components/dbus/seneschal/fake_seneschal_client.h" #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h" #include "chromeos/ash/components/dbus/seneschal/seneschal_service.pb.h" +#include "chromeos/ash/components/dbus/vm_concierge/concierge_service.pb.h" #include "components/prefs/pref_service.h" #include "content/public/test/browser_task_environment.h" #include "storage/browser/file_system/external_mount_points.h" @@ -120,6 +121,12 @@ ash::FakeConciergeClient::Get()->NotifyDiskImageProgress(signal); } + void SetImportResponse() { + vm_tools::concierge::ImportDiskImageResponse response; + response.set_status(vm_tools::concierge::DISK_STATUS_IN_PROGRESS); + ash::FakeConciergeClient::Get()->set_import_disk_image_response(response); + } + void SendImportProgress( const guest_os::GuestId& container_id, vm_tools::cicerone::ImportLxdContainerProgressSignal_Status status, @@ -398,6 +405,176 @@ } } +TEST_F(CrostiniExportImportTest, TestImportDiskImageSuccess) { + SetImportResponse(); + crostini_export_import_->FillOperationData( + ExportImportType::IMPORT_DISK_IMAGE); + base::ScopedTempFile zipfile; + EXPECT_TRUE(zipfile.Create()); + crostini_export_import_->FileSelected(ui::SelectedFileInfo(zipfile.path()), + 0); + task_environment_.RunUntilIdle(); + base::WeakPtr<CrostiniExportImportNotificationController> controller = + GetController(default_container_id_); + ASSERT_NE(controller, nullptr); + EXPECT_EQ(controller->status(), + CrostiniExportImportStatusTracker::Status::RUNNING); + + std::string notification_id; + { + const message_center::Notification& notification = + GetNotification(default_container_id_); + notification_id = notification.id(); + EXPECT_EQ(notification.progress(), 0); + EXPECT_TRUE(notification.pinned()); + } + + // 50% done. + SendDiskImageProgress(default_container_id_, + vm_tools::concierge::DISK_STATUS_IN_PROGRESS, 50); + ASSERT_NE(controller, nullptr); + EXPECT_EQ(controller->status(), + CrostiniExportImportStatusTracker::Status::RUNNING); + { + const message_center::Notification& notification = + GetNotification(default_container_id_); + EXPECT_EQ(notification.id(), notification_id); + EXPECT_EQ(notification.progress(), 50); + EXPECT_TRUE(notification.pinned()); + } + + // Close notification and update progress. Should not update notification. + controller->get_delegate()->Close(false); + SendDiskImageProgress(default_container_id_, + vm_tools::concierge::DISK_STATUS_IN_PROGRESS, 60); + ASSERT_NE(controller, nullptr); + EXPECT_EQ(controller->status(), + CrostiniExportImportStatusTracker::Status::RUNNING); + { + const message_center::Notification& notification = + GetNotification(default_container_id_); + EXPECT_EQ(notification.id(), notification_id); + EXPECT_EQ(notification.progress(), 50); + EXPECT_TRUE(notification.pinned()); + } + + // Done. + SendDiskImageProgress(default_container_id_, + vm_tools::concierge::DISK_STATUS_CREATED, 100); + EXPECT_EQ(GetController(default_container_id_), nullptr); + EXPECT_EQ(controller, nullptr); + { + const std::optional<message_center::Notification> ui_notification = + notification_display_service_->GetNotification(notification_id); + ASSERT_NE(ui_notification, std::nullopt); + EXPECT_FALSE(ui_notification->pinned()); + std::string msg("Linux apps & files have been successfully replaced"); + EXPECT_EQ(ui_notification->message(), base::UTF8ToUTF16(msg)); + } +} + +TEST_F(CrostiniExportImportTest, TestImportDiskImageFail) { + SetImportResponse(); + crostini_export_import_->FillOperationData( + ExportImportType::IMPORT_DISK_IMAGE); + base::ScopedTempFile zipfile; + EXPECT_TRUE(zipfile.Create()); + crostini_export_import_->FileSelected(ui::SelectedFileInfo(zipfile.path()), + 0); + task_environment_.RunUntilIdle(); + base::WeakPtr<CrostiniExportImportNotificationController> controller = + GetController(default_container_id_); + ASSERT_NE(controller, nullptr); + EXPECT_EQ(controller->status(), + CrostiniExportImportStatusTracker::Status::RUNNING); + + std::string notification_id; + { + const message_center::Notification& notification = + GetNotification(default_container_id_); + notification_id = notification.id(); + EXPECT_EQ(notification.progress(), 0); + EXPECT_TRUE(notification.pinned()); + } + + // Fails. + SendDiskImageProgress(default_container_id_, + vm_tools::concierge::DISK_STATUS_FAILED, 0); + EXPECT_EQ(GetController(default_container_id_), nullptr); + EXPECT_EQ(controller, nullptr); + { + const std::optional<message_center::Notification> ui_notification = + notification_display_service_->GetNotification(notification_id); + ASSERT_NE(ui_notification, std::nullopt); + EXPECT_FALSE(ui_notification->pinned()); + std::string msg("Restoring couldn't be completed due to an error"); + EXPECT_EQ(ui_notification->message(), base::UTF8ToUTF16(msg)); + } +} + +TEST_F(CrostiniExportImportTest, TestImportDiskImageCancelled) { + SetImportResponse(); + base::ScopedTempFile zipfile; + EXPECT_TRUE(zipfile.Create()); + crostini_export_import_->FillOperationData( + ExportImportType::IMPORT_DISK_IMAGE, custom_container_id_); + crostini_export_import_->FileSelected(ui::SelectedFileInfo(zipfile.path()), + 0); + task_environment_.RunUntilIdle(); + base::WeakPtr<CrostiniExportImportNotificationController> controller = + GetController(custom_container_id_); + ASSERT_NE(controller, nullptr); + EXPECT_EQ(controller->status(), + CrostiniExportImportStatusTracker::Status::RUNNING); + + std::string notification_id; + { + const message_center::Notification& notification = + GetNotification(custom_container_id_); + notification_id = notification.id(); + EXPECT_EQ(notification.progress(), 0); + EXPECT_TRUE(notification.pinned()); + } + + // CANCEL: + crostini_export_import_->CancelOperation(ExportImportType::IMPORT_DISK_IMAGE, + custom_container_id_); + ASSERT_NE(controller, nullptr); + EXPECT_EQ(controller->status(), + CrostiniExportImportStatusTracker::Status::CANCELLING); + { + const message_center::Notification& notification = + GetNotification(custom_container_id_); + EXPECT_EQ(notification.id(), notification_id); + EXPECT_EQ(notification.progress(), -1); + EXPECT_FALSE(notification.pinned()); + } + + // Should not be displayed as cancel is in progress + SendDiskImageProgress(default_container_id_, + vm_tools::concierge::DISK_STATUS_IN_PROGRESS, 7); + ASSERT_NE(controller, nullptr); + EXPECT_EQ(controller->status(), + CrostiniExportImportStatusTracker::Status::CANCELLING); + { + const message_center::Notification& notification = + GetNotification(custom_container_id_); + EXPECT_EQ(notification.id(), notification_id); + EXPECT_EQ(notification.progress(), -1); + EXPECT_FALSE(notification.pinned()); + } + + // CANCELLED: + task_environment_.RunUntilIdle(); + EXPECT_EQ(GetController(custom_container_id_), nullptr); + EXPECT_EQ(controller, nullptr); + { + const std::optional<message_center::Notification> ui_notification = + notification_display_service_->GetNotification(notification_id); + EXPECT_EQ(ui_notification, std::nullopt); + } +} + TEST_F(CrostiniExportImportTest, TestExportSuccess) { crostini_export_import_->FillOperationData(ExportImportType::EXPORT); crostini_export_import_->FileSelected(ui::SelectedFileInfo(tarball_), 0);
diff --git a/chrome/browser/ash/crostini/crostini_manager.cc b/chrome/browser/ash/crostini/crostini_manager.cc index c3257e6c..8b237708 100644 --- a/chrome/browser/ash/crostini/crostini_manager.cc +++ b/chrome/browser/ash/crostini/crostini_manager.cc
@@ -1867,13 +1867,13 @@ return; } if (user_id_hash.empty()) { - LOG(ERROR) << "vm_name is required"; + LOG(ERROR) << "user_id_hash is required"; std::move(callback).Run(CrostiniResult::CLIENT_ERROR); return; } if (disk_image_callbacks_.find(vm_id) != disk_image_callbacks_.end()) { - LOG(ERROR) << "Disk image export currently running for " << vm_id; + LOG(ERROR) << "Disk image operation currently running for " << vm_id; std::move(callback).Run(CrostiniResult::DISK_IMAGE_FAILED); } disk_image_callbacks_.emplace(vm_id, std::move(callback)); @@ -1930,6 +1930,76 @@ disk_image_uuid_to_guest_id_.emplace(response->command_uuid(), vm_id); } +void CrostiniManager::ImportDiskImage(guest_os::GuestId vm_id, + std::string user_id_hash, + base::FilePath import_path, + CrostiniResultCallback callback) { + if (vm_id.vm_name.empty()) { + LOG(ERROR) << "vm_name is required"; + std::move(callback).Run(CrostiniResult::CLIENT_ERROR); + return; + } + if (user_id_hash.empty()) { + LOG(ERROR) << "user_id_hash is required"; + std::move(callback).Run(CrostiniResult::CLIENT_ERROR); + return; + } + + if (disk_image_callbacks_.find(vm_id) != disk_image_callbacks_.end()) { + LOG(ERROR) << "Disk image operation currently running for " << vm_id; + std::move(callback).Run(CrostiniResult::DISK_IMAGE_FAILED); + } + disk_image_callbacks_.emplace(vm_id, std::move(callback)); + + base::File file(import_path, base::File::FLAG_OPEN | base::File::FLAG_READ); + if (!file.IsValid()) { + LOG(ERROR) << "Failed to open " << import_path; + return; + } + + vm_tools::concierge::ImportDiskImageRequest request; + request.set_vm_name(vm_id.vm_name); + request.set_cryptohome_id(user_id_hash); + // All vm's are stored in root except pluginvm, which is not supported in this + // flow. + request.set_storage_location(vm_tools::concierge::STORAGE_CRYPTOHOME_ROOT); + request.set_source_size(file.GetLength()); + + GetConciergeClient()->ImportDiskImage( + base::ScopedFD(file.TakePlatformFile()), std::move(request), + base::BindOnce(&CrostiniManager::OnImportDiskImage, + weak_ptr_factory_.GetWeakPtr(), vm_id)); +} + +void CrostiniManager::OnImportDiskImage( + guest_os::GuestId vm_id, + std::optional<vm_tools::concierge::ImportDiskImageResponse> response) { + auto it = disk_image_callbacks_.find(vm_id); + if (it == disk_image_callbacks_.end()) { + LOG(ERROR) << "No import callback for " << vm_id; + return; + } + + if (!response) { + LOG(ERROR) << "Failed to import disk image. Empty response."; + std::move(it->second).Run(CrostiniResult::DISK_IMAGE_FAILED); + disk_image_callbacks_.erase(it); + return; + } + + // If import has started, the callback will be invoked when the + // DiskImageProgressSignal signal indicates that import is + // complete, otherwise this is an error. + if (response->status() != vm_tools::concierge::DISK_STATUS_IN_PROGRESS) { + LOG(ERROR) << "Failed to import image: status=" << response->status() + << ", failure_reason=" << response->failure_reason(); + std::move(it->second).Run(CrostiniResult::DISK_IMAGE_FAILED); + disk_image_callbacks_.erase(it); + } + + disk_image_uuid_to_guest_id_.emplace(response->command_uuid(), vm_id); +} + void CrostiniManager::OnDiskImageProgress( const vm_tools::concierge::DiskImageStatusResponse& signal) { bool call_observers = false;
diff --git a/chrome/browser/ash/crostini/crostini_manager.h b/chrome/browser/ash/crostini/crostini_manager.h index 01807b75..b7aaa86 100644 --- a/chrome/browser/ash/crostini/crostini_manager.h +++ b/chrome/browser/ash/crostini/crostini_manager.h
@@ -335,6 +335,15 @@ bool force, CrostiniResultCallback callback); + // Checks the arguments for exporting a vm disk image via + // ConciergeClient::ImportDiskImage. |callback| is called immedaitely if the + // arguments are bad, or after the method call finishes. + // using DiskImageCallback = base::OnceCallback<void(CrostiniResult result)>; + void ImportDiskImage(guest_os::GuestId vm_id, + std::string user_id_hash, + base::FilePath import_path, + CrostiniResultCallback callback); + // Checks the arguments for exporting an Lxd container via // CiceroneClient::ExportLxdContainer. |callback| is called immediately if the // arguments are bad, or after the method call finishes. @@ -704,6 +713,12 @@ guest_os::GuestId vm_id, std::optional<vm_tools::concierge::ExportDiskImageResponse> response); + // Callback for ConciergeClient::ImportDiskImage. Called after the Concierge + // service method finishes. + void OnImportDiskImage( + guest_os::GuestId vm_id, + std::optional<vm_tools::concierge::ImportDiskImageResponse> response); + // Callback for CiceroneClient::CreateLxdContainer. May indicate the container // is still being created, in which case we will wait for an // OnLxdContainerCreated event.
diff --git a/chrome/browser/ash/crostini/crostini_manager_unittest.cc b/chrome/browser/ash/crostini/crostini_manager_unittest.cc index e7ce53a..336de0eb 100644 --- a/chrome/browser/ash/crostini/crostini_manager_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_manager_unittest.cc
@@ -2067,6 +2067,80 @@ EXPECT_EQ(result_future.Get<0>(), CrostiniResult::SUCCESS); } +TEST_F(CrostiniManagerTest, ImportDiskImageFailure) { + base::ScopedTempFile import_path; + EXPECT_TRUE(import_path.Create()); + TestFuture<CrostiniResult> result_future; + EXPECT_EQ(fake_concierge_client_->import_disk_image_call_count(), 0); + + vm_tools::concierge::ImportDiskImageResponse failure_response; + failure_response.set_status(vm_tools::concierge::DISK_STATUS_FAILED); + fake_concierge_client_->set_import_disk_image_response(failure_response); + + crostini_manager()->ImportDiskImage(container_id(), "my_cool_user_id_hash", + import_path.path(), + result_future.GetCallback()); + + EXPECT_EQ(fake_concierge_client_->import_disk_image_call_count(), 1); + EXPECT_EQ(result_future.Get<0>(), CrostiniResult::DISK_IMAGE_FAILED); +} + +TEST_F(CrostiniManagerTest, ImportDiskImageNoSpaceFailure) { + base::ScopedTempFile import_path; + EXPECT_TRUE(import_path.Create()); + TestFuture<CrostiniResult> result_future; + EXPECT_EQ(fake_concierge_client_->import_disk_image_call_count(), 0); + + vm_tools::concierge::DiskImageStatusResponse progress_signal; + progress_signal.set_status(vm_tools::concierge::DISK_STATUS_IN_PROGRESS); + progress_signal.set_progress(50); + vm_tools::concierge::DiskImageStatusResponse no_space_signal; + no_space_signal.set_status(vm_tools::concierge::DISK_STATUS_NOT_ENOUGH_SPACE); + std::vector<vm_tools::concierge::DiskImageStatusResponse> signals; + signals.emplace_back(progress_signal); + signals.emplace_back(no_space_signal); + fake_concierge_client_->set_disk_image_status_signals(signals); + + vm_tools::concierge::ImportDiskImageResponse response; + response.set_status(vm_tools::concierge::DISK_STATUS_IN_PROGRESS); + ash::FakeConciergeClient::Get()->set_import_disk_image_response(response); + + crostini_manager()->ImportDiskImage(container_id(), "my_cool_user_id_hash", + import_path.path(), + result_future.GetCallback()); + + EXPECT_EQ(fake_concierge_client_->import_disk_image_call_count(), 1); + EXPECT_EQ(result_future.Get<0>(), CrostiniResult::DISK_IMAGE_FAILED_NO_SPACE); +} + +TEST_F(CrostiniManagerTest, ImportDiskImageSuccess) { + base::ScopedTempFile import_path; + EXPECT_TRUE(import_path.Create()); + TestFuture<CrostiniResult> result_future; + EXPECT_EQ(fake_concierge_client_->import_disk_image_call_count(), 0); + + vm_tools::concierge::DiskImageStatusResponse progress_signal; + progress_signal.set_status(vm_tools::concierge::DISK_STATUS_IN_PROGRESS); + progress_signal.set_progress(50); + vm_tools::concierge::DiskImageStatusResponse done_signal; + done_signal.set_status(vm_tools::concierge::DISK_STATUS_CREATED); + std::vector<vm_tools::concierge::DiskImageStatusResponse> signals; + signals.emplace_back(progress_signal); + signals.emplace_back(done_signal); + fake_concierge_client_->set_disk_image_status_signals(signals); + + vm_tools::concierge::ImportDiskImageResponse response; + response.set_status(vm_tools::concierge::DISK_STATUS_IN_PROGRESS); + ash::FakeConciergeClient::Get()->set_import_disk_image_response(response); + + crostini_manager()->ImportDiskImage(container_id(), "my_cool_user_id_hash", + import_path.path(), + result_future.GetCallback()); + + EXPECT_EQ(fake_concierge_client_->import_disk_image_call_count(), 1); + EXPECT_EQ(result_future.Get<0>(), CrostiniResult::SUCCESS); +} + TEST_F(CrostiniManagerTest, ExportContainerSuccess) { uint64_t container_size = 123; uint64_t exported_size = 456;
diff --git a/chrome/browser/autofill/android/BUILD.gn b/chrome/browser/autofill/android/BUILD.gn index d558bd2..144a0ae 100644 --- a/chrome/browser/autofill/android/BUILD.gn +++ b/chrome/browser/autofill/android/BUILD.gn
@@ -29,6 +29,7 @@ "java/src/org/chromium/chrome/browser/autofill/editors/AddressEditorMediator.java", "java/src/org/chromium/chrome/browser/autofill/editors/DropdownFieldAdapter.java", "java/src/org/chromium/chrome/browser/autofill/editors/DropdownFieldView.java", + "java/src/org/chromium/chrome/browser/autofill/editors/EditTextNoAutofillView.java", "java/src/org/chromium/chrome/browser/autofill/editors/EditorBase.java", "java/src/org/chromium/chrome/browser/autofill/editors/EditorDialogToolbar.java", "java/src/org/chromium/chrome/browser/autofill/editors/EditorDialogView.java",
diff --git a/chrome/browser/autofill/android/java/res/layout/autofill_local_card_editor.xml b/chrome/browser/autofill/android/java/res/layout/autofill_local_card_editor.xml index 32f9774..cf09bbd 100644 --- a/chrome/browser/autofill/android/java/res/layout/autofill_local_card_editor.xml +++ b/chrome/browser/autofill/android/java/res/layout/autofill_local_card_editor.xml
@@ -21,7 +21,7 @@ app:errorTextAppearance="@style/TextAppearance.ErrorCaption"> <!-- TODO(crbug.com/40600572): Fix and remove lint ignore --> - <EditText + <org.chromium.chrome.browser.autofill.editors.EditTextNoAutofillView tools:ignore="Autofill,LabelFor" android:id="@+id/credit_card_number_edit" android:layout_width="match_parent" @@ -115,7 +115,7 @@ android:textAppearance="@style/TextAppearance.TextSmall.Secondary" android:text="@string/autofill_credit_card_editor_expiration_date" /> - <EditText + <org.chromium.chrome.browser.autofill.editors.EditTextNoAutofillView android:id="@+id/expiration_month_and_year" android:width="@dimen/local_card_expiration_date_editor_width" android:layout_width="match_parent" @@ -149,7 +149,7 @@ android:textAppearance="@style/TextAppearance.TextSmall.Secondary" android:text="@string/autofill_credit_card_editor_security_code" /> - <EditText + <org.chromium.chrome.browser.autofill.editors.EditTextNoAutofillView android:id="@+id/cvc" android:width="@dimen/local_card_cvc_editor_width" android:layout_width="match_parent" @@ -186,7 +186,7 @@ android:layout_marginBottom="@dimen/pref_autofill_field_bottom_margin"> <!-- TODO(crbug.com/40600572): Fix and remove lint ignore --> - <EditText + <org.chromium.chrome.browser.autofill.editors.EditTextNoAutofillView tools:ignore="Autofill,LabelFor" android:id="@+id/credit_card_name_edit" android:layout_width="match_parent" @@ -211,7 +211,7 @@ android:layout_marginTop="@dimen/pref_autofill_field_extra_large_top_margin" android:layout_marginBottom="@dimen/pref_autofill_field_bottom_margin"> - <EditText + <org.chromium.chrome.browser.autofill.editors.EditTextNoAutofillView tools:ignore="Autofill,LabelFor" android:id="@+id/credit_card_nickname_edit" android:maxLength="25"
diff --git a/chrome/browser/autofill/android/java/res/layout/autofill_local_iban_editor.xml b/chrome/browser/autofill/android/java/res/layout/autofill_local_iban_editor.xml index 0585be1e..508b1627 100644 --- a/chrome/browser/autofill/android/java/res/layout/autofill_local_iban_editor.xml +++ b/chrome/browser/autofill/android/java/res/layout/autofill_local_iban_editor.xml
@@ -20,7 +20,7 @@ android:layout_marginBottom="@dimen/pref_autofill_field_bottom_margin" app:errorTextAppearance="@style/TextAppearance.ErrorCaption"> - <EditText + <org.chromium.chrome.browser.autofill.editors.EditTextNoAutofillView tools:ignore="Autofill,LabelFor" android:id="@+id/iban_value_edit" android:layout_width="match_parent" @@ -44,7 +44,7 @@ android:layout_marginTop="@dimen/pref_autofill_field_extra_large_top_margin" android:layout_marginBottom="@dimen/pref_autofill_field_bottom_margin"> - <EditText + <org.chromium.chrome.browser.autofill.editors.EditTextNoAutofillView tools:ignore="Autofill,LabelFor" android:id="@+id/iban_nickname_edit" android:maxLength="25"
diff --git a/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java index d4e7338..e124550 100644 --- a/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java +++ b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java
@@ -829,26 +829,7 @@ public static String getBasicCardIssuerNetwork(String cardNumber, boolean emptyIfInvalid) { ThreadUtils.assertOnUiThread(); - return PersonalDataManagerJni.get() - .getBasicCardIssuerNetwork( - cardNumber, - emptyIfInvalid); - } - - public void addServerCreditCardForTest(CreditCard card) { - ThreadUtils.assertOnUiThread(); - assert !card.getIsLocal(); - PersonalDataManagerJni.get() - .addServerCreditCardForTest(mPersonalDataManagerAndroid, card); // IN-TEST - } - - public void addServerCreditCardForTestWithAdditionalFields( - CreditCard card, String nickname, int cardIssuer) { - ThreadUtils.assertOnUiThread(); - assert !card.getIsLocal(); - PersonalDataManagerJni.get() - .addServerCreditCardForTestWithAdditionalFields( - mPersonalDataManagerAndroid, card, nickname, cardIssuer); + return PersonalDataManagerJni.get().getBasicCardIssuerNetwork(cardNumber, emptyIfInvalid); } public void deleteCreditCard(String guid) { @@ -920,12 +901,6 @@ return PersonalDataManagerJni.get().getMaskedBankAccounts(mPersonalDataManagerAndroid); } - public void addMaskedBankAccountForTest(BankAccount bankAccount) { - ThreadUtils.assertOnUiThread(); - PersonalDataManagerJni.get() - .addMaskedBankAccountForTest(mPersonalDataManagerAndroid, bankAccount); - } - /** * Records the use of the profile associated with the specified {@code guid}. Effectively * increments the use count of the profile and sets its use date to the current time. Also logs @@ -938,25 +913,6 @@ PersonalDataManagerJni.get().recordAndLogProfileUse(mPersonalDataManagerAndroid, guid); } - protected void setProfileUseStatsForTesting(String guid, int count, int daysSinceLastUsed) { - ThreadUtils.assertOnUiThread(); - PersonalDataManagerJni.get() - .setProfileUseStatsForTesting( - mPersonalDataManagerAndroid, guid, count, daysSinceLastUsed); - } - - int getProfileUseCountForTesting(String guid) { - ThreadUtils.assertOnUiThread(); - return PersonalDataManagerJni.get() - .getProfileUseCountForTesting(mPersonalDataManagerAndroid, guid); // IN-TEST - } - - long getProfileUseDateForTesting(String guid) { - ThreadUtils.assertOnUiThread(); - return PersonalDataManagerJni.get() - .getProfileUseDateForTesting(mPersonalDataManagerAndroid, guid); // IN-TEST - } - /** * Records the use of the credit card associated with the specified {@code guid}. Effectively * increments the use count of the credit card and set its use date to the current time. Also @@ -969,44 +925,6 @@ PersonalDataManagerJni.get().recordAndLogCreditCardUse(mPersonalDataManagerAndroid, guid); } - protected void setCreditCardUseStatsForTesting(String guid, int count, int daysSinceLastUsed) { - ThreadUtils.assertOnUiThread(); - PersonalDataManagerJni.get() - .setCreditCardUseStatsForTesting( - mPersonalDataManagerAndroid, guid, count, daysSinceLastUsed); - } - - int getCreditCardUseCountForTesting(String guid) { - ThreadUtils.assertOnUiThread(); - return PersonalDataManagerJni.get() - .getCreditCardUseCountForTesting(mPersonalDataManagerAndroid, guid); // IN-TEST - } - - long getCreditCardUseDateForTesting(String guid) { - ThreadUtils.assertOnUiThread(); - return PersonalDataManagerJni.get() - .getCreditCardUseDateForTesting(mPersonalDataManagerAndroid, guid); // IN-TEST - } - - long getCurrentDateForTesting() { - ThreadUtils.assertOnUiThread(); - return PersonalDataManagerJni.get() - .getCurrentDateForTesting(mPersonalDataManagerAndroid); // IN-TEST - } - - long getDateNDaysAgoForTesting(int days) { - ThreadUtils.assertOnUiThread(); - return PersonalDataManagerJni.get() - .getDateNDaysAgoForTesting( // IN-TEST - mPersonalDataManagerAndroid, days); - } - - protected void clearServerDataForTesting() { - ThreadUtils.assertOnUiThread(); - PersonalDataManagerJni.get() - .clearServerDataForTesting(mPersonalDataManagerAndroid); // IN-TEST - } - protected void clearImageDataForTesting() { if (mImageFetcher == null) { return; @@ -1189,10 +1107,6 @@ .isAutofillCreditCardManaged(mPersonalDataManagerAndroid); } - public void setSyncServiceForTesting() { - PersonalDataManagerJni.get().setSyncServiceForTesting(mPersonalDataManagerAndroid); - } - private void fetchCreditCardArtImages() { mImageFetcher.prefetchImages( getCreditCardsToSuggest().stream() @@ -1291,55 +1205,16 @@ String setCreditCard(long nativePersonalDataManagerAndroid, CreditCard card); - long getDateNDaysAgoForTesting(long nativePersonalDataManagerAndroid, int days); // IN-TEST - void updateServerCardBillingAddress(long nativePersonalDataManagerAndroid, CreditCard card); String getBasicCardIssuerNetwork(String cardNumber, boolean emptyIfInvalid); - void addServerCreditCardForTest( - long nativePersonalDataManagerAndroid, CreditCard card); // IN-TEST - - void addServerCreditCardForTestWithAdditionalFields( - long nativePersonalDataManagerAndroid, - CreditCard card, - String nickname, - int cardIssuer); - void removeByGUID(long nativePersonalDataManagerAndroid, String guid); void recordAndLogProfileUse(long nativePersonalDataManagerAndroid, String guid); - void setProfileUseStatsForTesting( - long nativePersonalDataManagerAndroid, - String guid, - int count, - int daysSinceLastUsed); - - int getProfileUseCountForTesting( - long nativePersonalDataManagerAndroid, String guid); // IN-TEST - - long getProfileUseDateForTesting( - long nativePersonalDataManagerAndroid, String guid); // IN-TEST - void recordAndLogCreditCardUse(long nativePersonalDataManagerAndroid, String guid); - void setCreditCardUseStatsForTesting( - long nativePersonalDataManagerAndroid, - String guid, - int count, - int daysSinceLastUsed); - - int getCreditCardUseCountForTesting( - long nativePersonalDataManagerAndroid, String guid); // IN-TEST - - long getCreditCardUseDateForTesting( - long nativePersonalDataManagerAndroid, String guid); // IN-TEST - - long getCurrentDateForTesting(long nativePersonalDataManagerAndroid); // IN-TEST - - void clearServerDataForTesting(long nativePersonalDataManagerAndroid); // IN-TEST - boolean hasProfiles(long nativePersonalDataManagerAndroid); boolean hasCreditCards(long nativePersonalDataManagerAndroid); @@ -1354,8 +1229,6 @@ String toCountryCode(String countryName); - void setSyncServiceForTesting(long nativePersonalDataManagerAndroid); - AutofillImageFetcher getOrCreateJavaImageFetcher(long nativePersonalDataManagerAndroid); void addServerIbanForTest(long nativePersonalDataManagerAndroid, Iban iban); // IN-TEST @@ -1369,8 +1242,5 @@ boolean isValidIban(long nativePersonalDataManagerAndroid, String ibanValue); BankAccount[] getMaskedBankAccounts(long nativePersonalDataManagerAndroid); - - void addMaskedBankAccountForTest( - long nativePersonalDataManagerAndroid, BankAccount bankAccount); // IN-TEST } }
diff --git a/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/editors/EditTextNoAutofillView.java b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/editors/EditTextNoAutofillView.java new file mode 100644 index 0000000..4ff47d7 --- /dev/null +++ b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/editors/EditTextNoAutofillView.java
@@ -0,0 +1,24 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.autofill.editors; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.ViewStructure; +import android.widget.EditText; + +/** + * A wrapper class around {@link EditText} to stop Android Autofill from suggesting cards. This is + * achieved by overriding the {@code onProvideAutofillStructure} method. + */ +public class EditTextNoAutofillView extends EditText { + + public EditTextNoAutofillView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void onProvideAutofillStructure(ViewStructure structure, int flags) {} +}
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.cc b/chrome/browser/autofill/android/personal_data_manager_android.cc index ccbfda9..bb391bf 100644 --- a/chrome/browser/autofill/android/personal_data_manager_android.cc +++ b/chrome/browser/autofill/android/personal_data_manager_android.cc
@@ -390,32 +390,6 @@ {card}); } -void PersonalDataManagerAndroid::AddServerCreditCardForTest( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcard) { - std::unique_ptr<CreditCard> card = std::make_unique<CreditCard>(); - PopulateNativeCreditCardFromJava(jcard, env, card.get()); - card->set_record_type(CreditCard::RecordType::kMaskedServerCard); - personal_data_manager_->payments_data_manager().AddServerCreditCardForTest( - std::move(card)); - personal_data_manager_->NotifyPersonalDataObserver(); -} - -void PersonalDataManagerAndroid::AddServerCreditCardForTestWithAdditionalFields( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcard, - const base::android::JavaParamRef<jstring>& jnickname, - jint jcard_issuer) { - std::unique_ptr<CreditCard> card = std::make_unique<CreditCard>(); - PopulateNativeCreditCardFromJava(jcard, env, card.get()); - card->set_record_type(CreditCard::RecordType::kMaskedServerCard); - card->SetNickname(ConvertJavaStringToUTF16(jnickname)); - card->set_card_issuer(static_cast<CreditCard::Issuer>(jcard_issuer)); - personal_data_manager_->payments_data_manager().AddServerCreditCardForTest( - std::move(card)); - personal_data_manager_->NotifyPersonalDataObserver(); -} - void PersonalDataManagerAndroid::RemoveByGUID( JNIEnv* env, const JavaParamRef<jstring>& jguid) { @@ -446,39 +420,6 @@ } } -void PersonalDataManagerAndroid::SetProfileUseStatsForTesting( - JNIEnv* env, - const JavaParamRef<jstring>& jguid, - jint count, - jint days_since_last_used) { - DCHECK(count >= 0 && days_since_last_used >= 0); - - AutofillProfile profile = - *personal_data_manager_->address_data_manager().GetProfileByGUID( - ConvertJavaStringToUTF8(env, jguid)); - profile.set_use_count(static_cast<size_t>(count)); - profile.set_use_date(AutofillClock::Now() - base::Days(days_since_last_used)); - personal_data_manager_->address_data_manager().UpdateProfile(profile); -} - -jint PersonalDataManagerAndroid::GetProfileUseCountForTesting( - JNIEnv* env, - const base::android::JavaParamRef<jstring>& jguid) { - const AutofillProfile* profile = - personal_data_manager_->address_data_manager().GetProfileByGUID( - ConvertJavaStringToUTF8(env, jguid)); - return profile->use_count(); -} - -jlong PersonalDataManagerAndroid::GetProfileUseDateForTesting( - JNIEnv* env, - const base::android::JavaParamRef<jstring>& jguid) { - const AutofillProfile* profile = - personal_data_manager_->address_data_manager().GetProfileByGUID( - ConvertJavaStringToUTF8(env, jguid)); - return profile->use_date().ToTimeT(); -} - void PersonalDataManagerAndroid::RecordAndLogCreditCardUse( JNIEnv* env, const JavaParamRef<jstring>& jguid) { @@ -490,57 +431,6 @@ } } -void PersonalDataManagerAndroid::SetCreditCardUseStatsForTesting( - JNIEnv* env, - const JavaParamRef<jstring>& jguid, - jint count, - jint days_since_last_used) { - DCHECK(count >= 0 && days_since_last_used >= 0); - - CreditCard* card = - personal_data_manager_->payments_data_manager().GetCreditCardByGUID( - ConvertJavaStringToUTF8(env, jguid)); - card->set_use_count(static_cast<size_t>(count)); - card->set_use_date(AutofillClock::Now() - base::Days(days_since_last_used)); - - personal_data_manager_->NotifyPersonalDataObserver(); -} - -jint PersonalDataManagerAndroid::GetCreditCardUseCountForTesting( - JNIEnv* env, - const base::android::JavaParamRef<jstring>& jguid) { - const CreditCard* card = - personal_data_manager_->payments_data_manager().GetCreditCardByGUID( - ConvertJavaStringToUTF8(env, jguid)); - return card->use_count(); -} - -jlong PersonalDataManagerAndroid::GetCreditCardUseDateForTesting( - JNIEnv* env, - const base::android::JavaParamRef<jstring>& jguid) { - const CreditCard* card = - personal_data_manager_->payments_data_manager().GetCreditCardByGUID( - ConvertJavaStringToUTF8(env, jguid)); - return card->use_date().ToTimeT(); -} - -// TODO(crbug.com/40477114): Use a mock clock for testing. -jlong PersonalDataManagerAndroid::GetCurrentDateForTesting(JNIEnv* env) { - return base::Time::Now().ToTimeT(); -} - -jlong PersonalDataManagerAndroid::GetDateNDaysAgoForTesting( - JNIEnv* env, - jint days) { - return (AutofillClock::Now() - base::Days(days)).ToTimeT(); -} - -void PersonalDataManagerAndroid::ClearServerDataForTesting(JNIEnv* env) { - personal_data_manager_->payments_data_manager() - .ClearAllServerDataForTesting(); // IN-TEST - personal_data_manager_->NotifyPersonalDataObserver(); -} - jboolean PersonalDataManagerAndroid::HasProfiles(JNIEnv* env) { return !personal_data_manager_->address_data_manager().GetProfiles().empty(); } @@ -562,11 +452,6 @@ return IsCreditCardFidoAuthenticationEnabled(); } -void PersonalDataManagerAndroid::SetSyncServiceForTesting(JNIEnv* env) { - personal_data_manager_->payments_data_manager().SetSyncingForTest( - true); // IN-TEST -} - base::android::ScopedJavaLocalRef<jobject> PersonalDataManagerAndroid::GetOrCreateJavaImageFetcher(JNIEnv* env) { return static_cast<AutofillImageFetcherImpl*>( @@ -851,16 +736,6 @@ type.obj()); } -void PersonalDataManagerAndroid::AddMaskedBankAccountForTest( - JNIEnv* env, - const JavaParamRef<jobject>& jbank_account) { - BankAccount bank_account = - CreateNativeBankAccountFromJava(env, jbank_account); - personal_data_manager_->payments_data_manager().AddMaskedBankAccountForTest( - bank_account); // IN-TEST - personal_data_manager_->NotifyPersonalDataObserver(); -} - jboolean PersonalDataManagerAndroid::IsAutofillManaged(JNIEnv* env) { return prefs::IsAutofillManaged(prefs_); }
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.h b/chrome/browser/autofill/android/personal_data_manager_android.h index 7d61499..10b744c 100644 --- a/chrome/browser/autofill/android/personal_data_manager_android.h +++ b/chrome/browser/autofill/android/personal_data_manager_android.h
@@ -160,19 +160,6 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>& jcard); - // Adds a server credit card. Used only in tests. - void AddServerCreditCardForTest( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcard); - - // Adds a server credit card and sets the additional fields, for example, - // card_issuer, nickname. Used only in tests. - void AddServerCreditCardForTestWithAdditionalFields( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcard, - const base::android::JavaParamRef<jstring>& jnickname, - jint jcard_issuer); - // Removes the profile or credit card represented by |jguid|. void RemoveByGUID(JNIEnv* env, const base::android::JavaParamRef<jstring>& jguid); @@ -193,29 +180,6 @@ JNIEnv* env, const base::android::JavaParamRef<jstring>& jguid); - // Sets the use count and number of days since last use of the profile - // associated to the `jguid`. Both `count` and `days_since_last_used` should - // be non-negative. `days_since_last_used` represents the numbers of days - // since the profile was last used. - void SetProfileUseStatsForTesting( - JNIEnv* env, - const base::android::JavaParamRef<jstring>& jguid, - jint count, - jint days_since_last_used); - - // Returns the use count of the profile associated to the |jguid|. - jint GetProfileUseCountForTesting( - JNIEnv* env, - const base::android::JavaParamRef<jstring>& jguid); - - // Returns the use date of the profile associated to the |jguid|. It - // represents an absolute point in coordinated universal time (UTC) - // represented as microseconds since the Windows epoch. For more details see - // the comment header in time.h. - jlong GetProfileUseDateForTesting( - JNIEnv* env, - const base::android::JavaParamRef<jstring>& jguid); - // Records the use and log usage metrics for the credit card associated with // the |jguid|. Increments the use count of the credit card and sets its use // date to the current time. @@ -223,44 +187,6 @@ JNIEnv* env, const base::android::JavaParamRef<jstring>& jguid); - // Sets the use count and number of days since last use of the credit card - // associated to the`jguid`. Both `count` and `days_since_last_used` should be - // non-negative. `days_since_last_used` represents the numbers of days since - // the card was last used. - void SetCreditCardUseStatsForTesting( - JNIEnv* env, - const base::android::JavaParamRef<jstring>& jguid, - jint count, - jint days_since_last_used); - - // Returns the use count of the credit card associated to the |jguid|. - jint GetCreditCardUseCountForTesting( - JNIEnv* env, - const base::android::JavaParamRef<jstring>& jguid); - - // Returns the use date of the credit card associated to the |jguid|. It - // represents an absolute point in coordinated universal time (UTC) - // represented as microseconds since the Windows epoch. For more details see - // the comment header in time.h. - jlong GetCreditCardUseDateForTesting( - JNIEnv* env, - const base::android::JavaParamRef<jstring>& jguid); - - // Returns the current date represented as an absolute point in coordinated - // universal time (UTC) represented as microseconds since the Unix epoch. For - // more details see the comment header in time.h - jlong GetCurrentDateForTesting(JNIEnv* env); - - // Calculates a point in time `days` days ago from the current - // time. Returns the result as an absolute point in coordinated universal time - // (UTC) represented as microseconds since the Windows epoch. - jlong GetDateNDaysAgoForTesting( - JNIEnv* env, - jint days); - - // Clears server profiles and cards, to be used in tests only. - void ClearServerDataForTesting(JNIEnv* env); - // Checks whether the Autofill PersonalDataManager has profiles. jboolean HasProfiles(JNIEnv* env); @@ -270,8 +196,6 @@ // Checks whether FIDO authentication is available. jboolean IsFidoAuthenticationAvailable(JNIEnv* env); - void SetSyncServiceForTesting(JNIEnv* env); - // Get Java AutofillImageFetcher. base::android::ScopedJavaLocalRef<jobject> GetOrCreateJavaImageFetcher( JNIEnv* env); @@ -325,24 +249,18 @@ base::android::ScopedJavaLocalRef<jobjectArray> GetMaskedBankAccounts( JNIEnv* env); - // Add a BankAccount object to the existing list of BankAccounts stored in - // PersonalDataManager. - void AddMaskedBankAccountForTest( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jbank_account); - // Create an object of Java BankAccount from native BankAccount. static base::android::ScopedJavaLocalRef<jobject> CreateJavaBankAccountFromNative(JNIEnv* env, const BankAccount& bank_account); - private: - ~PersonalDataManagerAndroid() override; - // Create an object of native BankAccount from Java BankAccount. static BankAccount CreateNativeBankAccountFromJava( JNIEnv* env, const base::android::JavaParamRef<jobject>& jbank_account); + private: + ~PersonalDataManagerAndroid() override; + // Returns the GUIDs of the |profiles| passed as parameter. base::android::ScopedJavaLocalRef<jobjectArray> GetProfileGUIDs( JNIEnv* env,
diff --git a/chrome/browser/autofill/test/BUILD.gn b/chrome/browser/autofill/test/BUILD.gn index f01aee0..b3f7b40 100644 --- a/chrome/browser/autofill/test/BUILD.gn +++ b/chrome/browser/autofill/test/BUILD.gn
@@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/config/android/rules.gni") +import("//third_party/jni_zero/jni_zero.gni") android_library("test_java") { testonly = true @@ -44,6 +45,7 @@ "//content/public/android:content_java", "//third_party/android_deps:espresso_java", "//third_party/hamcrest:hamcrest_java", + "//third_party/jni_zero:jni_zero_java", "//url:gurl_java", ] @@ -53,4 +55,24 @@ "//components/autofill/android:main_autofill_java", "//content/public/test/android:content_java_test_support", ] + + srcjar_deps = [ ":jni_headers" ] +} + +generate_jni("jni_headers") { + testonly = true + visibility = [ ":*" ] + sources = [ "android/java/src/org/chromium/chrome/browser/autofill/AutofillTestHelper.java" ] +} + +static_library("test_support") { + testonly = true + sources = [ "android/autofill_test_helper_android.cc" ] + deps = [ + ":jni_headers", + "//base", + "//chrome/browser", + "//chrome/browser/autofill", + "//components/autofill/core/browser", + ] }
diff --git a/chrome/browser/autofill/test/android/autofill_test_helper_android.cc b/chrome/browser/autofill/test/android/autofill_test_helper_android.cc new file mode 100644 index 0000000..89ea118 --- /dev/null +++ b/chrome/browser/autofill/test/android/autofill_test_helper_android.cc
@@ -0,0 +1,192 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <jni.h> + +#include <memory> + +#include "base/android/jni_string.h" +#include "base/android/scoped_java_ref.h" +#include "chrome/browser/autofill/android/personal_data_manager_android.h" +#include "chrome/browser/autofill/personal_data_manager_factory.h" +#include "chrome/browser/autofill/test/jni_headers/AutofillTestHelper_jni.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "components/autofill/core/browser/data_model/bank_account.h" +#include "components/autofill/core/browser/data_model/credit_card.h" +#include "components/autofill/core/browser/personal_data_manager.h" +#include "components/autofill/core/common/autofill_clock.h" + +namespace autofill { +namespace { + +using ::base::android::ConvertJavaStringToUTF16; +using ::base::android::ConvertJavaStringToUTF8; +using ::base::android::JavaParamRef; + +PersonalDataManager* GetPersonalDataManagerForLastUsedProfile() { + return PersonalDataManagerFactory::GetForBrowserContext( + ProfileManager::GetLastUsedProfile()); +} + +} // anonymous namespace + +// static +jlong JNI_AutofillTestHelper_GetDateNDaysAgo(JNIEnv* env, jint days) { + return (AutofillClock::Now() - base::Days(days)).ToTimeT(); +} + +// static +void JNI_AutofillTestHelper_AddServerCreditCard( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcard) { + std::unique_ptr<CreditCard> card = std::make_unique<CreditCard>(); + PersonalDataManagerAndroid::PopulateNativeCreditCardFromJava(jcard, env, + card.get()); + card->set_record_type(CreditCard::RecordType::kMaskedServerCard); + PersonalDataManager* personal_data_manager = + GetPersonalDataManagerForLastUsedProfile(); + personal_data_manager->payments_data_manager().AddServerCreditCardForTest( + std::move(card)); + personal_data_manager->NotifyPersonalDataObserver(); +} + +// static +void JNI_AutofillTestHelper_AddServerCreditCardWithAdditionalFields( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcard, + const base::android::JavaParamRef<jstring>& jnickname, + jint jcard_issuer) { + std::unique_ptr<CreditCard> card = std::make_unique<CreditCard>(); + PersonalDataManagerAndroid::PopulateNativeCreditCardFromJava(jcard, env, + card.get()); + card->set_record_type(CreditCard::RecordType::kMaskedServerCard); + card->SetNickname(ConvertJavaStringToUTF16(jnickname)); + card->set_card_issuer(static_cast<CreditCard::Issuer>(jcard_issuer)); + PersonalDataManager* personal_data_manager = + GetPersonalDataManagerForLastUsedProfile(); + personal_data_manager->payments_data_manager().AddServerCreditCardForTest( + std::move(card)); + personal_data_manager->NotifyPersonalDataObserver(); +} + +// static +void JNI_AutofillTestHelper_SetProfileUseStats( + JNIEnv* env, + const JavaParamRef<jstring>& jguid, + jint count, + jint days_since_last_used) { + DCHECK(count >= 0 && days_since_last_used >= 0); + + PersonalDataManager* personal_data_manager = + GetPersonalDataManagerForLastUsedProfile(); + AutofillProfile profile = + *personal_data_manager->address_data_manager().GetProfileByGUID( + ConvertJavaStringToUTF8(env, jguid)); + profile.set_use_count(static_cast<size_t>(count)); + profile.set_use_date(AutofillClock::Now() - base::Days(days_since_last_used)); + personal_data_manager->address_data_manager().UpdateProfile(profile); +} + +// static +jint JNI_AutofillTestHelper_GetProfileUseCount( + JNIEnv* env, + const base::android::JavaParamRef<jstring>& jguid) { + PersonalDataManager* personal_data_manager = + GetPersonalDataManagerForLastUsedProfile(); + const AutofillProfile* profile = + personal_data_manager->address_data_manager().GetProfileByGUID( + ConvertJavaStringToUTF8(env, jguid)); + return profile->use_count(); +} + +// static +jlong JNI_AutofillTestHelper_GetProfileUseDate( + JNIEnv* env, + const base::android::JavaParamRef<jstring>& jguid) { + PersonalDataManager* personal_data_manager = + GetPersonalDataManagerForLastUsedProfile(); + const AutofillProfile* profile = + personal_data_manager->address_data_manager().GetProfileByGUID( + ConvertJavaStringToUTF8(env, jguid)); + return profile->use_date().ToTimeT(); +} + +// static +void JNI_AutofillTestHelper_SetCreditCardUseStats( + JNIEnv* env, + const JavaParamRef<jstring>& jguid, + jint count, + jint days_since_last_used) { + DCHECK(count >= 0 && days_since_last_used >= 0); + + PersonalDataManager* personal_data_manager = + GetPersonalDataManagerForLastUsedProfile(); + CreditCard* card = + personal_data_manager->payments_data_manager().GetCreditCardByGUID( + ConvertJavaStringToUTF8(env, jguid)); + card->set_use_count(static_cast<size_t>(count)); + card->set_use_date(AutofillClock::Now() - base::Days(days_since_last_used)); + + personal_data_manager->NotifyPersonalDataObserver(); +} + +// static +jint JNI_AutofillTestHelper_GetCreditCardUseCount( + JNIEnv* env, + const base::android::JavaParamRef<jstring>& jguid) { + PersonalDataManager* personal_data_manager = + GetPersonalDataManagerForLastUsedProfile(); + const CreditCard* card = + personal_data_manager->payments_data_manager().GetCreditCardByGUID( + ConvertJavaStringToUTF8(env, jguid)); + return card->use_count(); +} + +// static +jlong JNI_AutofillTestHelper_GetCreditCardUseDate( + JNIEnv* env, + const base::android::JavaParamRef<jstring>& jguid) { + PersonalDataManager* personal_data_manager = + GetPersonalDataManagerForLastUsedProfile(); + const CreditCard* card = + personal_data_manager->payments_data_manager().GetCreditCardByGUID( + ConvertJavaStringToUTF8(env, jguid)); + return card->use_date().ToTimeT(); +} + +// TODO(crbug.com/40477114): Use a mock clock for testing. +jlong JNI_AutofillTestHelper_GetCurrentDate(JNIEnv* env) { + return base::Time::Now().ToTimeT(); +} + +// static +void JNI_AutofillTestHelper_ClearServerData(JNIEnv* env) { + PersonalDataManager* personal_data_manager = + GetPersonalDataManagerForLastUsedProfile(); + personal_data_manager->payments_data_manager().ClearAllServerDataForTesting(); + personal_data_manager->NotifyPersonalDataObserver(); +} + +// static +void JNI_AutofillTestHelper_SetSyncService(JNIEnv* env) { + GetPersonalDataManagerForLastUsedProfile() + ->payments_data_manager() + .SetSyncingForTest(true); +} + +// static +void JNI_AutofillTestHelper_AddMaskedBankAccount( + JNIEnv* env, + const JavaParamRef<jobject>& jbank_account) { + BankAccount bank_account = + PersonalDataManagerAndroid::CreateNativeBankAccountFromJava( + env, jbank_account); + PersonalDataManager* personal_data_manager = + GetPersonalDataManagerForLastUsedProfile(); + personal_data_manager->payments_data_manager().AddMaskedBankAccountForTest( + bank_account); + personal_data_manager->NotifyPersonalDataObserver(); +} + +} // namespace autofill
diff --git a/chrome/browser/autofill/test/android/java/src/org/chromium/chrome/browser/autofill/AutofillTestHelper.java b/chrome/browser/autofill/test/android/java/src/org/chromium/chrome/browser/autofill/AutofillTestHelper.java index 984725c3..1ab3dd6 100644 --- a/chrome/browser/autofill/test/android/java/src/org/chromium/chrome/browser/autofill/AutofillTestHelper.java +++ b/chrome/browser/autofill/test/android/java/src/org/chromium/chrome/browser/autofill/AutofillTestHelper.java
@@ -19,6 +19,8 @@ import androidx.test.espresso.util.HumanReadables; import org.hamcrest.Matcher; +import org.jni_zero.JNINamespace; +import org.jni_zero.NativeMethods; import org.chromium.base.test.util.CallbackHelper; import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard; @@ -39,6 +41,7 @@ import java.util.concurrent.TimeoutException; /** Helper class for testing AutofillProfiles. */ +@JNINamespace("autofill") public class AutofillTestHelper { private final CallbackHelper mOnPersonalDataChangedHelper = new CallbackHelper(); @@ -68,8 +71,7 @@ } void setSyncServiceForTesting() { - runOnUiThreadBlocking( - () -> getPersonalDataManagerForLastUsedProfile().setSyncServiceForTesting()); + runOnUiThreadBlocking(() -> AutofillTestHelperJni.get().setSyncService()); } AutofillProfile getProfile(final String guid) { @@ -146,8 +148,7 @@ public void addServerCreditCard(final CreditCard card) throws TimeoutException { int callCount = mOnPersonalDataChangedHelper.getCallCount(); - runOnUiThreadBlocking( - () -> getPersonalDataManagerForLastUsedProfile().addServerCreditCardForTest(card)); + runOnUiThreadBlocking(() -> AutofillTestHelperJni.get().addServerCreditCard(card)); mOnPersonalDataChangedHelper.waitForCallback(callCount); } @@ -156,8 +157,8 @@ int callCount = mOnPersonalDataChangedHelper.getCallCount(); runOnUiThreadBlocking( () -> - getPersonalDataManagerForLastUsedProfile() - .addServerCreditCardForTestWithAdditionalFields( + AutofillTestHelperJni.get() + .addServerCreditCardWithAdditionalFields( card, nickname, cardIssuer)); mOnPersonalDataChangedHelper.waitForCallback(callCount); } @@ -197,8 +198,8 @@ int callCount = mOnPersonalDataChangedHelper.getCallCount(); runOnUiThreadBlocking( () -> - getPersonalDataManagerForLastUsedProfile() - .setProfileUseStatsForTesting(guid, count, daysSinceLastUsed)); + AutofillTestHelperJni.get() + .setProfileUseStats(guid, count, daysSinceLastUsed)); mOnPersonalDataChangedHelper.waitForCallback(callCount); } @@ -209,10 +210,7 @@ * @return The non-negative use count of the profile. */ public int getProfileUseCountForTesting(final String guid) { - return runOnUiThreadBlocking( - () -> - getPersonalDataManagerForLastUsedProfile() - .getProfileUseCountForTesting(guid)); + return runOnUiThreadBlocking(() -> AutofillTestHelperJni.get().getProfileUseCount(guid)); } /** @@ -224,8 +222,7 @@ * Windows epoch. For more details see the comment header in time.h. */ public long getProfileUseDateForTesting(final String guid) { - return runOnUiThreadBlocking( - () -> getPersonalDataManagerForLastUsedProfile().getProfileUseDateForTesting(guid)); + return runOnUiThreadBlocking(() -> AutofillTestHelperJni.get().getProfileUseDate(guid)); } /** @@ -256,8 +253,8 @@ int callCount = mOnPersonalDataChangedHelper.getCallCount(); runOnUiThreadBlocking( () -> - getPersonalDataManagerForLastUsedProfile() - .setCreditCardUseStatsForTesting(guid, count, daysSinceLastUsed)); + AutofillTestHelperJni.get() + .setCreditCardUseStats(guid, count, daysSinceLastUsed)); mOnPersonalDataChangedHelper.waitForCallback(callCount); } @@ -268,10 +265,7 @@ * @return The non-negative use count of the credit card. */ public int getCreditCardUseCountForTesting(final String guid) { - return runOnUiThreadBlocking( - () -> - getPersonalDataManagerForLastUsedProfile() - .getCreditCardUseCountForTesting(guid)); + return runOnUiThreadBlocking(() -> AutofillTestHelperJni.get().getCreditCardUseCount(guid)); } /** @@ -283,10 +277,7 @@ * the Windows epoch. For more details see the comment header in time.h. */ public long getCreditCardUseDateForTesting(final String guid) { - return runOnUiThreadBlocking( - () -> - getPersonalDataManagerForLastUsedProfile() - .getCreditCardUseDateForTesting(guid)); + return runOnUiThreadBlocking(() -> AutofillTestHelperJni.get().getCreditCardUseDate(guid)); } /** @@ -297,8 +288,7 @@ * more details see the comment header in time.h. */ public long getCurrentDateForTesting() { - return runOnUiThreadBlocking( - () -> getPersonalDataManagerForLastUsedProfile().getCurrentDateForTesting()); + return runOnUiThreadBlocking(() -> AutofillTestHelperJni.get().getCurrentDate()); } /** @@ -310,8 +300,7 @@ * For more details see the comment header in time.h. */ public long getDateNDaysAgoForTesting(final int days) { - return runOnUiThreadBlocking( - () -> getPersonalDataManagerForLastUsedProfile().getDateNDaysAgoForTesting(days)); + return runOnUiThreadBlocking(() -> AutofillTestHelperJni.get().getDateNDaysAgo(days)); } public void addServerIban(final Iban iban) throws TimeoutException { @@ -347,8 +336,7 @@ * #addServerCreditCard(CreditCard)}}. */ public void clearAllDataForTesting() throws TimeoutException { - runOnUiThreadBlocking( - () -> getPersonalDataManagerForLastUsedProfile().clearServerDataForTesting()); + runOnUiThreadBlocking(() -> AutofillTestHelperJni.get().clearServerData()); runOnUiThreadBlocking( () -> getPersonalDataManagerForLastUsedProfile().clearImageDataForTesting()); // Clear remaining local profiles and cards. @@ -489,10 +477,7 @@ } public static void addMaskedBankAccount(BankAccount bankAccount) { - runOnUiThreadBlocking( - () -> - getPersonalDataManagerForLastUsedProfile() - .addMaskedBankAccountForTest(bankAccount)); + runOnUiThreadBlocking(() -> AutofillTestHelperJni.get().addMaskedBankAccount(bankAccount)); } private void registerDataObserver() { @@ -588,4 +573,34 @@ /* source= */ InputDevice.SOURCE_CLASS_POINTER, /* flags= */ flags); } + + @NativeMethods + interface Natives { + long getDateNDaysAgo(int days); + + void addServerCreditCard(CreditCard card); + + void addServerCreditCardWithAdditionalFields( + CreditCard card, String nickname, int cardIssuer); + + void setProfileUseStats(String guid, int count, int daysSinceLastUsed); + + int getProfileUseCount(String guid); + + long getProfileUseDate(String guid); + + void setCreditCardUseStats(String guid, int count, int daysSinceLastUsed); + + int getCreditCardUseCount(String guid); + + long getCreditCardUseDate(String guid); + + long getCurrentDate(); + + void clearServerData(); + + void setSyncService(); + + void addMaskedBankAccount(BankAccount bankAccount); + } }
diff --git a/chrome/browser/commerce/coupons/android/BUILD.gn b/chrome/browser/commerce/coupons/android/BUILD.gn index 816ac8c43..9c0efc7 100644 --- a/chrome/browser/commerce/coupons/android/BUILD.gn +++ b/chrome/browser/commerce/coupons/android/BUILD.gn
@@ -36,8 +36,12 @@ android_resources("java_resources") { sources = [ + "java/res/drawable/discount_code_background.xml", + "java/res/drawable/discount_item_container_background.xml", "java/res/layout/discount_item_container.xml", "java/res/layout/discounts_content_container.xml", + "java/res/values/dimens.xml", + "java/res/values/styles.xml", ] deps = [
diff --git a/chrome/browser/commerce/coupons/android/java/res/drawable/discount_code_background.xml b/chrome/browser/commerce/coupons/android/java/res/drawable/discount_code_background.xml new file mode 100644 index 0000000..1c412eb --- /dev/null +++ b/chrome/browser/commerce/coupons/android/java/res/drawable/discount_code_background.xml
@@ -0,0 +1,13 @@ +<?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. +--> + +<shape + xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <corners android:radius="@dimen/discount_code_background_radius"/> + <solid android:color="@color/price_drop_annotation_bg_color"/> +</shape> \ No newline at end of file
diff --git a/chrome/browser/commerce/coupons/android/java/res/drawable/discount_item_container_background.xml b/chrome/browser/commerce/coupons/android/java/res/drawable/discount_item_container_background.xml new file mode 100644 index 0000000..832b062 --- /dev/null +++ b/chrome/browser/commerce/coupons/android/java/res/drawable/discount_item_container_background.xml
@@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2024 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="@macro/default_bg_color"/> + <corners android:radius="@dimen/discount_item_container_background_radius" /> +</shape> \ No newline at end of file
diff --git a/chrome/browser/commerce/coupons/android/java/res/layout/discount_item_container.xml b/chrome/browser/commerce/coupons/android/java/res/layout/discount_item_container.xml index f108f8cf..0a95350 100644 --- a/chrome/browser/commerce/coupons/android/java/res/layout/discount_item_container.xml +++ b/chrome/browser/commerce/coupons/android/java/res/layout/discount_item_container.xml
@@ -9,7 +9,9 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height= "wrap_content" - android:orientation="horizontal"> + android:orientation="horizontal" + android:padding="@dimen/discount_item_container_padding" + android:background="@drawable/discount_item_container_background"> <!-- Discount content layout --> <LinearLayout @@ -20,13 +22,20 @@ <TextView android:id="@+id/discount_code" android:layout_width="wrap_content" - android:layout_height="wrap_content"/> + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/discount_code_bottom_margin" + android:paddingHorizontal="@dimen/discount_code_horizontal_padding" + android:paddingVertical="@dimen/discount_code_vertical_padding" + android:textAppearance="@style/TextAppearance.DiscountCodeText" + android:background="@drawable/discount_code_background"/> <TextView android:id="@+id/description_detail" + android:textAppearance="@style/TextAppearance.TextMedium.Primary" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/expiry_time" + android:textAppearance="@style/TextAppearance.TextSmall.Secondary" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
diff --git a/chrome/browser/commerce/coupons/android/java/res/values/dimens.xml b/chrome/browser/commerce/coupons/android/java/res/values/dimens.xml new file mode 100644 index 0000000..cd95d1a4 --- /dev/null +++ b/chrome/browser/commerce/coupons/android/java/res/values/dimens.xml
@@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2024 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<resources xmlns:tools="http://schemas.android.com/tools"> + <dimen name="discount_item_container_background_radius">16dp</dimen> + <dimen name="discount_item_container_padding">12dp</dimen> + <dimen name="discount_code_background_radius">4dp</dimen> + <dimen name="discount_code_bottom_margin">4dp</dimen> + <dimen name="discount_code_horizontal_padding">8dp</dimen> + <dimen name="discount_code_vertical_padding">2dp</dimen> + <dimen name="discount_item_divider_height">2dp</dimen> +</resources> \ No newline at end of file
diff --git a/chrome/browser/commerce/coupons/android/java/res/values/styles.xml b/chrome/browser/commerce/coupons/android/java/res/values/styles.xml new file mode 100644 index 0000000..1cb3c64e --- /dev/null +++ b/chrome/browser/commerce/coupons/android/java/res/values/styles.xml
@@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2014 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<resources xmlns:tools="http://schemas.android.com/tools"> + <style name="TextAppearance.DiscountCodeText" parent="TextAppearance.TextSmall.Primary"> + <item name="android:textColor">@color/price_drop_annotation_text_green</item> + </style> +</resources> \ No newline at end of file
diff --git a/chrome/browser/commerce/coupons/android/java/src/org/chromium/chrome/browser/commerce/coupons/DiscountsBottomSheetContentCoordinator.java b/chrome/browser/commerce/coupons/android/java/src/org/chromium/chrome/browser/commerce/coupons/DiscountsBottomSheetContentCoordinator.java index fa6e826..46b65b0a 100644 --- a/chrome/browser/commerce/coupons/android/java/src/org/chromium/chrome/browser/commerce/coupons/DiscountsBottomSheetContentCoordinator.java +++ b/chrome/browser/commerce/coupons/android/java/src/org/chromium/chrome/browser/commerce/coupons/DiscountsBottomSheetContentCoordinator.java
@@ -11,11 +11,14 @@ import static org.chromium.chrome.browser.commerce.CommerceBottomSheetContentProperties.TYPE; import android.content.Context; +import android.graphics.Rect; import android.view.LayoutInflater; import android.view.View; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView.ItemDecoration; +import androidx.recyclerview.widget.RecyclerView.State; import org.chromium.base.Callback; import org.chromium.base.supplier.Supplier; @@ -51,6 +54,23 @@ mContentRecyclerView = mDiscountsContentContainer.findViewById(R.id.discounts_content_recycler_view); mContentRecyclerView.setAdapter(adapter); + mContentRecyclerView.addItemDecoration( + new ItemDecoration() { + @Override + public void getItemOffsets( + @NonNull Rect outRect, + @NonNull View view, + @NonNull RecyclerView parent, + @NonNull State state) { + // Avoid adding top padding to the first item in the list. + if (parent.getChildAdapterPosition(view) != 0) { + outRect.top = + mContext.getResources() + .getDimensionPixelOffset( + R.dimen.discount_item_divider_height); + } + } + }); mMediator = new DiscountsBottomSheetContentMediator(context, tabSupplier, mModelList); }
diff --git a/chrome/browser/commerce/coupons/android/javatests/src/org/chromium/chrome/browser/commerce/coupons/DiscountsBottomSheetContentRenderTest.java b/chrome/browser/commerce/coupons/android/javatests/src/org/chromium/chrome/browser/commerce/coupons/DiscountsBottomSheetContentRenderTest.java index 52d2e32f..45fc8d3 100644 --- a/chrome/browser/commerce/coupons/android/javatests/src/org/chromium/chrome/browser/commerce/coupons/DiscountsBottomSheetContentRenderTest.java +++ b/chrome/browser/commerce/coupons/android/javatests/src/org/chromium/chrome/browser/commerce/coupons/DiscountsBottomSheetContentRenderTest.java
@@ -44,7 +44,10 @@ public class DiscountsBottomSheetContentRenderTest extends BlankUiTestActivityTestCase { @Rule public RenderTestRule mRenderTestRule = - RenderTestRule.Builder.withPublicCorpus().setBugComponent(UI_BROWSER_SHOPPING).build(); + RenderTestRule.Builder.withPublicCorpus() + .setRevision(1) + .setBugComponent(UI_BROWSER_SHOPPING) + .build(); @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
diff --git a/chrome/browser/download/android/download_controller.cc b/chrome/browser/download/android/download_controller.cc index d4932162..ebeb740 100644 --- a/chrome/browser/download/android/download_controller.cc +++ b/chrome/browser/download/android/download_controller.cc
@@ -24,7 +24,6 @@ #include "chrome/browser/android/profile_key_startup_accessor.h" #include "chrome/browser/android/profile_key_util.h" #include "chrome/browser/android/tab_android.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/download/android/dangerous_download_infobar_delegate.h" #include "chrome/browser/download/android/download_manager_service.h" #include "chrome/browser/download/android/download_utils.h" @@ -37,7 +36,6 @@ #include "chrome/browser/offline_pages/android/offline_page_bridge.h" #include "chrome/browser/permissions/permission_update_message_controller_android.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/ui/android/tab_model/tab_model.h" #include "chrome/browser/ui/android/tab_model/tab_model_list.h" #include "chrome/common/pref_names.h" @@ -49,9 +47,6 @@ #include "components/pdf/common/constants.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" -#include "components/safe_browsing/android/safe_browsing_api_handler_bridge.h" -#include "components/safe_browsing/core/browser/db/database_manager.h" -#include "components/safe_browsing/core/browser/db/v4_protocol_manager_util.h" #include "components/safe_browsing/core/common/features.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/browser_context.h" @@ -190,64 +185,6 @@ !item->IsMustDownload() && item->IsTransient(); } -class DownloadBlocklistChecker - : public safe_browsing::SafeBrowsingDatabaseManager::Client, - public base::RefCounted<DownloadBlocklistChecker> { - public: - explicit DownloadBlocklistChecker(download::DownloadItem* item) - : url_chain_(item->GetUrlChain()) {} - - void Start() { - scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager; - if (g_browser_process->safe_browsing_service()) { - database_manager = - g_browser_process->safe_browsing_service()->database_manager(); - } - - if (!database_manager || - database_manager->CheckDownloadUrl(url_chain_, this)) { - Log(safe_browsing::SBThreatType::SB_THREAT_TYPE_SAFE); - } else { - // Add a reference to this object to prevent it from being destroyed - // before url checking result is returned. - AddRef(); - } - } - - private: - friend class base::RefCounted<DownloadBlocklistChecker>; - - ~DownloadBlocklistChecker() override = default; - - void Log(safe_browsing::SBThreatType threat_type) { - base::UmaHistogramEnumeration( - "SafeBrowsing.AndroidTelemetry.DownloadUrlChainThreatType", - threat_type); - } - - // SafeBrowsingDatabaseManager::Client: - void OnCheckDownloadUrlResult( - const std::vector<GURL>& url_chain, - safe_browsing::SBThreatType threat_type) override { - Log(threat_type); - Release(); // Balanced by AddRef in Start. - } - - std::vector<GURL> url_chain_; -}; - -void RecordDownloadBlocklistState(download::DownloadItem* item) { - // Startup in Chrome minimal mode may start a download before - // initializing the UI thread. - if (!content::BrowserThread::IsThreadInitialized( - content::BrowserThread::UI)) { - return; - } - - auto checker = base::MakeRefCounted<DownloadBlocklistChecker>(item); - checker->Start(); -} - void CleanupAppVerificationTimestamps(download::DownloadItem* item) { Profile* profile = Profile::FromBrowserContext( content::DownloadItemUtils::GetBrowserContext(item)); @@ -505,8 +442,6 @@ } void DownloadController::OnDownloadStarted(DownloadItem* download_item) { - RecordDownloadBlocklistState(download_item); - // For dangerous downloads, we need to show the dangerous infobar before the // download can start. if (!download_item->IsDangerous() &&
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/interstitial/DownloadInterstitialProperties.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/interstitial/DownloadInterstitialProperties.java index 0e24e53f..b09f4e7 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/interstitial/DownloadInterstitialProperties.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/interstitial/DownloadInterstitialProperties.java
@@ -15,10 +15,14 @@ import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey; /** - * Extends the properties defined in {@link ListProperties} to facilitate the logic for an entire - * UI containing a download ListItem. + * Extends the properties defined in {@link ListProperties} to facilitate the logic for an entire UI + * containing a download ListItem. */ interface DownloadInterstitialProperties extends ListProperties { + /** + * Keeps track of the state of the DownloadInterstitial. This may be different to the state of + * the offline item displayed within the UI. + */ @IntDef({ State.UNKNOWN, State.IN_PROGRESS, @@ -27,10 +31,6 @@ State.PAUSED, State.PENDING }) - /** - * Keeps track of the state of the DownloadInterstitial. This may be different to the state of - * the offline item displayed within the UI. - */ @interface State { int UNKNOWN = 0; int IN_PROGRESS = 1;
diff --git a/chrome/browser/extensions/api/debugger/debugger_api.cc b/chrome/browser/extensions/api/debugger/debugger_api.cc index 5266fa3..7c3f912 100644 --- a/chrome/browser/extensions/api/debugger/debugger_api.cc +++ b/chrome/browser/extensions/api/debugger/debugger_api.cc
@@ -58,6 +58,7 @@ #include "extensions/common/constants.h" #include "extensions/common/error_utils.h" #include "extensions/common/extension.h" +#include "extensions/common/extension_features.h" #include "extensions/common/extension_id.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/permissions/permissions_data.h" @@ -472,6 +473,11 @@ return true; } + if (base::FeatureList::IsEnabled( + extensions_features::kSilentDebuggerExtensionAPI)) { + return true; + } + // We allow policy-installed extensions to circumvent the normal // infobar warning. See crbug.com/693621. if (Manifest::IsPolicyLocation(extension_->location()))
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java index e38397e..489231d 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java
@@ -201,12 +201,8 @@ assertTrue(intent.hasExtra(CreatorIntentConstants.CREATOR_URL)); assertNotNull(intent.getExtras().getString(CreatorIntentConstants.CREATOR_URL)); assertTrue(intent.hasExtra(CreatorIntentConstants.CREATOR_ENTRY_POINT)); - assertNotNull(intent.getExtras().getInt(CreatorIntentConstants.CREATOR_ENTRY_POINT)); assertTrue(intent.hasExtra(CreatorIntentConstants.CREATOR_FOLLOWING)); - assertNotNull( - intent.getExtras().getBoolean(CreatorIntentConstants.CREATOR_FOLLOWING, false)); assertTrue(intent.hasExtra(CreatorIntentConstants.CREATOR_TAB_ID)); - assertNotNull(intent.getExtras().getInt(CreatorIntentConstants.CREATOR_TAB_ID)); } @Test
diff --git a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/DrawableButtonDataUnitTest.java b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/DrawableButtonDataUnitTest.java index 919aae4a..56e50fb 100644 --- a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/DrawableButtonDataUnitTest.java +++ b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/DrawableButtonDataUnitTest.java
@@ -60,7 +60,6 @@ DisplayButtonData buttonData = new DrawableButtonData( R.string.button_new_tab, R.string.button_new_incognito_tab, drawable); - assertEquals(buttonData, buttonData); assertEquals( buttonData, new DrawableButtonData(
diff --git a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/ResourceButtonDataUnitTest.java b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/ResourceButtonDataUnitTest.java index f13cd58..739d7ad 100644 --- a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/ResourceButtonDataUnitTest.java +++ b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/ResourceButtonDataUnitTest.java
@@ -61,7 +61,6 @@ R.string.button_new_tab, R.string.button_new_incognito_tab, R.drawable.ic_add); - assertEquals(buttonData, buttonData); assertEquals( buttonData, new ResourceButtonData(
diff --git a/chrome/browser/lacros/automation_manager_lacros.cc b/chrome/browser/lacros/automation_manager_lacros.cc index 5bbbf2ff1..e109ce7 100644 --- a/chrome/browser/lacros/automation_manager_lacros.cc +++ b/chrome/browser/lacros/automation_manager_lacros.cc
@@ -56,8 +56,8 @@ } void AutomationManagerLacros::DispatchAccessibilityLocationChange( - const ui::AXLocationChanges& details) { - ui::AXTreeID tree_id = details.ax_tree_id; + const ui::AXTreeID& tree_id, + const ui::AXLocationChange& details) { if (!tree_id.token()) return;
diff --git a/chrome/browser/lacros/automation_manager_lacros.h b/chrome/browser/lacros/automation_manager_lacros.h index 5e2647da..fd8a010 100644 --- a/chrome/browser/lacros/automation_manager_lacros.h +++ b/chrome/browser/lacros/automation_manager_lacros.h
@@ -31,7 +31,8 @@ const gfx::Point& mouse_location, const std::vector<ui::AXEvent>& events) override; void DispatchAccessibilityLocationChange( - const ui::AXLocationChanges& details) override; + const ui::AXTreeID& tree_id, + const ui::AXLocationChange& details) override; void DispatchTreeDestroyedEvent(ui::AXTreeID tree_id) override; void DispatchActionResult(const ui::AXActionData& data, bool result,
diff --git a/chrome/browser/lens/BUILD.gn b/chrome/browser/lens/BUILD.gn index d606492..bd138dca 100644 --- a/chrome/browser/lens/BUILD.gn +++ b/chrome/browser/lens/BUILD.gn
@@ -12,6 +12,7 @@ deps = [ ":java_resources", "//base:base_java", + "//base:service_loader_java", "//chrome/browser/contextmenu:java", "//chrome/browser/ui/android/strings:ui_strings_grd", "//components/embedder_support/android:context_menu_java", @@ -30,7 +31,6 @@ android_library("delegate_java") { sources = [ "java/src/org/chromium/chrome/browser/lens/LensControllerDelegate.java", - "java/src/org/chromium/chrome/browser/lens/LensControllerDelegateImpl.java", ] deps = [ @@ -44,21 +44,6 @@ "//ui/android:ui_java", ] resources_package = "org.chromium.chrome.browser.lens" - - # Add the actual implementation where necessary so that downstream targets - # can provide their own implementations. - jar_excluded_patterns = [ "*/LensControllerDelegateImpl.class" ] -} - -android_library("delegate_public_impl_java") { - sources = [ - "java/src/org/chromium/chrome/browser/lens/LensControllerDelegateImpl.java", - ] - - deps = [ - ":delegate_java", - ":util_java", - ] } android_library("util_java") {
diff --git a/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensController.java b/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensController.java index 51807fb..9572a6a 100644 --- a/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensController.java +++ b/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensController.java
@@ -6,6 +6,7 @@ import androidx.annotation.NonNull; import org.chromium.base.Callback; +import org.chromium.base.ServiceLoaderUtil; import org.chromium.components.embedder_support.contextmenu.ChipRenderParams; import org.chromium.ui.base.WindowAndroid; @@ -23,11 +24,17 @@ } public LensController() { - mDelegate = new LensControllerDelegateImpl(); + LensControllerDelegate delegate = + ServiceLoaderUtil.maybeCreate(LensControllerDelegate.class); + if (delegate == null) { + delegate = new LensControllerDelegate(); + } + mDelegate = delegate; } /** * Whether the Lens SDK is available. + * * @return Whether the Lens SDK is available. */ public boolean isSdkAvailable() {
diff --git a/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensControllerDelegate.java b/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensControllerDelegate.java index c137bb4e..a47c838 100644 --- a/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensControllerDelegate.java +++ b/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensControllerDelegate.java
@@ -18,8 +18,8 @@ /** * Base class for defining methods where different behavior is required by downstream targets. The - * correct version of {@link LensControllerDelegateImpl} will be determined at compile time via - * build rules. + * correct implementation of {@link LensControllerDelegate} will be determined at compile time via + * {@link ServiceLoaderUtil}. */ public class LensControllerDelegate { /**
diff --git a/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensControllerDelegateImpl.java b/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensControllerDelegateImpl.java deleted file mode 100644 index d094456..0000000 --- a/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensControllerDelegateImpl.java +++ /dev/null
@@ -1,13 +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. - -package org.chromium.chrome.browser.lens; - -/** - * Instantiable version of {@link LensControllerDelegate}, don't add anything to this class. - * Downstream targets may provide a different implementation. In GN, we specify that - * {@link LensControllerDelegate} is compiled separately from its implementation; other - * projects may specify a different LensControllerDelegate via GN. - */ -class LensControllerDelegateImpl extends LensControllerDelegate {}
diff --git a/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesCoordinator.java b/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesCoordinator.java index 072d70f..b8edb39 100644 --- a/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesCoordinator.java +++ b/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesCoordinator.java
@@ -140,7 +140,7 @@ super.onViewRecycled(holder); } }; - mModuleRegistry.registerAdapter(mAdapter, this::onViewCreated); + mModuleRegistry.registerAdapter(mAdapter, this); mRecyclerView.setAdapter(mAdapter); }
diff --git a/chrome/browser/metrics/tab_stats/tab_stats_tracker.cc b/chrome/browser/metrics/tab_stats/tab_stats_tracker.cc index 5eb32fdf..1a84693e 100644 --- a/chrome/browser/metrics/tab_stats/tab_stats_tracker.cc +++ b/chrome/browser/metrics/tab_stats/tab_stats_tracker.cc
@@ -626,10 +626,12 @@ base::UmaHistogramCounts100(kTabDuplicateCountSingleWindowHistogramName, duplicate_data_single_window.duplicate_count); - base::UmaHistogramPercentage( - kTabDuplicatePercentageSingleWindowHistogramName, - duplicate_data_single_window.duplicate_count * 100 / - duplicate_data_single_window.tab_count); + if (duplicate_data_single_window.tab_count > 0) { + base::UmaHistogramPercentage( + kTabDuplicatePercentageSingleWindowHistogramName, + duplicate_data_single_window.duplicate_count * 100 / + duplicate_data_single_window.tab_count); + } } for (const auto& duplicate_data : duplicate_data_per_profile) { // Guest mode and incognito should not count for the per-profile metrics @@ -641,10 +643,12 @@ base::UmaHistogramCounts100( kTabDuplicateCountAllProfileWindowsHistogramName, duplicate_data.second.duplicate_count); - base::UmaHistogramPercentage( - kTabDuplicatePercentageAllProfileWindowsHistogramName, - duplicate_data.second.duplicate_count * 100 / - duplicate_data.second.tab_count); + if (duplicate_data.second.tab_count > 0) { + base::UmaHistogramPercentage( + kTabDuplicatePercentageAllProfileWindowsHistogramName, + duplicate_data.second.duplicate_count * 100 / + duplicate_data.second.tab_count); + } } }
diff --git a/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/most_relevant_tab_resumption_page_handler.cc b/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/most_relevant_tab_resumption_page_handler.cc index 427c30c..37e88ee 100644 --- a/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/most_relevant_tab_resumption_page_handler.cc +++ b/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/most_relevant_tab_resumption_page_handler.cc
@@ -49,9 +49,9 @@ using Source = visited_url_ranking::URLVisit::Source; namespace { -// Name of preference to track list of dismissed tabs. -const char kDismissedTabsPrefName[] = - "NewTabPage.MostRelevantTabResumption.DismissedTabs"; +// Name of preference to track list of dismissed visits. +const char kDismissedVisitsPrefName[] = + "NewTabPage.MostRelevantTabResumption.DismissedVisits"; std::u16string FormatRelativeTime(const base::Time& time) { // Return a time like "1 hour ago", "2 days ago", etc. @@ -249,17 +249,31 @@ void MostRelevantTabResumptionPageHandler::DismissModule( const std::vector<ntp::most_relevant_tab_resumption::mojom::URLVisitPtr> url_visits) { + DismissURLVisits(url_visits); +} + +void MostRelevantTabResumptionPageHandler::DismissURLVisit( + ntp::most_relevant_tab_resumption::mojom::URLVisitPtr url_visit) { + std::vector<ntp::most_relevant_tab_resumption::mojom::URLVisitPtr> + url_visits_mojom; + url_visits_mojom.push_back(std::move(url_visit)); + DismissURLVisits(url_visits_mojom); +} + +void MostRelevantTabResumptionPageHandler::DismissURLVisits( + const std::vector<ntp::most_relevant_tab_resumption::mojom::URLVisitPtr>& + url_visits) { RemoveOldDismissedTabs(); - ScopedListPrefUpdate url_visit_list(profile_->GetPrefs(), - kDismissedTabsPrefName); + ScopedDictPrefUpdate url_visit_dict(profile_->GetPrefs(), + kDismissedVisitsPrefName); auto* visited_url_ranking_service = visited_url_ranking::VisitedURLRankingServiceFactory::GetForProfile( profile_); for (const auto& url_visit : url_visits) { - url_visit_list->Append(base::Value( - url_visit->url_key + ' ' + - base::NumberToString(url_visit->timestamp->ToDeltaSinceWindowsEpoch() - .InMicroseconds()))); + url_visit_dict->Set( + url_visit->url_key, + static_cast<double>( + url_visit->timestamp->ToDeltaSinceWindowsEpoch().InMicroseconds())); visited_url_ranking_service->RecordAction( visited_url_ranking::ScoredURLUserAction::kDismissed, url_visit->url_key, @@ -268,57 +282,40 @@ } } -void MostRelevantTabResumptionPageHandler::DismissURLVisit( - const ntp::most_relevant_tab_resumption::mojom::URLVisitPtr url_visit) { - RemoveOldDismissedTabs(); - ScopedListPrefUpdate url_visit_list(profile_->GetPrefs(), - kDismissedTabsPrefName); - url_visit_list->Append(base::Value( - url_visit->url_key + ' ' + - base::NumberToString( - url_visit->timestamp->ToDeltaSinceWindowsEpoch().InMicroseconds()))); - auto* visited_url_ranking_service = - visited_url_ranking::VisitedURLRankingServiceFactory::GetForProfile( - profile_); - visited_url_ranking_service->RecordAction( - visited_url_ranking::ScoredURLUserAction::kDismissed, url_visit->url_key, - segmentation_platform::TrainingRequestId(url_visit->training_request_id)); -} - void MostRelevantTabResumptionPageHandler::RestoreModule( const std::vector<ntp::most_relevant_tab_resumption::mojom::URLVisitPtr> url_visits) { - ScopedListPrefUpdate url_visit_list(profile_->GetPrefs(), - kDismissedTabsPrefName); - auto* visited_url_ranking_service = - visited_url_ranking::VisitedURLRankingServiceFactory::GetForProfile( - profile_); - for (const auto& url_visit : url_visits) { - url_visit_list->EraseValue(base::Value( - url_visit->url_key + ' ' + - base::NumberToString(url_visit->timestamp->ToDeltaSinceWindowsEpoch() - .InMicroseconds()))); - visited_url_ranking_service->RecordAction( - visited_url_ranking::ScoredURLUserAction::kSeen, url_visit->url_key, - segmentation_platform::TrainingRequestId( - url_visit->training_request_id)); - } + RestoreURLVisits(std::move(url_visits)); } void MostRelevantTabResumptionPageHandler::RestoreURLVisit( ntp::most_relevant_tab_resumption::mojom::URLVisitPtr url_visit) { - ScopedListPrefUpdate url_visit_list(profile_->GetPrefs(), - kDismissedTabsPrefName); - url_visit_list->EraseValue(base::Value( - url_visit->url_key + ' ' + - base::NumberToString( - url_visit->timestamp->ToDeltaSinceWindowsEpoch().InMicroseconds()))); + std::vector<ntp::most_relevant_tab_resumption::mojom::URLVisitPtr> + url_visits_mojom; + url_visits_mojom.push_back(std::move(url_visit)); + RestoreURLVisits(url_visits_mojom); +} + +void MostRelevantTabResumptionPageHandler::RestoreURLVisits( + const std::vector<ntp::most_relevant_tab_resumption::mojom::URLVisitPtr>& + url_visits) { + ScopedDictPrefUpdate url_visit_dict(profile_->GetPrefs(), + kDismissedVisitsPrefName); auto* visited_url_ranking_service = visited_url_ranking::VisitedURLRankingServiceFactory::GetForProfile( profile_); - visited_url_ranking_service->RecordAction( - visited_url_ranking::ScoredURLUserAction::kSeen, url_visit->url_key, - segmentation_platform::TrainingRequestId(url_visit->training_request_id)); + for (const auto& url_visit : url_visits) { + if (url_visit_dict->Find(url_visit->url_key) && + static_cast<long>( + url_visit_dict->Find(url_visit->url_key)->GetDouble()) == + url_visit->timestamp->ToDeltaSinceWindowsEpoch().InMicroseconds()) { + url_visit_dict->Remove(url_visit->url_key); + visited_url_ranking_service->RecordAction( + visited_url_ranking::ScoredURLUserAction::kSeen, url_visit->url_key, + segmentation_platform::TrainingRequestId( + url_visit->training_request_id)); + } + } } void MostRelevantTabResumptionPageHandler::OnURLVisitAggregatesFetched( @@ -473,40 +470,31 @@ // static void MostRelevantTabResumptionPageHandler::RegisterProfilePrefs( PrefRegistrySimple* registry) { - registry->RegisterListPref(kDismissedTabsPrefName, base::Value::List()); + registry->RegisterDictionaryPref(kDismissedVisitsPrefName, + base::Value::Dict()); } bool MostRelevantTabResumptionPageHandler::IsNewURL( ntp::most_relevant_tab_resumption::mojom::URLVisitPtr& url_visit) { - const base::Value::List& cached_urls = - profile_->GetPrefs()->GetList(kDismissedTabsPrefName); - auto it = std::find_if( - cached_urls.begin(), cached_urls.end(), - [&url_visit](const base::Value& cached_url) { - return cached_url.GetString() == - url_visit->url_key + ' ' + - base::NumberToString( - url_visit->timestamp->ToDeltaSinceWindowsEpoch() - .InMicroseconds()); - }); - return it == cached_urls.end(); + const base::Value::Dict& cached_urls = + profile_->GetPrefs()->GetDict(kDismissedVisitsPrefName); + if (cached_urls.Find(url_visit->url_key) == nullptr) { + return true; + } else { + return static_cast<long>( + cached_urls.Find(url_visit->url_key)->GetDouble()) != + url_visit->timestamp->ToDeltaSinceWindowsEpoch().InMicroseconds(); + } } void MostRelevantTabResumptionPageHandler::RemoveOldDismissedTabs() { - ScopedListPrefUpdate tab_list(profile_->GetPrefs(), kDismissedTabsPrefName); - for (const auto& entry : tab_list.Get().Clone()) { - const std::string dismissed_tab_string = entry.GetString(); - size_t delimiter_pos = dismissed_tab_string.find(' '); - if (delimiter_pos != std::string::npos) { - int64_t timestamp_microseconds; - base::StringToInt64(dismissed_tab_string.substr(delimiter_pos), - ×tamp_microseconds); - base::Time timestamp = base::Time::FromDeltaSinceWindowsEpoch( - base::Microseconds(timestamp_microseconds)); - if (base::Time::Now() - timestamp > - base::Days(dismissal_duration_days_)) { - tab_list->EraseValue(entry); - } + ScopedDictPrefUpdate visit_dict(profile_->GetPrefs(), + kDismissedVisitsPrefName); + for (auto it = visit_dict->begin(); it != visit_dict->end(); ++it) { + base::Time timestamp = base::Time::FromDeltaSinceWindowsEpoch( + base::Microseconds(it->second.GetDouble())); + if (base::Time::Now() - timestamp > base::Days(dismissal_duration_days_)) { + visit_dict->Remove(it->first); } } }
diff --git a/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/most_relevant_tab_resumption_page_handler.h b/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/most_relevant_tab_resumption_page_handler.h index 1ece78a5..e34ca4e 100644 --- a/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/most_relevant_tab_resumption_page_handler.h +++ b/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/most_relevant_tab_resumption_page_handler.h
@@ -52,8 +52,7 @@ const std::vector<ntp::most_relevant_tab_resumption::mojom::URLVisitPtr> url_visits) override; void DismissURLVisit( - const ntp::most_relevant_tab_resumption::mojom::URLVisitPtr url_visit) - override; + ntp::most_relevant_tab_resumption::mojom::URLVisitPtr url_visit) override; void RestoreModule( const std::vector<ntp::most_relevant_tab_resumption::mojom::URLVisitPtr> url_visits) override; @@ -91,6 +90,13 @@ bool IsNewURL( ntp::most_relevant_tab_resumption::mojom::URLVisitPtr& url_visit); + void DismissURLVisits( + const std::vector<ntp::most_relevant_tab_resumption::mojom::URLVisitPtr>& + url_visits); + void RestoreURLVisits( + const std::vector<ntp::most_relevant_tab_resumption::mojom::URLVisitPtr>& + url_visits); + // Method to clear dismissed tabs that are older than a certain amount of // time. void RemoveOldDismissedTabs();
diff --git a/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/most_relevant_tab_resumption_page_handler_unittest.cc b/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/most_relevant_tab_resumption_page_handler_unittest.cc index 533b568..b46b8dd 100644 --- a/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/most_relevant_tab_resumption_page_handler_unittest.cc +++ b/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/most_relevant_tab_resumption_page_handler_unittest.cc
@@ -371,7 +371,9 @@ {Fetcher::kSession})); url_visit_aggregates.emplace_back( visited_url_ranking::CreateSampleURLVisitAggregate( - GURL(visited_url_ranking::kSampleSearchUrl), 1.0f, + GURL(visited_url_ranking::kSampleSearchUrl + + std::string("1")), + 1.0f, base::Time::FromDeltaSinceWindowsEpoch( base::Microseconds(123456)), {Fetcher::kHistory}));
diff --git a/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/url_visit_types.mojom b/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/url_visit_types.mojom index 75446f0..a459f9b 100644 --- a/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/url_visit_types.mojom +++ b/chrome/browser/new_tab_page/modules/v2/most_relevant_tab_resumption/url_visit_types.mojom
@@ -22,6 +22,7 @@ enum DecorationType { kVisitedXAgo, kMostRecent, + kFrequentlyVisited, kFrequentlyVisitedAtTime, };
diff --git a/chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuidePushNotificationManager.java b/chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuidePushNotificationManager.java index db6768e..a00680c 100644 --- a/chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuidePushNotificationManager.java +++ b/chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuidePushNotificationManager.java
@@ -200,7 +200,7 @@ @VisibleForTesting public static String cacheKey(OptimizationType optimizationType) { return ChromePreferenceKeys.OPTIMIZATION_GUIDE_PUSH_NOTIFICATION_CACHE.createKey( - optimizationType.toString()); + optimizationType.name()); } public static void setNativeIsInitializedForTesting(Boolean nativeIsInitialized) {
diff --git a/chrome/browser/page_load_metrics/observers/third_party_cookie_deprecation_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/third_party_cookie_deprecation_metrics_observer_browsertest.cc index cf02b08..0f8bf7ad 100644 --- a/chrome/browser/page_load_metrics/observers/third_party_cookie_deprecation_metrics_observer_browsertest.cc +++ b/chrome/browser/page_load_metrics/observers/third_party_cookie_deprecation_metrics_observer_browsertest.cc
@@ -99,8 +99,6 @@ .allow_by_global_setting = true, .expected_allow_mechanism_histogram_sample = ThirdPartyCookieAllowMechanism::kAllowByGlobalSetting, - .expected_web_feature_histogram_sample = - WebFeature::kThirdPartyCookieDeprecation_AllowByGlobalSetting, }, { .allow_by_3pcd_1p_trial_token = true, @@ -176,8 +174,6 @@ .allow_by_explicit_setting = true, .expected_allow_mechanism_histogram_sample = ThirdPartyCookieAllowMechanism::kAllowByExplicitSetting, - .expected_web_feature_histogram_sample = - WebFeature::kThirdPartyCookieDeprecation_AllowByExplicitSetting, }, // Precedence testing test cases: { @@ -185,8 +181,6 @@ .allow_by_3pcd_1p_trial_token = true, .expected_allow_mechanism_histogram_sample = ThirdPartyCookieAllowMechanism::kAllowByGlobalSetting, - .expected_web_feature_histogram_sample = - WebFeature::kThirdPartyCookieDeprecation_AllowByGlobalSetting, }, { .allow_by_3pcd_1p_trial_token = true, @@ -1280,11 +1274,9 @@ histogram_tester.ExpectUniqueSample(kThirdPartyCookieAllowMechanismHistogram, /*kAllowByStorageAccess*/ 6, 2); - // Only record blink usage when tracking protection is onboard. histogram_tester.ExpectBucketCount( kWebFeatureHistogram, - WebFeature::kThirdPartyCookieDeprecation_AllowByStorageAccess, - GetParam() ? 1 : 0); + WebFeature::kThirdPartyCookieAccessBlockByExperiment, GetParam() ? 1 : 0); } class ThirdPartyCookieDeprecationObserverCookieReadBrowserTest
diff --git a/chrome/browser/page_load_metrics/observers/third_party_cookie_deprecation_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/third_party_cookie_deprecation_page_load_metrics_observer.cc index 3fd5b36..6dbd91e 100644 --- a/chrome/browser/page_load_metrics/observers/third_party_cookie_deprecation_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/third_party_cookie_deprecation_page_load_metrics_observer.cc
@@ -173,16 +173,12 @@ .Record(ukm::UkmRecorder::Get()); } - if (!is_blocked_by_experiment) { - return; - } - - // Record the following blink feature usage cookie metrics when the 3PCD - // experiment is actual block third party cookies, which means tracking - // protection is onboard. + // Record the following blink feature usage cookie metrics. std::vector<blink::mojom::WebFeature> third_party_cookie_features; - third_party_cookie_features.push_back( - blink::mojom::WebFeature::kThirdPartyCookieAccessBlockByExperiment); + if (is_blocked_by_experiment) { + third_party_cookie_features.push_back( + blink::mojom::WebFeature::kThirdPartyCookieAccessBlockByExperiment); + } switch (allow_mechanism) { case ThirdPartyCookieAllowMechanism::kAllowByExplicitSetting:
diff --git a/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizationsRoboUnitTest.java b/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizationsRoboUnitTest.java index 0fa449b..8666313 100644 --- a/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizationsRoboUnitTest.java +++ b/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizationsRoboUnitTest.java
@@ -118,21 +118,21 @@ public ShadowCustomizationProviderDelegate() {} + /** Returns the homepage string or null if none is available. */ @Implementation @Nullable - /** Returns the homepage string or null if none is available. */ protected String getHomepage() { return sHomepage; } - @Implementation /** Returns whether incognito mode is disabled. */ + @Implementation protected boolean isIncognitoModeDisabled() { return false; } - @Implementation /** Returns whether bookmark editing is disabled. */ + @Implementation protected boolean isBookmarksEditingDisabled() { return false; }
diff --git a/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordChangeType.java b/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordChangeType.java index c5ba009..3feeef2 100644 --- a/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordChangeType.java +++ b/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordChangeType.java
@@ -22,8 +22,6 @@ /** A user opened a site to change a password manually. */ int MANUAL_CHANGE = 1; - /** - * Deprecated as a part of APC removal (crbug.com/1386065). - * int AUTOMATED_CHANGE = 2; - */ + // Deprecated as a part of APC removal (crbug.com/1386065). + // int AUTOMATED_CHANGE = 2; }
diff --git a/chrome/browser/password_manager/android/access_loss/java/src/org/chromium/chrome/browser/access_loss/PasswordAccessLossWarningHelper.java b/chrome/browser/password_manager/android/access_loss/java/src/org/chromium/chrome/browser/access_loss/PasswordAccessLossWarningHelper.java index e749d77..6ba7228 100644 --- a/chrome/browser/password_manager/android/access_loss/java/src/org/chromium/chrome/browser/access_loss/PasswordAccessLossWarningHelper.java +++ b/chrome/browser/password_manager/android/access_loss/java/src/org/chromium/chrome/browser/access_loss/PasswordAccessLossWarningHelper.java
@@ -70,8 +70,8 @@ coordinator.showSheet(model); } - @Nullable /** Creates the model that has the text and functionality appropriate for the warning type. */ + @Nullable PropertyModel getModelForWarningType(@PasswordAccessLossWarningType int warningType) { switch (warningType) { case PasswordAccessLossWarningType.NO_GMS_CORE:
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/GmsUpdateLauncher.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/GmsUpdateLauncher.java index 0ae5fb2..67629b4 100644 --- a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/GmsUpdateLauncher.java +++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/GmsUpdateLauncher.java
@@ -32,6 +32,7 @@ intent.setPackage("com.android.vending"); intent.setData(Uri.parse(deepLinkUrl)); intent.putExtra("callerId", context.getPackageName()); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // Request for overlay flow, Play Store will fallback to the default // behaviour if overlay is not available.
diff --git a/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/GmsUpdateLauncherTest.java b/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/GmsUpdateLauncherTest.java index ca5d4d5..f1ce2e8 100644 --- a/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/GmsUpdateLauncherTest.java +++ b/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/GmsUpdateLauncherTest.java
@@ -36,6 +36,7 @@ assertEquals(intent.getAction(), Intent.ACTION_VIEW); assertEquals(intent.getPackage(), "com.android.vending"); assertEquals(intent.getStringExtra("callerId"), mockContext.getPackageName()); + assertEquals(intent.getFlags(), Intent.FLAG_ACTIVITY_NEW_TASK); assertEquals( intent.getData(), Uri.parse(
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index bad98a8..8cbedb5 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -1096,6 +1096,12 @@ "privacy_sandbox.activity_type.record"; #endif // BUILDFLAG(IS_ANDROID) +// Deprecated 09/2024. +#if !BUILDFLAG(IS_ANDROID) +const char kTabResumeDismissedTabsPrefName[] = + "NewTabPage.MostRelevantTabResumption.DismissedTabs"; +#endif // !BUILDFLAG(IS_ANDROID) + // Register local state used only for migration (clearing or moving to a new // key). void RegisterLocalStatePrefsForMigration(PrefRegistrySimple* registry) { @@ -1539,6 +1545,12 @@ #if BUILDFLAG(IS_ANDROID) registry->RegisterListPref(kPrivacySandboxActivityTypeRecord); #endif // BUILDFLAG(IS_ANDROID) + +// Deprecated 09/2024 +#if !BUILDFLAG(IS_ANDROID) + registry->RegisterListPref(kTabResumeDismissedTabsPrefName, + base::Value::List()); +#endif // !BUILDFLAG(IS_ANDROID) } void ClearSyncRequestedPrefAndMaybeMigrate(PrefService* profile_prefs) { @@ -2873,6 +2885,11 @@ profile_prefs->ClearPref(kPrivacySandboxActivityTypeRecord); #endif // BUILDFLAG(IS_ANDROID) +// Added 09/2024 +#if !BUILDFLAG(IS_ANDROID) + profile_prefs->ClearPref(kTabResumeDismissedTabsPrefName); +#endif // !BUILDFLAG(IS_ANDROID) + // Please don't delete the following line. It is used by PRESUBMIT.py. // END_MIGRATE_OBSOLETE_PROFILE_PREFS
diff --git a/chrome/browser/resources/lens/overlay/translate_button.html b/chrome/browser/resources/lens/overlay/translate_button.html index e08c911..5347f277 100644 --- a/chrome/browser/resources/lens/overlay/translate_button.html +++ b/chrome/browser/resources/lens/overlay/translate_button.html
@@ -386,7 +386,8 @@ </style> <div id="translateContainer"> <cr-button id="translateEnableButton" class="button" - on-click="onTranslateButtonClick"> + on-click="onTranslateButtonClick" aria-hidden="[[isTranslateModeEnabled]]" + tabindex$="[[getTabIndexForTranslateEntry(isTranslateModeEnabled)]]"> <span id="translateEnableIcon" class="translate-icon" slot="prefix-icon"> </span> <span id="translateButtonLabel" class="button-label"> @@ -395,7 +396,9 @@ </cr-button> <div id="languagePicker"> <cr-button id="sourceLanguageButton" class="button language-picker-button" - on-click="onSourceLanguageButtonClick"> + on-click="onSourceLanguageButtonClick" + aria-hidden="[[!isTranslateModeEnabled]]" + tabindex$="[[getTabIndexForLanguagePicker(isTranslateModeEnabled)]]"> <span id="starsIcon" slot="prefix-icon"></span> <span id="sourceLanguageLabel" class="button-label language-picker-label"> @@ -405,7 +408,9 @@ </cr-button> <span id="arrowRightIcon"></span> <cr-button id="targetLanguageButton" class="button language-picker-button" - on-click="onTargetLanguageButtonClick"> + on-click="onTargetLanguageButtonClick" + aria-hidden="[[!isTranslateModeEnabled]]" + tabindex$="[[getTabIndexForLanguagePicker(isTranslateModeEnabled)]]"> <span id="targetLanguageLabel" class="button-label language-picker-label"> [[getTargetLanguageDisplayName(targetLanguage)]] </span> @@ -413,7 +418,9 @@ </div> <div id="translateDisableButtonContainer"> <cr-button id="translateDisableButton" class="button" - on-click="onTranslateButtonClick"> + on-click="onTranslateButtonClick" + aria-hidden="[[!isTranslateModeEnabled]]" + tabindex$="[[getTabIndexForLanguagePicker(isTranslateModeEnabled)]]"> </cr-button> <span id="translateDisableIcon" class="translate-icon"></span> </div>
diff --git a/chrome/browser/resources/lens/overlay/translate_button.ts b/chrome/browser/resources/lens/overlay/translate_button.ts index 12ba638..248f8861 100644 --- a/chrome/browser/resources/lens/overlay/translate_button.ts +++ b/chrome/browser/resources/lens/overlay/translate_button.ts
@@ -395,6 +395,14 @@ return this.sourceLanguage === null; } + private getTabIndexForTranslateEntry(): number { + return this.isTranslateModeEnabled ? -1 : 0; + } + + private getTabIndexForLanguagePicker(): number { + return this.isTranslateModeEnabled ? 0 : -1; + } + private getAutoCheckedClass( sourceLanguage: chrome.languageSettingsPrivate.Language): string { return sourceLanguage === null ? 'selected' : '';
diff --git a/chrome/browser/resources/new_tab_page/modules/v2/most_relevant_tab_resumption/module.ts b/chrome/browser/resources/new_tab_page/modules/v2/most_relevant_tab_resumption/module.ts index 1baed51f..f0b0ab4e 100644 --- a/chrome/browser/resources/new_tab_page/modules/v2/most_relevant_tab_resumption/module.ts +++ b/chrome/browser/resources/new_tab_page/modules/v2/most_relevant_tab_resumption/module.ts
@@ -134,7 +134,8 @@ } private onDismissButtonClick_(e: DomRepeatEvent<URLVisit>) { - e.preventDefault(); + e.preventDefault(); // Stop navigation + e.stopPropagation(); // Stop firing of click handler const urlVisit = (e.target! as HTMLElement).parentElement!; const index = e.model.index; chrome.metricsPrivate.recordSmallCount(
diff --git a/chrome/browser/resources/password_manager/chrome_branded_manifest.webmanifest b/chrome/browser/resources/password_manager/chrome_branded_manifest.webmanifest index cf0c669..6d8075f8 100644 --- a/chrome/browser/resources/password_manager/chrome_branded_manifest.webmanifest +++ b/chrome/browser/resources/password_manager/chrome_branded_manifest.webmanifest
@@ -1,6 +1,6 @@ { - "short_name": "Google Password Manager", - "name": "Google Password Manager", + "short_name": "$i18n{passwordManagerTitle}", + "name": "$i18n{passwordManagerTitle}", "icons": [ { "src": "chrome://password-manager/images/password_manager_pwa_icon.svg", @@ -8,6 +8,7 @@ "sizes": "any" } ], + "description": "$i18n{passwordManagerDescription}", "start_url": "/?source=pwa", "id": "chrome://password-manager/", "display": "standalone",
diff --git a/chrome/browser/resources/password_manager/manifest.webmanifest b/chrome/browser/resources/password_manager/manifest.webmanifest index 3a4278be..56bc0ea 100644 --- a/chrome/browser/resources/password_manager/manifest.webmanifest +++ b/chrome/browser/resources/password_manager/manifest.webmanifest
@@ -1,6 +1,6 @@ { - "short_name": "Password Manager", - "name": "Password Manager", + "short_name": "$i18n{passwordManagerTitle}", + "name": "$i18n{passwordManagerTitle}", "icons": [ { "src": "chrome://password-manager/images/password_manager_logo.svg", @@ -12,4 +12,4 @@ "id": "chrome://password-manager/", "display": "standalone", "scope": "chrome://password-manager/" -} \ No newline at end of file +}
diff --git a/chrome/browser/resources/search_engine_choice/OWNERS b/chrome/browser/resources/search_engine_choice/OWNERS index a8ff91d..c7aa42b 100644 --- a/chrome/browser/resources/search_engine_choice/OWNERS +++ b/chrome/browser/resources/search_engine_choice/OWNERS
@@ -1 +1 @@ -file://components/search_engines/search_engine_choice/OWNERS +file://components/search_engines/search_engine_choice/COMPLIANCE_OWNERS
diff --git a/chrome/browser/resources/side_panel/customize_chrome/categories.ts b/chrome/browser/resources/side_panel/customize_chrome/categories.ts index ed95370..64ef3d0 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/categories.ts +++ b/chrome/browser/resources/side_panel/customize_chrome/categories.ts
@@ -23,7 +23,7 @@ import {getCss} from './categories.css.js'; import {getHtml} from './categories.html.js'; -import {CustomizeChromeAction, recordCustomizeChromeAction} from './common.js'; +import {CustomizeChromeAction, NtpImageType, recordCustomizeChromeAction, recordCustomizeChromeImageError} from './common.js'; import type {BackgroundCollection, CustomizeChromePageHandlerInterface, Theme} from './customize_chrome.mojom-webui.js'; import {CustomizeChromeApiProxy} from './customize_chrome_api_proxy.js'; import {WindowProxy} from './window_proxy.js'; @@ -193,6 +193,7 @@ if (!this.imageErrorDetectionEnabled_) { return; } + recordCustomizeChromeImageError(NtpImageType.COLLECTIONS); const index = Number((e.currentTarget as HTMLElement).dataset['index']); assert(this.collections_[index]); this.pageHandler_
diff --git a/chrome/browser/resources/side_panel/customize_chrome/common.ts b/chrome/browser/resources/side_panel/customize_chrome/common.ts index 7309b00..6e0f4daf 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/common.ts +++ b/chrome/browser/resources/side_panel/customize_chrome/common.ts
@@ -62,3 +62,25 @@ 'NewTabPage.CustomizeChromeSidePanelImpression', action, CustomizeChromeImpression.MAX_VALUE + 1); } + +/** + * Types of images that are shown on the NTP (and therefore also appear in + * Customize Chrome). This enum must match the numbering for NtpImageType in + * enums.xml. These values are persisted to logs. Entries should not be + * renumbered, removed or reused. + * + * MAX_VALUE should always be at the end to help get the current number of + * buckets. + */ +export enum NtpImageType { + BACKGROUND_IMAGE, + COLLECTIONS, + COLLECTION_IMAGES, + MAX_VALUE = COLLECTION_IMAGES, +} + +export function recordCustomizeChromeImageError(imageType: NtpImageType) { + chrome.metricsPrivate.recordEnumerationValue( + 'NewTabPage.BackgroundService.Images.Headers.ErrorDetected', imageType, + NtpImageType.MAX_VALUE + 1); +}
diff --git a/chrome/browser/resources/side_panel/customize_chrome/themes.html.ts b/chrome/browser/resources/side_panel/customize_chrome/themes.html.ts index e09aa98..f2baec2 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/themes.html.ts +++ b/chrome/browser/resources/side_panel/customize_chrome/themes.html.ts
@@ -34,7 +34,8 @@ <img is="cr-auto-img" data-index="${index}" .autoSrc="${item.previewImageUrl.url}" draggable="false" - @load="${this.onPreviewImageLoad_}"> + @load="${this.onPreviewImageLoad_}" + @error="${this.onPreviewImageError_}"> </img> </div> </customize-chrome-check-mark-wrapper>
diff --git a/chrome/browser/resources/side_panel/customize_chrome/themes.ts b/chrome/browser/resources/side_panel/customize_chrome/themes.ts index ef1c292..47196caa 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/themes.ts +++ b/chrome/browser/resources/side_panel/customize_chrome/themes.ts
@@ -18,7 +18,7 @@ import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; import type {PropertyValues} from 'chrome://resources/lit/v3_0/lit.rollup.js'; -import {CustomizeChromeAction, recordCustomizeChromeAction} from './common.js'; +import {CustomizeChromeAction, NtpImageType, recordCustomizeChromeAction, recordCustomizeChromeImageError} from './common.js'; import type {BackgroundCollection, CollectionImage, CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerInterface, Theme} from './customize_chrome.mojom-webui.js'; import {CustomizeChromeApiProxy} from './customize_chrome_api_proxy.js'; import {getCss} from './themes.css.js'; @@ -170,6 +170,12 @@ this.previewImageLoadStartEpoch_)); } + protected onPreviewImageError_() { + if (this.imageErrorDetectionEnabled_) { + recordCustomizeChromeImageError(NtpImageType.BACKGROUND_IMAGE); + } + } + private onCollectionChange_() { this.header_ = ''; this.themes_ = [];
diff --git a/chrome/browser/search/background/ntp_background_service.cc b/chrome/browser/search/background/ntp_background_service.cc index 17577bd..3984ab24 100644 --- a/chrome/browser/search/background/ntp_background_service.cc +++ b/chrome/browser/search/background/ntp_background_service.cc
@@ -374,10 +374,6 @@ void NtpBackgroundService::FetchReplacementCollectionPreviewImage( const std::string& collection_id, FetchReplacementImageCallback fetch_replacement_image_callback) { - // TODO(b:367702048) - Move metric to frontend, where the error was detected. - UMA_HISTOGRAM_ENUMERATION( - "NewTabPage.BackgroundService.Images.Headers.ErrorDetected", - NtpImageType::kCollections); FetchCollectionImageInfoInternal( collection_id, base::BindOnce(&NtpBackgroundService::
diff --git a/chrome/browser/search/background/ntp_background_service_unittest.cc b/chrome/browser/search/background/ntp_background_service_unittest.cc index ba49c83..ddd2fb6 100644 --- a/chrome/browser/search/background/ntp_background_service_unittest.cc +++ b/chrome/browser/search/background/ntp_background_service_unittest.cc
@@ -12,6 +12,7 @@ #include "base/run_loop.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/run_until.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "chrome/browser/browser_process.h" @@ -45,17 +46,13 @@ } // namespace -class NtpBackgroundServiceTest : public testing::Test, - public ::testing::WithParamInterface<bool> { +class NtpBackgroundServiceTest : public testing::Test { public: NtpBackgroundServiceTest() : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP), test_shared_loader_factory_( base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &test_url_loader_factory_)) { - feature_list_.InitWithFeatureState( - std::move(ntp_features::kNtpBackgroundImageErrorDetection), - BackgroundImageErrorDetectionEnabled()); } void TearDown() override { @@ -95,10 +92,6 @@ return &test_url_loader_factory_; } - // TODO(b:367699101) - Remove test parameters once image error - // detection logic is initiated solely in the frontend. - bool BackgroundImageErrorDetectionEnabled() const { return GetParam(); } - protected: // Required to run tests from UI and threads. content::BrowserTaskEnvironment task_environment_; @@ -111,14 +104,14 @@ std::unique_ptr<NtpBackgroundService> service_; }; -INSTANTIATE_TEST_SUITE_P(All, NtpBackgroundServiceTest, ::testing::Bool()); - -TEST_P(NtpBackgroundServiceTest, CollectionRequest) { +TEST_F(NtpBackgroundServiceTest, CollectionRequest) { g_browser_process->SetApplicationLocale("foo"); - service()->FetchCollectionInfo(); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1u, test_url_loader_factory()->pending_requests()->size()); + service()->FetchCollectionInfo(); + EXPECT_TRUE(base::test::RunUntil([&]() { + return test_url_loader_factory()->pending_requests()->size() == 1u; + })); + std::string request_body(test_url_loader_factory() ->pending_requests() ->at(0) @@ -129,13 +122,7 @@ ntp::background::GetCollectionsRequest collection_request; EXPECT_TRUE(collection_request.ParseFromString(request_body)); EXPECT_EQ("foo", collection_request.language()); - if (BackgroundImageErrorDetectionEnabled()) { - EXPECT_EQ(5, collection_request.filtering_label_size()); - EXPECT_EQ("chrome_desktop_ntp.error_detection", - collection_request.filtering_label(4)); - } else { - EXPECT_EQ(4, collection_request.filtering_label_size()); - } + EXPECT_EQ(4, collection_request.filtering_label_size()); EXPECT_EQ("chrome_desktop_ntp", collection_request.filtering_label(0)); EXPECT_EQ("chrome_desktop_ntp.M" + version_info::GetMajorVersionNumber(), collection_request.filtering_label(1)); @@ -144,7 +131,39 @@ EXPECT_EQ("chrome_desktop_ntp.gm3", collection_request.filtering_label(3)); } -TEST_P(NtpBackgroundServiceTest, CollectionInfoNetworkError) { +TEST_F(NtpBackgroundServiceTest, + CollectionRequestWithImageErrorDetectionEnabled) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + ntp_features::kNtpBackgroundImageErrorDetection); + g_browser_process->SetApplicationLocale("foo"); + + service()->FetchCollectionInfo(); + EXPECT_TRUE(base::test::RunUntil([&]() { + return test_url_loader_factory()->pending_requests()->size() == 1u; + })); + + std::string request_body(test_url_loader_factory() + ->pending_requests() + ->at(0) + .request.request_body->elements() + ->at(0) + .As<network::DataElementBytes>() + .AsStringPiece()); + ntp::background::GetCollectionsRequest collection_request; + EXPECT_TRUE(collection_request.ParseFromString(request_body)); + EXPECT_EQ("foo", collection_request.language()); + EXPECT_EQ(5, collection_request.filtering_label_size()); + EXPECT_EQ("chrome_desktop_ntp.error_detection", + collection_request.filtering_label(4)); + EXPECT_EQ("chrome_desktop_ntp.M" + version_info::GetMajorVersionNumber(), + collection_request.filtering_label(1)); + EXPECT_EQ("chrome_desktop_ntp.panorama", + collection_request.filtering_label(2)); + EXPECT_EQ("chrome_desktop_ntp.gm3", collection_request.filtering_label(3)); +} + +TEST_F(NtpBackgroundServiceTest, CollectionInfoNetworkError) { SetUpResponseWithNetworkError(service()->GetCollectionsLoadURLForTesting()); ASSERT_TRUE(service()->collection_info().empty()); @@ -158,7 +177,7 @@ ErrorType::NET_ERROR); } -TEST_P(NtpBackgroundServiceTest, BadCollectionsResponse) { +TEST_F(NtpBackgroundServiceTest, BadCollectionsResponse) { SetUpResponseWithData(service()->GetCollectionsLoadURLForTesting(), "bad serialized GetCollectionsResponse"); @@ -173,7 +192,7 @@ ErrorType::SERVICE_ERROR); } -TEST_P(NtpBackgroundServiceTest, GoodCollectionsResponse) { +TEST_F(NtpBackgroundServiceTest, GoodCollectionsResponse) { ntp::background::Collection collection; collection.set_collection_id("shapes"); collection.set_collection_name("Shapes"); @@ -203,7 +222,7 @@ EXPECT_EQ(service()->collection_error_info().error_type, ErrorType::NONE); } -TEST_P(NtpBackgroundServiceTest, BrokenCollectionPreviewImageHasNoReplacement) { +TEST_F(NtpBackgroundServiceTest, BrokenCollectionPreviewImageHasNoReplacement) { ntp::background::Collection collection; collection.set_collection_id("shapes"); collection.set_collection_name("Shapes"); @@ -231,15 +250,9 @@ service()->FetchReplacementCollectionPreviewImage( collection.collection_id(), std::move(replacement_image_callback)); run_loop.Run(); - - histogram_tester_.ExpectTotalCount( - "NewTabPage.BackgroundService.Images.Headers.ErrorDetected", 1); - ASSERT_EQ(1, histogram_tester_.GetBucketCount( - "NewTabPage.BackgroundService.Images.Headers.ErrorDetected", - NtpImageType::kCollections)); } -TEST_P(NtpBackgroundServiceTest, BrokenCollectionPreviewImageHasReplacement) { +TEST_F(NtpBackgroundServiceTest, BrokenCollectionPreviewImageHasReplacement) { ntp::background::Collection collection; collection.set_collection_id("shapes"); collection.set_collection_name("Shapes"); @@ -276,16 +289,9 @@ service()->FetchReplacementCollectionPreviewImage( collection.collection_id(), std::move(replacement_image_callback)); run_loop.Run(); - - histogram_tester_.ExpectTotalCount( - "NewTabPage.BackgroundService.Images.Headers.ErrorDetected", 1); - ASSERT_EQ(1, - histogram_tester_.GetBucketCount( - "NewTabPage.BackgroundService.Images.Headers.ErrorDetected", - NtpImageType::kCollections)); } -TEST_P(NtpBackgroundServiceTest, CollectionImagesNetworkError) { +TEST_F(NtpBackgroundServiceTest, CollectionImagesNetworkError) { SetUpResponseWithNetworkError(service()->GetImagesURLForTesting()); ASSERT_TRUE(service()->collection_images().empty()); @@ -294,16 +300,12 @@ service()->FetchCollectionImageInfo("shapes"); base::RunLoop().RunUntilIdle(); - if (BackgroundImageErrorDetectionEnabled()) { - histogram_tester_.ExpectTotalCount( - "NewTabPage.BackgroundService.Images.Headers.ErrorDetected", 0); - } EXPECT_TRUE(service()->collection_images().empty()); EXPECT_EQ(service()->collection_images_error_info().error_type, ErrorType::NET_ERROR); } -TEST_P(NtpBackgroundServiceTest, BadCollectionImagesResponse) { +TEST_F(NtpBackgroundServiceTest, BadCollectionImagesResponse) { SetUpResponseWithData(service()->GetImagesURLForTesting(), "bad serialized GetImagesInCollectionResponse"); @@ -313,16 +315,12 @@ service()->FetchCollectionImageInfo("shapes"); base::RunLoop().RunUntilIdle(); - if (BackgroundImageErrorDetectionEnabled()) { - histogram_tester_.ExpectTotalCount( - "NewTabPage.BackgroundService.Images.Headers.ErrorDetected", 0); - } EXPECT_TRUE(service()->collection_images().empty()); EXPECT_EQ(service()->collection_images_error_info().error_type, ErrorType::SERVICE_ERROR); } -TEST_P(NtpBackgroundServiceTest, ImageInCollectionHasNetworkError) { +TEST_F(NtpBackgroundServiceTest, ImageInCollectionHasNetworkError) { ntp::background::Image image; image.set_asset_id(12345); image.set_image_url(kTestImageUrl); @@ -357,7 +355,7 @@ ErrorType::NONE); } -TEST_P(NtpBackgroundServiceTest, GoodCollectionImagesResponse) { +TEST_F(NtpBackgroundServiceTest, GoodCollectionImagesResponse) { ntp::background::Image image; image.set_asset_id(12345); image.set_image_url(kTestImageUrl); @@ -386,17 +384,13 @@ collection_image.attribution.push_back(image.attribution(0).text()); collection_image.attribution_action_url = GURL(image.action_url()); - if (BackgroundImageErrorDetectionEnabled()) { - histogram_tester_.ExpectTotalCount( - "NewTabPage.BackgroundService.Images.Headers.ErrorDetected", 0); - } EXPECT_FALSE(service()->collection_images().empty()); EXPECT_THAT(service()->collection_images().at(0), Eq(collection_image)); EXPECT_EQ(service()->collection_images_error_info().error_type, ErrorType::NONE); } -TEST_P(NtpBackgroundServiceTest, +TEST_F(NtpBackgroundServiceTest, CollectionImageInfoRequestsAreIgnoredIfAnotherIsInProgress) { ntp::background::Collection collection; collection.set_collection_id("shapes"); @@ -447,17 +441,13 @@ GURL(image.image_url() + service()->GetImageOptionsForTesting()); collection_image.attribution.push_back(image.attribution(0).text()); - if (BackgroundImageErrorDetectionEnabled()) { - histogram_tester_.ExpectTotalCount( - "NewTabPage.BackgroundService.Images.Headers.ErrorDetected", 0); - } EXPECT_FALSE(service()->collection_info().empty()); EXPECT_THAT(service()->collection_info().at(0), Eq(collection_info)); EXPECT_FALSE(service()->collection_images().empty()); EXPECT_THAT(service()->collection_images().at(0), Eq(collection_image)); } -TEST_P(NtpBackgroundServiceTest, +TEST_F(NtpBackgroundServiceTest, CollectionImageInfoCanBeSuccessfullyFetchedMultipleTimes) { ntp::background::Image image; image.set_image_url(kTestImageUrl); @@ -482,7 +472,7 @@ EXPECT_THAT(service()->collection_images().at(0).collection_id, "colors"); } -TEST_P(NtpBackgroundServiceTest, NextImageNetworkError) { +TEST_F(NtpBackgroundServiceTest, NextImageNetworkError) { SetUpResponseWithNetworkError(service()->GetNextImageURLForTesting()); service()->FetchNextCollectionImage("shapes", std::nullopt); @@ -492,7 +482,7 @@ Eq(ErrorType::NET_ERROR)); } -TEST_P(NtpBackgroundServiceTest, BadNextImageResponse) { +TEST_F(NtpBackgroundServiceTest, BadNextImageResponse) { SetUpResponseWithData(service()->GetNextImageURLForTesting(), "bad serialized GetImageFromCollectionResponse"); @@ -503,7 +493,7 @@ Eq(ErrorType::SERVICE_ERROR)); } -TEST_P(NtpBackgroundServiceTest, GoodNextImageResponse) { +TEST_F(NtpBackgroundServiceTest, GoodNextImageResponse) { ntp::background::Image image; image.set_asset_id(12345); image.set_image_url(kTestImageUrl); @@ -540,7 +530,7 @@ Eq(ErrorType::NONE)); } -TEST_P(NtpBackgroundServiceTest, MultipleRequestsNextImage) { +TEST_F(NtpBackgroundServiceTest, MultipleRequestsNextImage) { ntp::background::Image image; image.set_asset_id(12345); image.set_image_url(kTestImageUrl); @@ -580,7 +570,7 @@ Eq(ErrorType::NONE)); } -TEST_P(NtpBackgroundServiceTest, CheckValidAndInvalidBackdropUrls) { +TEST_F(NtpBackgroundServiceTest, CheckValidAndInvalidBackdropUrls) { ntp::background::Image image; image.set_asset_id(12345); image.set_image_url(kTestImageUrl); @@ -599,10 +589,6 @@ service()->FetchCollectionImageInfo("shapes"); base::RunLoop().RunUntilIdle(); - if (BackgroundImageErrorDetectionEnabled()) { - histogram_tester_.ExpectTotalCount( - "NewTabPage.BackgroundService.Images.Headers.ErrorDetected", 0); - } EXPECT_TRUE(service()->IsValidBackdropUrl( GURL(image.image_url() + service()->GetImageOptionsForTesting()))); EXPECT_FALSE(service()->IsValidBackdropUrl( @@ -611,7 +597,7 @@ GURL("https://wallpapers.co/another_image"))); } -TEST_P(NtpBackgroundServiceTest, GetThumbnailUrl) { +TEST_F(NtpBackgroundServiceTest, GetThumbnailUrl) { const GURL kInvalidUrl("foo"); const GURL kValidUrl("https://www.foo.com"); const GURL kValidThumbnailUrl("https://www.foo.com/thumbnail"); @@ -622,7 +608,7 @@ EXPECT_EQ(GURL(), service()->GetThumbnailUrl(kInvalidUrl)); } -TEST_P(NtpBackgroundServiceTest, OverrideBaseUrl) { +TEST_F(NtpBackgroundServiceTest, OverrideBaseUrl) { base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( "collections-base-url", "https://foo.com"); service()->FetchCollectionInfo(); @@ -633,7 +619,7 @@ test_url_loader_factory()->pending_requests()->at(0).request.url); } -TEST_P(NtpBackgroundServiceTest, VerifyURLMetricsWithNetworkSuccess) { +TEST_F(NtpBackgroundServiceTest, VerifyURLMetricsWithNetworkSuccess) { SetUpResponseWithNetworkSuccess(GURL(kTestImageUrl)); histogram_tester_.ExpectTotalCount( "NewTabPage.BackgroundService.Images.Headers.RequestLatency", 0); @@ -659,7 +645,7 @@ net::HTTP_OK)); } -TEST_P(NtpBackgroundServiceTest, VerifyURLMetricsWithNetworkError) { +TEST_F(NtpBackgroundServiceTest, VerifyURLMetricsWithNetworkError) { SetUpResponseWithNetworkError(GURL(kTestImageUrl)); histogram_tester_.ExpectTotalCount( "NewTabPage.BackgroundService.Images.Headers.RequestLatency", 0);
diff --git a/chrome/browser/search_engine_choice/OWNERS b/chrome/browser/search_engine_choice/OWNERS index 5d7e015..c7aa42b 100644 --- a/chrome/browser/search_engine_choice/OWNERS +++ b/chrome/browser/search_engine_choice/OWNERS
@@ -1 +1 @@ -file://components/search_engines/search_engine_choice/OWNERS \ No newline at end of file +file://components/search_engines/search_engine_choice/COMPLIANCE_OWNERS
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java index dc2def9..7dfe52e 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java
@@ -128,13 +128,11 @@ if (bottomSheet == mBottomSheet) { mBottomSheet .getContentView() - .addOnLayoutChangeListener( - ShareSheetCoordinator.this::onLayoutChange); + .addOnLayoutChangeListener(ShareSheetCoordinator.this); } else { mBottomSheet .getContentView() - .removeOnLayoutChangeListener( - ShareSheetCoordinator.this::onLayoutChange); + .removeOnLayoutChangeListener(ShareSheetCoordinator.this); } } };
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/page_info_sheet/PageInfoSharingControllerUnitTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/page_info_sheet/PageInfoSharingControllerUnitTest.java index b2ab65f8..0a62f9b 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/page_info_sheet/PageInfoSharingControllerUnitTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/page_info_sheet/PageInfoSharingControllerUnitTest.java
@@ -883,7 +883,9 @@ .findViewById(R.id.learn_more_text); var learnMoreTextLinks = learnMoreText.getClickableSpans(); assertNotEquals( - "TextView should contain clickable spans", 0, learnMoreTextLinks); + "TextView should contain clickable spans", + 0, + learnMoreTextLinks.length); // Click first span, which should contain a "learn more" text and link to a web // page. learnMoreTextLinks[0].onClick(learnMoreText);
diff --git a/chrome/browser/signin/BUILD.gn b/chrome/browser/signin/BUILD.gn index acf1538..71997ec 100644 --- a/chrome/browser/signin/BUILD.gn +++ b/chrome/browser/signin/BUILD.gn
@@ -61,6 +61,7 @@ "//chrome/browser/search_engines", "//chrome/browser/themes", "//chrome/browser/ui:browser_list", + "//chrome/browser/ui:ui_features", "//chrome/browser/ui/signin", "//chrome/common:channel_info", "//chrome/common:constants",
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.cc b/chrome/browser/signin/dice_web_signin_interceptor.cc index 9a722ea..0db8385 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor.cc +++ b/chrome/browser/signin/dice_web_signin_interceptor.cc
@@ -51,6 +51,7 @@ #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" #include "chrome/browser/ui/profiles/profile_colors_util.h" #include "chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.h" +#include "chrome/browser/ui/ui_features.h" #include "chrome/common/channel_info.h" #include "chrome/common/pref_names.h" #include "chrome/common/themes/autogenerated_theme_util.h" @@ -788,7 +789,7 @@ DCHECK(IsRequiredExtendedAccountInfoAvailable(intercepted_account_info)); if (!base::FeatureList::IsEnabled( - kShowEnterpriseDialogForAllManagedAccountsSignin)) { + features::kEnterpriseUpdatedProfileCreationScreen)) { return false; } @@ -800,11 +801,16 @@ return false; } - // Check if the intercepted account is managed. - if (intercepted_account_info.IsManaged() && + // Check if the intercepted account is managed and has not yet accepted + // management. + if (!intercepted_account_info.IsManaged() || + enterprise_util::UserAcceptedAccountManagement(profile_)) { + return false; + } + + if (switches::IsImprovedSigninUIOnDesktopEnabled() || IsPrimaryAccountInterception(intercepted_account_info.account_id, - identity_manager_) && - !enterprise_util::UserAcceptedAccountManagement(profile_)) { + identity_manager_)) { return true; } @@ -1375,13 +1381,16 @@ } else { DCHECK_EQ(SigninInterceptionResult::kDeclined, create) << "The user can only accept or decline"; + if (state_->interception_type_ == + WebSigninInterceptor::SigninInterceptionType::kEnterpriseForced) { + auto* accounts_mutator = identity_manager_->GetAccountsMutator(); + accounts_mutator->RemoveAccount( + account_info.account_id, + signin_metrics::SourceForRefreshTokenOperation:: + kEnterpriseForcedProfileCreation_UserDecline); + } OnProfileCreationChoice(account_info, profile_color, SigninInterceptionResult::kDeclined); - auto* accounts_mutator = identity_manager_->GetAccountsMutator(); - accounts_mutator->RemoveAccount( - account_info.account_id, - signin_metrics::SourceForRefreshTokenOperation:: - kTurnOnSyncHelper_Abort); } }
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc b/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc index 46d739ac..9487c1e 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc +++ b/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc
@@ -26,6 +26,7 @@ #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" #include "chrome/browser/signin/web_signin_interceptor.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/ui_features.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/browser_with_test_window_test.h" @@ -495,7 +496,7 @@ NoForcedInterceptionShowsDialogIfFeatureEnabled) { base::test::ScopedFeatureList scoped_list; scoped_list.InitAndEnableFeature( - kShowEnterpriseDialogForAllManagedAccountsSignin); + features::kEnterpriseUpdatedProfileCreationScreen); // Reauth intercepted if enterprise confirmation not shown yet for forced // managed separation. AccountInfo account_info = identity_test_env()->MakePrimaryAccountAvailable( @@ -523,7 +524,7 @@ NoForcedInterceptionShowsNoDialogIfFeatureEnabledButDisabledDialogByPolicy) { base::test::ScopedFeatureList scoped_list; scoped_list.InitAndEnableFeature( - kShowEnterpriseDialogForAllManagedAccountsSignin); + features::kEnterpriseUpdatedProfileCreationScreen); // Reauth intercepted if enterprise confirmation not shown yet for forced // managed separation. AccountInfo account_info = identity_test_env()->MakePrimaryAccountAvailable(
diff --git a/chrome/browser/site_protection/site_familiarity_heuristic_name.h b/chrome/browser/site_protection/site_familiarity_heuristic_name.h index 09ba54d..575bd5a8 100644 --- a/chrome/browser/site_protection/site_familiarity_heuristic_name.h +++ b/chrome/browser/site_protection/site_familiarity_heuristic_name.h
@@ -22,7 +22,8 @@ kSiteEngagementScoreExists = 7, kNoVisitsToAnySiteMoreThanADayAgo = 8, kGlobalAllowlistNotReady = 9, - kMaxValue = kGlobalAllowlistNotReady, + kFamiliarLikelyPreviouslyUnfamiliar = 10, + kMaxValue = kFamiliarLikelyPreviouslyUnfamiliar, }; // Subset of SiteFamiliarityHeuristicName for heuristics related to navigation @@ -32,6 +33,7 @@ kVisitedMoreThanADayAgo = 1, kVisitedMoreThanFourHoursAgo = 2, kNoVisitsToAnySiteMoreThanADayAgo = 3, + kVisitedMoreThanADayAgoPreviouslyUnfamiliar = 4, }; } // namespace site_protection
diff --git a/chrome/browser/site_protection/site_protection_metrics_observer.cc b/chrome/browser/site_protection/site_protection_metrics_observer.cc index db67e7e..51c5bd0f 100644 --- a/chrome/browser/site_protection/site_protection_metrics_observer.cc +++ b/chrome/browser/site_protection/site_protection_metrics_observer.cc
@@ -140,6 +140,7 @@ SiteFamiliarityHeuristicName::kVisitedMoreThanFourHoursAgo); metrics_data->most_strict_matched_history_heuristic = SiteFamiliarityHistoryHeuristicName::kVisitedMoreThanFourHoursAgo; + metrics_data->last_visit_time = last_visit_result.last_visit; if (last_visit_result.last_visit < (base::Time::Now() - base::Days(1))) { OnGotVisitToOriginOlderThanADayAgo(std::move(metrics_data), @@ -165,6 +166,7 @@ SiteFamiliarityHeuristicName::kVisitedMoreThanADayAgo); metrics_data->most_strict_matched_history_heuristic = SiteFamiliarityHistoryHeuristicName::kVisitedMoreThanADayAgo; + metrics_data->last_visit_time = last_visit_result.last_visit; OnKnowIfAnyVisitOlderThanADayAgo(std::move(metrics_data), /*has_visit_older_than_a_day_ago=*/true); return; @@ -204,18 +206,20 @@ GURL last_committed_url = metrics_data->last_committed_url; database_manager->CheckUrlForHighConfidenceAllowlist( last_committed_url, - base::BindOnce(&SiteProtectionMetricsObserver::LogMetrics, + base::BindOnce(&SiteProtectionMetricsObserver:: + OnGotHighConfidenceAllowlistResult, weak_factory_.GetWeakPtr(), std::move(metrics_data))); return; } } - LogMetrics(std::move(metrics_data), - /*url_on_safe_browsing_high_confidence_allowlist=*/false, - /*logging_details=*/std::nullopt); + OnGotHighConfidenceAllowlistResult( + std::move(metrics_data), + /*url_on_safe_browsing_high_confidence_allowlist=*/false, + /*logging_details=*/std::nullopt); } -void SiteProtectionMetricsObserver::LogMetrics( +void SiteProtectionMetricsObserver::OnGotHighConfidenceAllowlistResult( std::unique_ptr<MetricsData> metrics_data, bool url_on_safe_browsing_high_confidence_allowlist, std::optional<safe_browsing::SafeBrowsingDatabaseManager:: @@ -228,10 +232,95 @@ url_on_safe_browsing_high_confidence_allowlist = false; } if (url_on_safe_browsing_high_confidence_allowlist) { + metrics_data->url_on_safe_browsing_high_confidence_allowlist = true; metrics_data->matched_heuristics.push_back( SiteFamiliarityHeuristicName::kGlobalAllowlistMatch); } + // Guess as to whether the site was previously categorized as unfamiliar. + // + // For the purpose of + // SiteFamiliarityHeuristicName::kFamiliarLikelyPreviouslyUnfamiliar an + // unfamiliar site is a site which is: + // - Not on the safe browsing high confidence allowlist + // AND + // - Wasn't visited more than 24 hours ago + // AND + // - Wasn't visited with a fresh profile which doesn't have any history + // older than 24 hours. + // + // Assume that high confidence allowlist is stable and that if origin is + // currently on high confidence allowlist that it would have been previously + // on high confidence allowlist. Ignore site engagement score. Ignoring + // site engagement score is ok because the site engagement score is capped + // for site engagement all on the same day. + std::optional<base::Time> last_visit_time = metrics_data->last_visit_time; + if (!url_on_safe_browsing_high_confidence_allowlist && last_visit_time && + *last_visit_time < (base::Time::Now() - base::Days(1))) { + url::Origin last_committed_origin = metrics_data->last_committed_origin; + history_service_->GetLastVisitToOrigin( + last_committed_origin, base::Time(), *last_visit_time - base::Days(1), + base::BindOnce(&SiteProtectionMetricsObserver:: + OnGotVisitToOriginOlderThanADayPriorToPreviousVisit, + weak_factory_.GetWeakPtr(), std::move(metrics_data)), + &task_tracker_); + return; + } + + LogMetrics(std::move(metrics_data)); +} + +void SiteProtectionMetricsObserver:: + OnGotVisitToOriginOlderThanADayPriorToPreviousVisit( + std::unique_ptr<MetricsData> metrics_data, + history::HistoryLastVisitResult last_visit_result) { + if (!last_visit_result.success || last_visit_result.last_visit.is_null()) { + // Check whether + // SiteFamiliarityHistoryHeuristicName::kNoVisitsToAnySiteMoreThanADayAgo + // heuristic would have matched the previous visit. + history::QueryOptions history_query_options; + history_query_options.end_time = + *metrics_data->last_visit_time - base::Days(1); + history_query_options.max_count = 1; + history_service_->QueryHistory( + u"", std::move(history_query_options), + base::BindOnce(&SiteProtectionMetricsObserver:: + OnGotVisitOlderThanADayPriorToPreviousVisit, + weak_factory_.GetWeakPtr(), std::move(metrics_data)), + &task_tracker_); + return; + } + + OnKnowIfSiteWasLikelyPreviouslyFamiliar( + std::move(metrics_data), + /*was_site_likely_previously_familiar=*/true); + return; +} + +void SiteProtectionMetricsObserver::OnGotVisitOlderThanADayPriorToPreviousVisit( + std::unique_ptr<MetricsData> metrics_data, + history::QueryResults query_results) { + OnKnowIfSiteWasLikelyPreviouslyFamiliar( + std::move(metrics_data), + /*was_site_likely_previously_familiar=*/query_results.empty()); +} + +void SiteProtectionMetricsObserver::OnKnowIfSiteWasLikelyPreviouslyFamiliar( + std::unique_ptr<MetricsData> metrics_data, + bool was_site_likely_previously_familiar) { + if (!was_site_likely_previously_familiar) { + metrics_data->matched_heuristics.push_back( + SiteFamiliarityHeuristicName::kFamiliarLikelyPreviouslyUnfamiliar); + metrics_data->most_strict_matched_history_heuristic = + SiteFamiliarityHistoryHeuristicName:: + kVisitedMoreThanADayAgoPreviouslyUnfamiliar; + } + + LogMetrics(std::move(metrics_data)); +} + +void SiteProtectionMetricsObserver::LogMetrics( + std::unique_ptr<MetricsData> metrics_data) { bool no_heuristics_match = metrics_data->matched_heuristics.empty(); if (no_heuristics_match) { metrics_data->matched_heuristics.push_back( @@ -257,7 +346,7 @@ ukm::builders::SiteFamiliarityHeuristicResult(metrics_data->ukm_source_id) .SetAnyHeuristicsMatch(!no_heuristics_match) .SetOnHighConfidenceAllowlist( - url_on_safe_browsing_high_confidence_allowlist) + metrics_data->url_on_safe_browsing_high_confidence_allowlist) .SetSiteEngagementScore( RoundSiteEngagementScoreForUkm(metrics_data->site_engagement_score)) .SetSiteFamiliarityHistoryHeuristic(
diff --git a/chrome/browser/site_protection/site_protection_metrics_observer.h b/chrome/browser/site_protection/site_protection_metrics_observer.h index 9d61562..3731a81 100644 --- a/chrome/browser/site_protection/site_protection_metrics_observer.h +++ b/chrome/browser/site_protection/site_protection_metrics_observer.h
@@ -72,9 +72,11 @@ ukm::SourceId ukm_source_id = ukm::kInvalidSourceId; double site_engagement_score = 0; + bool url_on_safe_browsing_high_confidence_allowlist = false; GURL last_committed_url; url::Origin last_committed_origin; base::Time data_fetch_start_time; + std::optional<base::Time> last_visit_time; std::vector<SiteFamiliarityHeuristicName> matched_heuristics; SiteFamiliarityHistoryHeuristicName most_strict_matched_history_heuristic = SiteFamiliarityHistoryHeuristicName::kNoHeuristicMatch; @@ -103,11 +105,33 @@ std::unique_ptr<MetricsData> metrics_data, bool has_visit_older_than_a_day_ago); - void LogMetrics(std::unique_ptr<MetricsData> metrics_data, - bool url_on_safe_browsing_high_confidence_allowlist, - std::optional<safe_browsing::SafeBrowsingDatabaseManager:: - HighConfidenceAllowlistCheckLoggingDetails> - logging_details); + // Called with whether the site is on the high confidence allowlist. + void OnGotHighConfidenceAllowlistResult( + std::unique_ptr<MetricsData> metrics_data, + bool url_on_safe_browsing_high_confidence_allowlist, + std::optional<safe_browsing::SafeBrowsingDatabaseManager:: + HighConfidenceAllowlistCheckLoggingDetails> + logging_details); + + // Called with the history visit to the origin in `metrics_data` which + // occurred more than a day prior to the most recent visit to the origin. + void OnGotVisitToOriginOlderThanADayPriorToPreviousVisit( + std::unique_ptr<MetricsData> metrics_data, + history::HistoryLastVisitResult last_visit_result); + + // Called with the history visit to any site which occurred more than a day + // prior to the visit to the origin in `metrics_data`. + void OnGotVisitOlderThanADayPriorToPreviousVisit( + std::unique_ptr<MetricsData> metrics_data, + history::QueryResults query_results); + + // Called with whether there is a history visit to any site more than a day + // prior to the visit to the origin in `metrics_data`. + void OnKnowIfSiteWasLikelyPreviouslyFamiliar( + std::unique_ptr<MetricsData> metrics_data, + bool was_site_likely_previously_familiar); + + void LogMetrics(std::unique_ptr<MetricsData> metrics_data); WEB_CONTENTS_USER_DATA_KEY_DECL();
diff --git a/chrome/browser/site_protection/site_protection_metrics_observer_unittest.cc b/chrome/browser/site_protection/site_protection_metrics_observer_unittest.cc index 116be2d0d..84a04845 100644 --- a/chrome/browser/site_protection/site_protection_metrics_observer_unittest.cc +++ b/chrome/browser/site_protection/site_protection_metrics_observer_unittest.cc
@@ -184,6 +184,12 @@ return values.size() == 1u ? values[0] : -1; } + int64_t GetUkmHistoryFamiliarityHeuristicValue( + ukm::TestUkmRecorder& ukm_recorder) { + return GetUkmFamiliarityHeuristicValue(ukm_recorder, + "SiteFamiliarityHistoryHeuristic"); + } + void NavigateAndCheckRecordedHeuristicUkm(const GURL& url, const std::string& metric_name, int64_t expected_value) { @@ -222,8 +228,7 @@ {SiteFamiliarityHeuristicName::kNoVisitsToAnySiteMoreThanADayAgo}); EXPECT_EQ(static_cast<int>(SiteFamiliarityHistoryHeuristicName:: kNoVisitsToAnySiteMoreThanADayAgo), - GetUkmFamiliarityHeuristicValue(ukm_recorder, - "SiteFamiliarityHistoryHeuristic")); + GetUkmHistoryFamiliarityHeuristicValue(ukm_recorder)); } // Test the histograms and UKM which are logged by SiteProtectionMetricsObserver @@ -250,8 +255,7 @@ SiteFamiliarityHeuristicName::kVisitedMoreThanADayAgo}); EXPECT_EQ(static_cast<int>( SiteFamiliarityHistoryHeuristicName::kVisitedMoreThanADayAgo), - GetUkmFamiliarityHeuristicValue( - ukm_recorder, "SiteFamiliarityHistoryHeuristic")); + GetUkmHistoryFamiliarityHeuristicValue(ukm_recorder)); } { @@ -262,8 +266,7 @@ EXPECT_EQ( static_cast<int>( SiteFamiliarityHistoryHeuristicName::kVisitedMoreThanFourHoursAgo), - GetUkmFamiliarityHeuristicValue(ukm_recorder, - "SiteFamiliarityHistoryHeuristic")); + GetUkmHistoryFamiliarityHeuristicValue(ukm_recorder)); } { @@ -272,8 +275,7 @@ kUrlVisited1HourAgo, {SiteFamiliarityHeuristicName::kNoHeuristicMatch}); EXPECT_EQ(static_cast<int>( SiteFamiliarityHistoryHeuristicName::kNoHeuristicMatch), - GetUkmFamiliarityHeuristicValue( - ukm_recorder, "SiteFamiliarityHistoryHeuristic")); + GetUkmHistoryFamiliarityHeuristicValue(ukm_recorder)); } } @@ -383,6 +385,87 @@ } } +// Test that SiteProtectionMetricsObserver logs the correct histograms and UKM +// if the SiteFamiliarityHeuristicName::kVisitedMoreThanADayAgo heuristic +// applies for the current visit to the site but the heuristic did not apply +// to the previous visit to the site. +TEST_F(SiteProtectionMetricsObserverTest, SiteFamiliarWasPreviouslyUnfamiliar) { + GURL kPageUrl("https://bar.com"); + GURL kOtherUrl("https://baz.com"); + + base::Time now = base::Time::Now(); + base::Time kPageVisitTime1 = now - base::Hours(25); + base::Time kPageVisitTime2 = kPageVisitTime1 - base::Hours(25); + base::Time kOtherVisitTime = kPageVisitTime2 - base::Hours(25); + + GetRegularProfileHistoryService()->AddPage(kPageUrl, kPageVisitTime1, + history::SOURCE_BROWSED); + GetRegularProfileHistoryService()->AddPage(kOtherUrl, kOtherVisitTime, + history::SOURCE_BROWSED); + { + ukm::TestAutoSetUkmRecorder ukm_recorder; + NavigateAndCheckRecordedHeuristicHistograms( + kPageUrl, + {SiteFamiliarityHeuristicName::kVisitedMoreThanFourHoursAgo, + SiteFamiliarityHeuristicName::kVisitedMoreThanADayAgo, + SiteFamiliarityHeuristicName::kFamiliarLikelyPreviouslyUnfamiliar}); + EXPECT_EQ(static_cast<int>(SiteFamiliarityHistoryHeuristicName:: + kVisitedMoreThanADayAgoPreviouslyUnfamiliar), + GetUkmHistoryFamiliarityHeuristicValue(ukm_recorder)); + } + + GetRegularProfileHistoryService()->AddPage(kPageUrl, kPageVisitTime2, + history::SOURCE_BROWSED); + + { + ukm::TestAutoSetUkmRecorder ukm_recorder; + NavigateAndCheckRecordedHeuristicHistograms( + kPageUrl, {SiteFamiliarityHeuristicName::kVisitedMoreThanFourHoursAgo, + SiteFamiliarityHeuristicName::kVisitedMoreThanADayAgo}); + EXPECT_EQ(static_cast<int>( + SiteFamiliarityHistoryHeuristicName::kVisitedMoreThanADayAgo), + GetUkmHistoryFamiliarityHeuristicValue(ukm_recorder)); + } +} + +// Test that SiteProtectionMetricsObserver logs the correct histograms +// if: +// - SiteFamiliarityHeuristicName::kVisitedMoreThanADayAgo heuristic +// applies for the current visit. +// AND +// - SiteFamiliarityHeuristicName::kVisitedMoreThanADayAgo heuristic +// does not apply to the previous visit. +// AND +// - SiteFamiliarityHeuristicName::kNoVisitsToAnySiteMoreThanADayAgo +// applies to the previous visit. +TEST_F(SiteProtectionMetricsObserverTest, + SiteFamiliarWasPreviouslyUnfamiliarDueToNoOldHistory) { + GURL kPageUrl("https://bar.com"); + GURL kOtherUrl("https://baz.com"); + + base::Time now = base::Time::Now(); + base::Time kPageVisitTime = now - base::Hours(25); + base::Time kOtherVisitTime1 = kPageVisitTime - base::Hours(1); + base::Time kOtherVisitTime2 = kOtherVisitTime1 - base::Hours(100); + + GetRegularProfileHistoryService()->AddPage(kPageUrl, kPageVisitTime, + history::SOURCE_BROWSED); + GetRegularProfileHistoryService()->AddPage(kOtherUrl, kOtherVisitTime1, + history::SOURCE_BROWSED); + + NavigateAndCheckRecordedHeuristicHistograms( + kPageUrl, {SiteFamiliarityHeuristicName::kVisitedMoreThanFourHoursAgo, + SiteFamiliarityHeuristicName::kVisitedMoreThanADayAgo}); + + GetRegularProfileHistoryService()->AddPage(kOtherUrl, kOtherVisitTime2, + history::SOURCE_BROWSED); + NavigateAndCheckRecordedHeuristicHistograms( + kPageUrl, + {SiteFamiliarityHeuristicName::kVisitedMoreThanFourHoursAgo, + SiteFamiliarityHeuristicName::kVisitedMoreThanADayAgo, + SiteFamiliarityHeuristicName::kFamiliarLikelyPreviouslyUnfamiliar}); +} + // Test that SiteProtectionMetricsObserver logs whether any heuristics matched // to UKM. TEST_F(SiteProtectionMetricsObserverTest, AnyHeuristicsMatchUkm) {
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java index 49e1183..3bc27ca 100644 --- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java +++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java
@@ -557,11 +557,10 @@ public static void performStorageMaintenance(List<Integer> liveTabIds) { ThreadUtils.assertOnUiThread(); for (Class<? extends PersistedTabData> clazz : sSupportedMaintenanceClasses) { + // Maintenance is supported only for regular Tabs. + boolean isEncrypted = false; PersistedTabDataConfiguration config = - PersistedTabDataConfiguration.get( - clazz, false - /** Maintenance is only supported for regular Tabs */ - ); + PersistedTabDataConfiguration.get(clazz, isEncrypted); PersistedTabDataStorage storage = config.getStorage(); storage.performMaintenance(liveTabIds, config.getId()); }
diff --git a/chrome/browser/thumbnail/generator/android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaParserTest.java b/chrome/browser/thumbnail/generator/android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaParserTest.java index aef2781..f0692db 100644 --- a/chrome/browser/thumbnail/generator/android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaParserTest.java +++ b/chrome/browser/thumbnail/generator/android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaParserTest.java
@@ -73,29 +73,21 @@ return result; } + /** Verify that the metadata from audio file can be retrieved correctly. */ @Test @LargeTest @Feature({"MediaParser"}) - /** - * Verify that the metadata from audio file can be retrieved correctly. - * - * @throws InterruptedException - */ public void testParseAudioMetatadata() { String filePath = UrlUtils.getIsolatedTestRoot() + "/media/test/data/sfx.mp3"; MediaParserResult result = parseMediaFile(filePath, "audio/mp3"); Assert.assertTrue("Failed to parse audio metadata.", result.mediaData != null); } + /** Verify metadata and thumbnail can be retrieved correctly from h264 video file. */ @Test @LargeTest @Feature({"MediaParser"}) @Restriction(DeviceFormFactor.PHONE) - /** - * Verify metadata and thumbnail can be retrieved correctly from h264 video file. - * - * @throws InterruptedException - */ public void testParseVideoH264() { String filePath = UrlUtils.getIsolatedTestRoot() + "/media/test/data/bear.mp4"; MediaParserResult result = parseMediaFile(filePath, "video/mp4"); @@ -106,14 +98,10 @@ "Failed to retrieve thumbnail.", result.mediaData.thumbnail.getHeight() > 0); } + /** Verify metadata and thumbnail can be retrieved correctly from vp8 video file. */ @Test @LargeTest @Feature({"MediaParser"}) - /** - * Verify metadata and thumbnail can be retrieved correctly from vp8 video file. - * - * @throws InterruptedException - */ public void testParseVideoThumbnailVp8() { String filePath = UrlUtils.getIsolatedTestRoot() + "/media/test/data/bear-vp8-webvtt.webm"; MediaParserResult result = parseMediaFile(filePath, "video/webm"); @@ -124,15 +112,13 @@ "Failed to retrieve thumbnail.", result.mediaData.thumbnail.getHeight() > 0); } - @Test - @LargeTest - @Feature({"MediaParser"}) /** * Verify metadata and thumbnail can be retrieved correctly from vp8 video file with alpha * plane. - * - * @throws InterruptedException */ + @Test + @LargeTest + @Feature({"MediaParser"}) public void testParseVideoThumbnailVp8WithAlphaPlane() { String filePath = UrlUtils.getIsolatedTestRoot() + "/media/test/data/bear-vp8a.webm"; MediaParserResult result = parseMediaFile(filePath, "video/webm"); @@ -143,14 +129,10 @@ "Failed to retrieve thumbnail.", result.mediaData.thumbnail.getHeight() > 0); } + /** Verify metadata and thumbnail can be retrieved correctly from vp9 video file. */ @Test @LargeTest @Feature({"MediaParser"}) - /** - * Verify metadata and thumbnail can be retrieved correctly from vp9 video file. - * - * @throws InterruptedException - */ public void testParseVideoThumbnailVp9() { String filePath = UrlUtils.getIsolatedTestRoot() + "/media/test/data/bear-vp9.webm"; MediaParserResult result = parseMediaFile(filePath, "video/webm"); @@ -161,14 +143,10 @@ "Failed to retrieve thumbnail.", result.mediaData.thumbnail.getHeight() > 0); } + /** Verify metadata and thumbnail can be retrieved correctly from av1 video file. */ @Test @LargeTest @Feature({"MediaParser"}) - /** - * Verify metadata and thumbnail can be retrieved correctly from av1 video file. - * - * @throws InterruptedException - */ public void testParseVideoThumbnailAv1() { String filePath = UrlUtils.getIsolatedTestRoot() + "/media/test/data/bear-av1.mp4"; MediaParserResult result = parseMediaFile(filePath, "video/mp4"); @@ -179,14 +157,10 @@ "Failed to retrieve thumbnail.", result.mediaData.thumbnail.getHeight() > 0); } + /** Verify metadata and thumbnail can be retrieved correctly from h265 video file. */ @Test @LargeTest @Feature({"MediaParser"}) - /** - * Verify metadata and thumbnail can be retrieved correctly from h265 video file. - * - * @throws InterruptedException - */ public void testParseVideoThumbnailH265() { String filePath = UrlUtils.getIsolatedTestRoot() + "/media/test/data/bear-hevc-frag.mp4"; MediaParserResult result = parseMediaFile(filePath, "video/mp4"); @@ -197,14 +171,10 @@ "Failed to retrieve thumbnail.", result.mediaData.thumbnail.getHeight() > 0); } + /** Verify graceful failure on parsing invalid video file. */ @Test @LargeTest @Feature({"MediaParser"}) - /** - * Verify graceful failure on parsing invalid video file. - * - * @throws InterruptedException - */ public void testParseInvalidVideoFile() throws Exception { File invalidFile = File.createTempFile("test", "webm"); MediaParserResult result = parseMediaFile(invalidFile.getAbsolutePath(), "video/webm");
diff --git a/chrome/browser/translate/android/java/src/org/chromium/chrome/browser/translate/AutoTranslateSnackbarControllerJavaTest.java b/chrome/browser/translate/android/java/src/org/chromium/chrome/browser/translate/AutoTranslateSnackbarControllerJavaTest.java index 869bb359..6ae84ee 100644 --- a/chrome/browser/translate/android/java/src/org/chromium/chrome/browser/translate/AutoTranslateSnackbarControllerJavaTest.java +++ b/chrome/browser/translate/android/java/src/org/chromium/chrome/browser/translate/AutoTranslateSnackbarControllerJavaTest.java
@@ -87,14 +87,14 @@ Assert.assertEquals("en", data.getTargetLanguage()); } - @Test - @SmallTest /** * The target language is stored in Translate format, which uses the old deprecated Java codes * for several languages (Hebrew, Indonesian), and uses "tl" while Chromium uses "fil" for * Tagalog/Filipino. This tests that when using Translate format codes the Chrome version is * displayed in the Snackbar. */ + @Test + @SmallTest public void testShowSnackbarChromeLanguage() throws Exception { // Use the Translate tag tl which Chrome should display as "Filipino" showSnackbar("tl");
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImplTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImplTest.java index 72028a9..014ad6fd 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImplTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImplTest.java
@@ -121,6 +121,7 @@ verify(mViewTreeObserver).removeOnGlobalLayoutListener(mImpl); } + @Test public void testRecalculateOmniboxAlignment_phone() { doReturn(mAnchorView).when(mHorizontalAlignmentView).getParent(); doReturn(60).when(mHorizontalAlignmentView).getTop(); @@ -138,6 +139,7 @@ alignment); } + @Test public void testRecalculateOmniboxAlignment_bottomWindowPadding() { mBottomWindowPadding = 40; doReturn(mAnchorView).when(mHorizontalAlignmentView).getParent();
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java index d4568293..b947577 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java
@@ -356,7 +356,8 @@ nextSuggestionLogicalIndex++; } else { assert false - : "Unsupported group render type: " + currentGroupConfig.getRenderType(); + : "Unsupported group render type: " + + currentGroupConfig.getRenderType().name(); } previousGroupConfig = currentGroupConfig;
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java index 261e97e6..f99e9839 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java
@@ -339,7 +339,8 @@ for (AnswerType type : ANSWER_TYPES) { SuggestionTestHelper suggHelper = createAnswerSuggestion(type, "", 1, "", 1, null); // Note: model is re-created on every iteration. - Assert.assertNotNull("No icon associated with type: " + type, suggHelper.getIcon()); + Assert.assertNotNull( + "No icon associated with type: " + type.name(), suggHelper.getIcon()); } } @@ -348,7 +349,8 @@ for (AnswerType type : ANSWER_TYPES) { SuggestionTestHelper suggHelper = createRichAnswerSuggestion(type, 0, false); // Note: model is re-created on every iteration. - Assert.assertNotNull("No icon associated with type: " + type, suggHelper.getIcon()); + Assert.assertNotNull( + "No icon associated with type: " + type.name(), suggHelper.getIcon()); } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DynamicSpacingRecyclerViewItemDecorationUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DynamicSpacingRecyclerViewItemDecorationUnitTest.java index 8ca3109e..a4a2f8b 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DynamicSpacingRecyclerViewItemDecorationUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DynamicSpacingRecyclerViewItemDecorationUnitTest.java
@@ -223,7 +223,8 @@ // It's unlikely that the minimum spacing would guarantee 2.5 items to be shown, but we can // verify this fast. - assertNotEquals(CONTAINER_SIZE, LEAD_IN_SPACE + itemWidth * 2.5 + MIN_ELEMENT_SPACE * 2); + assertNotEquals( + CONTAINER_SIZE, (int) (LEAD_IN_SPACE + itemWidth * 2.5 + MIN_ELEMENT_SPACE * 2)); // However, we don't permit dynamic spacing in landscape mode, so this should fall back to // MIN_ELEMENT_SPACE.
diff --git a/chrome/browser/ui/android/plus_addresses/java/src/org/chromium/chrome/browser/ui/plus_addresses/PlusAddressCreationErrorStateInfo.java b/chrome/browser/ui/android/plus_addresses/java/src/org/chromium/chrome/browser/ui/plus_addresses/PlusAddressCreationErrorStateInfo.java index b2a4079..0892f1ed 100644 --- a/chrome/browser/ui/android/plus_addresses/java/src/org/chromium/chrome/browser/ui/plus_addresses/PlusAddressCreationErrorStateInfo.java +++ b/chrome/browser/ui/android/plus_addresses/java/src/org/chromium/chrome/browser/ui/plus_addresses/PlusAddressCreationErrorStateInfo.java
@@ -10,8 +10,8 @@ import org.jni_zero.JNINamespace; import org.jni_zero.JniType; -@JNINamespace("plus_addresses") /** Contains necessary information to show a meaningful error message to the user. */ +@JNINamespace("plus_addresses") class PlusAddressCreationErrorStateInfo { private final @PlusAddressCreationBottomSheetErrorType int mErrorType; private final String mTitle;
diff --git a/chrome/browser/ui/android/plus_addresses/java/src/org/chromium/chrome/browser/ui/plus_addresses/PlusAddressCreationNormalStateInfo.java b/chrome/browser/ui/android/plus_addresses/java/src/org/chromium/chrome/browser/ui/plus_addresses/PlusAddressCreationNormalStateInfo.java index 35d26d9..d705d40 100644 --- a/chrome/browser/ui/android/plus_addresses/java/src/org/chromium/chrome/browser/ui/plus_addresses/PlusAddressCreationNormalStateInfo.java +++ b/chrome/browser/ui/android/plus_addresses/java/src/org/chromium/chrome/browser/ui/plus_addresses/PlusAddressCreationNormalStateInfo.java
@@ -14,8 +14,8 @@ import java.util.Objects; -@JNINamespace("plus_addresses") /** Contains necessary information to show a meaningful error message to the user. */ +@JNINamespace("plus_addresses") class PlusAddressCreationNormalStateInfo { private final String mTitle; private final String mDescription;
diff --git a/chrome/browser/ui/android/searchactivityutils/java/src/org/chromium/chrome/browser/ui/searchactivityutils/SearchActivityPreferencesManagerTest.java b/chrome/browser/ui/android/searchactivityutils/java/src/org/chromium/chrome/browser/ui/searchactivityutils/SearchActivityPreferencesManagerTest.java index e2955f79..b64af8f 100644 --- a/chrome/browser/ui/android/searchactivityutils/java/src/org/chromium/chrome/browser/ui/searchactivityutils/SearchActivityPreferencesManagerTest.java +++ b/chrome/browser/ui/android/searchactivityutils/java/src/org/chromium/chrome/browser/ui/searchactivityutils/SearchActivityPreferencesManagerTest.java
@@ -144,8 +144,6 @@ SearchActivityPreferences p2 = new SearchActivityPreferences( "test", new GURL("https://test.url"), true, true, true); - Assert.assertEquals(p1, p1); - Assert.assertEquals(p2, p2); Assert.assertEquals(p1, p2); Assert.assertEquals(p1.hashCode(), p2.hashCode());
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/history_sync/HistorySyncTest.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/history_sync/HistorySyncTest.java index 262d84e..0d9aeb2 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/history_sync/HistorySyncTest.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/history_sync/HistorySyncTest.java
@@ -481,13 +481,13 @@ histogramWatcher.assertExpected(); } - @Test - @MediumTest /** * This tests ensure that onClickListeners are attached to the accept/decline buttons when the * HistorySyncCoordinator is created without a view and the MinorModeHelper resolves before a * View is set. */ + @Test + @MediumTest public void testOnClickListenersAttachedWithMinorModeAccount() { mSigninTestRule.addAccountThenSignin(AccountManagerTestRule.AADC_MINOR_ACCOUNT); @@ -532,13 +532,13 @@ }); } - @Test - @MediumTest /** * This tests ensure that onClickListeners are attached to the accept/decline buttons when the * HistorySyncCoordinator is created without a view and the MinorModeHelper resolves before a * View is set. */ + @Test + @MediumTest public void testOnClickListenersAttachedWithNonMinorModeAccount() { mSigninTestRule.addAccountThenSignin(AccountManagerTestRule.AADC_ADULT_ACCOUNT);
diff --git a/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc b/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc index a5d25b62..93be4045 100644 --- a/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc +++ b/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc
@@ -160,7 +160,8 @@ } } void DispatchAccessibilityLocationChange( - const ui::AXLocationChanges& details) override {} + const ui::AXTreeID& tree_id, + const ui::AXLocationChange& details) override {} void DispatchTreeDestroyedEvent(ui::AXTreeID tree_id) override {} void DispatchActionResult( const ui::AXActionData& data,
diff --git a/chrome/browser/ui/fullscreen_util_mac.cc b/chrome/browser/ui/fullscreen_util_mac.cc index 7a3ad19..b94cff2 100644 --- a/chrome/browser/ui/fullscreen_util_mac.cc +++ b/chrome/browser/ui/fullscreen_util_mac.cc
@@ -6,6 +6,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window/public/browser_window_interface.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" @@ -15,12 +16,13 @@ namespace fullscreen_utils { -bool IsInContentFullscreen(Browser* browser) { - if (!browser->exclusive_access_manager()) { +bool IsInContentFullscreen(BrowserWindowInterface* browser_window_interface) { + if (!browser_window_interface->GetExclusiveAccessManager()) { return false; } - FullscreenController* controller = - browser->exclusive_access_manager()->fullscreen_controller(); + FullscreenController* const controller = + browser_window_interface->GetExclusiveAccessManager() + ->fullscreen_controller(); return controller && (controller->IsWindowFullscreenForTabOrPending() || controller->IsExtensionFullscreenOrPending()); }
diff --git a/chrome/browser/ui/fullscreen_util_mac.h b/chrome/browser/ui/fullscreen_util_mac.h index 1db44d4..96ab162 100644 --- a/chrome/browser/ui/fullscreen_util_mac.h +++ b/chrome/browser/ui/fullscreen_util_mac.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_FULLSCREEN_UTIL_MAC_H_ class Browser; +class BrowserWindowInterface; namespace fullscreen_utils { @@ -13,7 +14,7 @@ // - `browser` is currently in fullscreen // - the fullscreen mode is web or extension API initiated (as opposed to via // macOS affordances like traffic lights -bool IsInContentFullscreen(Browser* browser); +bool IsInContentFullscreen(BrowserWindowInterface* browser_window_interface); // Whether the "Always Show Toolbar in Full Screen" setting is enabled. Properly // handles PWAs.
diff --git a/chrome/browser/ui/lens/lens_overlay_controller.cc b/chrome/browser/ui/lens/lens_overlay_controller.cc index d67fcd0..f4371cb 100644 --- a/chrome/browser/ui/lens/lens_overlay_controller.cc +++ b/chrome/browser/ui/lens/lens_overlay_controller.cc
@@ -2096,6 +2096,8 @@ // Add our blur layer to the view. overlay_view_->SetPaintToLayer(); overlay_view_->layer()->Add(lens_overlay_blur_layer_delegate_->layer()); + overlay_view_->layer()->StackAtBottom( + lens_overlay_blur_layer_delegate_->layer()); lens_overlay_blur_layer_delegate_->layer()->SetBounds( overlay_view_->layer()->bounds()); return;
diff --git a/chrome/browser/ui/search_engine_choice/OWNERS b/chrome/browser/ui/search_engine_choice/OWNERS index a8ff91d..c7aa42b 100644 --- a/chrome/browser/ui/search_engine_choice/OWNERS +++ b/chrome/browser/ui/search_engine_choice/OWNERS
@@ -1 +1 @@ -file://components/search_engines/search_engine_choice/OWNERS +file://components/search_engines/search_engine_choice/COMPLIANCE_OWNERS
diff --git a/chrome/browser/ui/toasts/toast_controller.cc b/chrome/browser/ui/toasts/toast_controller.cc index 3fd8031..e7c441b 100644 --- a/chrome/browser/ui/toasts/toast_controller.cc +++ b/chrome/browser/ui/toasts/toast_controller.cc
@@ -36,6 +36,10 @@ #include "ui/views/view.h" #include "ui/views/widget/widget.h" +#if BUILDFLAG(IS_MAC) +#include "chrome/browser/ui/fullscreen_util_mac.h" +#endif + ToastParams::ToastParams(ToastId id) : toast_id_(id) {} ToastParams::ToastParams(ToastParams&& other) noexcept = default; ToastParams& ToastParams::operator=(ToastParams&& other) noexcept = default; @@ -232,6 +236,18 @@ } } +bool ToastController::ShouldRenderToastOverWebContents() { + bool render_in_contents = + browser_window_interface_->ShouldHideUIForFullscreen(); + +#if BUILDFLAG(IS_MAC) + render_in_contents |= + fullscreen_utils::IsInContentFullscreen(browser_window_interface_); +#endif + + return render_in_contents; +} + void ToastController::WebContentsDestroyed() { omnibox_helper_observer_.Reset(); Observe(nullptr); @@ -274,13 +290,13 @@ void ToastController::CreateToast(const ToastParams& params, const ToastSpecification* spec) { - views::View* anchor_view = browser_window_interface_->TopContainer(); + views::View* const anchor_view = browser_window_interface_->TopContainer(); CHECK(anchor_view); auto toast_view = std::make_unique<toasts::ToastView>( anchor_view, FormatString(spec->body_string_id(), params.body_string_replacement_params_), - spec->icon(), browser_window_interface_->ShouldHideUIForFullscreen(), + spec->icon(), ShouldRenderToastOverWebContents(), base::BindRepeating(&RecordToastDismissReason, params.toast_id_)); if (spec->has_close_button()) { @@ -335,7 +351,7 @@ void ToastController::OnFullscreenStateChanged() { toast_view_->UpdateRenderToastOverWebContentsAndPaint( - browser_window_interface_->ShouldHideUIForFullscreen()); + ShouldRenderToastOverWebContents()); } void ToastController::ClearTabScopedToasts() {
diff --git a/chrome/browser/ui/toasts/toast_controller.h b/chrome/browser/ui/toasts/toast_controller.h index eb4f4f3..cd51a6cd 100644 --- a/chrome/browser/ui/toasts/toast_controller.h +++ b/chrome/browser/ui/toasts/toast_controller.h
@@ -91,6 +91,8 @@ views::Widget* GetToastWidgetForTesting() { return toast_widget_; } + toasts::ToastView* GetToastViewForTesting() { return toast_view_; } + base::OneShotTimer* GetToastCloseTimerForTesting(); private: @@ -104,6 +106,7 @@ std::vector<std::u16string> replacement); void ClearTabScopedToasts(); void UpdateToastWidgetVisibility(bool show_toast_widget); + bool ShouldRenderToastOverWebContents(); // FullscreenObserver: void OnFullscreenStateChanged() override;
diff --git a/chrome/browser/ui/toasts/toast_controller_interactive_ui_test.cc b/chrome/browser/ui/toasts/toast_controller_interactive_ui_test.cc index de623d6..7e062c1 100644 --- a/chrome/browser/ui/toasts/toast_controller_interactive_ui_test.cc +++ b/chrome/browser/ui/toasts/toast_controller_interactive_ui_test.cc
@@ -13,6 +13,8 @@ #include "chrome/browser/ui/browser_element_identifiers.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/browser_window/public/browser_window_features.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/location_bar/location_bar.h" #include "chrome/browser/ui/omnibox/omnibox_tab_helper.h" #include "chrome/browser/ui/toasts/api/toast_id.h" @@ -31,10 +33,12 @@ #include "content/public/test/browser_test.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "third_party/blink/public/mojom/frame/fullscreen.mojom.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/interaction/element_identifier.h" #include "ui/base/interaction/interactive_test.h" #include "ui/events/keycodes/keyboard_codes.h" +#include "ui/gfx/geometry/rect.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/focus/focus_manager.h" #include "ui/views/interaction/interactive_views_test.h" @@ -448,3 +452,30 @@ toasts::ToastCloseReason::kAbort, 1); })); } + +IN_PROC_BROWSER_TEST_F(ToastControllerInteractiveTest, + ToastRendersOverWebContents) { +#if BUILDFLAG(IS_MAC) + FullscreenController* const fullscreen_controller = + browser()->exclusive_access_manager()->fullscreen_controller(); + fullscreen_controller->set_is_tab_fullscreen_for_testing(true); +#else + ui_test_utils::FullscreenWaiter waiter(browser(), {.tab_fullscreen = true}); + content::WebContents* const active_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + active_contents->GetDelegate()->EnterFullscreenModeForTab( + active_contents->GetPrimaryMainFrame(), {}); + waiter.Wait(); +#endif + + ToastController* const toast_controller = GetToastController(); + EXPECT_TRUE( + toast_controller->MaybeShowToast(ToastParams(ToastId::kLinkCopied))); + const gfx::Rect toast_bounds = + toast_controller->GetToastViewForTesting()->GetBoundsInScreen(); + const gfx::Rect web_view_bounds = + BrowserView::GetBrowserViewForBrowser(browser()) + ->GetContentsWebView() + ->GetBoundsInScreen(); + EXPECT_TRUE(web_view_bounds.Contains(toast_bounds)); +}
diff --git a/chrome/browser/ui/toasts/toast_view.cc b/chrome/browser/ui/toasts/toast_view.cc index 4e9d9886..55542a8 100644 --- a/chrome/browser/ui/toasts/toast_view.cc +++ b/chrome/browser/ui/toasts/toast_view.cc
@@ -19,9 +19,11 @@ #include "ui/compositor/layer.h" #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/animation/animation_builder.h" +#include "ui/views/border.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/controls/button/image_button_factory.h" #include "ui/views/controls/highlight_path_generator.h" +#include "ui/views/layout/layout_provider.h" #include "ui/views/view_class_properties.h" #include "ui/views/widget/widget.h" #include "ui/views/window/dialog_client_view.h" @@ -143,10 +145,12 @@ close_button_callback_.Then( base::BindRepeating(&ToastView::Close, base::Unretained(this), ToastCloseReason::kCloseButton)), - vector_icons::kCloseIcon, - lp->GetDistanceMetric(DISTANCE_TOAST_BUBBLE_HEIGHT_CONTENT) - - lp->GetInsetsMetric(views::INSETS_VECTOR_IMAGE_BUTTON).height(), + vector_icons::kCloseChromeRefreshIcon, + lp->GetDistanceMetric(DISTANCE_TOAST_BUBBLE_ICON_SIZE), ui::kColorToastForeground)); + // Override the image button's border with the appropriate icon border size. + close_button_->SetBorder(views::CreateEmptyBorder( + lp->GetInsetsMetric(views::InsetsMetric::INSETS_ICON_BUTTON))); views::InstallCircleHighlightPathGenerator(close_button_); close_button_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_CLOSE)); close_button_->SetProperty(views::kElementIdentifierKey, kToastCloseButton); @@ -280,7 +284,7 @@ icon_view_->SetImage(ui::ImageModel::FromVectorIcon( *icon_, color_provider->GetColor(ui::kColorToastForeground), ChromeLayoutProvider::Get()->GetDistanceMetric( - DISTANCE_TOAST_BUBBLE_LEADING_ICON_SIZE))); + DISTANCE_TOAST_BUBBLE_ICON_SIZE))); } void ToastView::AnimateOut(base::OnceClosure callback,
diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc index 4d32cec..0c66beb 100644 --- a/chrome/browser/ui/ui_features.cc +++ b/chrome/browser/ui/ui_features.cc
@@ -224,18 +224,6 @@ "SearchWebInSidePanel", base::FEATURE_DISABLED_BY_DEFAULT); -// Feature that controls whether or not feature engagement configurations can be -// used to control automatic triggering for side search. -BASE_FEATURE(kSideSearchAutoTriggering, - "SideSearchAutoTriggering", - base::FEATURE_ENABLED_BY_DEFAULT); - -// Feature param that determines how many times a user has to return to a given -// SRP before we automatically trigger the side search side panel for that SRP -// on a subsequent navigation. -const base::FeatureParam<int> kSideSearchAutoTriggeringReturnCount{ - &kSideSearchAutoTriggering, "SideSearchAutoTriggeringReturnCount", 2}; - BASE_FEATURE(kSidePanelWebView, "SidePanelWebView", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/browser/ui/ui_features.h b/chrome/browser/ui/ui_features.h index 818cb38..1c46163 100644 --- a/chrome/browser/ui/ui_features.h +++ b/chrome/browser/ui/ui_features.h
@@ -167,9 +167,6 @@ BASE_DECLARE_FEATURE(kSideSearchFeedback); BASE_DECLARE_FEATURE(kSearchWebInSidePanel); -BASE_DECLARE_FEATURE(kSideSearchAutoTriggering); -extern const base::FeatureParam<int> kSideSearchAutoTriggeringReturnCount; - BASE_DECLARE_FEATURE(kTabGroupsCollapseFreezing); BASE_DECLARE_FEATURE(kTabHoverCardImages);
diff --git a/chrome/browser/ui/views/chrome_layout_provider.cc b/chrome/browser/ui/views/chrome_layout_provider.cc index 3539939..9b189df 100644 --- a/chrome/browser/ui/views/chrome_layout_provider.cc +++ b/chrome/browser/ui/views/chrome_layout_provider.cc
@@ -172,7 +172,7 @@ return 36; case DISTANCE_TOAST_BUBBLE_HEIGHT_CONTENT: return 24; - case DISTANCE_TOAST_BUBBLE_LEADING_ICON_SIZE: + case DISTANCE_TOAST_BUBBLE_ICON_SIZE: return 20; case DISTANCE_TOAST_BUBBLE_LEADING_ICON_SIDE_MARGINS: return 2;
diff --git a/chrome/browser/ui/views/chrome_layout_provider.h b/chrome/browser/ui/views/chrome_layout_provider.h index 7d283922..d93d7fa 100644 --- a/chrome/browser/ui/views/chrome_layout_provider.h +++ b/chrome/browser/ui/views/chrome_layout_provider.h
@@ -110,8 +110,8 @@ DISTANCE_TOAST_BUBBLE_HEIGHT_ACTION_BUTTON, // Height of the toast text and close button icon. DISTANCE_TOAST_BUBBLE_HEIGHT_CONTENT, - // Width and height of the leading vector icon shown in the toast bubble. - DISTANCE_TOAST_BUBBLE_LEADING_ICON_SIZE, + // Width and height of the vector icons shown in the toast bubble. + DISTANCE_TOAST_BUBBLE_ICON_SIZE, // Left and right margins of the leading vector icon shown in the toast // bubble. DISTANCE_TOAST_BUBBLE_LEADING_ICON_SIDE_MARGINS,
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index c31c546..079c462 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -317,20 +317,18 @@ // has placeholder text. Use that instead of the DSE placeholder text. if (!model()->keyword_placeholder().empty()) { SetPlaceholderText(model()->keyword_placeholder()); - return; - } - - // Otherwise, if a DSE is set, use the DSE placeholder text. - const TemplateURL* const default_provider = controller() - ->client() - ->GetTemplateURLService() - ->GetDefaultSearchProvider(); - if (default_provider) { + } else if (const auto* default_provider = controller() + ->client() + ->GetTemplateURLService() + ->GetDefaultSearchProvider()) { + // Otherwise, if a DSE is set, use the DSE placeholder text. SetPlaceholderText(l10n_util::GetStringFUTF16( IDS_OMNIBOX_PLACEHOLDER_TEXT, default_provider->short_name())); } else { SetPlaceholderText(std::u16string()); } + + UpdatePlaceholderTextColor(); } bool OmniboxViewViews::GetSelectionAtEnd() const { @@ -630,8 +628,7 @@ void OmniboxViewViews::OnThemeChanged() { views::Textfield::OnThemeChanged(); - set_placeholder_text_color( - GetColorProvider()->GetColor(kColorOmniboxTextDimmed)); + UpdatePlaceholderTextColor(); SetSelectionBackgroundColor( GetColorProvider()->GetColor(kColorOmniboxSelectionBackground)); SetSelectionTextColor( @@ -2004,6 +2001,18 @@ #endif } +void OmniboxViewViews::UpdatePlaceholderTextColor() { + // Keyword placeholders are dim to differentiate from user input. DSE + // placeholders are not dim to draw attention to the omnibox and because the + // omnibox is unfocused so there's less risk of confusion with user input. + // Null in tests. + if (!GetColorProvider()) + return; + set_placeholder_text_color(GetColorProvider()->GetColor( + model()->keyword_placeholder().empty() ? kColorOmniboxText + : kColorOmniboxTextDimmed)); +} + BEGIN_METADATA(OmniboxViewViews) ADD_READONLY_PROPERTY_METADATA(bool, SelectionAtEnd) ADD_READONLY_PROPERTY_METADATA(int, TextWidth)
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h index a39f58c6..e8377f0 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.h +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
@@ -84,9 +84,7 @@ // Exposes the RenderText for tests. #if defined(UNIT_TEST) - gfx::RenderText* GetRenderText() { - return views::Textfield::GetRenderText(); - } + gfx::RenderText* GetRenderText() { return views::Textfield::GetRenderText(); } #endif // For use when switching tabs, this saves the current state onto the tab so @@ -326,6 +324,10 @@ // Called when the popup view becomes visible. void OnPopupOpened(); + // Helper for updating placeholder color depending on whether its a keyword or + // DSE placeholder. + void UpdatePlaceholderTextColor(); + // When true, the location bar view is read only and also is has a slightly // different presentation (smaller font size). This is used for popups. bool popup_window_mode_;
diff --git a/chrome/browser/ui/views/search_engine_choice/OWNERS b/chrome/browser/ui/views/search_engine_choice/OWNERS index a8ff91d..c7aa42b 100644 --- a/chrome/browser/ui/views/search_engine_choice/OWNERS +++ b/chrome/browser/ui/views/search_engine_choice/OWNERS
@@ -1 +1 @@ -file://components/search_engines/search_engine_choice/OWNERS +file://components/search_engines/search_engine_choice/COMPLIANCE_OWNERS
diff --git a/chrome/browser/ui/views/side_search/unified_side_search_controller.cc b/chrome/browser/ui/views/side_search/unified_side_search_controller.cc index c6ad7543..7e5a490 100644 --- a/chrome/browser/ui/views/side_search/unified_side_search_controller.cc +++ b/chrome/browser/ui/views/side_search/unified_side_search_controller.cc
@@ -14,7 +14,6 @@ #include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/side_search/side_search_utils.h" -#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/side_panel/side_panel.h" @@ -322,8 +321,10 @@ const GURL& previously_committed_url = navigation_handle->GetPreviousPrimaryMainFrameURL(); const bool is_renderer_initiated = navigation_handle->IsRendererInitiated(); - const int auto_triggering_return_count = - features::kSideSearchAutoTriggeringReturnCount.Get(); + + // How many times a user has to return to a given SRP before we automatically + // trigger the side search side panel for that SRP on a subsequent navigation. + constexpr int kAutoTriggeringReturnCount = 2; // Trigger the side panel only if we've returned to the same SRP n times and // this is the first navigation after navigating away from the Google SRP. We @@ -332,7 +333,7 @@ // etc. return is_renderer_initiated && tab_contents_helper->returned_to_previous_srp_count() == - auto_triggering_return_count && + kAutoTriggeringReturnCount && previously_committed_url == tab_contents_helper->last_search_url(); }
diff --git a/chrome/browser/ui/views/web_apps/web_app_navigation_capturing_iph_interactive_uitest.cc b/chrome/browser/ui/views/web_apps/web_app_navigation_capturing_iph_interactive_uitest.cc index de77d71d..c0c7c16 100644 --- a/chrome/browser/ui/views/web_apps/web_app_navigation_capturing_iph_interactive_uitest.cc +++ b/chrome/browser/ui/views/web_apps/web_app_navigation_capturing_iph_interactive_uitest.cc
@@ -34,6 +34,7 @@ #include "third_party/blink/public/common/input/web_mouse_event.h" #include "ui/base/interaction/element_identifier.h" #include "ui/base/interaction/state_observer.h" +#include "ui/base/test/ui_controls.h" #include "ui/views/interaction/interaction_test_util_views.h" #include "url/gurl.h" @@ -158,51 +159,24 @@ // Clicks on the "launch app" link on the start page with element ID // `element_id`. The start page must be open in at least one browser. The // context of the last step is the browser window containing the start page. - auto ClickLaunchLink(test::ClickMethod click, const std::string& element_id) { - int mouse_button; - bool shift = false; - switch (click) { - case test::ClickMethod::kLeftClick: - mouse_button = 0; - break; - case test::ClickMethod::kMiddleClick: - mouse_button = 1; - break; - case test::ClickMethod::kShiftClick: - mouse_button = 0; - shift = true; - break; - case test::ClickMethod::kRightClickLaunchApp: - mouse_button = 2; - break; - } - const auto js = base::StringPrintf(R"( - function(el) { - const event = new MouseEvent( - 'click', - { - bubbles: true, - button: %d, - cancelable: true, - shiftKey: %s - } - ); - el.dispatchEvent(event); - } - )", - mouse_button, shift ? "true" : "false"); - - return InAnyContext(ExecuteJsAt(kStartPageId, {"#" + element_id}, js) - .SetDescription("ClickLaunchLink()")); + auto ClickLaunchLink( + const std::string& element_id, + ui_controls::MouseButton button, + ui_controls::AcceleratorState accel = ui_controls::kNoAccelerator) { + return InAnyContext( + ClickElement(kStartPageId, {"#" + element_id}, button, accel) + .SetDescription("ClickLaunchLink()")); } // Clicks on `element_id` in the start page, which must be open in at least // one browser, launching a new app window. The context of the last step is // the window in which the link was opened. - auto TriggerAppLaunch(test::ClickMethod click, - const std::string& element_id) { + auto TriggerAppLaunch( + const std::string& element_id, + ui_controls::MouseButton button, + ui_controls::AcceleratorState accel = ui_controls::kNoAccelerator) { auto steps = Steps( - ClickLaunchLink(click, element_id), + ClickLaunchLink(element_id, button, accel), InAnyContext( WaitForShow(kBrowserViewElementId).SetTransitionOnlyOnEvent(true)), InSameContext(CheckViewProperty(kBrowserViewElementId, @@ -230,11 +204,11 @@ IN_PROC_BROWSER_TEST_F(WebAppNavigationCapturingIphUiTest, IPHShownOnLinkLeftClick) { const webapps::AppId app_id = InstallTestWebApp(GetDestinationUrl()); - RunTestSequence(OpenStartPage(), - TriggerAppLaunch(test::ClickMethod::kLeftClick, - kToSiteBTargetBlankNoOpener), - InSameContext(WaitForPromo( - feature_engagement::kIPHDesktopPWAsLinkCapturingLaunch))); + RunTestSequence( + OpenStartPage(), + TriggerAppLaunch(kToSiteBTargetBlankNoOpener, ui_controls::LEFT), + InSameContext(WaitForPromo( + feature_engagement::kIPHDesktopPWAsLinkCapturingLaunch))); } // Middle click does not work (consistently?) on Mac; see @@ -247,11 +221,11 @@ IN_PROC_BROWSER_TEST_F(WebAppNavigationCapturingIphUiTest, MAYBE_IPHShownOnLinkMiddleClick) { const webapps::AppId app_id = InstallTestWebApp(GetStartUrl()); - RunTestSequence(OpenAppStartPage(app_id), - TriggerAppLaunch(test::ClickMethod::kMiddleClick, - kToSiteATargetBlankWithOpener), - InSameContext(WaitForPromo( - feature_engagement::kIPHDesktopPWAsLinkCapturingLaunch))); + RunTestSequence( + OpenAppStartPage(app_id), + TriggerAppLaunch(kToSiteATargetBlankWithOpener, ui_controls::MIDDLE), + InSameContext(WaitForPromo( + feature_engagement::kIPHDesktopPWAsLinkCapturingLaunch))); } // Shift-click click does not work (consistently?) on Mac; see @@ -266,8 +240,8 @@ const webapps::AppId app_id_a = InstallTestWebApp(GetStartUrl()); const webapps::AppId app_id_b = InstallTestWebApp(GetDestinationUrl()); RunTestSequence(OpenAppStartPage(app_id_a), - TriggerAppLaunch(test::ClickMethod::kShiftClick, - kToSiteBTargetBlankWithOpener), + TriggerAppLaunch(kToSiteBTargetBlankWithOpener, + ui_controls::LEFT, ui_controls::kShift), InSameContext(WaitForPromo( feature_engagement::kIPHDesktopPWAsLinkCapturingLaunch))); } @@ -279,14 +253,14 @@ blink::Manifest::LaunchHandler( blink::mojom::ManifestLaunchHandler_ClientMode::kFocusExisting)); - RunTestSequence(OpenStartPage(), OpenApp(app_id), - ClickLaunchLink(test::ClickMethod::kLeftClick, - kToSiteBTargetBlankNoOpener), - // Switch back to the app browser's context and verify the IPH - // shows there. - InAnyContext(WithElement(kAppPageId, base::DoNothing())), - InSameContext(WaitForPromo( - feature_engagement::kIPHDesktopPWAsLinkCapturingLaunch))); + RunTestSequence( + OpenStartPage(), OpenApp(app_id), + ClickLaunchLink(kToSiteBTargetBlankNoOpener, ui_controls::LEFT), + // Switch back to the app browser's context and verify the IPH + // shows there. + InAnyContext(WithElement(kAppPageId, base::DoNothing())), + InSameContext(WaitForPromo( + feature_engagement::kIPHDesktopPWAsLinkCapturingLaunch))); } IN_PROC_BROWSER_TEST_F(WebAppNavigationCapturingIphUiTest, @@ -296,8 +270,7 @@ RunTestSequence( OpenAppStartPage(app_id_a), - TriggerAppLaunch(test::ClickMethod::kLeftClick, - kToSiteBTargetBlankWithOpener), + TriggerAppLaunch(kToSiteBTargetBlankWithOpener, ui_controls::LEFT), InSameContext(CheckPromoIsActive( feature_engagement::kIPHDesktopPWAsLinkCapturingLaunch, false))); } @@ -308,8 +281,7 @@ RunTestSequence( OpenStartPage(), - TriggerAppLaunch(test::ClickMethod::kLeftClick, - kToSiteBTargetBlankNoOpener), + TriggerAppLaunch(kToSiteBTargetBlankNoOpener, ui_controls::LEFT), InSameContext(Steps( WaitForPromo(feature_engagement::kIPHDesktopPWAsLinkCapturingLaunch), CheckActionCount("LinkCapturingIPHAppBubbleShown", 1), @@ -326,8 +298,7 @@ RunTestSequence( OpenStartPage(), - TriggerAppLaunch(test::ClickMethod::kLeftClick, - kToSiteBTargetBlankNoOpener), + TriggerAppLaunch(kToSiteBTargetBlankNoOpener, ui_controls::LEFT), InSameContext(Steps( WaitForPromo(feature_engagement::kIPHDesktopPWAsLinkCapturingLaunch), CheckActionCount("LinkCapturingIPHAppBubbleShown", 1), @@ -342,8 +313,7 @@ RunTestSequence( OpenStartPage(), - TriggerAppLaunch(test::ClickMethod::kLeftClick, - kToSiteBTargetBlankNoOpener), + TriggerAppLaunch(kToSiteBTargetBlankNoOpener, ui_controls::LEFT), InSameContext(Steps( WaitForPromo(feature_engagement::kIPHDesktopPWAsLinkCapturingLaunch), PressDefaultPromoButton(),
diff --git a/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler.cc b/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler.cc index d1c3474..be2dc4d 100644 --- a/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler.cc +++ b/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler.h" +#include "base/i18n/time_formatting.h" #include "base/metrics/histogram_functions.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/feedback/show_feedback_page.h" @@ -122,6 +123,8 @@ item->relative_time = base::UTF16ToUTF8(ui::TimeFormat::Simple( ui::TimeFormat::FORMAT_ELAPSED, ui::TimeFormat::LENGTH_SHORT, base::Time::Now() - scored_url_row.row.last_visit())); + item->short_date_time = base::UTF16ToUTF8( + base::TimeFormatShortDate(scored_url_row.row.last_visit())); item->last_url_visit_timestamp = scored_url_row.row.last_visit().InMillisecondsFSinceUnixEpoch();
diff --git a/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler_unittest.cc b/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler_unittest.cc index 86823f70..b8bb99a 100644 --- a/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler_unittest.cc +++ b/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler_unittest.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler.h" +#include "base/i18n/time_formatting.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" #include "base/test/scoped_feature_list.h" @@ -209,6 +210,9 @@ base::UTF16ToUTF8(ui::TimeFormat::Simple( ui::TimeFormat::FORMAT_ELAPSED, ui::TimeFormat::LENGTH_SHORT, base::Time::Now() - scored_url_row.row.last_visit()))); + EXPECT_EQ(mojo_result->items[0]->short_date_time, + base::UTF16ToUTF8( + base::TimeFormatShortDate(scored_url_row.row.last_visit()))); EXPECT_EQ(mojo_result->items[0]->last_url_visit_timestamp, scored_url_row.row.last_visit().InMillisecondsFSinceUnixEpoch()); EXPECT_EQ(mojo_result->items[0]->url_for_display, "google.com");
diff --git a/chrome/browser/ui/webui/password_manager/password_manager_ui.cc b/chrome/browser/ui/webui/password_manager/password_manager_ui.cc index 5c08590..d63f1dd 100644 --- a/chrome/browser/ui/webui/password_manager/password_manager_ui.cc +++ b/chrome/browser/ui/webui/password_manager/password_manager_ui.cc
@@ -355,6 +355,8 @@ {"passwordManager", IDS_PASSWORD_BUBBLES_PASSWORD_MANAGER_LINK_TEXT_SYNCED_TO_ACCOUNT}, // Header for the page, always "Password Manager". + {"passwordManagerDescription", + IDS_PASSWORD_MANAGER_UI_DESCRIPTION}, {"passwordManagerPinChanged", IDS_PASSWORD_MANAGER_PIN_CHANGED}, {"passwordManagerString", IDS_PASSWORD_MANAGER_UI_TITLE}, // Page title, branded. "Google Password Manager" or "Password Manager"
diff --git a/chrome/browser/ui/webui/search_engine_choice/OWNERS b/chrome/browser/ui/webui/search_engine_choice/OWNERS index 89018e9..c591a23 100644 --- a/chrome/browser/ui/webui/search_engine_choice/OWNERS +++ b/chrome/browser/ui/webui/search_engine_choice/OWNERS
@@ -1,3 +1,3 @@ -file://components/search_engines/search_engine_choice/OWNERS +file://components/search_engines/search_engine_choice/COMPLIANCE_OWNERS per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/browser/ui/webui/settings/settings_interactive_uitest.cc b/chrome/browser/ui/webui/settings/settings_interactive_uitest.cc index 53902e5..786a66e 100644 --- a/chrome/browser/ui/webui/settings/settings_interactive_uitest.cc +++ b/chrome/browser/ui/webui/settings/settings_interactive_uitest.cc
@@ -106,15 +106,10 @@ UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed); UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted); - bool is_3pcd = base::FeatureList::IsEnabled( - content_settings::features::kTrackingProtection3pcd); - const std::string cookie_row_selector = - is_3pcd ? "cr-link-row#trackingProtectionLinkRow" - : "cr-link-row#thirdPartyCookiesLinkRow"; const GURL cookie_setting_url("chrome://settings/privacy"); const WebContentsInteractionTestUtil::DeepQuery cookies_link_row = { "settings-ui", "settings-main", "settings-basic-page", - "settings-privacy-page", cookie_row_selector}; + "settings-privacy-page", "cr-link-row#thirdPartyCookiesLinkRow"}; const WebContentsInteractionTestUtil::DeepQuery cookies_setting_page_help_icon = { "settings-ui", @@ -152,14 +147,8 @@ auto* util = element->AsA<TrackedElementWebContents>()->owner(); auto* const contents = util->web_contents(); - if (is_3pcd) { - EXPECT_EQ( - contents->GetURL(), - GURL(chrome::kTrackingProtectionHelpCenterURL)); - } else { - EXPECT_EQ(contents->GetURL(), - chrome::kCookiesSettingsHelpCenterURL); - } + EXPECT_EQ(contents->GetURL(), + chrome::kCookiesSettingsHelpCenterURL); })) .Build()) .Build();
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc index 623fc7a..1b92d88 100644 --- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc +++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc
@@ -241,8 +241,9 @@ } void ReadAnythingWebContentsObserver::AccessibilityLocationChangesReceived( - const std::vector<ui::AXLocationChanges>& details) { - page_handler_->AccessibilityLocationChangesReceived(details); + const ui::AXTreeID& tree_id, + ui::AXLocationAndScrollUpdates& details) { + page_handler_->AccessibilityLocationChangesReceived(tree_id, details); } void ReadAnythingWebContentsObserver::PrimaryPageChanged(content::Page& page) { @@ -390,9 +391,10 @@ } void ReadAnythingUntrustedPageHandler::AccessibilityLocationChangesReceived( - const std::vector<ui::AXLocationChanges>& details) { + const ui::AXTreeID& tree_id, + ui::AXLocationAndScrollUpdates& details) { if (features::IsReadAnythingDocsIntegrationEnabled()) { - page_->AccessibilityLocationChangesReceived(details); + page_->AccessibilityLocationChangesReceived(tree_id, details); } }
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.h b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.h index 24968ac..abbf48be 100644 --- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.h +++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.h
@@ -57,7 +57,8 @@ void AccessibilityEventReceived( const ui::AXUpdatesAndEvents& details) override; void AccessibilityLocationChangesReceived( - const std::vector<ui::AXLocationChanges>& details) override; + const ui::AXTreeID& tree_id, + ui::AXLocationAndScrollUpdates& details) override; void PrimaryPageChanged(content::Page& page) override; void WebContentsDestroyed() override; @@ -102,7 +103,8 @@ void AccessibilityEventReceived(const ui::AXUpdatesAndEvents& details); void AccessibilityLocationChangesReceived( - const std::vector<ui::AXLocationChanges>& details); + const ui::AXTreeID& tree_id, + ui::AXLocationAndScrollUpdates& details); void PrimaryPageChanged(); void WebContentsDestroyed();
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler_unittest.cc b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler_unittest.cc index c18fff7..b45f4255 100644 --- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler_unittest.cc +++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler_unittest.cc
@@ -26,7 +26,6 @@ #include "ui/accessibility/ax_node_id_forward.h" #include "ui/accessibility/ax_tree_id.h" #include "ui/accessibility/mojom/ax_event.mojom.h" -#include "ui/accessibility/mojom/ax_location_changes.mojom.h" #include "ui/accessibility/mojom/ax_tree_id.mojom.h" #include "ui/accessibility/mojom/ax_tree_update.mojom.h" #include "ui/gfx/geometry/size.h" @@ -51,7 +50,12 @@ const std::vector<ui::AXEvent>& events)); MOCK_METHOD(void, AccessibilityLocationChangesReceived, - (const std::vector<ui::AXLocationChanges>& details)); + (const ui::AXTreeID& tree_id, + ui::AXLocationAndScrollUpdates& details)); + MOCK_METHOD(void, + AccessibilityLocationChangesReceived, + (const ui::AXTreeID& tree_id, + const ui::AXLocationAndScrollUpdates& details)); MOCK_METHOD(void, OnSettingsRestoredFromPrefs, (read_anything::mojom::LineSpacing line_spacing,
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 768145d..a2bc247 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1727791183-18ebb677bfded080d4fbccf41c258d8f5b869cce-5c8b1389ff74057dc8513e6687b93c9019d4a496.profdata +chrome-mac-arm-main-1727805595-7e9a010c1d8e5cb05c53975b96ca20fa6c385199-bdb53115de59bca1fe7e29f68cb950f5b1280da2.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index c7b36b7..5a4b2b4 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1727773147-71e35f3eeb906599fea4b886352dcd4a11b1a762-a163f2d7227da4a5b9792888bd14304ff72ce6f2.profdata +chrome-win64-main-1727783961-fa1fbfa59af5e894dd8c60c24877d4aaf771b088-f7bc99221b34f0a43ca97da3ec7dcc2ae2e90c0c.profdata
diff --git a/chrome/common/accessibility/read_anything.mojom b/chrome/common/accessibility/read_anything.mojom index 080c697..cf38aa56 100644 --- a/chrome/common/accessibility/read_anything.mojom +++ b/chrome/common/accessibility/read_anything.mojom
@@ -11,7 +11,7 @@ import "skia/public/mojom/bitmap.mojom"; import "ui/accessibility/ax_features.mojom"; import "ui/accessibility/mojom/ax_event.mojom"; -import "ui/accessibility/mojom/ax_location_changes.mojom"; +import "ui/accessibility/mojom/ax_location_and_scroll_updates.mojom"; import "ui/accessibility/mojom/ax_tree_id.mojom"; import "ui/accessibility/mojom/ax_tree_update.mojom"; import "mojo/public/mojom/base/values.mojom"; @@ -226,7 +226,9 @@ // Send a location change notification to the WebUI. The WebUI updates the // locations for each node in the vector. This does not trigger a distillation. [RuntimeFeature=ax.mojom.features.kReadAnythingDocsIntegration] - AccessibilityLocationChangesReceived(array<ax.mojom.AXLocationChanges> details); + AccessibilityLocationChangesReceived( + ax.mojom.AXTreeID tree_id, + ax.mojom.AXLocationAndScrollUpdates details); // Sends the active AXTreeID to the WebUI. This is not guaranteed to be called // after the tree_id was previously passed to AccessibilityEventsReceived.
diff --git a/chrome/enterprise_companion/enterprise_companion_client.cc b/chrome/enterprise_companion/enterprise_companion_client.cc index bf8d438..2b4cc72 100644 --- a/chrome/enterprise_companion/enterprise_companion_client.cc +++ b/chrome/enterprise_companion/enterprise_companion_client.cc
@@ -96,6 +96,7 @@ VLOG(1) << "Failed to connect to EnterpriseCompanionService remote. " "The service could not be launched."; std::move(callback).Run({}); + return; } mojo::PlatformChannelEndpoint endpoint =
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.cc b/chrome/renderer/accessibility/read_anything_app_controller.cc index 6992db7..8154fbb 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller.cc +++ b/chrome/renderer/accessibility/read_anything_app_controller.cc
@@ -47,6 +47,7 @@ #include "third_party/skia/include/core/SkImageInfo.h" #include "ui/accessibility/accessibility_features.h" #include "ui/accessibility/ax_enums.mojom-shared.h" +#include "ui/accessibility/ax_location_and_scroll_updates.h" #include "ui/accessibility/ax_node.h" #include "ui/accessibility/ax_node_id_forward.h" #include "ui/accessibility/ax_role_properties.h" @@ -523,10 +524,18 @@ } void ReadAnythingAppController::AccessibilityLocationChangesReceived( - const std::vector<ui::AXLocationChanges>& details) { + const ui::AXTreeID& tree_id, + const ui::AXLocationAndScrollUpdates& details) { + NOTREACHED() << "Non-const ref version of this method should be used as a " + "performance optimization."; +} + +void ReadAnythingAppController::AccessibilityLocationChangesReceived( + const ui::AXTreeID& tree_id, + ui::AXLocationAndScrollUpdates& details) { // Listen to location change notifications to update locations of the nodes // accordingly. - for (auto& change : details) { + for (auto& change : details.location_changes) { ui::AXNode* ax_node = model_.GetAXNode(change.id); if (!ax_node) { continue;
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.h b/chrome/renderer/accessibility/read_anything_app_controller.h index 974648b..b6f9fad 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller.h +++ b/chrome/renderer/accessibility/read_anything_app_controller.h
@@ -25,6 +25,7 @@ #include "services/metrics/public/cpp/ukm_source_id.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/accessibility/ax_location_and_scroll_updates.h" #include "ui/accessibility/ax_node_id_forward.h" #include "ui/accessibility/ax_node_position.h" #include "ui/accessibility/ax_position.h" @@ -121,7 +122,11 @@ const std::vector<ui::AXTreeUpdate>& updates, const std::vector<ui::AXEvent>& events) override; void AccessibilityLocationChangesReceived( - const std::vector<ui::AXLocationChanges>& details) override; + const ui::AXTreeID& tree_id, + ui::AXLocationAndScrollUpdates& details) override; + void AccessibilityLocationChangesReceived( + const ui::AXTreeID& tree_id, + const ui::AXLocationAndScrollUpdates& details) override; void OnActiveAXTreeIDChanged(const ui::AXTreeID& tree_id, ukm::SourceId ukm_source_id, bool is_pdf) override;
diff --git a/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc index 414e831..ac37ac2 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc +++ b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc
@@ -24,6 +24,7 @@ #include "services/strings/grit/services_strings.h" #include "testing/gmock/include/gmock/gmock.h" #include "ui/accessibility/accessibility_features.h" +#include "ui/accessibility/ax_location_and_scroll_updates.h" #include "ui/accessibility/ax_node.h" #include "ui/accessibility/ax_node_id_forward.h" #include "ui/accessibility/ax_serializable_tree.h" @@ -292,8 +293,9 @@ } void AccessibilityLocationChangesReceived( - const std::vector<ui::AXLocationChanges>& details) { - controller_->AccessibilityLocationChangesReceived(details); + const ui::AXTreeID& tree_id, + ui::AXLocationAndScrollUpdates& details) { + controller_->AccessibilityLocationChangesReceived(tree_id, details); } // Since a11y events happen asynchronously, they can come between the time @@ -1732,13 +1734,11 @@ ui::AXRelativeBounds location_update; location_update.offset_container_id = 1; location_update.bounds = gfx::RectF(5, 5, 100, 100); - ui::AXLocationChanges location_changes; - location_changes.id = 2; - location_changes.ax_tree_id = id_1; - location_changes.new_location = location_update; + ui::AXLocationAndScrollUpdates location_and_scroll_updates; + location_and_scroll_updates.location_changes.emplace_back(2, location_update); // Test that the node data updates correctly - AccessibilityLocationChangesReceived({location_changes}); + AccessibilityLocationChangesReceived(id_1, location_and_scroll_updates); node = GetNodeData(2); EXPECT_EQ(node.relative_bounds, location_update); }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeBrowserTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeBrowserTestRule.java index 1416c84..443786b 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeBrowserTestRule.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeBrowserTestRule.java
@@ -25,10 +25,8 @@ new Statement() { @Override public void evaluate() throws Throwable { - /** - * Loads the native library on the activity UI thread. After loading the library, - * this will initialize the browser process if necessary. - */ + // Loads the native library on the activity UI thread. After loading the + // library, this will initialize the browser process if necessary. NativeLibraryTestUtils.loadNativeLibraryAndInitBrowserProcess(); base.evaluate(); }
diff --git a/chrome/test/base/chrome_unit_test_suite.cc b/chrome/test/base/chrome_unit_test_suite.cc index 0ea9af3a..fb961c4 100644 --- a/chrome/test/base/chrome_unit_test_suite.cc +++ b/chrome/test/base/chrome_unit_test_suite.cc
@@ -52,8 +52,11 @@ #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h" #endif // !BUILDFLAG(IS_ANDROID) -#if BUILDFLAG(ENABLE_EXTENSIONS) +#if BUILDFLAG(ENABLE_EXTENSIONS_CORE) #include "chrome/common/initialize_extensions_client.h" +#endif + +#if BUILDFLAG(ENABLE_EXTENSIONS) #include "extensions/common/extension_paths.h" #endif // BUILDFLAG(ENABLE_EXTENSIONS) @@ -176,7 +179,9 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) extensions::RegisterPathProvider(); +#endif +#if BUILDFLAG(ENABLE_EXTENSIONS_CORE) EnsureExtensionsClientInitialized(); #endif
diff --git a/chrome/test/base/testing_browser_process.cc b/chrome/test/base/testing_browser_process.cc index 1f214167..1778d1bc 100644 --- a/chrome/test/base/testing_browser_process.cc +++ b/chrome/test/base/testing_browser_process.cc
@@ -68,6 +68,10 @@ #include "components/storage_monitor/test_storage_monitor.h" #endif +#if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS) +#include "chrome/browser/extensions/desktop_android/desktop_android_extensions_browser_client.h" +#endif + #if BUILDFLAG(ENABLE_PRINT_PREVIEW) #include "chrome/browser/printing/background_printing_manager.h" #include "chrome/browser/printing/print_preview_dialog_controller.h" @@ -175,7 +179,11 @@ test_network_connection_tracker_.get()); } -#if BUILDFLAG(ENABLE_EXTENSIONS) +#if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS) + extensions_browser_client_ = + std::make_unique<extensions::DesktopAndroidExtensionsBrowserClient>(); + extensions::ExtensionsBrowserClient::Set(extensions_browser_client_.get()); +#elif BUILDFLAG(ENABLE_EXTENSIONS) extensions_browser_client_ = std::make_unique<extensions::ChromeExtensionsBrowserClient>(); extensions_browser_client_->AddAPIProvider(
diff --git a/chrome/test/base/testing_browser_process.h b/chrome/test/base/testing_browser_process.h index 8ef74cb..617e441 100644 --- a/chrome/test/base/testing_browser_process.h +++ b/chrome/test/base/testing_browser_process.h
@@ -267,7 +267,9 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) std::unique_ptr<MediaFileSystemRegistry> media_file_system_registry_; +#endif +#if BUILDFLAG(ENABLE_EXTENSIONS_CORE) std::unique_ptr<extensions::ExtensionsBrowserClient> extensions_browser_client_; #endif
diff --git a/chrome/test/data/click.html b/chrome/test/data/click.html new file mode 100644 index 0000000..ab726b0 --- /dev/null +++ b/chrome/test/data/click.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<body> +<button id="button">Button</button> +<script> +const button = document.getElementById('button'); +button.addEventListener('click', function(event) { + button.lastClickEvent = event; +}); +</script> +</body> +</html>
diff --git a/chrome/test/data/webui/commerce/product_specifications/loading_state_test.ts b/chrome/test/data/webui/commerce/product_specifications/loading_state_test.ts index de7c847..4053a91 100644 --- a/chrome/test/data/webui/commerce/product_specifications/loading_state_test.ts +++ b/chrome/test/data/webui/commerce/product_specifications/loading_state_test.ts
@@ -17,6 +17,19 @@ document.body.appendChild(loadingElement); }); + function resizeContainer(width: number): Promise<void> { + // A ResizeObserver is used to ensure the ResizeObserver callback that shows + // the last column gradient has completed. + return new Promise<void>(resolve => { + const observer = new ResizeObserver(() => { + resolve(); + observer.unobserve(loadingElement.$.loadingContainer); + }); + observer.observe(loadingElement.$.loadingContainer); + loadingElement.$.loadingContainer.style.width = `${width}px`; + }); + } + test( 'last column gradient appears when SVG is wider than its container', async () => { @@ -31,7 +44,7 @@ // Container should be smaller than the loading gradient, so the last // column gradient should appear. - document.body.style.width = '200px'; + await resizeContainer(200); await microtasksFinished(); assertTrue(isVisible(lastColumnGradient)); });
diff --git a/chrome/test/data/webui/cr_components/history_embeddings/history_embeddings_test.ts b/chrome/test/data/webui/cr_components/history_embeddings/history_embeddings_test.ts index 6f0775a..fe5a6f0 100644 --- a/chrome/test/data/webui/cr_components/history_embeddings/history_embeddings_test.ts +++ b/chrome/test/data/webui/cr_components/history_embeddings/history_embeddings_test.ts
@@ -29,6 +29,7 @@ url: {url: 'http://google.com'}, urlForDisplay: 'google.com', relativeTime: '2 hours ago', + shortDateTime: 'Sept 2, 2022', sourcePassage: 'Google description', lastUrlVisitTimestamp: 1000, answerData: null, @@ -38,6 +39,7 @@ url: {url: 'http://youtube.com'}, urlForDisplay: 'youtube.com', relativeTime: '4 hours ago', + shortDateTime: 'Sept 2, 2022', sourcePassage: 'Youtube description', lastUrlVisitTimestamp: 2000, answerData: null, @@ -464,6 +466,7 @@ url: {url: 'http://answer.com'}, urlForDisplay: 'Answer.com', relativeTime: '2 months ago', + shortDateTime: 'Sept 2, 2022', sourcePassage: 'Answer description', lastUrlVisitTimestamp: 2000, answerData: {answerTextDirectives: []}, @@ -482,9 +485,11 @@ assertTrue(!!answerSource); assertFalse(answerSource.hidden); assertEquals('http://answer.com', answerSource.getAttribute('href')); - assertEquals( - 'Answer.com', - answerSource.querySelector<HTMLElement>('.result-url')!.innerText); + + const answerUrlAndDate = + answerSource.querySelector<HTMLElement>('.result-url')!.innerText; + assertTrue(answerUrlAndDate.startsWith('Answer.com')); + assertTrue(answerUrlAndDate.endsWith('Sept 2, 2022')); assertEquals( getFaviconForPageURL('http://answer.com', true), answerSource.querySelector<HTMLElement>(
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/categories_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/categories_test.ts index 1468442..3073bb1 100644 --- a/chrome/test/data/webui/side_panel/customize_chrome/categories_test.ts +++ b/chrome/test/data/webui/side_panel/customize_chrome/categories_test.ts
@@ -6,7 +6,7 @@ import type {CategoriesElement} from 'chrome://customize-chrome-side-panel.top-chrome/categories.js'; import {CHANGE_CHROME_THEME_CLASSIC_ELEMENT_ID, CHROME_THEME_COLLECTION_ELEMENT_ID} from 'chrome://customize-chrome-side-panel.top-chrome/categories.js'; -import {CustomizeChromeAction} from 'chrome://customize-chrome-side-panel.top-chrome/common.js'; +import {CustomizeChromeAction, NtpImageType} from 'chrome://customize-chrome-side-panel.top-chrome/common.js'; import type {BackgroundCollection, CustomizeChromePageRemote} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; import {CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerRemote} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; import {CustomizeChromeApiProxy} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome_api_proxy.js'; @@ -21,6 +21,11 @@ import {$$, createBackgroundImage, createTheme, installMock} from './test_support.js'; +interface CollectionOptions { + numCollections: number; + shouldReplaceBrokenImages?: boolean; +} + function createTestCollections(length: number): BackgroundCollection[] { const testCollections: BackgroundCollection[] = []; for (let i = 1; i < length + 1; i++) { @@ -41,16 +46,21 @@ let callbackRouterRemote: CustomizeChromePageRemote; let metrics: MetricsTracker; - async function setInitialSettings(numCollections: number) { + async function setInitialSettings( + {numCollections, shouldReplaceBrokenImages = false}: CollectionOptions) { handler.setResultFor('getBackgroundCollections', Promise.resolve({ collections: createTestCollections(numCollections), })); if (loadTimeData.getBoolean('imageErrorDetectionEnabled')) { handler.setResultMapperFor( 'getReplacementCollectionPreviewImage', (collectionId: string) => { - return Promise.resolve({ - previewImageUrl: {url: `https://replaced-${collectionId}.jpg`}, - }); + if (shouldReplaceBrokenImages) { + return Promise.resolve({ + previewImageUrl: {url: `https://replaced-${collectionId}.jpg`}, + }); + } else { + return Promise.resolve(null); + } }); } categoriesElement = document.createElement('customize-chrome-categories'); @@ -73,7 +83,7 @@ test('hide collection elements when collections empty', async () => { const numCollections = 0; - await setInitialSettings(numCollections); + await setInitialSettings({numCollections: numCollections}); const collections = categoriesElement.shadowRoot!.querySelectorAll('.collection'); @@ -90,8 +100,7 @@ test('collection visibility based on error detection', async () => { const numCollections = 2; - await setInitialSettings(numCollections); - await microtasksFinished(); + await setInitialSettings({numCollections: numCollections}); const collections = categoriesElement.shadowRoot!.querySelectorAll('.collection'); @@ -114,7 +123,8 @@ test('collection image src based on error detection', async () => { const numCollections = 2; - await setInitialSettings(numCollections); + await setInitialSettings( + {numCollections: numCollections, shouldReplaceBrokenImages: true}); const images = categoriesElement.shadowRoot!.querySelectorAll<CrAutoImgElement>( @@ -128,6 +138,10 @@ if (!errorDetectionEnabled) { assertEquals('https://collection-1.jpg', images[0]!.autoSrc); assertEquals('https://collection-2.jpg', images[1]!.autoSrc); + assertEquals( + 0, + metrics.count( + 'NewTabPage.BackgroundService.Images.Headers.ErrorDetected')); } else { assertEquals('https://replaced-1.jpg', images[0]!.autoSrc); assertEquals('https://replaced-2.jpg', images[1]!.autoSrc); @@ -135,17 +149,16 @@ }); test('collections surface if their images load', async () => { - await setInitialSettings(1); + await setInitialSettings({numCollections: 1}); await microtasksFinished(); const collection = $$(categoriesElement, '.collection'); assertTrue(!!collection); - const img1 = collection!.querySelector<CrAutoImgElement>('img'); - assertTrue(!!img1); - if (errorDetectionEnabled) { assertFalse(isVisible(collection)); } + const img1 = collection!.querySelector<CrAutoImgElement>('img'); + assertTrue(!!img1); img1.dispatchEvent(new Event('load')); await microtasksFinished(); @@ -155,13 +168,44 @@ metrics.count( 'NewTabPage.Images.ShownTime.CollectionPreviewImage')); }); + + test('error detection metrics fire correctly', async () => { + const numCollections = 2; + await setInitialSettings({numCollections: 2}); + + const images = + categoriesElement.shadowRoot!.querySelectorAll<CrAutoImgElement>( + '.collection img'); + assertEquals(numCollections, images.length); + const img1Error = eventToPromise('error', images[0]!); + const img2Error = eventToPromise('error', images[1]!); + await Promise.all([img1Error, img2Error]); + await microtasksFinished(); + + if (!errorDetectionEnabled) { + assertEquals( + 0, + metrics.count( + 'NewTabPage.BackgroundService.Images.Headers.ErrorDetected')); + } else { + assertEquals( + 2, + metrics.count( + 'NewTabPage.BackgroundService.Images.Headers.ErrorDetected')); + assertEquals( + 2, + metrics.count( + 'NewTabPage.BackgroundService.Images.Headers.ErrorDetected', + NtpImageType.COLLECTIONS)); + } + }); }); }); test('collection preview images create metrics when loaded', async () => { const startTime = 123.45; windowProxy.setResultFor('now', startTime); - await setInitialSettings(1); + await setInitialSettings({numCollections: 1}); assertEquals(1, windowProxy.getCallCount('now')); const imageLoadTime = 678.90; windowProxy.setResultFor('now', imageLoadTime); @@ -180,7 +224,7 @@ }); test('clicking collection sends event', async () => { - await setInitialSettings(1); + await setInitialSettings({numCollections: 1}); const eventPromise = eventToPromise('collection-select', categoriesElement); const category = @@ -193,7 +237,7 @@ }); test('back button creates event', async () => { - await setInitialSettings(0); + await setInitialSettings({numCollections: 0}); const eventPromise = eventToPromise('back-click', categoriesElement); categoriesElement.$.heading.getBackButton().click(); const event = await eventPromise; @@ -201,7 +245,7 @@ }); test('clicking classic chrome sets theme', async () => { - await setInitialSettings(0); + await setInitialSettings({numCollections: 0}); categoriesElement.$.classicChromeTile.click(); assertEquals(1, handler.getCallCount('removeBackgroundImage')); assertEquals(1, handler.getCallCount('setDefaultColor')); @@ -214,7 +258,7 @@ loadTimeData.overrideValues({ updatedToUploadedImage: 'Theme updated to uploaded image', }); - await setInitialSettings(0); + await setInitialSettings({numCollections: 0}); handler.setResultFor('chooseLocalCustomBackground', Promise.resolve({ success: true, })); @@ -239,14 +283,14 @@ }); test('clicking Chrome Web Store tile opens Chrome Web Store', async () => { - await setInitialSettings(0); + await setInitialSettings({numCollections: 0}); categoriesElement.$.chromeWebStoreTile.click(); assertEquals(1, handler.getCallCount('openChromeWebStore')); }); test('checks selected category', async () => { - await setInitialSettings(2); + await setInitialSettings({numCollections: 2}); // Set an empty theme with no color and no background. const theme = createTheme(); @@ -314,7 +358,7 @@ }); test('help bubble can correctly find anchor elements', async () => { - await setInitialSettings(5); + await setInitialSettings({numCollections: 5}); assertDeepEquals( categoriesElement.getSortedAnchorStatusesForTesting(), [ @@ -325,7 +369,7 @@ }); test('classic chrome tile shows correct image', async () => { - await setInitialSettings(0); + await setInitialSettings({numCollections: 0}); assertEquals( $$<HTMLImageElement>( @@ -346,7 +390,7 @@ test( `wallpaper search does ${flagEnabled ? '' : 'not '}show`, async () => { - await setInitialSettings(0); + await setInitialSettings({numCollections: 0}); assertEquals( !!categoriesElement.shadowRoot!.querySelector( '#wallpaperSearchTile'), @@ -354,7 +398,7 @@ }); test('check category for wallpaper search background', async () => { - await setInitialSettings(1); + await setInitialSettings({numCollections: 1}); // Set a theme with wallpaper search background. const theme = createTheme(); @@ -392,7 +436,7 @@ }); test('choosing collection sets metric', async () => { - await setInitialSettings(1); + await setInitialSettings({numCollections: 1}); const tile = categoriesElement.shadowRoot!.querySelector('.collection'); assertTrue(!!tile); @@ -409,7 +453,7 @@ }); test('choosing default chrome sets metric', async () => { - await setInitialSettings(0); + await setInitialSettings({numCollections: 0}); categoriesElement.$.classicChromeTile.click(); @@ -423,7 +467,7 @@ }); test('choosing wallpaper search sets metric', async () => { - await setInitialSettings(0); + await setInitialSettings({numCollections: 0}); const tile = categoriesElement.shadowRoot!.querySelector('#wallpaperSearchTile'); @@ -440,7 +484,7 @@ }); test('choosing upload sets metric', async () => { - await setInitialSettings(0); + await setInitialSettings({numCollections: 0}); categoriesElement.$.uploadImageTile.click();
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts index 2482f8c..8e9eba6 100644 --- a/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts +++ b/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts
@@ -4,7 +4,7 @@ import 'chrome://customize-chrome-side-panel.top-chrome/themes.js'; -import {CustomizeChromeAction} from 'chrome://customize-chrome-side-panel.top-chrome/common.js'; +import {CustomizeChromeAction, NtpImageType} from 'chrome://customize-chrome-side-panel.top-chrome/common.js'; import type {BackgroundCollection, CollectionImage, CustomizeChromePageRemote} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; import {CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerRemote} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; import {CustomizeChromeApiProxy} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome_api_proxy.js'; @@ -98,13 +98,13 @@ }); test('get collection images when collection changes', async () => { - let numThemes = 3; - await setCollection('test1', numThemes); + let numImages = 3; + await setCollection('test1', numImages); let header = themesElement.$.heading; assertEquals('test1', header.textContent!.trim()); let themes = themesElement.shadowRoot!.querySelectorAll('.theme'); - assertEquals(themes.length, numThemes); + assertEquals(themes.length, numImages); assertEquals( 'https://preview_1.jpg', themes[0]!.querySelector('img')!.getAttribute('auto-src')); @@ -115,13 +115,13 @@ 'https://preview_3.jpg', themes[2]!.querySelector('img')!.getAttribute('auto-src')); - numThemes = 5; - await setCollection('test2', numThemes); + numImages = 5; + await setCollection('test2', numImages); header = themesElement.$.heading; assertEquals('test2', header.textContent!.trim()); themes = themesElement.shadowRoot!.querySelectorAll('.theme'); - assertEquals(themes.length, numThemes); + assertEquals(themes.length, numImages); assertEquals( 'https://preview_1.jpg', themes[0]!.querySelector('img')!.getAttribute('auto-src')); @@ -350,11 +350,11 @@ }); test('theme visibility based on error detection', async () => { - const numThemes = 2; - await setCollection('test1', numThemes); + const numImages = 2; + await setCollection('test1', numImages); const themes = themesElement.shadowRoot!.querySelectorAll('.theme'); - assertEquals(numThemes, themes.length); + assertEquals(numImages, themes.length); if (!errorDetectionEnabled) { assertTrue(isVisible(themes[0]!)); assertTrue(isVisible(themes[1]!)); @@ -369,17 +369,43 @@ const theme = $$(themesElement, '.theme'); assertTrue(!!theme); - const img1 = theme!.querySelector<CrAutoImgElement>('img'); - assertTrue(!!img1); + const img = theme!.querySelector<CrAutoImgElement>('img'); + assertTrue(!!img); if (errorDetectionEnabled) { assertFalse(isVisible(theme)); } - img1.dispatchEvent(new Event('load')); + img.dispatchEvent(new Event('load')); + await microtasksFinished(); + + assertTrue(isVisible(theme)); + }); + + test('error detection metrics fire correctly', async () => { + const numImages = 1; + await setCollection('test1', numImages); + const img = $$(themesElement, '.theme img'); + assertTrue(!!img); await microtasksFinished(); - assertTrue(isVisible(theme)); + + if (!errorDetectionEnabled) { + assertEquals( + 0, + metrics.count( + 'NewTabPage.BackgroundService.Images.Headers.ErrorDetected')); + } else { + assertEquals( + numImages, + metrics.count( + 'NewTabPage.BackgroundService.Images.Headers.ErrorDetected')); + assertEquals( + numImages, + metrics.count( + 'NewTabPage.BackgroundService.Images.Headers.ErrorDetected', + NtpImageType.BACKGROUND_IMAGE)); + } }); }); });
diff --git a/chrome/test/interaction/README.md b/chrome/test/interaction/README.md index 77b1f5be..5ac3db9 100644 --- a/chrome/test/interaction/README.md +++ b/chrome/test/interaction/README.md
@@ -146,6 +146,8 @@ - `ScrollIntoView()` [Views, Browser] - Recommended before doing anything that needs the screen coordinates of a UI or DOM element that is in a scrollable container. + - `ClickElement()` [Browser] + - For use with instrumented webcontents; see below. - **Mouse** verbs simulate mouse input to the entire application, and are therefore only reliable in test fixtures that run as exclusive processes (e.g. interactive_browser_tests). Examples include:
diff --git a/chrome/test/interaction/interactive_browser_test.cc b/chrome/test/interaction/interactive_browser_test.cc index cc310100..6ae3aeb 100644 --- a/chrome/test/interaction/interactive_browser_test.cc +++ b/chrome/test/interaction/interactive_browser_test.cc
@@ -40,6 +40,7 @@ #include "ui/base/interaction/interaction_sequence.h" #include "ui/base/interaction/interaction_test_util.h" #include "ui/base/interaction/interactive_test_internal.h" +#include "ui/base/test/ui_controls.h" #include "ui/views/controls/webview/webview.h" #include "ui/views/interaction/interaction_test_util_views.h" #include "ui/views/interaction/interactive_views_test.h" @@ -762,6 +763,70 @@ .SetDescription("ScrollIntoView()")); } +ui::InteractionSequence::StepBuilder InteractiveBrowserTestApi::ClickElement( + ui::ElementIdentifier web_contents, + const DeepQuery& where, + ui_controls::MouseButton button, + ui_controls::AcceleratorState modifiers) { + int js_button; + switch (button) { + case ui_controls::LEFT: + js_button = 0; + break; + case ui_controls::MIDDLE: + js_button = 1; + break; + case ui_controls::RIGHT: + js_button = 2; + break; + } + + const bool shift = modifiers & ui_controls::AcceleratorState::kShift; + const bool alt = modifiers & ui_controls::AcceleratorState::kAlt; + const bool ctrl = modifiers & ui_controls::AcceleratorState::kControl; + const bool meta = modifiers & ui_controls::AcceleratorState::kCommand; + + auto b2s = [](bool b) { return b ? "true" : "false"; }; + + const std::string command = base::StringPrintf( + R"( + function(el) { + const rect = el.getBoundingClientRect(); + const left = Math.max(0, rect.x); + const top = Math.max(0, rect.y); + const right = Math.min(rect.x + rect.width, window.innerWidth); + const bottom = Math.min(rect.y + rect.height, window.innerHeight); + if (right <= left || bottom <= top) { + throw new Error( + 'Target element is zero size or ' + + 'has empty intersection with the viewport.'); + } + const x = (left + right) / 2; + const y = (top + bottom) / 2; + + const event = new MouseEvent( + 'click', + { + bubbles: true, + cancelable: true, + clientX: x, + clientY: y, + button: %d, + shiftKey: %s, + altKey: %s, + ctrlKey: %s, + metaKey: %s + } + ); + el.dispatchEvent(event); + } + )", + js_button, b2s(shift), b2s(alt), b2s(ctrl), b2s(meta)); + + return std::move(ExecuteJsAt(web_contents, where, command) + .SetDescription("ClickElement()")); +} + // static InteractiveBrowserTestApi::RelativePositionCallback InteractiveBrowserTestApi::DeepQueryToRelativePosition(const DeepQuery& query) {
diff --git a/chrome/test/interaction/interactive_browser_test.h b/chrome/test/interaction/interactive_browser_test.h index 360e034..75c1eba7 100644 --- a/chrome/test/interaction/interactive_browser_test.h +++ b/chrome/test/interaction/interactive_browser_test.h
@@ -358,6 +358,22 @@ [[nodiscard]] StepBuilder ScrollIntoView(ui::ElementIdentifier web_contents, const DeepQuery& where); + // Simulates clicking on an HTML element by injecting the click event directly + // into the DOM. You can specify the mouse button and additional modifier + // keys (default is left-click, no modifiers). + // + // Normally, clicking with buttons other than the left mouse button generates + // an auxclick event rather than a click event. However, injecting auxclick + // does not e.g. trigger navigation when clicking a link, so in all these + // cases, vanilla click events are sent, which should be handled normally for + // backwards-compatibility reasons. + [[nodiscard]] StepBuilder ClickElement( + ui::ElementIdentifier web_contents, + const DeepQuery& where, + ui_controls::MouseButton button = ui_controls::LEFT, + ui_controls::AcceleratorState modifiers = + ui_controls::AcceleratorState::kNoAccelerator); + protected: explicit InteractiveBrowserTestApi( std::unique_ptr<internal::InteractiveBrowserTestPrivate>
diff --git a/chrome/test/interaction/interactive_browser_test_browsertest.cc b/chrome/test/interaction/interactive_browser_test_browsertest.cc index 669177d..9e32acd8 100644 --- a/chrome/test/interaction/interactive_browser_test_browsertest.cc +++ b/chrome/test/interaction/interactive_browser_test_browsertest.cc
@@ -4,6 +4,9 @@ #include "chrome/test/interaction/interactive_browser_test.h" +#include <sstream> +#include <tuple> + #include "base/command_line.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -19,6 +22,7 @@ #include "ui/base/interaction/expect_call_in_scope.h" #include "ui/base/interaction/interaction_sequence.h" #include "ui/base/mojom/ui_base_types.mojom-shared.h" +#include "ui/base/test/ui_controls.h" #include "ui/base/ui_base_types.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/native_widget_types.h" @@ -30,6 +34,7 @@ DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kWebContentsId); constexpr char kDocumentWithNamedElement[] = "/select.html"; constexpr char kDocumentWithLinks[] = "/links.html"; +constexpr char kDocumentWithClickDetection[] = "/click.html"; constexpr char kScrollableDocument[] = "/scroll/scrollable_page_with_content.html"; } // namespace @@ -561,6 +566,99 @@ WaitForStateChange(kTabId, state_change))); } +using ClickElementParams = + std::tuple<ui_controls::MouseButton, ui_controls::AcceleratorState>; + +class InteractiveBrowserTestClickElementTest + : public InteractiveBrowserTestBrowsertest, + public testing::WithParamInterface<ClickElementParams> { + public: + InteractiveBrowserTestClickElementTest() = default; + ~InteractiveBrowserTestClickElementTest() override = default; +}; + +INSTANTIATE_TEST_SUITE_P( + , + InteractiveBrowserTestClickElementTest, + testing::Combine( + testing::Values(ui_controls::LEFT, + ui_controls::MIDDLE, + ui_controls::RIGHT), + testing::Values(ui_controls::AcceleratorState::kNoAccelerator, + ui_controls::AcceleratorState::kShift, + ui_controls::AcceleratorState::kControl, + ui_controls::AcceleratorState::kAlt, + ui_controls::AcceleratorState::kCommand, + static_cast<ui_controls::AcceleratorState>( + ui_controls::AcceleratorState::kAlt | + ui_controls::AcceleratorState::kShift), + static_cast<ui_controls::AcceleratorState>( + ui_controls::AcceleratorState::kControl | + ui_controls::AcceleratorState::kCommand | + ui_controls::AcceleratorState::kAlt | + ui_controls::AcceleratorState::kShift))), + [](const testing::TestParamInfo<ClickElementParams>& params) { + std::ostringstream oss; + switch (std::get<0>(params.param)) { + case ui_controls::LEFT: + oss << "Left"; + break; + case ui_controls::MIDDLE: + oss << "Middle"; + break; + case ui_controls::RIGHT: + oss << "Right"; + break; + } + const auto accel = std::get<1>(params.param); + if (accel & ui_controls::AcceleratorState::kControl) { + oss << "_Control"; + } + if (accel & ui_controls::AcceleratorState::kAlt) { + oss << "_Alt"; + } + if (accel & ui_controls::AcceleratorState::kShift) { + oss << "_Shift"; + } + if (accel & ui_controls::AcceleratorState::kCommand) { + oss << "_Meta"; + } + return oss.str(); + }); + +IN_PROC_BROWSER_TEST_P(InteractiveBrowserTestClickElementTest, ClickElement) { + const GURL url = embedded_test_server()->GetURL(kDocumentWithClickDetection); + const auto mouse_button = std::get<0>(GetParam()); + const auto modifier = std::get<1>(GetParam()); + const DeepQuery kButton = {"#button"}; + RunTestSequence( + InstrumentTab(kWebContentsId), NavigateWebContents(kWebContentsId, url), + ClickElement(kWebContentsId, kButton, mouse_button, modifier), + CheckJsResultAt(kWebContentsId, kButton, "el => el.lastClickEvent.button", + static_cast<int>(mouse_button)), + CheckJsResultAt(kWebContentsId, kButton, "el => el.lastClickEvent.altKey", + (modifier & ui_controls::AcceleratorState::kAlt) != 0), + CheckJsResultAt(kWebContentsId, kButton, + "el => el.lastClickEvent.shiftKey", + (modifier & ui_controls::AcceleratorState::kShift) != 0), + CheckJsResultAt( + kWebContentsId, kButton, "el => el.lastClickEvent.ctrlKey", + (modifier & ui_controls::AcceleratorState::kControl) != 0), + CheckJsResultAt( + kWebContentsId, kButton, "el => el.lastClickEvent.metaKey", + (modifier & ui_controls::AcceleratorState::kCommand) != 0), + CheckJsResultAt(kWebContentsId, kButton, + R"( + function(el) { + const x = el.lastClickEvent.x; + const y = el.lastClickEvent.y; + const rect = el.getBoundingClientRect(); + return x >= rect.left && x < rect.right && + y >= rect.top && y < rect.bottom; + } + )")); +} + // Parameter for WebUI coverage tests. struct CoverageConfig { // Whether to set the --devtools-code-coverage flag. If it's not set, nothing
diff --git a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java index 848e5c14..2626ee8 100644 --- a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java +++ b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java
@@ -454,11 +454,8 @@ return (playtimeLeftNsecs < 0) ? 0 : playtimeLeftNsecs / 1000; // return usecs } + /** Closes the instance by stopping playback and releasing the AudioTrack object. */ @CalledByNative - /** - * Closes the instance by stopping playback and releasing the AudioTrack - * object. - */ private void close() { Log.i(mTag, "Close AudioSinkAudioTrackImpl!"); if (!isStopped()) mAudioTrack.stop();
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 2585f39..ce8a865 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -16049.0.0-1063698 \ No newline at end of file +16050.0.0-1063704 \ No newline at end of file
diff --git a/chromeos/ash/components/boca/babelorca/BUILD.gn b/chromeos/ash/components/boca/babelorca/BUILD.gn index 67e203b..26e69b8 100644 --- a/chromeos/ash/components/boca/babelorca/BUILD.gn +++ b/chromeos/ash/components/boca/babelorca/BUILD.gn
@@ -25,7 +25,8 @@ "tachyon_registrar.cc", "tachyon_registrar.h", "tachyon_request_data_provider.h", - "tachyon_request_error.h", + "tachyon_response.cc", + "tachyon_response.h", "tachyon_utils.cc", "tachyon_utils.h", "token_data_wrapper.h", @@ -83,6 +84,7 @@ "tachyon_authed_client_impl_unittest.cc", "tachyon_client_impl_unittest.cc", "tachyon_registrar_unittest.cc", + "tachyon_response_unittest.cc", "token_manager_impl_unittest.cc", "transcript_sender_unittest.cc", ]
diff --git a/chromeos/ash/components/boca/babelorca/fakes/fake_tachyon_authed_client.cc b/chromeos/ash/components/boca/babelorca/fakes/fake_tachyon_authed_client.cc index 054d42f..9692683 100644 --- a/chromeos/ash/components/boca/babelorca/fakes/fake_tachyon_authed_client.cc +++ b/chromeos/ash/components/boca/babelorca/fakes/fake_tachyon_authed_client.cc
@@ -12,7 +12,7 @@ #include "base/run_loop.h" #include "base/types/expected.h" #include "chromeos/ash/components/boca/babelorca/request_data_wrapper.h" -#include "chromeos/ash/components/boca/babelorca/tachyon_request_error.h" +#include "chromeos/ash/components/boca/babelorca/tachyon_response.h" #include "third_party/protobuf/src/google/protobuf/message_lite.h" namespace ash::babelorca { @@ -40,7 +40,7 @@ } void FakeTachyonAuthedClient::ExecuteResponseCallback( - base::expected<std::string, TachyonRequestError> response) { + TachyonResponse response) { CHECK(response_cb_); std::move(response_cb_).Run(std::move(response)); }
diff --git a/chromeos/ash/components/boca/babelorca/fakes/fake_tachyon_authed_client.h b/chromeos/ash/components/boca/babelorca/fakes/fake_tachyon_authed_client.h index 4ad3db5..6686098 100644 --- a/chromeos/ash/components/boca/babelorca/fakes/fake_tachyon_authed_client.h +++ b/chromeos/ash/components/boca/babelorca/fakes/fake_tachyon_authed_client.h
@@ -9,13 +9,13 @@ #include <string> #include "base/run_loop.h" -#include "base/types/expected.h" #include "chromeos/ash/components/boca/babelorca/request_data_wrapper.h" #include "chromeos/ash/components/boca/babelorca/tachyon_authed_client.h" -#include "chromeos/ash/components/boca/babelorca/tachyon_request_error.h" namespace ash::babelorca { +class TachyonResponse; + class FakeTachyonAuthedClient : public TachyonAuthedClient { public: FakeTachyonAuthedClient(); @@ -33,8 +33,7 @@ std::unique_ptr<RequestDataWrapper> request_data, std::string request_string) override; - void ExecuteResponseCallback( - base::expected<std::string, TachyonRequestError> response); + void ExecuteResponseCallback(TachyonResponse response); RequestDataWrapper::ResponseCallback TakeResponseCallback();
diff --git a/chromeos/ash/components/boca/babelorca/request_data_wrapper.h b/chromeos/ash/components/boca/babelorca/request_data_wrapper.h index 8285249..2d60e47 100644 --- a/chromeos/ash/components/boca/babelorca/request_data_wrapper.h +++ b/chromeos/ash/components/boca/babelorca/request_data_wrapper.h
@@ -9,15 +9,14 @@ #include <string_view> #include "base/functional/callback.h" -#include "base/types/expected.h" -#include "chromeos/ash/components/boca/babelorca/tachyon_request_error.h" #include "net/traffic_annotation/network_traffic_annotation.h" namespace ash::babelorca { +class TachyonResponse; + struct RequestDataWrapper { - using ResponseCallback = base::OnceCallback<void( - base::expected<std::string, TachyonRequestError>)>; + using ResponseCallback = base::OnceCallback<void(TachyonResponse)>; RequestDataWrapper( const net::NetworkTrafficAnnotationTag& annotation_tag_param,
diff --git a/chromeos/ash/components/boca/babelorca/tachyon_authed_client_impl.cc b/chromeos/ash/components/boca/babelorca/tachyon_authed_client_impl.cc index a900e4f..53501289 100644 --- a/chromeos/ash/components/boca/babelorca/tachyon_authed_client_impl.cc +++ b/chromeos/ash/components/boca/babelorca/tachyon_authed_client_impl.cc
@@ -16,10 +16,9 @@ #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "base/task/thread_pool.h" -#include "base/types/expected.h" #include "chromeos/ash/components/boca/babelorca/request_data_wrapper.h" #include "chromeos/ash/components/boca/babelorca/tachyon_client.h" -#include "chromeos/ash/components/boca/babelorca/tachyon_request_error.h" +#include "chromeos/ash/components/boca/babelorca/tachyon_response.h" #include "chromeos/ash/components/boca/babelorca/token_manager.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "third_party/protobuf/src/google/protobuf/message_lite.h" @@ -70,7 +69,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!request_string) { std::move(request_data->response_cb) - .Run(base::unexpected(TachyonRequestError::kInternalError)); + .Run(TachyonResponse(TachyonResponse::Status::kInternalError)); return; } request_data->content_data = std::move(*request_string); @@ -91,7 +90,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!has_oauth_token) { std::move(request_data->response_cb) - .Run(base::unexpected(TachyonRequestError::kAuthError)); + .Run(TachyonResponse(TachyonResponse::Status::kAuthError)); return; } std::string oauth_token = *(oauth_token_manager_->GetTokenString()); @@ -108,7 +107,7 @@ static int constexpr kMaxAuthRetries = 1; if (request_data->oauth_retry_num >= kMaxAuthRetries) { std::move(request_data->response_cb) - .Run(base::unexpected(TachyonRequestError::kAuthError)); + .Run(TachyonResponse(TachyonResponse::Status::kAuthError)); return; } ++(request_data->oauth_retry_num);
diff --git a/chromeos/ash/components/boca/babelorca/tachyon_authed_client_impl_unittest.cc b/chromeos/ash/components/boca/babelorca/tachyon_authed_client_impl_unittest.cc index 3381d50..cdf95ff9 100644 --- a/chromeos/ash/components/boca/babelorca/tachyon_authed_client_impl_unittest.cc +++ b/chromeos/ash/components/boca/babelorca/tachyon_authed_client_impl_unittest.cc
@@ -11,12 +11,11 @@ #include "base/memory/raw_ptr.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" -#include "base/types/expected.h" #include "chromeos/ash/components/boca/babelorca/fakes/fake_tachyon_client.h" #include "chromeos/ash/components/boca/babelorca/fakes/fake_token_manager.h" #include "chromeos/ash/components/boca/babelorca/proto/testing_message.pb.h" #include "chromeos/ash/components/boca/babelorca/request_data_wrapper.h" -#include "chromeos/ash/components/boca/babelorca/tachyon_request_error.h" +#include "chromeos/ash/components/boca/babelorca/tachyon_response.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -24,8 +23,6 @@ namespace ash::babelorca { namespace { -using ExpectedTestingMessage = base::expected<std::string, TachyonRequestError>; - constexpr char kOAuthToken1[] = "oauth-token1"; constexpr char kOAuthToken2[] = "oauth-token2"; constexpr int kMaxRetries = 2; @@ -64,7 +61,7 @@ test_future_.GetCallback()); } - base::test::TestFuture<ExpectedTestingMessage>* test_future() { + base::test::TestFuture<TachyonResponse>* test_future() { return &test_future_; } @@ -76,7 +73,7 @@ FakeTokenManager fake_token_manager_; std::unique_ptr<TestingMessage> request_message_; std::string request_string_; - base::test::TestFuture<ExpectedTestingMessage> test_future_; + base::test::TestFuture<TachyonResponse> test_future_; }; TEST_F(TachyonAuthedClientImplTest, InitiallyAuthed) { @@ -215,8 +212,7 @@ fake_client_ptr()->WaitForRequest(); fake_client_ptr()->ExecuteAuthFailCb(); - EXPECT_EQ(test_future()->Get(), - base::unexpected(TachyonRequestError::kAuthError)); + EXPECT_EQ(test_future()->Get().status(), TachyonResponse::Status::kAuthError); } TEST_F(TachyonAuthedClientImplTest, TokenFetchFailed) { @@ -226,8 +222,7 @@ fake_token_manager()->WaitForForceFetchRequest(); fake_token_manager()->ExecuteFetchCallback(/*success=*/false); - EXPECT_EQ(test_future()->Get(), - base::unexpected(TachyonRequestError::kAuthError)); + EXPECT_EQ(test_future()->Get().status(), TachyonResponse::Status::kAuthError); } } // namespace
diff --git a/chromeos/ash/components/boca/babelorca/tachyon_client_impl.cc b/chromeos/ash/components/boca/babelorca/tachyon_client_impl.cc index 003d4a0..270b022 100644 --- a/chromeos/ash/components/boca/babelorca/tachyon_client_impl.cc +++ b/chromeos/ash/components/boca/babelorca/tachyon_client_impl.cc
@@ -5,6 +5,7 @@ #include "chromeos/ash/components/boca/babelorca/tachyon_client_impl.h" #include <memory> +#include <optional> #include <string> #include <utility> @@ -13,9 +14,8 @@ #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/strings/stringprintf.h" -#include "base/types/expected.h" #include "chromeos/ash/components/boca/babelorca/request_data_wrapper.h" -#include "chromeos/ash/components/boca/babelorca/tachyon_request_error.h" +#include "chromeos/ash/components/boca/babelorca/tachyon_response.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/http/http_request_headers.h" @@ -80,34 +80,17 @@ std::unique_ptr<RequestDataWrapper> request_data, AuthFailureCallback auth_failure_cb, std::unique_ptr<std::string> response_body) { - if (url_loader->NetError() != net::OK && - url_loader->NetError() != net::ERR_HTTP_RESPONSE_CODE_FAILURE) { - std::move(request_data->response_cb) - .Run(base::unexpected(TachyonRequestError::kNetworkError)); - return; + std::optional<int> http_status_code; + if (url_loader->ResponseInfo() && url_loader->ResponseInfo()->headers) { + http_status_code = url_loader->ResponseInfo()->headers->response_code(); } - if (!url_loader->ResponseInfo() || !url_loader->ResponseInfo()->headers) { - std::move(request_data->response_cb) - .Run(base::unexpected(TachyonRequestError::kInternalError)); - return; - } - const int response_code = - url_loader->ResponseInfo()->headers->response_code(); - if (response_code == net::HttpStatusCode::HTTP_UNAUTHORIZED) { + TachyonResponse response(url_loader->NetError(), http_status_code, + std::move(response_body)); + if (response.status() == TachyonResponse::Status::kAuthError) { std::move(auth_failure_cb).Run(std::move(request_data)); return; } - if (!network::IsSuccessfulStatus(response_code)) { - std::move(request_data->response_cb) - .Run(base::unexpected(TachyonRequestError::kHttpError)); - return; - } - if (!response_body) { - std::move(request_data->response_cb) - .Run(base::unexpected(TachyonRequestError::kInternalError)); - return; - } - std::move(request_data->response_cb).Run(std::move(*response_body)); + std::move(request_data->response_cb).Run(std::move(response)); } } // namespace ash::babelorca
diff --git a/chromeos/ash/components/boca/babelorca/tachyon_client_impl_unittest.cc b/chromeos/ash/components/boca/babelorca/tachyon_client_impl_unittest.cc index 6d7b4ad2..01cd300 100644 --- a/chromeos/ash/components/boca/babelorca/tachyon_client_impl_unittest.cc +++ b/chromeos/ash/components/boca/babelorca/tachyon_client_impl_unittest.cc
@@ -10,10 +10,9 @@ #include "base/memory/scoped_refptr.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" -#include "base/types/expected.h" #include "chromeos/ash/components/boca/babelorca/proto/testing_message.pb.h" #include "chromeos/ash/components/boca/babelorca/request_data_wrapper.h" -#include "chromeos/ash/components/boca/babelorca/tachyon_request_error.h" +#include "chromeos/ash/components/boca/babelorca/tachyon_response.h" #include "net/base/net_errors.h" #include "net/http/http_status_code.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -27,7 +26,6 @@ namespace ash::babelorca { namespace { -using ExpectedTestingMessage = base::expected<std::string, TachyonRequestError>; using RequestDataPtr = std::unique_ptr<RequestDataWrapper>; constexpr char kOAuthToken[] = "oauth-token"; @@ -50,13 +48,13 @@ return &auth_failure_future_; } - base::test::TestFuture<ExpectedTestingMessage>* result_future() { + base::test::TestFuture<TachyonResponse>* result_future() { return &result_future_; } private: base::test::TestFuture<RequestDataPtr> auth_failure_future_; - base::test::TestFuture<ExpectedTestingMessage> result_future_; + base::test::TestFuture<TachyonResponse> result_future_; base::test::TaskEnvironment task_env_; }; @@ -70,10 +68,10 @@ client.StartRequest(request_data(), kOAuthToken, auth_failure_future()->GetCallback()); - auto result = result_future()->Get(); - ASSERT_TRUE(result.has_value()); + auto result = result_future()->Take(); + EXPECT_TRUE(result.ok()); TestingMessage result_proto; - ASSERT_TRUE(result_proto.ParseFromString(result.value())); + ASSERT_TRUE(result_proto.ParseFromString(result.response_body())); EXPECT_EQ(result_proto.int_field(), 9999); EXPECT_FALSE(auth_failure_future()->IsReady()); } @@ -88,9 +86,8 @@ client.StartRequest(request_data(), kOAuthToken, auth_failure_future()->GetCallback()); - auto result = result_future()->Get(); - ASSERT_FALSE(result.has_value()); - EXPECT_EQ(result.error(), TachyonRequestError::kNetworkError); + auto result = result_future()->Take(); + EXPECT_EQ(result.status(), TachyonResponse::Status::kNetworkError); EXPECT_FALSE(auth_failure_future()->IsReady()); } @@ -103,9 +100,8 @@ client.StartRequest(request_data(), kOAuthToken, auth_failure_future()->GetCallback()); - auto result = result_future()->Get(); - ASSERT_FALSE(result.has_value()); - EXPECT_EQ(result.error(), TachyonRequestError::kHttpError); + auto result = result_future()->Take(); + EXPECT_EQ(result.status(), TachyonResponse::Status::kHttpError); EXPECT_FALSE(auth_failure_future()->IsReady()); }
diff --git a/chromeos/ash/components/boca/babelorca/tachyon_registrar.cc b/chromeos/ash/components/boca/babelorca/tachyon_registrar.cc index 28d13a1..5041ebac 100644 --- a/chromeos/ash/components/boca/babelorca/tachyon_registrar.cc +++ b/chromeos/ash/components/boca/babelorca/tachyon_registrar.cc
@@ -12,7 +12,6 @@ #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/sequence_checker.h" -#include "base/types/expected.h" #include "base/uuid.h" #include "chromeos/ash/components/boca/babelorca/proto/tachyon.pb.h" #include "chromeos/ash/components/boca/babelorca/proto/tachyon_common.pb.h" @@ -20,6 +19,7 @@ #include "chromeos/ash/components/boca/babelorca/request_data_wrapper.h" #include "chromeos/ash/components/boca/babelorca/tachyon_authed_client.h" #include "chromeos/ash/components/boca/babelorca/tachyon_constants.h" +#include "chromeos/ash/components/boca/babelorca/tachyon_response.h" #include "chromeos/ash/components/boca/babelorca/tachyon_utils.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -69,16 +69,15 @@ return tachyon_token_; } -void TachyonRegistrar::OnResponse( - base::OnceCallback<void(bool)> success_cb, - base::expected<std::string, TachyonRequestError> response) { +void TachyonRegistrar::OnResponse(base::OnceCallback<void(bool)> success_cb, + TachyonResponse response) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!response.has_value()) { + if (!response.ok()) { std::move(success_cb).Run(false); return; } SignInGaiaResponse signin_response; - if (!signin_response.ParseFromString(response.value())) { + if (!signin_response.ParseFromString(response.response_body())) { std::move(success_cb).Run(false); return; }
diff --git a/chromeos/ash/components/boca/babelorca/tachyon_registrar.h b/chromeos/ash/components/boca/babelorca/tachyon_registrar.h index 7f079cf..3b14125 100644 --- a/chromeos/ash/components/boca/babelorca/tachyon_registrar.h +++ b/chromeos/ash/components/boca/babelorca/tachyon_registrar.h
@@ -15,13 +15,12 @@ #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "base/thread_annotations.h" -#include "base/types/expected.h" -#include "chromeos/ash/components/boca/babelorca/tachyon_request_error.h" #include "net/traffic_annotation/network_traffic_annotation.h" namespace ash::babelorca { class TachyonAuthedClient; +class TachyonResponse; // Register user with Tachyon and store tachyon token to be used by other // tachyon requests. @@ -45,7 +44,7 @@ private: void OnResponse(base::OnceCallback<void(bool)> success_cb, - base::expected<std::string, TachyonRequestError> response); + TachyonResponse response); SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chromeos/ash/components/boca/babelorca/tachyon_registrar_unittest.cc b/chromeos/ash/components/boca/babelorca/tachyon_registrar_unittest.cc index 8b9a0a9..4b5aa66d 100644 --- a/chromeos/ash/components/boca/babelorca/tachyon_registrar_unittest.cc +++ b/chromeos/ash/components/boca/babelorca/tachyon_registrar_unittest.cc
@@ -9,10 +9,11 @@ #include "base/test/task_environment.h" #include "base/test/test_future.h" -#include "base/types/expected.h" #include "chromeos/ash/components/boca/babelorca/fakes/fake_tachyon_authed_client.h" #include "chromeos/ash/components/boca/babelorca/proto/tachyon.pb.h" -#include "chromeos/ash/components/boca/babelorca/tachyon_request_error.h" +#include "chromeos/ash/components/boca/babelorca/tachyon_response.h" +#include "net/base/net_errors.h" +#include "net/http/http_status_code.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -31,7 +32,9 @@ registrar.Register(kClientUuid, test_future.GetCallback()); SignInGaiaResponse signin_response; signin_response.mutable_auth_token()->set_payload(kTachyonToken); - authed_client.ExecuteResponseCallback(signin_response.SerializeAsString()); + authed_client.ExecuteResponseCallback(TachyonResponse( + net::OK, net::HttpStatusCode::HTTP_OK, + std::make_unique<std::string>(signin_response.SerializeAsString()))); EXPECT_TRUE(test_future.Get()); std::optional<std::string> tachyon_token = registrar.GetTachyonToken(); @@ -47,7 +50,7 @@ registrar.Register(kClientUuid, test_future.GetCallback()); authed_client.ExecuteResponseCallback( - base::unexpected(TachyonRequestError::kHttpError)); + TachyonResponse(TachyonResponse::Status::kHttpError)); EXPECT_FALSE(test_future.Get()); std::optional<std::string> tachyon_token = registrar.GetTachyonToken();
diff --git a/chromeos/ash/components/boca/babelorca/tachyon_request_error.h b/chromeos/ash/components/boca/babelorca/tachyon_request_error.h deleted file mode 100644 index 41ae4f4..0000000 --- a/chromeos/ash/components/boca/babelorca/tachyon_request_error.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_COMPONENTS_BOCA_BABELORCA_TACHYON_REQUEST_ERROR_H_ -#define CHROMEOS_ASH_COMPONENTS_BOCA_BABELORCA_TACHYON_REQUEST_ERROR_H_ - -namespace ash::babelorca { - -enum class TachyonRequestError { - kHttpError, - kNetworkError, - kInternalError, - kAuthError -}; - -} - -#endif // CHROMEOS_ASH_COMPONENTS_BOCA_BABELORCA_TACHYON_REQUEST_ERROR_H_
diff --git a/chromeos/ash/components/boca/babelorca/tachyon_response.cc b/chromeos/ash/components/boca/babelorca/tachyon_response.cc new file mode 100644 index 0000000..b2695a1 --- /dev/null +++ b/chromeos/ash/components/boca/babelorca/tachyon_response.cc
@@ -0,0 +1,66 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/ash/components/boca/babelorca/tachyon_response.h" + +#include <memory> +#include <string> +#include <utility> + +#include "net/base/net_errors.h" +#include "net/http/http_status_code.h" +#include "services/network/public/cpp/header_util.h" + +namespace ash::babelorca { + +TachyonResponse::TachyonResponse(Status status) : status_(status) {} + +TachyonResponse::TachyonResponse(int rpc_code, + const std::string& error_message) { + constexpr int kOkCode = 0; + constexpr int kUnauthenticatedCode = 16; + switch (rpc_code) { + case kOkCode: + status_ = Status::kOk; + break; + case kUnauthenticatedCode: + status_ = Status::kAuthError; + break; + default: + status_ = Status::kHttpError; + } + error_message_ = error_message; +} + +TachyonResponse::TachyonResponse(int net_error, + std::optional<int> http_status_code, + std::unique_ptr<std::string> response_body) { + if (net_error != net::OK && + net_error != net::ERR_HTTP_RESPONSE_CODE_FAILURE) { + status_ = Status::kNetworkError; + return; + } + if (!http_status_code.has_value()) { + status_ = Status::kInternalError; + return; + } + if (http_status_code == net::HttpStatusCode::HTTP_UNAUTHORIZED) { + status_ = Status::kAuthError; + return; + } + if (!network::IsSuccessfulStatus(http_status_code.value())) { + status_ = Status::kHttpError; + return; + } + response_body_ = response_body ? std::move(*response_body) : ""; + status_ = Status::kOk; +} + +TachyonResponse::~TachyonResponse() = default; + +bool TachyonResponse::ok() const { + return status_ == Status::kOk; +} + +} // namespace ash::babelorca
diff --git a/chromeos/ash/components/boca/babelorca/tachyon_response.h b/chromeos/ash/components/boca/babelorca/tachyon_response.h new file mode 100644 index 0000000..a2d7950c --- /dev/null +++ b/chromeos/ash/components/boca/babelorca/tachyon_response.h
@@ -0,0 +1,51 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_ASH_COMPONENTS_BOCA_BABELORCA_TACHYON_RESPONSE_H_ +#define CHROMEOS_ASH_COMPONENTS_BOCA_BABELORCA_TACHYON_RESPONSE_H_ + +#include <memory> +#include <string> + +namespace ash::babelorca { + +class TachyonResponse { + public: + enum class Status { + kOk, + kHttpError, + kNetworkError, + kInternalError, + kAuthError + }; + explicit TachyonResponse(Status status); + explicit TachyonResponse(int rpc_code, const std::string& error_message = ""); + TachyonResponse(int net_error, + std::optional<int> http_status_code, + std::unique_ptr<std::string> response_body); + + TachyonResponse(TachyonResponse&& other) = default; + TachyonResponse& operator=(TachyonResponse&& other) = default; + + ~TachyonResponse(); + + bool ok() const; + + Status status() const { return status_; } + + // Empty string if there is no response body. + const std::string& response_body() const { return response_body_; } + + // Empty string if there is no error message. + const std::string& error_message() const { return error_message_; } + + private: + Status status_; + std::string response_body_; + std::string error_message_; +}; + +} // namespace ash::babelorca + +#endif // CHROMEOS_ASH_COMPONENTS_BOCA_BABELORCA_TACHYON_RESPONSE_H_
diff --git a/chromeos/ash/components/boca/babelorca/tachyon_response_unittest.cc b/chromeos/ash/components/boca/babelorca/tachyon_response_unittest.cc new file mode 100644 index 0000000..c414e574 --- /dev/null +++ b/chromeos/ash/components/boca/babelorca/tachyon_response_unittest.cc
@@ -0,0 +1,96 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/ash/components/boca/babelorca/tachyon_response.h" + +#include <memory> +#include <string> + +#include "net/base/net_errors.h" +#include "net/http/http_status_code.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace ash::babelorca { +namespace { + +struct TachyonResponseTestCase { + std::string test_name; + int net_error; + std::optional<int> http_status_code; + std::string response_body; + TachyonResponse::Status expected_status; +}; + +using TachyonResponseTest = testing::TestWithParam<TachyonResponseTestCase>; + +TEST(TachyonResponseTest, InternalErrorStatus) { + TachyonResponse response(TachyonResponse::Status::kInternalError); + EXPECT_FALSE(response.ok()); + EXPECT_EQ(response.status(), TachyonResponse::Status::kInternalError); + EXPECT_THAT(response.error_message(), testing::IsEmpty()); + EXPECT_THAT(response.response_body(), testing::IsEmpty()); +} + +TEST(TachyonResponseTest, OkRpcCode) { + TachyonResponse response(/*rpc_code=*/0); + EXPECT_TRUE(response.ok()); + EXPECT_EQ(response.status(), TachyonResponse::Status::kOk); + EXPECT_THAT(response.error_message(), testing::IsEmpty()); + EXPECT_THAT(response.response_body(), testing::IsEmpty()); +} + +TEST(TachyonResponseTest, AuthErrorRpcCode) { + constexpr char kAuthErrorMessage[] = "auth error"; + TachyonResponse response(/*rpc_code=*/16, + /*error_message=*/kAuthErrorMessage); + EXPECT_FALSE(response.ok()); + EXPECT_EQ(response.status(), TachyonResponse::Status::kAuthError); + EXPECT_THAT(response.error_message(), testing::StrEq(kAuthErrorMessage)); + EXPECT_THAT(response.response_body(), testing::IsEmpty()); +} + +TEST(TachyonResponseTest, OtherRpcCode) { + constexpr char kResourcedMessage[] = "resource exhausted"; + TachyonResponse response(/*rpc_code=*/8, /*error_message=*/kResourcedMessage); + EXPECT_FALSE(response.ok()); + EXPECT_EQ(response.status(), TachyonResponse::Status::kHttpError); + EXPECT_THAT(response.error_message(), testing::StrEq(kResourcedMessage)); + EXPECT_THAT(response.response_body(), testing::IsEmpty()); +} + +TEST_P(TachyonResponseTest, HttpHeader) { + TachyonResponse response( + GetParam().net_error, GetParam().http_status_code, + std::make_unique<std::string>(GetParam().response_body)); + EXPECT_EQ(response.status(), GetParam().expected_status); + EXPECT_THAT(response.response_body(), + testing::StrEq(GetParam().response_body)); + EXPECT_THAT(response.error_message(), testing::IsEmpty()); +} + +INSTANTIATE_TEST_SUITE_P( + TachyonResponseTestSuiteInstantiation, + TachyonResponseTest, + testing::ValuesIn<TachyonResponseTestCase>({ + {"NetError", net::ERR_TOO_MANY_RETRIES, std::nullopt, "", + TachyonResponse::Status::kNetworkError}, + {"NoHttpStatus", net::OK, std::nullopt, "", + TachyonResponse::Status::kInternalError}, + {"AuthError", net::ERR_HTTP_RESPONSE_CODE_FAILURE, + net::HttpStatusCode::HTTP_UNAUTHORIZED, "", + TachyonResponse::Status::kAuthError}, + {"OtherHttpError", net::ERR_HTTP_RESPONSE_CODE_FAILURE, + net::HttpStatusCode::HTTP_PRECONDITION_FAILED, "", + TachyonResponse::Status::kHttpError}, + {"Success", net::ERR_HTTP_RESPONSE_CODE_FAILURE, + net::HttpStatusCode::HTTP_OK, "response", + TachyonResponse::Status::kOk}, + }), + [](const testing::TestParamInfo<TachyonResponseTest::ParamType>& info) { + return info.param.test_name; + }); + +} // namespace +} // namespace ash::babelorca
diff --git a/chromeos/ash/components/boca/babelorca/transcript_sender.cc b/chromeos/ash/components/boca/babelorca/transcript_sender.cc index 3e4ba0b..532278f 100644 --- a/chromeos/ash/components/boca/babelorca/transcript_sender.cc +++ b/chromeos/ash/components/boca/babelorca/transcript_sender.cc
@@ -28,7 +28,7 @@ #include "chromeos/ash/components/boca/babelorca/tachyon_authed_client.h" #include "chromeos/ash/components/boca/babelorca/tachyon_constants.h" #include "chromeos/ash/components/boca/babelorca/tachyon_request_data_provider.h" -#include "chromeos/ash/components/boca/babelorca/tachyon_request_error.h" +#include "chromeos/ash/components/boca/babelorca/tachyon_response.h" #include "chromeos/ash/components/boca/babelorca/tachyon_utils.h" #include "media/mojo/mojom/speech_recognition_result.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -203,10 +203,9 @@ std::move(request_string)); } -void TranscriptSender::OnSendResponse( - base::expected<std::string, TachyonRequestError> response) { +void TranscriptSender::OnSendResponse(TachyonResponse response) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (response.has_value()) { + if (response.ok()) { errors_num_ = 0; return; }
diff --git a/chromeos/ash/components/boca/babelorca/transcript_sender.h b/chromeos/ash/components/boca/babelorca/transcript_sender.h index d34a310..f97ee73 100644 --- a/chromeos/ash/components/boca/babelorca/transcript_sender.h +++ b/chromeos/ash/components/boca/babelorca/transcript_sender.h
@@ -18,8 +18,6 @@ #include "base/sequence_checker.h" #include "base/thread_annotations.h" #include "base/time/time.h" -#include "base/types/expected.h" -#include "chromeos/ash/components/boca/babelorca/tachyon_request_error.h" #include "net/traffic_annotation/network_traffic_annotation.h" namespace media { @@ -35,6 +33,7 @@ class BabelOrcaMessage; class TachyonAuthedClient; class TachyonRequestDataProvider; +class TachyonResponse; // Class to send transcriptions. class TranscriptSender { @@ -74,8 +73,7 @@ void Send(int max_retries, std::string message); - void OnSendResponse( - base::expected<std::string, TachyonRequestError> response); + void OnSendResponse(TachyonResponse response); SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chromeos/ash/components/boca/babelorca/transcript_sender_unittest.cc b/chromeos/ash/components/boca/babelorca/transcript_sender_unittest.cc index a87f7e0..0969b1e 100644 --- a/chromeos/ash/components/boca/babelorca/transcript_sender_unittest.cc +++ b/chromeos/ash/components/boca/babelorca/transcript_sender_unittest.cc
@@ -4,12 +4,13 @@ #include "chromeos/ash/components/boca/babelorca/transcript_sender.h" +#include <optional> #include <string> +#include <utility> #include "base/test/task_environment.h" #include "base/test/test_future.h" #include "base/time/time.h" -#include "base/types/expected.h" #include "chromeos/ash/components/boca/babelorca/fakes/fake_tachyon_authed_client.h" #include "chromeos/ash/components/boca/babelorca/fakes/fake_tachyon_client.h" #include "chromeos/ash/components/boca/babelorca/fakes/fake_tachyon_request_data_provider.h" @@ -18,8 +19,10 @@ #include "chromeos/ash/components/boca/babelorca/proto/tachyon_enums.pb.h" #include "chromeos/ash/components/boca/babelorca/request_data_wrapper.h" #include "chromeos/ash/components/boca/babelorca/tachyon_constants.h" -#include "chromeos/ash/components/boca/babelorca/tachyon_request_error.h" +#include "chromeos/ash/components/boca/babelorca/tachyon_response.h" #include "media/mojo/mojom/speech_recognition_result.h" +#include "net/base/net_errors.h" +#include "net/http/http_status_code.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -72,8 +75,9 @@ /*is_final=*/false); EXPECT_TRUE(sender.SendTranscriptionUpdate(transcript, kLanguage)); authed_client.WaitForRequest(); - authed_client.ExecuteResponseCallback( - InboxSendResponse().SerializeAsString()); + authed_client.ExecuteResponseCallback(TachyonResponse( + net::OK, net::HttpStatusCode::HTTP_OK, + std::make_unique<std::string>(InboxSendResponse().SerializeAsString()))); EXPECT_FALSE(failure_future.IsReady()); InboxSendRequest sent_request; @@ -135,16 +139,18 @@ EXPECT_TRUE(sender.SendTranscriptionUpdate(transcript1, kLanguage)); authed_client.WaitForRequest(); request_string1 = authed_client.GetRequestString(); - authed_client.ExecuteResponseCallback( - InboxSendResponse().SerializeAsString()); + authed_client.ExecuteResponseCallback(TachyonResponse( + net::OK, net::HttpStatusCode::HTTP_OK, + std::make_unique<std::string>(InboxSendResponse().SerializeAsString()))); media::SpeechRecognitionResult transcript2(kTranscriptText, /*is_final=*/false); EXPECT_TRUE(sender.SendTranscriptionUpdate(transcript2, kLanguage)); authed_client.WaitForRequest(); request_string2 = authed_client.GetRequestString(); - authed_client.ExecuteResponseCallback( - InboxSendResponse().SerializeAsString()); + authed_client.ExecuteResponseCallback(TachyonResponse( + net::OK, net::HttpStatusCode::HTTP_OK, + std::make_unique<std::string>(InboxSendResponse().SerializeAsString()))); EXPECT_FALSE(failure_future.IsReady()); InboxSendRequest sent_request1; @@ -194,14 +200,14 @@ EXPECT_TRUE(sender.SendTranscriptionUpdate(transcript1, kLanguage)); authed_client.WaitForRequest(); authed_client.ExecuteResponseCallback( - base::unexpected(TachyonRequestError::kHttpError)); + TachyonResponse(TachyonResponse::Status::kHttpError)); media::SpeechRecognitionResult transcript2(kTranscriptText, /*is_final=*/false); EXPECT_TRUE(sender.SendTranscriptionUpdate(transcript2, kLanguage)); authed_client.WaitForRequest(); authed_client.ExecuteResponseCallback( - base::unexpected(TachyonRequestError::kHttpError)); + TachyonResponse(TachyonResponse::Status::kHttpError)); media::SpeechRecognitionResult transcript3(kTranscriptText, /*is_final=*/false); @@ -230,15 +236,16 @@ EXPECT_TRUE(sender.SendTranscriptionUpdate(transcript1, kLanguage)); authed_client.WaitForRequest(); authed_client.ExecuteResponseCallback( - base::unexpected(TachyonRequestError::kHttpError)); + TachyonResponse(TachyonResponse::Status::kHttpError)); // Successful request, should reset error count. media::SpeechRecognitionResult transcript2(kTranscriptText, /*is_final=*/false); EXPECT_TRUE(sender.SendTranscriptionUpdate(transcript2, kLanguage)); authed_client.WaitForRequest(); - authed_client.ExecuteResponseCallback( - InboxSendResponse().SerializeAsString()); + authed_client.ExecuteResponseCallback(TachyonResponse( + net::OK, net::HttpStatusCode::HTTP_OK, + std::make_unique<std::string>(InboxSendResponse().SerializeAsString()))); // Failed request, should not trigger failure callback since the error count // was reset. @@ -247,7 +254,7 @@ EXPECT_TRUE(sender.SendTranscriptionUpdate(transcript3, kLanguage)); authed_client.WaitForRequest(); authed_client.ExecuteResponseCallback( - base::unexpected(TachyonRequestError::kHttpError)); + TachyonResponse(TachyonResponse::Status::kHttpError)); EXPECT_FALSE(failure_future.IsReady()); } @@ -288,14 +295,14 @@ authed_client.TakeResponseCallback(); std::move(response_cb1) - .Run(base::unexpected(TachyonRequestError::kHttpError)); + .Run(TachyonResponse(TachyonResponse::Status::kHttpError)); std::move(response_cb2) - .Run(base::unexpected(TachyonRequestError::kHttpError)); + .Run(TachyonResponse(TachyonResponse::Status::kHttpError)); EXPECT_TRUE(failure_future.IsReady()); std::move(response_cb3) - .Run(base::unexpected(TachyonRequestError::kHttpError)); + .Run(TachyonResponse(TachyonResponse::Status::kHttpError)); media::SpeechRecognitionResult transcript4(kTranscriptText, /*is_final=*/false);
diff --git a/chromeos/profiles/arm.afdo.newest.txt b/chromeos/profiles/arm.afdo.newest.txt index 7c19afd68..efe8bc0 100644 --- a/chromeos/profiles/arm.afdo.newest.txt +++ b/chromeos/profiles/arm.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-arm-none-131-6723.9-1727662744-benchmark-131.0.6749.0-r1-redacted.afdo.xz +chromeos-chrome-arm-none-131-6723.9-1727662744-benchmark-131.0.6750.0-r1-redacted.afdo.xz
diff --git a/clank b/clank index 59c00202..4120c4d 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 59c00202c7c9270d760bf9a57ffd242ef6b0f271 +Subproject commit 4120c4d811f4c534ae4be631037163de6f797935
diff --git a/components/OWNERS b/components/OWNERS index e0ba2bb..6fa527a 100644 --- a/components/OWNERS +++ b/components/OWNERS
@@ -48,8 +48,8 @@ per-file privacy_sandbox_strings.grd=file://components/privacy_sandbox/OWNERS per-file reset_password_strings.grdp=file://components/safe_browsing/OWNERS per-file saved_tab_groups_strings.grdp=file://components/saved_tab_groups/OWNERS -per-file search_engine_choice_strings.grdp=file://components/search_engines/search_engine_choice/OWNERS -per-file search_engine_descriptions_strings.grd=file://components/search_engines/search_engine_choice/OWNERS +per-file search_engine_choice_strings.grdp=file://components/search_engines/search_engine_choice/COMPLIANCE_OWNERS +per-file search_engine_descriptions_strings.grd=file://components/search_engines/search_engine_choice/COMPLIANCE_OWNERS per-file security_interstitials_strings.grdp=file://components/security_interstitials/OWNERS per-file send_tab_to_self_strings.grdp=file://components/send_tab_to_self/OWNERS per-file site_settings_strings.grdp=file://components/browser_ui/site_settings/OWNERS
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/payments/AutofillSaveIbanUiInfo.java b/components/autofill/android/java/src/org/chromium/components/autofill/payments/AutofillSaveIbanUiInfo.java index e11ead6..1ab20afa 100644 --- a/components/autofill/android/java/src/org/chromium/components/autofill/payments/AutofillSaveIbanUiInfo.java +++ b/components/autofill/android/java/src/org/chromium/components/autofill/payments/AutofillSaveIbanUiInfo.java
@@ -17,11 +17,11 @@ import java.util.List; import java.util.Objects; -@JNINamespace("autofill") /** * The android version of the C++ AutofillSaveIbanUiInfo providing UI resources for the save IBAN * bottom sheet. */ +@JNINamespace("autofill") public class AutofillSaveIbanUiInfo { private final String mAcceptText; private final String mCancelText; @@ -64,8 +64,6 @@ return mTitleText; } - @CalledByNative - @VisibleForTesting /** * Construct the {@link AutofillSaveIbanUiInfo} given all the members. This constructor is used * for native binding purposes. @@ -80,6 +78,8 @@ * {@code 0} for local save. * @param titleText A bottom sheet title UI string. This value must not be {@code null}. */ + @CalledByNative + @VisibleForTesting /* package */ AutofillSaveIbanUiInfo( @JniType("std::u16string") String acceptText, @JniType("std::u16string") String cancelText,
diff --git a/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_filling_engine_impl.cc b/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_filling_engine_impl.cc index a1ba10c..9e01583 100644 --- a/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_filling_engine_impl.cc +++ b/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_filling_engine_impl.cc
@@ -154,6 +154,10 @@ // in the suggestion as the main text. select_option_text = predicted_select_option_it->text; } + // Skip predictions for non-empty text fields. + else if (field.IsTextInputElement() && !field.value().empty()) { + continue; + } const std::u16string label = filled_form_field_proto.normalized_label().empty()
diff --git a/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_filling_engine_impl_unittest.cc b/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_filling_engine_impl_unittest.cc index f1ee7f68..b58c00f 100644 --- a/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_filling_engine_impl_unittest.cc +++ b/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_filling_engine_impl_unittest.cc
@@ -108,6 +108,7 @@ AddFieldToResponse(response, "Country - response equals selected value, not filled", "", "2"); + AddFieldToResponse(response, "Field has value, not filled", "", "value"); optimization_guide::proto::Any any; any.set_type_url(response.GetTypeName()); response.SerializeToString(any.mutable_value()); @@ -139,7 +140,8 @@ .value = u"2", .form_control_type = autofill::FormControlType::kSelectOne, .select_options = {{.value = u"1", .text = u"France"}, - {.value = u"2", .text = u"Spain"}}}}}; + {.value = u"2", .text = u"Spain"}}}, + {.label = u"Field has value, not filled", .value = u"value"}}}; autofill::FormData form = autofill::test::GetFormData(form_description); optimization_guide::proto::AXTreeUpdate ax_tree;
diff --git a/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_manager.cc b/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_manager.cc index e923a85..09f11c2 100644 --- a/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_manager.cc +++ b/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_manager.cc
@@ -36,6 +36,8 @@ namespace { +constexpr int kNumberFieldsToShowInSuggestionLabel = 2; + // Define `field_types_to_fill` as Autofill address types + // `IMPROVED_PREDICTION`. // TODO(crbug.com/364808228): Remove `UNKNOWN_TYPE` from `field_types_to_fill`. @@ -213,8 +215,6 @@ // Add a `kFillPredictionImprovements` suggestion with a separator to // `suggestion.children` before the field-by-field filling entries. { - // TODO(crbug.com/361434879): Add hardcoded string to an appropriate grd - // file. autofill::Suggestion fill_all_child( l10n_util::GetStringUTF16( IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_FILL_ALL_MAIN_TEXT), @@ -225,7 +225,13 @@ } // Add the child suggestion for the triggering field on top. suggestion.children.emplace_back(CreateChildSuggestionForFilling(prediction)); - // Then add child suggestions for all remaining, non-empty fields. + // Initialize as 1 because of the suggestion added above. + size_t n_fields_to_fill = 1; + // The label depends on the fields that will be filled. + std::u16string label = + l10n_util::GetStringUTF16( + IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_FILL_LABEL_TEXT) + + u" " + prediction.label; for (const auto& [child_field_global_id, child_prediction] : (*cache_)) { // Only add a child suggestion if the field is not the triggering field and // the value to fill is not empty. @@ -235,16 +241,34 @@ } suggestion.children.emplace_back( CreateChildSuggestionForFilling(child_prediction)); + ++n_fields_to_fill; + if (n_fields_to_fill == 2) { + label += l10n_util::GetStringUTF16( + IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_FILL_LABEL_SEPARATOR) + + child_prediction.label; + } } - if (!suggestion.children.empty()) { - suggestion.labels.emplace_back(); - // TODO(crbug.com/361434879): Add hardcoded string to an appropriate grd - // file. - suggestion.labels.back().emplace_back(u"& more"); - suggestion.children.emplace_back(autofill::SuggestionType::kSeparator); - suggestion.children.emplace_back( - CreateEditPredictionImprovementsInformation()); + + suggestion.children.emplace_back(autofill::SuggestionType::kSeparator); + suggestion.children.emplace_back( + CreateEditPredictionImprovementsInformation()); + + if (n_fields_to_fill > kNumberFieldsToShowInSuggestionLabel) { + // When more than `kNumberFieldsToShowInSuggestionLabel` are filled, include + // the "& More". + size_t number_of_more_fields_to_fill = + n_fields_to_fill - kNumberFieldsToShowInSuggestionLabel; + const std::u16string more_fields_label_substr = + number_of_more_fields_to_fill > 1 + ? l10n_util::GetStringFUTF16( + IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_FILL_SUGGESTION_AND_N_MORE_FIELDS, + base::NumberToString16(number_of_more_fields_to_fill)) + : l10n_util::GetStringUTF16( + IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_FILL_SUGGESTION_AND_ONE_MORE_FIELD); + label = base::StrCat({label, u" ", more_fields_label_substr}); } + suggestion.labels.emplace_back(); + suggestion.labels.back().emplace_back(label); // TODO(crbug.com/365512352): Figure out how to handle Undo suggestion. std::vector<autofill::Suggestion> filling_suggestions = {suggestion};
diff --git a/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_manager_unittest.cc b/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_manager_unittest.cc index 4d18f16..3c291858 100644 --- a/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_manager_unittest.cc +++ b/components/autofill_prediction_improvements/core/browser/autofill_prediction_improvements_manager_unittest.cc
@@ -509,6 +509,81 @@ HasType(SuggestionType::kPredictionImprovementsFeedback))); } +// Tests that the filling suggestion label is correct when only one field can be +// filled. +TEST_F( + AutofillPredictionImprovementsManagerTest, + FillingSuggestion_OneFieldCanBeFilled_CreateLabelThatContainsOnlyOneFieldData) { + autofill::test::FormDescription form_description = { + .fields = {{.role = autofill::NAME_FIRST, + .heuristic_type = autofill::NAME_FIRST}}}; + autofill::FormData form = autofill::test::GetFormData(form_description); + test_api(*manager_).SetCache(PredictionsByGlobalId{ + {form.fields()[0].global_id(), {u"Jane", u"First name"}}}); + + std::vector<Suggestion> suggestions_to_show; + EXPECT_TRUE( + manager_->MaybeUpdateSuggestions(suggestions_to_show, form.fields()[0], + /*should_add_trigger_suggestion=*/true)); + EXPECT_EQ(suggestions_to_show[0].labels[0][0].value, u"Fill First name"); +} + +// Tests that the filling suggestion label is correct when 3 fields can be +// filled. +TEST_F(AutofillPredictionImprovementsManagerTest, + FillingSuggestion_ThreeFieldsCanBeFilled_UserSingularAndMoreString) { + autofill::test::FormDescription form_description = { + .fields = {{.role = autofill::NAME_FIRST, + .heuristic_type = autofill::NAME_FIRST}, + {.role = autofill::ADDRESS_HOME_STREET_NAME, + .heuristic_type = autofill::ADDRESS_HOME_STREET_NAME}, + {.role = autofill::ADDRESS_HOME_STATE, + .heuristic_type = autofill::ADDRESS_HOME_STATE, + .form_control_type = autofill::FormControlType::kSelectOne}}}; + autofill::FormData form = autofill::test::GetFormData(form_description); + test_api(*manager_).SetCache(PredictionsByGlobalId{ + {form.fields()[0].global_id(), {u"Jane", u"First name"}}, + {form.fields()[1].global_id(), {u"Country roads str", u"Street name"}}, + {form.fields()[2].global_id(), {u"33", u"state", u"West Virginia"}}}); + + std::vector<Suggestion> suggestions_to_show; + EXPECT_TRUE( + manager_->MaybeUpdateSuggestions(suggestions_to_show, form.fields()[0], + /*should_add_trigger_suggestion=*/true)); + EXPECT_EQ(suggestions_to_show[0].labels[0][0].value, + u"Fill First name, Street name & 1 more field"); +} + +// Tests that the filling suggestion label is correct when more than 3 fields +// can be filled. +TEST_F( + AutofillPredictionImprovementsManagerTest, + FillingSuggestion_MoreThanThreeFieldsCanBeFilled_UserPluralAndMoreString) { + autofill::test::FormDescription form_description = { + .fields = { + {.role = autofill::NAME_FIRST, + .heuristic_type = autofill::NAME_FIRST}, + {.role = autofill::NAME_LAST, .heuristic_type = autofill::NAME_LAST}, + {.role = autofill::ADDRESS_HOME_STREET_NAME, + .heuristic_type = autofill::ADDRESS_HOME_STREET_NAME}, + {.role = autofill::ADDRESS_HOME_STATE, + .heuristic_type = autofill::ADDRESS_HOME_STATE, + .form_control_type = autofill::FormControlType::kSelectOne}}}; + autofill::FormData form = autofill::test::GetFormData(form_description); + test_api(*manager_).SetCache(PredictionsByGlobalId{ + {form.fields()[0].global_id(), {u"Jane", u"First name"}}, + {form.fields()[1].global_id(), {u"Doe", u"Last name"}}, + {form.fields()[2].global_id(), {u"Country roads str", u"Street name"}}, + {form.fields()[3].global_id(), {u"33", u"state", u"West Virginia"}}}); + + std::vector<Suggestion> suggestions_to_show; + EXPECT_TRUE( + manager_->MaybeUpdateSuggestions(suggestions_to_show, form.fields()[0], + /*should_add_trigger_suggestion=*/true)); + EXPECT_EQ(suggestions_to_show[0].labels[0][0].value, + u"Fill First name, Last name & 2 more fields"); +} + class AutofillPredictionImprovementsManagerUserFeedbackTest : public AutofillPredictionImprovementsManagerTest, public testing::WithParamInterface<
diff --git a/components/autofill_prediction_improvements_strings.grdp b/components/autofill_prediction_improvements_strings.grdp index 7e5eae2..05e52fe 100644 --- a/components/autofill_prediction_improvements_strings.grdp +++ b/components/autofill_prediction_improvements_strings.grdp
@@ -9,8 +9,17 @@ <message name="IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_FILL_ALL_MAIN_TEXT" desc="Suggestion shown when the user focuses a prediction improvements field." translateable="false"> Fill all </message> - <message name="IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_FILL_SUGGESTION_AND_MORE" desc="Text displayed as label to indicate more fields will be filled." translateable="false"> - & more + <message name="IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_FILL_LABEL_TEXT" desc="Text shown as a label when the user sees a prediction improvements suggestion." translateable="false"> + Fill + </message> + <message name="IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_FILL_LABEL_SEPARATOR" desc="The separator character used in the prediction improvements label." translateable="false"> + , ''' + </message> + <message name="IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_FILL_SUGGESTION_AND_ONE_MORE_FIELD" desc="Text displayed as label to indicate more fields will be filled." translateable="false"> + & 1 more field + </message> + <message name="IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_FILL_SUGGESTION_AND_N_MORE_FIELDS" desc="Text displayed as label to indicate more fields will be filled." translateable="false"> + & <ph name="N_FIELDS">$1<ex>4</ex></ph> more fields </message> <!-- Save prompt -->
diff --git a/components/browser_ui/media/android/java/src/org/chromium/components/browser_ui/media/MediaNotificationInfoTest.java b/components/browser_ui/media/android/java/src/org/chromium/components/browser_ui/media/MediaNotificationInfoTest.java index 70ba875a..bd7009d3 100644 --- a/components/browser_ui/media/android/java/src/org/chromium/components/browser_ui/media/MediaNotificationInfoTest.java +++ b/components/browser_ui/media/android/java/src/org/chromium/components/browser_ui/media/MediaNotificationInfoTest.java
@@ -90,7 +90,6 @@ assertNotNull(info); // Make sure hashCode() doesn't crash. - int hashValue = info.hashCode(); - assertNotNull(hashValue); + info.hashCode(); } }
diff --git a/components/browser_ui/widget/android/java/res/layout/title_and_description_layout.xml b/components/browser_ui/widget/android/java/res/layout/title_and_description_layout.xml index 0504a27..52d15a98 100644 --- a/components/browser_ui/widget/android/java/res/layout/title_and_description_layout.xml +++ b/components/browser_ui/widget/android/java/res/layout/title_and_description_layout.xml
@@ -5,79 +5,83 @@ found in the LICENSE file. --> -<LinearLayout +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_weight="1" - android:orientation="vertical" - android:layout_gravity="center_vertical" > + android:layout_weight="1" > - <LinearLayout - android:layout_width="match_parent" + <ImageView + android:id="@+id/before_title_icon" + android:layout_marginEnd="6dp" + android:layout_marginTop="4dp" + android:layout_marginBottom="2dp" + android:layout_width="16dp" + android:layout_height="16dp" + android:contentDescription="@null" + android:visibility="gone" + app:layout_constraintHorizontal_bias="0.0" + app:layout_constraintHorizontal_chainStyle="packed" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toStartOf="@+id/title" /> + + <TextView + android:id="@+id/title" + android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="start" - android:orientation="horizontal" - tools:ignore="UseCompoundDrawables" > + android:maxLines="1" + android:ellipsize="end" + android:textAppearance="@style/TextAppearance.TextLarge.Primary" + app:layout_constraintHorizontal_bias="0.0" + app:layout_constraintHorizontal_chainStyle="packed" + app:layout_constrainedWidth="true" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintStart_toEndOf="@+id/before_title_icon" + app:layout_constraintEnd_toStartOf="@+id/space_anchor" /> - <ImageView - android:id="@+id/icon" - android:layout_marginEnd="6dp" - android:layout_marginTop="4dp" - android:layout_marginBottom="2dp" - android:layout_width="16dp" - android:layout_height="16dp" - android:contentDescription="@null" - android:visibility="gone" /> + <!-- Anchor to ensure the chain terminates without any elements being pushed offscreen. --> + <Space + android:id="@+id/space_anchor" + android:layout_width="0dp" + android:layout_height="match_parent" + app:layout_constraintEnd_toEndOf="parent" /> - <TextView - android:id="@+id/title" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:maxLines="1" - android:ellipsize="end" - android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> - </LinearLayout> - - <androidx.constraintlayout.widget.ConstraintLayout - android:id="@+id/chip_description" - android:layout_width="match_parent" + <TextView + android:id="@+id/description" + android:layout_gravity="center_vertical|start" + android:layout_width="wrap_content" android:layout_height="wrap_content" - android:orientation="horizontal"> + android:maxLines="1" + android:ellipsize="end" + android:textAppearance="@style/TextAppearance.TextMedium.Secondary" + app:layout_constraintHorizontal_bias="0.0" + app:layout_constraintHorizontal_chainStyle="packed" + app:layout_constraintTop_toBottomOf="@+id/title" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toStartOf="@+id/chip" /> - <TextView - android:id="@+id/description" - android:layout_gravity="center_vertical|start" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:maxLines="1" - android:ellipsize="end" - android:textAppearance="@style/TextAppearance.TextMedium.Secondary" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" /> - - <!-- An optional chip view. Used for history.TODO(b/331856225): Consider adding min_width - to prevent the description view from occupying the whole space. --> - <org.chromium.components.browser_ui.widget.chips.ChipView - android:id="@+id/chip" - android:layout_gravity="center_vertical|start" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginStart="8dp" - android:visibility="gone" - app:layout_constrainedWidth="true" - app:layout_constraintBottom_toBottomOf="@+id/description" - app:layout_constraintStart_toEndOf="@+id/description" - app:layout_constraintTop_toTopOf="@+id/description" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_bias="0" - style="@style/HistoryAppChip" /> - </androidx.constraintlayout.widget.ConstraintLayout> + <!-- An optional chip view. Used for history. --> + <org.chromium.components.browser_ui.widget.chips.ChipView + android:id="@+id/chip" + android:layout_gravity="center_vertical|start" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:visibility="gone" + app:layout_constrainedWidth="true" + app:layout_constraintTop_toTopOf="@+id/description" + app:layout_constraintBottom_toBottomOf="@+id/description" + app:layout_constraintStart_toEndOf="@+id/description" + app:layout_constraintEnd_toStartOf="@+id/space_anchor" + style="@style/HistoryAppChip" /> <FrameLayout android:id="@+id/custom_content_container" android:layout_width="wrap_content" - android:layout_height="wrap_content" /> -</LinearLayout> + android:layout_height="wrap_content" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/description" /> +</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableItemViewBaseTest.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableItemViewBaseTest.java index e28bdd80..89cc040b2 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableItemViewBaseTest.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableItemViewBaseTest.java
@@ -61,7 +61,7 @@ SelectionDelegate<Integer> selectionDelegate = new SelectionDelegate<>(); mSelectableItemViewBase.setSelectionDelegate(selectionDelegate); - Integer item = new Integer(1); + Integer item = 1; assertNull(mSelectableItemViewBase.getItem()); mSelectableItemViewBase.setItem(item); assertEquals(item, mSelectableItemViewBase.getItem()); @@ -87,7 +87,7 @@ @Test public void testSelection_NullDelegate() { - Integer item = new Integer(1); + Integer item = 1; assertNull(mSelectableItemViewBase.getItem()); mSelectableItemViewBase.setItem(item); assertNull(mSelectableItemViewBase.getItem());
diff --git a/components/cronet/android/api/src/org/chromium/net/apihelpers/ContentTypeParametersParser.java b/components/cronet/android/api/src/org/chromium/net/apihelpers/ContentTypeParametersParser.java index 3394c465..d3a56a9 100644 --- a/components/cronet/android/api/src/org/chromium/net/apihelpers/ContentTypeParametersParser.java +++ b/components/cronet/android/api/src/org/chromium/net/apihelpers/ContentTypeParametersParser.java
@@ -172,7 +172,7 @@ } private static boolean isAscii(char ch) { - return (char) 0 <= ch && ch <= (char) 127; + return ch <= 127; } private static boolean isWhitespace(char c) {
diff --git a/components/cronet/android/sample/javatests/src/org/chromium/cronet_sample_apk/CronetSampleTest.java b/components/cronet/android/sample/javatests/src/org/chromium/cronet_sample_apk/CronetSampleTest.java index 8090371..1af4c5a 100644 --- a/components/cronet/android/sample/javatests/src/org/chromium/cronet_sample_apk/CronetSampleTest.java +++ b/components/cronet/android/sample/javatests/src/org/chromium/cronet_sample_apk/CronetSampleTest.java
@@ -18,6 +18,6 @@ @Test @SmallTest public void testSimple() throws Exception { - assertThat(1).isEqualTo(1); + assertThat(1 + 1).isEqualTo(2); } }
diff --git a/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/Options.java b/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/Options.java index 74c77bc..09d0176 100644 --- a/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/Options.java +++ b/components/cronet/android/sample/src/org/chromium/cronet_sample_apk/Options.java
@@ -14,29 +14,34 @@ import java.util.Map; /** - * Adding an option here will make it show up in the list of available options. - * Each {@link Option} has the following attributes: + * Adding an option here will make it show up in the list of available options. Each {@link Option} + * has the following attributes: + * * <ul> - * <li>A short name which appears in bold on the options list.</li> - * <li>A description which provides a thorough explanation of what this option does.</li> - * <li>An {@link Action} which is applied on CronetEngine's Builder each time the user hits "Reset - * Engine". </li> <li>A default value, every option must have a default value.</li> + * <li>A short name which appears in bold on the options list. + * <li>A description which provides a thorough explanation of what this option does. + * <li>An {@link Action} which is applied on CronetEngine's Builder each time the user hits "Reset + * Engine". + * <li>A default value, every option must have a default value. * </ul> + * * <b>NOTE</b>: Each option must map to one {@link OptionsIdentifier OptionsIdentifier}. This is * necessary to provide custom implementation for options that does not configure the builders. See * {@link OptionsIdentifier#SLOW_DOWNLOAD} as an example. * - * <p> To add a new option, do the following: + * <p>To add a new option, do the following: + * * <ol> - * <li> Add a new optionIdentifier {@link OptionsIdentifier} </li> - * <li> Inject a new Option instance into your optionIdentifier enum value. </li> - * <li> Implement the logic for the new option within a new {@link Action}. </li> - * <li> If the {@link Action} interface is not enough to satisfy the use-case. Feel free to add - * custom logic, See {@link OptionsIdentifier#SLOW_DOWNLOAD} as an example.</li> - * <li> Restart the APK and verify that your option is working as intended. </li> + * <li>Add a new optionIdentifier {@link OptionsIdentifier} + * <li>Inject a new Option instance into your optionIdentifier enum value. + * <li>Implement the logic for the new option within a new {@link Action}. + * <li>If the {@link Action} interface is not enough to satisfy the use-case. Feel free to add + * custom logic, See {@link OptionsIdentifier#SLOW_DOWNLOAD} as an example. + * <li>Restart the APK and verify that your option is working as intended. * </ol> */ public class Options { + @SuppressWarnings("ImmutableEnumChecker") public enum OptionsIdentifier { MIGRATE_SESSIONS_ON_NETWORK_CHANGE_V2( new BooleanOption( @@ -57,9 +62,9 @@ new BooleanOption( "migrate_sessions_early_v2", "Enable QUIC early session migration. This will make quic send probing" - + " packets when the network is degrading, QUIC will migrate the " - + "sessions to a different network even before the original network " - + "has disconnected.", + + " packets when the network is degrading, QUIC will migrate the" + + " sessions to a different network even before the original network" + + " has disconnected.", new Action<Boolean>() { @Override @OptIn(markerClass = ConnectionMigrationOptions.Experimental.class) @@ -72,7 +77,8 @@ SLOW_DOWNLOAD( new BooleanOption( "Slow Download (10s)", - "Hang the onReadCompleted for 10s before proceeding. This should simulate slow connection.", + "Hang the onReadCompleted for 10s before proceeding. This should simulate" + + " slow connection.", new Action<>() {}, false));
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java index b1c75f7..240d8a3 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestRule.java
@@ -678,6 +678,8 @@ ExperimentalCronetEngine.Builder getCronetEngineBuilder(Context context); } + // Warning should go away once we can use java.util.function.Function. + @SuppressWarnings("ImmutableEnumChecker") public enum CronetImplementation { STATICALLY_LINKED( context ->
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java index 92bd66a..914c621 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java
@@ -1813,17 +1813,11 @@ String url = NativeTestServer.getFileURL("/cacheable.txt"); // When cache is disabled, making a request does not write to the cache. - checkRequestCaching( - cronetEngine, url, false, true - /** disable cache */ - ); + checkRequestCaching(cronetEngine, url, false, true); checkRequestCaching(cronetEngine, url, false); // When cache is enabled, the second request is cached. - checkRequestCaching( - cronetEngine, url, false, true - /** disable cache */ - ); + checkRequestCaching(cronetEngine, url, false, true); checkRequestCaching(cronetEngine, url, true); // Shut down the server, next request should have a cached response.
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestTest.java index dc544afd..9bde7eb 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestTest.java
@@ -2875,12 +2875,12 @@ } } - @Test - @SmallTest /** * Open many connections and cancel them right away. This test verifies all internal sockets and * other Closeables are properly closed. See crbug.com/726193. */ + @Test + @SmallTest public void testGzipCancel() throws Exception { String url = NativeTestServer.getFileURL("/gzipped.html"); for (int i = 0; i < 100; i++) { @@ -2912,10 +2912,10 @@ } } + /** Do a HEAD request and get back a 404. */ @Test @SmallTest @RequiresMinApi(8) // JavaUrlRequest fixed in API level 8: crrev.com/499303 - /** Do a HEAD request and get back a 404. */ public void test404Head() throws Exception { TestUrlRequestCallback callback = new TestUrlRequestCallback(); UrlRequest.Builder builder = @@ -2997,12 +2997,12 @@ assertThat(CronetTestUtil.nativeGetTaggedBytes(tag)).isGreaterThan(priorBytes); } - @Test - @SmallTest /** * Initiate many requests concurrently to make sure neither Cronet implementation crashes. * Regression test for https://crbug.com/844031. */ + @Test + @SmallTest public void testManyRequests() throws Exception { String url = NativeTestServer.getMultiRedirectURL(); final int numRequests = 2000;
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/TestUrlRequestCallback.java b/components/cronet/android/test/javatests/src/org/chromium/net/TestUrlRequestCallback.java index 4191b21..11e51d43 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/TestUrlRequestCallback.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/TestUrlRequestCallback.java
@@ -198,7 +198,7 @@ // Termination shouldn't take long. Use 1 min which should be more than enough. mExecutorService.awaitTermination(1, TimeUnit.MINUTES); } catch (InterruptedException e) { - fail("ExecutorService is interrupted while waiting for termination"); + throw new RuntimeException(e); } assertThat(mExecutorService.isTerminated()).isTrue(); }
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandlerTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandlerTest.java index 1fd392d..75e19256 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandlerTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandlerTest.java
@@ -88,6 +88,7 @@ @Test @SmallTest + @SuppressWarnings("AddressSelection") public void testOpenConnectionWithProxy() throws Exception { URL url = new URL(NativeTestServer.getEchoMethodURL()); CronetHttpURLStreamHandler streamHandler =
diff --git a/components/embedder_support/android/native_java_unittests/src/org/chromium/components/embedder_support/util/InputStreamUnittest.java b/components/embedder_support/android/native_java_unittests/src/org/chromium/components/embedder_support/util/InputStreamUnittest.java index f1863018..1f1352cd 100644 --- a/components/embedder_support/android/native_java_unittests/src/org/chromium/components/embedder_support/util/InputStreamUnittest.java +++ b/components/embedder_support/android/native_java_unittests/src/org/chromium/components/embedder_support/util/InputStreamUnittest.java
@@ -9,6 +9,7 @@ import java.io.IOException; import java.io.InputStream; +@SuppressWarnings("InputStreamSlowMultibyteRead") class InputStreamUnittest { private InputStreamUnittest() {}
diff --git a/components/facilitated_payments/core/browser/facilitated_payments_manager.cc b/components/facilitated_payments/core/browser/facilitated_payments_manager.cc index f810f95..aa71cc4 100644 --- a/components/facilitated_payments/core/browser/facilitated_payments_manager.cc +++ b/components/facilitated_payments/core/browser/facilitated_payments_manager.cc
@@ -60,11 +60,7 @@ ukm_source_id_ = ukm_source_id; trigger_source_ = TriggerSource::kCopyEvent; // Check whether the domain for the render_frame_host_url is allowlisted. - auto decision = optimization_guide_decider_->CanApplyOptimization( - render_frame_host_url, - optimization_guide::proto::PIX_MERCHANT_ORIGINS_ALLOWLIST, - /*optimization_metadata=*/nullptr); - if (decision != optimization_guide::OptimizationGuideDecision::kTrue) { + if (!IsMerchantAllowlisted(render_frame_host_url)) { // The merchant is not part of the allowlist, ignore the copy event. return; } @@ -79,21 +75,20 @@ void FacilitatedPaymentsManager::RegisterPixAllowlist() const { optimization_guide_decider_->RegisterOptimizationTypes( - {optimization_guide::proto::PIX_PAYMENT_MERCHANT_ALLOWLIST, - optimization_guide::proto::PIX_MERCHANT_ORIGINS_ALLOWLIST}); + {optimization_guide::proto::PIX_MERCHANT_ORIGINS_ALLOWLIST}); } -optimization_guide::OptimizationGuideDecision -FacilitatedPaymentsManager::GetAllowlistCheckResult(const GURL& url) const { +bool FacilitatedPaymentsManager::IsMerchantAllowlisted(const GURL& url) const { // Since the optimization guide decider integration corresponding to PIX // merchant lists are allowlists for the question "Can this site be // optimized?", a match on the allowlist answers the question with "yes". - // Therefore, `kTrue` indicates that `url` is allowed for running PIX code - // detection. If the optimization type was not registered in time when we + // Therefore, `kTrue` indicates that `url` is allowed for detecting PIX code + // on copy events. If the optimization type was not registered in time when we // queried it, it will be `kUnknown`. return optimization_guide_decider_->CanApplyOptimization( - url, optimization_guide::proto::PIX_PAYMENT_MERCHANT_ALLOWLIST, - /*optimization_metadata=*/nullptr); + url, optimization_guide::proto::PIX_MERCHANT_ORIGINS_ALLOWLIST, + /*optimization_metadata=*/nullptr) == + optimization_guide::OptimizationGuideDecision::kTrue; } void FacilitatedPaymentsManager::OnPixCodeValidated(
diff --git a/components/facilitated_payments/core/browser/facilitated_payments_manager.h b/components/facilitated_payments/core/browser/facilitated_payments_manager.h index 7c70c47..2bbbc3e 100644 --- a/components/facilitated_payments/core/browser/facilitated_payments_manager.h +++ b/components/facilitated_payments/core/browser/facilitated_payments_manager.h
@@ -223,8 +223,8 @@ // 1. In the allowlist // 2. Not in the allowlist // 3. Infra for querying is not ready - optimization_guide::OptimizationGuideDecision GetAllowlistCheckResult( - const GURL& url) const; + // Returns true if the result is [1]. + bool IsMerchantAllowlisted(const GURL& url) const; // Called by the utility process after validation of the `pix_code`. If the // utility processes has disconnected (e.g., due to a crash in the validation
diff --git a/components/facilitated_payments/core/browser/facilitated_payments_manager_unittest.cc b/components/facilitated_payments/core/browser/facilitated_payments_manager_unittest.cc index c1e382a..dc0f365 100644 --- a/components/facilitated_payments/core/browser/facilitated_payments_manager_unittest.cc +++ b/components/facilitated_payments/core/browser/facilitated_payments_manager_unittest.cc
@@ -242,7 +242,6 @@ TEST_F(FacilitatedPaymentsManagerTest, RegisterPixAllowlist) { EXPECT_CALL(*optimization_guide_decider_, RegisterOptimizationTypes(testing::ElementsAre( - optimization_guide::proto::PIX_PAYMENT_MERCHANT_ALLOWLIST, optimization_guide::proto::PIX_MERCHANT_ORIGINS_ALLOWLIST))) .Times(1);
diff --git a/components/ip_protection/common/ip_protection_token_manager_impl.cc b/components/ip_protection/common/ip_protection_token_manager_impl.cc index 8823367..389fadf 100644 --- a/components/ip_protection/common/ip_protection_token_manager_impl.cc +++ b/components/ip_protection/common/ip_protection_token_manager_impl.cc
@@ -262,7 +262,9 @@ return; } - VLOG(2) << "IPPATC::OnGotAuthTokens got " << tokens->size() << " tokens"; + VLOG(2) << "IPPATC::OnGotAuthTokens got " << tokens->size() + << " tokens for proxy " + << int(proxy_layer_); try_get_auth_tokens_after_ = base::Time(); RemoveExpiredTokens();
diff --git a/components/module_installer/android/junit/src/org/chromium/components/module_installer/engine/SplitCompatEngineTest.java b/components/module_installer/android/junit/src/org/chromium/components/module_installer/engine/SplitCompatEngineTest.java index d168f62..ece61a8 100644 --- a/components/module_installer/android/junit/src/org/chromium/components/module_installer/engine/SplitCompatEngineTest.java +++ b/components/module_installer/android/junit/src/org/chromium/components/module_installer/engine/SplitCompatEngineTest.java
@@ -86,12 +86,8 @@ // Arrange. String installedModule = "m1"; String uninstalledModule = "m2"; - Set<String> installedModules = - new HashSet<String>() { - { - add(installedModule); - } - }; + Set<String> installedModules = new HashSet<String>(); + installedModules.add(installedModule); doReturn(installedModules).when(mManager).getInstalledModules(); // Act & Assert.
diff --git a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteMatch.java b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteMatch.java index d53b337..e8b4249 100644 --- a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteMatch.java +++ b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteMatch.java
@@ -509,6 +509,7 @@ } @Override + @SuppressWarnings("LiteProtoToString") public String toString() { List<String> pieces = Arrays.asList(
diff --git a/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java b/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java index 76cc7d0..14543ea 100644 --- a/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java +++ b/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java
@@ -341,9 +341,7 @@ // we should have only one column. Bitmap[][] bitmapMatrix = mModel.get(PlayerFrameProperties.BITMAP_MATRIX); Assert.assertTrue(Arrays.deepEquals(bitmapMatrix, new Bitmap[4][1])); - Assert.assertEquals( - new ArrayList<Pair<View, Rect>>(), - mModel.get(PlayerFrameProperties.SUBFRAME_VIEWS)); + Assert.assertEquals(List.of(), mModel.get(PlayerFrameProperties.SUBFRAME_VIEWS)); } /**
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/JniPaymentApp.java b/components/payments/content/android/java/src/org/chromium/components/payments/JniPaymentApp.java index 0bb4fd1..176e0bd5 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/JniPaymentApp.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/JniPaymentApp.java
@@ -235,6 +235,8 @@ mNativeObject = 0; } + // TODO(crbug.com/40286193): Use an explicit destroy() method. + @SuppressWarnings("Finalize") @Override public void finalize() throws Throwable { dismissInstrument();
diff --git a/components/performance_manager/public/scenarios/loading_scenario_observer.h b/components/performance_manager/public/scenarios/loading_scenario_observer.h index cd61194..b68eef62 100644 --- a/components/performance_manager/public/scenarios/loading_scenario_observer.h +++ b/components/performance_manager/public/scenarios/loading_scenario_observer.h
@@ -5,7 +5,6 @@ #ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_SCENARIOS_LOADING_SCENARIO_OBSERVER_H_ #define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_SCENARIOS_LOADING_SCENARIO_OBSERVER_H_ -#include "base/numerics/clamped_math.h" #include "base/sequence_checker.h" #include "components/performance_manager/public/graph/graph.h" #include "components/performance_manager/public/graph/page_node.h" @@ -40,9 +39,9 @@ LoadingScenario GetScenario() const; private: - base::ClampedNumeric<size_t> focused_loading_pages_; - base::ClampedNumeric<size_t> visible_loading_pages_; - base::ClampedNumeric<size_t> loading_pages_; + size_t focused_loading_pages_ = 0; + size_t visible_loading_pages_ = 0; + size_t loading_pages_ = 0; }; LoadingScenarioObserver() = default;
diff --git a/components/performance_manager/scenarios/loading_scenario_observer.cc b/components/performance_manager/scenarios/loading_scenario_observer.cc index af68b40..ea734a2 100644 --- a/components/performance_manager/scenarios/loading_scenario_observer.cc +++ b/components/performance_manager/scenarios/loading_scenario_observer.cc
@@ -8,6 +8,7 @@ #include "base/check_op.h" #include "base/notreached.h" +#include "base/numerics/checked_math.h" #include "base/sequence_checker.h" #include "components/performance_manager/public/graph/graph.h" #include "components/performance_manager/public/graph/page_node.h" @@ -31,6 +32,16 @@ NOTREACHED(); } +// Increments `num` in-place, and CHECK's on overflow. +void CheckIncrement(size_t& num) { + num = base::CheckAdd(num, 1).ValueOrDie(); +} + +// Decrements `num` in-place, and CHECK's on underflow. +void CheckDecrement(size_t& num) { + num = base::CheckSub(num, 1).ValueOrDie(); +} + } // namespace LoadingScenario LoadingScenarioObserver::LoadingCounts::GetScenario() const { @@ -49,27 +60,24 @@ void LoadingScenarioObserver::LoadingCounts::IncrementLoadingPageCounts( bool visible, bool focused) { - loading_pages_++; + CheckIncrement(loading_pages_); if (visible) { - visible_loading_pages_++; + CheckIncrement(visible_loading_pages_); } if (focused) { - focused_loading_pages_++; + CheckIncrement(focused_loading_pages_); } } void LoadingScenarioObserver::LoadingCounts::DecrementLoadingPageCounts( bool visible, bool focused) { - CHECK_GT(loading_pages_.RawValue(), 0u); - loading_pages_--; + CheckDecrement(loading_pages_); if (visible) { - CHECK_GT(visible_loading_pages_.RawValue(), 0u); - visible_loading_pages_--; + CheckDecrement(visible_loading_pages_); } if (focused) { - CHECK_GT(focused_loading_pages_.RawValue(), 0u); - focused_loading_pages_--; + CheckDecrement(focused_loading_pages_); } }
diff --git a/components/privacy_sandbox/privacy_sandbox_features.cc b/components/privacy_sandbox/privacy_sandbox_features.cc index fdfe248..44f7ad8 100644 --- a/components/privacy_sandbox/privacy_sandbox_features.cc +++ b/components/privacy_sandbox/privacy_sandbox_features.cc
@@ -148,7 +148,7 @@ BASE_FEATURE(kTrackingProtection3pcdUx, "TrackingProtection3pcdUx", - base::FEATURE_ENABLED_BY_DEFAULT); + base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kFingerprintingProtectionUserBypass, "FingerprintingProtectionUserBypass",
diff --git a/components/resources/OWNERS b/components/resources/OWNERS index cff876a..ec153ba 100644 --- a/components/resources/OWNERS +++ b/components/resources/OWNERS
@@ -13,7 +13,7 @@ per-file offline_pages_resources.grdp=file://components/offline_pages/OWNERS per-file policy_resources.grdp=file://components/policy/OWNERS per-file printing_resources.grdp=file://printing/OWNERS -per-file search_engine_choice_scaled_resources.grdp=file://components/search_engines/search_engine_choice/OWNERS +per-file search_engine_choice_scaled_resources.grdp=file://components/search_engines/search_engine_choice/COMPLIANCE_OWNERS per-file security_interstitials_dev_ui_resources.grdp=file://components/security_interstitials/OWNERS per-file security_interstitials_resources.grdp=file://components/security_interstitials/OWNERS per-file sync_driver_resources.grdp=file://components/sync/OWNERS
diff --git a/components/resources/default_100_percent/search_engine_choice/OWNERS b/components/resources/default_100_percent/search_engine_choice/OWNERS index a8ff91d..c7aa42b 100644 --- a/components/resources/default_100_percent/search_engine_choice/OWNERS +++ b/components/resources/default_100_percent/search_engine_choice/OWNERS
@@ -1 +1 @@ -file://components/search_engines/search_engine_choice/OWNERS +file://components/search_engines/search_engine_choice/COMPLIANCE_OWNERS
diff --git a/components/resources/default_200_percent/search_engine_choice/OWNERS b/components/resources/default_200_percent/search_engine_choice/OWNERS index a8ff91d..c7aa42b 100644 --- a/components/resources/default_200_percent/search_engine_choice/OWNERS +++ b/components/resources/default_200_percent/search_engine_choice/OWNERS
@@ -1 +1 @@ -file://components/search_engines/search_engine_choice/OWNERS +file://components/search_engines/search_engine_choice/COMPLIANCE_OWNERS
diff --git a/components/resources/default_300_percent/search_engine_choice/OWNERS b/components/resources/default_300_percent/search_engine_choice/OWNERS index a8ff91d..c7aa42b 100644 --- a/components/resources/default_300_percent/search_engine_choice/OWNERS +++ b/components/resources/default_300_percent/search_engine_choice/OWNERS
@@ -1 +1 @@ -file://components/search_engines/search_engine_choice/OWNERS +file://components/search_engines/search_engine_choice/COMPLIANCE_OWNERS
diff --git a/components/safe_browsing/android/remote_database_manager.cc b/components/safe_browsing/android/remote_database_manager.cc index 525753a..ddb40db 100644 --- a/components/safe_browsing/android/remote_database_manager.cc +++ b/components/safe_browsing/android/remote_database_manager.cc
@@ -55,83 +55,40 @@ // class RemoteSafeBrowsingDatabaseManager::ClientRequest { public: - enum class CallbackType { - BROWSE_URL, - DOWNLOAD_URL, - }; - ClientRequest(Client* client, - CallbackType callback_type, RemoteSafeBrowsingDatabaseManager* db_manager, - const std::vector<GURL>& urls); + const GURL& url); + void OnRequestDone(SBThreatType matched_threat_type, const ThreatMetadata& metadata); - void AddPendingCheck(); // Accessors Client* client() const { return client_; } - const std::vector<GURL>& urls() const { return urls_; } - size_t pending_checks() const { return pending_checks_; } + const GURL& url() const { return url_; } base::WeakPtr<ClientRequest> GetWeakPtr() { return weak_factory_.GetWeakPtr(); } private: - void CompleteCheck(); - raw_ptr<Client, DanglingUntriaged> client_; - CallbackType callback_type_; raw_ptr<RemoteSafeBrowsingDatabaseManager, DanglingUntriaged> db_manager_; - std::vector<GURL> urls_; - size_t pending_checks_ = 0; - SBThreatType most_severe_threat_type_ = SBThreatType::SB_THREAT_TYPE_SAFE; - ThreatMetadata most_severe_metadata_; + GURL url_; base::ElapsedTimer timer_; base::WeakPtrFactory<ClientRequest> weak_factory_{this}; }; RemoteSafeBrowsingDatabaseManager::ClientRequest::ClientRequest( Client* client, - CallbackType callback_type, RemoteSafeBrowsingDatabaseManager* db_manager, - const std::vector<GURL>& urls) - : client_(client), - callback_type_(callback_type), - db_manager_(db_manager), - urls_(urls) {} + const GURL& url) + : client_(client), db_manager_(db_manager), url_(url) {} void RemoteSafeBrowsingDatabaseManager::ClientRequest::OnRequestDone( SBThreatType matched_threat_type, const ThreatMetadata& metadata) { DVLOG(1) << "OnRequestDone took " << timer_.Elapsed().InMilliseconds() - << " ms for client " << client_; - - if (most_severe_threat_type_ == SBThreatType::SB_THREAT_TYPE_SAFE) { - most_severe_threat_type_ = matched_threat_type; - most_severe_metadata_ = metadata; - } - - --pending_checks_; - - if (pending_checks_ == 0) { - CompleteCheck(); - } -} - -void RemoteSafeBrowsingDatabaseManager::ClientRequest::AddPendingCheck() { - ++pending_checks_; -} - -void RemoteSafeBrowsingDatabaseManager::ClientRequest::CompleteCheck() { - switch (callback_type_) { - case CallbackType::BROWSE_URL: - client_->OnCheckBrowseUrlResult(urls_[0], most_severe_threat_type_, - most_severe_metadata_); - break; - case CallbackType::DOWNLOAD_URL: - client_->OnCheckDownloadUrlResult(urls_, most_severe_threat_type_); - break; - } + << " ms for client " << client_ << " and URL " << url_; + client_->OnCheckBrowseUrlResult(url_, matched_threat_type, metadata); UMA_HISTOGRAM_TIMES("SB2.RemoteCall.Elapsed", timer_.Elapsed()); // CancelCheck() will delete *this. db_manager_->CancelCheck(client_); @@ -155,6 +112,7 @@ for (auto itr = current_requests_.begin(); itr != current_requests_.end(); ++itr) { if ((*itr)->client() == client) { + DVLOG(2) << "Canceling check for URL " << (*itr)->url(); current_requests_.erase(itr); return; } @@ -184,14 +142,11 @@ return true; // Safe, continue right away. } - auto req = std::make_unique<ClientRequest>( - client, ClientRequest::CallbackType::BROWSE_URL, this, - std::vector<GURL>{url}); + auto req = std::make_unique<ClientRequest>(client, this, url); DVLOG(1) << "Checking for client " << client << " and URL " << url; - SafeBrowsingApiHandlerBridge::ResponseCallback callback = + auto callback = base::BindOnce(&ClientRequest::OnRequestDone, req->GetWeakPtr()); - req->AddPendingCheck(); switch (check_type) { case CheckBrowseUrlType::kHashDatabase: SafeBrowsingApiHandlerBridge::GetInstance().StartHashDatabaseUrlCheck( @@ -210,45 +165,8 @@ bool RemoteSafeBrowsingDatabaseManager::CheckDownloadUrl( const std::vector<GURL>& url_chain, Client* client) { - DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); - - if (!enabled_) { - return true; - } - - auto req = std::make_unique<ClientRequest>( - client, ClientRequest::CallbackType::DOWNLOAD_URL, this, url_chain); - - // Must add pending checks in a separate loop so that synchronous responses - // from the SafeBrowsingApiHandlerBridge can't complete the check early. - for (const GURL& url : url_chain) { - if (!CanCheckUrl(url)) { - continue; - } - req->AddPendingCheck(); - } - - if (req->pending_checks() == 0) { - return true; - } - - for (const GURL& url : url_chain) { - if (!CanCheckUrl(url)) { - continue; - } - DVLOG(1) << "Checking for client " << client << " and URL " << url; - auto callback = SafeBrowsingApiHandlerBridge::ResponseCallback( - base::BindOnce(&ClientRequest::OnRequestDone, req->GetWeakPtr())); - SafeBrowsingApiHandlerBridge::GetInstance().StartHashDatabaseUrlCheck( - std::move(callback), url, - CreateSBThreatTypeSet({SBThreatType::SB_THREAT_TYPE_URL_MALWARE, - SBThreatType::SB_THREAT_TYPE_URL_UNWANTED})); - } - - current_requests_.push_back(std::move(req)); - - // Defer the resource load. - return false; + NOTREACHED_IN_MIGRATION(); + return true; } bool RemoteSafeBrowsingDatabaseManager::CheckExtensionIDs( @@ -291,14 +209,11 @@ return true; } - auto req = std::make_unique<ClientRequest>( - client, ClientRequest::CallbackType::BROWSE_URL, this,