diff --git a/AUTHORS b/AUTHORS index 5206baf..9ae03a5 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -437,6 +437,7 @@ Hari Singh <hari.singh1@samsung.com> Harpreet Singh Khurana <harpreet.sk@samsung.com> Harshikesh Kumar <harshikeshnobug@gmail.com> +Harshit Pal <harshitp12345@gmail.com> Hassan Salehe Matar <hassansalehe@gmail.com> Hautio Kari <khautio@gmail.com> Heejin R. Chung <heejin.r.chung@samsung.com>
diff --git a/BUILD.gn b/BUILD.gn index 02596c90..23ea3bc 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -179,7 +179,7 @@ if (!is_ios) { deps += [ - ":chromedriver", + ":chromedriver_group", "//cc:cc_unittests", "//components:components_browsertests", "//components/policy:policy_templates", @@ -1068,7 +1068,7 @@ } if (!is_ios) { - group("chromedriver") { + group("chromedriver_group") { testonly = true if (is_fuchsia || is_android) { @@ -1091,6 +1091,12 @@ } } + # TODO(chromium:1382224): Remove this target as soon as all the builders have switched to :chromedriver_group + group("chromedriver") { + testonly = true + deps = [ ":chromedriver_group" ] + } + # This group includes all of the targets needed to build and test Blink, # including running web tests (see below). This target is defined here because # previously //third_party/WebKit, now //third_party/blink, couldn't depend on
diff --git a/DEPS b/DEPS index 1c1e6f0a..3095d9c0 100644 --- a/DEPS +++ b/DEPS
@@ -306,7 +306,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '9d56e506b4df8a75b559aa9d25ecdb7db88ca8a0', + 'skia_revision': '8e2ed1e3d1b9dd47f668535bd5ad98f3a11795b1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -314,7 +314,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': '386ef2eefe63af50162ef61ce2f5c00e6bde7b66', + 'angle_revision': 'ec42459200373e4fed77933f67b098ba45290f47', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -385,7 +385,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': 'c73fe21a0ec8ff28fd24c584fcb001571a2ca025', + 'devtools_frontend_revision': 'fecd73d233db03c980e6c1b3af7dc4d28f6cd8b9', # 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. @@ -421,7 +421,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': '9f2829f4718e3b7742aa6795df78491e20f7ffab', + 'dawn_revision': 'aedda6a50076c7747e66954a1b55bc0776615d17', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -816,7 +816,7 @@ 'src/clank': { 'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' + - 'c07fc321ae7f5f3a285f568fb1f0b2d6a4db99ff', + 'f1c755b7ba172daac62f1f1266fae32aff2c22d1', 'condition': 'checkout_android and checkout_src_internal and not checkout_clank_via_src_internal', }, @@ -1249,7 +1249,7 @@ Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '85429b8992a921c63c2bae4de22c81737d12ad3a', + 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'b899c39111bf4837c800da8c81c2d2f2ef95c1be', 'condition': 'checkout_src_internal', }, @@ -1664,7 +1664,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '6f7678ba37a925e02df652a13c50be9daaeb484e', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '6c5c80b3c694219abfaa0a1fe814522e70c0dc65', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1849,7 +1849,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'fa3aad630e1a992808c28986bb6b24cadd6d1c15', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '408f0be5c23024a4b88f80b7707f570cd53ca6a6', + Var('webrtc_git') + '/src.git' + '@' + '76793c300fdd87fa8fd8be3dd2e5faf8c1916e96', # 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. @@ -1919,7 +1919,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a17c545b26c0974baa4603d45a63377f0530b53d', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@11b1d9bac3891adcdbbcf2e479dc2a47c546b6e6', 'condition': 'checkout_src_internal', }, @@ -1971,7 +1971,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/projector_app/app', - 'version': '1W6l_EV9c96k_haPLjYQYFoEuoLiwiYqGdKCU9D4-BsC', + 'version': '4xnC6TU1wpoJID-muq1szP_W5mRqh6iPyQIXxkQ2D1cC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/webui/camera_app_ui/resources/js/device/camera_manager.ts b/ash/webui/camera_app_ui/resources/js/device/camera_manager.ts index 7ba1f31..2c1e864 100644 --- a/ash/webui/camera_app_ui/resources/js/device/camera_manager.ts +++ b/ash/webui/camera_app_ui/resources/js/device/camera_manager.ts
@@ -479,9 +479,12 @@ async startCapture(): Promise<[Promise<void>]> { this.setCameraAvailable(false); - const captureDone = await this.scheduler.startCapture(); - this.setCameraAvailable(true); - return assertExists(captureDone); + try { + const captureDone = await this.scheduler.startCapture(); + return assertExists(captureDone); + } finally { + this.setCameraAvailable(true); + } } stopCapture(): void {
diff --git a/ash/wm/window_cycle/window_cycle_controller_unittest.cc b/ash/wm/window_cycle/window_cycle_controller_unittest.cc index a63a7cb..23e5427b 100644 --- a/ash/wm/window_cycle/window_cycle_controller_unittest.cc +++ b/ash/wm/window_cycle/window_cycle_controller_unittest.cc
@@ -75,6 +75,7 @@ #include "ui/events/test/event_generator.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/vector2d.h" +#include "ui/views/accessibility/accessibility_paint_checks.h" namespace ash { @@ -179,6 +180,12 @@ return cycle_view()->mirror_container_->children(); } + const views::View* GetTabSliderActiveButtonSelector() const { + if (auto* tab_slider_container = cycle_view()->tab_slider_container_) + return tab_slider_container->active_button_selector_; + return nullptr; + } + const views::View::Views& GetTabSliderButtons() const { auto* tab_slider_container = cycle_view()->tab_slider_container_; if (!tab_slider_container) { @@ -236,6 +243,11 @@ return WindowCycleListTestApi(GetCycleList()).GetTabSliderButtons(); } + const views::View* GetWindowCycleTabSliderActiveButtonSelector() const { + return WindowCycleListTestApi(GetCycleList()) + .GetTabSliderActiveButtonSelector(); + } + const views::Label* GetWindowCycleNoRecentItemsLabel() const { return WindowCycleListTestApi(GetCycleList()).no_recent_items_label(); } @@ -3101,6 +3113,42 @@ EXPECT_TRUE(cycle_controller->IsCycling()); } +// Runs the accessibility paint checks on the active button selector. +// There should be no DCHECK failures. +TEST_F(ModeSelectionWindowCycleControllerTest, + AccessibilityPaintChecksOnActiveButtonSelector) { + WindowCycleController* cycle_controller = + Shell::Get()->window_cycle_controller(); + + // Create a second desk. + auto* desks_controller = DesksController::Get(); + desks_controller->NewDesk(DesksCreationRemovalSource::kButton); + ASSERT_EQ(2u, desks_controller->desks().size()); + + // Put one window on each desk. + auto win0 = CreateAppWindow(gfx::Rect(0, 0, 250, 100)); + ActivateDesk(desks_controller->desks()[1].get()); + auto win1 = CreateAppWindow(gfx::Rect(0, 0, 300, 200)); + + // Start cycle. Verify the slider buttons are present. + cycle_controller->StartCycling(); + auto tab_slider_buttons = GetWindowCycleTabSliderButtons(); + EXPECT_EQ(2u, tab_slider_buttons.size()); + + // Run the accessibility paint checks on the active button selector. + // There should be no DCHECK failures. Failures in the past occurred due to + // the active button selector having `FocusBehavior::ALWAYS`. That change, + // done to improve ChromeVox's presentation, appears to no longer be needed. + // Therefore the default focus behavior (`FocusBehavior::NEVER`) is once again + // in place. + auto* active_button_selector = GetWindowCycleTabSliderActiveButtonSelector(); + EXPECT_EQ(active_button_selector->GetFocusBehavior(), + views::View::FocusBehavior::NEVER); + RunAccessibilityPaintChecks(const_cast<views::View*>(active_button_selector)); + + CompleteCycling(cycle_controller); +} + namespace { constexpr char kUser1Email[] = "user1@alttab"; @@ -3235,6 +3283,11 @@ return WindowCycleListTestApi(GetCycleList()).GetWindowCycleItemViews(); } + const views::View* GetWindowCycleTabSliderActiveButtonSelector() const { + return WindowCycleListTestApi(GetCycleList()) + .GetTabSliderActiveButtonSelector(); + } + const views::View::Views& GetWindowCycleTabSliderButtons() const { return WindowCycleListTestApi(GetCycleList()).GetTabSliderButtons(); }
diff --git a/ash/wm/window_cycle/window_cycle_tab_slider.cc b/ash/wm/window_cycle/window_cycle_tab_slider.cc index 55a7204f..c927a990 100644 --- a/ash/wm/window_cycle/window_cycle_tab_slider.cc +++ b/ash/wm/window_cycle/window_cycle_tab_slider.cc
@@ -10,12 +10,13 @@ #include "ash/wm/window_cycle/window_cycle_controller.h" #include "base/bind.h" #include "base/strings/utf_string_conversions.h" +#include "ui/accessibility/ax_enums.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/compositor/layer.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/transform_util.h" -#include "ui/views/accessibility/accessibility_paint_checks.h" +#include "ui/views/accessibility/view_accessibility.h" #include "ui/views/animation/animation_builder.h" #include "ui/views/background.h" #include "ui/views/controls/highlight_path_generator.h" @@ -105,13 +106,6 @@ Shell::Get()->window_cycle_controller()->IsAltTabPerActiveDesk(); all_desks_tab_slider_button_->SetToggled(!per_desk); current_desk_tab_slider_button_->SetToggled(per_desk); - - // TODO(crbug.com/1218186): Remove this, this is in place temporarily to be - // able to submit accessibility checks. This crashes if fetching a11y node - // data during paint because `active_button_selector_` is null. - active_button_selector_->SetProperty(views::kSkipAccessibilityPaintChecks, - true); - active_button_selector_->SetFocusBehavior(View::FocusBehavior::ALWAYS); } void WindowCycleTabSlider::SetFocus(bool focus) {
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1 index 438d539..812b8c2 100644 --- a/build/fuchsia/linux_internal.sdk.sha1 +++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@ -10.20221117.1.1 +10.20221118.0.1
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn index 4fe4ce9..fe9a487 100644 --- a/chrome/android/features/autofill_assistant/BUILD.gn +++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -89,7 +89,6 @@ "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCollectUserDataUiTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantCustomTabTestRule.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDetailsUiTest.java", - "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandlerTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacadeTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFormActionTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantGenericUiTest.java", @@ -120,7 +119,6 @@ "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUpdateClientSettingsIntegrationTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetOnboardingCoordinatorTest.java", - "javatests/src/org/chromium/chrome/browser/autofill_assistant/DirectActionsIntegrationTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/InCctTriggeringFromGsaTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/InCctTriggeringFromNonGsaTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/JsFlowIntegrationTest.java", @@ -129,7 +127,6 @@ "javatests/src/org/chromium/chrome/browser/autofill_assistant/PasswordChangeFixtureTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/PasswordChangeFixtureTestUtils.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/ProtoTestUtil.java", - "javatests/src/org/chromium/chrome/browser/autofill_assistant/TestingAutofillAssistantModuleEntryProvider.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/TriggerContextTest.java", ]
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandlerTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandlerTest.java deleted file mode 100644 index 312fe53..0000000 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandlerTest.java +++ /dev/null
@@ -1,369 +0,0 @@ -// Copyright 2019 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_assistant; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; - -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; - -import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.waitUntilViewMatchesCondition; - -import android.os.Bundle; - -import androidx.test.filters.MediumTest; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.chromium.base.Callback; -import org.chromium.base.supplier.Supplier; -import org.chromium.base.test.util.Batch; -import org.chromium.base.test.util.CallbackHelper; -import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.DisableIf; -import org.chromium.base.test.util.DisabledTest; -import org.chromium.chrome.browser.app.ChromeActivity; -import org.chromium.chrome.browser.directactions.DirectActionHandler; -import org.chromium.chrome.browser.directactions.DirectActionReporter; -import org.chromium.chrome.browser.directactions.DirectActionReporter.Type; -import org.chromium.chrome.browser.directactions.FakeDirectActionReporter; -import org.chromium.chrome.browser.flags.ChromeSwitches; -import org.chromium.chrome.browser.preferences.Pref; -import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -import org.chromium.components.autofill_assistant.R; -import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; -import org.chromium.components.prefs.PrefService; -import org.chromium.components.user_prefs.UserPrefs; -import org.chromium.content_public.browser.WebContents; -import org.chromium.content_public.browser.test.util.TestThreadUtils; - -/** Tests the direct actions exposed by AA. */ -@RunWith(ChromeJUnit4ClassRunner.class) -@Batch(Batch.PER_CLASS) -@CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE) -public class AutofillAssistantDirectActionHandlerTest { - @Rule - public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); - - private ChromeActivity mActivity; - private BottomSheetController mBottomSheetController; - private DirectActionHandler mHandler; - private TestingAutofillAssistantModuleEntryProvider mModuleEntryProvider; - - @Before - public void setUp() throws Exception { - mActivityTestRule.startMainActivityOnBlankPage(); - mActivity = mActivityTestRule.getActivity(); - - mBottomSheetController = TestThreadUtils.runOnUiThreadBlocking( - () -> AutofillAssistantUiTestUtil.getBottomSheetController(mActivity)); - mModuleEntryProvider = new TestingAutofillAssistantModuleEntryProvider(); - mModuleEntryProvider.setCannotInstall(); - - Supplier<WebContents> webContentsSupplier = - () -> mActivity.getActivityTabProvider().get().getWebContents(); - - mHandler = new AutofillAssistantDirectActionHandler(mActivity, mBottomSheetController, - mActivity.getBrowserControlsManager(), - mActivity.getCompositorViewHolderForTesting(), mActivity.getActivityTabProvider(), - webContentsSupplier, mModuleEntryProvider); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile()); - prefService.clearPref(Pref.AUTOFILL_ASSISTANT_CONSENT); - prefService.clearPref(Pref.AUTOFILL_ASSISTANT_ENABLED); - }); - } - - @After - public void tearDown() { - TestThreadUtils.runOnUiThreadBlocking(() -> { - PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile()); - prefService.clearPref(Pref.AUTOFILL_ASSISTANT_CONSENT); - prefService.clearPref(Pref.AUTOFILL_ASSISTANT_ENABLED); - }); - } - - @Test - @MediumTest - public void testReportOnboardingOnlyIfNotAccepted() throws Exception { - mModuleEntryProvider.setInstalled(); - - FakeDirectActionReporter reporter = new FakeDirectActionReporter(); - reportAvailableDirectActions(mHandler, reporter); - - Assert.assertThat(reporter.getDirectActions(), - containsInAnyOrder("onboarding", "onboarding_and_start")); - - FakeDirectActionReporter.FakeDefinition onboarding = - reporter.mActions.get(reporter.getDirectActions().indexOf("onboarding")); - assertEquals("onboarding", onboarding.mId); - assertEquals(2, onboarding.mParameters.size()); - assertEquals("name", onboarding.mParameters.get(0).mName); - assertEquals(Type.STRING, onboarding.mParameters.get(0).mType); - assertEquals("experiment_ids", onboarding.mParameters.get(1).mName); - assertEquals(Type.STRING, onboarding.mParameters.get(1).mType); - assertEquals(1, onboarding.mResults.size()); - assertEquals("success", onboarding.mResults.get(0).mName); - assertEquals(Type.BOOLEAN, onboarding.mResults.get(0).mType); - } - - @Test - @MediumTest - @DisabledTest(message = "https://crbug.com/1296764") - public void testReportAvailableDirectActions() throws Exception { - mModuleEntryProvider.setInstalled(); - TestThreadUtils.runOnUiThreadBlocking(() -> { - PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile()); - prefService.setBoolean(Pref.AUTOFILL_ASSISTANT_CONSENT, true); - prefService.setBoolean(Pref.AUTOFILL_ASSISTANT_ENABLED, true); - }); - - // Start the autofill assistant stack. - - FakeDirectActionReporter reporter = new FakeDirectActionReporter(); - reportAvailableDirectActions(mHandler, reporter); - - assertEquals(1, reporter.mActions.size()); - - FakeDirectActionReporter.FakeDefinition fetch = reporter.mActions.get(0); - assertEquals("fetch_website_actions", fetch.mId); - assertEquals(2, fetch.mParameters.size()); - assertEquals("user_name", fetch.mParameters.get(0).mName); - assertEquals(Type.STRING, fetch.mParameters.get(0).mType); - assertEquals(false, fetch.mParameters.get(0).mRequired); - assertEquals("experiment_ids", fetch.mParameters.get(1).mName); - assertEquals(Type.STRING, fetch.mParameters.get(1).mType); - assertEquals(false, fetch.mParameters.get(1).mRequired); - assertEquals(1, fetch.mResults.size()); - assertEquals("success", fetch.mResults.get(0).mName); - assertEquals(Type.BOOLEAN, fetch.mResults.get(0).mType); - - // Start the autofill assistant stack. - fetchWebsiteActions(); - // Reset the reported actions. - reporter = new FakeDirectActionReporter(); - reportAvailableDirectActions(mHandler, reporter); - - // Now that the AA stack is up, the fetdch_website_actions should no longer show up. - assertEquals(3, reporter.mActions.size()); - - // Now we expect 3 dyamic actions "search", "action2" and "action2_alias". - FakeDirectActionReporter.FakeDefinition search = reporter.mActions.get(0); - assertEquals("search", search.mId); - assertEquals(3, search.mParameters.size()); - assertEquals("experiment_ids", search.mParameters.get(0).mName); - assertEquals(Type.STRING, search.mParameters.get(0).mType); - assertEquals("SEARCH_QUERY", search.mParameters.get(1).mName); - assertEquals(Type.STRING, search.mParameters.get(1).mType); - assertEquals("arg2", search.mParameters.get(2).mName); - assertEquals(Type.STRING, search.mParameters.get(2).mType); - assertEquals(1, search.mResults.size()); - assertEquals("success", search.mResults.get(0).mName); - assertEquals(Type.BOOLEAN, search.mResults.get(0).mType); - - FakeDirectActionReporter.FakeDefinition action2 = reporter.mActions.get(1); - assertEquals("action2", action2.mId); - assertEquals(3, action2.mParameters.size()); - assertEquals("experiment_ids", action2.mParameters.get(0).mName); - assertEquals(Type.STRING, action2.mParameters.get(0).mType); - assertEquals("SEARCH_QUERY", action2.mParameters.get(1).mName); - assertEquals(Type.STRING, action2.mParameters.get(1).mType); - assertEquals("arg2", action2.mParameters.get(2).mName); - assertEquals(Type.STRING, action2.mParameters.get(2).mType); - assertEquals(1, action2.mResults.size()); - assertEquals("success", action2.mResults.get(0).mName); - assertEquals(Type.BOOLEAN, action2.mResults.get(0).mType); - - FakeDirectActionReporter.FakeDefinition action2Alias = reporter.mActions.get(2); - assertEquals("action2_alias", action2Alias.mId); - assertEquals(3, action2Alias.mParameters.size()); - assertEquals("experiment_ids", action2Alias.mParameters.get(0).mName); - assertEquals(Type.STRING, action2Alias.mParameters.get(0).mType); - assertEquals("SEARCH_QUERY", action2Alias.mParameters.get(1).mName); - assertEquals(Type.STRING, action2Alias.mParameters.get(1).mType); - assertEquals("arg2", action2Alias.mParameters.get(2).mName); - assertEquals(Type.STRING, action2Alias.mParameters.get(2).mType); - assertEquals(1, action2Alias.mResults.size()); - assertEquals("success", action2Alias.mResults.get(0).mName); - assertEquals(Type.BOOLEAN, action2Alias.mResults.get(0).mType); - } - - @Test - @MediumTest - public void testReportAvailableAutofillAssistantActions() throws Exception { - mModuleEntryProvider.setInstalled(); - TestThreadUtils.runOnUiThreadBlocking(() -> { - PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile()); - prefService.setBoolean(Pref.AUTOFILL_ASSISTANT_CONSENT, true); - prefService.setBoolean(Pref.AUTOFILL_ASSISTANT_ENABLED, true); - }); - - FakeDirectActionReporter reporter = new FakeDirectActionReporter(); - reportAvailableDirectActions(mHandler, reporter); - - assertEquals(1, reporter.mActions.size()); - - FakeDirectActionReporter.FakeDefinition fetch = reporter.mActions.get(0); - assertEquals("fetch_website_actions", fetch.mId); - assertEquals(2, fetch.mParameters.size()); - assertEquals("user_name", fetch.mParameters.get(0).mName); - assertEquals(Type.STRING, fetch.mParameters.get(0).mType); - assertEquals(false, fetch.mParameters.get(0).mRequired); - assertEquals("experiment_ids", fetch.mParameters.get(1).mName); - assertEquals(Type.STRING, fetch.mParameters.get(1).mType); - assertEquals(false, fetch.mParameters.get(1).mRequired); - - assertEquals(1, fetch.mResults.size()); - assertEquals("success", fetch.mResults.get(0).mName); - assertEquals(Type.BOOLEAN, fetch.mResults.get(0).mType); - } - - @Test - @MediumTest - @DisableIf.Build(sdk_is_greater_than = 22) // TODO(crbug/990118): re-enable - public void testOnboarding() throws Exception { - mModuleEntryProvider.setInstalled(); - - assertThat(isActionReported("onboarding"), is(true)); - acceptOnboarding(); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile()); - assertTrue(prefService.getBoolean(Pref.AUTOFILL_ASSISTANT_CONSENT)); - }); - } - - @Test - @MediumTest - public void testModuleNotAvailable() throws Exception { - mModuleEntryProvider.setCannotInstall(); - - assertThat(isActionReported("onboarding"), is(true)); - assertFalse(performAction("onboarding", Bundle.EMPTY)); - } - - @Test - @MediumTest - @DisableIf.Build(sdk_is_greater_than = 22) // TODO(crbug/990118): re-enable - public void testInstallModuleOnDemand() throws Exception { - mModuleEntryProvider.setNotInstalled(); - - assertThat(isActionReported("onboarding"), is(true)); - acceptOnboarding(); - } - - private void acceptOnboarding() throws Exception { - WaitingCallback<Boolean> onboardingCallback = - performActionAsync("onboarding", Bundle.EMPTY); - - waitUntilViewMatchesCondition(withId(R.id.button_init_ok), isCompletelyDisplayed()); - - assertFalse(onboardingCallback.hasResult()); - onView(withId(R.id.button_init_ok)).perform(click()); - assertEquals(Boolean.TRUE, onboardingCallback.waitForResult("accept onboarding")); - } - - private boolean isActionReported(String actionId) throws Exception { - FakeDirectActionReporter reporter = new FakeDirectActionReporter(); - reportAvailableDirectActions(mHandler, reporter); - - for (FakeDirectActionReporter.FakeDefinition definition : reporter.mActions) { - if (definition.mId.equals(actionId)) { - return true; - } - } - return false; - } - - // TODO(b/134741524): Add tests that list and execute direct actions coming from scripts, once - // we have a way to fake RPCs and can create a bottom sheet controller on demand. - - /** Calls fetch_website_actions and returns whether that succeeded or not. */ - private boolean fetchWebsiteActions() throws Exception { - WaitingCallback<Bundle> callback = new WaitingCallback<Bundle>(); - assertTrue(TestThreadUtils.runOnUiThreadBlocking( - () - -> mHandler.performDirectAction( - "fetch_website_actions", Bundle.EMPTY, callback))); - return callback.waitForResult("fetch_website_actions").getBoolean("success", false); - } - - /** - * When reporting direct actions involves web_contents in the controller, it needs to run on the - * UI thread. - */ - private void reportAvailableDirectActions( - DirectActionHandler handler, DirectActionReporter reporter) throws Exception { - assertTrue(TestThreadUtils.runOnUiThreadBlocking(() -> { - handler.reportAvailableDirectActions(reporter); - return true; - })); - } - - /** Performs direct action |name| and returns the result. */ - private Boolean performAction(String name, Bundle arguments) throws Exception { - return performActionAsync(name, arguments).waitForResult("success"); - } - - /** - * Performs direct action |name| and returns a {@link WaitingCallback} that'll eventually - * contain the result. - */ - private WaitingCallback<Boolean> performActionAsync(String name, Bundle arguments) - throws Exception { - WaitingCallback<Boolean> callback = new WaitingCallback<Boolean>(); - Bundle allArguments = new Bundle(arguments); - TestThreadUtils.runOnUiThreadBlocking( - () - -> mHandler.performDirectAction(name, allArguments, - (bundle) -> callback.onResult(bundle.getBoolean("success")))); - return callback; - } - - /** - * A callback that allows waiting for the result to be available, then retrieving it. - */ - private static class WaitingCallback<T> implements Callback<T> { - private final CallbackHelper mHelper = new CallbackHelper(); - private boolean mHasResult; - private T mResult; - - @Override - public synchronized void onResult(T result) { - mResult = result; - mHasResult = true; - mHelper.notifyCalled(); - } - - synchronized T waitForResult(String msg) throws Exception { - if (!mHasResult) mHelper.waitForFirst(msg); - assertTrue(mHasResult); - return mResult; - } - - synchronized boolean hasResult() { - return mHasResult; - } - - synchronized T getResult() { - return mResult; - } - } -}
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/DirectActionsIntegrationTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/DirectActionsIntegrationTest.java deleted file mode 100644 index 94fd95b..0000000 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/DirectActionsIntegrationTest.java +++ /dev/null
@@ -1,475 +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.autofill_assistant; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription; -import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; - -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.not; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.Mockito.verify; - -import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.checkElementExists; -import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.waitUntil; -import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.waitUntilViewMatchesCondition; -import static org.chromium.chrome.browser.autofill_assistant.MiniActionTestUtil.addTapSteps; -import static org.chromium.chrome.browser.autofill_assistant.ProtoTestUtil.toCssSelector; - -import android.os.Bundle; - -import androidx.test.espresso.matcher.ViewMatchers.Visibility; -import androidx.test.filters.MediumTest; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; - -import org.chromium.base.Callback; -import org.chromium.base.test.util.Batch; -import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.CriteriaNotSatisfiedException; -import org.chromium.base.test.util.DisabledTest; -import org.chromium.chrome.browser.autofill_assistant.proto.ActionProto; -import org.chromium.chrome.browser.autofill_assistant.proto.ChipProto; -import org.chromium.chrome.browser.autofill_assistant.proto.DirectActionProto; -import org.chromium.chrome.browser.autofill_assistant.proto.InfoBoxProto; -import org.chromium.chrome.browser.autofill_assistant.proto.PromptProto; -import org.chromium.chrome.browser.autofill_assistant.proto.ShowInfoBoxProto; -import org.chromium.chrome.browser.autofill_assistant.proto.StopProto; -import org.chromium.chrome.browser.autofill_assistant.proto.SupportedScriptProto; -import org.chromium.chrome.browser.autofill_assistant.proto.SupportedScriptProto.PresentationProto; -import org.chromium.chrome.browser.autofill_assistant.proto.TellProto; -import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule; -import org.chromium.chrome.browser.directactions.DirectActionHandler; -import org.chromium.chrome.browser.directactions.FakeDirectActionReporter; -import org.chromium.chrome.browser.flags.ChromeFeatureList; -import org.chromium.chrome.browser.flags.ChromeSwitches; -import org.chromium.chrome.browser.preferences.Pref; -import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.chrome.test.util.browser.Features.EnableFeatures; -import org.chromium.components.autofill_assistant.AssistantDependencies; -import org.chromium.components.autofill_assistant.AssistantFeatures; -import org.chromium.components.autofill_assistant.AutofillAssistantModuleEntry; -import org.chromium.components.autofill_assistant.AutofillAssistantModuleEntryProvider; -import org.chromium.components.autofill_assistant.R; -import org.chromium.components.prefs.PrefService; -import org.chromium.components.user_prefs.UserPrefs; -import org.chromium.content_public.browser.test.util.TestThreadUtils; - -import java.util.ArrayList; -import java.util.Collections; - -/** - * Tests Autofill Assistant direct actions. - */ -@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -@Batch(Batch.PER_CLASS) -@RunWith(ChromeJUnit4ClassRunner.class) -public class DirectActionsIntegrationTest { - public DirectActionsIntegrationTest() {} - - private final CustomTabActivityTestRule mTestRule = new CustomTabActivityTestRule(); - - @Rule - public final TestRule mRulesChain = - RuleChain.outerRule(mTestRule).around(new AutofillAssistantCustomTabTestRule( - mTestRule, "autofill_assistant_target_website.html")); - - @Rule - public MockitoRule mMockitoRule = MockitoJUnit.rule(); - - @Mock - Callback<Bundle> mDirectActionResultCallback; - - private AutofillAssistantModuleEntry mModuleEntry; - private DirectActionHandler mDirectActionHandler; - private FakeDirectActionReporter mDirectActionReporter; - - @Before - public void setUp() { - mDirectActionReporter = new FakeDirectActionReporter(); - TestThreadUtils.runOnUiThreadBlocking(() -> { - mModuleEntry = - AutofillAssistantModuleEntryProvider.INSTANCE.getModuleEntryIfInstalled(); - assert mModuleEntry != null; - AssistantDependencies dependencies = - new AssistantStaticDependenciesChrome().createDependencies( - mTestRule.getActivity()); - mDirectActionHandler = AutofillAssistantFacade.createDirectActionHandler( - mTestRule.getActivity(), dependencies.getBottomSheetController(), - mTestRule.getActivity().getBrowserControlsManager(), dependencies.getRootView(), - mTestRule.getActivity().getActivityTabProvider()); - }); - } - - @After - public void tearDown() { - TestThreadUtils.runOnUiThreadBlocking(() -> { - PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile()); - prefService.clearPref(Pref.AUTOFILL_ASSISTANT_CONSENT); - prefService.clearPref(Pref.AUTOFILL_ASSISTANT_ENABLED); - }); - } - - /** Sets the value of @param preference to @param value. */ - private void setBooleanPref(String preference, boolean value) { - TestThreadUtils.runOnUiThreadBlocking(() -> { - PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile()); - prefService.setBoolean(preference, value); - }); - } - - @Test - @MediumTest - @EnableFeatures({ChromeFeatureList.DIRECT_ACTIONS, AssistantFeatures.AUTOFILL_ASSISTANT_NAME, - AssistantFeatures.AUTOFILL_ASSISTANT_DIRECT_ACTIONS_NAME}) - public void - testOnboardingAndStart() { - setBooleanPref(Pref.AUTOFILL_ASSISTANT_CONSENT, false); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - mDirectActionHandler.reportAvailableDirectActions(mDirectActionReporter); - Assert.assertThat(mDirectActionReporter.getDirectActions(), - containsInAnyOrder("onboarding", "onboarding_and_start")); - }); - - ArrayList<ActionProto> list = new ArrayList<>(); - // Tapping touch_area_one will make it disappear. - addTapSteps(toCssSelector("#touch_area_one"), list); - - AutofillAssistantTestScript script = new AutofillAssistantTestScript( - SupportedScriptProto.newBuilder() - .setPath("autofill_assistant_target_website.html") - .setPresentation(PresentationProto.newBuilder().setDirectAction( - DirectActionProto.newBuilder() - .addNames("some_direct_action") - .build())) - .build(), - list); - - AutofillAssistantTestService testService = - new AutofillAssistantTestService(Collections.singletonList(script)); - testService.scheduleForInjection(); - - Bundle arguments = new Bundle(); - arguments.putString("name", "some_direct_action"); - TestThreadUtils.runOnUiThreadBlocking(() -> { - mDirectActionHandler.performDirectAction( - "onboarding_and_start", arguments, mDirectActionResultCallback); - }); - - waitUntilViewMatchesCondition(withText("I agree"), isDisplayed()); - onView(withText("I agree")).perform(click()); - - waitUntil(() -> !checkElementExists(mTestRule.getWebContents(), "touch_area_one")); - verify(mDirectActionResultCallback) - .onResult(argThat(bundle -> bundle.getBoolean("success"))); - } - - @Test - @MediumTest - @EnableFeatures({ChromeFeatureList.DIRECT_ACTIONS, AssistantFeatures.AUTOFILL_ASSISTANT_NAME, - AssistantFeatures.AUTOFILL_ASSISTANT_DIRECT_ACTIONS_NAME}) - public void - testOnboardingAndStartShowsErrorMessageIfRequested() { - setBooleanPref(Pref.AUTOFILL_ASSISTANT_CONSENT, false); - TestThreadUtils.runOnUiThreadBlocking(() -> { - mDirectActionHandler.reportAvailableDirectActions(mDirectActionReporter); - Assert.assertThat(mDirectActionReporter.getDirectActions(), - containsInAnyOrder("onboarding", "onboarding_and_start")); - }); - - // No scripts available. - AutofillAssistantTestService testService = - new AutofillAssistantTestService(Collections.emptyList()); - testService.scheduleForInjection(); - - Bundle arguments = new Bundle(); - arguments.putString("name", "some_direct_action"); - arguments.putBoolean("show_error_on_failure", true); - TestThreadUtils.runOnUiThreadBlocking(() -> { - mDirectActionHandler.performDirectAction( - "onboarding_and_start", arguments, mDirectActionResultCallback); - }); - - waitUntilViewMatchesCondition(withText("I agree"), isDisplayed()); - onView(withText("I agree")).perform(click()); - - waitUntilViewMatchesCondition(withText("Something went wrong"), isDisplayed()); - verify(mDirectActionResultCallback) - .onResult(argThat(bundle -> !bundle.getBoolean("success"))); - } - - /** - * Regression test for b/200916720. - */ - @Test - @MediumTest - @EnableFeatures({ChromeFeatureList.DIRECT_ACTIONS, AssistantFeatures.AUTOFILL_ASSISTANT_NAME, - AssistantFeatures.AUTOFILL_ASSISTANT_DIRECT_ACTIONS_NAME}) - public void - testOnboardingTwice() { - setBooleanPref(Pref.AUTOFILL_ASSISTANT_CONSENT, false); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - mDirectActionHandler.reportAvailableDirectActions(mDirectActionReporter); - Assert.assertThat(mDirectActionReporter.getDirectActions(), - containsInAnyOrder("onboarding", "onboarding_and_start")); - }); - - ArrayList<ActionProto> list = new ArrayList<>(); - // Tapping touch_area_one will make it disappear. - addTapSteps(toCssSelector("#touch_area_one"), list); - - AutofillAssistantTestScript script = new AutofillAssistantTestScript( - SupportedScriptProto.newBuilder() - .setPath("autofill_assistant_target_website.html") - .setPresentation(PresentationProto.newBuilder().setDirectAction( - DirectActionProto.newBuilder() - .addNames("some_direct_action") - .build())) - .build(), - list); - - AutofillAssistantTestService testService = - new AutofillAssistantTestService(Collections.singletonList(script)); - testService.scheduleForInjection(); - - Bundle arguments = new Bundle(); - arguments.putString("name", "some_direct_action"); - TestThreadUtils.runOnUiThreadBlocking(() -> { - mDirectActionHandler.performDirectAction( - "onboarding_and_start", arguments, mDirectActionResultCallback); - }); - waitUntilViewMatchesCondition(withText("I agree"), isDisplayed()); - - // Don't agree to the onboarding. Instead, restart the direct action. This tests a case - // where the client already exists, but the controller does not. - TestThreadUtils.runOnUiThreadBlocking(() -> { - mDirectActionHandler.performDirectAction( - "onboarding_and_start", arguments, mDirectActionResultCallback); - }); - waitUntilViewMatchesCondition(withText("I agree"), isDisplayed()); - - onView(withText("I agree")).perform(click()); - waitUntil(() -> !checkElementExists(mTestRule.getWebContents(), "touch_area_one")); - verify(mDirectActionResultCallback) - .onResult(argThat(bundle -> bundle.getBoolean("success"))); - } - - /** - * Regression test for b/195417453. - */ - @Test - @MediumTest - @EnableFeatures({ChromeFeatureList.DIRECT_ACTIONS, AssistantFeatures.AUTOFILL_ASSISTANT_NAME, - AssistantFeatures.AUTOFILL_ASSISTANT_DIRECT_ACTIONS_NAME}) - @DisabledTest(message = "https://crbug.com/1272997") - public void - testStatusMessageResetsBetweenRuns() { - setBooleanPref(Pref.AUTOFILL_ASSISTANT_CONSENT, true); - - ArrayList<ActionProto> list = new ArrayList<>(); - list.add(ActionProto.newBuilder() - .setPrompt(PromptProto.newBuilder().addChoices( - PromptProto.Choice.newBuilder().setChip( - ChipProto.newBuilder().setText("Prompt")))) - .build()); - list.add(ActionProto.newBuilder() - .setShowInfoBox(ShowInfoBoxProto.newBuilder().setInfoBox( - InfoBoxProto.newBuilder().setExplanation( - "InfoBox message from previous run"))) - .build()); - list.add(ActionProto.newBuilder() - .setTell(TellProto.newBuilder().setMessage( - "Status message from previous run")) - .build()); - list.add(ActionProto.newBuilder().setStop(StopProto.newBuilder()).build()); - - AutofillAssistantTestScript script = new AutofillAssistantTestScript( - SupportedScriptProto.newBuilder() - .setPath("autofill_assistant_target_website.html") - .setPresentation(PresentationProto.newBuilder().setDirectAction( - DirectActionProto.newBuilder() - .addNames("some_direct_action") - .build())) - .build(), - list); - - AutofillAssistantTestService testService = - new AutofillAssistantTestService(Collections.singletonList(script)); - testService.scheduleForInjection(); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - mDirectActionHandler.reportAvailableDirectActions(mDirectActionReporter); - Assert.assertThat(mDirectActionReporter.getDirectActions(), - containsInAnyOrder("fetch_website_actions")); - mDirectActionHandler.performDirectAction( - "fetch_website_actions", new Bundle(), mDirectActionResultCallback); - verify(mDirectActionResultCallback) - .onResult(argThat(bundle -> bundle.getBoolean("success"))); - - mDirectActionHandler.reportAvailableDirectActions(mDirectActionReporter); - Assert.assertThat(mDirectActionReporter.getDirectActions(), - containsInAnyOrder("fetch_website_actions", "some_direct_action")); - mDirectActionHandler.performDirectAction( - "some_direct_action", new Bundle(), mDirectActionResultCallback); - }); - waitUntilViewMatchesCondition(withText("Prompt"), isDisplayed()); - - // Changes the status message, shows the info box, then gracefully stops the script. - onView(withText("Prompt")).perform(click()); - - // Run the same direct action again, but don't accept the prompt. The script won't run the - // showInfoBox and tell actions, thus the UI should be left at startup-default. - TestThreadUtils.runOnUiThreadBlocking(() -> { - mDirectActionHandler.performDirectAction( - "some_direct_action", new Bundle(), mDirectActionResultCallback); - }); - waitUntilViewMatchesCondition(withText("Prompt"), isDisplayed()); - onView(withText("InfoBox message from previous run")).check(doesNotExist()); - onView(withId(R.id.info_box_explanation)).check(matches(not(isDisplayed()))); - onView(withText("Status message from previous run")).check(doesNotExist()); - } - - /** - * Regression test for b/195417125. - */ - @Test - @MediumTest - @EnableFeatures({ChromeFeatureList.DIRECT_ACTIONS, AssistantFeatures.AUTOFILL_ASSISTANT_NAME, - AssistantFeatures.AUTOFILL_ASSISTANT_DIRECT_ACTIONS_NAME}) - public void - testLastTellMessageDisplayedAfterStop() { - ArrayList<ActionProto> list = new ArrayList<>(); - list.add(ActionProto.newBuilder() - .setPrompt(PromptProto.newBuilder().addChoices( - PromptProto.Choice.newBuilder().setChip( - ChipProto.newBuilder().setText("Prompt")))) - .build()); - list.add(ActionProto.newBuilder() - .setTell(TellProto.newBuilder().setMessage("Last tell message")) - .build()); - list.add(ActionProto.newBuilder().setStop(StopProto.newBuilder()).build()); - - AutofillAssistantTestScript script = new AutofillAssistantTestScript( - SupportedScriptProto.newBuilder() - .setPath("autofill_assistant_target_website.html") - .setPresentation(PresentationProto.newBuilder().setDirectAction( - DirectActionProto.newBuilder() - .addNames("some_direct_action") - .build())) - .build(), - list); - AutofillAssistantTestService testService = - new AutofillAssistantTestService(Collections.singletonList(script)); - testService.scheduleForInjection(); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - mDirectActionHandler.reportAvailableDirectActions(mDirectActionReporter); - Assert.assertThat(mDirectActionReporter.getDirectActions(), - containsInAnyOrder("fetch_website_actions")); - mDirectActionHandler.performDirectAction( - "fetch_website_actions", new Bundle(), mDirectActionResultCallback); - verify(mDirectActionResultCallback) - .onResult(argThat(bundle -> bundle.getBoolean("success"))); - - mDirectActionHandler.reportAvailableDirectActions(mDirectActionReporter); - Assert.assertThat(mDirectActionReporter.getDirectActions(), - containsInAnyOrder("fetch_website_actions", "some_direct_action")); - mDirectActionHandler.performDirectAction( - "some_direct_action", new Bundle(), mDirectActionResultCallback); - }); - waitUntilViewMatchesCondition(withText("Prompt"), isDisplayed()); - onView(withText("Prompt")).perform(click()); - waitUntilViewMatchesCondition(withText("Last tell message"), isDisplayed()); - // The last tell message should still be visible (and not disappear - // immediately) after the script stops. - try { - waitUntilViewMatchesCondition(withText("Last tell message"), not(isDisplayed()), 200); - } catch (AssertionError e) { - if (e.getCause() instanceof CriteriaNotSatisfiedException) { - // This is ok, the view is still there, the test succeeds. - return; - } - throw e; - } - throw new CriteriaNotSatisfiedException( - "Expected last tell message to be visible after stop"); - } - - /** - * Regression test for b/224759196. - */ - @Test - @MediumTest - @EnableFeatures({ChromeFeatureList.DIRECT_ACTIONS, AssistantFeatures.AUTOFILL_ASSISTANT_NAME, - AssistantFeatures.AUTOFILL_ASSISTANT_DIRECT_ACTIONS_NAME}) - public void - testCloseDirectAction() { - ArrayList<ActionProto> list = new ArrayList<>(); - list.add(ActionProto.newBuilder() - .setPrompt(PromptProto.newBuilder().addChoices( - PromptProto.Choice.newBuilder().setChip( - ChipProto.newBuilder().setText("Prompt")))) - .build()); - list.add(ActionProto.newBuilder() - .setTell(TellProto.newBuilder().setMessage("Last tell message")) - .build()); - list.add(ActionProto.newBuilder().setStop(StopProto.newBuilder()).build()); - - AutofillAssistantTestScript script = new AutofillAssistantTestScript( - SupportedScriptProto.newBuilder() - .setPath("autofill_assistant_target_website.html") - .setPresentation(PresentationProto.newBuilder().setDirectAction( - DirectActionProto.newBuilder() - .addNames("some_direct_action") - .build())) - .build(), - list); - AutofillAssistantTestService testService = - new AutofillAssistantTestService(Collections.singletonList(script)); - testService.scheduleForInjection(); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - mDirectActionHandler.reportAvailableDirectActions(mDirectActionReporter); - Assert.assertThat(mDirectActionReporter.getDirectActions(), - containsInAnyOrder("fetch_website_actions")); - mDirectActionHandler.performDirectAction( - "fetch_website_actions", new Bundle(), mDirectActionResultCallback); - verify(mDirectActionResultCallback) - .onResult(argThat(bundle -> bundle.getBoolean("success"))); - - mDirectActionHandler.reportAvailableDirectActions(mDirectActionReporter); - Assert.assertThat(mDirectActionReporter.getDirectActions(), - containsInAnyOrder("fetch_website_actions", "some_direct_action")); - mDirectActionHandler.performDirectAction( - "some_direct_action", new Bundle(), mDirectActionResultCallback); - }); - waitUntilViewMatchesCondition(withText("Prompt"), isDisplayed()); - onView(withText("Prompt")).perform(click()); - waitUntilViewMatchesCondition(withText("Last tell message"), isDisplayed()); - onView(allOf(withContentDescription("Close"), withEffectiveVisibility(Visibility.VISIBLE))) - .perform(click()); - } -}
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/TestingAutofillAssistantModuleEntryProvider.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/TestingAutofillAssistantModuleEntryProvider.java deleted file mode 100644 index a2b62ab..0000000 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/TestingAutofillAssistantModuleEntryProvider.java +++ /dev/null
@@ -1,124 +0,0 @@ -// Copyright 2019 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_assistant; - -import android.content.Context; -import android.view.View; - -import org.chromium.base.Callback; -import org.chromium.base.supplier.Supplier; -import org.chromium.components.autofill_assistant.AssistantBrowserControlsFactory; -import org.chromium.components.autofill_assistant.AssistantDependencies; -import org.chromium.components.autofill_assistant.AssistantModuleInstallUi; -import org.chromium.components.autofill_assistant.AssistantOnboardingHelper; -import org.chromium.components.autofill_assistant.AssistantStaticDependencies; -import org.chromium.components.autofill_assistant.AutofillAssistantActionHandler; -import org.chromium.components.autofill_assistant.AutofillAssistantActionHandlerImpl; -import org.chromium.components.autofill_assistant.AutofillAssistantDirectAction; -import org.chromium.components.autofill_assistant.AutofillAssistantDirectActionImpl; -import org.chromium.components.autofill_assistant.AutofillAssistantModuleEntry; -import org.chromium.components.autofill_assistant.AutofillAssistantModuleEntryProvider; -import org.chromium.components.autofill_assistant.onboarding.OnboardingCoordinatorFactory; -import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; -import org.chromium.content_public.browser.WebContents; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Implementation of {@link AutofillAssistantModuleEntryProvider} that can be manipulated to - * simulate missing or uninstallable module. - */ -class TestingAutofillAssistantModuleEntryProvider extends AutofillAssistantModuleEntryProvider { - private boolean mNotInstalled; - private boolean mCannotInstall; - - /* - * Mock action handler. We only override returning dynamic actions. - * - * TODO(crbug/806868): Inject a service also for the DirectAction path and get rid of this - * mock. - */ - static class MockAutofillAssistantActionHandler extends AutofillAssistantActionHandlerImpl { - public MockAutofillAssistantActionHandler(Context context, - BottomSheetController bottomSheetController, - AssistantBrowserControlsFactory browserControlsFactory, View rootView, - Supplier<WebContents> webContentsSupplier, - AssistantStaticDependencies staticDependencies) { - super(new OnboardingCoordinatorFactory(context, bottomSheetController, - staticDependencies.getBrowserContext(), browserControlsFactory, rootView, - staticDependencies.getAccessibilityUtil(), - staticDependencies.createInfoPageUtil()), - webContentsSupplier, staticDependencies); - } - - @Override - public List<AutofillAssistantDirectAction> getActions() { - String[] search = new String[] {"search"}; - String[] required = new String[] {"SEARCH_QUERY"}; - String[] optional = new String[] {"arg2"}; - String[] action2 = new String[] {"action2", "action2_alias"}; - AutofillAssistantDirectAction[] actions = new AutofillAssistantDirectActionImpl[] { - new AutofillAssistantDirectActionImpl(search, required, optional), - new AutofillAssistantDirectActionImpl(action2, required, optional)}; - return new ArrayList<>(Arrays.asList(actions)); - } - } - - /** Mock module entry. */ - static class MockAutofillAssistantModuleEntry implements AutofillAssistantModuleEntry { - @Override - public AssistantOnboardingHelper createOnboardingHelper( - WebContents webContents, AssistantDependencies dependencies) { - return null; - } - - @Override - public AutofillAssistantActionHandler createActionHandler(Context context, - BottomSheetController bottomSheetController, - AssistantBrowserControlsFactory browserControlsFactory, View rootView, - Supplier<WebContents> webContentsSupplier, - AssistantStaticDependencies staticDependencies) { - return new MockAutofillAssistantActionHandler(context, bottomSheetController, - browserControlsFactory, rootView, webContentsSupplier, staticDependencies); - } - } - - /** The module is already installed. This is the default state. */ - public void setInstalled() { - mNotInstalled = false; - mCannotInstall = false; - } - - /** The module is not installed, but can be installed. */ - public void setNotInstalled() { - mNotInstalled = true; - mCannotInstall = false; - } - - /** The module is not installed, and cannot be installed. */ - public void setCannotInstall() { - mNotInstalled = true; - mCannotInstall = true; - } - - @Override - public AutofillAssistantModuleEntry getModuleEntryIfInstalled() { - if (mNotInstalled) return null; - return new MockAutofillAssistantModuleEntry(); - } - - @Override - public void getModuleEntry(Callback<AutofillAssistantModuleEntry> callback, - AssistantModuleInstallUi.Provider moduleInstallUiProvider, boolean showUi) { - if (mCannotInstall) { - callback.onResult(null); - return; - } - mNotInstalled = false; - super.getModuleEntry(callback, moduleInstallUiProvider, showUi); - } -}
diff --git a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandler.java b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandler.java deleted file mode 100644 index 9d11f7e..0000000 --- a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandler.java +++ /dev/null
@@ -1,291 +0,0 @@ -// Copyright 2019 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_assistant; - -import android.content.Context; -import android.os.Bundle; -import android.view.View; - -import androidx.annotation.Nullable; - -import org.chromium.base.Callback; -import org.chromium.base.ThreadUtils; -import org.chromium.base.supplier.Supplier; -import org.chromium.chrome.browser.ActivityTabProvider; -import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; -import org.chromium.chrome.browser.directactions.DirectActionHandler; -import org.chromium.chrome.browser.directactions.DirectActionReporter; -import org.chromium.chrome.browser.directactions.DirectActionReporter.Definition; -import org.chromium.chrome.browser.directactions.DirectActionReporter.Type; -import org.chromium.chrome.browser.preferences.Pref; -import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.tab.Tab; -import org.chromium.components.autofill_assistant.AutofillAssistantActionHandler; -import org.chromium.components.autofill_assistant.AutofillAssistantDirectAction; -import org.chromium.components.autofill_assistant.AutofillAssistantModuleEntry; -import org.chromium.components.autofill_assistant.AutofillAssistantModuleEntryProvider; -import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; -import org.chromium.components.prefs.PrefService; -import org.chromium.components.user_prefs.UserPrefs; -import org.chromium.content_public.browser.WebContents; - -/** - * A handler that provides just enough functionality to allow on-demand loading of the module - * through direct actions. The actual implementation is in the module. - */ -public class AutofillAssistantDirectActionHandler implements DirectActionHandler { - private static final String FETCH_WEBSITE_ACTIONS = "fetch_website_actions"; - private static final String FETCH_WEBSITE_ACTIONS_RESULT = "success"; - private static final String AA_ACTION_RESULT = "success"; - private static final String ACTION_NAME = "name"; - private static final String EXPERIMENT_IDS = "experiment_ids"; - private static final String ONBOARDING_ACTION = "onboarding"; - private static final String ONBOARDING_AND_START_ACTION = "onboarding_and_start"; - private static final String USER_NAME = "user_name"; - private static final String SHOW_ERROR_ON_FAILURE = "show_error_on_failure"; - - private final Context mContext; - private final BottomSheetController mBottomSheetController; - private final BrowserControlsStateProvider mBrowserControls; - private final View mRootView; - private final ActivityTabProvider mActivityTabProvider; - private final Supplier<WebContents> mWebContentsSupplier; - private final AutofillAssistantModuleEntryProvider mModuleEntryProvider; - - @Nullable - private AutofillAssistantActionHandler mDelegate; - - AutofillAssistantDirectActionHandler(Context context, - BottomSheetController bottomSheetController, - BrowserControlsStateProvider browserControls, View rootView, - ActivityTabProvider activityTabProvider, Supplier<WebContents> webContentsSupplier, - AutofillAssistantModuleEntryProvider moduleEntryProvider) { - mContext = context; - mBottomSheetController = bottomSheetController; - mBrowserControls = browserControls; - mRootView = rootView; - mActivityTabProvider = activityTabProvider; - mWebContentsSupplier = webContentsSupplier; - mModuleEntryProvider = moduleEntryProvider; - } - - private PrefService getPrefs() { - return UserPrefs.get(Profile.getLastUsedRegularProfile()); - } - - @Override - public void reportAvailableDirectActions(DirectActionReporter reporter) { - ThreadUtils.assertOnUiThread(); - - if (!getPrefs().getBoolean(Pref.AUTOFILL_ASSISTANT_ENABLED)) { - return; - } - - if (!getPrefs().getBoolean(Pref.AUTOFILL_ASSISTANT_CONSENT)) { - reporter.addDirectAction(ONBOARDING_ACTION) - .withParameter(ACTION_NAME, Type.STRING, /* required= */ false) - .withParameter(EXPERIMENT_IDS, Type.STRING, /* required= */ false) - .withResult(AA_ACTION_RESULT, Type.BOOLEAN); - reporter.addDirectAction(ONBOARDING_AND_START_ACTION) - .withParameter(ACTION_NAME, Type.STRING, /* required= */ true) - .withParameter(USER_NAME, Type.STRING, /* required= */ false) - .withParameter(EXPERIMENT_IDS, Type.STRING, /* required= */ false) - .withParameter(SHOW_ERROR_ON_FAILURE, Type.BOOLEAN, /* required= */ false) - .withResult(AA_ACTION_RESULT, Type.BOOLEAN); - return; - } - - if (mDelegate == null || (mDelegate != null && !mDelegate.hasRunFirstCheck())) { - reporter.addDirectAction(FETCH_WEBSITE_ACTIONS) - .withParameter(USER_NAME, Type.STRING, /* required= */ false) - .withParameter(EXPERIMENT_IDS, Type.STRING, /* required= */ false) - .withResult(FETCH_WEBSITE_ACTIONS_RESULT, Type.BOOLEAN); - } else { - // Otherwise we are already done fetching scripts and can just return the ones we know - // about. - for (AutofillAssistantDirectAction action : mDelegate.getActions()) { - for (String name : action.getNames()) { - Definition definition = reporter.addDirectAction(name) - .withParameter(EXPERIMENT_IDS, Type.STRING, - /* required= */ false) - .withResult(AA_ACTION_RESULT, Type.BOOLEAN); - - // TODO(b/138833619): Support non-string arguments. Requires updating the proto - // definition. - for (String required : action.getRequiredArguments()) { - definition.withParameter(required, Type.STRING, /* required= */ true); - } - for (String optional : action.getOptionalArguments()) { - definition.withParameter(optional, Type.STRING, /* required= */ false); - } - } - } - } - } - - @Override - public boolean performDirectAction( - String actionId, Bundle arguments, Callback<Bundle> callback) { - if (actionId.equals(FETCH_WEBSITE_ACTIONS) - && getPrefs().getBoolean(Pref.AUTOFILL_ASSISTANT_CONSENT)) { - fetchWebsiteActions(arguments, callback); - return true; - } - // Only handle and perform the action if it is known to the controller. - if (isActionAvailable(actionId) || ONBOARDING_ACTION.equals(actionId) - || ONBOARDING_AND_START_ACTION.equals(actionId)) { - performAction(actionId, arguments, callback); - return true; - } - return false; - } - - private boolean isActionAvailable(String actionId) { - if (mDelegate == null || !mDelegate.hasRunFirstCheck()) return false; - for (AutofillAssistantDirectAction action : mDelegate.getActions()) { - if (action.getNames().contains(actionId)) return true; - } - return false; - } - - private void fetchWebsiteActions(Bundle arguments, Callback<Bundle> bundleCallback) { - Callback<Boolean> successCallback = (success) -> { - Bundle bundle = new Bundle(); - bundle.putBoolean(FETCH_WEBSITE_ACTIONS_RESULT, success); - bundleCallback.onResult(bundle); - }; - - if (!getPrefs().getBoolean(Pref.AUTOFILL_ASSISTANT_ENABLED) - || !getPrefs().getBoolean(Pref.AUTOFILL_ASSISTANT_CONSENT)) { - successCallback.onResult(false); - return; - } - - String userName = arguments.getString(USER_NAME, ""); - arguments.remove(USER_NAME); - - String experimentIds = arguments.getString(EXPERIMENT_IDS, ""); - arguments.remove(EXPERIMENT_IDS); - - getDelegate(/* installIfNecessary= */ false, (delegate) -> { - if (delegate == null) { - successCallback.onResult(false); - return; - } - delegate.fetchWebsiteActions(userName, experimentIds, arguments, successCallback); - }); - } - - private void performAction(String actionId, Bundle arguments, Callback<Bundle> bundleCallback) { - Callback<Boolean> booleanCallback = (result) -> { - Bundle bundle = new Bundle(); - bundle.putBoolean(AA_ACTION_RESULT, result); - bundleCallback.onResult(bundle); - }; - - if (!getPrefs().getBoolean(Pref.AUTOFILL_ASSISTANT_ENABLED)) { - booleanCallback.onResult(false); - return; - } - - String experimentIds = arguments.getString(EXPERIMENT_IDS, ""); - arguments.remove(EXPERIMENT_IDS); - - getDelegate(/* installIfNecessary= */ true, (delegate) -> { - if (delegate == null) { - booleanCallback.onResult(false); - return; - } - if (delegate.isSupervisedUser()) { - booleanCallback.onResult(false); - return; - } - if (ONBOARDING_ACTION.equals(actionId)) { - delegate.performOnboarding(experimentIds, arguments, booleanCallback); - return; - } - if (ONBOARDING_AND_START_ACTION.equals(actionId)) { - delegate.performOnboarding(experimentIds, arguments, onboardingResult -> { - if (!onboardingResult) { - booleanCallback.onResult(false); - return; - } - boolean showErrorOnFailure = arguments.getBoolean(SHOW_ERROR_ON_FAILURE, false); - delegate.fetchWebsiteActions(arguments.getString(USER_NAME, ""), - arguments.getString(EXPERIMENT_IDS, ""), arguments, - fetchActionsResult -> { - if (!fetchActionsResult) { - booleanCallback.onResult(false); - if (showErrorOnFailure) { - delegate.showFatalError(); - } - return; - } - String afterOnboardingActionId = - arguments.getString(ACTION_NAME, ""); - if (!isActionAvailable(afterOnboardingActionId)) { - booleanCallback.onResult(false); - if (showErrorOnFailure) { - delegate.showFatalError(); - } - return; - } - delegate.performAction(afterOnboardingActionId, experimentIds, - arguments, booleanCallback); - }); - }); - return; - } - - Callback<Boolean> successCallback = (success) -> { - booleanCallback.onResult(success && !delegate.getActions().isEmpty()); - }; - delegate.performAction(actionId, experimentIds, arguments, successCallback); - }); - } - - /** - * Builds the delegate, if possible, and pass it to the callback. - * - * <p>If necessary, this function creates a delegate instance and keeps it in {@link - * #mDelegate}. - * - * @param installIfNecessary if true, install the DFM if necessary - * @param callback callback to report the delegate to - */ - private void getDelegate( - boolean installIfNecessary, Callback<AutofillAssistantActionHandler> callback) { - if (mDelegate == null) { - mDelegate = createDelegate(mModuleEntryProvider.getModuleEntryIfInstalled()); - } - if (mDelegate != null || !installIfNecessary) { - callback.onResult(mDelegate); - return; - } - - Tab tab = mActivityTabProvider.get(); - if (tab == null) { - // TODO(b/134741524): Allow DFM loading UI to work with no tabs. - callback.onResult(null); - return; - } - mModuleEntryProvider.getModuleEntry((entry) -> { - mDelegate = createDelegate(entry); - callback.onResult(mDelegate); - }, new AssistantModuleInstallUiProviderChrome(tab), /* showUi = */ true); - } - - /** Creates a delegate from the given {@link AutofillAssistantModuleEntry}, if possible. */ - @Nullable - private AutofillAssistantActionHandler createDelegate( - @Nullable AutofillAssistantModuleEntry entry) { - if (entry == null) return null; - - return entry.createActionHandler(mContext, mBottomSheetController, - () - -> new AssistantBrowserControlsChrome(mBrowserControls), - mRootView, mWebContentsSupplier, new AssistantStaticDependenciesChrome()); - } -}
diff --git a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java index 39581be4..5db3019 100644 --- a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java +++ b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
@@ -5,29 +5,22 @@ package org.chromium.chrome.browser.autofill_assistant; import android.app.Activity; -import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.text.TextUtils; -import android.view.View; import androidx.annotation.Nullable; import org.chromium.base.Callback; import org.chromium.base.Log; -import org.chromium.base.supplier.Supplier; import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.app.ChromeActivity; -import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; -import org.chromium.chrome.browser.directactions.DirectActionHandler; import org.chromium.chrome.browser.tab.Tab; import org.chromium.components.autofill_assistant.AssistantFeatures; import org.chromium.components.autofill_assistant.AutofillAssistantMetrics; -import org.chromium.components.autofill_assistant.AutofillAssistantModuleEntryProvider; import org.chromium.components.autofill_assistant.TriggerContext; import org.chromium.components.autofill_assistant.metrics.DropOutReason; -import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.external_intents.ExternalNavigationDelegate.IntentToAutofillAllowingAppResult; import org.chromium.content_public.browser.WebContents; @@ -95,24 +88,6 @@ tab -> { AutofillAssistantTabHelper.get(tab).start(triggerContext); }); } - /** - * Returns a {@link DirectActionHandler} for making dynamic actions available under Android Q. - * - * <p>This should only be called if {@link - * AssistantDependencyUtilsChrome#areDirectActionsAvailable} returns true. This method can also - * return null if autofill assistant is not available for some other reasons. - */ - public static DirectActionHandler createDirectActionHandler(Context context, - BottomSheetController bottomSheetController, - BrowserControlsStateProvider browserControls, View rootView, - ActivityTabProvider activityTabProvider) { - Supplier<WebContents> webContentsSupplier = () -> getWebContents(activityTabProvider); - - return new AutofillAssistantDirectActionHandler(context, bottomSheetController, - browserControls, rootView, activityTabProvider, webContentsSupplier, - AutofillAssistantModuleEntryProvider.INSTANCE); - } - /** Provides the callback with a tab, waits if necessary. */ private static void waitForTab(ChromeActivity activity, Callback<Tab> callback) { if (activity.getActivityTab() != null) {
diff --git a/chrome/android/features/autofill_assistant/public/java_sources.gni b/chrome/android/features/autofill_assistant/public/java_sources.gni index 141ee5c..4b1d91b 100644 --- a/chrome/android/features/autofill_assistant/public/java_sources.gni +++ b/chrome/android/features/autofill_assistant/public/java_sources.gni
@@ -22,7 +22,6 @@ "//chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantTabChangeObserverChrome.java", "//chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantTabObscuringUtilChrome.java", "//chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantTabUtilChrome.java", - "//chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandler.java", "//chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java", "//chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantHistoryDeletionObserver.java", "//chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTabHelper.java",
diff --git a/chrome/android/features/keyboard_accessory/BUILD.gn b/chrome/android/features/keyboard_accessory/BUILD.gn index 422c816f..b20d6fe 100644 --- a/chrome/android/features/keyboard_accessory/BUILD.gn +++ b/chrome/android/features/keyboard_accessory/BUILD.gn
@@ -61,6 +61,7 @@ "javatests/src/org/chromium/chrome/browser/keyboard_accessory/all_passwords_bottom_sheet/AllPasswordsBottomSheetIntegrationTest.java", "javatests/src/org/chromium/chrome/browser/keyboard_accessory/all_passwords_bottom_sheet/AllPasswordsBottomSheetViewTest.java", "javatests/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryModernViewTest.java", + "javatests/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryTestHelper.java", "javatests/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryViewTest.java", "javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_component/AccessorySheetRenderTest.java", "javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_component/AccessorySheetViewTest.java",
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingMediator.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingMediator.java index a51fd7b..60987a93 100644 --- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingMediator.java +++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingMediator.java
@@ -411,8 +411,8 @@ private void transitionIntoState(@KeyboardExtensionState int extensionState) { if (!meetsStatePreconditions(extensionState)) return; TraceEvent.begin("ManualFillingMediator#transitionIntoState"); - enforceStateProperties(extensionState); changeBottomControlSpaceForState(extensionState); + enforceStateProperties(extensionState); // Triggers a relayout. Call after changing insets. updateKeyboard(extensionState); TraceEvent.end("ManualFillingMediator#transitionIntoState"); } @@ -559,6 +559,11 @@ } } + @Override + public void onBarFadeInAnimationEnd() { + mActivity.getCurrentWebContents().scrollFocusedEditableNodeIntoView(); + } + /** * Opens the keyboard which implicitly dismisses the sheet. Without open sheet, this is a NoOp. */
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryCoordinator.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryCoordinator.java index c2a57423e..e70b07d 100644 --- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryCoordinator.java +++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryCoordinator.java
@@ -62,6 +62,12 @@ * Called when the sheet needs to be hidden. */ void onCloseAccessorySheet(); + + /** + * Signals that the accessory bar has completed the fade-in. This may be relevant to the + * keyboard extensions state to adjust the scroll position. + */ + void onBarFadeInAnimationEnd(); } /** @@ -245,6 +251,7 @@ * while the view might still be in progress of being updated accordingly. * @return True if the accessory should be visible, false otherwise. */ + // TODO(crbug/1385400): Hide because it's only used in tests. public boolean isShown() { return mMediator.isShown(); }
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryMediator.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryMediator.java index 6c08148..6f97991 100644 --- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryMediator.java +++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryMediator.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.keyboard_accessory.bar_component; +import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryProperties.ANIMATION_LISTENER; import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryProperties.BAR_ITEMS; import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryProperties.BOTTOM_OFFSET_PX; import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryProperties.DISABLE_ANIMATIONS_FOR_TESTING; @@ -73,6 +74,7 @@ mModel.set(OBFUSCATED_CHILD_AT_CALLBACK, this::onSuggestionObfuscatedAt); mModel.set(SHOW_KEYBOARD_CALLBACK, this::closeSheet); mModel.set(SHEET_OPENER_ITEM, new SheetOpenerBarItem(sheetOpenerCallbacks)); + mModel.set(ANIMATION_LISTENER, mVisibilityDelegate::onBarFadeInAnimationEnd); if (ChromeFeatureList.isEnabled(ChromeFeatureList.AUTOFILL_KEYBOARD_ACCESSORY)) { mModel.get(BAR_ITEMS).add(mModel.get(SHEET_OPENER_ITEM)); } @@ -275,7 +277,7 @@ || propertyKey == SKIP_CLOSING_ANIMATION || propertyKey == DISABLE_ANIMATIONS_FOR_TESTING || propertyKey == OBFUSCATED_CHILD_AT_CALLBACK || propertyKey == SHOW_SWIPING_IPH - || propertyKey == HAS_SUGGESTIONS) { + || propertyKey == HAS_SUGGESTIONS || propertyKey == ANIMATION_LISTENER) { return; } assert false : "Every property update needs to be handled explicitly!";
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryMetricsRecorder.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryMetricsRecorder.java index 36a06708..10ac0ca 100644 --- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryMetricsRecorder.java +++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryMetricsRecorder.java
@@ -78,7 +78,8 @@ || propertyKey == KeyboardAccessoryProperties.DISABLE_ANIMATIONS_FOR_TESTING || propertyKey == KeyboardAccessoryProperties.SHOW_SWIPING_IPH || propertyKey == KeyboardAccessoryProperties.OBFUSCATED_CHILD_AT_CALLBACK - || propertyKey == KeyboardAccessoryProperties.HAS_SUGGESTIONS) { + || propertyKey == KeyboardAccessoryProperties.HAS_SUGGESTIONS + || propertyKey == KeyboardAccessoryProperties.ANIMATION_LISTENER) { return; } assert false : "Every property update needs to be handled explicitly!";
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryModernViewBinder.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryModernViewBinder.java index 93c12a3..c12ee56b 100644 --- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryModernViewBinder.java +++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryModernViewBinder.java
@@ -13,12 +13,14 @@ import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryProperties.SHOW_KEYBOARD_CALLBACK; import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryProperties.SHOW_SWIPING_IPH; +import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.view.View; import android.view.ViewGroup; import org.chromium.base.TraceEvent; +import org.chromium.chrome.browser.autofill.AutofillUiUtils; import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.keyboard_accessory.R; import org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryProperties.AutofillBarItem; @@ -104,16 +106,19 @@ // the event that the bitmap is not present in the PersonalDataManager, fall back to the // default `iconId`. Bitmap customIconBitmap = null; + Resources res = chipView.getContext().getResources(); if (item.getSuggestion().getCustomIconUrl() != null && item.getSuggestion().getCustomIconUrl().isValid()) { - customIconBitmap = PersonalDataManager.getInstance() - .getCustomImageForAutofillSuggestionIfAvailable( - item.getSuggestion().getCustomIconUrl()); + customIconBitmap = + PersonalDataManager.getInstance().getCustomImageForAutofillSuggestionIfAvailable( + AutofillUiUtils.getCCIconURLWithParams( + item.getSuggestion().getCustomIconUrl(), + res.getDimensionPixelSize( + R.dimen.keyboard_accessory_bar_item_cc_icon_width), + res.getDimensionPixelSize(R.dimen.chip_icon_size))); } if (customIconBitmap != null) { - chipView.setIcon(new BitmapDrawable(mRootViewForIPH.getContext().getResources(), - customIconBitmap), - false); + chipView.setIcon(new BitmapDrawable(res, customIconBitmap), false); } else { chipView.setIcon(iconId != 0 ? iconId : ChipView.INVALID_ICON_ID, false); }
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryProperties.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryProperties.java index 74fceffd..164cbf6 100644 --- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryProperties.java +++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryProperties.java
@@ -56,12 +56,15 @@ static final WritableBooleanPropertyKey HAS_SUGGESTIONS = new WritableBooleanPropertyKey("has_suggestions"); + static final WritableObjectPropertyKey<KeyboardAccessoryView.AnimationListener> + ANIMATION_LISTENER = new WritableObjectPropertyKey<>("animation_listener"); + static PropertyModel.Builder defaultModelBuilder() { return new PropertyModel .Builder(DISABLE_ANIMATIONS_FOR_TESTING, BAR_ITEMS, VISIBLE, SKIP_CLOSING_ANIMATION, BOTTOM_OFFSET_PX, SHEET_OPENER_ITEM, KEYBOARD_TOGGLE_VISIBLE, SHEET_TITLE, SHOW_KEYBOARD_CALLBACK, OBFUSCATED_CHILD_AT_CALLBACK, SHOW_SWIPING_IPH, - HAS_SUGGESTIONS) + HAS_SUGGESTIONS, ANIMATION_LISTENER) .with(BAR_ITEMS, new ListModel<>()) .with(VISIBLE, false) .with(SKIP_CLOSING_ANIMATION, false)
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryView.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryView.java index 26b97a8..3e18e80 100644 --- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryView.java +++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryView.java
@@ -16,6 +16,7 @@ import android.widget.LinearLayout; import androidx.annotation.CallSuper; +import androidx.annotation.VisibleForTesting; import androidx.core.view.ViewCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -40,6 +41,16 @@ private boolean mShouldSkipClosingAnimation; private boolean mDisableAnimations; + /** Interface that allows to react to animations. */ + interface AnimationListener { + /** + * Called if the accessory bar stopped fading in. The fade-in only happens sometimes, e.g. + * if the bar is already visible or animations are disabled, this signal is not issued. + */ + void onFadeInEnd(); + } + private AnimationListener mAnimationListener; + protected static class HorizontalDividerItemDecoration extends RecyclerView.ItemDecoration { private final int mHorizontalMargin; @@ -133,6 +144,10 @@ mBarItemsView.setAdapter(adapter); } + void setAnimationListener(AnimationListener animationListener) { + mAnimationListener = animationListener; + } + /** Template method. Override to be notified if the bar items change. */ @CallSuper protected void onItemsChanged() {} @@ -140,7 +155,10 @@ private void show() { TraceEvent.begin("KeyboardAccessoryView#show"); bringToFront(); // Needs to overlay every component and the bottom sheet - like a keyboard. - if (mRunningAnimation != null) mRunningAnimation.cancel(); + if (mRunningAnimation != null) { + mRunningAnimation.cancel(); + mRunningAnimation = null; + } if (areAnimationsDisabled()) { mRunningAnimation = null; setVisibility(View.VISIBLE); @@ -151,13 +169,20 @@ .alpha(1f) .setDuration(FADE_ANIMATION_DURATION_MS) .setInterpolator(new AccelerateInterpolator()) - .withStartAction(() -> setVisibility(View.VISIBLE)); + .withStartAction(() -> setVisibility(View.VISIBLE)) + .withEndAction(() -> { + mAnimationListener.onFadeInEnd(); + mRunningAnimation = null; + }); announceForAccessibility(getContentDescription()); TraceEvent.end("KeyboardAccessoryView#show"); } private void hide() { - if (mRunningAnimation != null) mRunningAnimation.cancel(); + if (mRunningAnimation != null) { + mRunningAnimation.cancel(); + mRunningAnimation = null; + } if (mShouldSkipClosingAnimation || areAnimationsDisabled()) { mRunningAnimation = null; setVisibility(View.GONE); @@ -169,7 +194,10 @@ .setInterpolator(new AccelerateInterpolator()) .setStartDelay(HIDING_ANIMATION_DELAY_MS) .setDuration(FADE_ANIMATION_DURATION_MS - HIDING_ANIMATION_DELAY_MS) - .withEndAction(() -> setVisibility(View.GONE)); + .withEndAction(() -> { + setVisibility(View.GONE); + mRunningAnimation = null; + }); } void setSkipClosingAnimation(boolean shouldSkipClosingAnimation) { @@ -201,4 +229,9 @@ ViewCompat.setPaddingRelative(recyclerView, pad, 0, 0, 0); } + + @VisibleForTesting + boolean hasRunningAnimation() { + return mRunningAnimation != null; + } }
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryViewBinder.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryViewBinder.java index b9dedba..b233e1a 100644 --- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryViewBinder.java +++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryViewBinder.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.keyboard_accessory.bar_component; +import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryProperties.ANIMATION_LISTENER; import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryProperties.BAR_ITEMS; import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryProperties.BOTTOM_OFFSET_PX; import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryProperties.DISABLE_ANIMATIONS_FOR_TESTING; @@ -113,6 +114,8 @@ if (!model.get(VISIBLE)) view.setVisible(false); // Update to cancel any animation. } else if (propertyKey == BOTTOM_OFFSET_PX) { view.setBottomOffset(model.get(BOTTOM_OFFSET_PX)); + } else if (propertyKey == ANIMATION_LISTENER) { + view.setAnimationListener(model.get(ANIMATION_LISTENER)); } else if (propertyKey == SHOW_KEYBOARD_CALLBACK || propertyKey == KEYBOARD_TOGGLE_VISIBLE || propertyKey == SHEET_TITLE || propertyKey == SHEET_OPENER_ITEM || propertyKey == OBFUSCATED_CHILD_AT_CALLBACK || propertyKey == SHOW_SWIPING_IPH
diff --git a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/CreditCardAccessorySheetViewBinder.java b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/CreditCardAccessorySheetViewBinder.java index 73e2acae..711ecf2 100644 --- a/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/CreditCardAccessorySheetViewBinder.java +++ b/chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/CreditCardAccessorySheetViewBinder.java
@@ -3,6 +3,8 @@ // found in the LICENSE file. package org.chromium.chrome.browser.keyboard_accessory.sheet_tabs; + +import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.view.View; @@ -12,6 +14,7 @@ import androidx.appcompat.content.res.AppCompatResources; import androidx.recyclerview.widget.RecyclerView; +import org.chromium.chrome.browser.autofill.AutofillUiUtils; import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.keyboard_accessory.R; import org.chromium.chrome.browser.keyboard_accessory.data.KeyboardAccessoryData; @@ -78,13 +81,18 @@ // the event that the bitmap is not present in the PersonalDataManager, fall back to the // icon corresponding to the `mOrigin`. Bitmap iconBitmap = null; + Resources res = view.getContext().getResources(); if (info.getIconUrl() != null && info.getIconUrl().isValid()) { iconBitmap = - PersonalDataManager.getInstance() - .getCustomImageForAutofillSuggestionIfAvailable(info.getIconUrl()); + PersonalDataManager.getInstance().getCustomImageForAutofillSuggestionIfAvailable( + AutofillUiUtils.getCCIconURLWithParams(info.getIconUrl(), + res.getDimensionPixelSize( + R.dimen.keyboard_accessory_bar_item_cc_icon_width), + res.getDimensionPixelSize( + R.dimen.keyboard_accessory_suggestion_icon_size))); } if (iconBitmap != null) { - view.setIcon(new BitmapDrawable(view.getContext().getResources(), iconBitmap)); + view.setIcon(new BitmapDrawable(res, iconBitmap)); } else { view.setIcon(AppCompatResources.getDrawable( view.getContext(), getDrawableForOrigin(info.getOrigin())));
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingIntegrationTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingIntegrationTest.java index 5f3f7e7..9e1147a 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingIntegrationTest.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingIntegrationTest.java
@@ -8,6 +8,8 @@ import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItem; +import static androidx.test.espresso.contrib.RecyclerViewActions.scrollTo; import static androidx.test.espresso.matcher.ViewMatchers.assertThat; import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; @@ -15,12 +17,12 @@ import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertNotNull; import static org.chromium.chrome.browser.keyboard_accessory.ManualFillingTestHelper.selectTabAtPosition; +import static org.chromium.chrome.browser.keyboard_accessory.ManualFillingTestHelper.selectTabWithDescription; import static org.chromium.chrome.browser.keyboard_accessory.ManualFillingTestHelper.waitToBeHidden; import static org.chromium.chrome.browser.keyboard_accessory.ManualFillingTestHelper.whenDisplayed; import static org.chromium.chrome.browser.keyboard_accessory.tab_layout_component.KeyboardAccessoryTabTestHelper.isKeyboardAccessoryTabLayout; @@ -138,8 +140,11 @@ onView(withChild(withId(R.id.keyboard_accessory_sheet))).check(doesNotExist()); // Trigger the sheet and wait for it to open and the keyboard to disappear. - onView(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(withId(R.id.bar_items_view)) + .perform(scrollTo(isKeyboardAccessoryTabLayout()), + actionOnItem(isKeyboardAccessoryTabLayout(), + selectTabWithDescription( + R.string.password_accessory_sheet_toggle))); mHelper.waitForKeyboardToDisappear(); whenDisplayed(withChild(withId(R.id.keyboard_accessory_sheet))); } @@ -182,8 +187,11 @@ onView(withChild(withId(R.id.keyboard_accessory_sheet))).check(doesNotExist()); // Trigger the sheet and wait for it to open and the keyboard to disappear. - onView(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(withId(R.id.bar_items_view)) + .perform(scrollTo(isKeyboardAccessoryTabLayout()), + actionOnItem(isKeyboardAccessoryTabLayout(), + selectTabWithDescription( + R.string.password_accessory_sheet_toggle))); mHelper.waitForKeyboardToDisappear(); whenDisplayed(withChild(withId(R.id.keyboard_accessory_sheet))).check((view, e) -> { accessorySheetView.set(view); @@ -236,14 +244,12 @@ mHelper.waitForKeyboardAccessoryToBeShown(); // Click the tab to show the sheet and hide the keyboard. - whenDisplayed(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(isKeyboardAccessoryTabLayout()).perform(selectTabAtPosition(0)); mHelper.waitForKeyboardToDisappear(); whenDisplayed(withChild(withId(R.id.keyboard_accessory_sheet))); // Click the tab again to hide the sheet and show the keyboard. - onView(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(isKeyboardAccessoryTabLayout()).perform(selectTabAtPosition(0)); mHelper.waitForKeyboardAccessoryToBeShown(); onView(withId(R.id.keyboard_accessory)).check(matches(isDisplayed())); waitToBeHidden(withChild(withId(R.id.keyboard_accessory_sheet))); @@ -262,7 +268,7 @@ // Focus the password field to bring up the accessory. mHelper.focusPasswordField(); mHelper.waitForKeyboardAccessoryToBeShown(); - whenDisplayed(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())); + whenDisplayed(isKeyboardAccessoryTabLayout()); // Clicking a field without completion hides the accessory again. mHelper.clickFieldWithoutCompletion(); @@ -280,8 +286,11 @@ mHelper.waitForKeyboardAccessoryToBeShown(); // Click the tab to show the sheet and hide the keyboard. - whenDisplayed(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(withId(R.id.bar_items_view)) + .perform(scrollTo(isKeyboardAccessoryTabLayout()), + actionOnItem(isKeyboardAccessoryTabLayout(), + selectTabWithDescription( + R.string.password_accessory_sheet_toggle))); mHelper.waitForKeyboardToDisappear(); whenDisplayed(withChild(withId(R.id.keyboard_accessory_sheet))); @@ -304,8 +313,11 @@ mHelper.waitForKeyboardAccessoryToBeShown(); // Click the tab to show the sheet and hide the keyboard. - whenDisplayed(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(withId(R.id.bar_items_view)) + .perform(scrollTo(isKeyboardAccessoryTabLayout()), + actionOnItem(isKeyboardAccessoryTabLayout(), + selectTabWithDescription( + R.string.password_accessory_sheet_toggle))); mHelper.waitForKeyboardToDisappear(); whenDisplayed(withChild(withId(R.id.keyboard_accessory_sheet))); @@ -327,8 +339,11 @@ mHelper.waitForKeyboardAccessoryToBeShown(); // Click the tab to show the sheet and hide the keyboard. - whenDisplayed(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(withId(R.id.bar_items_view)) + .perform(scrollTo(isKeyboardAccessoryTabLayout()), + actionOnItem(isKeyboardAccessoryTabLayout(), + selectTabWithDescription( + R.string.password_accessory_sheet_toggle))); mHelper.waitForKeyboardToDisappear(); whenDisplayed(withChild(withId(R.id.keyboard_accessory_sheet))); } @@ -347,8 +362,11 @@ mHelper.waitForKeyboardAccessoryToBeShown(); // Click the tab to show the sheet and hide the keyboard. - whenDisplayed(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(withId(R.id.bar_items_view)) + .perform(scrollTo(isKeyboardAccessoryTabLayout()), + actionOnItem(isKeyboardAccessoryTabLayout(), + selectTabWithDescription( + R.string.password_accessory_sheet_toggle))); mHelper.waitForKeyboardToDisappear(); whenDisplayed(withChild(withId(R.id.keyboard_accessory_sheet))); @@ -429,8 +447,11 @@ assertThat(mActivityTestRule.getInfoBarContainer().getVisibility(), is(not(View.VISIBLE))); // Click the tab to show the sheet and hide the keyboard. - whenDisplayed(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(withId(R.id.bar_items_view)) + .perform(scrollTo(isKeyboardAccessoryTabLayout()), + actionOnItem(isKeyboardAccessoryTabLayout(), + selectTabWithDescription( + R.string.password_accessory_sheet_toggle))); mHelper.waitForKeyboardToDisappear(); whenDisplayed(withChild(withId(R.id.keyboard_accessory_sheet))); assertThat(mActivityTestRule.getInfoBarContainer().getVisibility(), is(not(View.VISIBLE))); @@ -479,8 +500,11 @@ onView(withText(kSnackbarText)).check(matches(isCompletelyDisplayed())); // Open a keyboard accessory sheet -- this also shouldn't hide the snackbar. - whenDisplayed(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(withId(R.id.bar_items_view)) + .perform(scrollTo(isKeyboardAccessoryTabLayout()), + actionOnItem(isKeyboardAccessoryTabLayout(), + selectTabWithDescription( + R.string.password_accessory_sheet_toggle))); whenDisplayed(withChild(withId(R.id.keyboard_accessory_sheet))); onView(withText(kSnackbarText)).check(matches(isCompletelyDisplayed())); @@ -516,8 +540,11 @@ // Focus the field to bring up the accessory. mHelper.focusPasswordField(); mHelper.waitForKeyboardAccessoryToBeShown(); - whenDisplayed(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(withId(R.id.bar_items_view)) + .perform(scrollTo(isKeyboardAccessoryTabLayout()), + actionOnItem(isKeyboardAccessoryTabLayout(), + selectTabWithDescription( + R.string.password_accessory_sheet_toggle))); whenDisplayed(withChild(withId(R.id.keyboard_accessory_sheet))); assertThat(mActivityTestRule.getInfoBarContainer().getVisibility(), is(not(View.VISIBLE)));
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java index 8807c2c..4ea31d2d 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java
@@ -12,6 +12,12 @@ import static org.hamcrest.core.AllOf.allOf; import static org.chromium.autofill.mojom.FocusedFieldType.FILLABLE_NON_SEARCH_FIELD; +import static org.chromium.base.test.util.CriteriaHelper.pollInstrumentationThread; +import static org.chromium.base.test.util.CriteriaHelper.pollUiThread; +import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryTestHelper.accessoryStartedHiding; +import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryTestHelper.accessoryStartedShowing; +import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryTestHelper.accessoryViewFullyHidden; +import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryTestHelper.accessoryViewFullyShown; import static org.chromium.chrome.browser.keyboard_accessory.tab_layout_component.KeyboardAccessoryTabTestHelper.isKeyboardAccessoryTabLayout; import static org.chromium.ui.base.LocalizationUtils.setRtlForTesting; import static org.chromium.ui.test.util.ViewUtils.VIEW_GONE; @@ -37,7 +43,6 @@ import com.google.android.material.tabs.TabLayout; -import org.chromium.ui.widget.ChromeImageButton; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.Matchers; @@ -45,7 +50,6 @@ import org.chromium.base.task.PostTask; import org.chromium.base.test.util.Criteria; -import org.chromium.base.test.util.CriteriaHelper; import org.chromium.chrome.browser.ChromeWindow; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.autofill.AutofillTestHelper; @@ -69,6 +73,7 @@ import org.chromium.net.test.EmbeddedTestServer; import org.chromium.net.test.ServerCertificate; import org.chromium.ui.DropdownPopupWindowInterface; +import org.chromium.ui.widget.ChromeImageButton; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; @@ -239,7 +244,7 @@ // --------------------------------- public void waitForKeyboardToDisappear() { - CriteriaHelper.pollUiThread(() -> { + pollUiThread(() -> { Activity activity = mActivityTestRule.getActivity(); return !getKeyboard().isAndroidSoftKeyboardShowing( activity, activity.getCurrentFocus()); @@ -247,15 +252,8 @@ } public void waitForKeyboardAccessoryToDisappear() { - CriteriaHelper.pollInstrumentationThread(() -> { - KeyboardAccessoryCoordinator accessory = - getManualFillingCoordinator().getMediatorForTesting().getKeyboardAccessory(); - return accessory != null && !accessory.isShown(); - }); - CriteriaHelper.pollUiThread(() -> { - View accessory = mActivityTestRule.getActivity().findViewById(R.id.keyboard_accessory); - return accessory != null && !accessory.isShown(); - }); + pollInstrumentationThread(() -> accessoryStartedHiding(getKeyboardAccessoryBar())); + pollUiThread(() -> accessoryViewFullyHidden(mActivityTestRule.getActivity())); } public void waitForKeyboardAccessoryToBeShown() { @@ -263,19 +261,12 @@ } public void waitForKeyboardAccessoryToBeShown(boolean waitForSuggestionsToLoad) { - CriteriaHelper.pollInstrumentationThread(() -> { - KeyboardAccessoryCoordinator accessory = - getManualFillingCoordinator().getMediatorForTesting().getKeyboardAccessory(); - return accessory != null && accessory.isShown(); - }); - CriteriaHelper.pollUiThread(() -> { - View accessory = mActivityTestRule.getActivity().findViewById(R.id.keyboard_accessory); - return accessory != null && accessory.isShown(); - }); + pollInstrumentationThread(() -> accessoryStartedShowing(getKeyboardAccessoryBar())); + pollUiThread(() -> accessoryViewFullyShown(mActivityTestRule.getActivity())); if (waitForSuggestionsToLoad) { - CriteriaHelper.pollUiThread(() - -> getFirstAccessorySuggestion() != null, - "Waited for suggestions that never appeared."); + pollUiThread(() -> { + return getFirstAccessorySuggestion() != null; + }, "Waited for suggestions that never appeared."); } } @@ -284,14 +275,14 @@ final View view = webContents.getViewAndroidDelegate().getContainerView(); // Wait for InputConnection to be ready and fill the filterInput. Then wait for the anchor. - CriteriaHelper.pollUiThread(() -> { + pollUiThread(() -> { Criteria.checkThat( mInputMethodManagerWrapper.getShowSoftInputCounter(), Matchers.is(1)); }); TestThreadUtils.runOnUiThreadBlocking(() -> { ImeAdapter.fromWebContents(webContents).setComposingTextForTest(filterInput, 4); }); - CriteriaHelper.pollUiThread(() -> { + pollUiThread(() -> { Criteria.checkThat("Autofill Popup anchor view was never added.", view.findViewById(R.id.dropdown_popup_window), Matchers.notNullValue()); }); @@ -300,7 +291,7 @@ Assert.assertTrue(anchorView.getTag() instanceof DropdownPopupWindowInterface); final DropdownPopupWindowInterface popup = (DropdownPopupWindowInterface) anchorView.getTag(); - CriteriaHelper.pollUiThread(() -> { + pollUiThread(() -> { Criteria.checkThat(popup.isShowing(), Matchers.is(true)); Criteria.checkThat(popup.getListView(), Matchers.notNullValue()); Criteria.checkThat(popup.getListView().getHeight(), Matchers.not(0)); @@ -326,6 +317,10 @@ .getOrCreateSheet(mWebContentsRef.get(), AccessoryTabType.CREDIT_CARDS); } + private KeyboardAccessoryCoordinator getKeyboardAccessoryBar() { + return getManualFillingCoordinator().getMediatorForTesting().getKeyboardAccessory(); + } + // ---------------------------------- // Helpers to set up the native side. // ---------------------------------- @@ -444,7 +439,7 @@ return new ViewAction() { @Override public Matcher<View> getConstraints() { - return allOf(isDisplayed(), isAssignableFrom(TabLayout.class)); + return allOf(isDisplayed(), isKeyboardAccessoryTabLayout()); } @Override
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryTestHelper.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryTestHelper.java new file mode 100644 index 0000000..6b9fac7 --- /dev/null +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryTestHelper.java
@@ -0,0 +1,60 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.keyboard_accessory.bar_component; + +import android.app.Activity; + +import org.chromium.chrome.browser.keyboard_accessory.R; + +/** + * Helpers in this class simplify interactions with the Keyboard Accessory bar component. + */ +public class KeyboardAccessoryTestHelper { + /** + * Returns true if the accessory becomes visible. It is not guaranteed that the view reflects + * this state already. Use {@link #accessoryViewFullyShown(Activity)} for that. + * + * @param accessory An {@link KeyboardAccessoryCoordinator} + * @return True iff the component was ordered to show. + */ + public static boolean accessoryStartedShowing(KeyboardAccessoryCoordinator accessory) { + return accessory != null && accessory.isShown(); + } + + /** + * Returns true if the accessory starts hiding. It is not guaranteed that the view reflects this + * state already. Use {@link #accessoryViewFullyHidden(Activity)} (Activity)} for that. + * + * @param accessory An {@link KeyboardAccessoryCoordinator} + * @return True iff the component was ordered to hide. + */ + public static boolean accessoryStartedHiding(KeyboardAccessoryCoordinator accessory) { + return accessory != null && !accessory.isShown(); + } + + /** + * Helper that finds the accessory bar and checks whether it's shown. Returns false until + * animations have concluded. + * + * @param activity The {@link Activity} containing the accessory bar. + * @return True iff the bar view is visible and animations have ended. + */ + public static boolean accessoryViewFullyShown(Activity activity) { + KeyboardAccessoryView accessory = activity.findViewById(R.id.keyboard_accessory); + return accessory != null && accessory.isShown() && !accessory.hasRunningAnimation(); + } + + /** + * Helper that finds the accessory bar and checks whether it's hidden. Returns false until + * animations have concluded. + * + * @param activity The {@link Activity} containing the accessory bar. + * @return True iff the bar view is hidden and animations have ended. + */ + public static boolean accessoryViewFullyHidden(Activity activity) { + KeyboardAccessoryView accessory = activity.findViewById(R.id.keyboard_accessory); + return accessory == null || (!accessory.isShown() && !accessory.hasRunningAnimation()); + } +}
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/CreditCardAccessoryIntegrationTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/CreditCardAccessoryIntegrationTest.java index ac09334..eec8da98 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/CreditCardAccessoryIntegrationTest.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/CreditCardAccessoryIntegrationTest.java
@@ -9,22 +9,16 @@ import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItem; import static androidx.test.espresso.contrib.RecyclerViewActions.scrollTo; -import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.not; -import static org.chromium.chrome.browser.keyboard_accessory.ManualFillingTestHelper.selectTabAtPosition; +import static org.chromium.chrome.browser.keyboard_accessory.ManualFillingTestHelper.selectTabWithDescription; import static org.chromium.chrome.browser.keyboard_accessory.ManualFillingTestHelper.whenDisplayed; import static org.chromium.chrome.browser.keyboard_accessory.tab_layout_component.KeyboardAccessoryTabTestHelper.isKeyboardAccessoryTabLayout; -import android.widget.TextView; - import androidx.test.filters.MediumTest; import androidx.test.filters.SmallTest; @@ -136,9 +130,12 @@ mHelper.waitForKeyboardAccessoryToBeShown(); // Click the tab to show the sheet and hide the keyboard. - whenDisplayed(allOf(withContentDescription(R.string.credit_card_accessory_sheet_toggle), - not(isAssignableFrom(TextView.class)))) - .perform(click()); + whenDisplayed(withId(R.id.bar_items_view)) + .perform(scrollTo(isKeyboardAccessoryTabLayout()), + actionOnItem(isKeyboardAccessoryTabLayout(), + selectTabWithDescription( + R.string.credit_card_accessory_sheet_toggle))); + mHelper.waitForKeyboardToDisappear(); whenDisplayed(withId(R.id.credit_card_sheet)); onView(withText(containsString("No saved payment methods"))).check(matches(isDisplayed())); @@ -157,7 +154,9 @@ // Scroll to last element and click the first icon: whenDisplayed(withId(R.id.bar_items_view)) .perform(scrollTo(isKeyboardAccessoryTabLayout()), - actionOnItem(isKeyboardAccessoryTabLayout(), selectTabAtPosition(0))); + actionOnItem(isKeyboardAccessoryTabLayout(), + selectTabWithDescription( + R.string.credit_card_accessory_sheet_toggle))); // Wait for the sheet to come up and be stable. whenDisplayed(withId(R.id.credit_card_sheet));
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java index 4646e41f..7281b4a 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java
@@ -14,7 +14,6 @@ import static androidx.test.espresso.matcher.ViewMatchers.withText; import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.core.AllOf.allOf; import static org.chromium.chrome.browser.keyboard_accessory.ManualFillingTestHelper.isTransformed; import static org.chromium.chrome.browser.keyboard_accessory.ManualFillingTestHelper.scrollToLastElement; @@ -88,8 +87,7 @@ // Focus the field to bring up the accessory. mHelper.focusPasswordField(); mHelper.waitForKeyboardAccessoryToBeShown(); - whenDisplayed(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(isKeyboardAccessoryTabLayout()).perform(selectTabAtPosition(0)); // Check that the provided elements are there. whenDisplayed(withText("mayapark@gmail.com")); @@ -109,8 +107,7 @@ // Focus the field to bring up the accessory. mHelper.focusPasswordField(); mHelper.waitForKeyboardAccessoryToBeShown(); - whenDisplayed(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(isKeyboardAccessoryTabLayout()).perform(selectTabAtPosition(0)); mHelper.waitForKeyboardToDisappear(); whenDisplayed(withId(R.id.passwords_sheet)).perform(scrollToLastElement()); @@ -127,8 +124,7 @@ // Focus the field to bring up the accessory. mHelper.focusPasswordField(); mHelper.waitForKeyboardAccessoryToBeShown(); - whenDisplayed(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(isKeyboardAccessoryTabLayout()).perform(selectTabAtPosition(0)); // Click the suggestion. whenDisplayed(withText("ShorterPassword")).perform(click()); @@ -154,8 +150,7 @@ mHelper.waitForKeyboardAccessoryToBeShown(); // Click the tab to show the sheet and hide the keyboard. - whenDisplayed(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(isKeyboardAccessoryTabLayout()).perform(selectTabAtPosition(0)); mHelper.waitForKeyboardToDisappear(); whenDisplayed(withId(R.id.passwords_sheet)); onView(withText(containsString("No saved passwords"))).check(matches(isDisplayed())); @@ -166,15 +161,14 @@ @EnableFeatures({ChromeFeatureList.RECOVER_FROM_NEVER_SAVE_ANDROID, ChromeFeatureList.AUTOFILL_KEYBOARD_ACCESSORY}) public void - testEnablesUndenylistingToggle() throws TimeoutException { + testEnablesUndenylistingToggle() throws TimeoutException, InterruptedException { mHelper.loadTestPage(false); mHelper.cacheCredentials(new String[0], new String[0], true); // Focus the field to bring up the accessory. mHelper.focusPasswordField(); mHelper.waitForKeyboardAccessoryToBeShown(); - whenDisplayed(allOf(isDisplayed(), isKeyboardAccessoryTabLayout())) - .perform(selectTabAtPosition(0)); + whenDisplayed(isKeyboardAccessoryTabLayout()).perform(selectTabAtPosition(0)); whenDisplayed(withId(R.id.option_toggle_switch)).check(matches(isNotChecked())); onView(withId(R.id.option_toggle_subtitle)).check(matches(withText(R.string.text_off)));
diff --git a/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java b/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java index 8eb920c7..96137b6 100644 --- a/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java +++ b/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java
@@ -1116,6 +1116,12 @@ } @Test + public void testScrollsPageUpAfterBarIsFullyShown() { + mMediator.onBarFadeInAnimationEnd(); + verify(mLastMockWebContents).scrollFocusedEditableNodeIntoView(); + } + + @Test public void testShowAccessorySheetTab() { // Prepare a tab and register a new tab, so there is a reason to display the bar. addBrowserTab(mMediator, 1111, null);
diff --git a/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryControllerTest.java b/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryControllerTest.java index b87eede7..e6c2c8a 100644 --- a/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryControllerTest.java +++ b/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryControllerTest.java
@@ -18,6 +18,7 @@ import static org.chromium.chrome.browser.keyboard_accessory.AccessoryAction.AUTOFILL_SUGGESTION; import static org.chromium.chrome.browser.keyboard_accessory.AccessoryAction.GENERATE_PASSWORD_AUTOMATIC; +import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryProperties.ANIMATION_LISTENER; import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryProperties.BAR_ITEMS; import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryProperties.HAS_SUGGESTIONS; import static org.chromium.chrome.browser.keyboard_accessory.bar_component.KeyboardAccessoryProperties.OBFUSCATED_CHILD_AT_CALLBACK; @@ -585,6 +586,12 @@ assertThat(mModel.get(HAS_SUGGESTIONS), is(false)); } + @Test + public void testFowardsAnimationEventsToVisibilityDelegate() { + mModel.get(ANIMATION_LISTENER).onFadeInEnd(); + verify(mMockVisibilityDelegate).onBarFadeInAnimationEnd(); + } + private int getGenerationImpressionCount() { return RecordHistogram.getHistogramValueCountForTesting( ManualFillingMetricsRecorder.UMA_KEYBOARD_ACCESSORY_ACTION_IMPRESSION,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java index c12ede7..adaa2831 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java
@@ -196,11 +196,10 @@ * it'd be preferred over the iconId. */ @CalledByNative - private static void addToAutofillSuggestionArray(AutofillSuggestion[] array, int index, - String label, String secondaryLabel, String sublabel, String secondarySublabel, - String itemTag, int iconId, boolean isIconAtStart, int suggestionId, - boolean isDeletable, boolean isLabelMultiline, boolean isLabelBold, - GURL customIconUrl) { + private void addToAutofillSuggestionArray(AutofillSuggestion[] array, int index, String label, + String secondaryLabel, String sublabel, String secondarySublabel, String itemTag, + int iconId, boolean isIconAtStart, int suggestionId, boolean isDeletable, + boolean isLabelMultiline, boolean isLabelBold, GURL customIconUrl) { int drawableId = iconId == 0 ? DropdownItem.NO_ICON : iconId; AutofillSuggestion.Builder builder = new AutofillSuggestion.Builder() .setLabel(label) @@ -214,10 +213,15 @@ .setIsDeletable(isDeletable) .setIsMultiLineLabel(isLabelMultiline) .setIsBoldLabel(isLabelBold); - if (customIconUrl != null) { + if (customIconUrl != null && customIconUrl.isValid()) { builder.setCustomIcon( PersonalDataManager.getInstance() - .getCustomImageForAutofillSuggestionIfAvailable(customIconUrl)); + .getCustomImageForAutofillSuggestionIfAvailable( + AutofillUiUtils.getCCIconURLWithParams(customIconUrl, + mContext.getResources().getDimensionPixelSize( + R.dimen.autofill_dropdown_icon_width), + mContext.getResources().getDimensionPixelSize( + R.dimen.autofill_dropdown_icon_height)))); } array[index] = builder.build(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java index 122dd84..78d90ba 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java
@@ -28,6 +28,7 @@ import android.widget.TextView; import androidx.annotation.IntDef; +import androidx.annotation.Px; import androidx.annotation.VisibleForTesting; import androidx.core.content.res.ResourcesCompat; import androidx.core.widget.TextViewCompat; @@ -40,6 +41,7 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.ui.text.NoUnderlineClickableSpan; import org.chromium.ui.text.SpanApplier; +import org.chromium.url.GURL; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -434,4 +436,29 @@ new NoUnderlineClickableSpan( context, view -> onClickCallback.onResult(url)))); } + + /** + * Adds dimension params to card art URL for credit cards. + * @param customIconURL A FIFE URL to fetch the card art icon. + * @param width in pixels. + * @param height in pixels. + * @return {@link GURL} formatted with the icon dimensions to fetch the card art icon. + */ + public static GURL getCCIconURLWithParams(GURL customIconURL, @Px int width, @Px int height) { + // TODO(crbug.com/1313616): There is only one gstatic card art image we are using currently. + // Remove this logic and append FIFE URL suffix by default when the static image is + // deprecated. + // Check if the image is gstatic stored in Static Content Service. If not append the + // dimension params to the FIFE URL. + if (customIconURL.getSpec().equals( + "https://www.gstatic.com/autofill/virtualcard/icon/capitalone.png")) { + return customIconURL; + } + // Params can be added to a FIFE URL by appending them at the end like URL[=params]. "w" + // option is used to set the width in pixels, "h" is used to set the height in pixels, + // and "n" represents center cropping the image. + StringBuilder url = new StringBuilder(customIconURL.getSpec()); + url.append("=w").append(width).append("-h").append(height).append("-n"); + return new GURL(url.toString()); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java index 9942fb1..ccea071 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java
@@ -6,6 +6,11 @@ import android.content.Context; import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PorterDuff.Mode; +import android.graphics.PorterDuffColorFilter; import android.text.format.DateUtils; import androidx.annotation.VisibleForTesting; @@ -1348,6 +1353,7 @@ return UserPrefs.get(Profile.getLastUsedRegularProfile()); } + // TODO (crbug.com/1384128): Add icon dimensions to card art URL. private void fetchCreditCardArtImages() { for (CreditCard card : getCreditCardsToSuggest(/*includeServerCards= */ true)) { // Fetch the image using the ImageFetcher only if it is not present in the cache. @@ -1360,7 +1366,7 @@ } /** - * Return the card art image for the given `cardArtUrl`. + * Return the card art image for the given `customImageUrl`. * * @param customImageUrl URL of the image. If the image is available, it is returned, otherwise * it is fetched from this URL. @@ -1372,8 +1378,23 @@ } // Schedule the fetching of image and return null so that the UI thread does not have to // wait and can show the default network icon. - fetchImage(customImageUrl, - bitmap -> mCreditCardArtImages.put(customImageUrl.getSpec(), bitmap)); + fetchImage(customImageUrl, bitmap -> { + // Create an empty mutable bitmap and set it in a canvas. + Bitmap cardArtImageWithGrayOverlay = Bitmap.createBitmap( + bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(cardArtImageWithGrayOverlay); + + // Create a gray paint with 4% opacity. + Paint paint = new Paint(); + paint.setColorFilter(new PorterDuffColorFilter( + Color.argb(/* alpha= */ 10, /* red= */ 68, /* green= */ 68, /* blue= */ 68), + Mode.DARKEN)); + + // Add the icon and the 4% gray overlay. + canvas.drawBitmap( + /* bitmap= */ bitmap, /* left= */ 0, /* top= */ 0, /* paint= */ paint); + mCreditCardArtImages.put(customImageUrl.getSpec(), cardArtImageWithGrayOverlay); + }); return null; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/ForeignSessionHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/ForeignSessionHelper.java index 0228c1c..1f5e797 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/ForeignSessionHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/ForeignSessionHelper.java
@@ -39,26 +39,14 @@ * Represents synced foreign session. */ static class ForeignSession { - // Please keep in sync with components/sync/protocol/sync_enums.proto. - static final int DEVICE_TYPE_UNSET = 0; - static final int DEVICE_TYPE_WIN = 1; - static final int DEVICE_TYPE_MACOSX = 2; - static final int DEVICE_TYPE_LINUX = 3; - static final int DEVICE_TYPE_CHROMEOS = 4; - static final int DEVICE_TYPE_OTHER = 5; - static final int DEVICE_TYPE_PHONE = 6; - static final int DEVICE_TYPE_TABLET = 7; - public final String tag; public final String name; - public final int deviceType; public final long modifiedTime; public final List<ForeignSessionWindow> windows = new ArrayList<ForeignSessionWindow>(); - private ForeignSession(String tag, String name, int deviceType, long modifiedTime) { + private ForeignSession(String tag, String name, long modifiedTime) { this.tag = tag; this.name = name; - this.deviceType = deviceType; this.modifiedTime = modifiedTime; } } @@ -97,9 +85,8 @@ @CalledByNative private static ForeignSession pushSession( - List<ForeignSession> sessions, String tag, String name, int deviceType, - long modifiedTime) { - ForeignSession session = new ForeignSession(tag, name, deviceType, modifiedTime); + List<ForeignSession> sessions, String tag, String name, long modifiedTime) { + ForeignSession session = new ForeignSession(tag, name, modifiedTime); sessions.add(session); return session; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java index 495a488..65abd22 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java
@@ -11,7 +11,6 @@ import androidx.annotation.ColorInt; import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.CallbackController; @@ -83,6 +82,7 @@ private final @ColorInt int mStandardDefaultThemeColor; private final @ColorInt int mIncognitoDefaultThemeColor; private final @ColorInt int mActiveOmniboxDefaultColor; + private @ColorInt int mToolbarColor; private @Nullable TabModelSelector mTabModelSelector; private CallbackController mCallbackController = new CallbackController(); @@ -91,6 +91,7 @@ private boolean mIsInOverviewMode; private boolean mIsIncognito; private boolean mIsOmniboxFocused; + private boolean mToolbarAnimationInProgress; private @ColorInt int mScrimColor; private float mStatusBarScrimFraction; @@ -142,14 +143,7 @@ @Override public void onDidChangeThemeColor(Tab tab, int color) { - if (OmniboxFeatures.shouldMatchToolbarAndStatusBarColor()) { - // The theme color change assignment will override the feature flag which - // matches the toolbar and the status bar color, specifically for custom tabs - // with theme colors. - updateStatusBarColor(color); - } else { - updateStatusBarColor(); - } + updateStatusBarColor(); } @Override @@ -249,8 +243,9 @@ // TopToolbarCoordinator.UrlExpansionObserver implementation. @Override - public void onUrlExpansionProgressChanged(float fraction) { + public void onUrlExpansionProgressChanged(float fraction, boolean changeInProgress) { mToolbarUrlExpansionPercentage = fraction; + mToolbarAnimationInProgress = changeInProgress; if (mShouldUpdateStatusBarColorForNTP) updateStatusBarColor(); } @@ -266,8 +261,8 @@ return; } - // The status indicator will override the toolbar color match if available. - updateStatusBarColor(color); + mToolbarColor = color; + updateStatusBarColor(); } // StatusIndicatorCoordinator.StatusIndicatorObserver implementation. @@ -275,13 +270,7 @@ @Override public void onStatusIndicatorColorChanged(@ColorInt int newColor) { mStatusIndicatorColor = newColor; - if (OmniboxFeatures.shouldMatchToolbarAndStatusBarColor()) { - // The status indicator color assignment will override the feature flag which matches - // the toolbar and the status bar color. - updateStatusBarColor(calculateBaseStatusBarColor()); - } else { - updateStatusBarColor(); - } + updateStatusBarColor(); } @Override @@ -296,13 +285,7 @@ */ public void setStatusBarScrimFraction(float fraction) { mStatusBarScrimFraction = fraction; - if (OmniboxFeatures.shouldMatchToolbarAndStatusBarColor()) { - // The scrim fraction color assignment will override the feature flag which matches - // the toolbar and the status bar color. - updateStatusBarColor(calculateBaseStatusBarColor()); - } else { - updateStatusBarColor(); - } + updateStatusBarColor(); } /** @@ -319,22 +302,7 @@ * Calculate and update the status bar's color. */ public void updateStatusBarColor() { - // We will synchronize the status bar's color with toolbar's color if the feature flag is - // toggled, so we skip the original color assignment here. - if (OmniboxFeatures.shouldMatchToolbarAndStatusBarColor()) { - return; - } - updateStatusBarColor(calculateBaseStatusBarColor()); - } - - /** - * Update the status bar's color with provided color. - * @param color The color to be applied to status bar. - */ - @VisibleForTesting - public void updateStatusBarColor(@ColorInt int color) { - mStatusBarColorWithoutStatusIndicator = color; - + mStatusBarColorWithoutStatusIndicator = calculateBaseStatusBarColor(); int statusBarColor = applyStatusBarIndicatorColor(mStatusBarColorWithoutStatusIndicator); statusBarColor = applyCurrentScrimToColor(statusBarColor); setStatusBarColor(mWindow, statusBarColor); @@ -365,7 +333,14 @@ // When Omnibox gains focus, we want to clear the status bar theme color. // The theme should be restored when Omnibox focus clears. - if (mIsOmniboxFocused) return calculateDefaultStatusBarColor(); + if (mIsOmniboxFocused) { + // If the flag is enabled, we will use the toolbar color. + if (OmniboxFeatures.shouldMatchToolbarAndStatusBarColor() + && mToolbarAnimationInProgress) { + return mToolbarColor; + } + return calculateDefaultStatusBarColor(); + } // Return status bar color in overview mode. if (mIsInOverviewMode) { @@ -384,6 +359,10 @@ } // Return status bar color to match the toolbar. + // If the flag is enabled, we will use the toolbar color. + if (OmniboxFeatures.shouldMatchToolbarAndStatusBarColor() && mToolbarAnimationInProgress) { + return mToolbarColor; + } return mTopUiThemeColor.getThemeColorOrFallback( mCurrentTab, calculateDefaultStatusBarColor()); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkTest.java index b37b8714..edcde3b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkTest.java
@@ -271,7 +271,6 @@ @Test @SmallTest - @DisabledTest(message = "crbug.com/1385530") public void testAddBookmark() throws Exception { mActivityTestRule.loadUrl(mTestPage); // Check partner bookmarks are lazily loaded. @@ -1161,7 +1160,6 @@ @Test @MediumTest - @DisabledTest(message = "crbug.com/1385530") public void testMoveButtonsGoneForPartnerBookmarks() throws Exception { loadFakePartnerBookmarkShimForTesting(); BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.NO_PROMO);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java index 52f5958..f13bc23 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java
@@ -229,6 +229,31 @@ @Test @SmallTest @Feature({"Autofill"}) + public void testCreditCardArtURLIsFormattedWithImageSpecs() throws TimeoutException { + GURL virtualCardIconURL = + new GURL("https://www.gstatic.com/autofill/virtualcard/icon/capitalone.png"); + GURL cardArtURL = new GURL("http://google.com/test"); + int widthPixels = 32; + int heightPixels = 20; + + // For virtual card icon, the URL should not be updated. For card art icon, the URL should + // be updated as `cardArtURL=w{width}-h{height}-n`. + assertThat(AutofillUiUtils.getCCIconURLWithParams( + virtualCardIconURL, widthPixels, heightPixels)) + .isEqualTo(virtualCardIconURL); + assertThat(AutofillUiUtils.getCCIconURLWithParams(cardArtURL, widthPixels, heightPixels)) + .isEqualTo(new GURL(new StringBuilder(cardArtURL.getSpec()) + .append("=w") + .append(widthPixels) + .append("-h") + .append(heightPixels) + .append("-n") + .toString())); + } + + @Test + @SmallTest + @Feature({"Autofill"}) public void testAddAndDeleteCreditCard() throws TimeoutException { CreditCard card = createLocalCreditCard("Visa", "1234123412341234", "5", "2020"); card.setOrigin("Chrome settings");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java index dc2e262..931172b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ui/system/StatusBarColorControllerTest.java
@@ -49,6 +49,7 @@ import org.chromium.chrome.test.util.browser.ThemeTestUtils; import org.chromium.components.browser_ui.styles.ChromeColors; import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.ui.test.util.DisableAnimationsTestRule; import org.chromium.ui.test.util.UiRestriction; import org.chromium.ui.util.ColorUtils; @@ -67,6 +68,9 @@ public class StatusBarColorControllerTest { // clang-format on @ClassRule + public static DisableAnimationsTestRule sEnableAnimationsRule = + new DisableAnimationsTestRule(false); + @ClassRule public static ChromeTabbedActivityTestRule sActivityTestRule = new ChromeTabbedActivityTestRule(); @@ -237,13 +241,16 @@ "/chrome/test/data/android/theme_color_test.html"); sActivityTestRule.loadUrl(pageWithBrandColorUrl); ThemeTestUtils.waitForThemeColor(activity, Color.RED); + mOmniboxUtils.waitAnimationsComplete(); waitForStatusBarColor(activity, Color.RED); waitForStatusBarColorToMatchToolbarColor(activity); mOmniboxUtils.requestFocus(); + mOmniboxUtils.waitAnimationsComplete(); waitForStatusBarColor(activity, expectedDefaultStandardColor); waitForStatusBarColorToMatchToolbarColor(activity); mOmniboxUtils.clearFocus(); + mOmniboxUtils.waitAnimationsComplete(); waitForStatusBarColor(activity, Color.RED); waitForStatusBarColorToMatchToolbarColor(activity); }
diff --git a/chrome/app/password_manager_ui_strings_grdp/OWNERS b/chrome/app/password_manager_ui_strings_grdp/OWNERS new file mode 100644 index 0000000..2d3493b --- /dev/null +++ b/chrome/app/password_manager_ui_strings_grdp/OWNERS
@@ -0,0 +1 @@ +file://chrome/browser/password_manager/OWNERS
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index ac89d8c..5159f05b 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -245,6 +245,7 @@ "+components/paint_preview/browser", "+components/paint_preview/buildflags", "+components/password_manager/content/browser", + "+components/password_manager/content/common", "+components/password_manager/core/browser", "+components/password_manager/core/common", "+components/payments/content",
diff --git a/chrome/browser/android/foreign_session_helper.cc b/chrome/browser/android/foreign_session_helper.cc index bec11fb..b1bedfb 100644 --- a/chrome/browser/android/foreign_session_helper.cc +++ b/chrome/browser/android/foreign_session_helper.cc
@@ -234,7 +234,7 @@ last_pushed_session.Reset(Java_ForeignSessionHelper_pushSession( env, result, ConvertUTF8ToJavaString(env, session.session_tag), - ConvertUTF8ToJavaString(env, session.session_name), session.device_type, + ConvertUTF8ToJavaString(env, session.session_name), session.modified_time.ToJavaTime())); // Push the full session, with tabs ordered by visual position.
diff --git a/chrome/browser/ash/login/saml/lockscreen_reauth_dialog_test_helper.cc b/chrome/browser/ash/login/saml/lockscreen_reauth_dialog_test_helper.cc index a7221e2..c460370 100644 --- a/chrome/browser/ash/login/saml/lockscreen_reauth_dialog_test_helper.cc +++ b/chrome/browser/ash/login/saml/lockscreen_reauth_dialog_test_helper.cc
@@ -35,6 +35,7 @@ const test::UIPath kErrorCancelButton = {"main-element", "cancelButtonErrorScreen"}; const test::UIPath kSamlCancelButton = {"main-element", "saml-close-button"}; +const test::UIPath kChangeIdPButton = {"main-element", "change-account"}; const test::UIPath kMainScreen = {"main-element", "verifyAccountScreen"}; const test::UIPath kErrorScreen = {"main-element", "errorScreen"}; const test::UIPath kSamlConfirmPasswordScreen = {"main-element", @@ -167,6 +168,11 @@ DialogJS().TapOnPath(kSamlCancelButton); } +void LockScreenReauthDialogTestHelper::ClickChangeIdPButtonOnSamlScreen() { + ExpectSamlScreenVisible(); + DialogJS().TapOnPath(kChangeIdPButton); +} + void LockScreenReauthDialogTestHelper::WaitForSamlScreen() { WaitForAuthenticatorToLoad(); DialogJS().CreateVisibilityWaiter(true, kSamlContainer)->Wait(); @@ -194,6 +200,10 @@ DialogJS().ExpectHiddenPath(kSamlContainer); } +void LockScreenReauthDialogTestHelper::ExpectGaiaScreenVisible() { + DialogJS().ExpectAttributeEQ("isDefaultSsoProvider", {"main-element"}, false); +} + void LockScreenReauthDialogTestHelper::ExpectSamlConfirmPasswordVisible() { DialogJS().CreateVisibilityWaiter(true, kSamlConfirmPasswordScreen)->Wait(); DialogJS().ExpectVisiblePath(kSamlConfirmPasswordScreen);
diff --git a/chrome/browser/ash/login/saml/lockscreen_reauth_dialog_test_helper.h b/chrome/browser/ash/login/saml/lockscreen_reauth_dialog_test_helper.h index 4a2a22c..98efb49 100644 --- a/chrome/browser/ash/login/saml/lockscreen_reauth_dialog_test_helper.h +++ b/chrome/browser/ash/login/saml/lockscreen_reauth_dialog_test_helper.h
@@ -72,6 +72,9 @@ // Clicks the 'Cancel' button on the 'Saml Account' screen. void ClickCancelButtonOnSamlScreen(); + // Clicks the 'Enter Google Account Info' button on the SAML screen. + void ClickChangeIdPButtonOnSamlScreen(); + // Waits for a screen with the `saml-container` element to be shown. void WaitForSamlScreen(); @@ -83,6 +86,8 @@ void ExpectSamlScreenVisible(); void ExpectSamlScreenHidden(); + void ExpectGaiaScreenVisible(); + // Next members allow to check visibility of some elements on 'confirm // password screen' and also help to fill forms. Precondition: 'confirm // password screen' is visible.
diff --git a/chrome/browser/ash/login/saml/saml_lockscreen_browsertest.cc b/chrome/browser/ash/login/saml/saml_lockscreen_browsertest.cc index 9f944e2..74aa1970 100644 --- a/chrome/browser/ash/login/saml/saml_lockscreen_browsertest.cc +++ b/chrome/browser/ash/login/saml/saml_lockscreen_browsertest.cc
@@ -206,6 +206,23 @@ UnlockWithSAML(); } +// Tests that we can switch from SAML page to GAIA page on the lock screen. +IN_PROC_BROWSER_TEST_F(LockscreenWebUiTest, SamlSwitchToGaia) { + fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); + + Login(); + + // Lock the screen and trigger the lock screen SAML reauth dialog. + ScreenLockerTester().Lock(); + + absl::optional<LockScreenReauthDialogTestHelper> reauth_dialog_helper = + LockScreenReauthDialogTestHelper::StartSamlAndWaitForIdpPageLoad(); + + reauth_dialog_helper->ClickChangeIdPButtonOnSamlScreen(); + + reauth_dialog_helper->ExpectGaiaScreenVisible(); +} + // Tests the cancel button in Verify Screen. IN_PROC_BROWSER_TEST_F(LockscreenWebUiTest, VerifyScreenCancel) { fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job.cc b/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job.cc index c02b463..136a6ac6 100644 --- a/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job.cc +++ b/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job.cc
@@ -505,6 +505,14 @@ std::move(response_callback)); break; } + case ash::cros_healthd::mojom::DiagnosticRoutineEnum::kPrivacyScreen: { + constexpr char kPrivacyScreenTargetState[] = "targetState"; + absl::optional<bool> target_state = + params_dict_.GetDict().FindBool(kPrivacyScreenTargetState); + diagnostics_service->RunPrivacyScreenRoutine( + target_state.value_or(true), std::move(response_callback)); + break; + } } }
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job_unittest.cc b/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job_unittest.cc index 655a9a1..db28720 100644 --- a/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job_unittest.cc +++ b/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job_unittest.cc
@@ -65,6 +65,10 @@ constexpr char kMinimumChargePercentRequiredFieldName[] = "minimumChargePercentRequired"; +// String constants identifying the parameter field for the privacy screen +// routine. +constexpr char kPrivacyScreenTargetStateFieldName[] = "targetState"; + constexpr uint32_t kId = 11; constexpr auto kStatus = ash::cros_healthd::mojom::DiagnosticRoutineStatusEnum::kRunning; @@ -1463,4 +1467,43 @@ }))); } +// Test that privacy screen routine succeeds with all parameters specified. +TEST_F(DeviceCommandRunRoutineJobTest, RunPrivacyScreenRoutineSuccess) { + auto run_routine_response = + ash::cros_healthd::mojom::RunRoutineResponse::New(kId, kStatus); + ash::cros_healthd::FakeCrosHealthd::Get()->SetRunRoutineResponseForTesting( + run_routine_response); + base::Value params_dict(base::Value::Type::DICTIONARY); + params_dict.SetBoolKey(kPrivacyScreenTargetStateFieldName, true); + EXPECT_TRUE( + RunJob(ash::cros_healthd::mojom::DiagnosticRoutineEnum::kPrivacyScreen, + std::move(params_dict), + base::BindLambdaForTesting([](RemoteCommandJob* job) { + EXPECT_EQ(job->status(), RemoteCommandJob::SUCCEEDED); + std::unique_ptr<std::string> payload = job->GetResultPayload(); + EXPECT_TRUE(payload); + EXPECT_EQ(CreateSuccessPayload(kId, kStatus), *payload); + }))); +} + +// Test that privacy screen routine succeeds without the optional parameter +// |targetState| specified. +TEST_F(DeviceCommandRunRoutineJobTest, + RunPrivacyScreenRoutineSuccessNoOptionalTargetState) { + auto run_routine_response = + ash::cros_healthd::mojom::RunRoutineResponse::New(kId, kStatus); + ash::cros_healthd::FakeCrosHealthd::Get()->SetRunRoutineResponseForTesting( + run_routine_response); + base::Value params_dict(base::Value::Type::DICTIONARY); + EXPECT_TRUE( + RunJob(ash::cros_healthd::mojom::DiagnosticRoutineEnum::kPrivacyScreen, + std::move(params_dict), + base::BindLambdaForTesting([](RemoteCommandJob* job) { + EXPECT_EQ(job->status(), RemoteCommandJob::SUCCEEDED); + std::unique_ptr<std::string> payload = job->GetResultPayload(); + EXPECT_TRUE(payload); + EXPECT_EQ(CreateSuccessPayload(kId, kStatus), *payload); + }))); +} + } // namespace policy
diff --git a/chrome/browser/banners/app_banner_manager_desktop_browsertest.cc b/chrome/browser/banners/app_banner_manager_desktop_browsertest.cc index 8852908..df44a183 100644 --- a/chrome/browser/banners/app_banner_manager_desktop_browsertest.cc +++ b/chrome/browser/banners/app_banner_manager_desktop_browsertest.cc
@@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/run_loop.h" +#include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" @@ -32,6 +33,8 @@ #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/common/chrome_features.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/password_manager/content/common/web_ui_constants.h" +#include "components/password_manager/core/common/password_manager_features.h" #include "components/webapps/browser/banners/app_banner_metrics.h" #include "components/webapps/browser/banners/app_banner_settings_helper.h" #include "components/webapps/browser/install_result_code.h" @@ -46,20 +49,27 @@ namespace webapps { +namespace { + +std::vector<base::test::FeatureRef> GetDisabledFeatures() { +#if BUILDFLAG(IS_CHROMEOS_ASH) + return {features::kWebAppsCrosapi, chromeos::features::kLacrosPrimary}; +#else + return {}; +#endif +} + +} // namespace + using State = AppBannerManager::State; class AppBannerManagerDesktopBrowserTest : public AppBannerManagerBrowserTestBase { public: - AppBannerManagerDesktopBrowserTest() { -#if BUILDFLAG(IS_CHROMEOS_ASH) - // With Lacros, web apps are not installed using the Ash browser. - scoped_feature_list_.InitWithFeatures( - {}, {features::kWebAppsCrosapi, chromeos::features::kLacrosPrimary}); -#endif - } + AppBannerManagerDesktopBrowserTest() = default; void SetUp() override { + scoped_feature_list_.InitWithFeatures({}, GetDisabledFeatures()); TestAppBannerManagerDesktop::SetUp(); AppBannerManagerBrowserTestBase::SetUp(); } @@ -81,7 +91,7 @@ AppBannerManagerDesktopBrowserTest& operator=( const AppBannerManagerDesktopBrowserTest&) = delete; - private: + protected: base::test::ScopedFeatureList scoped_feature_list_; }; @@ -450,4 +460,38 @@ EXPECT_TRUE(manager->IsPromptAvailableForTesting()); } +class AppBannerManagerDesktopBrowserTestForPasswordManagerPage + : public AppBannerManagerDesktopBrowserTest { + public: + void SetUp() override { + scoped_feature_list_.InitWithFeatures( + {password_manager::features::kPasswordManagerRedesign}, + GetDisabledFeatures()); + TestAppBannerManagerDesktop::SetUp(); + AppBannerManagerBrowserTestBase::SetUp(); + } +}; + +IN_PROC_BROWSER_TEST_F(AppBannerManagerDesktopBrowserTestForPasswordManagerPage, + WebUiPasswordManagerApp) { + TestAppBannerManagerDesktop* manager = + TestAppBannerManagerDesktop::FromWebContents( + browser()->tab_strip_model()->GetActiveWebContents()); + + // Simulate loading a PasswordManager page. + { + base::RunLoop run_loop; + manager->PrepareDone(run_loop.QuitClosure()); + + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), + GURL(base::StrCat( + {"chrome://", password_manager::kChromeUIPasswordManagerHost})))); + run_loop.Run(); + } + + EXPECT_EQ(AppBannerManager::InstallableWebAppCheckResult::kYes_ByUserRequest, + manager->GetInstallableWebAppCheckResultForTesting()); +} + } // namespace webapps
diff --git a/chrome/browser/chrome_service_worker_browsertest.cc b/chrome/browser/chrome_service_worker_browsertest.cc index 0505739..024d8278 100644 --- a/chrome/browser/chrome_service_worker_browsertest.cc +++ b/chrome/browser/chrome_service_worker_browsertest.cc
@@ -37,6 +37,7 @@ #include "components/favicon/content/content_favicon_driver.h" #include "components/favicon/core/favicon_driver_observer.h" #include "components/nacl/common/buildflags.h" +#include "components/ukm/test_ukm_recorder.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -58,6 +59,7 @@ #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" #include "ppapi/shared_impl/ppapi_switches.h" +#include "services/metrics/public/cpp/ukm_builders.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/messaging/string_message_codec.h" #include "third_party/blink/public/common/storage_key/storage_key.h" @@ -314,6 +316,82 @@ kInstallAndWaitForActivatedPageWithModuleScript); } +IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerTest, SubresourceCount) { + base::RunLoop ukm_loop; + ukm::TestAutoSetUkmRecorder test_recorder; + test_recorder.SetOnAddEntryCallback( + ukm::builders::ServiceWorker_OnLoad::kEntryName, ukm_loop.QuitClosure()); + + WriteFile(FILE_PATH_LITERAL("fallback.css"), ""); + WriteFile(FILE_PATH_LITERAL("nofallback.css"), ""); + WriteFile(FILE_PATH_LITERAL("subresources.html"), + "<link href='./fallback.css' rel='stylesheet'>" + "<link href='./nofallback.css' rel='stylesheet'>"); + WriteFile(FILE_PATH_LITERAL("sw.js"), + "this.onactivate = function(event) {" + " event.waitUntil(self.clients.claim());" + "};" + "this.onfetch = function(event) {" + // We will fallback fallback.css. + " if (event.request.url.endsWith('/fallback.css')) {" + " return;" + " }" + " event.respondWith(fetch(event.request));" + "};"); + WriteFile(FILE_PATH_LITERAL("test.html"), + "<script>" + "navigator.serviceWorker.register('./sw.js', {scope: './'})" + " .then(function(reg) {" + " reg.addEventListener('updatefound', function() {" + " var worker = reg.installing;" + " worker.addEventListener('statechange', function() {" + " if (worker.state == 'activated')" + " document.title = 'READY';" + " });" + " });" + " });" + "</script>"); + + InitializeServer(); + + { + // The message "READY" will be sent when the service worker is activated. + const std::u16string expected_title = u"READY"; + content::TitleWatcher title_watcher( + browser()->tab_strip_model()->GetActiveWebContents(), expected_title); + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), embedded_test_server()->GetURL("/test.html"))); + EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); + } + + // Navigate to the service worker controlled page. + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), embedded_test_server()->GetURL("/subresources.html"))); + + // Navigate away to record metrics. + ASSERT_TRUE( + ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL))); + + // Wait until the UKM record is updated. + ukm_loop.Run(); + auto entries = test_recorder.GetEntriesByName( + ukm::builders::ServiceWorker_OnLoad::kEntryName); + ASSERT_EQ(entries.size(), 1u); + test_recorder.ExpectEntryMetric( + entries[0], + ukm::builders::ServiceWorker_OnLoad::kMainAndSubResourceLoadLocationName, + 6 /* = kMainResourceNotFallbackAndSubResourceMixed */); + test_recorder.ExpectEntryMetric( + entries[0], + ukm::builders::ServiceWorker_OnLoad::kTotalSubResourceLoadName, 2); + test_recorder.ExpectEntryMetric( + entries[0], + ukm::builders::ServiceWorker_OnLoad::kTotalSubResourceFallbackName, 1); + test_recorder.ExpectEntryMetric( + entries[0], + ukm::builders::ServiceWorker_OnLoad::kSubResourceFallbackRatioName, 50); +} + class ChromeServiceWorkerFetchTest : public ChromeServiceWorkerTest { public: ChromeServiceWorkerFetchTest(const ChromeServiceWorkerFetchTest&) = delete;
diff --git a/chrome/browser/device_api/device_attribute_api.cc b/chrome/browser/device_api/device_attribute_api.cc index 5b24bb5..a98aad6 100644 --- a/chrome/browser/device_api/device_attribute_api.cc +++ b/chrome/browser/device_api/device_attribute_api.cc
@@ -108,14 +108,12 @@ void GetSerialNumber(DeviceAPIService::GetSerialNumberCallback callback) { #if BUILDFLAG(IS_CHROMEOS_ASH) - const std::string attribute = - chromeos::system::StatisticsProvider::GetInstance() - ->GetEnterpriseMachineID(); - if (attribute.empty()) - std::move(callback).Run( - Result::NewAttribute(absl::optional<std::string>())); - else - std::move(callback).Run(Result::NewAttribute(attribute)); + const absl::optional<base::StringPiece> attribute = + chromeos::system::StatisticsProvider::GetInstance()->GetMachineID(); + std::move(callback).Run(Result::NewAttribute( + attribute ? absl::optional<std::string>(attribute.value()) + : absl::nullopt)); + #elif BUILDFLAG(IS_CHROMEOS_LACROS) // TODO(crbug.com/1328100): Replace with crosapi BrowserInitParams. chromeos::LacrosService::Get()
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index 3f9e3493..cf14d148 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -216,8 +216,6 @@ "api/image_writer_private/operation_manager.h", "api/image_writer_private/removable_storage_provider.cc", "api/image_writer_private/removable_storage_provider.h", - "api/image_writer_private/single_file_tar_reader.cc", - "api/image_writer_private/single_file_tar_reader.h", "api/image_writer_private/tar_extractor.cc", "api/image_writer_private/tar_extractor.h", "api/image_writer_private/write_from_file_operation.cc",
diff --git a/chrome/browser/extensions/api/image_writer_private/extractor_browsertest.cc b/chrome/browser/extensions/api/image_writer_private/extractor_browsertest.cc index c746300..17464b7 100644 --- a/chrome/browser/extensions/api/image_writer_private/extractor_browsertest.cc +++ b/chrome/browser/extensions/api/image_writer_private/extractor_browsertest.cc
@@ -12,6 +12,7 @@ #include "base/test/mock_callback.h" #include "chrome/browser/extensions/api/image_writer_private/error_constants.h" #include "chrome/browser/extensions/api/image_writer_private/extraction_properties.h" +#include "chrome/browser/extensions/api/image_writer_private/tar_extractor.h" #include "chrome/browser/extensions/api/image_writer_private/test_utils.h" #include "chrome/browser/extensions/api/image_writer_private/xz_extractor.h" #include "chrome/test/base/in_process_browser_test.h" @@ -54,6 +55,26 @@ base::ScopedTempDir temp_dir_; }; +IN_PROC_BROWSER_TEST_F(ExtractorBrowserTest, ExtractTar) { + base::ScopedAllowBlockingForTesting allow_blocking; + + base::FilePath test_data_dir; + ASSERT_TRUE(GetTestDataDirectory(&test_data_dir)); + properties_.image_path = test_data_dir.AppendASCII("test.tar"); + + base::FilePath out_path; + base::RunLoop run_loop; + EXPECT_CALL(open_callback_, Run(_)).WillOnce(SaveArg<0>(&out_path)); + EXPECT_CALL(complete_callback_, Run()) + .WillOnce(base::test::RunClosure(run_loop.QuitClosure())); + TarExtractor::Extract(std::move(properties_)); + run_loop.Run(); + + std::string contents; + ASSERT_TRUE(base::ReadFileToString(out_path, &contents)); + EXPECT_EQ("foo\n", contents); +} + IN_PROC_BROWSER_TEST_F(ExtractorBrowserTest, ExtractTarXz) { base::ScopedAllowBlockingForTesting allow_blocking; @@ -89,7 +110,7 @@ } // Verify that tar.xz with a 0 byte file works. -IN_PROC_BROWSER_TEST_F(ExtractorBrowserTest, ZeroByteFile) { +IN_PROC_BROWSER_TEST_F(ExtractorBrowserTest, ZeroByteTarXzFile) { base::ScopedAllowBlockingForTesting allow_blocking; base::FilePath test_data_dir; @@ -114,7 +135,7 @@ EXPECT_TRUE(contents.empty()); } -IN_PROC_BROWSER_TEST_F(ExtractorBrowserTest, ExtractBigFile) { +IN_PROC_BROWSER_TEST_F(ExtractorBrowserTest, ExtractBigTarXzFile) { base::ScopedAllowBlockingForTesting allow_blocking; base::FilePath test_data_dir;
diff --git a/chrome/browser/extensions/api/image_writer_private/extractor_unittest.cc b/chrome/browser/extensions/api/image_writer_private/extractor_unittest.cc index f40811d1..6425363 100644 --- a/chrome/browser/extensions/api/image_writer_private/extractor_unittest.cc +++ b/chrome/browser/extensions/api/image_writer_private/extractor_unittest.cc
@@ -2,17 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <string> -#include <utility> - #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/run_loop.h" -#include "base/test/gmock_callback_support.h" -#include "base/test/mock_callback.h" -#include "base/test/task_environment.h" -#include "chrome/browser/extensions/api/image_writer_private/error_constants.h" -#include "chrome/browser/extensions/api/image_writer_private/extraction_properties.h" #include "chrome/browser/extensions/api/image_writer_private/tar_extractor.h" #include "chrome/browser/extensions/api/image_writer_private/test_utils.h" #include "chrome/browser/extensions/api/image_writer_private/xz_extractor.h" @@ -22,91 +13,17 @@ namespace extensions { namespace image_writer { -using ::testing::_; -using ::testing::NiceMock; -using ::testing::SaveArg; -using ::testing::StrictMock; - class ExtractorTest : public testing::Test { protected: ExtractorTest() = default; ~ExtractorTest() override = default; - void SetUp() override { - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - - properties_.temp_dir_path = temp_dir_.GetPath(); - properties_.open_callback = open_callback_.Get(); - properties_.complete_callback = complete_callback_.Get(); - properties_.failure_callback = failure_callback_.Get(); - properties_.progress_callback = progress_callback_.Get(); - } + void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } protected: - StrictMock<base::MockCallback<ExtractionProperties::OpenCallback>> - open_callback_; - StrictMock<base::MockCallback<ExtractionProperties::CompleteCallback>> - complete_callback_; - StrictMock<base::MockCallback<ExtractionProperties::FailureCallback>> - failure_callback_; - NiceMock<base::MockCallback<ExtractionProperties::ProgressCallback>> - progress_callback_; - - ExtractionProperties properties_; base::ScopedTempDir temp_dir_; - - base::test::TaskEnvironment task_environment_; }; -TEST_F(ExtractorTest, ExtractTar) { - base::FilePath test_data_dir; - ASSERT_TRUE(GetTestDataDirectory(&test_data_dir)); - properties_.image_path = test_data_dir.AppendASCII("test.tar"); - - base::FilePath out_path; - base::RunLoop run_loop; - EXPECT_CALL(open_callback_, Run(_)).WillOnce(SaveArg<0>(&out_path)); - EXPECT_CALL(complete_callback_, Run()) - .WillOnce(base::test::RunClosure(run_loop.QuitClosure())); - TarExtractor::Extract(std::move(properties_)); - run_loop.Run(); - - std::string contents; - ASSERT_TRUE(base::ReadFileToString(out_path, &contents)); - EXPECT_EQ("foo\n", contents); -} - -TEST_F(ExtractorTest, ExtractTarLargerThanChunk) { - base::FilePath test_data_dir; - ASSERT_TRUE(GetTestDataDirectory(&test_data_dir)); - properties_.image_path = test_data_dir.AppendASCII("test_large.tar"); - - base::FilePath out_path; - base::RunLoop run_loop; - EXPECT_CALL(open_callback_, Run(_)).WillOnce(SaveArg<0>(&out_path)); - EXPECT_CALL(complete_callback_, Run()) - .WillOnce(base::test::RunClosure(run_loop.QuitClosure())); - TarExtractor::Extract(std::move(properties_)); - run_loop.Run(); - - std::string contents; - ASSERT_TRUE(base::ReadFileToString(out_path, &contents)); - // Larger than the buffer of SingleFileTarReader. - EXPECT_EQ(10u * 1024u, contents.size()); -} - -TEST_F(ExtractorTest, ExtractNonExistentTar) { - base::FilePath test_data_dir; - ASSERT_TRUE(GetTestDataDirectory(&test_data_dir)); - properties_.image_path = test_data_dir.AppendASCII("non_existent.tar"); - - base::RunLoop run_loop; - EXPECT_CALL(failure_callback_, Run(error::kUnzipGenericError)) - .WillOnce(base::test::RunClosure(run_loop.QuitClosure())); - TarExtractor::Extract(std::move(properties_)); - run_loop.Run(); -} - TEST_F(ExtractorTest, IsZipFile) { base::FilePath test_data_dir; ASSERT_TRUE(GetTestDataDirectory(&test_data_dir));
diff --git a/chrome/browser/extensions/api/image_writer_private/single_file_tar_reader.cc b/chrome/browser/extensions/api/image_writer_private/single_file_tar_reader.cc deleted file mode 100644 index 206ca48..0000000 --- a/chrome/browser/extensions/api/image_writer_private/single_file_tar_reader.cc +++ /dev/null
@@ -1,125 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/extensions/api/image_writer_private/single_file_tar_reader.h" - -#include <algorithm> -#include <string> - -#include "base/check.h" -#include "base/containers/span.h" -#include "chrome/browser/extensions/api/image_writer_private/error_constants.h" - -namespace extensions { -namespace image_writer { - -namespace { -constexpr int kTarBufferSize = 8192; -} // namespace - -SingleFileTarReader::SingleFileTarReader(Delegate* delegate) - : delegate_(delegate), buffer_(kTarBufferSize) {} - -SingleFileTarReader::~SingleFileTarReader() = default; - -SingleFileTarReader::Result SingleFileTarReader::ExtractChunk() { - // Drain as much of the data as we can fit into the buffer. - base::span<char> storage = base::make_span(buffer_); - size_t bytes_read = 0; - bool pipe_drained = false; - do { - uint32_t num_bytes = static_cast<uint32_t>(storage.size()); - const Result result = - delegate_->ReadTarFile(storage.data(), &num_bytes, &error_id_); - switch (result) { - case Result::kFailure: - return result; - - case Result::kSuccess: - if (num_bytes == 0) { - pipe_drained = true; - } else { - storage = storage.subspan(num_bytes); - bytes_read += num_bytes; - } - break; - - case Result::kShouldWait: - pipe_drained = true; - break; - } - } while (!pipe_drained && !storage.empty()); - - int offset = 0; - - // We haven't read the header. - if (!total_bytes_.has_value()) { - if (bytes_read < 512) { - error_id_ = error::kUnzipInvalidArchive; - return Result::kFailure; - } - - // TODO(tetsui): check the file header checksum - - // Read the actual file size. - total_bytes_ = ReadOctalNumber(buffer_.data() + 124, 12); - - // Skip the rest of the header. - offset += 512; - } - - DCHECK(total_bytes_.has_value()); - - // A tar file always has a padding at the end of the file. As they should not - // be included in the output, we should take the minimum of the actual - // remaining bytes versus the bytes read. - uint64_t bytes_written = std::min<uint64_t>( - total_bytes_.value() - curr_bytes_, bytes_read - offset); - if (!delegate_->WriteContents(buffer_.data() + offset, bytes_written, - &error_id_)) { - return Result::kFailure; - } - curr_bytes_ += bytes_written; - - // TODO(tetsui): check it's the end of the file - - return Result::kSuccess; -} - -bool SingleFileTarReader::IsComplete() const { - if (!total_bytes_.has_value()) - return false; - return total_bytes_.value() == curr_bytes_; -} - -// static -uint64_t SingleFileTarReader::ReadOctalNumber(const char* buffer, - size_t length) { - DCHECK(length > 8); - - uint64_t num = 0; - - // In GNU tar extension, when the number starts with an invalid ASCII - // character 0x80, then non-leading 8 bytes of the field should be interpreted - // as a big-endian integer. - // https://www.gnu.org/software/tar/manual/html_node/Extensions.html - if (static_cast<unsigned char>(buffer[0]) == 0x80) { - for (size_t i = length - 8; i < length; ++i) { - num <<= 8; - num += static_cast<unsigned char>(buffer[i]); - } - return num; - } - - for (size_t i = 0; i < length; ++i) { - if (buffer[i] == '\0') - break; - num *= 8; - num += buffer[i] - '0'; - } - return num; -} - -} // namespace image_writer -} // namespace extensions
diff --git a/chrome/browser/extensions/api/image_writer_private/single_file_tar_reader.h b/chrome/browser/extensions/api/image_writer_private/single_file_tar_reader.h deleted file mode 100644 index 2541d57..0000000 --- a/chrome/browser/extensions/api/image_writer_private/single_file_tar_reader.h +++ /dev/null
@@ -1,96 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_EXTENSIONS_API_IMAGE_WRITER_PRIVATE_SINGLE_FILE_TAR_READER_H_ -#define CHROME_BROWSER_EXTENSIONS_API_IMAGE_WRITER_PRIVATE_SINGLE_FILE_TAR_READER_H_ - -#include <stdint.h> - -#include <string> -#include <vector> - -#include "base/gtest_prod_util.h" -#include "base/memory/raw_ptr.h" -#include "third_party/abseil-cpp/absl/types/optional.h" - -namespace extensions { -namespace image_writer { - -class SingleFileTarReaderTest; - -// SingleFileTarReader is a reader of tar archives with limited function. It -// only supports a tar archive with a single file entry. An archive with -// multiple files is rejected as error. -class SingleFileTarReader { - public: - enum class Result { kSuccess, kFailure, kShouldWait }; - - // An interface that delegates file I/O of SingleFileTarReader. - class Delegate { - public: - using Result = SingleFileTarReader::Result; - - virtual ~Delegate() = default; - - // Reads input data and returns kSuccess if it succeeds. - // The input data will be written to |data|. |*size| is initially the size - // of the |data| buffer. |*size| will be set to the amount actually read. - // Returns kShouldWait if the data is still not available. - // Returns kFailure and sets |error_id| if it fails. - virtual Result ReadTarFile(char* data, - uint32_t* size, - std::string* error_id) = 0; - - // Writes the passed data. |size| is the size of the |data| buffer. - // Returns false and sets |error_id| if it fails. - virtual bool WriteContents(const char* data, - int size, - std::string* error_id) = 0; - }; - - explicit SingleFileTarReader(Delegate* delegate); - SingleFileTarReader(const SingleFileTarReader&) = delete; - SingleFileTarReader& operator=(const SingleFileTarReader&) = delete; - ~SingleFileTarReader(); - - // Extracts a chunk of the tar file. To fully extract the file, the caller has - // to repeatedly call this function until IsComplete() returns true. - // Returns kShouldWait if the input data is still not available. The caller - // has to call ExtractChunk() again when the data is ready. The detail depends - // on the implementation of the delegate. - // Returns kFailure if it fails. error_id() identifies the reason of the - // error. - Result ExtractChunk(); - - bool IsComplete() const; - - absl::optional<uint64_t> total_bytes() const { return total_bytes_; } - uint64_t curr_bytes() const { return curr_bytes_; } - - const std::string& error_id() const { return error_id_; } - - private: - FRIEND_TEST_ALL_PREFIXES(SingleFileTarReaderTest, ReadOctalNumber); - - // Read a number in Tar file header. It is normally a null-terminated octal - // ASCII number but can be big-endian integer with padding when GNU extension - // is used. |length| must greater than 8. - static uint64_t ReadOctalNumber(const char* buffer, size_t length); - - const raw_ptr<Delegate> delegate_; - - // Populated once the size has been parsed. The value 0 means the file in - // the tar is empty. - absl::optional<uint64_t> total_bytes_; - uint64_t curr_bytes_ = 0; - - std::vector<char> buffer_; - - std::string error_id_; -}; - -} // namespace image_writer -} // namespace extensions - -#endif // CHROME_BROWSER_EXTENSIONS_API_IMAGE_WRITER_PRIVATE_SINGLE_FILE_TAR_READER_H_
diff --git a/chrome/browser/extensions/api/image_writer_private/tar_extractor.cc b/chrome/browser/extensions/api/image_writer_private/tar_extractor.cc index 09e10b5..5190c6d 100644 --- a/chrome/browser/extensions/api/image_writer_private/tar_extractor.cc +++ b/chrome/browser/extensions/api/image_writer_private/tar_extractor.cc
@@ -4,11 +4,15 @@ #include "chrome/browser/extensions/api/image_writer_private/tar_extractor.h" -#include <algorithm> #include <utility> -#include "base/task/sequenced_task_runner.h" +#include "base/files/file.h" +#include "base/files/file_path.h" #include "chrome/browser/extensions/api/image_writer_private/error_constants.h" +#include "chrome/browser/file_util_service.h" + +// TarExtractor extracts a .tar file. The actual .tar file extraction is +// performed in a utility process. namespace extensions { namespace image_writer { @@ -24,16 +28,17 @@ } // namespace bool TarExtractor::IsTarFile(const base::FilePath& image_path) { - base::File infile(image_path, base::File::FLAG_OPEN | base::File::FLAG_READ | - base::File::FLAG_WIN_EXCLUSIVE_WRITE | - base::File::FLAG_WIN_SHARE_DELETE); - if (!infile.IsValid()) + base::File src_file(image_path, base::File::FLAG_OPEN | + base::File::FLAG_READ | + base::File::FLAG_WIN_EXCLUSIVE_WRITE | + base::File::FLAG_WIN_SHARE_DELETE); + if (!src_file.IsValid()) return false; // Tar header record is always 512 bytes, so if the file is shorter than that, // it's not tar. char header[512] = {}; - if (infile.ReadAtCurrentPos(header, sizeof(header)) != sizeof(header)) + if (src_file.ReadAtCurrentPos(header, sizeof(header)) != sizeof(header)) return false; return std::equal(kExpectedMagic, kExpectedMagic + sizeof(kExpectedMagic), @@ -49,75 +54,85 @@ } TarExtractor::TarExtractor(ExtractionProperties properties) - : tar_reader_(this), properties_(std::move(properties)) {} + : properties_(std::move(properties)) {} TarExtractor::~TarExtractor() = default; -SingleFileTarReader::Result TarExtractor::ReadTarFile(char* data, - uint32_t* size, - std::string* error_id) { - const int bytes_read = infile_.ReadAtCurrentPos(data, *size); - if (bytes_read < 0) { - *error_id = error::kUnzipGenericError; - return SingleFileTarReader::Result::kFailure; - } - *size = bytes_read; - return SingleFileTarReader::Result::kSuccess; -} - -bool TarExtractor::WriteContents(const char* data, - int size, - std::string* error_id) { - const int bytes_written = outfile_.WriteAtCurrentPos(data, size); - if (bytes_written < 0 || bytes_written != size) { - *error_id = error::kTempFileError; - return false; - } - return true; +void TarExtractor::OnProgress(uint64_t total_bytes, uint64_t progress_bytes) { + properties_.progress_callback.Run(total_bytes, progress_bytes); } void TarExtractor::ExtractImpl() { - infile_.Initialize(properties_.image_path, - base::File::FLAG_OPEN | base::File::FLAG_READ); - if (!infile_.IsValid()) { - std::move(properties_.failure_callback).Run(error::kUnzipGenericError); - delete this; + service_.Bind(LaunchFileUtilService()); + service_->BindSingleFileTarFileExtractor( + remote_single_file_extractor_.BindNewPipeAndPassReceiver()); + + // TODO(b/254591810): Run on a pooled worker thread to avoid blocking + // operation on the main UI thread. + base::File src_file(properties_.image_path, + base::File::FLAG_OPEN | base::File::FLAG_READ | + // Do not allow others to write to the file. + base::File::FLAG_WIN_EXCLUSIVE_WRITE | + base::File::FLAG_WIN_SHARE_DELETE); + if (!src_file.IsValid()) { + RunFailureCallbackAndDeleteThis(error::kUnzipGenericError); return; } base::FilePath out_image_path = properties_.temp_dir_path.Append(kExtractedBinFileName); - outfile_.Initialize(out_image_path, - base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); - if (!outfile_.IsValid()) { - std::move(properties_.failure_callback).Run(error::kTempFileError); - delete this; + // TODO(b/254591810): Run on a pooled worker thread to avoid blocking + // operation on the main UI thread. + base::File dst_file(out_image_path, + base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE | + // Do not allow others to read the file. + base::File::FLAG_WIN_EXCLUSIVE_READ | + // Do not allow others to write to the file. + base::File::FLAG_WIN_EXCLUSIVE_WRITE | + base::File::FLAG_WIN_SHARE_DELETE); + if (!dst_file.IsValid()) { + RunFailureCallbackAndDeleteThis(error::kTempFileError); return; } std::move(properties_.open_callback).Run(out_image_path); - ExtractChunk(); + // base::Unretained(this) is safe here because callback won't be called once + // `remote_single_file_extractor_` is destroyed. + remote_single_file_extractor_->Extract( + std::move(src_file), std::move(dst_file), + listener_.BindNewPipeAndPassRemote(), + base::BindOnce(&TarExtractor::OnRemoteFinished, base::Unretained(this))); } -void TarExtractor::ExtractChunk() { - if (tar_reader_.ExtractChunk() != SingleFileTarReader::Result::kSuccess) { - std::move(properties_.failure_callback).Run(tar_reader_.error_id()); - delete this; - return; +void TarExtractor::OnRemoteFinished( + chrome::file_util::mojom::ExtractionResult result) { + switch (result) { + case chrome::file_util::mojom::ExtractionResult::kSuccess: { + auto complete_callback = std::move(properties_.complete_callback); + delete this; + std::move(complete_callback).Run(); + return; + } + case chrome::file_util::mojom::ExtractionResult::kGenericError: { + RunFailureCallbackAndDeleteThis(error::kUnzipGenericError); + return; + } + case chrome::file_util::mojom::ExtractionResult::kInvalidSrcFile: { + RunFailureCallbackAndDeleteThis(error::kUnzipInvalidArchive); + return; + } + case chrome::file_util::mojom::ExtractionResult::kDstFileError: { + RunFailureCallbackAndDeleteThis(error::kTempFileError); + return; + } } +} - if (tar_reader_.IsComplete()) { - std::move(properties_.complete_callback).Run(); - delete this; - return; - } - - properties_.progress_callback.Run(tar_reader_.total_bytes().value(), - tar_reader_.curr_bytes()); - - base::SequencedTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindRepeating(&TarExtractor::ExtractChunk, - weak_ptr_factory_.GetWeakPtr())); +void TarExtractor::RunFailureCallbackAndDeleteThis( + const std::string& error_id) { + auto failure_callback = std::move(properties_.failure_callback); + delete this; + std::move(failure_callback).Run(error_id); } } // namespace image_writer
diff --git a/chrome/browser/extensions/api/image_writer_private/tar_extractor.h b/chrome/browser/extensions/api/image_writer_private/tar_extractor.h index 25fb1cd..7c138ab 100644 --- a/chrome/browser/extensions/api/image_writer_private/tar_extractor.h +++ b/chrome/browser/extensions/api/image_writer_private/tar_extractor.h
@@ -5,19 +5,24 @@ #ifndef CHROME_BROWSER_EXTENSIONS_API_IMAGE_WRITER_PRIVATE_TAR_EXTRACTOR_H_ #define CHROME_BROWSER_EXTENSIONS_API_IMAGE_WRITER_PRIVATE_TAR_EXTRACTOR_H_ -#include "base/files/file_util.h" +#include <string> + #include "chrome/browser/extensions/api/image_writer_private/extraction_properties.h" -#include "chrome/browser/extensions/api/image_writer_private/single_file_tar_reader.h" +#include "chrome/services/file_util/public/mojom/constants.mojom.h" +#include "chrome/services/file_util/public/mojom/file_util_service.mojom.h" +#include "chrome/services/file_util/public/mojom/single_file_extractor.mojom.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" namespace extensions { namespace image_writer { -class TarExtractor : public SingleFileTarReader::Delegate { +class TarExtractor : public chrome::mojom::SingleFileExtractorListener { public: static bool IsTarFile(const base::FilePath& image_path); - // Start extracting the archive at |image_path| to |temp_dir_path| in - // |properties|. + // Start extracting the archive at `image_path` to `temp_dir_path` in + // `properties`. static void Extract(ExtractionProperties properties); TarExtractor(const TarExtractor&) = delete; @@ -28,25 +33,27 @@ explicit TarExtractor(ExtractionProperties properties); ~TarExtractor() override; + // chrome::mojom::SingleFileExtractorListener implementation. + void OnProgress(uint64_t total_bytes, uint64_t progress_bytes) override; + void ExtractImpl(); - void ExtractChunk(); + void OnRemoteFinished(chrome::file_util::mojom::ExtractionResult result); + void RunFailureCallbackAndDeleteThis(const std::string& error_id); - // SingleFileTarReader::Delegate: - SingleFileTarReader::Result ReadTarFile(char* data, - uint32_t* size, - std::string* error_id) override; - bool WriteContents(const char* data, - int size, - std::string* error_id) override; + // `service_` is a class member so that the utility process where the actual + // .tar file extraction is performed is kept alive while extraction is in + // progress. + mojo::Remote<chrome::mojom::FileUtilService> service_; - SingleFileTarReader tar_reader_; + mojo::Remote<chrome::mojom::SingleFileExtractor> + remote_single_file_extractor_; - base::File infile_; - base::File outfile_; + // Listener receiver. + // This class listens for tar extraction progress reports from the utility + // process. + mojo::Receiver<chrome::mojom::SingleFileExtractorListener> listener_{this}; ExtractionProperties properties_; - - base::WeakPtrFactory<TarExtractor> weak_ptr_factory_{this}; }; } // namespace image_writer
diff --git a/chrome/browser/extensions/api/image_writer_private/xz_extractor.cc b/chrome/browser/extensions/api/image_writer_private/xz_extractor.cc index 1ff2f6c..615a131 100644 --- a/chrome/browser/extensions/api/image_writer_private/xz_extractor.cc +++ b/chrome/browser/extensions/api/image_writer_private/xz_extractor.cc
@@ -59,8 +59,11 @@ } void XzExtractor::ExtractImpl() { + // TODO(b/254591810): Run on a pooled worker thread to avoid blocking + // operation on the main UI thread. base::File src_file(properties_.image_path, base::File::FLAG_OPEN | base::File::FLAG_READ | + // Do not allow others to write to the file. base::File::FLAG_WIN_EXCLUSIVE_WRITE | base::File::FLAG_WIN_SHARE_DELETE); if (!src_file.IsValid()) { @@ -70,11 +73,15 @@ base::FilePath out_image_path = properties_.temp_dir_path.Append(kExtractedBinFileName); - base::File dst_file(out_image_path, base::File::FLAG_CREATE_ALWAYS | - base::File::FLAG_WRITE | - base::File::FLAG_WIN_EXCLUSIVE_READ | - base::File::FLAG_WIN_EXCLUSIVE_WRITE | - base::File::FLAG_WIN_SHARE_DELETE); + // TODO(b/254591810): Run on a pooled worker thread to avoid blocking + // operation on the main UI thread. + base::File dst_file(out_image_path, + base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE | + // Do not allow others to read the file. + base::File::FLAG_WIN_EXCLUSIVE_READ | + // Do not allow others to write to the file. + base::File::FLAG_WIN_EXCLUSIVE_WRITE | + base::File::FLAG_WIN_SHARE_DELETE); if (!dst_file.IsValid()) { RunFailureCallbackAndDeleteThis(error::kTempFileError); return; @@ -83,9 +90,9 @@ service_.Bind(LaunchFileUtilService()); service_->BindSingleFileTarXzFileExtractor( - remote_single_file_tar_xz_file_extractor_.BindNewPipeAndPassReceiver()); + remote_single_file_extractor_.BindNewPipeAndPassReceiver()); - remote_single_file_tar_xz_file_extractor_->Extract( + remote_single_file_extractor_->Extract( std::move(src_file), std::move(dst_file), listener_.BindNewPipeAndPassRemote(), base::BindOnce(&XzExtractor::OnRemoteFinished, base::Unretained(this))); @@ -100,22 +107,22 @@ std::move(complete_callback).Run(); return; } - case chrome::file_util::mojom::ExtractionResult::kUnzipGenericError: { + case chrome::file_util::mojom::ExtractionResult::kGenericError: { RunFailureCallbackAndDeleteThis(error::kUnzipGenericError); return; } - case chrome::file_util::mojom::ExtractionResult::kUnzipInvalidArchive: { + case chrome::file_util::mojom::ExtractionResult::kInvalidSrcFile: { RunFailureCallbackAndDeleteThis(error::kUnzipInvalidArchive); return; } - case chrome::file_util::mojom::ExtractionResult::kTempFileError: { + case chrome::file_util::mojom::ExtractionResult::kDstFileError: { RunFailureCallbackAndDeleteThis(error::kTempFileError); return; } } } -void XzExtractor::RunFailureCallbackAndDeleteThis(std::string error_id) { +void XzExtractor::RunFailureCallbackAndDeleteThis(const std::string& error_id) { auto failure_callback = std::move(properties_.failure_callback); delete this; std::move(failure_callback).Run(error_id);
diff --git a/chrome/browser/extensions/api/image_writer_private/xz_extractor.h b/chrome/browser/extensions/api/image_writer_private/xz_extractor.h index 6db6e6e..ec143ec 100644 --- a/chrome/browser/extensions/api/image_writer_private/xz_extractor.h +++ b/chrome/browser/extensions/api/image_writer_private/xz_extractor.h
@@ -10,7 +10,7 @@ #include "chrome/browser/extensions/api/image_writer_private/extraction_properties.h" #include "chrome/services/file_util/public/mojom/constants.mojom.h" #include "chrome/services/file_util/public/mojom/file_util_service.mojom.h" -#include "chrome/services/file_util/public/mojom/single_file_tar_xz_file_extractor.mojom.h" +#include "chrome/services/file_util/public/mojom/single_file_extractor.mojom.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" @@ -23,7 +23,7 @@ // .tar.xz archive extractor. Should be called from a SequencedTaskRunner // context. -class XzExtractor : public chrome::mojom::SingleFileTarXzFileExtractorListener { +class XzExtractor : public chrome::mojom::SingleFileExtractorListener { public: static bool IsXzFile(const base::FilePath& image_path); @@ -41,23 +41,25 @@ explicit XzExtractor(ExtractionProperties properties); ~XzExtractor() override; - // chrome::mojom::SingleFileTarXzFileExtractorListener implementation. + // chrome::mojom::SingleFileExtractorListener implementation. void OnProgress(uint64_t total_bytes, uint64_t progress_bytes) override; void ExtractImpl(); void OnRemoteFinished(chrome::file_util::mojom::ExtractionResult result); - // |error_id| might be a member variable, so it cannot be a reference. - void RunFailureCallbackAndDeleteThis(std::string error_id); + void RunFailureCallbackAndDeleteThis(const std::string& error_id); + // `service_` is a class member so that the utility process where the actual + // .tar.xz file extraction is performed is kept alive while extraction is in + // progress. mojo::Remote<chrome::mojom::FileUtilService> service_; - mojo::Remote<chrome::mojom::SingleFileTarXzFileExtractor> - remote_single_file_tar_xz_file_extractor_; + + mojo::Remote<chrome::mojom::SingleFileExtractor> + remote_single_file_extractor_; // Listener receiver. // This class listens for .tar.xz extraction progress reports from the utility // process. - mojo::Receiver<chrome::mojom::SingleFileTarXzFileExtractorListener> listener_{ - this}; + mojo::Receiver<chrome::mojom::SingleFileExtractorListener> listener_{this}; ExtractionProperties properties_; };
diff --git a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc index 6971683..ffe63c7 100644 --- a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc
@@ -10,6 +10,7 @@ #include "components/page_load_metrics/browser/page_load_metrics_util.h" #include "content/public/browser/navigation_handle.h" #include "net/http/http_response_headers.h" +#include "services/metrics/public/cpp/metrics_utils.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_recorder.h" #include "third_party/blink/public/common/loader/loading_behavior_flag.h" @@ -117,6 +118,19 @@ return transition & ui::PAGE_TRANSITION_FORWARD_BACK; } +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class ServiceWorkerResourceLoadStatus { + kMainResourceFallbackAndSubResourceFallback = 0, + kMainResourceFallbackAndSubResourceNotFallback = 1, + kMainResourceFallbackAndSubResourceMixed = 2, + kMainResourceFallbackAndNoSubResource = 3, + kMainResourceNotFallbackAndSubResourceFallback = 4, + kMainResourceNotFallbackAndSubResourceNotFallback = 5, + kMainResourceNotFallbackAndSubResourceMixed = 6, + kMainResourceNotFallbackAndNoSubResource = 7, +}; + } // namespace ServiceWorkerPageLoadMetricsObserver::ServiceWorkerPageLoadMetricsObserver() {} @@ -382,6 +396,7 @@ all_frames_largest_contentful_paint.Time().value()); } } + RecordSubresourceLoad(); } bool ServiceWorkerPageLoadMetricsObserver::IsServiceWorkerControlled() { @@ -397,3 +412,76 @@ blink::LoadingBehaviorFlag:: kLoadingBehaviorServiceWorkerFetchHandlerSkippable) != 0; } + +void ServiceWorkerPageLoadMetricsObserver::RecordSubresourceLoad() { + const auto& optional_metrics = GetDelegate().GetSubresourceLoadMetrics(); + if (!optional_metrics) { + return; + } + auto metrics = *optional_metrics; + // serviceworker's subresource load must always be smaller than + // or equals to total subresource loads. + if (metrics.number_of_subresource_loads_handled_by_service_worker > + metrics.number_of_subresources_loaded) { + // If the data is not set or invalid, it should not be worth recording. + return; + } + + ServiceWorkerResourceLoadStatus status; + if (GetDelegate().GetMainFrameMetadata().behavior_flags & + blink::LoadingBehaviorFlag:: + kLoadingBehaviorServiceWorkerMainResourceFetchFallback) { + if (metrics.number_of_subresource_loads_handled_by_service_worker == 0) { + status = ServiceWorkerResourceLoadStatus:: + kMainResourceFallbackAndSubResourceFallback; + } else if (metrics.number_of_subresources_loaded == + metrics.number_of_subresource_loads_handled_by_service_worker) { + if (metrics.number_of_subresources_loaded == 0) { + status = ServiceWorkerResourceLoadStatus:: + kMainResourceFallbackAndSubResourceNotFallback; + } else { + status = ServiceWorkerResourceLoadStatus:: + kMainResourceFallbackAndNoSubResource; + } + } else { + status = ServiceWorkerResourceLoadStatus:: + kMainResourceFallbackAndSubResourceMixed; + } + } else { + if (metrics.number_of_subresource_loads_handled_by_service_worker == 0) { + status = ServiceWorkerResourceLoadStatus:: + kMainResourceNotFallbackAndSubResourceFallback; + } else if (metrics.number_of_subresources_loaded == + metrics.number_of_subresource_loads_handled_by_service_worker) { + if (metrics.number_of_subresources_loaded == 0) { + status = ServiceWorkerResourceLoadStatus:: + kMainResourceNotFallbackAndSubResourceNotFallback; + } else { + status = ServiceWorkerResourceLoadStatus:: + kMainResourceNotFallbackAndNoSubResource; + } + } else { + status = ServiceWorkerResourceLoadStatus:: + kMainResourceNotFallbackAndSubResourceMixed; + } + } + + // We calculate the number of fallbacks here. + uint32_t number_of_fallback = + metrics.number_of_subresources_loaded - + metrics.number_of_subresource_loads_handled_by_service_worker; + int64_t fallback_ratio = -1; + if (metrics.number_of_subresources_loaded > 0) { + fallback_ratio = + 100 * number_of_fallback / metrics.number_of_subresources_loaded; + } + + ukm::builders::ServiceWorker_OnLoad(GetDelegate().GetPageUkmSourceId()) + .SetMainAndSubResourceLoadLocation(static_cast<int64_t>(status)) + .SetTotalSubResourceLoad(ukm::GetExponentialBucketMinForCounts1000( + metrics.number_of_subresources_loaded)) + .SetTotalSubResourceFallback( + ukm::GetExponentialBucketMinForCounts1000(number_of_fallback)) + .SetSubResourceFallbackRatio(fallback_ratio) + .Record(ukm::UkmRecorder::Get()); +}
diff --git a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h index 5a00b25..0a17468c 100644 --- a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h
@@ -93,6 +93,7 @@ void RecordTimingHistograms(); bool IsServiceWorkerControlled(); bool IsServiceWorkerFetchHandlerSkippable(); + void RecordSubresourceLoad(); ui::PageTransition transition_ = ui::PAGE_TRANSITION_LINK; bool was_no_store_main_resource_ = false;
diff --git a/chrome/browser/password_manager/android/password_store_android_backend.cc b/chrome/browser/password_manager/android/password_store_android_backend.cc index 6ead7355..3fe0973 100644 --- a/chrome/browser/password_manager/android/password_store_android_backend.cc +++ b/chrome/browser/password_manager/android/password_store_android_backend.cc
@@ -676,7 +676,9 @@ bridge_->SetConsumer(weak_ptr_factory_.GetWeakPtr()); sync_controller_delegate_ = std::make_unique<PasswordSyncControllerDelegateAndroid>( - std::make_unique<PasswordSyncControllerDelegateBridgeImpl>()); + std::make_unique<PasswordSyncControllerDelegateBridgeImpl>(), + base::BindOnce(&PasswordStoreAndroidBackend::SyncShutdown, + weak_ptr_factory_.GetWeakPtr())); } PasswordStoreAndroidBackend::PasswordStoreAndroidBackend( @@ -712,6 +714,7 @@ void PasswordStoreAndroidBackend::Shutdown( base::OnceClosure shutdown_completed) { + sync_service_ = nullptr; lifecycle_helper_->UnregisterObserver(); // TODO(https://crbug.com/1229654): Implement (e.g. unsubscribe from GMS). std::move(shutdown_completed).Run(); @@ -1393,4 +1396,8 @@ }); } +void PasswordStoreAndroidBackend::SyncShutdown() { + sync_service_ = nullptr; +} + } // namespace password_manager
diff --git a/chrome/browser/password_manager/android/password_store_android_backend.h b/chrome/browser/password_manager/android/password_store_android_backend.h index e9657375..5b5249b 100644 --- a/chrome/browser/password_manager/android/password_store_android_backend.h +++ b/chrome/browser/password_manager/android/password_store_android_backend.h
@@ -319,6 +319,10 @@ // each task cleared this way that it could have failed. void ClearZombieTasks(); + // Clears |sync_service_| when syncer::SyncServiceObserver::OnSyncShutdown is + // called. + void SyncShutdown(); + // Observer to propagate potential password changes to. RemoteChangesReceived stored_passwords_changed_;
diff --git a/chrome/browser/password_manager/android/password_store_android_backend_unittest.cc b/chrome/browser/password_manager/android/password_store_android_backend_unittest.cc index a94f53a..6ae5e3fc 100644 --- a/chrome/browser/password_manager/android/password_store_android_backend_unittest.cc +++ b/chrome/browser/password_manager/android/password_store_android_backend_unittest.cc
@@ -9,6 +9,7 @@ #include "base/callback_forward.h" #include "base/callback_helpers.h" +#include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" #include "base/strings/strcat.h" #include "base/test/metrics/histogram_tester.h" @@ -259,7 +260,8 @@ CreatePasswordSyncControllerDelegate() { auto unique_delegate = std::make_unique< PasswordSyncControllerDelegateAndroid>( - std::make_unique<NiceMock<MockPasswordSyncControllerDelegateBridge>>()); + std::make_unique<NiceMock<MockPasswordSyncControllerDelegateBridge>>(), + base::DoNothing()); sync_controller_delegate_ = unique_delegate.get(); return unique_delegate; }
diff --git a/chrome/browser/password_manager/android/password_sync_controller_delegate_android.cc b/chrome/browser/password_manager/android/password_sync_controller_delegate_android.cc index 15095bf..225b73c2 100644 --- a/chrome/browser/password_manager/android/password_sync_controller_delegate_android.cc +++ b/chrome/browser/password_manager/android/password_sync_controller_delegate_android.cc
@@ -31,8 +31,10 @@ } // namespace PasswordSyncControllerDelegateAndroid::PasswordSyncControllerDelegateAndroid( - std::unique_ptr<PasswordSyncControllerDelegateBridge> bridge) - : bridge_(std::move(bridge)) { + std::unique_ptr<PasswordSyncControllerDelegateBridge> bridge, + base::OnceClosure on_sync_shutdown) + : bridge_(std::move(bridge)), + on_sync_shutdown_(std::move(on_sync_shutdown)) { DCHECK(bridge_); bridge_->SetConsumer(weak_ptr_factory_.GetWeakPtr()); } @@ -144,6 +146,14 @@ } } +void PasswordSyncControllerDelegateAndroid::OnSyncShutdown( + syncer::SyncService* sync) { + sync_service_ = nullptr; + if (!on_sync_shutdown_) + return; + std::move(on_sync_shutdown_).Run(); +} + void PasswordSyncControllerDelegateAndroid::OnCredentialManagerNotified() { base::UmaHistogramBoolean( BuildCredentialManagerNotificationMetricName("Success"), 1);
diff --git a/chrome/browser/password_manager/android/password_sync_controller_delegate_android.h b/chrome/browser/password_manager/android/password_sync_controller_delegate_android.h index 0709f51f..cb345df 100644 --- a/chrome/browser/password_manager/android/password_sync_controller_delegate_android.h +++ b/chrome/browser/password_manager/android/password_sync_controller_delegate_android.h
@@ -9,6 +9,7 @@ #include <string> #include "base/callback.h" +#include "base/functional/callback_forward.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observation.h" #include "base/types/strong_alias.h" @@ -31,7 +32,8 @@ public PasswordSyncControllerDelegateBridge::Consumer { public: explicit PasswordSyncControllerDelegateAndroid( - std::unique_ptr<PasswordSyncControllerDelegateBridge> bridge); + std::unique_ptr<PasswordSyncControllerDelegateBridge> bridge, + base::OnceClosure on_sync_shutdown); PasswordSyncControllerDelegateAndroid( const PasswordSyncControllerDelegateAndroid&) = delete; PasswordSyncControllerDelegateAndroid( @@ -54,6 +56,7 @@ // syncer::SyncServiceObserver implementation. void OnStateChanged(syncer::SyncService* sync) override; + void OnSyncShutdown(syncer::SyncService* sync) override; // PasswordStoreAndroidBackendBridge::Consumer implementation. void OnCredentialManagerNotified() override; @@ -83,6 +86,8 @@ // Last sync status set in CredentialManager. absl::optional<IsSyncEnabled> credential_manager_sync_setting_; + base::OnceClosure on_sync_shutdown_; + base::ScopedObservation<syncer::SyncService, syncer::SyncServiceObserver> sync_observation_{this};
diff --git a/chrome/browser/password_manager/android/password_sync_controller_delegate_android_unittest.cc b/chrome/browser/password_manager/android/password_sync_controller_delegate_android_unittest.cc index f90cb43..f63fac52 100644 --- a/chrome/browser/password_manager/android/password_sync_controller_delegate_android_unittest.cc +++ b/chrome/browser/password_manager/android/password_sync_controller_delegate_android_unittest.cc
@@ -6,7 +6,9 @@ #include <memory> +#include "base/functional/callback_helpers.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/mock_callback.h" #include "base/test/task_environment.h" #include "chrome/browser/password_manager/android/mock_password_sync_controller_delegate_bridge.h" #include "components/password_manager/core/browser/android_backend_error.h" @@ -32,7 +34,8 @@ protected: PasswordSyncControllerDelegateAndroidTest() { sync_controller_delegate_ = - std::make_unique<PasswordSyncControllerDelegateAndroid>(CreateBridge()); + std::make_unique<PasswordSyncControllerDelegateAndroid>( + CreateBridge(), base::DoNothing()); } ~PasswordSyncControllerDelegateAndroidTest() override { @@ -50,7 +53,6 @@ return *sync_controller_delegate_; } - private: std::unique_ptr<PasswordSyncControllerDelegateBridge> CreateBridge() { auto unique_delegate_bridge = std::make_unique< StrictMock<MockPasswordSyncControllerDelegateBridge>>(); @@ -59,6 +61,7 @@ return unique_delegate_bridge; } + private: base::test::SingleThreadTaskEnvironment task_environment_; syncer::TestSyncService sync_service_; std::unique_ptr<PasswordSyncControllerDelegateAndroid> @@ -205,4 +208,15 @@ EXPECT_TRUE(sync_service()->HasObserver(sync_controller_delegate())); } +TEST_F(PasswordSyncControllerDelegateAndroidTest, OnSyncShutdown) { + base::MockCallback<base::OnceClosure> mock_callback; + auto sync_controller = + std::make_unique<PasswordSyncControllerDelegateAndroid>( + CreateBridge(), mock_callback.Get()); + syncer::TestSyncService sync_service; + + EXPECT_CALL(mock_callback, Run); + sync_controller->OnSyncShutdown(&sync_service); +} + } // namespace password_manager
diff --git a/chrome/browser/resources/apc_internals/apc_internals.js b/chrome/browser/resources/apc_internals/apc_internals.js index 1726c734..5fb5ea2 100644 --- a/chrome/browser/resources/apc_internals/apc_internals.js +++ b/chrome/browser/resources/apc_internals/apc_internals.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {addWebUIListener} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener} from 'chrome://resources/js/cr.js'; import {$} from 'chrome://resources/js/util.js'; function createButton(text, onClickClosure) { @@ -158,14 +158,14 @@ } document.addEventListener('DOMContentLoaded', function(event) { - addWebUIListener('on-flags-information-received', onFlagsInfoReceived); - addWebUIListener('on-prefs-information-received', onPrefsInfoReceived); - addWebUIListener( + addWebUiListener('on-flags-information-received', onFlagsInfoReceived); + addWebUiListener('on-prefs-information-received', onPrefsInfoReceived); + addWebUiListener( 'on-script-fetching-information-received', onScriptFetchingInfoReceived); - addWebUIListener( + addWebUiListener( 'on-autofill-assistant-information-received', onAutofillAssistantInfoReceived); - addWebUIListener('on-script-cache-received', onScriptCacheReceived); + addWebUiListener('on-script-cache-received', onScriptCacheReceived); hideScriptCache(); $('script-cache-hide').onclick = hideScriptCache;
diff --git a/chrome/browser/resources/chromeos/cloud_upload/file_handler_page.html b/chrome/browser/resources/chromeos/cloud_upload/file_handler_page.html index e823e33..2a6392a 100644 --- a/chrome/browser/resources/chromeos/cloud_upload/file_handler_page.html +++ b/chrome/browser/resources/chromeos/cloud_upload/file_handler_page.html
@@ -41,6 +41,7 @@ display: flex; font: var(--cros-body-1-font); height: 54px; + margin-block-end: 4px; } .radio-label:has(> input[type='radio']) { @@ -76,7 +77,7 @@ <div class="icon-placeholder"></div> <span id="drive-app-name"></span> </label> - <div class="normal-text"> + <div class="normal-text" id="available-to-install"> Apps available to install </div>
diff --git a/chrome/browser/resources/chromeos/cloud_upload/file_handler_page.ts b/chrome/browser/resources/chromeos/cloud_upload/file_handler_page.ts index 7953d8a1b..b959ddcc 100644 --- a/chrome/browser/resources/chromeos/cloud_upload/file_handler_page.ts +++ b/chrome/browser/resources/chromeos/cloud_upload/file_handler_page.ts
@@ -38,9 +38,17 @@ // Sets the dynamic content of the page like the file name. async initDynamicContent() { try { - const dialogArgs = await this.proxy.handler.getDialogArgs(); + const [dialogArgs, {installed: isOfficePwaInstalled}] = + await Promise.all([ + this.proxy.handler.getDialogArgs(), + this.proxy.handler.isOfficePWAInstalled(), + ]); assert(dialogArgs.args); + if (isOfficePwaInstalled) { + this.shadowRoot!.querySelector('#available-to-install')!.remove(); + } + const fileNameElement = this.shadowRoot!.querySelector<HTMLSpanElement>('#file-name'); assert(fileNameElement);
diff --git a/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.html b/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.html index b6853955..49455f3 100644 --- a/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.html +++ b/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.html
@@ -1,3 +1,4 @@ +<!-- TODO(b/259386106): reduce duplication with login screen code --> <style> :host { --lock-screen-reauth-dialog-buttons-horizontal-padding: 40px; @@ -93,8 +94,8 @@ } #samlContainer[saml-notice-message] { - /* #F1F3F4 */ - background: rgb(241, 243, 244); + /* #FFFFFF */ + background: white; } #samlNoticeMessage { @@ -105,6 +106,18 @@ padding-top: 15px; } + #saml-footer-container { + align-items: center; + background: white; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.17); + /* #6a6a6a */ + color: rgb(106, 106, 106); + display: flex; + height: 58px; + justify-content: flex-end; + min-height: 0; + } + #saml-close-button { --cr-icon-button-margin-end: 0; --cr-icon-button-margin-start: 0; @@ -116,6 +129,12 @@ width: 100%; } + #change-account { + margin: 0 4px; + padding-inline-end: 8px; + padding-inline-start: 8px; + } + .title-icon { /* #1a73e8 */ --iron-icon-fill-color: rgb(26, 115, 232); @@ -292,6 +311,14 @@ </div> <webview id="signin-frame" name="signin-frame" class="flex"> </webview> + <div id="saml-footer-container" hidden="[[!isDefaultSsoProvider]]" + class="layout horizontal"> + <div>[[i18nDynamic(locale, 'samlChangeProviderMessage')]]</div> + <oobe-text-button id="change-account" + text-key="samlChangeProviderButton" + on-click="onChangeSigninProviderClicked_"> + </oobe-text-button> + </div> </div> <div id="samlConfirmPasswordScreen" class="content-wrapper"
diff --git a/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.js b/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.js index 1882ba46..bc9d2fe2 100644 --- a/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.js +++ b/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.js
@@ -13,6 +13,7 @@ import 'chrome://resources/cr_elements/cr_input/cr_input.js'; import 'chrome://resources/cr_elements/icons.html.js'; import 'chrome://resources/cr_elements/cr_shared_vars.css.js'; +import './components/buttons/oobe_text_button.js'; import './components/oobe_icons.m.js'; import {I18nBehavior} from 'chrome://resources/ash/common/i18n_behavior.js'; @@ -73,6 +74,14 @@ }, /** + * Whether default SAML IdP is shown. + */ + isDefaultSsoProvider: { + type: Boolean, + value: false, + }, + + /** * Whether there is a failure to scrape the user's password. */ isConfirmPassword_: { @@ -191,6 +200,7 @@ this.authenticatorParams_ = params; this.email_ = data.email; + this.isDefaultSsoProvider = data.doSamlRedirect; if (!data['doSamlRedirect']) { this.doGaiaRedirect_(); } @@ -381,4 +391,15 @@ 'passwordChangedIncorrectOldPassword'); }, + /** + * Invoked when "Enter Google Account info" button is pressed on SAML screen. + * @private + */ + onChangeSigninProviderClicked_() { + this.authenticatorParams_.doSamlRedirect = false; + this.authenticatorParams_.enableGaiaActionButtons = true; + this.isDefaultSsoProvider = false; + this.authenticator_.load(AuthMode.DEFAULT, this.authenticatorParams_); + }, + });
diff --git a/chrome/browser/resources/device_log_ui/device_log_ui.js b/chrome/browser/resources/device_log_ui/device_log_ui.js index 8fd3b5c..8335e5f 100644 --- a/chrome/browser/resources/device_log_ui/device_log_ui.js +++ b/chrome/browser/resources/device_log_ui/device_log_ui.js
@@ -4,7 +4,7 @@ import './strings.m.js'; -import {sendWithPromise} from 'chrome://resources/js/cr.m.js'; +import {sendWithPromise} from 'chrome://resources/js/cr.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {$} from 'chrome://resources/js/util.js';
diff --git a/chrome/browser/resources/family_link_user_internals/family_link_user_internals.js b/chrome/browser/resources/family_link_user_internals/family_link_user_internals.js index b4ed094..864bfd2 100644 --- a/chrome/browser/resources/family_link_user_internals/family_link_user_internals.js +++ b/chrome/browser/resources/family_link_user_internals/family_link_user_internals.js
@@ -4,7 +4,7 @@ import 'chrome://resources/js/jstemplate_compiled.js'; -import {addWebUIListener, sendWithPromise} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener, sendWithPromise} from 'chrome://resources/js/cr.js'; import {$} from 'chrome://resources/js/util.js'; function initialize() { @@ -24,9 +24,9 @@ // Make the prototype jscontent element disappear. jstProcess({}, $('filtering-results-container')); - addWebUIListener('basic-info-received', receiveBasicInfo); - addWebUIListener('user-settings-received', receiveUserSettings); - addWebUIListener('filtering-result-received', receiveFilteringResult); + addWebUiListener('basic-info-received', receiveBasicInfo); + addWebUiListener('user-settings-received', receiveUserSettings); + addWebUiListener('filtering-result-received', receiveFilteringResult); chrome.send('registerForEvents');
diff --git a/chrome/browser/resources/invalidations/about_invalidations.js b/chrome/browser/resources/invalidations/about_invalidations.js index 94630ff..21781f3 100644 --- a/chrome/browser/resources/invalidations/about_invalidations.js +++ b/chrome/browser/resources/invalidations/about_invalidations.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import 'chrome://resources/js/jstemplate_compiled.js'; -import {addWebUIListener} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener} from 'chrome://resources/js/cr.js'; import {$} from 'chrome://resources/js/util.js'; import {loadTestModule} from './test_loader_util.js'; @@ -195,15 +195,15 @@ * ready to receive real-time notifications. */ function onLoadWork() { - addWebUIListener('handlers-updated', handlers => updateHandlers(handlers)); - addWebUIListener( + addWebUiListener('handlers-updated', handlers => updateHandlers(handlers)); + addWebUiListener( 'state-updated', (state, lastChanged) => updateInvalidatorState(state, lastChanged)); - addWebUIListener( + addWebUiListener( 'ids-updated', (registrar, ids) => updateIds(registrar, ids)); - addWebUIListener( + addWebUiListener( 'log-invalidations', invalidations => logInvalidations(invalidations)); - addWebUIListener( + addWebUiListener( 'detailed-status-updated', networkDetails => updateDetailedStatus(networkDetails)); $('request-detailed-status').onclick = function() {
diff --git a/chrome/browser/resources/net_internals/browser_bridge.js b/chrome/browser/resources/net_internals/browser_bridge.js index 0411d18..41bc387 100644 --- a/chrome/browser/resources/net_internals/browser_bridge.js +++ b/chrome/browser/resources/net_internals/browser_bridge.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {sendWithPromise} from 'chrome://resources/js/cr.m.js'; +import {sendWithPromise} from 'chrome://resources/js/cr.js'; /** @type {?BrowserBridge} */ let instance = null;
diff --git a/chrome/browser/resources/ntp4/incognito_tab.js b/chrome/browser/resources/ntp4/incognito_tab.js index 78608423..5a955b13 100644 --- a/chrome/browser/resources/ntp4/incognito_tab.js +++ b/chrome/browser/resources/ntp4/incognito_tab.js
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {addWebUIListener} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener} from 'chrome://resources/js/cr.js'; import {$} from 'chrome://resources/js/util.js'; window.addEventListener('load', function() { let cookieSettingsUrl; - addWebUIListener('theme-changed', themeData => { + addWebUiListener('theme-changed', themeData => { document.documentElement.setAttribute( 'hascustombackground', themeData.hasCustomBackground); $('incognitothemecss').href = @@ -16,7 +16,7 @@ }); chrome.send('observeThemeChanges'); - addWebUIListener('cookie-controls-changed', dict => { + addWebUiListener('cookie-controls-changed', dict => { $('cookie-controls-tooltip-icon').hidden = !dict.enforced; $('cookie-controls-tooltip-icon').iconClass = dict.icon; $('cookie-controls-toggle').disabled = dict.enforced;
diff --git a/chrome/browser/resources/ntp4/new_tab.js b/chrome/browser/resources/ntp4/new_tab.js index d873b0f..b8a879a 100644 --- a/chrome/browser/resources/ntp4/new_tab.js +++ b/chrome/browser/resources/ntp4/new_tab.js
@@ -5,7 +5,7 @@ import './strings.m.js'; import {assert} from 'chrome://resources/js/assert.js'; -import {addWebUIListener} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener} from 'chrome://resources/js/cr.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {$, appendParam, getRequiredElement} from 'chrome://resources/js/util.js'; @@ -110,7 +110,7 @@ startTime = Date.now(); - addWebUIListener('theme-changed', () => { + addWebUiListener('theme-changed', () => { $('themecss').href = 'chrome://theme/css/new_tab_theme.css?' + Date.now(); }); chrome.send('observeThemeChanges');
diff --git a/chrome/browser/resources/settings/chromeos/os_privacy_page/privacy_hub_page.html b/chrome/browser/resources/settings/chromeos/os_privacy_page/privacy_hub_page.html index 386a867d..5519ab1 100644 --- a/chrome/browser/resources/settings/chromeos/os_privacy_page/privacy_hub_page.html +++ b/chrome/browser/resources/settings/chromeos/os_privacy_page/privacy_hub_page.html
@@ -1,7 +1,12 @@ <style include="settings-shared"> - iron-list > :not(:last-of-type) { + .list-item:not(:last-of-type) { border-bottom: var(--cr-separator-line); } + + .list-frame { + padding-bottom: 8px; + padding-top: 8px; + } </style> <div id="camera"> @@ -24,13 +29,11 @@ </template> <template is="dom-if" if="[[!isCameraListEmpty_]]" restamp> - <iron-list id="cameraList" items="[[camerasConnected_]]"> - <template> - <div class="list-item"> - [[item]] - </div> - </template> - </iron-list> + <template id="cameraList" is="dom-repeat" items="[[camerasConnected_]]"> + <div class="list-item"> + [[item]] + </div> + </template> </template> </div> </div> @@ -55,13 +58,11 @@ </template> <template is="dom-if" if="[[!isMicListEmpty_]]" restamp> - <iron-list id="micList" items="[[microphonesConnected_]]"> - <template> - <div class="list-item"> - [[item]] - </div> - </template> - </iron-list> + <template id="micList" is="dom-repeat" items="[[microphonesConnected_]]"> + <div class="list-item"> + [[item]] + </div> + </template> </template> </div> </div>
diff --git a/chrome/browser/signin/account_reconcilor_factory.cc b/chrome/browser/signin/account_reconcilor_factory.cc index d353893..c90dd191 100644 --- a/chrome/browser/signin/account_reconcilor_factory.cc +++ b/chrome/browser/signin/account_reconcilor_factory.cc
@@ -20,6 +20,7 @@ #include "components/signin/core/browser/mirror_account_reconcilor_delegate.h" #include "components/signin/public/base/account_consistency_method.h" #include "components/signin/public/base/signin_buildflags.h" +#include "components/signin/public/base/signin_client.h" #if BUILDFLAG(IS_CHROMEOS) #include "components/account_manager_core/chromeos/account_manager_facade_factory.h" @@ -218,7 +219,8 @@ case signin::AccountConsistencyMethod::kDice: #if BUILDFLAG(ENABLE_DICE_SUPPORT) return std::make_unique<signin::DiceAccountReconcilorDelegate>( - IdentityManagerFactory::GetForProfile(profile)); + IdentityManagerFactory::GetForProfile(profile), + ChromeSigninClientFactory::GetForProfile(profile)); #else NOTREACHED(); return nullptr;
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc index 58111bd7..f518588e 100644 --- a/chrome/browser/signin/chrome_signin_client.cc +++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -38,6 +38,7 @@ #include "components/prefs/pref_service.h" #include "components/signin/core/browser/cookie_settings_util.h" #include "components/signin/public/base/signin_buildflags.h" +#include "components/signin/public/base/signin_client.h" #include "components/signin/public/base/signin_pref_names.h" #include "components/signin/public/identity_manager/access_token_info.h" #include "components/signin/public/identity_manager/identity_manager.h" @@ -199,6 +200,11 @@ ->RemoveObserver(observer); } +bool ChromeSigninClient::IsClearPrimaryAccountAllowed() const { + return UserSignoutSettingToSignoutDecision(profile_) == + SigninClient::SignoutDecision::ALLOW; +} + void ChromeSigninClient::PreSignOut( base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached, signin_metrics::ProfileSignout signout_source_metric) {
diff --git a/chrome/browser/signin/chrome_signin_client.h b/chrome/browser/signin/chrome_signin_client.h index ad785bc..a743e48 100644 --- a/chrome/browser/signin/chrome_signin_client.h +++ b/chrome/browser/signin/chrome_signin_client.h
@@ -49,6 +49,7 @@ // SigninClient implementation. PrefService* GetPrefs() override; + bool IsClearPrimaryAccountAllowed() const override; void PreSignOut( base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached, signin_metrics::ProfileSignout signout_source_metric) override;
diff --git a/chrome/browser/signin/chrome_signin_client_unittest.cc b/chrome/browser/signin/chrome_signin_client_unittest.cc index be605b6f..69fe52d 100644 --- a/chrome/browser/signin/chrome_signin_client_unittest.cc +++ b/chrome/browser/signin/chrome_signin_client_unittest.cc
@@ -265,6 +265,8 @@ case signin_metrics::ProfileSignout:: IOS_ACCOUNT_REMOVED_FROM_DEVICE_AFTER_RESTORE: case signin_metrics::ProfileSignout::USER_DELETED_ACCOUNT_COOKIES: + case signin_metrics::ProfileSignout::GAIA_COOKIE_UPDATED: + case signin_metrics::ProfileSignout::ACCOUNT_RECONCILOR_RECONCILE: // There's no special-casing for these in ChromeSigninClient, as they only // happen when there's no sync account and policies aren't enforced. // PrimaryAccountManager won't actually invoke PreSignOut in this case, @@ -429,6 +431,8 @@ signin_metrics::ProfileSignout::ACCOUNT_EMAIL_UPDATED, signin_metrics::ProfileSignout:: USER_CLICKED_SIGNOUT_FROM_CLEAR_BROWSING_DATA_PAGE, + signin_metrics::ProfileSignout::GAIA_COOKIE_UPDATED, + signin_metrics::ProfileSignout::ACCOUNT_RECONCILOR_RECONCILE, }; // kNumberOfObsoleteSignoutSources should be updated when a ProfileSignout // value is deprecated.
diff --git a/chrome/browser/signin/dice_response_handler.cc b/chrome/browser/signin/dice_response_handler.cc index 646c139..159e15f 100644 --- a/chrome/browser/signin/dice_response_handler.cc +++ b/chrome/browser/signin/dice_response_handler.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/signin/identity_manager_factory.h" #include "components/signin/core/browser/about_signin_internals.h" #include "components/signin/core/browser/signin_header_helper.h" +#include "components/signin/public/base/consent_level.h" #include "components/signin/public/base/signin_client.h" #include "components/signin/public/base/signin_metrics.h" #include "components/signin/public/identity_manager/accounts_mutator.h" @@ -323,8 +324,14 @@ const std::vector<signin::DiceResponseParams::AccountInfo>& account_infos) { VLOG(1) << "Start processing Dice signout response"; - CoreAccountId primary_account = - identity_manager_->GetPrimaryAccountId(signin::ConsentLevel::kSync); + // If there is a restriction on removing the primary account. Do not remove + // the account regardless of the consent level. Else, the sync account can + // only be invalidated. + signin::ConsentLevel level = signin_client_->IsClearPrimaryAccountAllowed() + ? signin::ConsentLevel::kSync + : signin::ConsentLevel::kSignin; + + CoreAccountId primary_account = identity_manager_->GetPrimaryAccountId(level); bool primary_account_signed_out = false; auto* accounts_mutator = identity_manager_->GetAccountsMutator(); for (const auto& account_info : account_infos) {
diff --git a/chrome/browser/signin/dice_response_handler_unittest.cc b/chrome/browser/signin/dice_response_handler_unittest.cc index 3840333..1b30418 100644 --- a/chrome/browser/signin/dice_response_handler_unittest.cc +++ b/chrome/browser/signin/dice_response_handler_unittest.cc
@@ -36,6 +36,15 @@ const char kEmail[] = "test@email.com"; const int kSessionIndex = 42; +DiceResponseParams::AccountInfo GetDiceResponseParamsAccountInfo( + const std::string& email) { + DiceResponseParams::AccountInfo account_info; + account_info.gaia_id = signin::GetTestGaiaIdForEmail(email); + account_info.email = kEmail; + account_info.session_index = kSessionIndex; + return account_info; +} + // TestSigninClient implementation that intercepts the GaiaAuthConsumer and // replaces it by a dummy one. class DiceTestSigninClient : public TestSigninClient, public GaiaAuthConsumer { @@ -113,7 +122,7 @@ AboutSigninInternals::RegisterPrefs(pref_service_.registry()); auto account_reconcilor_delegate = std::make_unique<signin::DiceAccountReconcilorDelegate>( - identity_manager()); + identity_manager(), &signin_client_); account_reconcilor_ = std::make_unique<AccountReconcilor>( identity_test_env_.identity_manager(), &signin_client_, std::move(account_reconcilor_delegate)); @@ -140,10 +149,8 @@ DiceResponseParams MakeDiceParams(DiceAction action) { DiceResponseParams dice_params; dice_params.user_intention = action; - DiceResponseParams::AccountInfo account_info; - account_info.gaia_id = signin::GetTestGaiaIdForEmail(kEmail); - account_info.email = kEmail; - account_info.session_index = kSessionIndex; + DiceResponseParams::AccountInfo account_info = + GetDiceResponseParamsAccountInfo(kEmail); switch (action) { case DiceAction::SIGNIN: dice_params.signin_info = @@ -822,6 +829,53 @@ account_id_2)); } +TEST_F(DiceResponseHandlerTest, + SignoutMainNonSyncAccountWithSignoutRestrictions) { + signin_client_.set_is_clear_primary_account_allowed( + SigninClient::SignoutDecision::CLEAR_PRIMARY_ACCOUNT_DISALLOWED); + const char kSecondaryEmail[] = "other@gmail.com"; + DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNOUT); + dice_params.signout_info->account_infos.push_back( + GetDiceResponseParamsAccountInfo(kSecondaryEmail)); + const auto& dice_account_info = dice_params.signout_info->account_infos[0]; + AccountInfo account_info = identity_test_env_.MakePrimaryAccountAvailable( + dice_account_info.email, signin::ConsentLevel::kSignin); + AccountInfo secondary_account_info = + identity_test_env_.MakeAccountAvailable(kSecondaryEmail); + EXPECT_TRUE( + identity_manager()->HasAccountWithRefreshToken(account_info.account_id)); + EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken( + secondary_account_info.account_id)); + EXPECT_FALSE( + identity_manager()->HasPrimaryAccount(signin::ConsentLevel::kSync)); + EXPECT_TRUE( + identity_manager()->HasPrimaryAccount(signin::ConsentLevel::kSignin)); + // Receive signout response. + dice_response_handler_->ProcessDiceHeader( + dice_params, std::make_unique<TestProcessDiceHeaderDelegate>(this)); + // User is not signed out, token for the main account is now invalid. + // Secondary account removed. + EXPECT_TRUE( + identity_manager()->HasAccountWithRefreshToken(account_info.account_id)); + EXPECT_TRUE( + identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState( + account_info.account_id)); + auto error = identity_manager()->GetErrorStateOfRefreshTokenForAccount( + account_info.account_id); + EXPECT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, error.state()); + EXPECT_EQ(GoogleServiceAuthError::InvalidGaiaCredentialsReason:: + CREDENTIALS_REJECTED_BY_CLIENT, + error.GetInvalidGaiaCredentialsReason()); + EXPECT_FALSE(identity_manager()->HasAccountWithRefreshToken( + secondary_account_info.account_id)); + + EXPECT_TRUE( + identity_manager()->HasPrimaryAccount(signin::ConsentLevel::kSignin)); + // Check that the reconcilor was not blocked. + EXPECT_EQ(0, reconcilor_blocked_count_); + EXPECT_EQ(0, reconcilor_unblocked_count_); +} + // Tests that the DiceResponseHandler is created for a normal profile but not // for off-the-record profiles. TEST(DiceResponseHandlerFactoryTest, NotInOffTheRecord) {
diff --git a/chrome/browser/support_tool/support_tool_util.cc b/chrome/browser/support_tool/support_tool_util.cc index c2f0d50..a499b19 100644 --- a/chrome/browser/support_tool/support_tool_util.cc +++ b/chrome/browser/support_tool/support_tool_util.cc
@@ -7,6 +7,7 @@ #include <memory> #include <set> #include <string> +#include <vector> #include "base/files/file_path.h" #include "build/chromeos_buildflags.h" @@ -42,6 +43,45 @@ #endif // BUILDFLAG(IS_CHROMEOS_WITH_HW_DETAILS) #endif // BUILDFLAG(IS_CHROMEOS_ASH) +namespace { + +// Data collector types that can work on every platform. +constexpr support_tool::DataCollectorType kDataCollectors[] = { + support_tool::CHROME_INTERNAL, support_tool::CRASH_IDS, + support_tool::MEMORY_DETAILS, support_tool::POLICIES}; + +// Data collector types can only work on Chrome OS Ash. +constexpr support_tool::DataCollectorType kDataCollectorsChromeosAsh[] = { + support_tool::CHROMEOS_UI_HIERARCHY, + support_tool::CHROMEOS_COMMAND_LINE, + support_tool::CHROMEOS_DEVICE_EVENT, + support_tool::CHROMEOS_IWL_WIFI_DUMP, + support_tool::CHROMEOS_TOUCH_EVENTS, + support_tool::CHROMEOS_DBUS, + support_tool::CHROMEOS_NETWORK_ROUTES, + support_tool::CHROMEOS_SHILL, + support_tool::CHROMEOS_SYSTEM_STATE, + support_tool::CHROMEOS_SYSTEM_LOGS, + support_tool::CHROMEOS_CHROME_USER_LOGS, + support_tool::CHROMEOS_BLUETOOTH_FLOSS, + support_tool::CHROMEOS_CONNECTED_INPUT_DEVICES, + support_tool::CHROMEOS_TRAFFIC_COUNTERS, + support_tool::CHROMEOS_VIRTUAL_KEYBOARD}; + +// Data collector types that can only work on if IS_CHROMEOS_WITH_HW_DETAILS +// flag is turned on. IS_CHROMEOS_WITH_HW_DETAILS flag will be turned on for +// Chrome OS Flex devices. +constexpr support_tool::DataCollectorType kDataCollectorsChromeosHwDetails[] = { + support_tool::CHROMEOS_REVEN}; + +// Data collector types that may be available on the device depending on other +// components or flags. Currently consists of data collactors that collect +// logs for Lacros. +constexpr support_tool::DataCollectorType kOptionalDataCollectors[] = { + support_tool::CHROMEOS_CROS_API, support_tool::CHROMEOS_LACROS}; + +} // namespace + std::unique_ptr<SupportToolHandler> GetSupportToolHandler( std::string case_id, std::string email_address, @@ -201,3 +241,44 @@ } return handler; } + +std::vector<support_tool::DataCollectorType> GetAllDataCollectors() { + std::vector<support_tool::DataCollectorType> data_collectors; + for (const auto& type : kDataCollectors) { + data_collectors.push_back(type); + } + for (const auto& type : kDataCollectorsChromeosAsh) { + data_collectors.push_back(type); + } + for (const auto& type : kDataCollectorsChromeosHwDetails) { + data_collectors.push_back(type); + } + for (const auto& type : kOptionalDataCollectors) { + data_collectors.push_back(type); + } + return data_collectors; +} + +std::vector<support_tool::DataCollectorType> +GetAllAvailableDataCollectorsOnDevice() { + std::vector<support_tool::DataCollectorType> data_collectors; + for (const auto& type : kDataCollectors) { + data_collectors.push_back(type); + } +#if BUILDFLAG(IS_CHROMEOS_ASH) + for (const auto& type : kDataCollectorsChromeosAsh) { + data_collectors.push_back(type); + } + if (crosapi::browser_util::IsLacrosEnabled()) + data_collectors.push_back(support_tool::CHROMEOS_LACROS); + if (crosapi::BrowserManager::Get()->IsRunning() && + crosapi::BrowserManager::Get()->GetFeedbackDataSupported()) + data_collectors.push_back(support_tool::CHROMEOS_CROS_API); +#if BUILDFLAG(IS_CHROMEOS_WITH_HW_DETAILS) + for (const auto& type : kDataCollectorsChromeosHwDetails) { + data_collectors.push_back(type); + } +#endif // BUILDFLAG(IS_CHROMEOS_WITH_HW_DETAILS) +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + return data_collectors; +}
diff --git a/chrome/browser/support_tool/support_tool_util.h b/chrome/browser/support_tool/support_tool_util.h index 0b6ee0b..92cee75 100644 --- a/chrome/browser/support_tool/support_tool_util.h +++ b/chrome/browser/support_tool/support_tool_util.h
@@ -5,42 +5,14 @@ #ifndef CHROME_BROWSER_SUPPORT_TOOL_SUPPORT_TOOL_UTIL_H_ #define CHROME_BROWSER_SUPPORT_TOOL_SUPPORT_TOOL_UTIL_H_ +#include <set> +#include <vector> + #include "chrome/browser/support_tool/data_collection_module.pb.h" #include "chrome/browser/support_tool/support_tool_handler.h" class Profile; -// Data collector types that can work on every platform. -static constexpr support_tool::DataCollectorType kDataCollectors[] = { - support_tool::CHROME_INTERNAL, support_tool::CRASH_IDS, - support_tool::MEMORY_DETAILS, support_tool::POLICIES}; - -// Data collector types can only work on Chrome OS Ash. -static constexpr support_tool::DataCollectorType kDataCollectorsChromeosAsh[] = - {support_tool::CHROMEOS_UI_HIERARCHY, - support_tool::CHROMEOS_COMMAND_LINE, - support_tool::CHROMEOS_DEVICE_EVENT, - support_tool::CHROMEOS_IWL_WIFI_DUMP, - support_tool::CHROMEOS_TOUCH_EVENTS, - support_tool::CHROMEOS_CROS_API, - support_tool::CHROMEOS_LACROS, - support_tool::CHROMEOS_DBUS, - support_tool::CHROMEOS_NETWORK_ROUTES, - support_tool::CHROMEOS_SHILL, - support_tool::CHROMEOS_SYSTEM_STATE, - support_tool::CHROMEOS_SYSTEM_LOGS, - support_tool::CHROMEOS_CHROME_USER_LOGS, - support_tool::CHROMEOS_BLUETOOTH_FLOSS, - support_tool::CHROMEOS_CONNECTED_INPUT_DEVICES, - support_tool::CHROMEOS_TRAFFIC_COUNTERS, - support_tool::CHROMEOS_VIRTUAL_KEYBOARD}; - -// Data collector types that can only work on if IS_CHROMEOS_WITH_HW_DETAILS -// flag is turned on. IS_CHROMEOS_WITH_HW_DETAILS flag will be turned on for -// Chrome OS Flex devices. -static constexpr support_tool::DataCollectorType - kDataCollectorsChromeosHwDetails[] = {support_tool::CHROMEOS_REVEN}; - // Returns SupportToolHandler that is created for collecting logs from the // given information. Adds the corresponding DataCollectors that were listed in // `included_data_collectors` to the returned SupportToolHandler. @@ -51,4 +23,9 @@ Profile* profile, std::set<support_tool::DataCollectorType> included_data_collectors); +std::vector<support_tool::DataCollectorType> GetAllDataCollectors(); + +std::vector<support_tool::DataCollectorType> +GetAllAvailableDataCollectorsOnDevice(); + #endif // CHROME_BROWSER_SUPPORT_TOOL_SUPPORT_TOOL_UTIL_H_
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 2029edbf..33261c5 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -534,6 +534,7 @@ "//components/optimization_guide/optimization_guide_internals/webui", "//components/optimization_guide/optimization_guide_internals/webui:mojo_bindings", "//components/password_manager/content/browser", + "//components/password_manager/content/common", "//components/password_manager/core/browser", "//components/password_manager/core/browser:affiliation", "//components/password_manager/core/browser:import_results", @@ -1847,6 +1848,7 @@ "//components/network_session_configurator/common", "//components/page_load_metrics/browser", "//components/paint_preview/buildflags", + "//components/password_manager/content/common", "//components/performance_manager:site_data_proto", "//components/reading_list/features:flags", "//components/safe_browsing/core/common:safe_browsing_policy_handler", @@ -2097,8 +2099,6 @@ "app_list/search/common/string_util.h", "app_list/search/common/types_util.cc", "app_list/search/common/types_util.h", - "app_list/search/common/url_icon_source.cc", - "app_list/search/common/url_icon_source.h", "app_list/search/cros_action_history/cros_action_recorder.cc", "app_list/search/cros_action_history/cros_action_recorder.h", "app_list/search/cros_action_history/cros_action_recorder_tab_tracker.cc",
diff --git a/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc b/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc index 7923755..9b29d4a9 100644 --- a/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc +++ b/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc
@@ -126,7 +126,8 @@ suggestion.frontend_id == POPUP_ITEM_ID_MIXED_FORM_MESSAGE; Java_AutofillPopupBridge_addToAutofillSuggestionArray( - env, data_array, i, base::android::ConvertUTF16ToJavaString(env, label), + env, java_object_, data_array, i, + base::android::ConvertUTF16ToJavaString(env, label), base::android::ConvertUTF16ToJavaString(env, secondary_label), base::android::ConvertUTF16ToJavaString(env, sublabel), base::android::ConvertUTF16ToJavaString(env, secondary_sublabel),
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java index 5c01d8b..621c04c 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -976,7 +976,8 @@ Math.max(Math.max(mNtpSearchBoxScrollFraction, mStartSurfaceScrollFraction), mUrlFocusChangeFraction); for (UrlExpansionObserver observer : mUrlExpansionObservers) { - observer.onUrlExpansionProgressChanged(mUrlExpansionFraction); + observer.onUrlExpansionProgressChanged( + mUrlExpansionFraction, mUrlFocusChangeInProgress); } assert mUrlExpansionFraction >= 0; assert mUrlExpansionFraction <= 1;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java index 41e1558c..13e59de 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
@@ -67,8 +67,10 @@ * @param fraction The toolbar expansion progress. 0 indicates that the URL bar is not * expanded. 1 indicates that the URL bar is expanded to the maximum * width. + * + * @param changeInProgress Whether the toolbar animation is still in progress or not. */ - void onUrlExpansionProgressChanged(float fraction); + void onUrlExpansionProgressChanged(float fraction, boolean changeInProgress); } /**
diff --git a/chrome/browser/ui/app_list/search/chrome_search_result.h b/chrome/browser/ui/app_list/search/chrome_search_result.h index c32f661..e524026 100644 --- a/chrome/browser/ui/app_list/search/chrome_search_result.h +++ b/chrome/browser/ui/app_list/search/chrome_search_result.h
@@ -220,7 +220,7 @@ // obtained from. These can include scores from intermediate ranking steps, as // well as prototype scores to be inspected for experimentation. // - // TODO(crbug.com/1199206): Move this to a map<string, string> of debug info + // TODO(crbug.com/1292783): Move this to a map<string, string> of debug info // that contains more than just scores, and display the contents of // |scoring_| in chrome://launcher-internals base::flat_map<std::string, double> ranker_scores_;
diff --git a/chrome/browser/ui/app_list/search/common/url_icon_source.cc b/chrome/browser/ui/app_list/search/common/url_icon_source.cc deleted file mode 100644 index 19b6a4e..0000000 --- a/chrome/browser/ui/app_list/search/common/url_icon_source.cc +++ /dev/null
@@ -1,113 +0,0 @@ -// Copyright 2013 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/app_list/search/common/url_icon_source.h" - -#include <string> -#include <utility> - -#include "base/bind.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/storage_partition.h" -#include "net/base/load_flags.h" -#include "net/traffic_annotation/network_traffic_annotation.h" -#include "services/network/public/cpp/resource_request.h" -#include "services/network/public/cpp/simple_url_loader.h" -#include "services/network/public/mojom/url_loader_factory.mojom.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/image/image_skia_operations.h" -#include "ui/gfx/image/image_skia_rep.h" - -using content::BrowserThread; - -namespace app_list { - -UrlIconSource::UrlIconSource(IconLoadedCallback icon_loaded_callback, - content::BrowserContext* browser_context, - const GURL& icon_url, - int icon_size, - int default_icon_resource_id) - : icon_loaded_callback_(std::move(icon_loaded_callback)), - browser_context_(browser_context), - icon_url_(icon_url), - icon_size_(icon_size), - default_icon_resource_id_(default_icon_resource_id), - icon_fetch_attempted_(false) { - DCHECK(!icon_loaded_callback_.is_null()); -} - -UrlIconSource::~UrlIconSource() { -} - -void UrlIconSource::StartIconFetch() { - icon_fetch_attempted_ = true; - - auto resource_request = std::make_unique<network::ResourceRequest>(); - resource_request->url = icon_url_; - resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit; - net::NetworkTrafficAnnotationTag traffic_annotation = - net::DefineNetworkTrafficAnnotation("url_icon_source_fetch", R"( - semantics { - sender: "URL Icon Source" - description: - "Chrome OS downloads an app icon for display in the app list." - trigger: - "An icon/image needs to be downloaded to be displayed." - data: - "URL of the icon/image. " - "No user information is sent." - destination: WEBSITE - } - policy { - cookies_allowed: NO - setting: "Unconditionally enabled on Chrome OS." - policy_exception_justification: - "Not implemented, considered not useful." - })"); - simple_loader_ = network::SimpleURLLoader::Create(std::move(resource_request), - traffic_annotation); - network::mojom::URLLoaderFactory* loader_factory = - browser_context_->GetDefaultStoragePartition() - ->GetURLLoaderFactoryForBrowserProcess() - .get(); - simple_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( - loader_factory, base::BindOnce(&UrlIconSource::OnSimpleLoaderComplete, - base::Unretained(this))); -} - -gfx::ImageSkiaRep UrlIconSource::GetImageForScale(float scale) { - if (!icon_fetch_attempted_) - StartIconFetch(); - - if (!icon_.isNull()) - return icon_.GetRepresentation(scale); - - return ui::ResourceBundle::GetSharedInstance() - .GetImageSkiaNamed(default_icon_resource_id_)->GetRepresentation(scale); -} - -void UrlIconSource::OnSimpleLoaderComplete( - std::unique_ptr<std::string> response_body) { - if (!response_body) { - return; - } - - // Call start to begin decoding. The ImageDecoder will call OnImageDecoded - // with the data when it is done. - ImageDecoder::Start(this, std::move(*response_body)); -} - -void UrlIconSource::OnImageDecoded(const SkBitmap& decoded_image) { - const float scale = decoded_image.width() / icon_size_; - icon_ = gfx::ImageSkia::CreateFromBitmap(decoded_image, scale); - DCHECK(!icon_loaded_callback_.is_null()); - std::move(icon_loaded_callback_).Run(); -} - -void UrlIconSource::OnDecodeImageFailed() { - // Failed to decode image. Do nothing and just use the default icon. -} - -} // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/common/url_icon_source.h b/chrome/browser/ui/app_list/search/common/url_icon_source.h deleted file mode 100644 index 65505d4..0000000 --- a/chrome/browser/ui/app_list/search/common/url_icon_source.h +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2013 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_COMMON_URL_ICON_SOURCE_H_ -#define CHROME_BROWSER_UI_APP_LIST_SEARCH_COMMON_URL_ICON_SOURCE_H_ - -#include <memory> -#include <string> - -#include "base/callback.h" -#include "chrome/browser/image_decoder/image_decoder.h" -#include "ui/gfx/image/image_skia.h" -#include "ui/gfx/image/image_skia_source.h" -#include "url/gurl.h" - -namespace content { -class BrowserContext; -} - -namespace network { -class SimpleURLLoader; -} - -namespace app_list { - -// An ImageSkiaSource for icons fetched from a URL. Till the URL icon is -// fetched, the default icon (specified by it's resource id) is shown. -class UrlIconSource : public gfx::ImageSkiaSource, - public ImageDecoder::ImageRequest { - public: - typedef base::OnceClosure IconLoadedCallback; - - // Create a URL Icon source with the given URL. The post_process parameter - // specifies a function to post-process the result icon before displaying it. - UrlIconSource(IconLoadedCallback icon_loaded_callback, - content::BrowserContext* browser_context, - const GURL& icon_url, - int icon_size, - int default_icon_resource_id); - - UrlIconSource(const UrlIconSource&) = delete; - UrlIconSource& operator=(const UrlIconSource&) = delete; - - ~UrlIconSource() override; - - private: - // Invoked from GetImageForScale to download the app icon when the hosting - // ImageSkia gets painted on screen. - void StartIconFetch(); - - // Invoked from SimpleURLLoader after download is complete. - void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body); - - // gfx::ImageSkiaSource overrides: - gfx::ImageSkiaRep GetImageForScale(float scale) override; - - // ImageDecoder::ImageRequest overrides: - void OnImageDecoded(const SkBitmap& decoded_image) override; - void OnDecodeImageFailed() override; - - IconLoadedCallback icon_loaded_callback_; - content::BrowserContext* browser_context_; - const GURL icon_url_; - const int icon_size_; - const int default_icon_resource_id_; - - bool icon_fetch_attempted_; - std::unique_ptr<network::SimpleURLLoader> simple_loader_; - - gfx::ImageSkia icon_; -}; - -} // namespace app_list - -#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_COMMON_URL_ICON_SOURCE_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/launch_data.h b/chrome/browser/ui/app_list/search/ranking/launch_data.h index 9bd7424..b6af55cd 100644 --- a/chrome/browser/ui/app_list/search/ranking/launch_data.h +++ b/chrome/browser/ui/app_list/search/ranking/launch_data.h
@@ -24,7 +24,7 @@ ash::AppListSearchResultType result_type = ash::AppListSearchResultType::kUnknown; // The type of the result used for ranking. - // TODO(crbug.com/1199206): This is no longer needed and can be removed when + // TODO(crbug.com/1378861): This is no longer needed and can be removed when // the search_result_ranker/ directory is removed. RankingItemType ranking_item_type = RankingItemType::kUnknown; ash::AppListLaunchedFrom launched_from =
diff --git a/chrome/browser/ui/app_list/search/ranking/ranker_manager.cc b/chrome/browser/ui/app_list/search/ranking/ranker_manager.cc index f4d0f0e1..5a17ac29 100644 --- a/chrome/browser/ui/app_list/search/ranking/ranker_manager.cc +++ b/chrome/browser/ui/app_list/search/ranking/ranker_manager.cc
@@ -39,7 +39,6 @@ score_normalizer_params.max_bins = 5; // Result ranking parameters. - // TODO(crbug.com/1199206): These need tweaking. FtrlOptimizer::Params ftrl_result_params; ftrl_result_params.alpha = 0.1; ftrl_result_params.gamma = 0.1; @@ -51,7 +50,6 @@ mrfu_result_params.max_items = 200u; // Category ranking parameters. - // TODO(crbug.com/1199206): These need tweaking. FtrlOptimizer::Params ftrl_category_params; ftrl_category_params.alpha = 0.1; ftrl_category_params.gamma = 0.1;
diff --git a/chrome/browser/ui/app_list/search/ranking/util.h b/chrome/browser/ui/app_list/search/ranking/util.h index 97da8ebd..d9c626e 100644 --- a/chrome/browser/ui/app_list/search/ranking/util.h +++ b/chrome/browser/ui/app_list/search/ranking/util.h
@@ -22,7 +22,7 @@ Category StringToCategory(const std::string& value); -// TODO(crbug.com/1199206): This can be removed once LaunchData contains the +// TODO(crbug.com/1378862): This can be removed once LaunchData contains the // result category. // // This is slightly inconsistent with the true result->category mapping, because
diff --git a/chrome/browser/ui/app_list/search/search_controller_impl.cc b/chrome/browser/ui/app_list/search/search_controller_impl.cc index 8df8c361..df70ee1 100644 --- a/chrome/browser/ui/app_list/search/search_controller_impl.cc +++ b/chrome/browser/ui/app_list/search/search_controller_impl.cc
@@ -316,7 +316,7 @@ std::vector<ChromeSearchResult*> all_results; for (const auto& type_results : results_) { for (const auto& result : type_results.second) { - // TODO(crbug.com/1199206): Category-based search combines apps into the + // TODO(crbug.com/1385194): Category-based search combines apps into the // results list, so redirect any kTile results to kList before updating // the UI. Once SearchControllerImpl is the only search controller, // this can be removed and all results can be created as kList.
diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc index 6048fa0..cb56154 100644 --- a/chrome/browser/ui/browser_navigator.cc +++ b/chrome/browser/ui/browser_navigator.cc
@@ -44,6 +44,7 @@ #include "chrome/common/url_constants.h" #include "components/captive_portal/core/buildflags.h" #include "components/no_state_prefetch/browser/no_state_prefetch_manager.h" +#include "components/password_manager/content/common/web_ui_constants.h" #include "components/prefs/pref_service.h" #include "content/public/browser/browser_url_handler.h" #include "content/public/browser/navigation_entry.h" @@ -913,7 +914,7 @@ host != chrome::kChromeUIHistoryHost && host != chrome::kChromeUIExtensionsHost && host != chrome::kChromeUIBookmarksHost && - host != chrome::kChromeUIPasswordManagerHost; + host != password_manager::kChromeUIPasswordManagerHost; } bool IsURLAllowedInIncognito(const GURL& url,
diff --git a/chrome/browser/ui/passwords/password_generation_popup_controller_impl.h b/chrome/browser/ui/passwords/password_generation_popup_controller_impl.h index 068a555..a382dcb 100644 --- a/chrome/browser/ui/passwords/password_generation_popup_controller_impl.h +++ b/chrome/browser/ui/passwords/password_generation_popup_controller_impl.h
@@ -126,6 +126,10 @@ const zoom::ZoomController::ZoomChangedEventData& data) override; #endif // !BUILDFLAG(IS_ANDROID) +#if defined(UNIT_TEST) + PasswordGenerationPopupView* view() const { return view_; } +#endif + protected: PasswordGenerationPopupControllerImpl( const gfx::RectF& bounds, @@ -135,9 +139,6 @@ content::WebContents* web_contents, content::RenderFrameHost* frame); - // Handle to the popup. May be NULL if popup isn't showing. - raw_ptr<PasswordGenerationPopupView> view_; - private: class KeyPressRegistrator; // PasswordGenerationPopupController implementation: @@ -171,6 +172,9 @@ // Accept password if it's selected. bool PossiblyAcceptPassword(); + // Handle to the popup. May be NULL if popup isn't showing. + raw_ptr<PasswordGenerationPopupView> view_; + const autofill::FormData form_data_; base::WeakPtr<password_manager::PasswordManagerDriver> const driver_;
diff --git a/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc b/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc index 38c00008..051cb79 100644 --- a/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc +++ b/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc
@@ -6,117 +6,116 @@ #include <string> -#include "base/memory/raw_ptr.h" -#include "build/build_config.h" +#include "base/memory/weak_ptr.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/passwords/password_generation_popup_controller_impl.h" #include "chrome/browser/ui/passwords/password_generation_popup_view_tester.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" -#include "components/autofill/core/common/unique_ids.h" #include "components/password_manager/content/browser/content_password_manager_driver.h" #include "components/password_manager/content/browser/content_password_manager_driver_factory.h" #include "content/public/test/browser_test.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/events/event_utils.h" namespace autofill { -class TestPasswordGenerationPopupController - : public PasswordGenerationPopupControllerImpl { - public: - // |vertical_offset| specifies the vertical offset of the popup relative to - // the web contents container. - explicit TestPasswordGenerationPopupController( - content::WebContents* web_contents, - int vertical_offset = 0) - : PasswordGenerationPopupControllerImpl( - gfx::RectF(web_contents->GetContainerBounds().x(), - web_contents->GetContainerBounds().y() + vertical_offset, - 10, - 10), - autofill::password_generation::PasswordGenerationUIData( - /*bounds=*/gfx::RectF(web_contents->GetContainerBounds().x(), - web_contents->GetContainerBounds().y(), - 10, - 10), - /*max_length=*/10, - /*generation_element=*/std::u16string(), - /*user_typed_password=*/std::u16string(), - autofill::FieldRendererId(100), - /*is_generation_element_password_type=*/true, - /*text_direction=*/base::i18n::TextDirection(), - FormData()), - password_manager::ContentPasswordManagerDriverFactory:: - FromWebContents(web_contents) - ->GetDriverForFrame(web_contents->GetPrimaryMainFrame()) - ->AsWeakPtr(), - nullptr /* PasswordGenerationPopupObserver*/, - web_contents, - web_contents->GetPrimaryMainFrame()) {} - - ~TestPasswordGenerationPopupController() override {} - - PasswordGenerationPopupView* view() { return view_; } -}; - -class PasswordGenerationPopupViewTest : public InProcessBrowserTest { - public: - content::WebContents* GetWebContents() { - return browser()->tab_strip_model()->GetActiveWebContents(); - } - - std::unique_ptr<PasswordGenerationPopupViewTester> GetViewTester() { - return PasswordGenerationPopupViewTester::For(controller_->view()); - } - - protected: - raw_ptr<TestPasswordGenerationPopupController, DanglingUntriaged> controller_; -}; +class PasswordGenerationPopupViewTest : public InProcessBrowserTest {}; // Regression test for crbug.com/400543. Verifying that moving the mouse in the // editing dialog doesn't crash. IN_PROC_BROWSER_TEST_F(PasswordGenerationPopupViewTest, MouseMovementInEditingPopup) { - controller_ = - new autofill::TestPasswordGenerationPopupController(GetWebContents()); - controller_->Show(PasswordGenerationPopupController::kEditGeneratedPassword); - EXPECT_TRUE(controller_->IsVisible()); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + password_generation::PasswordGenerationUIData ui_data( + gfx::RectF(web_contents->GetContainerBounds().x(), + web_contents->GetContainerBounds().y(), 10, 10), + /*max_length=*/10, + /*generation_element=*/std::u16string(), + /*user_typed_password=*/std::u16string(), FieldRendererId(100), + /*is_generation_element_password_type=*/true, base::i18n::TextDirection(), + FormData()); - GetViewTester()->SimulateMouseMovementAt( - gfx::Point(GetWebContents()->GetContainerBounds().x() + 1, - GetWebContents()->GetContainerBounds().y() + 1)); + base::WeakPtr<PasswordGenerationPopupControllerImpl> controller = + PasswordGenerationPopupControllerImpl::GetOrCreate( + /*previous=*/nullptr, ui_data.bounds, ui_data, + password_manager::ContentPasswordManagerDriverFactory:: + FromWebContents(web_contents) + ->GetDriverForFrame(web_contents->GetPrimaryMainFrame()) + ->AsWeakPtr(), + /*observer=*/nullptr, web_contents, + web_contents->GetPrimaryMainFrame()); + + controller->Show(PasswordGenerationPopupController::kEditGeneratedPassword); + EXPECT_TRUE(controller->IsVisible()); + + PasswordGenerationPopupViewTester::For(controller->view()) + ->SimulateMouseMovementAt( + gfx::Point(web_contents->GetContainerBounds().x() + 1, + web_contents->GetContainerBounds().y() + 1)); // This hides the popup and destroys the controller. - GetWebContents()->Close(); + web_contents->Close(); } // Verify that destroying web contents with visible popup does not crash. IN_PROC_BROWSER_TEST_F(PasswordGenerationPopupViewTest, CloseWebContentsWithVisiblePopup) { - controller_ = - new autofill::TestPasswordGenerationPopupController(GetWebContents()); - controller_->Show(PasswordGenerationPopupController::kEditGeneratedPassword); - EXPECT_TRUE(controller_->IsVisible()); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + password_generation::PasswordGenerationUIData ui_data( + gfx::RectF(web_contents->GetContainerBounds().x(), + web_contents->GetContainerBounds().y(), 10, 10), + /*max_length=*/10, + /*generation_element=*/std::u16string(), + /*user_typed_password=*/std::u16string(), FieldRendererId(100), + /*is_generation_element_password_type=*/true, base::i18n::TextDirection(), + FormData()); - GetWebContents()->Close(); + base::WeakPtr<PasswordGenerationPopupControllerImpl> controller = + PasswordGenerationPopupControllerImpl::GetOrCreate( + /*previous=*/nullptr, ui_data.bounds, ui_data, + password_manager::ContentPasswordManagerDriverFactory:: + FromWebContents(web_contents) + ->GetDriverForFrame(web_contents->GetPrimaryMainFrame()) + ->AsWeakPtr(), + /*observer=*/nullptr, web_contents, + web_contents->GetPrimaryMainFrame()); + + controller->Show(PasswordGenerationPopupController::kEditGeneratedPassword); + EXPECT_TRUE(controller->IsVisible()); + + web_contents->Close(); } // Verify that controller is not crashed in case of insufficient vertical space // for showing popup. IN_PROC_BROWSER_TEST_F(PasswordGenerationPopupViewTest, - DoNotCrashInCaseOfInsuffucientVertialSpace) { - // TODO(crbug.com/1365893): Remove TestPasswordGenerationPopupController class - // so that only GetOrCreate() would be used and then GetWeakPtr() won't be - // needed. - controller_ = new autofill::TestPasswordGenerationPopupController( - GetWebContents(), /*vertical_offset=*/-20); - base::WeakPtr<PasswordGenerationPopupControllerImpl> weak_controller = - controller_->GetWeakPtr(); - controller_->Show(PasswordGenerationPopupController::kEditGeneratedPassword); - // Check that the object |controller_| points to was invalidated. - EXPECT_FALSE(weak_controller); + DoNotCrashInCaseOfInsuffucientVerticalSpace) { + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + password_generation::PasswordGenerationUIData ui_data( + gfx::RectF(web_contents->GetContainerBounds().x(), + web_contents->GetContainerBounds().y() - 20, 10, 10), + /*max_length=*/10, + /*generation_element=*/std::u16string(), + /*user_typed_password=*/std::u16string(), FieldRendererId(100), + /*is_generation_element_password_type=*/true, base::i18n::TextDirection(), + FormData()); + + base::WeakPtr<PasswordGenerationPopupControllerImpl> controller = + PasswordGenerationPopupControllerImpl::GetOrCreate( + /*previous=*/nullptr, ui_data.bounds, ui_data, + password_manager::ContentPasswordManagerDriverFactory:: + FromWebContents(web_contents) + ->GetDriverForFrame(web_contents->GetPrimaryMainFrame()) + ->AsWeakPtr(), + /*observer=*/nullptr, web_contents, + web_contents->GetPrimaryMainFrame()); + + controller->Show(PasswordGenerationPopupController::kEditGeneratedPassword); + // Check that the object `controller` points to was invalidated. + EXPECT_FALSE(controller); } } // namespace autofill
diff --git a/chrome/browser/ui/webui/ash/in_session_password_change/lock_screen_start_reauth_ui.cc b/chrome/browser/ui/webui/ash/in_session_password_change/lock_screen_start_reauth_ui.cc index b85239f5..3e27d38e 100644 --- a/chrome/browser/ui/webui/ash/in_session_password_change/lock_screen_start_reauth_ui.cc +++ b/chrome/browser/ui/webui/ash/in_session_password_change/lock_screen_start_reauth_ui.cc
@@ -9,6 +9,7 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/ui/webui/ash/in_session_password_change/lock_screen_reauth_handler.h" +#include "chrome/browser/ui/webui/ash/login/oobe_ui.h" #include "chrome/browser/ui/webui/metrics_handler.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/browser_resources.h" @@ -110,17 +111,19 @@ "passwordChangedOldPasswordHint", l10n_util::GetStringUTF16(IDS_LOCK_PASSWORD_CHANGED_OLD_PASSWORD_HINT)); + source->AddString( + "samlChangeProviderMessage", + l10n_util::GetStringUTF16(IDS_LOGIN_SAML_CHANGE_PROVIDER_MESSAGE)); + source->AddString( + "samlChangeProviderButton", + l10n_util::GetStringUTF16(IDS_LOGIN_SAML_CHANGE_PROVIDER_BUTTON)); + source->AddResourcePaths( base::make_span(kPasswordChangeResources, kPasswordChangeResourcesSize)); source->SetDefaultResource(IDR_PASSWORD_CHANGE_LOCK_SCREEN_REAUTH_APP_HTML); - // Add Gaia Authenticator resources - source->AddResourcePaths( - base::make_span(kGaiaAuthHostResources, kGaiaAuthHostResourcesSize)); - - // Add OOBE resources - source->AddResourcePaths(base::make_span(kOobeUnconditionalResources, - kOobeUnconditionalResourcesSize)); + // Add OOBE and Gaia Authenticator resources + OobeUI::AddOobeComponents(source); content::WebUIDataSource::Add(profile, source); }
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index 8e58900..bfc2ebe 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -84,6 +84,7 @@ #include "components/history_clusters/history_clusters_internals/webui/url_constants.h" #include "components/nacl/common/buildflags.h" #include "components/optimization_guide/optimization_guide_internals/webui/url_constants.h" +#include "components/password_manager/content/common/web_ui_constants.h" #include "components/prefs/pref_service.h" #include "components/reading_list/features/reading_list_switches.h" #include "components/safe_browsing/buildflags.h" @@ -861,7 +862,7 @@ url.host_piece() == chrome::kChromeUIExtensionsHost || url.host_piece() == chrome::kChromeUINewTabPageHost || url.host_piece() == chrome::kChromeUINewTabPageThirdPartyHost || - url.host_piece() == chrome::kChromeUIPasswordManagerHost)) { + url.host_piece() == password_manager::kChromeUIPasswordManagerHost)) { return &NewWebUI<PageNotAvailableForGuestUI>; } if (url.host_piece() == chrome::kChromeUIAppServiceInternalsHost) @@ -869,7 +870,7 @@ // Bookmarks are part of NTP on Android. if (url.host_piece() == chrome::kChromeUIBookmarksHost) return &NewWebUI<BookmarksUI>; - if (url.host_piece() == chrome::kChromeUIPasswordManagerHost && + if (url.host_piece() == password_manager::kChromeUIPasswordManagerHost && base::FeatureList::IsEnabled( password_manager::features::kPasswordManagerRedesign)) return &NewWebUI<PasswordManagerUI>; @@ -1396,7 +1397,7 @@ if (page_url.host_piece() == chrome::kChromeUIHistoryHost) return HistoryUI::GetFaviconResourceBytes(scale_factor); - if (page_url.host_piece() == chrome::kChromeUIPasswordManagerHost) + if (page_url.host_piece() == password_manager::kChromeUIPasswordManagerHost) return PasswordManagerUI::GetFaviconResourceBytes(scale_factor); // Android uses the native download manager.
diff --git a/chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.cc b/chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.cc index 33758bae..e26af95 100644 --- a/chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.cc +++ b/chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.cc
@@ -9,6 +9,7 @@ #include "chrome/common/url_constants.h" #include "chrome/grit/browser_resources.h" #include "chrome/grit/generated_resources.h" +#include "components/password_manager/content/common/web_ui_constants.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" @@ -28,7 +29,7 @@ page_title = l10n_util::GetStringUTF16(IDS_HISTORY_TITLE); else if (host_name == chrome::kChromeUIExtensionsHost) page_title = l10n_util::GetStringUTF16(IDS_EXTENSIONS_TOOLBAR_TITLE); - else if (host_name == chrome::kChromeUIPasswordManagerHost) + else if (host_name == password_manager::kChromeUIPasswordManagerHost) page_title = l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_UI_TITLE); else page_title = base::UTF8ToUTF16(host_name);
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 70f2ca0..f65c71b 100644 --- a/chrome/browser/ui/webui/password_manager/password_manager_ui.cc +++ b/chrome/browser/ui/webui/password_manager/password_manager_ui.cc
@@ -15,6 +15,7 @@ #include "chrome/grit/password_manager_resources.h" #include "chrome/grit/password_manager_resources_map.h" #include "components/grit/components_scaled_resources.h" +#include "components/password_manager/content/common/web_ui_constants.h" #include "content/public/browser/web_ui_data_source.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" @@ -23,8 +24,8 @@ namespace { content::WebUIDataSource* CreatePasswordsUIHTMLSource(Profile* profile) { - content::WebUIDataSource* source = - content::WebUIDataSource::Create(chrome::kChromeUIPasswordManagerHost); + content::WebUIDataSource* source = content::WebUIDataSource::Create( + password_manager::kChromeUIPasswordManagerHost); webui::SetupWebUIDataSource( source,
diff --git a/chrome/browser/ui/webui/support_tool/support_tool_ui.cc b/chrome/browser/ui/webui/support_tool/support_tool_ui.cc index e33790a..baf1899 100644 --- a/chrome/browser/ui/webui/support_tool/support_tool_ui.cc +++ b/chrome/browser/ui/webui/support_tool/support_tool_ui.cc
@@ -212,7 +212,7 @@ AllowJavascript(); CHECK_EQ(1U, args.size()); const base::Value& callback_id = args[0]; - ResolveJavascriptCallback(callback_id, GetAllDataCollectors()); + ResolveJavascriptCallback(callback_id, GetAllDataCollectorItems()); } // Starts data collection with the issue details and selected set of data
diff --git a/chrome/browser/ui/webui/support_tool/support_tool_ui_utils.cc b/chrome/browser/ui/webui/support_tool/support_tool_ui_utils.cc index c54c4e6b..ec1ffe5 100644 --- a/chrome/browser/ui/webui/support_tool/support_tool_ui_utils.cc +++ b/chrome/browser/ui/webui/support_tool/support_tool_ui_utils.cc
@@ -303,51 +303,25 @@ base::Value::List data_collector_list; support_tool::DataCollectionModule module; InitDataCollectionModuleFromURLQuery(&module, module_query); - for (const auto& type : kDataCollectors) { + for (const auto& type : GetAllAvailableDataCollectorsOnDevice()) { data_collector_list.Append(GetDataCollectorItemForType(module, type)); } -#if BUILDFLAG(IS_CHROMEOS_ASH) - for (const auto& type : kDataCollectorsChromeosAsh) { - data_collector_list.Append(GetDataCollectorItemForType(module, type)); - } -#if BUILDFLAG(IS_CHROMEOS_WITH_HW_DETAILS) - for (const auto& type : kDataCollectorsChromeosHwDetails) { - data_collector_list.Append(GetDataCollectorItemForType(module, type)); - } -#endif // BUILDFLAG(IS_CHROMEOS_WITH_HW_DETAILS) -#endif // BUILDFLAG(IS_CHROMEOS_ASH) return data_collector_list; } -base::Value::List GetAllDataCollectors() { +base::Value::List GetAllDataCollectorItems() { base::Value::List data_collector_list; - for (const auto& type : kDataCollectors) { - data_collector_list.Append(GetDataCollectorItemForType(type)); - } - for (const auto& type : kDataCollectorsChromeosAsh) { - data_collector_list.Append(GetDataCollectorItemForType(type)); - } - for (const auto& type : kDataCollectorsChromeosHwDetails) { + for (const auto& type : GetAllDataCollectors()) { data_collector_list.Append(GetDataCollectorItemForType(type)); } return data_collector_list; } -base::Value::List GetAllDataCollectorsForDevice() { +base::Value::List GetAllDataCollectorItemsForDeviceForTesting() { base::Value::List data_collector_list; - for (const auto& type : kDataCollectors) { + for (const auto& type : GetAllAvailableDataCollectorsOnDevice()) { data_collector_list.Append(GetDataCollectorItemForType(type)); } -#if BUILDFLAG(IS_CHROMEOS_ASH) - for (const auto& type : kDataCollectorsChromeosAsh) { - data_collector_list.Append(GetDataCollectorItemForType(type)); - } -#if BUILDFLAG(IS_CHROMEOS_WITH_HW_DETAILS) - for (const auto& type : kDataCollectorsChromeosHwDetails) { - data_collector_list.Append(GetDataCollectorItemForType(type)); - } -#endif // BUILDFLAG(IS_CHROMEOS_WITH_HW_DETAILS) -#endif // BUILDFLAG(IS_CHROMEOS_ASH) return data_collector_list; }
diff --git a/chrome/browser/ui/webui/support_tool/support_tool_ui_utils.h b/chrome/browser/ui/webui/support_tool/support_tool_ui_utils.h index 77582d2..a797b74 100644 --- a/chrome/browser/ui/webui/support_tool/support_tool_ui_utils.h +++ b/chrome/browser/ui/webui/support_tool/support_tool_ui_utils.h
@@ -85,6 +85,7 @@ // protoEnum: number, // } // Returns only the data collectors that are available for user's device. +// Sets `isIncluded` as false for all items if `module_query` is empty. base::Value::List GetDataCollectorItemsInQuery(std::string module_query); // Creates base::Value::List according to the format Support Tool UI @@ -96,13 +97,13 @@ // isIncluded: boolean, // protoEnum: number, // } -base::Value::List GetAllDataCollectors(); +base::Value::List GetAllDataCollectorItems(); // Creates base::Value::List according to the format Support Tool UI // accepts and fills the contents with all data collectors with isIncluded: // false as a default choice. Only return data collectors available for caller's // platform. -base::Value::List GetAllDataCollectorsForDevice(); +base::Value::List GetAllDataCollectorItemsForDeviceForTesting(); std::set<support_tool::DataCollectorType> GetIncludedDataCollectorTypes( const base::Value::List* data_collector_items);
diff --git a/chrome/browser/ui/webui/support_tool/support_tool_ui_utils_unittest.cc b/chrome/browser/ui/webui/support_tool/support_tool_ui_utils_unittest.cc index f32fbb33..98246f1 100644 --- a/chrome/browser/ui/webui/support_tool/support_tool_ui_utils_unittest.cc +++ b/chrome/browser/ui/webui/support_tool/support_tool_ui_utils_unittest.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/webui/support_tool/support_tool_ui_utils.h" +#include <memory> #include <set> #include <string> @@ -14,12 +15,17 @@ #include "chrome/browser/support_tool/data_collection_module.pb.h" #include "chrome/browser/support_tool/data_collector.h" #include "components/feedback/pii_types.h" +#include "content/public/test/browser_task_environment.h" #include "net/base/url_util.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "chrome/browser/ash/crosapi/fake_browser_manager.h" +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + using ::testing::ContainerEq; using ::testing::IsEmpty; using ::testing::Not; @@ -56,9 +62,14 @@ class SupportToolUiUtilsTest : public ::testing::Test { public: - SupportToolUiUtilsTest() = default; + SupportToolUiUtilsTest() +#if BUILDFLAG(IS_CHROMEOS_ASH) + : browser_manager_(std::make_unique<crosapi::FakeBrowserManager>()){} +#else + = default; +#endif // BUILDFLAG(IS_CHROMEOS_ASH) - SupportToolUiUtilsTest(const SupportToolUiUtilsTest&) = delete; + SupportToolUiUtilsTest(const SupportToolUiUtilsTest&) = delete; SupportToolUiUtilsTest& operator=(const SupportToolUiUtilsTest&) = delete; // Change included field of `included_data_collectors` in `data_collectors` as @@ -78,6 +89,12 @@ data_collector_item.Set(support_tool_ui::kDataCollectorIncluded, true); } } + + private: + content::BrowserTaskEnvironment task_environment_; +#if BUILDFLAG(IS_CHROMEOS_ASH) + std::unique_ptr<crosapi::FakeBrowserManager> browser_manager_; +#endif // BUILDFLAG(IS_CHROMEOS_ASH) }; TEST_F(SupportToolUiUtilsTest, PiiItems) { @@ -120,7 +137,8 @@ TEST_F(SupportToolUiUtilsTest, CustomizedUrl) { const std::string test_case_id = "test_case_id_0"; // Get list of all data collectors. - base::Value::List expected_data_collectors = GetAllDataCollectorsForDevice(); + base::Value::List expected_data_collectors = + GetAllDataCollectorItemsForDeviceForTesting(); std::set<support_tool::DataCollectorType> included_data_collectors = { support_tool::DataCollectorType::CHROME_INTERNAL, support_tool::DataCollectorType::CRASH_IDS};
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index 3dc8d0e..603741f 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -339,6 +339,7 @@ "//components/device_event_log", "//components/keep_alive_registry:keep_alive_registry", "//components/keyed_service/content", + "//components/password_manager/content/common", "//components/performance_manager", "//components/permissions:permissions", "//components/pref_registry",
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.cc index 63fe5ca..ce70f42 100644 --- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.cc +++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.h" #include <memory> +#include <utility> #include "base/bind.h" #include "base/callback.h" @@ -174,29 +175,40 @@ DCHECK(cache_entry_it != reader_cache_.End()); DCHECK_EQ(cache_entry_it->second.state, Cache::Entry::State::kPending); - absl::optional<ReadResponseError> error; + absl::optional< + std::pair<ReadResponseError, ReadIntegrityBlockAndMetadataStatus>> + error_and_status; if (read_integrity_block_and_metadata_error.has_value()) { - error = - ReadResponseError::ForError(*read_integrity_block_and_metadata_error); + error_and_status = std::make_pair( + ReadResponseError::ForError(*read_integrity_block_and_metadata_error), + GetStatusFromError(*read_integrity_block_and_metadata_error)); } SignedWebBundleReader& reader = cache_entry_it->second.GetReader(); - if (!error.has_value()) { + if (!error_and_status.has_value()) { if (auto error_message = validator_->ValidateMetadata( web_bundle_id, reader.GetPrimaryURL(), reader.GetEntries()); error_message.has_value()) { - error = ReadResponseError::ForMetadataValidationError(*error_message); + error_and_status = std::make_pair( + ReadResponseError::ForMetadataValidationError(*error_message), + ReadIntegrityBlockAndMetadataStatus::kMetadataValidationError); } } + base::UmaHistogramEnumeration( + "WebApp.Isolated.ReadIntegrityBlockAndMetadataStatus", + error_and_status.has_value() + ? error_and_status->second + : ReadIntegrityBlockAndMetadataStatus::kSuccess); + std::vector<std::pair<network::ResourceRequest, ReadResponseCallback>> pending_requests = std::exchange(cache_entry_it->second.pending_requests, {}); - if (error.has_value()) { + if (error_and_status.has_value()) { for (auto& [resource_request, callback] : pending_requests) { - std::move(callback).Run(base::unexpected(*error)); + std::move(callback).Run(base::unexpected(error_and_status->first)); } reader_cache_.Erase(cache_entry_it); return; @@ -260,6 +272,52 @@ std::move(callback).Run(Response(std::move(*response_head), reader)); } +IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus +IsolatedWebAppReaderRegistry::GetStatusFromError( + const SignedWebBundleReader::ReadIntegrityBlockAndMetadataError& error) { + return absl::visit( + base::Overloaded{ + [](const web_package::mojom::BundleIntegrityBlockParseErrorPtr& + error) { + switch (error->type) { + case web_package::mojom::BundleParseErrorType:: + kParserInternalError: + return ReadIntegrityBlockAndMetadataStatus:: + kIntegrityBlockParserInternalError; + case web_package::mojom::BundleParseErrorType::kFormatError: + return ReadIntegrityBlockAndMetadataStatus:: + kIntegrityBlockParserFormatError; + case web_package::mojom::BundleParseErrorType::kVersionError: + return ReadIntegrityBlockAndMetadataStatus:: + kIntegrityBlockParserVersionError; + } + }, + [](const SignedWebBundleReader::AbortedByCaller& error) { + return ReadIntegrityBlockAndMetadataStatus:: + kIntegrityBlockValidationError; + }, + [](const web_package::SignedWebBundleSignatureVerifier::Error& + error) { + return ReadIntegrityBlockAndMetadataStatus:: + kSignatureVerificationError; + }, + [](const web_package::mojom::BundleMetadataParseErrorPtr& error) { + switch (error->type) { + case web_package::mojom::BundleParseErrorType:: + kParserInternalError: + return ReadIntegrityBlockAndMetadataStatus:: + kMetadataParserInternalError; + case web_package::mojom::BundleParseErrorType::kFormatError: + return ReadIntegrityBlockAndMetadataStatus:: + kMetadataParserFormatError; + case web_package::mojom::BundleParseErrorType::kVersionError: + return ReadIntegrityBlockAndMetadataStatus:: + kMetadataParserVersionError; + } + }}, + error); +} + IsolatedWebAppReaderRegistry::Response::Response( web_package::mojom::BundleResponsePtr head, base::WeakPtr<SignedWebBundleReader> reader)
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.h b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.h index aba69d5c..7382770d 100644 --- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.h +++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.h
@@ -127,6 +127,31 @@ const network::ResourceRequest& resource_request, ReadResponseCallback callback); + // This enum represents every error type that can occur during integrity block + // and metadata parsing, before responses are read from Signed Web Bundles. + // + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + enum class ReadIntegrityBlockAndMetadataStatus { + kSuccess = 0, + // Integrity Block-related errors + kIntegrityBlockParserInternalError = 1, + kIntegrityBlockParserFormatError = 2, + kIntegrityBlockParserVersionError = 3, + kIntegrityBlockValidationError = 4, + + // Signature verification errors + kSignatureVerificationError = 5, + + // Metadata-related errors + kMetadataParserInternalError = 6, + kMetadataParserFormatError = 7, + kMetadataParserVersionError = 8, + kMetadataValidationError = 9, + + kMaxValue = kMetadataValidationError + }; + private: FRIEND_TEST_ALL_PREFIXES(IsolatedWebAppReaderRegistryTest, TestConcurrentRequests); @@ -162,6 +187,9 @@ base::expected<web_package::mojom::BundleResponsePtr, SignedWebBundleReader::ReadResponseError> response_head); + ReadIntegrityBlockAndMetadataStatus GetStatusFromError( + const SignedWebBundleReader::ReadIntegrityBlockAndMetadataError& error); + enum class ReaderCacheState; // A thin wrapper around `base::flat_map<base::FilePath, Cache::Entry>` that
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry_unittest.cc index b67d2c1..390a5b1 100644 --- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry_unittest.cc +++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry_unittest.cc
@@ -199,6 +199,8 @@ IsolatedWebAppReaderRegistry::ReadResponseError>; TEST_F(IsolatedWebAppReaderRegistryTest, TestSingleRequest) { + base::HistogramTester histogram_tester; + network::ResourceRequest resource_request; resource_request.url = kPrimaryUrl; @@ -214,6 +216,12 @@ ASSERT_TRUE(result.has_value()) << result.error().message; EXPECT_EQ(result->head()->response_code, 200); + histogram_tester.ExpectBucketCount( + "WebApp.Isolated.ReadIntegrityBlockAndMetadataStatus", + IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus:: + kSuccess, + 1); + std::string response_body = ReadAndFulfillResponseBody( result->head()->payload_length, base::BindOnce(&IsolatedWebAppReaderRegistry::Response::ReadBody, @@ -417,7 +425,17 @@ "Pending Tasks have been logged."); } -TEST_F(IsolatedWebAppReaderRegistryTest, TestInvalidIntegrityBlock) { +class IsolatedWebAppReaderRegistryIntegrityBlockParserErrorTest + : public IsolatedWebAppReaderRegistryTest, + public ::testing::WithParamInterface<std::pair< + web_package::mojom::BundleParseErrorType, + IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus>> { +}; + +TEST_P(IsolatedWebAppReaderRegistryIntegrityBlockParserErrorTest, + TestIntegrityBlockParserError) { + base::HistogramTester histogram_tester; + network::ResourceRequest resource_request; resource_request.url = kPrimaryUrl; @@ -426,6 +444,7 @@ read_response_future.GetCallback()); auto error = web_package::mojom::BundleIntegrityBlockParseError::New(); + error->type = GetParam().first; error->message = "test error"; parser_factory_->RunIntegrityBlockCallback(nullptr, std::move(error)); @@ -435,9 +454,32 @@ IsolatedWebAppReaderRegistry::ReadResponseError::Type::kOtherError); EXPECT_EQ(result.error().message, "Failed to parse integrity block: test error"); + + histogram_tester.ExpectBucketCount( + "WebApp.Isolated.ReadIntegrityBlockAndMetadataStatus", GetParam().second, + 1); } +INSTANTIATE_TEST_SUITE_P( + All, + IsolatedWebAppReaderRegistryIntegrityBlockParserErrorTest, + ::testing::Values( + std::make_pair( + web_package::mojom::BundleParseErrorType::kParserInternalError, + IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus:: + kIntegrityBlockParserInternalError), + std::make_pair( + web_package::mojom::BundleParseErrorType::kVersionError, + IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus:: + kIntegrityBlockParserVersionError), + std::make_pair( + web_package::mojom::BundleParseErrorType::kFormatError, + IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus:: + kIntegrityBlockParserFormatError))); + TEST_F(IsolatedWebAppReaderRegistryTest, TestInvalidIntegrityBlockContents) { + base::HistogramTester histogram_tester; + network::ResourceRequest resource_request; resource_request.url = kPrimaryUrl; @@ -461,6 +503,12 @@ IsolatedWebAppReaderRegistry::ReadResponseError::Type::kOtherError); EXPECT_EQ(result.error().message, "Failed to validate integrity block: test error"); + + histogram_tester.ExpectBucketCount( + "WebApp.Isolated.ReadIntegrityBlockAndMetadataStatus", + IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus:: + kIntegrityBlockValidationError, + 1); } class IsolatedWebAppReaderRegistrySignatureVerificationErrorTest @@ -470,6 +518,8 @@ TEST_P(IsolatedWebAppReaderRegistrySignatureVerificationErrorTest, SignatureVerificationError) { + base::HistogramTester histogram_tester; + network::ResourceRequest resource_request; resource_request.url = kPrimaryUrl; @@ -497,6 +547,12 @@ ReadResult result = read_response_future.Take(); ASSERT_TRUE(result.has_value()) << result.error().message; + + histogram_tester.ExpectBucketCount( + "WebApp.Isolated.ReadIntegrityBlockAndMetadataStatus", + IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus:: + kSuccess, + 1); #else ReadResult result = read_response_future.Take(); ASSERT_FALSE(result.has_value()); @@ -505,6 +561,12 @@ EXPECT_EQ(result.error().message, base::StringPrintf("Failed to verify signatures: %s", GetParam().message.c_str())); + + histogram_tester.ExpectBucketCount( + "WebApp.Isolated.ReadIntegrityBlockAndMetadataStatus", + IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus:: + kSignatureVerificationError, + 1); #endif // BUILDFLAG(IS_CHROMEOS) } @@ -517,7 +579,17 @@ web_package::SignedWebBundleSignatureVerifier::Error:: ForInvalidSignature("invalid signature"))); -TEST_F(IsolatedWebAppReaderRegistryTest, TestInvalidMetadata) { +class IsolatedWebAppReaderRegistryMetadataParserErrorTest + : public IsolatedWebAppReaderRegistryTest, + public ::testing::WithParamInterface<std::pair< + web_package::mojom::BundleParseErrorType, + IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus>> { +}; + +TEST_P(IsolatedWebAppReaderRegistryMetadataParserErrorTest, + TestMetadataParserError) { + base::HistogramTester histogram_tester; + network::ResourceRequest resource_request; resource_request.url = kPrimaryUrl; @@ -528,6 +600,7 @@ FulfillIntegrityBlock(); auto error = web_package::mojom::BundleMetadataParseError::New(); error->message = "test error"; + error->type = GetParam().first; parser_factory_->RunMetadataCallback(integrity_block_->size, nullptr, std::move(error)); @@ -536,9 +609,32 @@ EXPECT_EQ(result.error().type, IsolatedWebAppReaderRegistry::ReadResponseError::Type::kOtherError); EXPECT_EQ(result.error().message, "Failed to parse metadata: test error"); + + histogram_tester.ExpectBucketCount( + "WebApp.Isolated.ReadIntegrityBlockAndMetadataStatus", GetParam().second, + 1); } +INSTANTIATE_TEST_SUITE_P( + All, + IsolatedWebAppReaderRegistryMetadataParserErrorTest, + ::testing::Values( + std::make_pair( + web_package::mojom::BundleParseErrorType::kParserInternalError, + IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus:: + kMetadataParserInternalError), + std::make_pair( + web_package::mojom::BundleParseErrorType::kVersionError, + IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus:: + kMetadataParserVersionError), + std::make_pair( + web_package::mojom::BundleParseErrorType::kFormatError, + IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus:: + kMetadataParserFormatError))); + TEST_F(IsolatedWebAppReaderRegistryTest, TestInvalidMetadataPrimaryUrl) { + base::HistogramTester histogram_tester; + network::ResourceRequest resource_request; resource_request.url = kPrimaryUrl; @@ -561,6 +657,12 @@ base::StringPrintf( "Failed to validate metadata: Primary URL must be %s, but was %s", kPrimaryUrl.spec().c_str(), kInvalidIsolatedWebAppUrl)); + + histogram_tester.ExpectBucketCount( + "WebApp.Isolated.ReadIntegrityBlockAndMetadataStatus", + IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus:: + kMetadataValidationError, + 1); } TEST_F(IsolatedWebAppReaderRegistryTest, TestInvalidMetadataInvalidExchange) {
diff --git a/chrome/browser/web_applications/web_app_helpers.cc b/chrome/browser/web_applications/web_app_helpers.cc index 99cd3ef..a33045ef 100644 --- a/chrome/browser/web_applications/web_app_helpers.cc +++ b/chrome/browser/web_applications/web_app_helpers.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/web_applications/web_app_registrar.h" #include "chrome/common/webui_url_constants.h" #include "components/crx_file/id_util.h" +#include "components/password_manager/content/common/web_ui_constants.h" #include "components/prefs/pref_service.h" #include "content/public/common/content_features.h" #include "crypto/sha2.h" @@ -117,7 +118,7 @@ app_url.SchemeIs(url::kHttpsScheme) || app_url.SchemeIs("chrome-extension") || (app_url.SchemeIs("chrome") && - (app_url.host() == chrome::kChromeUIPasswordManagerHost)); + (app_url.host() == password_manager::kChromeUIPasswordManagerHost)); } absl::optional<AppId> FindInstalledAppWithUrlInScope(Profile* profile,
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 08ba915..15f9596f 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1668729482-dae03be88903b96c0cb8dab14f08e8268d432145.profdata +chrome-linux-main-1668751127-43c4df5d1c2afa5ec63f00c507bd21a7240573ca.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index f1088bc..ae029f92 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1668729482-a579f9d50b0e3f0452bcbffb10fd12ec4b4d4420.profdata +chrome-mac-arm-main-1668751127-f9da020dd08da2388edd5cadb4c9c120716836bc.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index dd3cfcf..f2a69ec9 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1668729482-08450af1d482d5db59d38586aa4751ad5f2c5dba.profdata +chrome-mac-main-1668772733-72afca7487af2915577e91fe5203389749726ad8.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 2e452a5..19291f6 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1668729482-cda98716d89013ed34a00bfc4c3d23cdb303195d.profdata +chrome-win32-main-1668761948-da9a7feafa1dd554dd023fb485d20466cd1496a7.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index f15a826..76b40f82 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1668729482-f0dc1ff845c24bd6650354d4915408b19fd85051.profdata +chrome-win64-main-1668751127-16a1797a5307905ae4e126f9c5ae8740d36d0520.profdata
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index 5b683ab..e645c4b 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -263,6 +263,7 @@ "//components/no_state_prefetch/common", "//components/no_state_prefetch/common:mojo_bindings", "//components/page_load_metrics/common:common", + "//components/password_manager/content/common", ] if (enable_pdf) {
diff --git a/chrome/common/DEPS b/chrome/common/DEPS index 81130b8..ea0da1a 100644 --- a/chrome/common/DEPS +++ b/chrome/common/DEPS
@@ -36,6 +36,7 @@ "+components/ntp_tiles", "+components/nux", "+components/offline_pages/buildflags", + "+components/password_manager/content/common", "+components/password_manager/core/common", "+components/pdf/common", "+components/policy/core/common",
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json index f1984596..87d1d13 100644 --- a/chrome/common/extensions/api/_permission_features.json +++ b/chrome/common/extensions/api/_permission_features.json
@@ -632,7 +632,8 @@ "allowlist": [ "63ED55E43214C211F82122ED56407FF1A807F2A3", // Media Router Dev "226CF815E39A363090A1E547D53063472B8279FA", // Media Router Stable - "1BFB3A47AA4A1E1C4714D919217602685CDD0FA7" // http://crbug.com/574600 + "1BFB3A47AA4A1E1C4714D919217602685CDD0FA7", // http://crbug.com/574600 + "DD87C93131FF8D3DE4E483DC1EB298D73C7223A6" // http://crbug.com/1328114 ] }, {
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 70ba0aab..c1aa0c2a 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -11,6 +11,7 @@ #include "components/history_clusters/history_clusters_internals/webui/url_constants.h" #include "components/nacl/common/buildflags.h" #include "components/optimization_guide/optimization_guide_internals/webui/url_constants.h" +#include "components/password_manager/content/common/web_ui_constants.h" #include "components/safe_browsing/core/common/web_ui_constants.h" #include "extensions/buildflags/buildflags.h" #include "third_party/blink/public/common/chrome_debug_urls.h" @@ -156,7 +157,6 @@ #endif const char kChromeUIPasswordManagerInternalsHost[] = "password-manager-internals"; -const char kChromeUIPasswordManagerHost[] = "password-manager"; const char kChromeUIPerformanceSettingsURL[] = "chrome://settings/performance"; const char kChromeUIPolicyHost[] = "policy"; const char kChromeUIPolicyURL[] = "chrome://policy/"; @@ -680,7 +680,7 @@ kChromeUIOmniboxHost, optimization_guide_internals::kChromeUIOptimizationGuideInternalsHost, kChromeUIPasswordManagerInternalsHost, - kChromeUIPasswordManagerHost, + password_manager::kChromeUIPasswordManagerHost, kChromeUIPolicyHost, kChromeUIPredictorsHost, kChromeUIPrefsInternalsHost,
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index 5e2a9d1..7bed16c 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -152,7 +152,6 @@ extern const char kChromeUIOsUrlAppURL[]; #endif extern const char kChromeUIPasswordManagerInternalsHost[]; -extern const char kChromeUIPasswordManagerHost[]; extern const char kChromeUIPerformanceSettingsURL[]; extern const char kChromeUIPolicyHost[]; extern const char kChromeUIPolicyURL[];
diff --git a/chrome/services/file_util/BUILD.gn b/chrome/services/file_util/BUILD.gn index 4708517..ecbb8e02 100644 --- a/chrome/services/file_util/BUILD.gn +++ b/chrome/services/file_util/BUILD.gn
@@ -35,11 +35,11 @@ "zip_file_creator.h", ] - deps += ["//components/services/filesystem/public/mojom"] + deps += [ "//components/services/filesystem/public/mojom" ] } if (is_mac) { - deps += ["//chrome/utility/safe_browsing/mac"] + deps += [ "//chrome/utility/safe_browsing/mac" ] } if (safe_browsing_mode == 1) { @@ -71,8 +71,10 @@ } } - if (enable_xz_extractor) { + if (enable_extractors) { sources += [ + "single_file_tar_file_extractor.cc", + "single_file_tar_file_extractor.h", "single_file_tar_reader.cc", "single_file_tar_reader.h", "single_file_tar_xz_file_extractor.cc", @@ -88,8 +90,12 @@ source_set("unit_tests") { testonly = true - if (enable_xz_extractor) { - sources = [ "single_file_tar_xz_file_extractor_unittest.cc" ] + if (enable_extractors) { + sources = [ + "single_file_tar_file_extractor_unittest.cc", + "single_file_tar_reader_unittest.cc", + "single_file_tar_xz_file_extractor_unittest.cc", + ] deps = [ ":file_util", @@ -104,7 +110,7 @@ buildflag_header("buildflags") { header = "buildflags.h" flags = [ - "ENABLE_XZ_EXTRACTOR=$enable_xz_extractor", + "ENABLE_EXTRACTORS=$enable_extractors", "ENABLE_MALDOCA=$enable_maldoca", ] }
diff --git a/chrome/services/file_util/file_util_service.cc b/chrome/services/file_util/file_util_service.cc index 7de3f7e..303907181 100644 --- a/chrome/services/file_util/file_util_service.cc +++ b/chrome/services/file_util/file_util_service.cc
@@ -22,7 +22,8 @@ #include "chrome/services/file_util/zip_file_creator.h" #endif -#if BUILDFLAG(ENABLE_XZ_EXTRACTOR) +#if BUILDFLAG(ENABLE_EXTRACTORS) +#include "chrome/services/file_util/single_file_tar_file_extractor.h" #include "chrome/services/file_util/single_file_tar_xz_file_extractor.h" #endif @@ -47,10 +48,14 @@ } #endif -#if BUILDFLAG(ENABLE_XZ_EXTRACTOR) +#if BUILDFLAG(ENABLE_EXTRACTORS) +void FileUtilService::BindSingleFileTarFileExtractor( + mojo::PendingReceiver<chrome::mojom::SingleFileExtractor> receiver) { + mojo::MakeSelfOwnedReceiver(std::make_unique<SingleFileTarFileExtractor>(), + std::move(receiver)); +} void FileUtilService::BindSingleFileTarXzFileExtractor( - mojo::PendingReceiver<chrome::mojom::SingleFileTarXzFileExtractor> - receiver) { + mojo::PendingReceiver<chrome::mojom::SingleFileExtractor> receiver) { mojo::MakeSelfOwnedReceiver(std::make_unique<SingleFileTarXzFileExtractor>(), std::move(receiver)); }
diff --git a/chrome/services/file_util/file_util_service.h b/chrome/services/file_util/file_util_service.h index e1e8121e..0a7350f 100644 --- a/chrome/services/file_util/file_util_service.h +++ b/chrome/services/file_util/file_util_service.h
@@ -36,10 +36,13 @@ override; #endif -#if BUILDFLAG(ENABLE_XZ_EXTRACTOR) +#if BUILDFLAG(ENABLE_EXTRACTORS) void BindSingleFileTarXzFileExtractor( - mojo::PendingReceiver<chrome::mojom::SingleFileTarXzFileExtractor> - receiver) override; + mojo::PendingReceiver<chrome::mojom::SingleFileExtractor> receiver) + override; + void BindSingleFileTarFileExtractor( + mojo::PendingReceiver<chrome::mojom::SingleFileExtractor> receiver) + override; #endif mojo::Receiver<chrome::mojom::FileUtilService> receiver_;
diff --git a/chrome/services/file_util/public/features.gni b/chrome/services/file_util/public/features.gni index 2570caf..eaa5edb 100644 --- a/chrome/services/file_util/public/features.gni +++ b/chrome/services/file_util/public/features.gni
@@ -5,10 +5,10 @@ import("//extensions/buildflags/buildflags.gni") declare_args() { - # Whether the file_util service supports .xz file extraction. + # Whether the file_util service supports .TAR.XZ and .TAR file extraction. # Currently only used by imageWriterPrivate extension API, so only enabled # when Extensions are enabled. - enable_xz_extractor = enable_extensions + enable_extractors = enable_extensions # Enables analysis of Office documents for malicious macros enable_maldoca = is_linux || is_win
diff --git a/chrome/services/file_util/public/mojom/BUILD.gn b/chrome/services/file_util/public/mojom/BUILD.gn index eac7223..b9e80cc 100644 --- a/chrome/services/file_util/public/mojom/BUILD.gn +++ b/chrome/services/file_util/public/mojom/BUILD.gn
@@ -27,12 +27,12 @@ public_deps += [ "//components/services/filesystem/public/mojom" ] } - if (enable_xz_extractor) { + if (enable_extractors) { sources += [ "constants.mojom", - "single_file_tar_xz_file_extractor.mojom", + "single_file_extractor.mojom", ] - enabled_features += [ "xz_extractor" ] + enabled_features += [ "extractors" ] } if (safe_browsing_mode == 1 && enable_maldoca) {
diff --git a/chrome/services/file_util/public/mojom/constants.mojom b/chrome/services/file_util/public/mojom/constants.mojom index 445ca482..93a494b 100644 --- a/chrome/services/file_util/public/mojom/constants.mojom +++ b/chrome/services/file_util/public/mojom/constants.mojom
@@ -8,8 +8,7 @@ // The set of errors which may occur while extracting a file. enum ExtractionResult { kSuccess, - // These enums mirror the extensions::image_writer::error strings. - kUnzipGenericError, - kUnzipInvalidArchive, - kTempFileError, + kGenericError, + kInvalidSrcFile, + kDstFileError, };
diff --git a/chrome/services/file_util/public/mojom/file_util_service.mojom b/chrome/services/file_util/public/mojom/file_util_service.mojom index 4f4c401..3dc3cd0c 100644 --- a/chrome/services/file_util/public/mojom/file_util_service.mojom +++ b/chrome/services/file_util/public/mojom/file_util_service.mojom
@@ -12,8 +12,8 @@ [EnableIf=is_chromeos_ash] import "chrome/services/file_util/public/mojom/zip_file_creator.mojom"; -[EnableIf=xz_extractor] -import "chrome/services/file_util/public/mojom/single_file_tar_xz_file_extractor.mojom"; +[EnableIf=extractors] +import "chrome/services/file_util/public/mojom/single_file_extractor.mojom"; // The main interface to the file utility service. Binds any of various // specific utility receivers. @@ -27,8 +27,15 @@ [EnableIf=full_safe_browsing] BindSafeArchiveAnalyzer(pending_receiver<SafeArchiveAnalyzer> receiver); - // Binds an interface of the SingleFileTarXzFileExtractor interface. - [EnableIf=xz_extractor] + // Binds a SingleFileTarFileExtractor instance of the SingleFileExtractor + // interface. + [EnableIf=extractors] + BindSingleFileTarFileExtractor( + pending_receiver<SingleFileExtractor> receiver); + + // Binds a SingleFileTarXzFileExtractor instance of the SingleFileExtractor + // interface. + [EnableIf=extractors] BindSingleFileTarXzFileExtractor( - pending_receiver<SingleFileTarXzFileExtractor> receiver); + pending_receiver<SingleFileExtractor> receiver); };
diff --git a/chrome/services/file_util/public/mojom/single_file_extractor.mojom b/chrome/services/file_util/public/mojom/single_file_extractor.mojom new file mode 100644 index 0000000..990a725 --- /dev/null +++ b/chrome/services/file_util/public/mojom/single_file_extractor.mojom
@@ -0,0 +1,35 @@ +// 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. + +module chrome.mojom; + +import "chrome/services/file_util/public/mojom/constants.mojom"; +import "mojo/public/mojom/base/file.mojom"; +import "mojo/public/mojom/base/read_only_file.mojom"; + +// Service that extracts a single file from `src_file`. `src_file` is a .TAR.XZ +// or .TAR file. SingleFileExtractor interface is a common interface for +// .TAR.XZ file extraction and .TAR file extraction. `src_file` has to contain +// a single file. If it does multiple files, the service rejects the request +// and chrome.file_util.mojom.ExtractionResult.kInvalidSrcFile will return via +// `result`. This service is designed to extract large files such as OS image +// files. +interface SingleFileExtractor { + // Extracts a single file from `src_file` and writes the result to + // `dst_file`. Progress is regularly reported via the passed `listener`. + Extract(mojo_base.mojom.ReadOnlyFile src_file, + mojo_base.mojom.File dst_file, + pending_remote<SingleFileExtractorListener> listener) + => (chrome.file_util.mojom.ExtractionResult result); +}; + +// Listener of extract operation. +interface SingleFileExtractorListener { + // Regularly called during the extract operation to report progress. + // `total_bytes` indicates the size of the destination file after extraction. + // `progress_bytes` indicates the bytes already written to the destination + // file. + OnProgress(uint64 total_bytes, + uint64 progress_bytes); +};
diff --git a/chrome/services/file_util/public/mojom/single_file_tar_xz_file_extractor.mojom b/chrome/services/file_util/public/mojom/single_file_tar_xz_file_extractor.mojom deleted file mode 100644 index 1a607af..0000000 --- a/chrome/services/file_util/public/mojom/single_file_tar_xz_file_extractor.mojom +++ /dev/null
@@ -1,35 +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. - -module chrome.mojom; - -import "chrome/services/file_util/public/mojom/constants.mojom"; -import "mojo/public/mojom/base/file.mojom"; -import "mojo/public/mojom/base/read_only_file.mojom"; - -// Service that extracts a .TAR.XZ file. The .TAR.XZ file has to be a single -// file which is archived and compressed with tar and xz. That is, the .TAR.XZ -// file has to be a compressed tar archive with a single file entry. A -// compressed archive with multiple files will be rejected and -// chrome.file_util.mojom.ExtractionResult.kUnzipInvalidArchive will return via -// `result`. This service is designed to extract large files such as OS image -// files. -interface SingleFileTarXzFileExtractor { - // Extracts the .TAR.XZ file `src_file` and writes the result to `dst_file`. - // Progress is regularly reported via the passed `listener`. - Extract(mojo_base.mojom.ReadOnlyFile src_file, - mojo_base.mojom.File dst_file, - pending_remote<SingleFileTarXzFileExtractorListener> listener) - => (chrome.file_util.mojom.ExtractionResult result); -}; - -// Listener of a .TAR.XZ extraction operation. -interface SingleFileTarXzFileExtractorListener { - // Regularly called during the .TAR.XZ extraction operation to report - // progress. `total_bytes` indicates the size of the destination file after - // extraction. `progress_bytes` indicates the bytes already written to the - // destination file. - OnProgress(uint64 total_bytes, - uint64 progress_bytes); -};
diff --git a/chrome/services/file_util/single_file_tar_file_extractor.cc b/chrome/services/file_util/single_file_tar_file_extractor.cc new file mode 100644 index 0000000..dec83ae --- /dev/null +++ b/chrome/services/file_util/single_file_tar_file_extractor.cc
@@ -0,0 +1,114 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/services/file_util/single_file_tar_file_extractor.h" + +#include <utility> + +#include "chrome/services/file_util/public/mojom/constants.mojom.h" +#include "chrome/services/file_util/single_file_tar_reader.h" + +namespace { + +// TarExtractorInner extracts a .TAR file and writes the extracted data to the +// destination file. +class TarExtractorInner : public SingleFileTarReader::Delegate { + public: + TarExtractorInner( + mojo::PendingRemote<chrome::mojom::SingleFileExtractorListener> + pending_listener, + base::File src_file, + base::File dst_file) + : listener_(std::move(pending_listener)), + src_file_(std::move(src_file)), + dst_file_(std::move(dst_file)), + tar_reader_(this) {} + + chrome::file_util::mojom::ExtractionResult Extract() { + while (true) { + if (tar_reader_.ExtractChunk() != SingleFileTarReader::Result::kSuccess) + return tar_reader_.error(); + + if (tar_reader_.IsComplete()) + return chrome::file_util::mojom::ExtractionResult::kSuccess; + + listener_->OnProgress(tar_reader_.total_bytes().value(), + tar_reader_.curr_bytes()); + } + } + + void CloseFiles() { + src_file_.Close(); + dst_file_.Close(); + } + + private: + // SingleFileTarReader::Delegate implementation. + // TODO(b/256967002): Use base::span<>. + SingleFileTarReader::Result ReadTarFile( + char* data, + uint32_t* size, + chrome::file_util::mojom::ExtractionResult* error) override { + const int bytes_read = src_file_.ReadAtCurrentPos(data, *size); + if (bytes_read < 0) { + *error = chrome::file_util::mojom::ExtractionResult::kGenericError; + return SingleFileTarReader::Result::kFailure; + } + if (bytes_read == 0) { + // After reading the last chunk of file content, it is expected that the + // tar_reader_.IsComplete() in the Extract function returns true and the + // .tar.xz file extraction ends. + *error = chrome::file_util::mojom::ExtractionResult::kGenericError; + return SingleFileTarReader::Result::kFailure; + } + *size = bytes_read; + return SingleFileTarReader::Result::kSuccess; + } + + // SingleFileTarReader::Delegate implementation. + // TODO(b/256967002): Use base::span<>. + bool WriteContents( + const char* data, + int size, + chrome::file_util::mojom::ExtractionResult* error) override { + const int bytes_written = dst_file_.WriteAtCurrentPos(data, size); + if (bytes_written < 0 || bytes_written != size) { + *error = chrome::file_util::mojom::ExtractionResult::kDstFileError; + return false; + } + return true; + } + + const mojo::Remote<chrome::mojom::SingleFileExtractorListener> listener_; + + base::File src_file_; + base::File dst_file_; + + SingleFileTarReader tar_reader_; +}; +} // namespace + +SingleFileTarFileExtractor::SingleFileTarFileExtractor() = default; +SingleFileTarFileExtractor::~SingleFileTarFileExtractor() = default; + +void SingleFileTarFileExtractor::Extract( + base::File src_file, + base::File dst_file, + mojo::PendingRemote<chrome::mojom::SingleFileExtractorListener> + pending_listener, + SingleFileExtractor::ExtractCallback callback) { + if (!src_file.IsValid() || !dst_file.IsValid()) { + std::move(callback).Run( + chrome::file_util::mojom::ExtractionResult::kGenericError); + return; + } + TarExtractorInner extractor(std::move(pending_listener), std::move(src_file), + std::move(dst_file)); + chrome::file_util::mojom::ExtractionResult result = extractor.Extract(); + + // Explicitly close the files before calling `callback` to ensure all + // extracted data is flushed to the file and the file is closed. + extractor.CloseFiles(); + std::move(callback).Run(result); +}
diff --git a/chrome/services/file_util/single_file_tar_file_extractor.h b/chrome/services/file_util/single_file_tar_file_extractor.h new file mode 100644 index 0000000..a2dd31e6 --- /dev/null +++ b/chrome/services/file_util/single_file_tar_file_extractor.h
@@ -0,0 +1,28 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_SERVICES_FILE_UTIL_SINGLE_FILE_TAR_FILE_EXTRACTOR_H_ +#define CHROME_SERVICES_FILE_UTIL_SINGLE_FILE_TAR_FILE_EXTRACTOR_H_ + +#include "base/files/file.h" +#include "chrome/services/file_util/public/mojom/single_file_extractor.mojom.h" +#include "mojo/public/cpp/bindings/remote.h" + +class SingleFileTarFileExtractor : public chrome::mojom::SingleFileExtractor { + public: + SingleFileTarFileExtractor(); + ~SingleFileTarFileExtractor() override; + SingleFileTarFileExtractor(const SingleFileTarFileExtractor&) = delete; + SingleFileTarFileExtractor& operator=(const SingleFileTarFileExtractor&) = + delete; + + // chrome::mojom::SingleFileExtractor implementation. + void Extract( + base::File src_file, + base::File dst_file, + mojo::PendingRemote<chrome::mojom::SingleFileExtractorListener> listener, + ExtractCallback callback) override; +}; + +#endif // CHROME_SERVICES_FILE_UTIL_SINGLE_FILE_TAR_FILE_EXTRACTOR_H_
diff --git a/chrome/services/file_util/single_file_tar_file_extractor_unittest.cc b/chrome/services/file_util/single_file_tar_file_extractor_unittest.cc new file mode 100644 index 0000000..2d47685 --- /dev/null +++ b/chrome/services/file_util/single_file_tar_file_extractor_unittest.cc
@@ -0,0 +1,163 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/services/file_util/single_file_tar_file_extractor.h" + +#include <stdint.h> + +#include <string> +#include <utility> + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/path_service.h" +#include "base/test/mock_callback.h" +#include "base/test/task_environment.h" +#include "base/test/test_future.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/services/file_util/public/mojom/constants.mojom.h" +#include "chrome/services/file_util/public/mojom/single_file_extractor.mojom.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chrome { + +using ::testing::StrictMock; + +class SingleFileTarFileExtractorTest : public testing::Test { + public: + void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } + + protected: + SingleFileTarFileExtractorTest() = default; + ~SingleFileTarFileExtractorTest() override = default; + + base::FilePath GetFilePath(const char* file_name) { + base::FilePath test_data; + EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data)); + return test_data.AppendASCII("image_writer_private").AppendASCII(file_name); + } + + const base::FilePath& temp_dir() const { return temp_dir_.GetPath(); } + + // BindNewPipeAndPassRemote() requires a sequenced context. + base::test::TaskEnvironment task_environment_; + + private: + base::ScopedTempDir temp_dir_; +}; + +// TODO(b/254591810): Make MockSingleFileExtractorListener a mock. +class MockSingleFileExtractorListener + : public chrome::mojom::SingleFileExtractorListener { + // chrome::mojom::SingleFileExtractorListener implementation. + void OnProgress(uint64_t total_bytes, uint64_t progress_bytes) override {} +}; + +TEST_F(SingleFileTarFileExtractorTest, Extract) { + base::test::TestFuture<chrome::file_util::mojom::ExtractionResult> future; + + base::FilePath path; + ASSERT_NO_FATAL_FAILURE(path = GetFilePath("test.tar")); + base::File src_file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); + + base::FilePath out_path = temp_dir().AppendASCII("Extract_dst_file"); + base::File dst_file(out_path, + base::File::FLAG_CREATE | base::File::FLAG_WRITE); + + auto mock_listener = std::make_unique<MockSingleFileExtractorListener>(); + mojo::Receiver<chrome::mojom::SingleFileExtractorListener> listener{ + mock_listener.get()}; + + SingleFileTarFileExtractor extractor; + extractor.Extract(std::move(src_file), std::move(dst_file), + listener.BindNewPipeAndPassRemote(), future.GetCallback()); + + const chrome::file_util::mojom::ExtractionResult& result = future.Get(); + EXPECT_EQ(chrome::file_util::mojom::ExtractionResult::kSuccess, result); + std::string contents; + ASSERT_TRUE(base::ReadFileToString(out_path, &contents)); + EXPECT_EQ("foo\n", contents); +} + +TEST_F(SingleFileTarFileExtractorTest, ExtractTarLargerThanChunk) { + base::test::TestFuture<chrome::file_util::mojom::ExtractionResult> future; + + base::FilePath path; + ASSERT_NO_FATAL_FAILURE(path = GetFilePath("test_large.tar")); + base::File src_file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); + + base::FilePath out_path = + temp_dir().AppendASCII("ExtractTarLargerThanChunk_dst_file"); + base::File dst_file(out_path, + base::File::FLAG_CREATE | base::File::FLAG_WRITE); + + auto mock_listener = std::make_unique<MockSingleFileExtractorListener>(); + mojo::Receiver<chrome::mojom::SingleFileExtractorListener> listener{ + mock_listener.get()}; + + SingleFileTarFileExtractor extractor; + extractor.Extract(std::move(src_file), std::move(dst_file), + listener.BindNewPipeAndPassRemote(), future.GetCallback()); + + const chrome::file_util::mojom::ExtractionResult& result = future.Get(); + EXPECT_EQ(chrome::file_util::mojom::ExtractionResult::kSuccess, result); + std::string contents; + ASSERT_TRUE(base::ReadFileToString(out_path, &contents)); + EXPECT_EQ(10u * 1024u, contents.size()); +} + +TEST_F(SingleFileTarFileExtractorTest, ExtractNonExistentTar) { + base::test::TestFuture<chrome::file_util::mojom::ExtractionResult> future; + + base::FilePath path; + ASSERT_NO_FATAL_FAILURE(path = GetFilePath("non_existent.tar")); + base::File src_file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); + + base::FilePath out_path = + temp_dir().AppendASCII("ExtractNonExistentTar_dst_file"); + base::File dst_file(out_path, + base::File::FLAG_CREATE | base::File::FLAG_WRITE); + + auto mock_listener = std::make_unique<MockSingleFileExtractorListener>(); + mojo::Receiver<chrome::mojom::SingleFileExtractorListener> listener{ + mock_listener.get()}; + + SingleFileTarFileExtractor extractor; + extractor.Extract(std::move(src_file), std::move(dst_file), + listener.BindNewPipeAndPassRemote(), future.GetCallback()); + + const chrome::file_util::mojom::ExtractionResult& result = future.Get(); + EXPECT_EQ(chrome::file_util::mojom::ExtractionResult::kGenericError, result); +} + +// Verify that a .tar file with a 0 byte file works. +TEST_F(SingleFileTarFileExtractorTest, ZeroByteFile) { + base::test::TestFuture<chrome::file_util::mojom::ExtractionResult> future; + + base::FilePath path; + ASSERT_NO_FATAL_FAILURE(path = GetFilePath("empty_file.tar")); + base::File src_file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); + + base::FilePath out_path = temp_dir().AppendASCII("ZeroByteFile_dst_file"); + base::File dst_file(out_path, + base::File::FLAG_CREATE | base::File::FLAG_WRITE); + + auto mock_listener = std::make_unique<MockSingleFileExtractorListener>(); + mojo::Receiver<chrome::mojom::SingleFileExtractorListener> listener{ + mock_listener.get()}; + + SingleFileTarFileExtractor extractor; + extractor.Extract(std::move(src_file), std::move(dst_file), + listener.BindNewPipeAndPassRemote(), future.GetCallback()); + + const chrome::file_util::mojom::ExtractionResult& result = future.Get(); + EXPECT_EQ(chrome::file_util::mojom::ExtractionResult::kSuccess, result); + std::string contents; + ASSERT_TRUE(base::ReadFileToString(out_path, &contents)); + ASSERT_TRUE(contents.empty()); +} + +} // namespace chrome
diff --git a/chrome/services/file_util/single_file_tar_reader.cc b/chrome/services/file_util/single_file_tar_reader.cc index f62e8377..f6ae8a5 100644 --- a/chrome/services/file_util/single_file_tar_reader.cc +++ b/chrome/services/file_util/single_file_tar_reader.cc
@@ -52,7 +52,7 @@ // We haven't read the header. if (!total_bytes_.has_value()) { if (bytes_read < 512) { - error_ = chrome::file_util::mojom::ExtractionResult::kUnzipInvalidArchive; + error_ = chrome::file_util::mojom::ExtractionResult::kInvalidSrcFile; return Result::kFailure; }
diff --git a/chrome/browser/extensions/api/image_writer_private/single_file_tar_reader_unittest.cc b/chrome/services/file_util/single_file_tar_reader_unittest.cc similarity index 75% rename from chrome/browser/extensions/api/image_writer_private/single_file_tar_reader_unittest.cc rename to chrome/services/file_util/single_file_tar_reader_unittest.cc index bbd19cd..33536304 100644 --- a/chrome/browser/extensions/api/image_writer_private/single_file_tar_reader_unittest.cc +++ b/chrome/services/file_util/single_file_tar_reader_unittest.cc
@@ -2,18 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/extensions/api/image_writer_private/single_file_tar_reader.h" +#include "chrome/services/file_util/single_file_tar_reader.h" #include <memory> #include <vector> #include "base/files/file_util.h" -#include "chrome/browser/extensions/api/image_writer_private/test_utils.h" +#include "base/path_service.h" +#include "chrome/common/chrome_paths.h" #include "testing/gtest/include/gtest/gtest.h" -namespace extensions { -namespace image_writer { - class SingleFileTarReaderTest : public testing::Test, public SingleFileTarReader::Delegate { public: @@ -23,17 +21,26 @@ SingleFileTarReaderTest& operator=(const SingleFileTarReaderTest&) = delete; ~SingleFileTarReaderTest() override = default; + bool GetTestDataDirectory(base::FilePath* path) { + bool success = base::PathService::Get(chrome::DIR_TEST_DATA, path); + if (!success) + return false; + *path = path->AppendASCII("image_writer_private"); + return true; + } + bool OpenTarFile(const base::FilePath& file_path) { - infile_ = std::make_unique<base::File>( + src_file_ = std::make_unique<base::File>( file_path, base::File::FLAG_OPEN | base::File::FLAG_READ); - return infile_->IsValid(); + return src_file_->IsValid(); } // SingleFileTarReader::Delegate: - SingleFileTarReader::Result ReadTarFile(char* data, - uint32_t* size, - std::string* error_id) override { - int bytes_read = infile_->ReadAtCurrentPos(data, *size); + SingleFileTarReader::Result ReadTarFile( + char* data, + uint32_t* size, + chrome::file_util::mojom::ExtractionResult* error) override { + int bytes_read = src_file_->ReadAtCurrentPos(data, *size); if (bytes_read < 0) { return SingleFileTarReader::Result::kFailure; } @@ -42,9 +49,10 @@ return SingleFileTarReader::Result::kSuccess; } - bool WriteContents(const char* data, - int size, - std::string* error_id) override { + bool WriteContents( + const char* data, + int size, + chrome::file_util::mojom::ExtractionResult* error) override { contents_.insert(contents_.end(), data, data + size); return true; } @@ -53,7 +61,7 @@ const std::vector<char>& contents() const { return contents_; } private: - std::unique_ptr<base::File> infile_; + std::unique_ptr<base::File> src_file_; std::vector<char> contents_; SingleFileTarReader reader_; @@ -92,6 +100,3 @@ EXPECT_EQ(SingleFileTarReader::Result::kSuccess, reader().ExtractChunk()); EXPECT_TRUE(reader().IsComplete()); } - -} // namespace image_writer -} // namespace extensions
diff --git a/chrome/services/file_util/single_file_tar_xz_file_extractor.cc b/chrome/services/file_util/single_file_tar_xz_file_extractor.cc index 9a1dec5..b766b1d 100644 --- a/chrome/services/file_util/single_file_tar_xz_file_extractor.cc +++ b/chrome/services/file_util/single_file_tar_xz_file_extractor.cc
@@ -33,11 +33,10 @@ // output file. class ExtractorInner : public SingleFileTarReader::Delegate { public: - ExtractorInner( - mojo::PendingRemote<chrome::mojom::SingleFileTarXzFileExtractorListener> - pending_listener, - base::File src_file, - base::File dst_file) + ExtractorInner(mojo::PendingRemote<chrome::mojom::SingleFileExtractorListener> + pending_listener, + base::File src_file, + base::File dst_file) : listener_(std::move(pending_listener)), src_file_(std::move(src_file)), dst_file_(std::move(dst_file)), @@ -53,12 +52,12 @@ const int bytes_read = src_file_.ReadAtCurrentPos( reinterpret_cast<char*>(xz_buffer.data()), xz_buffer.size()); if (bytes_read < 0) - return chrome::file_util::mojom::ExtractionResult::kUnzipGenericError; + return chrome::file_util::mojom::ExtractionResult::kGenericError; if (bytes_read == 0) { // After reading the last chunk of file content, it is expected that the // ExtractChunk() below populates `result` with kSuccess and the .tar.xz // file extraction ends. - return chrome::file_util::mojom::ExtractionResult::kUnzipGenericError; + return chrome::file_util::mojom::ExtractionResult::kGenericError; } absl::optional<chrome::file_util::mojom::ExtractionResult> result; @@ -73,6 +72,11 @@ } } + void CloseFiles() { + src_file_.Close(); + dst_file_.Close(); + } + ~ExtractorInner() override { XzUnpacker_Free(&state_); } private: @@ -91,8 +95,7 @@ /*srcFinished=*/xz_buffer.empty(), CODER_FINISH_ANY, &status); if (xz_result != SZ_OK) { - *result = - chrome::file_util::mojom::ExtractionResult::kUnzipGenericError; + *result = chrome::file_util::mojom::ExtractionResult::kGenericError; return; } xz_buffer = xz_buffer.subspan(compressed_size); @@ -133,14 +136,13 @@ chrome::file_util::mojom::ExtractionResult* error) override { const int bytes_written = dst_file_.WriteAtCurrentPos(data, size); if (bytes_written < 0 || bytes_written != size) { - *error = chrome::file_util::mojom::ExtractionResult::kTempFileError; + *error = chrome::file_util::mojom::ExtractionResult::kDstFileError; return false; } return true; } - const mojo::Remote<chrome::mojom::SingleFileTarXzFileExtractorListener> - listener_; + const mojo::Remote<chrome::mojom::SingleFileExtractorListener> listener_; CXzUnpacker state_; ISzAlloc alloc_; @@ -168,18 +170,20 @@ void SingleFileTarXzFileExtractor::Extract( base::File src_file, base::File dst_file, - mojo::PendingRemote<chrome::mojom::SingleFileTarXzFileExtractorListener> + mojo::PendingRemote<chrome::mojom::SingleFileExtractorListener> pending_listener, - SingleFileTarXzFileExtractor::ExtractCallback callback) { + SingleFileExtractor::ExtractCallback callback) { if (!src_file.IsValid() || !dst_file.IsValid()) { std::move(callback).Run( - chrome::file_util::mojom::ExtractionResult::kUnzipGenericError); + chrome::file_util::mojom::ExtractionResult::kGenericError); return; } - ExtractorInner* extractor = new ExtractorInner( - std::move(pending_listener), std::move(src_file), std::move(dst_file)); - chrome::file_util::mojom::ExtractionResult result = extractor->Extract(); - // Destroy the File objects before calling `callback`. - delete extractor; + ExtractorInner extractor(std::move(pending_listener), std::move(src_file), + std::move(dst_file)); + chrome::file_util::mojom::ExtractionResult result = extractor.Extract(); + + // Explicitly close the files before calling `callback` to ensure all + // extracted data is flushed to the file and the file is closed. + extractor.CloseFiles(); std::move(callback).Run(result); }
diff --git a/chrome/services/file_util/single_file_tar_xz_file_extractor.h b/chrome/services/file_util/single_file_tar_xz_file_extractor.h index 1c76846..8c21f4c 100644 --- a/chrome/services/file_util/single_file_tar_xz_file_extractor.h +++ b/chrome/services/file_util/single_file_tar_xz_file_extractor.h
@@ -6,11 +6,10 @@ #define CHROME_SERVICES_FILE_UTIL_SINGLE_FILE_TAR_XZ_FILE_EXTRACTOR_H_ #include "base/files/file.h" -#include "chrome/services/file_util/public/mojom/single_file_tar_xz_file_extractor.mojom.h" +#include "chrome/services/file_util/public/mojom/single_file_extractor.mojom.h" #include "mojo/public/cpp/bindings/remote.h" -class SingleFileTarXzFileExtractor - : public chrome::mojom::SingleFileTarXzFileExtractor { +class SingleFileTarXzFileExtractor : public chrome::mojom::SingleFileExtractor { public: SingleFileTarXzFileExtractor(); ~SingleFileTarXzFileExtractor() override; @@ -18,12 +17,11 @@ SingleFileTarXzFileExtractor& operator=(const SingleFileTarXzFileExtractor&) = delete; - // chrome::mojom::SingleFileTarXzFileExtractor implementation. + // chrome::mojom::SingleFileExtractor implementation. void Extract( base::File src_file, base::File dst_file, - mojo::PendingRemote<chrome::mojom::SingleFileTarXzFileExtractorListener> - listener, + mojo::PendingRemote<chrome::mojom::SingleFileExtractorListener> listener, ExtractCallback callback) override; };
diff --git a/chrome/services/file_util/single_file_tar_xz_file_extractor_unittest.cc b/chrome/services/file_util/single_file_tar_xz_file_extractor_unittest.cc index 4d170a9..f428f1c 100644 --- a/chrome/services/file_util/single_file_tar_xz_file_extractor_unittest.cc +++ b/chrome/services/file_util/single_file_tar_xz_file_extractor_unittest.cc
@@ -15,9 +15,10 @@ #include "base/path_service.h" #include "base/test/mock_callback.h" #include "base/test/task_environment.h" +#include "base/test/test_future.h" #include "chrome/common/chrome_paths.h" #include "chrome/services/file_util/public/mojom/constants.mojom.h" -#include "chrome/services/file_util/public/mojom/single_file_tar_xz_file_extractor.mojom.h" +#include "chrome/services/file_util/public/mojom/single_file_extractor.mojom.h" #include "mojo/public/cpp/bindings/receiver.h" #include "testing/gtest/include/gtest/gtest.h" @@ -51,14 +52,16 @@ base::ScopedTempDir temp_dir_; }; -// TODO(b/254591810): Make MockSingleFileTarXzFileExtractorListener a mock. -class MockSingleFileTarXzFileExtractorListener - : public chrome::mojom::SingleFileTarXzFileExtractorListener { - // chrome::mojom::SingleFileTarXzFileExtractorListener implementation. +// TODO(b/254591810): Make MockSingleFileExtractorListener a mock. +class MockSingleFileExtractorListener + : public chrome::mojom::SingleFileExtractorListener { + // chrome::mojom::SingleFileExtractorListener implementation. void OnProgress(uint64_t total_bytes, uint64_t progress_bytes) override {} }; TEST_F(SingleFileTarXzFileExtractorTest, Extract) { + base::test::TestFuture<chrome::file_util::mojom::ExtractionResult> future; + base::FilePath path; ASSERT_NO_FATAL_FAILURE(path = GetFilePath("test.tar.xz")); base::File src_file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); @@ -67,20 +70,15 @@ base::File dst_file(out_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE); - auto mock_listener = - std::make_unique<MockSingleFileTarXzFileExtractorListener>(); - mojo::Receiver<chrome::mojom::SingleFileTarXzFileExtractorListener> listener{ + auto mock_listener = std::make_unique<MockSingleFileExtractorListener>(); + mojo::Receiver<chrome::mojom::SingleFileExtractorListener> listener{ mock_listener.get()}; - StrictMock<base::MockCallback<SingleFileTarXzFileExtractor::ExtractCallback>> - callback; - - chrome::file_util::mojom::ExtractionResult result; - EXPECT_CALL(callback, Run).WillOnce(testing::SaveArg<0>(&result)); SingleFileTarXzFileExtractor extractor; extractor.Extract(std::move(src_file), std::move(dst_file), - listener.BindNewPipeAndPassRemote(), callback.Get()); + listener.BindNewPipeAndPassRemote(), future.GetCallback()); + const chrome::file_util::mojom::ExtractionResult& result = future.Get(); EXPECT_EQ(chrome::file_util::mojom::ExtractionResult::kSuccess, result); std::string contents; ASSERT_TRUE(base::ReadFileToString(out_path, &contents)); @@ -88,6 +86,8 @@ } TEST_F(SingleFileTarXzFileExtractorTest, ExtractNonExistentTarXz) { + base::test::TestFuture<chrome::file_util::mojom::ExtractionResult> future; + base::FilePath path; ASSERT_NO_FATAL_FAILURE(path = GetFilePath("non_existent.tar.xz")); base::File src_file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); @@ -97,25 +97,21 @@ base::File dst_file(out_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE); - auto mock_listener = - std::make_unique<MockSingleFileTarXzFileExtractorListener>(); - mojo::Receiver<chrome::mojom::SingleFileTarXzFileExtractorListener> listener{ + auto mock_listener = std::make_unique<MockSingleFileExtractorListener>(); + mojo::Receiver<chrome::mojom::SingleFileExtractorListener> listener{ mock_listener.get()}; - StrictMock<base::MockCallback<SingleFileTarXzFileExtractor::ExtractCallback>> - callback; - - chrome::file_util::mojom::ExtractionResult result; - EXPECT_CALL(callback, Run).WillOnce(testing::SaveArg<0>(&result)); SingleFileTarXzFileExtractor extractor; extractor.Extract(std::move(src_file), std::move(dst_file), - listener.BindNewPipeAndPassRemote(), callback.Get()); + listener.BindNewPipeAndPassRemote(), future.GetCallback()); - EXPECT_EQ(chrome::file_util::mojom::ExtractionResult::kUnzipGenericError, - result); + const chrome::file_util::mojom::ExtractionResult& result = future.Get(); + EXPECT_EQ(chrome::file_util::mojom::ExtractionResult::kGenericError, result); } TEST_F(SingleFileTarXzFileExtractorTest, ZeroByteFile) { + base::test::TestFuture<chrome::file_util::mojom::ExtractionResult> future; + base::FilePath path; ASSERT_NO_FATAL_FAILURE(path = GetFilePath("empty_file.tar.xz")); base::File src_file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); @@ -124,20 +120,15 @@ base::File dst_file(out_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE); - auto mock_listener = - std::make_unique<MockSingleFileTarXzFileExtractorListener>(); - mojo::Receiver<chrome::mojom::SingleFileTarXzFileExtractorListener> listener{ + auto mock_listener = std::make_unique<MockSingleFileExtractorListener>(); + mojo::Receiver<chrome::mojom::SingleFileExtractorListener> listener{ mock_listener.get()}; - StrictMock<base::MockCallback<SingleFileTarXzFileExtractor::ExtractCallback>> - callback; - - chrome::file_util::mojom::ExtractionResult result; - EXPECT_CALL(callback, Run).WillOnce(testing::SaveArg<0>(&result)); SingleFileTarXzFileExtractor extractor; extractor.Extract(std::move(src_file), std::move(dst_file), - listener.BindNewPipeAndPassRemote(), callback.Get()); + listener.BindNewPipeAndPassRemote(), future.GetCallback()); + const chrome::file_util::mojom::ExtractionResult& result = future.Get(); EXPECT_EQ(chrome::file_util::mojom::ExtractionResult::kSuccess, result); std::string contents; ASSERT_TRUE(base::ReadFileToString(out_path, &contents)); @@ -145,6 +136,8 @@ } TEST_F(SingleFileTarXzFileExtractorTest, ExtractBigFile) { + base::test::TestFuture<chrome::file_util::mojom::ExtractionResult> future; + base::FilePath path; ASSERT_NO_FATAL_FAILURE(path = GetFilePath("2MBzeros.tar.xz")); base::File src_file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); @@ -153,20 +146,15 @@ base::File dst_file(out_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE); - auto mock_listener = - std::make_unique<MockSingleFileTarXzFileExtractorListener>(); - mojo::Receiver<chrome::mojom::SingleFileTarXzFileExtractorListener> listener{ + auto mock_listener = std::make_unique<MockSingleFileExtractorListener>(); + mojo::Receiver<chrome::mojom::SingleFileExtractorListener> listener{ mock_listener.get()}; - StrictMock<base::MockCallback<SingleFileTarXzFileExtractor::ExtractCallback>> - callback; - - chrome::file_util::mojom::ExtractionResult result; - EXPECT_CALL(callback, Run).WillOnce(testing::SaveArg<0>(&result)); SingleFileTarXzFileExtractor extractor; extractor.Extract(std::move(src_file), std::move(dst_file), - listener.BindNewPipeAndPassRemote(), callback.Get()); + listener.BindNewPipeAndPassRemote(), future.GetCallback()); + const chrome::file_util::mojom::ExtractionResult& result = future.Get(); EXPECT_EQ(chrome::file_util::mojom::ExtractionResult::kSuccess, result); std::string contents; ASSERT_TRUE(base::ReadFileToString(out_path, &contents));
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 1aaa0a3..f38384a31 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1412,6 +1412,7 @@ "//components/page_load_metrics/common", "//components/page_load_metrics/common:test_support", "//components/password_manager/content/browser", + "//components/password_manager/content/common", "//components/password_manager/core/browser:affiliation_proto", "//components/password_manager/core/browser/form_parsing", "//components/payments/content", @@ -7912,7 +7913,6 @@ "../browser/extensions/api/image_writer_private/image_writer_private_api_unittest.cc", "../browser/extensions/api/image_writer_private/operation_manager_unittest.cc", "../browser/extensions/api/image_writer_private/operation_unittest.cc", - "../browser/extensions/api/image_writer_private/single_file_tar_reader_unittest.cc", "../browser/extensions/api/image_writer_private/test_utils.cc", "../browser/extensions/api/image_writer_private/test_utils.h", "../browser/extensions/api/image_writer_private/write_from_file_operation_unittest.cc",
diff --git a/chrome/test/chromedriver/chrome/adb_impl.cc b/chrome/test/chromedriver/chrome/adb_impl.cc index 2484642..25d2a16 100644 --- a/chrome/test/chromedriver/chrome/adb_impl.cc +++ b/chrome/test/chromedriver/chrome/adb_impl.cc
@@ -246,10 +246,17 @@ const std::string& device_serial, const std::string& package, const std::string& activity) { std::string response; + ExecuteHostShellCommand(device_serial, "getprop ro.build.version.release", + &response); + int android_version = stoi(response); + if (android_version >= 13) { + ExecuteHostShellCommand( + device_serial, + "pm grant " + package + " android.permission.POST_NOTIFICATIONS", + &response); + } Status status = ExecuteHostShellCommand( - device_serial, - "am start -W -n " + package + "/" + activity + " -d data:,", - &response); + device_serial, "am start -W -n " + package + "/" + activity, &response); if (!status.IsOk()) return status; if (response.find("Complete") == std::string::npos)
diff --git a/chrome/test/chromedriver/window_commands.cc b/chrome/test/chromedriver/window_commands.cc index 68cb94c..d160931 100644 --- a/chrome/test/chromedriver/window_commands.cc +++ b/chrome/test/chromedriver/window_commands.cc
@@ -248,8 +248,15 @@ SetSafeInt(dict, "expiry", cookie.expiry); dict.Set("httpOnly", cookie.http_only); dict.Set("secure", cookie.secure); - if (!cookie.samesite.empty()) + if (!cookie.samesite.empty()) { dict.Set("sameSite", cookie.samesite); + } else { + // The default in the standard is Lax: + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite + // Chrome (mostly) treats default cookies as Lax so this seems correct: + // https://chromestatus.com/feature/5088147346030592 + dict.Set("sameSite", "Lax"); + } return dict; }
diff --git a/chrome/test/chromedriver/window_commands_unittest.cc b/chrome/test/chromedriver/window_commands_unittest.cc index 5b45128..75c4184 100644 --- a/chrome/test/chromedriver/window_commands_unittest.cc +++ b/chrome/test/chromedriver/window_commands_unittest.cc
@@ -366,6 +366,133 @@ namespace { +class GetCookiesWebView : public StubWebView { + public: + explicit GetCookiesWebView(std::string document_url) + : StubWebView("1"), document_url_(document_url) {} + ~GetCookiesWebView() override = default; + + Status CallFunction(const std::string& frame, + const std::string& function, + const base::Value::List& args, + std::unique_ptr<base::Value>* result) override { + if (function.find("document.URL") != std::string::npos) { + *result = std::make_unique<base::Value>(document_url_); + } + return Status(kOk); + } + + Status GetCookies(base::Value* cookies, + const std::string& current_page_url) override { + base::Value::List new_cookies; + base::Value::Dict cookie_0; + cookie_0.Set("name", "a"); + cookie_0.Set("value", "0"); + cookie_0.Set("domain", "example.com"); + cookie_0.Set("path", "/"); + cookie_0.Set("session", true); + new_cookies.Append(cookie_0.Clone()); + base::Value::Dict cookie_1; + cookie_1.Set("name", "b"); + cookie_1.Set("value", "1"); + cookie_1.Set("domain", "example.org"); + cookie_1.Set("path", "/test"); + cookie_1.Set("sameSite", "None"); + cookie_1.Set("expires", 10); + cookie_1.Set("httpOnly", true); + cookie_1.Set("session", false); + cookie_1.Set("secure", true); + new_cookies.Append(cookie_1.Clone()); + *cookies = base::Value(new_cookies.Clone()); + return Status(kOk); + } + + private: + std::string document_url_; +}; + +} // namespace + +TEST(WindowCommandsTest, ExecuteGetCookies) { + GetCookiesWebView webview = GetCookiesWebView("https://chromium.org"); + base::Value::Dict params; + std::unique_ptr<base::Value> result_value; + Status status = + CallWindowCommand(ExecuteGetCookies, &webview, params, &result_value); + ASSERT_EQ(kOk, status.code()) << status.message(); + base::Value::List expected_cookies; + base::Value::Dict cookie_0; + cookie_0.Set("name", "a"); + cookie_0.Set("value", "0"); + cookie_0.Set("domain", "example.com"); + cookie_0.Set("path", "/"); + cookie_0.Set("sameSite", "Lax"); + cookie_0.Set("httpOnly", false); + cookie_0.Set("secure", false); + expected_cookies.Append(cookie_0.Clone()); + base::Value::Dict cookie_1; + cookie_1.Set("name", "b"); + cookie_1.Set("value", "1"); + cookie_1.Set("domain", "example.org"); + cookie_1.Set("path", "/test"); + cookie_1.Set("sameSite", "None"); + cookie_1.Set("expiry", 10); + cookie_1.Set("httpOnly", true); + cookie_1.Set("secure", true); + expected_cookies.Append(cookie_1.Clone()); + EXPECT_EQ(result_value->GetList(), expected_cookies); +} + +TEST(WindowCommandsTest, ExecuteGetNamedCookie) { + GetCookiesWebView webview = GetCookiesWebView("https://chromium.org"); + base::Value::Dict params; + std::unique_ptr<base::Value> result_value; + + // Get without cookie name. + Status status = + CallWindowCommand(ExecuteGetNamedCookie, &webview, params, &result_value); + ASSERT_EQ(kInvalidArgument, status.code()) << status.message(); + + // Get with undefined cookie. + params.Set("name", "missing"); + status = + CallWindowCommand(ExecuteGetNamedCookie, &webview, params, &result_value); + ASSERT_EQ(kNoSuchCookie, status.code()) << status.message(); + + // Get cookie a. + params.Set("name", "a"); + status = + CallWindowCommand(ExecuteGetNamedCookie, &webview, params, &result_value); + ASSERT_EQ(kOk, status.code()) << status.message(); + base::Value::Dict expected_cookie_0; + expected_cookie_0.Set("name", "a"); + expected_cookie_0.Set("value", "0"); + expected_cookie_0.Set("domain", "example.com"); + expected_cookie_0.Set("path", "/"); + expected_cookie_0.Set("sameSite", "Lax"); + expected_cookie_0.Set("httpOnly", false); + expected_cookie_0.Set("secure", false); + EXPECT_EQ(result_value->GetDict(), expected_cookie_0); + + // Get cookie b. + params.Set("name", "b"); + status = + CallWindowCommand(ExecuteGetNamedCookie, &webview, params, &result_value); + ASSERT_EQ(kOk, status.code()) << status.message(); + base::Value::Dict expected_cookie_1; + expected_cookie_1.Set("name", "b"); + expected_cookie_1.Set("value", "1"); + expected_cookie_1.Set("domain", "example.org"); + expected_cookie_1.Set("path", "/test"); + expected_cookie_1.Set("sameSite", "None"); + expected_cookie_1.Set("expiry", 10); + expected_cookie_1.Set("httpOnly", true); + expected_cookie_1.Set("secure", true); + EXPECT_EQ(result_value->GetDict(), expected_cookie_1); +} + +namespace { + class StorePrintParamsWebView : public StubWebView { public: StorePrintParamsWebView() : StubWebView("1") {}
diff --git a/chrome/test/data/webui/invalidations/invalidations_test.js b/chrome/test/data/webui/invalidations/invalidations_test.js index be49504..8f0e5ff 100644 --- a/chrome/test/data/webui/invalidations/invalidations_test.js +++ b/chrome/test/data/webui/invalidations/invalidations_test.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js'; +import {webUIListenerCallback} from 'chrome://resources/js/cr.js'; import {$} from 'chrome://resources/js/util.js'; import {assertEquals, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
diff --git a/chrome/test/data/webui/password_manager/password_manager_browsertest.js b/chrome/test/data/webui/password_manager/password_manager_browsertest.js index 218d5e2..91971405 100644 --- a/chrome/test/data/webui/password_manager/password_manager_browsertest.js +++ b/chrome/test/data/webui/password_manager/password_manager_browsertest.js
@@ -24,12 +24,6 @@ } }; -// TODO(crbug.com/1383449): Failing on Mac. -GEN('#if BUILDFLAG(IS_MAC)'); -GEN('#define MAYBE_PasswordManagerUIPasswordsSectionTest DISABLED_All'); -GEN('#else'); -GEN('#define MAYBE_PasswordManagerUIPasswordsSectionTest All'); -GEN('#endif'); [['App', 'password_manager_app_test.js'], ['SideBar', 'password_manager_side_bar_test.js'], ['Settings', 'settings_section_test.js'],
diff --git a/chrome/test/data/webui/password_manager/passwords_section_test.ts b/chrome/test/data/webui/password_manager/passwords_section_test.ts index 35a7958..c43d9ef 100644 --- a/chrome/test/data/webui/password_manager/passwords_section_test.ts +++ b/chrome/test/data/webui/password_manager/passwords_section_test.ts
@@ -17,12 +17,14 @@ * @param subsection The passwords subsection element that will be checked. * @param expectedPasswords The expected passwords in this subsection. */ -async function validatePasswordsSubsection( +function validatePasswordsSubsection( list: IronListElement, expectedGroups: chrome.passwordsPrivate.CredentialGroup[]) { assertDeepEquals(expectedGroups, list.items); const listItemElements = list.querySelectorAll('password-list-item'); + assertEquals(listItemElements.length, expectedGroups.length); + for (let index = 0; index < expectedGroups.length; ++index) { const expectedGroup = expectedGroups[index]!; const listItemElement = listItemElements[index]; @@ -43,16 +45,7 @@ return flushTasks(); }); - // TODO(crbug.com/1383225): Enable test again once the solution is found. - test.skip('password section listens to updates', async function() { - const section: PasswordsSectionElement = - document.createElement('passwords-section'); - document.body.appendChild(section); - await flushTasks(); - - // PasswordsList is hidden as there are no passwords. - assertFalse(isVisible(section.$.passwordsList)); - + test('groups shown correctly', async function() { passwordManager.data.groups = [ createCredentialGroup({ name: 'test.com', @@ -63,14 +56,28 @@ credentials: [createPasswordEntry({username: 'user', id: 1})], }), ]; - assertTrue(!!passwordManager.listeners.savedPasswordListChangedListener); - passwordManager.listeners.savedPasswordListChangedListener!([]); + + const section: PasswordsSectionElement = + document.createElement('passwords-section'); + document.body.appendChild(section); + await passwordManager.whenCalled('getCredentialGroups'); await flushTasks(); validatePasswordsSubsection( section.$.passwordsList, passwordManager.data.groups); }); + test('passwords list is hidden if nothing to show', async function() { + const section: PasswordsSectionElement = + document.createElement('passwords-section'); + document.body.appendChild(section); + await passwordManager.whenCalled('getCredentialGroups'); + await flushTasks(); + + // PasswordsList is hidden as there are no passwords. + assertFalse(isVisible(section.$.passwordsList)); + }); + test('clicking group navigates to details page', async function() { Router.getInstance().navigateTo(Page.PASSWORDS); passwordManager.data.groups = [createCredentialGroup({
diff --git a/chrome/test/data/webui/settings/review_notification_permissions_interactive_ui_test.ts b/chrome/test/data/webui/settings/review_notification_permissions_interactive_ui_test.ts index 854f0b0..4c3ad64 100644 --- a/chrome/test/data/webui/settings/review_notification_permissions_interactive_ui_test.ts +++ b/chrome/test/data/webui/settings/review_notification_permissions_interactive_ui_test.ts
@@ -10,7 +10,7 @@ import {SettingsReviewNotificationPermissionsElement, SiteSettingsPrefsBrowserProxyImpl} from 'chrome://settings/lazy_load.js'; import {assert} from 'chrome://resources/js/assert_ts.js'; -import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js'; +import {webUIListenerCallback} from 'chrome://resources/js/cr.js'; // clang-format on suite('CrSettingsReviewNotificationPermissionsInteractiveUITest', function() { @@ -165,4 +165,4 @@ await focusPromise; assertExpandButtonFocus(); }); -}); \ No newline at end of file +});
diff --git a/chrome/test/data/webui/sys_internals/api_test.js b/chrome/test/data/webui/sys_internals/api_test.js index a0b684d0..d8567d7 100644 --- a/chrome/test/data/webui/sys_internals/api_test.js +++ b/chrome/test/data/webui/sys_internals/api_test.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {sendWithPromise} from 'chrome://resources/js/cr.m.js'; +import {sendWithPromise} from 'chrome://resources/js/cr.js'; suite('getSysInfo', function() { test('Message handler integration test', function(done) {
diff --git a/chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.cc b/chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.cc index 05b1849..fa3cbda 100644 --- a/chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.cc +++ b/chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.cc
@@ -775,6 +775,16 @@ std::move(callback).Run(run_routine_response_.Clone()); } +void FakeCrosHealthd::RunPrivacyScreenRoutine( + bool target_state, + RunPrivacyScreenRoutineCallback callback) { + last_run_routine_ = mojom::DiagnosticRoutineEnum::kPrivacyScreen; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(std::move(callback), run_routine_response_.Clone()), + callback_delay_); +} + void FakeCrosHealthd::AddBluetoothObserver( mojo::PendingRemote<mojom::CrosHealthdBluetoothObserver> observer) { bluetooth_observers_.Add(std::move(observer));
diff --git a/chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h b/chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h index a351d719..b74c371c7 100644 --- a/chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h +++ b/chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h
@@ -324,6 +324,9 @@ void RunFingerprintRoutine(RunFingerprintRoutineCallback callback) override; void RunFingerprintAliveRoutine( RunFingerprintAliveRoutineCallback callback) override; + void RunPrivacyScreenRoutine( + bool target_state, + RunPrivacyScreenRoutineCallback callback) override; // CrosHealthdEventService overrides: void AddBluetoothObserver(
diff --git a/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom index bfdbd1ed..1f389459 100644 --- a/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom +++ b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom
@@ -54,7 +54,7 @@ // Diagnostics interface exposed by the cros_healthd daemon. // -// NextMinVersion: 4, NextIndex: 36 +// NextMinVersion: 5, NextIndex: 37 [Stable] interface CrosHealthdDiagnosticsService { // Returns an array of all diagnostic routines that the platform supports. @@ -550,6 +550,16 @@ // * |response| - contains a unique identifier and status for the created // routine. [MinVersion=3] RunFingerprintAliveRoutine@35() + => (RunRoutineResponse response); + + // Requests that the PrivacyScreen routine is created and started on the + // platform. This routine checks whether the privacy screen is working as + // expected. This routine is only available if GetAvailableRoutines returned + // kPrivacyScreen. + // + // The request: + // * |target_state| - privacy screen target state. + [MinVersion=4] RunPrivacyScreenRoutine@36(bool target_state) => (RunRoutineResponse response); };
diff --git a/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom index 3988da10..7171a944 100644 --- a/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom +++ b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom
@@ -15,7 +15,7 @@ // Enumeration of each of the diagnostics routines the platform may support. // -// NextMinVersion: 3, NextIndex: 34 +// NextMinVersion: 4, NextIndex: 35 [Stable, Extensible] enum DiagnosticRoutineEnum { [Default] kUnknown = 30, @@ -52,6 +52,7 @@ [MinVersion=1] kSensitiveSensor = 31, [MinVersion=2] kFingerprint = 32, [MinVersion=2] kFingerprintAlive = 33, + [MinVersion=3] kPrivacyScreen = 34 }; // Enumeration of the possible DiskRead routine's command type
diff --git a/chromeos/services/network_config/cros_network_config.cc b/chromeos/services/network_config/cros_network_config.cc index bc9e5c2..3ea55d2 100644 --- a/chromeos/services/network_config/cros_network_config.cc +++ b/chromeos/services/network_config/cros_network_config.cc
@@ -3615,9 +3615,17 @@ DCHECK(network_metadata_store); base::Value::List new_apns; - if (const base::Value::List* old_apns = + if (const base::Value::List* old_custom_apns = network_metadata_store->GetCustomApnList(network_guid)) { - new_apns = old_apns->Clone(); + if (old_custom_apns->size() >= mojom::kMaxNumCustomApns) { + NET_LOG(ERROR) + << "CreateCustomApn: Cannot create new custom APN for network: " + << network_guid << ". Network already has the max amount allowed: " + << mojom::kMaxNumCustomApns; + return; + } + + new_apns = old_custom_apns->Clone(); } // Set unique Id for custom APNs
diff --git a/chromeos/services/network_config/cros_network_config_unittest.cc b/chromeos/services/network_config/cros_network_config_unittest.cc index 49c48b5a..2bc22ac 100644 --- a/chromeos/services/network_config/cros_network_config_unittest.cc +++ b/chromeos/services/network_config/cros_network_config_unittest.cc
@@ -1941,6 +1941,45 @@ } } +TEST_F(CrosNetworkConfigTest, CreateCustomApn_MaxAmountAllowed) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(ash::features::kApnRevamp); + + // Register an observer to capture values sent to Shill + TestNetworkConfigurationObserver network_config_observer( + network_configuration_handler()); + + const base::Value::List* custom_apns = + network_metadata_store()->GetCustomApnList(kCellularGuid); + ASSERT_FALSE(custom_apns); + + TestApnData test_apn1; + test_apn1.access_point_name = kCellularTestApn1; + test_apn1.name = kCellularTestApnName1; + test_apn1.username = kCellularTestApnUsername1; + test_apn1.password = kCellularTestApnPassword1; + test_apn1.attach = kCellularTestApnAttach1; + test_apn1.mojo_apn_types = {mojom::ApnType::kDefault, + mojom::ApnType::kAttach}; + test_apn1.onc_apn_types = {::onc::cellular_apn::kApnTypeDefault, + ::onc::cellular_apn::kApnTypeAttach}; + + // Verify that the API creates as many APNs as allowed + for (size_t i = 0; i < mojom::kMaxNumCustomApns; ++i) { + CreateCustomApn(kCellularGuid, test_apn1.AsMojoApn()); + EXPECT_EQ(i + 1, + network_config_observer.GetOnConfigurationModifiedCallCount()); + } + // Verify that the next call does nothing + CreateCustomApn(kCellularGuid, test_apn1.AsMojoApn()); + EXPECT_EQ(mojom::kMaxNumCustomApns, + network_config_observer.GetOnConfigurationModifiedCallCount()); + + custom_apns = network_metadata_store()->GetCustomApnList(kCellularGuid); + ASSERT_TRUE(custom_apns); + EXPECT_EQ(mojom::kMaxNumCustomApns, custom_apns->size()); +} + TEST_F(CrosNetworkConfigTest, ConnectedAPN_ApnRevampEnabled) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeature(ash::features::kApnRevamp);
diff --git a/chromeos/services/network_config/public/mojom/cros_network_config.mojom b/chromeos/services/network_config/public/mojom/cros_network_config.mojom index 8b3acbf0..843530e 100644 --- a/chromeos/services/network_config/public/mojom/cros_network_config.mojom +++ b/chromeos/services/network_config/public/mojom/cros_network_config.mojom
@@ -17,6 +17,9 @@ import "services/network/public/mojom/ip_address.mojom"; import "url/mojom/url.mojom"; +// The maximum number of custom APNs that a cellular network can have. +const uint8 kMaxNumCustomApns = 10; + // Activation state for Cellular networks. enum ActivationStateType { kUnknown,
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillDropdownAdapter.java b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillDropdownAdapter.java index 9deab27..50507d9 100644 --- a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillDropdownAdapter.java +++ b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillDropdownAdapter.java
@@ -291,6 +291,10 @@ } // If a customIcon is provided we prefer to use it over the iconId of the item. if (item.getCustomIcon() != null) { + // TODO(crbug.com/1381189): We need to scale the bitmap because we show custom icons to + // highlight certain credit card features (like virtual cards), which are available in a + // fixed size. In future, if we show only the card art for all cards, there is no need + // to scale the bitmap as we can directly fetch the icon in the required size. // Scale the bitmap to match the dimensions of the default resources used for other // items. Bitmap scaledBitmap = Bitmap.createScaledBitmap(item.getCustomIcon(),
diff --git a/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.js b/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.js index 7077b956..dbdc0ed 100644 --- a/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.js +++ b/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.js
@@ -6,7 +6,7 @@ import 'chrome://resources/js/ios/web_ui.js'; // </if> -import {addWebUIListener} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener} from 'chrome://resources/js/cr.js'; import {$} from 'chrome://resources/js/util.js'; // By default this page only records metrics for a given period of time in order @@ -260,7 +260,7 @@ setUpMarker(); setUpDownload('password-manager'); setUpStopRecording(); - addWebUIListener( + addWebUiListener( 'enable-reset-upm-eviction-button', enableResetUpmEvictionButton); } @@ -414,13 +414,13 @@ } document.addEventListener('DOMContentLoaded', function(event) { - addWebUIListener('enable-reset-cache-button', enableResetCacheButton); - addWebUIListener('notify-about-incognito', notifyAboutIncognito); - addWebUIListener('notify-about-variations', notifyAboutVariations); - addWebUIListener('notify-reset-done', message => showModalDialog(message)); - addWebUIListener('add-structured-log', addStructuredLog); - addWebUIListener('setup-autofill-internals', setUpAutofillInternals); - addWebUIListener( + addWebUiListener('enable-reset-cache-button', enableResetCacheButton); + addWebUiListener('notify-about-incognito', notifyAboutIncognito); + addWebUiListener('notify-about-variations', notifyAboutVariations); + addWebUiListener('notify-reset-done', message => showModalDialog(message)); + addWebUiListener('add-structured-log', addStructuredLog); + addWebUiListener('setup-autofill-internals', setUpAutofillInternals); + addWebUiListener( 'setup-password-manager-internals', setUpPasswordManagerInternals); chrome.send('loaded');
diff --git a/components/autofill/core/browser/form_types.cc b/components/autofill/core/browser/form_types.cc index 8b542bd7..15b6a13 100644 --- a/components/autofill/core/browser/form_types.cc +++ b/components/autofill/core/browser/form_types.cc
@@ -34,13 +34,13 @@ base::StringPiece FormTypeToStringPiece(FormType form_type) { switch (form_type) { case FormType::kAddressForm: - return "AddressForm"; + return "Address"; case FormType::kCreditCardForm: - return "CreditCardForm"; + return "CreditCard"; case FormType::kPasswordForm: - return "PasswordForm"; + return "Password"; case FormType::kUnknownFormType: - return "UnknownFormType"; + return "Unknown"; } NOTREACHED();
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc index ce90a7c..597d27f 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc +++ b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
@@ -469,8 +469,7 @@ base::HistogramTester histogram_tester; SubmitForm(form); - const std::string histogram_prefix = - "Autofill.FieldFillingStats.AddressForm."; + const std::string histogram_prefix = "Autofill.FieldFillingStats.Address."; histogram_tester.ExpectUniqueSample(histogram_prefix + "Accepted", 2, 1); histogram_tester.ExpectUniqueSample(histogram_prefix + "CorrectedToSameType",
diff --git a/components/autofill_assistant/android/BUILD.gn b/components/autofill_assistant/android/BUILD.gn index cd1c36d..ac4aa8b0 100644 --- a/components/autofill_assistant/android/BUILD.gn +++ b/components/autofill_assistant/android/BUILD.gn
@@ -76,10 +76,8 @@ "java/src/org/chromium/components/autofill_assistant/AssistantTagsForTesting.java", "java/src/org/chromium/components/autofill_assistant/AssistantTextLinkDelegate.java", "java/src/org/chromium/components/autofill_assistant/AssistantTextUtils.java", - "java/src/org/chromium/components/autofill_assistant/AutofillAssistantActionHandlerImpl.java", "java/src/org/chromium/components/autofill_assistant/AutofillAssistantClient.java", "java/src/org/chromium/components/autofill_assistant/AutofillAssistantDependencyInjector.java", - "java/src/org/chromium/components/autofill_assistant/AutofillAssistantDirectActionImpl.java", "java/src/org/chromium/components/autofill_assistant/AutofillAssistantModuleEntryImpl.java", "java/src/org/chromium/components/autofill_assistant/AutofillAssistantUiController.java", "java/src/org/chromium/components/autofill_assistant/BottomSheetUtils.java", @@ -216,8 +214,6 @@ "public/java/src/org/chromium/components/autofill_assistant/AssistantModuleInstallUi.java", "public/java/src/org/chromium/components/autofill_assistant/AssistantOnboardingHelper.java", "public/java/src/org/chromium/components/autofill_assistant/AssistantPaymentInstrumentEditorGms.java", - "public/java/src/org/chromium/components/autofill_assistant/AutofillAssistantActionHandler.java", - "public/java/src/org/chromium/components/autofill_assistant/AutofillAssistantDirectAction.java", "public/java/src/org/chromium/components/autofill_assistant/AutofillAssistantMetrics.java", "public/java/src/org/chromium/components/autofill_assistant/AutofillAssistantModuleEntry.java", "public/java/src/org/chromium/components/autofill_assistant/AutofillAssistantModuleEntryProvider.java", @@ -296,7 +292,6 @@ "java/src/org/chromium/components/autofill_assistant/AssistantOnboardingHelperImpl.java", "java/src/org/chromium/components/autofill_assistant/AutofillAssistantClient.java", "java/src/org/chromium/components/autofill_assistant/AutofillAssistantDependencyInjector.java", - "java/src/org/chromium/components/autofill_assistant/AutofillAssistantDirectActionImpl.java", "java/src/org/chromium/components/autofill_assistant/AutofillAssistantUiController.java", "java/src/org/chromium/components/autofill_assistant/carousel/AssistantChip.java", "java/src/org/chromium/components/autofill_assistant/details/AssistantDetails.java",
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AutofillAssistantActionHandlerImpl.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AutofillAssistantActionHandlerImpl.java deleted file mode 100644 index cfb7c03..0000000 --- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AutofillAssistantActionHandlerImpl.java +++ /dev/null
@@ -1,196 +0,0 @@ -// Copyright 2019 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.components.autofill_assistant; - -import android.app.Activity; -import android.os.Bundle; - -import androidx.annotation.Nullable; - -import org.chromium.base.Callback; -import org.chromium.base.ThreadUtils; -import org.chromium.base.supplier.Supplier; -import org.chromium.components.autofill_assistant.onboarding.AssistantOnboardingResult; -import org.chromium.components.autofill_assistant.onboarding.BaseOnboardingCoordinator; -import org.chromium.components.autofill_assistant.onboarding.OnboardingCoordinatorFactory; -import org.chromium.components.autofill_assistant.overlay.AssistantOverlayCoordinator; -import org.chromium.components.user_prefs.UserPrefs; -import org.chromium.content_public.browser.WebContents; -import org.chromium.ui.base.WindowAndroid; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * A handler that provides Autofill Assistant actions for a specific activity. - */ -public class AutofillAssistantActionHandlerImpl implements AutofillAssistantActionHandler { - private final OnboardingCoordinatorFactory mOnboardingCoordinatorFactory; - private final AssistantStaticDependencies mStaticDependencies; - private final Supplier<WebContents> mWebContentsSupplier; - // Encapsulates access to {@link PrefService} pref keys for Autofill Assistant. - private final AutofillAssistantPreferenceManager mPreferenceManager; - - public AutofillAssistantActionHandlerImpl( - OnboardingCoordinatorFactory onboardingCoordinatorFactory, - Supplier<WebContents> webContentsSupplier, - AssistantStaticDependencies staticDependencies) { - mOnboardingCoordinatorFactory = onboardingCoordinatorFactory; - mWebContentsSupplier = webContentsSupplier; - mStaticDependencies = staticDependencies; - mPreferenceManager = new AutofillAssistantPreferenceManager( - UserPrefs.get(mStaticDependencies.getBrowserContext())); - } - - @Override - public void fetchWebsiteActions( - String userName, String experimentIds, Bundle arguments, Callback<Boolean> callback) { - if (!mPreferenceManager.getOnboardingConsent()) { - callback.onResult(false); - return; - } - AutofillAssistantClient client = getOrCreateClient(); - if (client == null) { - callback.onResult(false); - return; - } - - client.fetchWebsiteActions(userName, experimentIds, toArgumentMap(arguments), callback); - } - - @Override - public boolean hasRunFirstCheck() { - if (!mPreferenceManager.getOnboardingConsent()) { - return false; - } - - AutofillAssistantClient client = getOrCreateClient(); - if (client == null) return false; - return client.hasRunFirstCheck(); - } - - @Override - public List<AutofillAssistantDirectAction> getActions() { - AutofillAssistantClient client = getOrCreateClient(); - if (client == null) { - return Collections.emptyList(); - } - return client.getDirectActions(); - } - - @Override - public void performOnboarding( - String experimentIds, Bundle arguments, Callback<Boolean> callback) { - Map<String, String> parameters = toArgumentMap(arguments); - BaseOnboardingCoordinator coordinator = - mOnboardingCoordinatorFactory.createBottomSheetOnboardingCoordinator( - experimentIds, parameters); - coordinator.show(result -> { - coordinator.hide(); - callback.onResult(result == AssistantOnboardingResult.ACCEPTED); - }); - } - - @Override - public void performAction( - String name, String experimentIds, Bundle arguments, Callback<Boolean> callback) { - AutofillAssistantClient client = getOrCreateClient(); - if (client == null) { - callback.onResult(false); - return; - } - - Map<String, String> argumentMap = toArgumentMap(arguments); - Callback<AssistantOverlayCoordinator> afterOnboarding = (overlayCoordinator) -> { - callback.onResult(client.performDirectAction( - name, experimentIds, argumentMap, overlayCoordinator)); - }; - - if (!mPreferenceManager.getOnboardingConsent()) { - BaseOnboardingCoordinator coordinator = - mOnboardingCoordinatorFactory.createBottomSheetOnboardingCoordinator( - experimentIds, argumentMap); - coordinator.show(result -> { - if (result != AssistantOnboardingResult.ACCEPTED) { - coordinator.hide(); - callback.onResult(false); - return; - } - afterOnboarding.onResult(coordinator.transferControls()); - }); - return; - } - afterOnboarding.onResult(null); - } - - @Override - public void showFatalError() { - AutofillAssistantClient client = getOrCreateClient(); - if (client == null) { - return; - } - client.showFatalError(); - } - - @Override - public boolean isSupervisedUser() { - AutofillAssistantClient client = getOrCreateClient(); - if (client == null) { - return false; - } - return client.isSupervisedUser(); - } - - /** - * Returns a client for the current tab or {@code null} if there's no current tab or the current - * tab doesn't have an associated browser content. - */ - @Nullable - private AutofillAssistantClient getOrCreateClient() { - ThreadUtils.assertOnUiThread(); - - WebContents webContents = mWebContentsSupplier.get(); - Activity activity = getActivityFromWebContents(webContents); - if (webContents == null || activity == null) { - return null; - } - - return AutofillAssistantClient.createForWebContents( - webContents, mStaticDependencies.createDependencies(activity)); - } - - /** - * Looks up the Activity of the given web contents. This can be null. Should never be cached, - * because web contents can change activities, e.g., when user selects "Open in Chrome" menu - * item. - * - * @param webContents The web contents for which to lookup the Activity. - * @return Activity currently related to webContents. Could be <c>null</c> and could change, - * therefore do not cache. - */ - @Nullable - private static Activity getActivityFromWebContents(@Nullable WebContents webContents) { - if (webContents == null || webContents.isDestroyed()) return null; - - WindowAndroid window = webContents.getTopLevelNativeWindow(); - if (window == null) return null; - - return window.getActivity().get(); - } - - /** Extracts string arguments from a bundle. */ - private Map<String, String> toArgumentMap(Bundle bundle) { - Map<String, String> map = new HashMap<>(); - for (String key : bundle.keySet()) { - String value = bundle.getString(key); - if (value != null) { - map.put(key, value); - } - } - return map; - } -}
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AutofillAssistantClient.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AutofillAssistantClient.java index 8daba2c..4a854623 100644 --- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AutofillAssistantClient.java +++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AutofillAssistantClient.java
@@ -11,11 +11,9 @@ import androidx.annotation.Nullable; import org.chromium.base.Callback; -import org.chromium.base.ThreadUtils; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeMethods; -import org.chromium.components.autofill_assistant.overlay.AssistantOverlayCoordinator; import org.chromium.components.autofill_assistant.user_data.GmsIntegrator; import org.chromium.components.signin.AccessTokenData; import org.chromium.components.signin.AccountManagerFacadeProvider; @@ -23,10 +21,7 @@ import org.chromium.content.browser.accessibility.BrowserAccessibilityState; import org.chromium.content_public.browser.WebContents; -import java.util.Arrays; -import java.util.Collections; import java.util.List; -import java.util.Map; /** * An Autofill Assistant client, associated with a specific WebContents. @@ -113,69 +108,6 @@ mNativeClientAndroid, AutofillAssistantClient.this); } - /** Starts the controller and fetching scripts for websites. */ - public void fetchWebsiteActions(String userName, String experimentIds, - Map<String, String> arguments, Callback<Boolean> callback) { - if (mNativeClientAndroid == 0) { - callback.onResult(false); - return; - } - - chooseAccountAsyncIfNecessary(userName.isEmpty() ? null : userName); - - // The native side calls sendDirectActionList() on the callback once the controller has - // results. - AutofillAssistantClientJni.get().fetchWebsiteActions(mNativeClientAndroid, - AutofillAssistantClient.this, experimentIds, - arguments.keySet().toArray(new String[arguments.size()]), - arguments.values().toArray(new String[arguments.size()]), callback); - } - - /** Return true if the controller exists and is in tracking mode. */ - public boolean hasRunFirstCheck() { - if (mNativeClientAndroid == 0) { - return false; - } - - ThreadUtils.assertOnUiThread(); - return AutofillAssistantClientJni.get().hasRunFirstCheck( - mNativeClientAndroid, AutofillAssistantClient.this); - } - - /** Lists available direct actions. */ - public List<AutofillAssistantDirectAction> getDirectActions() { - if (mNativeClientAndroid == 0) { - return Collections.emptyList(); - } - AutofillAssistantDirectAction[] actions = AutofillAssistantClientJni.get().getDirectActions( - mNativeClientAndroid, AutofillAssistantClient.this); - return Arrays.asList(actions); - } - - /** - * Performs a direct action. - * - * @param actionId id of the action - * @param experimentIds comma-separated set of experiments to use while running the flow - * @param arguments report these as script parameters while performing this specific action - * @param overlayCoordinator if non-null, reuse existing UI elements, usually created to show - * onboarding. - * @return true if the action was found started, false otherwise. The action can still fail - * after this method returns true; the failure will be displayed on the UI. - */ - public boolean performDirectAction(String actionId, String experimentIds, - Map<String, String> arguments, - @Nullable AssistantOverlayCoordinator overlayCoordinator) { - if (mNativeClientAndroid == 0) return false; - - // Note that only fetchWebsiteActions can start AA, so only it needs - // chooseAccountAsyncIfNecessary. - return AutofillAssistantClientJni.get().performDirectAction(mNativeClientAndroid, - AutofillAssistantClient.this, actionId, experimentIds, - arguments.keySet().toArray(new String[arguments.size()]), - arguments.values().toArray(new String[arguments.size()]), overlayCoordinator); - } - /** * Displays a generic error message. Intended for direct actions only, to let specific direct * actions show an error on failure. @@ -358,12 +290,6 @@ return Build.MODEL; } - /** Adds a dynamic action to the given reporter. */ - @CalledByNative - private void onFetchWebsiteActions(Callback<Boolean> callback, boolean success) { - callback.onResult(success); - } - @CalledByNative private void clearNativePtr() { mNativeClientAndroid = 0; @@ -380,15 +306,6 @@ long nativeClientAndroid, AutofillAssistantClient caller, byte[] clientToken); String getPrimaryAccountName(long nativeClientAndroid, AutofillAssistantClient caller); void onJavaDestroyUI(long nativeClientAndroid, AutofillAssistantClient caller); - void fetchWebsiteActions(long nativeClientAndroid, AutofillAssistantClient caller, - String experimentIds, String[] argumentNames, String[] argumentValues, - Object callback); - boolean hasRunFirstCheck(long nativeClientAndroid, AutofillAssistantClient caller); - AutofillAssistantDirectAction[] getDirectActions( - long nativeClientAndroid, AutofillAssistantClient caller); - boolean performDirectAction(long nativeClientAndroid, AutofillAssistantClient caller, - String actionId, String experimentId, String[] argumentNames, - String[] argumentValues, @Nullable AssistantOverlayCoordinator overlayCoordinator); void showFatalError(long nativeClientAndroid, AutofillAssistantClient caller); boolean isSupervisedUser(long nativeClientAndroid, AutofillAssistantClient caller); void onSpokenFeedbackAccessibilityServiceChanged(
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AutofillAssistantDirectActionImpl.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AutofillAssistantDirectActionImpl.java deleted file mode 100644 index 6b43c4d..0000000 --- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AutofillAssistantDirectActionImpl.java +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2019 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.components.autofill_assistant; - -import org.chromium.base.annotations.CalledByNative; -import org.chromium.base.annotations.JNINamespace; - -import java.util.Arrays; -import java.util.List; - -/** - * A container that corresponds to the DirectActionProto used to store action realated data like - * arguments. - */ -@JNINamespace("autofill_assistant") -public class AutofillAssistantDirectActionImpl implements AutofillAssistantDirectAction { - /* List of direct actions with the given names. */ - private final List<String> mNames; - - /* List of required argument names for this action. */ - private final List<String> mRequiredArguments; - - /* List of optional argument names for this action. */ - private final List<String> mOptionalArguments; - - @CalledByNative - public AutofillAssistantDirectActionImpl(String[] names, String[] required, String[] optional) { - mNames = Arrays.asList(names); - mRequiredArguments = Arrays.asList(required); - mOptionalArguments = Arrays.asList(optional); - } - - @Override - public List<String> getNames() { - return mNames; - } - - @Override - public List<String> getRequiredArguments() { - return mRequiredArguments; - } - - @Override - public List<String> getOptionalArguments() { - return mOptionalArguments; - } -}
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AutofillAssistantModuleEntryImpl.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AutofillAssistantModuleEntryImpl.java index e3f6893..1eb1f90 100644 --- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AutofillAssistantModuleEntryImpl.java +++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AutofillAssistantModuleEntryImpl.java
@@ -4,12 +4,6 @@ package org.chromium.components.autofill_assistant; -import android.content.Context; -import android.view.View; - -import org.chromium.base.supplier.Supplier; -import org.chromium.components.autofill_assistant.onboarding.OnboardingCoordinatorFactory; -import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.content_public.browser.WebContents; /** @@ -22,18 +16,4 @@ WebContents webContents, AssistantDependencies dependencies) { return new AssistantOnboardingHelperImpl(webContents, dependencies); } - - @Override - public AutofillAssistantActionHandler createActionHandler(Context context, - BottomSheetController bottomSheetController, - AssistantBrowserControlsFactory browserControlsFactory, View rootView, - Supplier<WebContents> webContentsSupplier, - AssistantStaticDependencies staticDependencies) { - return new AutofillAssistantActionHandlerImpl( - new OnboardingCoordinatorFactory(context, bottomSheetController, - staticDependencies.getBrowserContext(), browserControlsFactory, rootView, - staticDependencies.getAccessibilityUtil(), - staticDependencies.createInfoPageUtil()), - webContentsSupplier, staticDependencies); - } }
diff --git a/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AutofillAssistantActionHandler.java b/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AutofillAssistantActionHandler.java deleted file mode 100644 index 8fdc35c9..0000000 --- a/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AutofillAssistantActionHandler.java +++ /dev/null
@@ -1,82 +0,0 @@ -// Copyright 2019 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.components.autofill_assistant; - -import android.os.Bundle; - -import org.chromium.base.Callback; - -import java.util.List; - -/** - * Interface that provides implementation for AA actions, triggered by direct actions. - */ -public interface AutofillAssistantActionHandler { - /** - * Start fetching potential actions for websites. - * - * <p>This method starts AA on the current tab, if necessary, and waits for the first results. - * The method hasRunFirstCheck will return true when that's done. Note that {@code callback} - * will receive true if fetching actions was successful and the resulting set is not empty. - * <p>This method needs to be called before getActions below will return anything. - * - * @param userName name of the user to use when sending RPCs. Might be empty. - * @param experimentIds comma-separated set of experiment ids. Might be empty - * @param arguments extra arguments to include into the RPC. Might be empty. - * @param callback callback to report when actions are available. - */ - void fetchWebsiteActions( - String userName, String experimentIds, Bundle arguments, Callback<Boolean> callback); - - /** - * Returns if autofill assistant has fetched actions for the current URL. - * - * <p>This method queries the underlying Autofill Assistant stack to find out if it has been - * started and whether the first round of fetching scripts and checking availability has been - * completed. - * - * @return Whether scripts have been fetched and preconditions checked. - */ - boolean hasRunFirstCheck(); - - /** - * Returns the available AA actions to be reported to the direct actions framework. - * - * <p>This method simply returns the list of actions known to AA. An empty string array means - * either that the controller has not yet been started or there are no actions available for the - * current website. - * - * @return Array of actions containing the names and arguments of known actions. - */ - List<AutofillAssistantDirectAction> getActions(); - - /** Performs onboarding and returns the result to the callback. */ - void performOnboarding(String experimentIds, Bundle arguments, Callback<Boolean> callback); - - /** - * Performs an AA action. - * - * <p>If this method returns {@code true}, a definition for the action was successfully started. - * It can still fail later, and the failure will be reported to the UI. - * - * @param name action name, might be empty to autostart - * @param experimentIds comma-separated set of experiment ids. Might be empty. - * @param arguments extra arguments to pass to the action. Might be empty. - * @param callback to report the result to - */ - void performAction( - String name, String experimentIds, Bundle arguments, Callback<Boolean> callback); - - /** - * Displays a generic error message to the user. - */ - void showFatalError(); - - /** - * Check whether the user is supervised. - * @return supervised state - */ - boolean isSupervisedUser(); -}
diff --git a/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AutofillAssistantDirectAction.java b/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AutofillAssistantDirectAction.java deleted file mode 100644 index b99d5b1..0000000 --- a/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AutofillAssistantDirectAction.java +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2019 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.components.autofill_assistant; - -import java.util.List; - -/** - * Interface for direct action containers. - */ -public interface AutofillAssistantDirectAction { - /** Returns a list of name and aliases for this direct action. */ - List<String> getNames(); - - /** Returns the list of required argument names. */ - List<String> getRequiredArguments(); - - /** Returns the list of optional argument names. */ - List<String> getOptionalArguments(); -}
diff --git a/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AutofillAssistantModuleEntry.java b/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AutofillAssistantModuleEntry.java index 3118ca3..33af909 100644 --- a/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AutofillAssistantModuleEntry.java +++ b/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AutofillAssistantModuleEntry.java
@@ -4,11 +4,6 @@ package org.chromium.components.autofill_assistant; -import android.content.Context; -import android.view.View; - -import org.chromium.base.supplier.Supplier; -import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.module_installer.builder.ModuleInterface; import org.chromium.content_public.browser.WebContents; @@ -25,21 +20,4 @@ */ AssistantOnboardingHelper createOnboardingHelper( WebContents webContents, AssistantDependencies dependencies); - - /** - * Returns a {@link AutofillAssistantActionHandler} instance tied to the activity owning the - * given bottom sheet, and scrim view. - * - * @param context activity context - * @param bottomSheetController bottom sheet controller instance of the activity - * @param browserControlsFactory factory for providing browser controls state - * @param rootView root view of the activity - * @param webContentsSupplier supplier of the current WebContents - * @param staticDependencies used to create platform-specific dependencies - */ - AutofillAssistantActionHandler createActionHandler(Context context, - BottomSheetController bottomSheetController, - AssistantBrowserControlsFactory browserControlsFactory, View rootView, - Supplier<WebContents> webContentsSupplier, - AssistantStaticDependencies staticDependencies); }
diff --git a/components/autofill_assistant/browser/android/client_android.cc b/components/autofill_assistant/browser/android/client_android.cc index d48fc0a..6552d14 100644 --- a/components/autofill_assistant/browser/android/client_android.cc +++ b/components/autofill_assistant/browser/android/client_android.cc
@@ -20,7 +20,6 @@ #include "base/time/default_tick_clock.h" #include "components/autofill_assistant/android/jni_headers/AssistantParseSingleTagXmlUtilWrapper_jni.h" #include "components/autofill_assistant/android/jni_headers/AutofillAssistantClient_jni.h" -#include "components/autofill_assistant/android/jni_headers/AutofillAssistantDirectActionImpl_jni.h" #include "components/autofill_assistant/browser/android/ui_controller_android_utils.h" #include "components/autofill_assistant/browser/autofill_assistant_tts_controller.h" #include "components/autofill_assistant/browser/controller.h" @@ -222,158 +221,6 @@ } } -void ClientAndroid::FetchWebsiteActions( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcaller, - const base::android::JavaParamRef<jstring>& jexperiment_ids, - const base::android::JavaParamRef<jobjectArray>& jparameter_names, - const base::android::JavaParamRef<jobjectArray>& jparameter_values, - const base::android::JavaParamRef<jobject>& jcallback) { - if (!controller_) { - CreateController(ui_controller_android_utils::GetServiceToInject(env, this), - /* trigger_script= */ absl::nullopt); - } - - base::android::ScopedJavaGlobalRef<jobject> scoped_jcallback(env, jcallback); - controller_->Track( - ui_controller_android_utils::CreateTriggerContext( - env, GetWebContents(), jexperiment_ids, jparameter_names, - jparameter_values, /* jdevice_only_parameter_names= */ - base::android::JavaParamRef<jobjectArray>(nullptr), - /* jdevice_only_parameter_values= */ - base::android::JavaParamRef<jobjectArray>(nullptr), - /* onboarding_shown = */ false, - /* is_direct_action = */ true, - /* jinitial_url = */ nullptr, - /* is_custom_tab = */ - dependencies_->GetPlatformDependencies()->IsCustomTab( - *GetWebContents())), - base::BindOnce(&ClientAndroid::OnFetchWebsiteActions, - weak_ptr_factory_.GetWeakPtr(), scoped_jcallback)); -} - -bool ClientAndroid::HasRunFirstCheck( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcaller) const { - return controller_ != nullptr && controller_->HasRunFirstCheck(); -} - -base::android::ScopedJavaLocalRef<jobjectArray> -ClientAndroid::GetDirectActionsAsJavaArrayOfStrings(JNIEnv* env) const { - // Using a set here helps remove duplicates. - std::set<std::string> names; - - if (!controller_) { - return base::android::ToJavaArrayOfStrings( - env, std::vector<std::string>(names.begin(), names.end())); - } - - for (const ScriptHandle& script : controller_->GetDirectActionScripts()) { - for (const std::string& name : script.direct_action.names) { - names.insert(name); - } - } - - return base::android::ToJavaArrayOfStrings( - env, std::vector<std::string>(names.begin(), names.end())); -} - -base::android::ScopedJavaLocalRef<jobject> -ClientAndroid::ToJavaAutofillAssistantDirectAction( - JNIEnv* env, - const DirectAction& direct_action) const { - std::set<std::string> names; - for (const std::string& name : direct_action.names) - names.insert(name); - auto jnames = base::android::ToJavaArrayOfStrings( - env, std::vector<std::string>(names.begin(), names.end())); - - std::vector<std::string> required_arguments; - for (const std::string& arg : direct_action.required_arguments) - required_arguments.emplace_back(arg); - auto jrequired_arguments = - base::android::ToJavaArrayOfStrings(env, required_arguments); - - std::vector<std::string> optional_arguments; - for (const std::string& arg : direct_action.optional_arguments) - optional_arguments.emplace_back(arg); - auto joptional_arguments = - base::android::ToJavaArrayOfStrings(env, std::move(optional_arguments)); - - return Java_AutofillAssistantDirectActionImpl_Constructor( - env, jnames, jrequired_arguments, joptional_arguments); -} - -base::android::ScopedJavaLocalRef<jobjectArray> ClientAndroid::GetDirectActions( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcaller) { - DCHECK(controller_ != nullptr); - // Prepare the java array to hold the direct actions. - base::android::ScopedJavaLocalRef<jclass> directaction_array_class = - base::android::GetClass(env, - "org/chromium/components/autofill_assistant/" - "AutofillAssistantDirectActionImpl", - "autofill_assistant"); - - const std::vector<ScriptHandle>& direct_action_scripts = - controller_->GetDirectActionScripts(); - - jobjectArray joa = env->NewObjectArray( - direct_action_scripts.size(), directaction_array_class.obj(), nullptr); - jni_generator::CheckException(env); - - for (size_t i = 0; i < direct_action_scripts.size(); i++) { - auto jdirect_action = ToJavaAutofillAssistantDirectAction( - env, direct_action_scripts.at(i).direct_action); - env->SetObjectArrayElement(joa, i, jdirect_action.obj()); - } - return base::android::ScopedJavaLocalRef<jobjectArray>(env, joa); -} - -void ClientAndroid::OnFetchWebsiteActions( - const base::android::JavaRef<jobject>& jcallback) { - JNIEnv* env = AttachCurrentThread(); - Java_AutofillAssistantClient_onFetchWebsiteActions( - env, java_object_, jcallback, controller_ != nullptr); -} - -bool ClientAndroid::PerformDirectAction( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcaller, - const base::android::JavaParamRef<jstring>& jaction_name, - const base::android::JavaParamRef<jstring>& jexperiment_ids, - const base::android::JavaParamRef<jobjectArray>& jparameter_names, - const base::android::JavaParamRef<jobjectArray>& jparameter_values, - const base::android::JavaParamRef<jobject>& joverlay_coordinator) { - std::string action_name = - base::android::ConvertJavaStringToUTF8(env, jaction_name); - - auto trigger_context = ui_controller_android_utils::CreateTriggerContext( - env, GetWebContents(), jexperiment_ids, jparameter_names, - jparameter_values, /* jdevice_only_parameter_names= */ - base::android::JavaParamRef<jobjectArray>(nullptr), - /* jdevice_only_parameter_values= */ - base::android::JavaParamRef<jobjectArray>(nullptr), - /* onboarding_shown = */ false, - /* is_direct_action = */ true, - /* jinitial_url = */ - nullptr, - /* is_custom_tab = */ - dependencies_->GetPlatformDependencies()->IsCustomTab(*GetWebContents())); - - int action_index = FindDirectAction(action_name); - if (action_index == -1) - return false; - - // If an overlay is already shown, then show the rest of the UI immediately. - if (joverlay_coordinator) { - AttachUI(joverlay_coordinator); - } - - return controller_->PerformDirectAction(action_index, - std::move(trigger_context)); -} - void ClientAndroid::ShowFatalError( JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller) { @@ -423,24 +270,6 @@ return jdependencies_; } -int ClientAndroid::FindDirectAction(const std::string& action_name) { - // It's too late to create a controller. This should have been done in - // FetchWebsiteActions. - if (!controller_) - return -1; - - const std::vector<ScriptHandle>& direct_action_scripts = - controller_->GetDirectActionScripts(); - for (size_t i = 0; i < direct_action_scripts.size(); i++) { - const base::flat_set<std::string>& action_names = - direct_action_scripts.at(i).direct_action.names; - if (action_names.count(action_name) != 0) - return i; - } - - return -1; -} - void ClientAndroid::AttachUI() { AttachUI(nullptr); } @@ -777,10 +606,6 @@ started_ = false; } -bool ClientAndroid::NeedsUI() { - return !ui_controller_android_ && controller_ && controller_->NeedsUI(); -} - bool ClientAndroid::GetMakeSearchesAndBrowsingBetterEnabled() const { return dependencies_->GetCommonDependencies() ->GetMakeSearchesAndBrowsingBetterEnabled();
diff --git a/components/autofill_assistant/browser/android/client_android.h b/components/autofill_assistant/browser/android/client_android.h index 0860add80..9ce2a02 100644 --- a/components/autofill_assistant/browser/android/client_android.h +++ b/components/autofill_assistant/browser/android/client_android.h
@@ -79,31 +79,6 @@ const base::android::JavaParamRef<jobject>& jcaller, const base::android::JavaParamRef<jbyteArray>& jclient_token); - void FetchWebsiteActions( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcaller, - const base::android::JavaParamRef<jstring>& jexperiment_ids, - const base::android::JavaParamRef<jobjectArray>& jargument_names, - const base::android::JavaParamRef<jobjectArray>& jargument_values, - const base::android::JavaParamRef<jobject>& jcallback); - - bool HasRunFirstCheck( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcaller) const; - - base::android::ScopedJavaLocalRef<jobjectArray> GetDirectActions( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcaller); - - bool PerformDirectAction( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcaller, - const base::android::JavaParamRef<jstring>& jaction_id, - const base::android::JavaParamRef<jstring>& jexperiment_ids, - const base::android::JavaParamRef<jobjectArray>& jargument_names, - const base::android::JavaParamRef<jobjectArray>& jargument_values, - const base::android::JavaParamRef<jobject>& joverlay_coordinator); - void ShowFatalError(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); @@ -176,21 +151,8 @@ const absl::optional<TriggerScriptProto>& trigger_script); void DestroyController(); void AttachUI(const base::android::JavaRef<jobject>& joverlay_coordinator); - bool NeedsUI(); - void OnFetchWebsiteActions(const base::android::JavaRef<jobject>& jcallback); void SafeDestroyControllerAndUI(Metrics::DropOutReason reason); - base::android::ScopedJavaLocalRef<jobjectArray> - GetDirectActionsAsJavaArrayOfStrings(JNIEnv* env) const; - - base::android::ScopedJavaLocalRef<jobject> - ToJavaAutofillAssistantDirectAction(JNIEnv* env, - const DirectAction& direct_action) const; - - // Returns the index of a direct action with that name, to pass to - // UiDelegate::PerformUserAction() or -1 if not found. - int FindDirectAction(const std::string& action_name); - void OnAnnotateDomModelFileAvailable( base::OnceCallback<void(absl::optional<int64_t>)> callback, bool available);
diff --git a/components/autofill_assistant/browser/android/ui_controller_android.cc b/components/autofill_assistant/browser/android/ui_controller_android.cc index 201355b..bfb262dd 100644 --- a/components/autofill_assistant/browser/android/ui_controller_android.cc +++ b/components/autofill_assistant/browser/android/ui_controller_android.cc
@@ -507,19 +507,6 @@ ResetGenericUiControllers(); return; - case AutofillAssistantState::TRACKING: - SetOverlayState(OverlayState::HIDDEN); - SetSpinPoodle(false); - - if (!execution_delegate_->NeedsUI()) { - Java_AssistantModel_setVisible(AttachCurrentThread(), GetModel(), - false); - DestroySelf(); - } else if (execution_delegate_->IsTabSelected()) { - ShowContentAndExpandBottomSheet(); - } - return; - case AutofillAssistantState::INACTIVE: // Wait for the state to change. return; @@ -895,8 +882,7 @@ // Special case: don't create a default cancel chip during shutdown. if (!has_close_or_cancel && !ui_delegate_->IsUiShuttingDown()) { base::android::ScopedJavaLocalRef<jobject> jcancel_chip; - if (execution_delegate_->GetState() == AutofillAssistantState::STOPPED || - execution_delegate_->GetState() == AutofillAssistantState::TRACKING) { + if (execution_delegate_->GetState() == AutofillAssistantState::STOPPED) { jcancel_chip = Java_AutofillAssistantUiController_createCloseButton( env, java_object_, static_cast<int>(CLOSE_ACTION), ICON_CLEAR, ConvertUTF8ToJavaString(env, ""),
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc index de59a77..d0284a1 100644 --- a/components/autofill_assistant/browser/controller.cc +++ b/components/autofill_assistant/browser/controller.cc
@@ -170,10 +170,6 @@ touchable_element_area()->SetFromProto(area); } -const std::vector<ScriptHandle>& Controller::GetDirectActionScripts() const { - return direct_action_scripts_; -} - bool Controller::IsNavigatingToNewDocument() { return navigating_to_new_document_; } @@ -260,24 +256,6 @@ browse_domains_allowlist_ = std::move(domains); } -bool Controller::PerformDirectAction(int index, - std::unique_ptr<TriggerContext> context) { - if (index < 0 || - static_cast<size_t>(index) >= direct_action_scripts_.size()) { - NOTREACHED() << "Invalid direct action index: " << index; - return false; - } - - ScriptHandle handle = direct_action_scripts_.at(index); - direct_action_scripts_.clear(); - ExecuteScript(handle.path, handle.start_message, handle.needs_ui, - std::move(context), - state_ == AutofillAssistantState::TRACKING - ? AutofillAssistantState::TRACKING - : AutofillAssistantState::PROMPT); - return true; -} - void Controller::SetViewportMode(ViewportMode mode) { if (mode == viewport_mode_) return; @@ -360,15 +338,10 @@ } void Controller::ShutdownIfNecessary() { - if (!tracking_) { - // We expect the DropOutReason to be already reported when we reach this - // point and therefore the reason we pass here in the argument should be - // ignored. - Shutdown(Metrics::DropOutReason::UI_CLOSED_UNEXPECTEDLY); - } else if (NeedsUI()) { - needs_ui_ = false; - client_->DestroyUISoon(); - } + // We expect the DropOutReason to be already reported when we reach this + // point and therefore the reason we pass here in the argument should be + // ignored. + Shutdown(Metrics::DropOutReason::UI_CLOSED_UNEXPECTEDLY); } void Controller::EnterBrowseModeForShutdown() { @@ -404,10 +377,8 @@ VLOG(2) << __func__ << ": " << state_ << " -> " << state; - // The only valid way of leaving the STOPPED state is to go back to tracking - // mode. - DCHECK(state_ != AutofillAssistantState::STOPPED || - (state == AutofillAssistantState::TRACKING && tracking_)); + // Leaving the STOPPED state is not allowed. + DCHECK(state_ != AutofillAssistantState::STOPPED); state_ = state; bool should_suppress_keyboard = ShouldSuppressKeyboard(); @@ -439,17 +410,12 @@ } void Controller::OnUrlChange() { - if (state_ == AutofillAssistantState::STOPPED) { - PerformDelayedShutdownIfNecessary(); - return; - } user_model_.SetCurrentURL(GetCurrentURL()); GetOrCheckScripts(); } bool Controller::ShouldCheckScripts() { - return state_ == AutofillAssistantState::TRACKING || - state_ == AutofillAssistantState::STARTING || + return state_ == AutofillAssistantState::STARTING || ((state_ == AutofillAssistantState::PROMPT || state_ == AutofillAssistantState::BROWSE) && (!script_tracker_ || !script_tracker_->running())); @@ -646,13 +612,6 @@ if (scripts.empty()) { script_tracker()->SetScripts({}); - - if (state_ == AutofillAssistantState::TRACKING) { - OnFatalError(GetDisplayStringUTF8(ClientSettingsProto::DEFAULT_ERROR, - GetSettings()), - Metrics::DropOutReason::NO_SCRIPTS); - return; - } OnNoRunnableScriptsForPage(); } @@ -667,19 +626,8 @@ AutofillAssistantState end_state) { DCHECK(!script_tracker()->running()); - // To prevent state from persisting across direct actions, we need to - // explicitly clear it each time before we run a script (b/195417453). Note - // that for cases where a JITT script transitions into a regular script, - // preserving state is important, so we can't clear this indiscriminately. - if (context->GetDirectAction()) { - ResetState(); - } - if (needs_ui) { RequireUI(); - } else if (needs_ui_ && state_ == AutofillAssistantState::TRACKING) { - needs_ui_ = false; - client_->DestroyUI(); } EnterState(AutofillAssistantState::RUNNING); @@ -691,7 +639,6 @@ // Runnable scripts will be checked and reported if necessary after executing // the script. script_tracker_->ClearRunnableScripts(); - direct_action_scripts_.clear(); script_tracker()->ExecuteScript( script_path, &user_data_, std::move(context), @@ -722,43 +669,21 @@ switch (result.at_end) { case ScriptExecutor::SHUTDOWN: - if (!tracking_) { - Shutdown(Metrics::DropOutReason::SCRIPT_SHUTDOWN); - return; - } - needs_ui_ = false; - end_state = AutofillAssistantState::TRACKING; - break; - + Shutdown(Metrics::DropOutReason::SCRIPT_SHUTDOWN); + return; case ScriptExecutor::SHUTDOWN_GRACEFULLY: - if (!tracking_) { - EnterStoppedState(); - RecordDropOutOrShutdown(Metrics::DropOutReason::SCRIPT_SHUTDOWN); - return; - } - needs_ui_ = true; - SetStoppedUI(); - end_state = AutofillAssistantState::TRACKING; - break; - + EnterStoppedState(); + RecordDropOutOrShutdown(Metrics::DropOutReason::SCRIPT_SHUTDOWN); + return; case ScriptExecutor::CLOSE_CUSTOM_TAB: for (ControllerObserver& observer : observers_) { observer.CloseCustomTab(); } - if (!tracking_) { - Shutdown(Metrics::DropOutReason::CUSTOM_TAB_CLOSED); - return; - } - needs_ui_ = false; - end_state = AutofillAssistantState::TRACKING; + Shutdown(Metrics::DropOutReason::CUSTOM_TAB_CLOSED); return; - case ScriptExecutor::CONTINUE: - if (end_state == AutofillAssistantState::TRACKING) { - needs_ui_ = false; - } + // Do nothing. break; - default: VLOG(1) << "Unexpected value for at_end: " << result.at_end; break; @@ -766,15 +691,6 @@ EnterState(end_state); } -void Controller::ResetState() { - viewport_mode_ = ViewportMode::NO_RESIZE; - overlay_behavior_ = ConfigureUiStateProto::DEFAULT; - touchable_element_area()->Clear(); - for (ControllerObserver& observer : observers_) { - observer.OnResetState(); - } -} - void Controller::MaybeAutostartScript( const std::vector<ScriptHandle>& runnable_scripts) { // We are still waiting for preconditions to match. @@ -795,7 +711,6 @@ } if (autostart_index == -1) { - SetDirectActionScripts(runnable_scripts); return; } @@ -862,36 +777,9 @@ trigger_context_->GetScriptParameters().GetDisableRpcSigning()); } -void Controller::Track(std::unique_ptr<TriggerContext> trigger_context, - base::OnceCallback<void()> on_first_check_done) { - tracking_ = true; - - if (state_ == AutofillAssistantState::INACTIVE) { - trigger_context_ = std::move(trigger_context); - InitFromParameters(); - for (ControllerObserver& observer : observers_) { - observer.OnStart(*GetTriggerContext()); - } - EnterState(AutofillAssistantState::TRACKING); - } - - if (on_first_check_done) { - if (has_run_first_check_) { - std::move(on_first_check_done).Run(); - } else { - on_has_run_first_check_.emplace_back(std::move(on_first_check_done)); - } - } -} - -bool Controller::HasRunFirstCheck() const { - return tracking_ && has_run_first_check_; -} - bool Controller::Start(const GURL& deeplink_url, std::unique_ptr<TriggerContext> trigger_context) { - if (state_ != AutofillAssistantState::INACTIVE && - state_ != AutofillAssistantState::TRACKING) { + if (state_ != AutofillAssistantState::INACTIVE) { return false; } @@ -904,10 +792,6 @@ return false; } - // Force a re-evaluation of the script, to get a chance to autostart. - if (state_ == AutofillAssistantState::TRACKING) - script_tracker_->ClearRunnableScripts(); - if (IsNavigatingToNewDocument()) { start_after_navigation_ = base::BindOnce( &Controller::ShowFirstMessageAndStart, weak_ptr_factory_.GetWeakPtr()); @@ -950,7 +834,6 @@ case AutofillAssistantState::BROWSE: case AutofillAssistantState::MODAL_DIALOG: case AutofillAssistantState::STOPPED: - case AutofillAssistantState::TRACKING: case AutofillAssistantState::INACTIVE: return false; } @@ -1000,11 +883,6 @@ } EnterStoppedState(); - if (tracking_) { - EnterState(AutofillAssistantState::TRACKING); - return; - } - RecordDropOutOrShutdown(reason); } @@ -1021,18 +899,6 @@ } EnterStoppedState(); - // If we haven't managed to check the set of scripts yet at this point, we - // never will. - MaybeReportFirstCheckDone(); - - if (tracking_ && script_url_.host() == GetCurrentURL().host()) { - // When tracking the controller should stays until the browser has navigated - // away from the last domain that was checked to be able to tell callers - // that the set of user actions is empty. - delayed_shutdown_reason_ = reason; - return; - } - RecordDropOutOrShutdown(reason); } @@ -1049,28 +915,6 @@ } } -void Controller::PerformDelayedShutdownIfNecessary() { - if (delayed_shutdown_reason_ && - script_url_.host() != GetCurrentURL().host()) { - Metrics::DropOutReason reason = delayed_shutdown_reason_.value(); - delayed_shutdown_reason_ = absl::nullopt; - tracking_ = false; - Shutdown(reason); - } -} - -void Controller::MaybeReportFirstCheckDone() { - if (has_run_first_check_) - return; - - has_run_first_check_ = true; - - while (!on_has_run_first_check_.empty()) { - std::move(on_has_run_first_check_.back()).Run(); - on_has_run_first_check_.pop_back(); - } -} - void Controller::OnNoRunnableScriptsForPage() { if (script_tracker()->running()) return; @@ -1101,17 +945,6 @@ } } -void Controller::SetDirectActionScripts( - const std::vector<ScriptHandle>& runnable_scripts) { - direct_action_scripts_.clear(); - for (const auto& script : runnable_scripts) { - if (script.direct_action.empty()) - continue; - - direct_action_scripts_.push_back(script); - } -} - void Controller::SetSemanticSelectorPolicy(SemanticSelectorPolicy policy) { DCHECK(annotate_dom_model_service_); if (!annotate_dom_model_service_->SetOverridesPolicy(std::move(policy))) { @@ -1121,32 +954,15 @@ void Controller::OnRunnableScriptsChanged( const std::vector<ScriptHandle>& runnable_scripts) { - base::ScopedClosureRunner report_first_check; - if (!has_run_first_check_) { - // Only report first check done once we're done processing the given set of - // scripts - whatever the outcome - so callers can see that outcome in the - // state of the controller. - report_first_check.ReplaceClosure( - base::BindOnce(&Controller::MaybeReportFirstCheckDone, - weak_ptr_factory_.GetWeakPtr())); - } - // Script selection is disabled when a script is already running. We will // check again and maybe update when the current script has finished. if (script_tracker()->running()) return; - switch (state_) { - case AutofillAssistantState::STARTING: - MaybeAutostartScript(runnable_scripts); - return; - case AutofillAssistantState::TRACKING: - SetDirectActionScripts(runnable_scripts); - return; - default: - // In other states we ignore the script update. - break; + if (state_ == AutofillAssistantState::STARTING) { + MaybeAutostartScript(runnable_scripts); } + // In other states we ignore the script update. } void Controller::DidFinishLoad(content::RenderFrameHost* render_frame_host, @@ -1239,15 +1055,6 @@ return; } - // When in TRACKING state all navigation is allowed, but user-initiated - // navigation will close the UI if any. - if (state_ == AutofillAssistantState::TRACKING && - is_user_initiated_or_back_forward && - !navigation_handle->WasServerRedirect()) { - ShutdownIfNecessary(); - return; - } - // Note that BROWSE state end conditions are in DidFinishNavigation, in order // to be able to properly evaluate the committed url. } @@ -1270,7 +1077,6 @@ return; } break; - case AutofillAssistantState::TRACKING: case AutofillAssistantState::STOPPED: case AutofillAssistantState::INACTIVE: break; @@ -1407,7 +1213,6 @@ return true; case AutofillAssistantState::INACTIVE: - case AutofillAssistantState::TRACKING: case AutofillAssistantState::STOPPED: case AutofillAssistantState::RUNNING: return false;
diff --git a/components/autofill_assistant/browser/controller.h b/components/autofill_assistant/browser/controller.h index e879208..a20d044 100644 --- a/components/autofill_assistant/browser/controller.h +++ b/components/autofill_assistant/browser/controller.h
@@ -79,23 +79,6 @@ ~Controller() override; - // Let the controller know it should keep tracking script availability for the - // current domain, to be ready to report any scripts as action. - // - // Activates the controller, if needed and runs it in the background, without - // showing any UI until a script is started or Start() is called. - // - // Only the context of the first call to Track() is taken into account. - // - // If non-null |on_first_check_done| is called once the result of the first - // check of script availability are in - whether they're positive or negative. - void Track(std::unique_ptr<TriggerContext> trigger_context, - base::OnceCallback<void()> on_first_check_done); - - // Returns true if we are in tracking mode and the first round of script - // checks has been completed. - bool HasRunFirstCheck() const; - // Called when autofill assistant should start. // // This shows a UI, containing a progress bar, and executes the first @@ -103,13 +86,9 @@ // // Start() does nothing if called more than once or if a script is already // running. - // - // Start() will overwrite any context previously set by Track(). bool Start(const GURL& deeplink_url, std::unique_ptr<TriggerContext> trigger_context); - const std::vector<ScriptHandle>& GetDirectActionScripts() const; - bool PerformDirectAction(int index, std::unique_ptr<TriggerContext> context); base::Value GetDebugContext(); // Overrides ScriptExecutorDelegate: @@ -176,7 +155,6 @@ Metrics::DropOutReason reason); // Overrides ExecutionDelegate: - bool NeedsUI() const override; void GetVisualViewport(RectF* visual_viewport) const override; ViewportMode GetViewportMode() override; bool IsTabSelected() override; @@ -241,8 +219,6 @@ void StopPeriodicScriptChecks(); void OnPeriodicScriptCheck(); - void MaybeReportFirstCheckDone(); - // Runs autostart scripts from |runnable_scripts|, if the conditions are // right. Nothing happens if an empty vector is passed. // If none of the scripts is autostartable or too many are, it stops the @@ -302,14 +278,11 @@ bool allow_autostart() { return state_ == AutofillAssistantState::STARTING; } void RecordDropOutOrShutdown(Metrics::DropOutReason reason); - void PerformDelayedShutdownIfNecessary(); bool StateNeedsUI(AutofillAssistantState state); // Resets the controller to the initial state. void ResetState(); - void SetDirectActionScripts( - const std::vector<ScriptHandle>& direct_action_scripts); // Records flow metrics. This may be invoked multiple times per flow, but will // only record the first impression for each flow. @@ -324,6 +297,8 @@ absl::optional<int64_t> model_version); void GetScriptsForUrl(const GURL& url); + bool NeedsUI() const; + ClientSettings settings_; const raw_ptr<Client> client_; const raw_ptr<const base::TickClock> tick_clock_; @@ -373,9 +348,6 @@ // Lazily instantiate in touchable_element_area(). std::unique_ptr<ElementArea> touchable_element_area_; - // Current set of direct actions. - std::vector<ScriptHandle> direct_action_scripts_; - // Current viewport mode. ViewportMode viewport_mode_ = ViewportMode::NO_RESIZE; @@ -411,41 +383,16 @@ base::ObserverList<ControllerObserver> observers_; - // If true, the controller is supposed to stay up and running in the - // background even without UI, keeping track of scripts. - // - // This has two main effects: - // - the controllers stays alive even after a fatal error, just so it can - // immediately report that no actions are available on that website. - // - scripts error are not considered fatal errors. The controller reverts - // to TRACKING mode. - // - // This is set by Track(). - bool tracking_ = false; - // Whether the controller is in a state in which a UI should be shown. bool needs_ui_ = false; // Whether UI is shown. bool ui_shown_ = false; - // True once the controller has run the first set of scripts and have either - // declared it invalid - and entered stopped state - or have processed its - // result - and updated the state and set of available actions. - bool has_run_first_check_ = false; - // Whether the overlay should be set according to state or always hidden. ConfigureUiStateProto::OverlayBehavior overlay_behavior_ = ConfigureUiStateProto::DEFAULT; - // Callbacks to call when |has_run_first_check_| becomes true. - std::vector<base::OnceCallback<void()>> on_has_run_first_check_; - - // If set, the controller entered the STOPPED state but shutdown was delayed - // until the browser has left the |script_url_.host()| for which the decision - // was taken. - absl::optional<Metrics::DropOutReason> delayed_shutdown_reason_; - UserModel user_model_; std::vector<std::string> browse_domains_allowlist_;
diff --git a/components/autofill_assistant/browser/controller_observer.h b/components/autofill_assistant/browser/controller_observer.h index 7aa71127..d3aede0 100644 --- a/components/autofill_assistant/browser/controller_observer.h +++ b/components/autofill_assistant/browser/controller_observer.h
@@ -92,9 +92,6 @@ // Called when the flow is stopped. virtual void OnStop() = 0; - // Called when the state needs to be reset. - virtual void OnResetState() = 0; - // Called whenever the UI is shown or hidden. virtual void OnUiShownChanged(bool shown) = 0; };
diff --git a/components/autofill_assistant/browser/controller_unittest.cc b/components/autofill_assistant/browser/controller_unittest.cc index c8a23903..074ec0b 100644 --- a/components/autofill_assistant/browser/controller_unittest.cc +++ b/components/autofill_assistant/browser/controller_unittest.cc
@@ -171,14 +171,10 @@ protected: static SupportedScriptProto* AddRunnableScript( SupportsScriptResponseProto* response, - const std::string& name_and_path, - bool direct_action = true) { + const std::string& name_and_path) { SupportedScriptProto* script = response->add_scripts(); script->set_path(name_and_path); - if (direct_action) { - script->mutable_presentation()->mutable_direct_action()->add_names( - name_and_path); - } + script->mutable_presentation()->set_autostart(true); return script; } @@ -218,11 +214,6 @@ controller_->Start(url, std::move(trigger_context)); } - void Track() { - SetLastCommittedUrl(GURL("http://initialurl.com")); - controller_->Track(std::make_unique<TriggerContext>(), base::DoNothing()); - } - void SetLastCommittedUrl(const GURL& url) { content::WebContentsTester::For(web_contents())->SetLastCommittedURL(url); } @@ -330,76 +321,6 @@ events.emplace_back(state); } -TEST_F(ControllerTest, ReportDirectActions) { - SupportsScriptResponseProto script_response; - - AddRunnableScript(&script_response, "action"); - - SetNextScriptResponse(script_response); - - testing::InSequence seq; - - Track(); - - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - EXPECT_THAT(controller_->GetDirectActionScripts(), - UnorderedElementsAre(AllOf( - Field(&ScriptHandle::direct_action, - Field(&DirectAction::names, ElementsAre("action")))))); -} - -TEST_F(ControllerTest, RunDirectActionWithArguments) { - SupportsScriptResponseProto script_response; - - // script is available as a direct action. - auto* script1 = AddRunnableScript(&script_response, "action"); - auto* action = script1->mutable_presentation()->mutable_direct_action(); - action->add_required_arguments("required"); - action->add_optional_arguments("arg0"); - action->add_optional_arguments("arg1"); - - SetNextScriptResponse(script_response); - - testing::InSequence seq; - - SetLastCommittedUrl(GURL("http://example.com/")); - controller_->Track(std::make_unique<TriggerContext>(), base::DoNothing()); - - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - EXPECT_THAT(controller_->GetDirectActionScripts(), - ElementsAre(Field( - &ScriptHandle::direct_action, - AllOf(Field(&DirectAction::names, ElementsAre("action")), - Field(&DirectAction::required_arguments, - ElementsAre("required")), - Field(&DirectAction::optional_arguments, - ElementsAre("arg0", "arg1")))))); - - EXPECT_CALL(*mock_service_, GetActions("action", _, _, _, _, _)) - .WillOnce([](const std::string& script_path, const GURL& url, - const TriggerContext& trigger_context, - const std::string& global_payload, - const std::string& script_payload, - ServiceRequestSender::ResponseCallback callback) { - EXPECT_THAT(trigger_context.GetScriptParameters().ToProto(), - testing::UnorderedElementsAreArray( - base::flat_map<std::string, std::string>( - {{"required", "value"}, {"arg0", "value0"}}))); - EXPECT_TRUE(trigger_context.GetDirectAction()); - - std::move(callback).Run(true, "", ServiceRequestSender::ResponseInfo{}); - }); - - TriggerContext::Options options; - options.is_direct_action = true; - EXPECT_TRUE(controller_->PerformDirectAction( - 0, std::make_unique<TriggerContext>( - /* parameters = */ std::make_unique<ScriptParameters>( - base::flat_map<std::string, std::string>{{"required", "value"}, - {"arg0", "value0"}}), - options))); -} - TEST_F(ControllerTest, NoScripts) { SupportsScriptResponseProto empty; SetNextScriptResponse(empty); @@ -437,28 +358,6 @@ EXPECT_EQ(AutofillAssistantState::STARTING, controller_->GetState()); } -TEST_F(ControllerTest, ClearDirectActionsWhenRunning) { - SupportsScriptResponseProto script_response; - AddRunnableScript(&script_response, "script1"); - AddRunnableScript(&script_response, "script2"); - - ActionsResponseProto runnable_script; - auto* prompt_action = runnable_script.add_actions()->mutable_prompt(); - prompt_action->add_choices()->mutable_chip()->set_text("continue"); - - SetupActionsForScript("script1", runnable_script); - SetNextScriptResponse(script_response); - - Track(); - // We initially have 2 direct action scripts available. - ASSERT_THAT(controller_->GetDirectActionScripts(), SizeIs(2)); - // We execute one of them. - EXPECT_TRUE( - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>())); - // There are no direct actions available once the script is running. - EXPECT_THAT(controller_->GetDirectActionScripts(), SizeIs(0)); -} - TEST_F(ControllerTest, ScriptStartMessage) { SupportsScriptResponseProto script_response; auto* script = AddRunnableScript(&script_response, "script"); @@ -468,11 +367,8 @@ ActionsResponseProto script_actions; SetupActionsForScript("script", script_actions); - Start("http://a.example.com/path"); - EXPECT_CALL(mock_observer_, OnExecuteScript("Starting Script...")); - EXPECT_TRUE( - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>())); + Start("http://a.example.com/path"); } TEST_F(ControllerTest, UpdateClientSettings) { @@ -554,15 +450,10 @@ .WillOnce(RunOnceCallback<5>(net::HTTP_OK, actions_response_str, ServiceRequestSender::ResponseInfo{})); - Start(); - ASSERT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - // Non-gracefuls shutdowns don't call |OnStop|, we just shut down directly. EXPECT_CALL(mock_observer_, OnStop()).Times(0); - testing::InSequence seq; EXPECT_CALL(mock_client_, Shutdown(Metrics::DropOutReason::SCRIPT_SHUTDOWN)); - EXPECT_TRUE( - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>())); + Start(); } TEST_F(ControllerTest, ShutdownGracefully) { @@ -578,15 +469,10 @@ EXPECT_CALL(*mock_service_, GetActions(StrEq("stop"), _, _, _, _, _)) .WillOnce(RunOnceCallback<5>(net::HTTP_OK, actions_response_str, ServiceRequestSender::ResponseInfo{})); - - Start(); - ASSERT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); EXPECT_CALL(mock_observer_, OnStop()); - EXPECT_CALL(mock_client_, RecordDropOut(Metrics::DropOutReason::SCRIPT_SHUTDOWN)); - EXPECT_TRUE( - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>())); + Start(); } TEST_F(ControllerTest, CloseCustomTab) { @@ -602,15 +488,11 @@ .WillOnce(RunOnceCallback<5>(net::HTTP_OK, actions_response_str, ServiceRequestSender::ResponseInfo{})); - Start(); - ASSERT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); EXPECT_CALL(mock_observer_, CloseCustomTab()); - testing::InSequence seq; EXPECT_CALL(mock_client_, Shutdown(Metrics::DropOutReason::CUSTOM_TAB_CLOSED)); - EXPECT_TRUE( - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>())); + Start(); } TEST_F(ControllerTest, RefreshScriptWhenDomainChanges) { @@ -636,10 +518,11 @@ TEST_F(ControllerTest, Autostart) { SupportsScriptResponseProto script_response; - AddRunnableScript(&script_response, "runnable"); - AddRunnableScript(&script_response, "autostart") + AddRunnableScript(&script_response, "runnable") ->mutable_presentation() - ->set_autostart(true); + ->set_autostart(false); + AddRunnableScript(&script_response, "autostart"); + SetNextScriptResponse(script_response); ActionsResponseProto autostart_script; @@ -660,10 +543,10 @@ TEST_F(ControllerTest, AutostartWithoutKeyboardSuppression) { SupportsScriptResponseProto script_response; - AddRunnableScript(&script_response, "runnable"); - AddRunnableScript(&script_response, "autostart") + AddRunnableScript(&script_response, "runnable") ->mutable_presentation() - ->set_autostart(true); + ->set_autostart(false); + AddRunnableScript(&script_response, "autostart"); SetNextScriptResponse(script_response); ActionsResponseProto autostart_script; @@ -721,34 +604,6 @@ SimulateWebContentsFocused(); // must call AttachUI } -TEST_F(ControllerTest, KeepCheckingForElement) { - SupportsScriptResponseProto script_response; - *AddRunnableScript(&script_response, "no_match_yet") - ->mutable_presentation() - ->mutable_precondition() - ->mutable_element_condition() - ->mutable_match() = ToSelectorProto("#element"); - SetNextScriptResponse(script_response); - - Track(); - // No scripts yet; the element doesn't exit. - EXPECT_THAT(controller_->GetDirectActionScripts(), SizeIs(0)); - - for (int i = 0; i < 3; i++) { - task_environment()->FastForwardBy(base::Seconds(1)); - EXPECT_THAT(controller_->GetDirectActionScripts(), SizeIs(0)); - } - - EXPECT_CALL(*mock_web_controller_, FindElement(_, _, _)) - .WillRepeatedly(WithArgs<2>([](auto&& callback) { - std::move(callback).Run(OkClientStatus(), - std::make_unique<ElementFinderResult>()); - })); - task_environment()->FastForwardBy(base::Seconds(1)); - - EXPECT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); -} - TEST_F(ControllerTest, ScriptTimeoutError) { // Wait for #element to show up for will_never_match. After 25s, execute the // script on_timeout_error. @@ -1004,12 +859,6 @@ ServiceRequestSender::ResponseInfo{}))); Start("http://a.example.com/path"); - EXPECT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - - // Start script, which waits for some navigation event to happen after the - // expect_navigation action has run.. - EXPECT_TRUE( - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>())); // No navigation event happened within the action timeout and the script ends. EXPECT_THAT(processed_actions_capture, SizeIs(0)); @@ -1040,12 +889,6 @@ ServiceRequestSender::ResponseInfo{}))); Start("http://a.example.com/path"); - EXPECT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - - // Start script, which waits for some navigation event to happen after the - // expect_navigation action has run.. - EXPECT_TRUE( - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>())); // Navigation starts, but does not end, within the timeout. EXPECT_THAT(processed_actions_capture, SizeIs(0)); @@ -1080,7 +923,6 @@ .WillOnce(SaveArg<0>(&script_store_config)); Start("http://a.example.com/path"); - controller_->GetDirectActionScripts(); EXPECT_THAT(script_store_config.bundle_path(), Eq("bundle/path")); EXPECT_THAT(script_store_config.bundle_version(), Eq(12)); @@ -1098,414 +940,6 @@ EXPECT_THAT(controller_->GetCurrentURL().spec(), navigate_url); } -TEST_F(ControllerTest, Track) { - SupportsScriptResponseProto script_response; - AddRunnableScript(&script_response, "runnable"); - std::string response_str; - script_response.SerializeToString(&response_str); - EXPECT_CALL(*mock_service_, - GetScriptsForUrl(GURL("http://example.com/"), _, _)) - .WillOnce(RunOnceCallback<2>(net::HTTP_OK, response_str, - ServiceRequestSender::ResponseInfo{})); - - EXPECT_CALL(*mock_service_, - GetScriptsForUrl(GURL("http://b.example.com/"), _, _)) - .WillOnce(RunOnceCallback<2>(net::HTTP_OK, "", - ServiceRequestSender::ResponseInfo{})); - - // Start tracking at example.com, with one script matching - SetLastCommittedUrl(GURL("http://example.com/")); - - controller_->Track(std::make_unique<TriggerContext>(), base::DoNothing()); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - ASSERT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - - // Execute the script, which requires showing the UI, then go back to tracking - // mode - EXPECT_CALL(mock_client_, AttachUI()); - EXPECT_TRUE( - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>())); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - EXPECT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - - // Move to a domain for which there are no scripts. This causes the controller - // to stop. - SimulateNavigateToUrl(GURL("http://b.example.com/")); - EXPECT_EQ(AutofillAssistantState::STOPPED, controller_->GetState()); - - // Check the full history of state transitions. - EXPECT_THAT(states_, ElementsAre(AutofillAssistantState::TRACKING, - AutofillAssistantState::RUNNING, - AutofillAssistantState::TRACKING, - AutofillAssistantState::STOPPED)); - EXPECT_THAT(keyboard_states_, ElementsAre(false, true, false, false)); - - // Shutdown once we've moved from domain b.example.com, for which we know - // there are no scripts, to c.example.com, which we don't want to check. - EXPECT_CALL(mock_client_, Shutdown(Metrics::DropOutReason::NO_SCRIPTS)); - SimulateNavigateToUrl(GURL("http://c.example.com/")); -} - -TEST_F(ControllerTest, TrackScriptWithNoUI) { - // The UI is never shown during this test. - EXPECT_CALL(mock_client_, AttachUI()).Times(0); - - SupportsScriptResponseProto script_response; - auto* script = AddRunnableScript(&script_response, "runnable"); - script->mutable_presentation()->set_needs_ui(false); - SetupScripts(script_response); - - // Script does nothing - ActionsResponseProto runnable_script; - auto* hidden_tell = runnable_script.add_actions()->mutable_tell(); - hidden_tell->set_message("optional message"); - hidden_tell->set_needs_ui(false); - runnable_script.add_actions()->mutable_stop(); - SetupActionsForScript("runnable", runnable_script); - - // Start tracking at example.com, with one script matching - SetLastCommittedUrl(GURL("http://example.com/")); - - controller_->Track(std::make_unique<TriggerContext>(), base::DoNothing()); - ASSERT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - - EXPECT_TRUE( - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>())); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - - // Check the full history of state transitions. - EXPECT_THAT(states_, ElementsAre(AutofillAssistantState::TRACKING, - AutofillAssistantState::RUNNING, - AutofillAssistantState::TRACKING)); -} - -TEST_F(ControllerTest, TrackScriptShowUIOnTell) { - SupportsScriptResponseProto script_response; - auto* script = AddRunnableScript(&script_response, "runnable"); - script->mutable_presentation()->set_needs_ui(true); - SetupScripts(script_response); - - ActionsResponseProto runnable_script; - runnable_script.add_actions()->mutable_tell()->set_message("error"); - runnable_script.add_actions()->mutable_stop(); - SetupActionsForScript("runnable", runnable_script); - - // Start tracking at example.com, with one script matching - SetLastCommittedUrl(GURL("http://example.com/")); - - controller_->Track(std::make_unique<TriggerContext>(), base::DoNothing()); - ASSERT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - - EXPECT_FALSE(controller_->NeedsUI()); - EXPECT_CALL(mock_client_, AttachUI()); - EXPECT_TRUE( - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>())); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - - // The last tell message should still be shown to the user. - EXPECT_TRUE(controller_->NeedsUI()); - - // Check the full history of state transitions. - EXPECT_THAT(states_, ElementsAre(AutofillAssistantState::TRACKING, - AutofillAssistantState::RUNNING, - AutofillAssistantState::TRACKING)); -} - -TEST_F(ControllerTest, RunDirectActionWhileTrackingWithUi) { - SupportsScriptResponseProto script_response; - auto* script_needs_ui = AddRunnableScript(&script_response, "needs_ui"); - script_needs_ui->mutable_presentation()->set_needs_ui(true); - - auto* script_no_ui = AddRunnableScript(&script_response, "no_ui"); - script_no_ui->mutable_presentation()->set_needs_ui(false); - SetupScripts(script_response); - - ActionsResponseProto needs_ui_script; - needs_ui_script.add_actions()->mutable_tell()->set_message("error"); - needs_ui_script.add_actions()->mutable_stop(); - SetupActionsForScript("needs_ui", needs_ui_script); - - ActionsResponseProto no_ui_script; - no_ui_script.add_actions()->mutable_stop(); - SetupActionsForScript("no_ui", no_ui_script); - - // Start tracking at example.com, with one script matching - SetLastCommittedUrl(GURL("http://example.com/")); - - controller_->Track(std::make_unique<TriggerContext>(), base::DoNothing()); - ASSERT_THAT(controller_->GetDirectActionScripts(), SizeIs(2)); - EXPECT_EQ(controller_->GetDirectActionScripts()[0].path, "needs_ui"); - - EXPECT_FALSE(controller_->NeedsUI()); - EXPECT_CALL(mock_client_, AttachUI()); - EXPECT_TRUE( - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>())); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - - // The last tell message should still be shown to the user. - EXPECT_TRUE(controller_->NeedsUI()); - - EXPECT_CALL(mock_client_, DestroyUI()); - EXPECT_TRUE( - controller_->PerformDirectAction(1, std::make_unique<TriggerContext>())); - - // UI should have been cleared - EXPECT_FALSE(controller_->NeedsUI()); - - // Check the full history of state transitions. - EXPECT_THAT(states_, ElementsAre(AutofillAssistantState::TRACKING, - AutofillAssistantState::RUNNING, - AutofillAssistantState::TRACKING, - AutofillAssistantState::RUNNING, - AutofillAssistantState::TRACKING)); -} - -TEST_F(ControllerTest, TrackScriptClosesUI) { - SupportsScriptResponseProto script_response; - auto* script = AddRunnableScript(&script_response, "runnable"); - script->mutable_presentation()->set_needs_ui(false); - SetupScripts(script_response); - - ActionsResponseProto runnable_script; - runnable_script.add_actions()->mutable_tell()->set_message("hi"); - runnable_script.add_actions() - ->mutable_wait_for_dom() - ->mutable_wait_condition(); - runnable_script.add_actions()->mutable_stop(); - - SetupActionsForScript("runnable", runnable_script); - - // Start tracking at example.com, with one script matching - SetLastCommittedUrl(GURL("http://example.com/")); - - controller_->Track(std::make_unique<TriggerContext>(), base::DoNothing()); - ASSERT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - - EXPECT_FALSE(controller_->NeedsUI()); - EXPECT_CALL(mock_client_, AttachUI()); - EXPECT_TRUE( - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>())); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - - // The tell action wasn't the last one before close, so UI should close when - // the script is finished. - EXPECT_FALSE(controller_->NeedsUI()); - - // Check the full history of state transitions. - EXPECT_THAT(states_, ElementsAre(AutofillAssistantState::TRACKING, - AutofillAssistantState::RUNNING, - AutofillAssistantState::TRACKING)); -} - -TEST_F(ControllerTest, TrackScriptShowUIOnError) { - SupportsScriptResponseProto script_response; - auto* script = AddRunnableScript(&script_response, "runnable"); - script->mutable_presentation()->set_needs_ui(false); - SetupScripts(script_response); - - // Running the script fails, due to a backend issue. The error message should - // be shown. - EXPECT_CALL(*mock_service_, GetActions) - .WillOnce(RunOnceCallback<5>(net::HTTP_UNAUTHORIZED, "", - ServiceRequestSender::ResponseInfo{})); - - // Start tracking at example.com, with one script matching - SetLastCommittedUrl(GURL("http://example.com/")); - - controller_->Track(std::make_unique<TriggerContext>(), base::DoNothing()); - ASSERT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - - EXPECT_FALSE(controller_->NeedsUI()); - EXPECT_CALL(mock_client_, AttachUI()); - EXPECT_TRUE( - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>())); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - - // UI must remain visible for the user to see the error message. - EXPECT_TRUE(controller_->NeedsUI()); - - // Check the full history of state transitions. - EXPECT_THAT(states_, ElementsAre(AutofillAssistantState::TRACKING, - AutofillAssistantState::RUNNING, - AutofillAssistantState::STOPPED, - AutofillAssistantState::TRACKING)); -} - -TEST_F(ControllerTest, TrackContinuesAfterScriptError) { - SupportsScriptResponseProto script_response; - AddRunnableScript(&script_response, "runnable"); - std::string response_str; - script_response.SerializeToString(&response_str); - EXPECT_CALL(*mock_service_, - GetScriptsForUrl(GURL("http://example.com/"), _, _)) - .WillOnce(RunOnceCallback<2>(net::HTTP_OK, response_str, - ServiceRequestSender::ResponseInfo{})); - - // Start tracking at example.com, with one script matching - SetLastCommittedUrl(GURL("http://example.com/")); - - controller_->Track(std::make_unique<TriggerContext>(), base::DoNothing()); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - ASSERT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - - EXPECT_CALL(*mock_service_, GetActions(StrEq("runnable"), _, _, _, _, _)) - .WillOnce(RunOnceCallback<5>(net::HTTP_UNAUTHORIZED, "", - ServiceRequestSender::ResponseInfo{})); - - // When the script fails, the controller transitions to STOPPED state, then - // right away back to TRACKING state. - EXPECT_TRUE( - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>())); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - EXPECT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - - // Check the full history of state transitions. - EXPECT_THAT(states_, ElementsAre(AutofillAssistantState::TRACKING, - AutofillAssistantState::RUNNING, - AutofillAssistantState::STOPPED, - AutofillAssistantState::TRACKING)); -} - -TEST_F(ControllerTest, TrackReportsFirstSetOfScripts) { - ServiceRequestSender::ResponseCallback get_scripts_callback; - EXPECT_CALL(*mock_service_, GetScriptsForUrl(_, _, _)) - .WillOnce([&get_scripts_callback]( - const GURL& url, const TriggerContext& trigger_context, - ServiceRequestSender::ResponseCallback callback) { - get_scripts_callback = std::move(callback); - }); - - SetLastCommittedUrl(GURL("http://example.com/")); - bool first_check_done = false; - controller_->Track(std::make_unique<TriggerContext>(), - base::BindOnce( - [](Controller* controller, bool* is_done) { - // User actions must have been set when this is - // called - EXPECT_THAT(controller->GetDirectActionScripts(), - SizeIs(1)); - *is_done = true; - }, - base::Unretained(controller_.get()), - base::Unretained(&first_check_done))); - EXPECT_FALSE(first_check_done); - EXPECT_FALSE(controller_->HasRunFirstCheck()); - - ASSERT_TRUE(get_scripts_callback); - - SupportsScriptResponseProto script_response; - AddRunnableScript(&script_response, "runnable"); - std::string response_str; - script_response.SerializeToString(&response_str); - std::move(get_scripts_callback) - .Run(net::HTTP_OK, response_str, ServiceRequestSender::ResponseInfo{}); - - EXPECT_TRUE(first_check_done); - EXPECT_TRUE(controller_->HasRunFirstCheck()); -} - -TEST_F(ControllerTest, TrackReportsNoScripts) { - SetLastCommittedUrl(GURL("http://example.com/")); - base::MockCallback<base::OnceCallback<void()>> callback; - - EXPECT_CALL(callback, Run()); - controller_->Track(std::make_unique<TriggerContext>(), callback.Get()); - EXPECT_EQ(AutofillAssistantState::STOPPED, controller_->GetState()); -} - -TEST_F(ControllerTest, TrackReportsNoScriptsForNow) { - SupportsScriptResponseProto script_response; - *AddRunnableScript(&script_response, "no_match_yet") - ->mutable_presentation() - ->mutable_precondition() - ->mutable_element_condition() - ->mutable_match() = ToSelectorProto("#element"); - SetNextScriptResponse(script_response); - - SetLastCommittedUrl(GURL("http://example.com/")); - base::MockCallback<base::OnceCallback<void()>> callback; - - EXPECT_CALL(callback, Run()); - controller_->Track(std::make_unique<TriggerContext>(), callback.Get()); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); -} - -TEST_F(ControllerTest, TrackReportsNoScriptsForThePage) { - // Having scripts for the domain but not for the current page is fatal in - // STARTING or PROMPT mode, but not in TRACKING mode. - SupportsScriptResponseProto script_response; - AddRunnableScript(&script_response, "no_match_yet") - ->mutable_presentation() - ->mutable_precondition() - ->add_path_pattern("/otherpage.html"); - SetNextScriptResponse(script_response); - - SetLastCommittedUrl(GURL("http://example.com/")); - base::MockCallback<base::OnceCallback<void()>> callback; - - EXPECT_CALL(callback, Run()); - controller_->Track(std::make_unique<TriggerContext>(), callback.Get()); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); -} - -TEST_F(ControllerTest, TrackReportsAlreadyDone) { - SupportsScriptResponseProto script_response; - AddRunnableScript(&script_response, "runnable"); - SetNextScriptResponse(script_response); - - SetLastCommittedUrl(GURL("http://example.com/")); - controller_->Track(std::make_unique<TriggerContext>(), base::DoNothing()); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - - base::MockCallback<base::OnceCallback<void()>> callback; - EXPECT_CALL(callback, Run()); - controller_->Track(std::make_unique<TriggerContext>(), callback.Get()); -} - -TEST_F(ControllerTest, TrackThenAutostart) { - SupportsScriptResponseProto script_response; - AddRunnableScript(&script_response, "runnable"); - AddRunnableScript(&script_response, "autostart", /*direct_action=*/false) - ->mutable_presentation() - ->set_autostart(true); - SetNextScriptResponse(script_response); - - SetLastCommittedUrl(GURL("http://example.com/")); - controller_->Track(std::make_unique<TriggerContext>(), base::DoNothing()); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - EXPECT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - - ActionsResponseProto autostart_script; - autostart_script.add_actions()->mutable_tell()->set_message("autostart"); - autostart_script.add_actions()->mutable_stop(); - SetupActionsForScript("autostart", autostart_script); - - ActionsResponseProto runnable_script; - runnable_script.add_actions()->mutable_tell()->set_message("runnable"); - runnable_script.add_actions()->mutable_stop(); - SetupActionsForScript("runnable", runnable_script); - - EXPECT_CALL(mock_client_, AttachUI()); - Start("http://example.com/"); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - EXPECT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - - // Run "runnable", which then calls stop and ends. The controller should then - // go back to TRACKING mode. - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>()); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - - // Full history of state transitions. - EXPECT_THAT(states_, ElementsAre(AutofillAssistantState::TRACKING, - AutofillAssistantState::STARTING, - AutofillAssistantState::RUNNING, - AutofillAssistantState::TRACKING, - AutofillAssistantState::RUNNING, - AutofillAssistantState::TRACKING)); - EXPECT_THAT(keyboard_states_, - ElementsAre(false, true, true, false, true, false)); -} - TEST_F(ControllerTest, BrowseStateStopsOnDifferentDomain) { SupportsScriptResponseProto script_response; AddRunnableScript(&script_response, "runnable") @@ -1709,64 +1143,6 @@ ->Commit(); } -TEST_F(ControllerTest, UnexpectedNavigationDuringPromptAction_Tracking) { - SupportsScriptResponseProto script_response; - AddRunnableScript(&script_response, "runnable"); - SetNextScriptResponse(script_response); - - ActionsResponseProto runnable_script; - runnable_script.add_actions() - ->mutable_prompt() - ->add_choices() - ->mutable_chip() - ->set_text("continue"); - runnable_script.add_actions() - ->mutable_configure_bottom_sheet() - ->set_viewport_resizing( - ConfigureBottomSheetProto::RESIZE_LAYOUT_VIEWPORT); - SetupActionsForScript("runnable", runnable_script); - - SetLastCommittedUrl(GURL("http://example.com/")); - controller_->Track(std::make_unique<TriggerContext>(), base::DoNothing()); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - ASSERT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - EXPECT_EQ(controller_->GetDirectActionScripts()[0].direct_action.names.count( - "runnable"), - 1u); - - // Start the script, which should show a prompt with the continue chip. - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>()); - EXPECT_EQ(AutofillAssistantState::PROMPT, controller_->GetState()); - ASSERT_THAT(*fake_script_executor_ui_delegate_.GetUserActions(), SizeIs(1)); - EXPECT_EQ( - fake_script_executor_ui_delegate_.GetUserActions()->at(0).chip().text, - "continue"); - - // Browser (not document) initiated navigation while in prompt mode (such as - // go back): The controller stops the scripts, shows an error, then goes back - // to tracking mode. - // - // The ConfigureBottomSheet action which follows the prompt should never be - // executed. - EXPECT_CALL(mock_observer_, OnViewportModeChanged(_)).Times(0); - - content::NavigationSimulator::NavigateAndCommitFromBrowser( - web_contents(), GURL("http://example.com/otherpage")); - - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - ASSERT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - EXPECT_EQ(controller_->GetDirectActionScripts()[0].direct_action.names.count( - "runnable"), - 1u); - - // Full history of state transitions. - EXPECT_THAT(states_, ElementsAre(AutofillAssistantState::TRACKING, - AutofillAssistantState::RUNNING, - AutofillAssistantState::PROMPT, - AutofillAssistantState::STOPPED, - AutofillAssistantState::TRACKING)); -} - TEST_F(ControllerTest, UnexpectedNavigationDuringPromptAction) { SupportsScriptResponseProto script_response; AddRunnableScript(&script_response, "autostart") @@ -1920,41 +1296,6 @@ AutofillAssistantState::STOPPED)); } -TEST_F(ControllerTest, NavigationWhileTrackingWithUi) { - SupportsScriptResponseProto script_response; - auto* script = AddRunnableScript(&script_response, "runnable"); - script->mutable_presentation()->set_needs_ui(true); - SetupScripts(script_response); - - ActionsResponseProto runnable_script; - runnable_script.add_actions()->mutable_tell()->set_message("error"); - runnable_script.add_actions()->mutable_stop(); - SetupActionsForScript("runnable", runnable_script); - - // Start tracking at example.com, with one script matching - SetLastCommittedUrl(GURL("http://example.com/")); - - controller_->Track(std::make_unique<TriggerContext>(), base::DoNothing()); - ASSERT_THAT(controller_->GetDirectActionScripts(), SizeIs(1)); - - EXPECT_TRUE( - controller_->PerformDirectAction(0, std::make_unique<TriggerContext>())); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - EXPECT_TRUE(controller_->NeedsUI()); - - // Browser navigation will destroy the UI. - EXPECT_CALL(mock_client_, DestroyUISoon()); - content::NavigationSimulator::NavigateAndCommitFromBrowser( - web_contents(), GURL("http://a.example.com/page")); - EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState()); - EXPECT_FALSE(controller_->NeedsUI()); - - // Full history of state transitions. - EXPECT_THAT(states_, ElementsAre(AutofillAssistantState::TRACKING, - AutofillAssistantState::RUNNING, - AutofillAssistantState::TRACKING)); -} - TEST_F(ControllerTest, NavigationToGooglePropertyShutsDownDestroyingUI) { SupportsScriptResponseProto script_response; AddRunnableScript(&script_response, "autostart") @@ -2638,7 +1979,11 @@ script_response.mutable_semantic_selector_policy() ->mutable_bag_of_words() ->add_data_point_map(); - AddRunnableScript(&script_response, "runnable"); + *AddRunnableScript(&script_response, "runnable") + ->mutable_presentation() + ->mutable_precondition() + ->mutable_element_condition() + ->mutable_match() = ToSelectorProto("#element"); SetNextScriptResponse(script_response); EXPECT_CALL(mock_client_, AttachUI());
diff --git a/components/autofill_assistant/browser/empty_controller_observer.h b/components/autofill_assistant/browser/empty_controller_observer.h index 5ebe62fd..4f8fcda5 100644 --- a/components/autofill_assistant/browser/empty_controller_observer.h +++ b/components/autofill_assistant/browser/empty_controller_observer.h
@@ -34,7 +34,6 @@ void OnExecuteScript(const std::string& start_message) override {} void OnStart(const TriggerContext& trigger_context) override {} void OnStop() override {} - void OnResetState() override {} void OnUiShownChanged(bool shown) override {} }; } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/execution_delegate.h b/components/autofill_assistant/browser/execution_delegate.h index 9176fb3..4a6826ce 100644 --- a/components/autofill_assistant/browser/execution_delegate.h +++ b/components/autofill_assistant/browser/execution_delegate.h
@@ -115,9 +115,6 @@ // Remove a previously registered observer. virtual void RemoveObserver(const ControllerObserver* observer) = 0; - // Returns true if the controller is in a state where UI is necessary. - virtual bool NeedsUI() const = 0; - protected: ExecutionDelegate() = default; };
diff --git a/components/autofill_assistant/browser/script_tracker.cc b/components/autofill_assistant/browser/script_tracker.cc index 773b2bb2..3def224 100644 --- a/components/autofill_assistant/browser/script_tracker.cc +++ b/components/autofill_assistant/browser/script_tracker.cc
@@ -89,6 +89,8 @@ GURL url = delegate_->GetCurrentURL(); batch_element_checker_ = std::make_unique<BatchElementChecker>(); for (const std::unique_ptr<Script>& script : available_scripts_) { + // Direct actions are not supported anymore, but might still be served by + // the server. if (script->handle.direct_action.empty() && !script->handle.autostart) continue; @@ -167,24 +169,6 @@ available_scripts_js.Append(script->handle.path); dict.Set("available-scripts", std::move(available_scripts_js)); - base::Value::List runnable_scripts_js; - for (const auto& entry : runnable_scripts_) { - base::Value::Dict script_js; - script_js.Set("path", entry.path); - script_js.Set("autostart", entry.autostart); - - base::Value::Dict direct_action_js; - direct_action_js.Set("names", ToValueList(entry.direct_action.names)); - direct_action_js.Set("required_arguments", - ToValueList(entry.direct_action.required_arguments)); - direct_action_js.Set("optional_arguments", - ToValueList(entry.direct_action.optional_arguments)); - script_js.Set("direct_action", std::move(direct_action_js)); - - runnable_scripts_js.Append(std::move(script_js)); - } - dict.Set("runnable-scripts", std::move(runnable_scripts_js)); - return base::Value(std::move(dict)); }
diff --git a/components/autofill_assistant/browser/state.h b/components/autofill_assistant/browser/state.h index 9c117c7..b2cadf6 100644 --- a/components/autofill_assistant/browser/state.h +++ b/components/autofill_assistant/browser/state.h
@@ -17,32 +17,14 @@ // // INACTIVE -> STARTING -> RUNNING -> PROMPT -> RUNNING -> .. -> STOPPED // -// A typical run, when started from a direct action, goes into tracking mode, -// execute a script, the goes back to tracking mode: -// -// INACTIVE -> TRACKING -> RUNNING -> TRACKING -> ... -> STOPPED -// // See the individual state for possible state transitions. enum class AutofillAssistantState { // Autofill assistant is not doing or showing anything. // // Initial state. - // Next states: STARTING, TRACKING, STOPPED + // Next states: STARTING, STOPPED INACTIVE = 0, - // Autofill assistant is keeping track of script availability. - // - // UI will only be shown if the previous state was RUNNING and if the script - // finished with tell + stop. - // - // In this mode, scripts are not autostarted. User actions might be available. - // - // Note that it is possible to go from TRACKING to STARTING to trigger - // whatever autostartable scripts is defined for a page. - // - // Next states: STARTING, RUNNING, STOPPED - TRACKING, - // Autofill assistant is waiting for an autostart script. // // Status message, progress and details are initialized to useful values. @@ -55,7 +37,7 @@ // Status message, progress and details kept up-to-date by the running // script. // - // Next states: PROMPT, MODAL_DIALOG, TRACKING, STARTING, STOPPED + // Next states: PROMPT, MODAL_DIALOG, STARTING, STOPPED RUNNING, // Autofill assistant is waiting for the user to make a choice. @@ -64,7 +46,7 @@ // empty. A touchable area must be configured. The user might be filling in // the data for a payment request. // - // Next states: RUNNING, TRACKING, STOPPED + // Next states: RUNNING, STOPPED PROMPT, // Autofill assistant is expecting a modal dialog, such as the one asking for @@ -81,7 +63,7 @@ // In that scenario, the status message at the time of transition to STOPPED // is supposed to contain the final message. // - // Next states: TRACKING + // Next states: none. STOPPED, // Autofill assistant is waiting for the user to browse the website until one @@ -96,7 +78,7 @@ // are not a reason to shutdown autofill assistant. Navigating away from the // original domain will however shut down autofill assistant. // - // Next states: RUNNING, TRACKING, STOPPED + // Next states: RUNNING, STOPPED BROWSE, }; @@ -112,9 +94,6 @@ case AutofillAssistantState::INACTIVE: out << "INACTIVE"; break; - case AutofillAssistantState::TRACKING: - out << "TRACKING"; - break; case AutofillAssistantState::STARTING: out << "STARTING"; break;
diff --git a/components/autofill_assistant/browser/ui_controller.cc b/components/autofill_assistant/browser/ui_controller.cc index 51d3ec6..58ecd81 100644 --- a/components/autofill_assistant/browser/ui_controller.cc +++ b/components/autofill_assistant/browser/ui_controller.cc
@@ -1228,23 +1228,6 @@ SetForm(nullptr, base::DoNothing(), base::DoNothing()); } -void UiController::OnResetState() { - // TODO(b/204963552): this list is incomplete. It would be much better if, - // instead of selectively clearing fields, we'd solve this in a more holistic - // way. - bubble_message_.clear(); - tts_message_.clear(); - status_message_.clear(); - details_.clear(); - info_box_.reset(); - progress_visible_ = true; - progress_bar_error_state_ = false; - progress_active_step_ = 0; - step_progress_bar_configuration_ = - ShowProgressBarProto::StepProgressBarConfiguration(); - peek_mode_ = ConfigureBottomSheetProto::HANDLE; -} - void UiController::OnUiShownChanged(bool shown) { // Stop any ongoing TTS if UI is hidden. if (!shown && tts_button_state_ == TtsButtonState::PLAYING) {
diff --git a/components/autofill_assistant/browser/ui_controller.h b/components/autofill_assistant/browser/ui_controller.h index 23efd5b2..10c3e2f 100644 --- a/components/autofill_assistant/browser/ui_controller.h +++ b/components/autofill_assistant/browser/ui_controller.h
@@ -210,7 +210,6 @@ void OnExecuteScript(const std::string& start_message) override; void OnStart(const TriggerContext& trigger_context) override; void OnStop() override; - void OnResetState() override; void OnUiShownChanged(bool shown) override; // Overrides AutofillAssistantTtsController::TtsEventDelegate
diff --git a/components/browser_ui/site_settings/android/BUILD.gn b/components/browser_ui/site_settings/android/BUILD.gn index e7f5cfc..9bb808b 100644 --- a/components/browser_ui/site_settings/android/BUILD.gn +++ b/components/browser_ui/site_settings/android/BUILD.gn
@@ -147,6 +147,7 @@ sources = [ "junit/src/org/chromium/components/browser_ui/site_settings/AddExceptionPreferenceUnitTest.java", "junit/src/org/chromium/components/browser_ui/site_settings/DesktopSiteMetricsUnitTest.java", + "junit/src/org/chromium/components/browser_ui/site_settings/SiteDataCleanerUnitTest.java", ] deps = [ @@ -155,6 +156,7 @@ "//base:base_java_test_support", "//base:base_junit_test_support", "//components/content_settings/android:content_settings_enums_java", + "//content/public/android:content_java", "//third_party/junit", "//third_party/mockito:mockito_java", ]
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteDataCleaner.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteDataCleaner.java index 90f7b94..8802314 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteDataCleaner.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteDataCleaner.java
@@ -7,8 +7,11 @@ import org.chromium.components.content_settings.ContentSettingValues; import org.chromium.content_public.browser.BrowserContextHandle; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + /** - * Encapsulates clearing the data of {@link Website}s. + * Encapsulates clearing the data of {@link Website}s and {@link WebsiteGroup}s. * Requires native library to be initialized. */ public class SiteDataCleaner { @@ -26,6 +29,25 @@ } /** + * Clears the data for each of the sites in a given group. + * @param finishCallback is called when the entire operation is finished. + */ + public void clearData( + BrowserContextHandle contextHandle, WebsiteGroup group, Runnable finishCallback) { + final AtomicInteger callbacksReceived = new AtomicInteger(0); + List<Website> sites = group.getWebsites(); + final int websitesCount = sites.size(); + final Runnable singleWebsiteCallback = () -> { + if (callbacksReceived.incrementAndGet() >= websitesCount) { + finishCallback.run(); + } + }; + for (Website site : sites) { + clearData(contextHandle, site, singleWebsiteCallback); + } + } + + /** * Resets the permissions of the specified site. */ public void resetPermissions(BrowserContextHandle browserContextHandle, Website site) { @@ -43,4 +65,13 @@ info.revoke(browserContextHandle); } } + + /** + * Resets the permissions for each of the sites in a given group. + */ + public void resetPermissions(BrowserContextHandle browserContextHandle, WebsiteGroup group) { + for (Website site : group.getWebsites()) { + resetPermissions(browserContextHandle, site); + } + } }
diff --git a/components/browser_ui/site_settings/android/junit/src/org/chromium/components/browser_ui/site_settings/SiteDataCleanerUnitTest.java b/components/browser_ui/site_settings/android/junit/src/org/chromium/components/browser_ui/site_settings/SiteDataCleanerUnitTest.java new file mode 100644 index 0000000..f19d98f6 --- /dev/null +++ b/components/browser_ui/site_settings/android/junit/src/org/chromium/components/browser_ui/site_settings/SiteDataCleanerUnitTest.java
@@ -0,0 +1,72 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.browser_ui.site_settings; + +import static org.mockito.Mockito.verify; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.JniMocker; +import org.chromium.content_public.browser.BrowserContextHandle; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Unit tests for {@link SiteDataCleaner}. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class SiteDataCleanerUnitTest { + @Rule + public JniMocker mJniMocker = new JniMocker(); + + @Mock + private WebsitePreferenceBridge.Natives mBridgeMock; + + @Mock + private BrowserContextHandle mContextHandle; + + private SiteDataCleaner mSiteDataCleaner; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mJniMocker.mock(WebsitePreferenceBridgeJni.TEST_HOOKS, mBridgeMock); + mSiteDataCleaner = new SiteDataCleaner(); + } + + @Test + public void testClearData() { + Website origin1 = new Website(WebsiteAddress.create("https://google.com"), null); + Website origin2 = new Website(WebsiteAddress.create("mail.google.com"), null); + Website origin3 = new Website(WebsiteAddress.create("https://docs.google.com"), null); + WebsiteGroup group = new WebsiteGroup( + "google.com", new ArrayList<>(Arrays.asList(origin1, origin2, origin3))); + final AtomicInteger callbacksReceived = new AtomicInteger(0); + final Runnable callback = () -> { + callbacksReceived.incrementAndGet(); + }; + mSiteDataCleaner.clearData(mContextHandle, group, callback); + // Check that the callback was invoked only once. + Assert.assertEquals(1, callbacksReceived.get()); + // Verify that the bridge is called for each of the websites. + for (Website website : group.getWebsites()) { + verify(mBridgeMock).clearCookieData(mContextHandle, website.getAddress().getOrigin()); + verify(mBridgeMock).clearBannerData(mContextHandle, website.getAddress().getOrigin()); + verify(mBridgeMock) + .clearMediaLicenses(mContextHandle, website.getAddress().getOrigin()); + } + } +}
diff --git a/components/gcm_driver/resources/gcm_internals.js b/components/gcm_driver/resources/gcm_internals.js index f42e5c8..2ff874c09 100644 --- a/components/gcm_driver/resources/gcm_internals.js +++ b/components/gcm_driver/resources/gcm_internals.js
@@ -7,7 +7,7 @@ // </if> import './strings.m.js'; -import {addWebUIListener} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener} from 'chrome://resources/js/cr.js'; import {$} from 'chrome://resources/js/util.js'; let isRecording = false; @@ -142,7 +142,7 @@ } function initialize() { - addWebUIListener('set-gcm-internals-info', setGcmInternalsInfo); + addWebUiListener('set-gcm-internals-info', setGcmInternalsInfo); $('recording').disabled = true; $('refresh').onclick = refreshAll; $('recording').onclick = setRecording;
diff --git a/components/net_log/resources/net_export.js b/components/net_log/resources/net_export.js index 475ec07..671ed4e 100644 --- a/components/net_log/resources/net_export.js +++ b/components/net_log/resources/net_export.js
@@ -7,7 +7,7 @@ import 'chrome://resources/js/ios/web_ui.js'; // </if> -import {addWebUIListener} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener} from 'chrome://resources/js/cr.js'; import {$} from 'chrome://resources/js/util.js'; /**
diff --git a/components/ntp_tiles/webui/resources/ntp_tiles_internals.js b/components/ntp_tiles/webui/resources/ntp_tiles_internals.js index 74e4d4e..2735f1b 100644 --- a/components/ntp_tiles/webui/resources/ntp_tiles_internals.js +++ b/components/ntp_tiles/webui/resources/ntp_tiles_internals.js
@@ -7,7 +7,7 @@ // </if> import 'chrome://resources/js/jstemplate_compiled.js'; -import {addWebUIListener} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener} from 'chrome://resources/js/cr.js'; import {$} from 'chrome://resources/js/util.js'; const initialize = function() { @@ -32,10 +32,10 @@ } }); - addWebUIListener('receive-source-info', state => { + addWebUiListener('receive-source-info', state => { jstProcess(new JsEvalContext(state), $('sources')); }); - addWebUIListener('receive-sites', sites => { + addWebUiListener('receive-sites', sites => { jstProcess(new JsEvalContext(sites), $('sites')); }); chrome.send('registerForEvents');
diff --git a/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.cc b/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.cc index 5a50e48..ab7ce778 100644 --- a/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.cc +++ b/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.cc
@@ -144,6 +144,11 @@ return page_input_timing_; } +const absl::optional<mojom::SubresourceLoadMetrics>& +FakePageLoadMetricsObserverDelegate::GetSubresourceLoadMetrics() const { + return subresource_load_metrics_; +} + const PageRenderData& FakePageLoadMetricsObserverDelegate::GetMainFrameRenderData() const { return main_frame_render_data_;
diff --git a/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.h b/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.h index a5c5bee..bee300c 100644 --- a/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.h +++ b/components/page_load_metrics/browser/fake_page_load_metrics_observer_delegate.h
@@ -63,6 +63,8 @@ const NormalizedResponsivenessMetrics& GetNormalizedResponsivenessMetrics() const override; const mojom::InputTiming& GetPageInputTiming() const override; + const absl::optional<mojom::SubresourceLoadMetrics>& + GetSubresourceLoadMetrics() const override; const PageRenderData& GetMainFrameRenderData() const override; const ui::ScopedVisibilityTracker& GetVisibilityTracker() const override; const ResourceTracker& GetResourceTracker() const override; @@ -94,6 +96,7 @@ NormalizedCLSData normalized_cls_data_; NormalizedResponsivenessMetrics normalized_responsiveness_metrics_; mojom::InputTiming page_input_timing_; + absl::optional<mojom::SubresourceLoadMetrics> subresource_load_metrics_; PageRenderData main_frame_render_data_; ui::ScopedVisibilityTracker visibility_tracker_; ResourceTracker resource_tracker_;
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer.cc b/components/page_load_metrics/browser/metrics_web_contents_observer.cc index b9192f6c..228a48f 100644 --- a/components/page_load_metrics/browser/metrics_web_contents_observer.cc +++ b/components/page_load_metrics/browser/metrics_web_contents_observer.cc
@@ -1047,6 +1047,7 @@ mojom::FrameRenderDataUpdatePtr render_data, mojom::CpuTimingPtr cpu_timing, mojom::InputTimingPtr input_timing_delta, + mojom::SubresourceLoadMetricsPtr subresource_load_metrics, uint32_t soft_navigation_count) { // Replacing this call by GetPageLoadTracker breaks some tests. // @@ -1073,11 +1074,11 @@ } if (tracker) { - tracker->UpdateMetrics(render_frame_host, std::move(timing), - std::move(metadata), std::move(new_features), - resources, std::move(render_data), - std::move(cpu_timing), std::move(input_timing_delta), - soft_navigation_count); + tracker->UpdateMetrics( + render_frame_host, std::move(timing), std::move(metadata), + std::move(new_features), resources, std::move(render_data), + std::move(cpu_timing), std::move(input_timing_delta), + std::move(subresource_load_metrics), soft_navigation_count); } } @@ -1106,13 +1107,14 @@ mojom::FrameRenderDataUpdatePtr render_data, mojom::CpuTimingPtr cpu_timing, mojom::InputTimingPtr input_timing_delta, + mojom::SubresourceLoadMetricsPtr subresource_load_metrics, uint32_t soft_navigation_count) { content::RenderFrameHost* render_frame_host = page_load_metrics_receivers_.GetCurrentTargetFrame(); OnTimingUpdated(render_frame_host, std::move(timing), std::move(metadata), new_features, resources, std::move(render_data), std::move(cpu_timing), std::move(input_timing_delta), - soft_navigation_count); + std::move(subresource_load_metrics), soft_navigation_count); } void MetricsWebContentsObserver::SetUpSharedMemoryForSmoothness(
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer.h b/components/page_load_metrics/browser/metrics_web_contents_observer.h index e3c1cd0..71b6ea3 100644 --- a/components/page_load_metrics/browser/metrics_web_contents_observer.h +++ b/components/page_load_metrics/browser/metrics_web_contents_observer.h
@@ -151,6 +151,7 @@ mojom::FrameRenderDataUpdatePtr render_data, mojom::CpuTimingPtr cpu_timing, mojom::InputTimingPtr input_timing_delta, + mojom::SubresourceLoadMetricsPtr subresource_load_metrics, uint32_t soft_navigation_count); // Informs the observers of the currently committed primary page load that @@ -205,14 +206,16 @@ content::NavigationHandle* navigation_handle); // page_load_metrics::mojom::PageLoadMetrics implementation. - void UpdateTiming(mojom::PageLoadTimingPtr timing, - mojom::FrameMetadataPtr metadata, - const std::vector<blink::UseCounterFeature>& new_features, - std::vector<mojom::ResourceDataUpdatePtr> resources, - mojom::FrameRenderDataUpdatePtr render_data, - mojom::CpuTimingPtr cpu_timing, - mojom::InputTimingPtr input_timing, - uint32_t soft_navigation_count) override; + void UpdateTiming( + mojom::PageLoadTimingPtr timing, + mojom::FrameMetadataPtr metadata, + const std::vector<blink::UseCounterFeature>& new_features, + std::vector<mojom::ResourceDataUpdatePtr> resources, + mojom::FrameRenderDataUpdatePtr render_data, + mojom::CpuTimingPtr cpu_timing, + mojom::InputTimingPtr input_timing, + const mojom::SubresourceLoadMetricsPtr subresource_load_metrics, + uint32_t soft_navigation_count) override; void SetUpSharedMemoryForSmoothness( base::ReadOnlySharedMemoryRegion shared_memory) override;
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc b/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc index cb6eb67..6fd821cf 100644 --- a/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc +++ b/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc
@@ -118,13 +118,14 @@ void SimulateCpuTimingUpdate(const mojom::CpuTiming& timing, content::RenderFrameHost* render_frame_host) { - observer()->OnTimingUpdated(render_frame_host, previous_timing_->Clone(), - mojom::FrameMetadataPtr(absl::in_place), - std::vector<blink::UseCounterFeature>(), - std::vector<mojom::ResourceDataUpdatePtr>(), - mojom::FrameRenderDataUpdatePtr(absl::in_place), - timing.Clone(), - mojom::InputTimingPtr(absl::in_place), 0); + observer()->OnTimingUpdated( + render_frame_host, previous_timing_->Clone(), + mojom::FrameMetadataPtr(absl::in_place), + std::vector<blink::UseCounterFeature>(), + std::vector<mojom::ResourceDataUpdatePtr>(), + mojom::FrameRenderDataUpdatePtr(absl::in_place), timing.Clone(), + mojom::InputTimingPtr(absl::in_place), + mojom::SubresourceLoadMetricsPtr(absl::in_place), 0); } void SimulateTimingUpdate(const mojom::PageLoadTiming& timing, @@ -142,13 +143,15 @@ const mojom::PageLoadTiming& timing, content::RenderFrameHost* render_frame_host) { previous_timing_ = timing.Clone(); - observer()->OnTimingUpdated(render_frame_host, timing.Clone(), - mojom::FrameMetadataPtr(absl::in_place), - std::vector<blink::UseCounterFeature>(), - std::vector<mojom::ResourceDataUpdatePtr>(), - mojom::FrameRenderDataUpdatePtr(absl::in_place), - mojom::CpuTimingPtr(absl::in_place), - mojom::InputTimingPtr(absl::in_place), 0); + observer()->OnTimingUpdated( + render_frame_host, timing.Clone(), + mojom::FrameMetadataPtr(absl::in_place), + std::vector<blink::UseCounterFeature>(), + std::vector<mojom::ResourceDataUpdatePtr>(), + mojom::FrameRenderDataUpdatePtr(absl::in_place), + mojom::CpuTimingPtr(absl::in_place), + mojom::InputTimingPtr(absl::in_place), + mojom::SubresourceLoadMetricsPtr(absl::in_place), 0); } virtual std::unique_ptr<TestMetricsWebContentsObserverEmbedder>
diff --git a/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc b/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc index 0f7e94f..1d37a29f 100644 --- a/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc +++ b/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
@@ -211,7 +211,8 @@ std::vector<blink::UseCounterFeature>(), resources, mojom::FrameRenderDataUpdatePtr(absl::in_place), mojom::CpuTimingPtr(absl::in_place), - mojom::InputTimingPtr(absl::in_place), 0); + mojom::InputTimingPtr(absl::in_place), + mojom::SubresourceLoadMetricsPtr(absl::in_place), 0); } };
diff --git a/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.cc b/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.cc index 4a2e6b6d5..7ff1dc0 100644 --- a/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.cc +++ b/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.cc
@@ -130,10 +130,10 @@ void PageLoadMetricsObserverTester::SimulateTimingUpdate( const mojom::PageLoadTiming& timing, content::RenderFrameHost* rfh) { - SimulatePageLoadTimingUpdate(timing, mojom::FrameMetadata(), - /*new_features=*/{}, - mojom::FrameRenderDataUpdate(), - mojom::CpuTiming(), mojom::InputTiming(), rfh); + SimulatePageLoadTimingUpdate( + timing, mojom::FrameMetadata(), /* new_features= */ {}, + mojom::FrameRenderDataUpdate(), mojom::CpuTiming(), mojom::InputTiming(), + mojom::SubresourceLoadMetrics(), rfh); } void PageLoadMetricsObserverTester::SimulateCpuTimingUpdate( @@ -147,8 +147,9 @@ auto timing = page_load_metrics::mojom::PageLoadTimingPtr(absl::in_place); page_load_metrics::InitPageLoadTimingForTest(timing.get()); SimulatePageLoadTimingUpdate( - *timing, mojom::FrameMetadata(), /*new_features=*/{}, - mojom::FrameRenderDataUpdate(), cpu_timing, mojom::InputTiming(), rfh); + *timing, mojom::FrameMetadata(), /* new_features= */ {}, + mojom::FrameRenderDataUpdate(), cpu_timing, mojom::InputTiming(), + mojom::SubresourceLoadMetrics(), rfh); } void PageLoadMetricsObserverTester::SimulateInputTimingUpdate( @@ -163,17 +164,18 @@ auto timing = page_load_metrics::mojom::PageLoadTimingPtr(absl::in_place); page_load_metrics::InitPageLoadTimingForTest(timing.get()); SimulatePageLoadTimingUpdate( - *timing, mojom::FrameMetadata(), /*new_features=*/{}, - mojom::FrameRenderDataUpdate(), mojom::CpuTiming(), input_timing, rfh); + *timing, mojom::FrameMetadata(), /* new_features= */ {}, + mojom::FrameRenderDataUpdate(), mojom::CpuTiming(), input_timing, + mojom::SubresourceLoadMetrics(), rfh); } void PageLoadMetricsObserverTester::SimulateTimingAndMetadataUpdate( const mojom::PageLoadTiming& timing, const mojom::FrameMetadata& metadata) { - SimulatePageLoadTimingUpdate(timing, metadata, /*new_features=*/{}, - mojom::FrameRenderDataUpdate(), - mojom::CpuTiming(), mojom::InputTiming(), - web_contents()->GetPrimaryMainFrame()); + SimulatePageLoadTimingUpdate( + timing, metadata, /* new_features= */ {}, mojom::FrameRenderDataUpdate(), + mojom::CpuTiming(), mojom::InputTiming(), mojom::SubresourceLoadMetrics(), + web_contents()->GetPrimaryMainFrame()); } void PageLoadMetricsObserverTester::SimulateMetadataUpdate( @@ -181,17 +183,18 @@ content::RenderFrameHost* rfh) { mojom::PageLoadTiming timing; InitPageLoadTimingForTest(&timing); - SimulatePageLoadTimingUpdate(timing, metadata, /*new_features=*/{}, + SimulatePageLoadTimingUpdate(timing, metadata, /* new_features= */ {}, mojom::FrameRenderDataUpdate(), - mojom::CpuTiming(), mojom::InputTiming(), rfh); + mojom::CpuTiming(), mojom::InputTiming(), + mojom::SubresourceLoadMetrics(), rfh); } void PageLoadMetricsObserverTester::SimulateFeaturesUpdate( const std::vector<blink::UseCounterFeature>& new_features) { - SimulatePageLoadTimingUpdate(mojom::PageLoadTiming(), mojom::FrameMetadata(), - new_features, mojom::FrameRenderDataUpdate(), - mojom::CpuTiming(), mojom::InputTiming(), - web_contents()->GetPrimaryMainFrame()); + SimulatePageLoadTimingUpdate( + mojom::PageLoadTiming(), mojom::FrameMetadata(), new_features, + mojom::FrameRenderDataUpdate(), mojom::CpuTiming(), mojom::InputTiming(), + mojom::SubresourceLoadMetrics(), web_contents()->GetPrimaryMainFrame()); } void PageLoadMetricsObserverTester::SimulateRenderDataUpdate( @@ -205,17 +208,18 @@ mojom::PageLoadTiming timing; InitPageLoadTimingForTest(&timing); SimulatePageLoadTimingUpdate(timing, mojom::FrameMetadata(), - /*new_features=*/{}, render_data, - mojom::CpuTiming(), mojom::InputTiming(), rfh); + /* new_features= */ {}, render_data, + mojom::CpuTiming(), mojom::InputTiming(), + mojom::SubresourceLoadMetrics(), rfh); } void PageLoadMetricsObserverTester::SimulateSoftNavigationCountUpdate( uint32_t soft_navigation_count) { SimulatePageLoadTimingUpdate( mojom::PageLoadTiming(), mojom::FrameMetadata(), - /*new_features=*/{}, mojom::FrameRenderDataUpdate(), mojom::CpuTiming(), - mojom::InputTiming(), web_contents()->GetPrimaryMainFrame(), - soft_navigation_count); + /* new_features= */ {}, mojom::FrameRenderDataUpdate(), + mojom::CpuTiming(), mojom::InputTiming(), mojom::SubresourceLoadMetrics(), + web_contents()->GetPrimaryMainFrame(), soft_navigation_count); } void PageLoadMetricsObserverTester::SimulatePageLoadTimingUpdate( @@ -225,12 +229,14 @@ const mojom::FrameRenderDataUpdate& render_data, const mojom::CpuTiming& cpu_timing, const mojom::InputTiming& input_timing, + const mojom::SubresourceLoadMetrics& subresource_load_metrics, content::RenderFrameHost* rfh, uint32_t soft_navigation_count) { metrics_web_contents_observer_->OnTimingUpdated( rfh, timing.Clone(), metadata.Clone(), new_features, std::vector<mojom::ResourceDataUpdatePtr>(), render_data.Clone(), - cpu_timing.Clone(), input_timing.Clone(), soft_navigation_count); + cpu_timing.Clone(), input_timing.Clone(), + subresource_load_metrics.Clone(), soft_navigation_count); // If sending the timing update caused the PageLoadMetricsUpdateDispatcher to // schedule a buffering timer, then fire it now so metrics are dispatched to // observers. @@ -256,7 +262,8 @@ std::vector<blink::UseCounterFeature>(), resources, mojom::FrameRenderDataUpdatePtr(absl::in_place), mojom::CpuTimingPtr(absl::in_place), - mojom::InputTimingPtr(absl::in_place), 0); + mojom::InputTimingPtr(absl::in_place), + mojom::SubresourceLoadMetricsPtr(absl::in_place), 0); } void PageLoadMetricsObserverTester::SimulateLoadedResource(
diff --git a/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.h b/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.h index ca7b68f..db60315 100644 --- a/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.h +++ b/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.h
@@ -172,6 +172,7 @@ const mojom::FrameRenderDataUpdate& render_data, const mojom::CpuTiming& cpu_timing, const mojom::InputTiming& input_timing, + const mojom::SubresourceLoadMetrics& subresource_load_metrics, content::RenderFrameHost* rfh, uint32_t soft_navigation_count = 0);
diff --git a/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h b/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h index 3ae0df0..5809fc7 100644 --- a/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h +++ b/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h
@@ -189,6 +189,8 @@ virtual const PageRenderData& GetMainFrameRenderData() const = 0; virtual const ui::ScopedVisibilityTracker& GetVisibilityTracker() const = 0; virtual const ResourceTracker& GetResourceTracker() const = 0; + virtual const absl::optional<mojom::SubresourceLoadMetrics>& + GetSubresourceLoadMetrics() const = 0; // Returns a shared LargestContentfulPaintHandler for page load metrics. virtual const LargestContentfulPaintHandler&
diff --git a/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.cc b/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.cc index 5e0d77b..fd0b89c3 100644 --- a/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.cc +++ b/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.cc
@@ -475,6 +475,7 @@ mojom::FrameRenderDataUpdatePtr render_data, mojom::CpuTimingPtr new_cpu_timing, mojom::InputTimingPtr input_timing_delta, + mojom::SubresourceLoadMetricsPtr subresource_load_metrics, uint32_t soft_navigation_count) { if (embedder_interface_->IsExtensionUrl( render_frame_host->GetLastCommittedURL())) { @@ -496,6 +497,9 @@ UpdateMainFrameMetadata(render_frame_host, std::move(new_metadata)); UpdateMainFrameTiming(std::move(new_timing)); UpdateMainFrameRenderData(*render_data); + if (subresource_load_metrics) { + UpdateMainFrameSubresourceLoadMetrics(*subresource_load_metrics); + } UpdateSoftNavigationCount(soft_navigation_count); } else { UpdateSubFrameMetadata(render_frame_host, std::move(new_metadata)); @@ -635,6 +639,11 @@ MaybeUpdateMainFrameIntersectionRect(render_frame_host, subframe_metadata); } +void PageLoadMetricsUpdateDispatcher::UpdateMainFrameSubresourceLoadMetrics( + const mojom::SubresourceLoadMetrics& subresource_load_metrics) { + subresource_load_metrics_ = subresource_load_metrics; +} + void PageLoadMetricsUpdateDispatcher::UpdateSoftNavigationCount( uint32_t soft_navigation_count) { client_->OnSoftNavigationCountChanged(soft_navigation_count);
diff --git a/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.h b/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.h index e6925f9e..66f7386 100644 --- a/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.h +++ b/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.h
@@ -170,6 +170,7 @@ mojom::FrameRenderDataUpdatePtr render_data, mojom::CpuTimingPtr new_cpu_timing, mojom::InputTimingPtr input_timing_delta, + mojom::SubresourceLoadMetricsPtr subresource_load_metrics, uint32_t soft_navigation_count); void SetUpSharedMemoryForSmoothness( @@ -219,6 +220,10 @@ const mojom::InputTiming& page_input_timing() const { return *page_input_timing_; } + const absl::optional<mojom::SubresourceLoadMetrics>& + subresource_load_metrics() const { + return subresource_load_metrics_; + } void UpdateResponsivenessMetricsNormalizationForBfcache() { responsiveness_metrics_normalization_.ClearAllUserInteractionLatencies(); } @@ -246,6 +251,9 @@ void UpdateSubFrameMetadata(content::RenderFrameHost* render_frame_host, mojom::FrameMetadataPtr subframe_metadata); + void UpdateMainFrameSubresourceLoadMetrics( + const mojom::SubresourceLoadMetrics& subresource_load_metrics); + void UpdateSoftNavigationCount(uint32_t soft_navigation_count); void UpdatePageInputTiming(const mojom::InputTiming& input_timing_delta); @@ -299,6 +307,9 @@ // InputTiming data accumulated across all frames. mojom::InputTimingPtr page_input_timing_; + // SubresourceLoadMetrics for the main frame. + absl::optional<mojom::SubresourceLoadMetrics> subresource_load_metrics_; + // True if this page load started in prerender. const bool is_prerendered_page_load_;
diff --git a/components/page_load_metrics/browser/page_load_tracker.cc b/components/page_load_metrics/browser/page_load_tracker.cc index 7e598dc..c279486e 100644 --- a/components/page_load_metrics/browser/page_load_tracker.cc +++ b/components/page_load_metrics/browser/page_load_tracker.cc
@@ -1093,6 +1093,11 @@ return metrics_update_dispatcher_.page_input_timing(); } +const absl::optional<mojom::SubresourceLoadMetrics>& +PageLoadTracker::GetSubresourceLoadMetrics() const { + return metrics_update_dispatcher_.subresource_load_metrics(); +} + const PageRenderData& PageLoadTracker::GetMainFrameRenderData() const { return metrics_update_dispatcher_.main_frame_render_data(); } @@ -1198,18 +1203,20 @@ mojom::FrameRenderDataUpdatePtr render_data, mojom::CpuTimingPtr cpu_timing, mojom::InputTimingPtr input_timing_delta, + mojom::SubresourceLoadMetricsPtr subresource_load_metrics, uint32_t soft_navigation_count) { if (parent_tracker_) { parent_tracker_->UpdateMetrics( render_frame_host, timing.Clone(), metadata.Clone(), features, resources, render_data.Clone(), cpu_timing.Clone(), - input_timing_delta.Clone(), soft_navigation_count); + input_timing_delta.Clone(), subresource_load_metrics.Clone(), + soft_navigation_count); } metrics_update_dispatcher_.UpdateMetrics( render_frame_host, std::move(timing), std::move(metadata), std::move(features), resources, std::move(render_data), std::move(cpu_timing), std::move(input_timing_delta), - soft_navigation_count); + std::move(subresource_load_metrics), soft_navigation_count); } void PageLoadTracker::SetPageMainFrame(content::RenderFrameHost* rfh) {
diff --git a/components/page_load_metrics/browser/page_load_tracker.h b/components/page_load_metrics/browser/page_load_tracker.h index a0af84c..1b3d84e 100644 --- a/components/page_load_metrics/browser/page_load_tracker.h +++ b/components/page_load_metrics/browser/page_load_tracker.h
@@ -259,6 +259,8 @@ const NormalizedResponsivenessMetrics& GetNormalizedResponsivenessMetrics() const override; const mojom::InputTiming& GetPageInputTiming() const override; + const absl::optional<mojom::SubresourceLoadMetrics>& + GetSubresourceLoadMetrics() const override; const PageRenderData& GetMainFrameRenderData() const override; const ui::ScopedVisibilityTracker& GetVisibilityTracker() const override; const ResourceTracker& GetResourceTracker() const override; @@ -414,6 +416,7 @@ mojom::FrameRenderDataUpdatePtr render_data, mojom::CpuTimingPtr new_cpu_timing, mojom::InputTimingPtr input_timing_delta, + mojom::SubresourceLoadMetricsPtr subresource_load_metrics, uint32_t soft_navigation_count); // Set RenderFrameHost for the main frame of the page this tracker instance is
diff --git a/components/page_load_metrics/common/page_load_metrics.mojom b/components/page_load_metrics/common/page_load_metrics.mojom index 836d6d4..56a5e57 100644 --- a/components/page_load_metrics/common/page_load_metrics.mojom +++ b/components/page_load_metrics/common/page_load_metrics.mojom
@@ -214,6 +214,16 @@ gfx.mojom.Rect? main_frame_viewport_rect; }; +struct SubresourceLoadMetrics { + // Number of subresources loads for the frame. + // Note that this include subresources where a service worker responded. + uint32 number_of_subresources_loaded; + + // Number of subresources loads that is responded by the service worker. + // i.e. `respondWith` was called. + uint32 number_of_subresource_loads_handled_by_service_worker; +}; + // Enumeration of distinct cache types. enum CacheType { kNotCached, // Resource came from network. @@ -368,6 +378,8 @@ // UpdateTiming calls are buffered, and contain all updates that have been // received in the last buffer window. Some of the update data may be empty. // Only called when at least one change has been observed within the frame. + // Note that counts in `subresource_load_metrics` are cumulative and not a + // delta. UpdateTiming(PageLoadTiming page_load_timing, FrameMetadata frame_metadata, // `new_features` will not contain any previously seen values. @@ -376,6 +388,7 @@ FrameRenderDataUpdate render_data, CpuTiming cpu_load_timing, InputTiming input_timing_delta, + SubresourceLoadMetrics? subresource_load_metrics, uint32 soft_navigation_count); // Set up a shared memory used to transfer smoothness data from the renderer
diff --git a/components/page_load_metrics/renderer/fake_page_timing_sender.cc b/components/page_load_metrics/renderer/fake_page_timing_sender.cc index 6f258a0..533fd94 100644 --- a/components/page_load_metrics/renderer/fake_page_timing_sender.cc +++ b/components/page_load_metrics/renderer/fake_page_timing_sender.cc
@@ -25,10 +25,11 @@ const mojom::FrameRenderDataUpdate& render_data, const mojom::CpuTimingPtr& cpu_timing, const mojom::InputTimingPtr new_input_timing, + const mojom::SubresourceLoadMetricsPtr subresource_load_metrics, uint32_t soft_navigation_count) { validator_->UpdateTiming(timing, metadata, new_features, resources, render_data, cpu_timing, new_input_timing, - soft_navigation_count); + subresource_load_metrics, soft_navigation_count); } void FakePageTimingSender::SetUpSmoothnessReporting( @@ -84,6 +85,18 @@ actual_input_timing->total_adjusted_input_delay); } +void FakePageTimingSender::PageTimingValidator:: + UpdateExpectedSubresourceLoadMetrics( + const mojom::SubresourceLoadMetrics& subresource_load_metrics) { + expected_subresource_load_metrics_ = subresource_load_metrics.Clone(); +} + +void FakePageTimingSender::PageTimingValidator:: + VerifyExpectedSubresourceLoadMetrics() const { + ASSERT_EQ(expected_subresource_load_metrics_, + actual_subresource_load_metrics_); +} + void FakePageTimingSender::PageTimingValidator::VerifyExpectedCpuTimings() const { ASSERT_EQ(actual_cpu_timings_.size(), expected_cpu_timings_.size()); @@ -132,6 +145,7 @@ const mojom::FrameRenderDataUpdate& render_data, const mojom::CpuTimingPtr& cpu_timing, const mojom::InputTimingPtr& new_input_timing, + const mojom::SubresourceLoadMetricsPtr& subresource_load_metrics, uint32_t soft_navigation_count) { actual_timings_.push_back(timing.Clone()); if (!cpu_timing->task_time.is_zero()) { @@ -152,6 +166,7 @@ actual_input_timing->total_input_delay += new_input_timing->total_input_delay; actual_input_timing->total_adjusted_input_delay += new_input_timing->total_adjusted_input_delay; + actual_subresource_load_metrics_ = subresource_load_metrics.Clone(); VerifyExpectedTimings(); VerifyExpectedCpuTimings(); @@ -159,6 +174,7 @@ VerifyExpectedRenderData(); VerifyExpectedMainFrameIntersectionRect(); VerifyExpectedMainFrameViewportRect(); + VerifyExpectedSubresourceLoadMetrics(); // TODO(yoav): Verify that soft nav count matches expectations. }
diff --git a/components/page_load_metrics/renderer/fake_page_timing_sender.h b/components/page_load_metrics/renderer/fake_page_timing_sender.h index 123a8ac..1c2b2dd 100644 --- a/components/page_load_metrics/renderer/fake_page_timing_sender.h +++ b/components/page_load_metrics/renderer/fake_page_timing_sender.h
@@ -62,6 +62,8 @@ void VerifyExpectedInputTiming() const; + void VerifyExpectedSubresourceLoadMetrics() const; + // PageLoad features that are expected to be sent through SendTiming() // should be passed via UpdateExpectedPageLoadFeatures. void UpdateExpectPageLoadFeatures(const blink::UseCounterFeature& feature); @@ -73,6 +75,9 @@ void UpdateExpectedInputTiming(const base::TimeDelta input_delay); + void UpdateExpectedSubresourceLoadMetrics( + const mojom::SubresourceLoadMetrics& subresource_load_metrics); + void UpdateExpectedMainFrameIntersectionRect( const gfx::Rect& main_frame_intersection_rect) { expected_main_frame_intersection_rect_ = main_frame_intersection_rect; @@ -105,6 +110,7 @@ const mojom::FrameRenderDataUpdate& render_data, const mojom::CpuTimingPtr& cpu_timing, const mojom::InputTimingPtr& input_timing, + const mojom::SubresourceLoadMetricsPtr& subresource_load_metrics, uint32_t soft_navigation_count); private: @@ -122,6 +128,8 @@ absl::optional<gfx::Rect> actual_main_frame_viewport_rect_; mojom::InputTimingPtr expected_input_timing; mojom::InputTimingPtr actual_input_timing; + mojom::SubresourceLoadMetricsPtr expected_subresource_load_metrics_; + mojom::SubresourceLoadMetricsPtr actual_subresource_load_metrics_; }; explicit FakePageTimingSender(PageTimingValidator* validator); @@ -138,6 +146,7 @@ const mojom::FrameRenderDataUpdate& render_data, const mojom::CpuTimingPtr& cpu_timing, mojom::InputTimingPtr new_input_timing, + mojom::SubresourceLoadMetricsPtr subresource_load_metrics, uint32_t soft_navigation_count) override; void SetUpSmoothnessReporting(
diff --git a/components/page_load_metrics/renderer/metrics_render_frame_observer.cc b/components/page_load_metrics/renderer/metrics_render_frame_observer.cc index 2b0d647..c8922f6 100644 --- a/components/page_load_metrics/renderer/metrics_render_frame_observer.cc +++ b/components/page_load_metrics/renderer/metrics_render_frame_observer.cc
@@ -55,13 +55,14 @@ const mojom::FrameRenderDataUpdate& render_data, const mojom::CpuTimingPtr& cpu_timing, mojom::InputTimingPtr input_timing_delta, + mojom::SubresourceLoadMetricsPtr subresource_load_metrics, uint32_t soft_navigation_count) override { DCHECK(page_load_metrics_); page_load_metrics_->UpdateTiming( limited_sending_mode_ ? CreatePageLoadTiming() : timing->Clone(), metadata->Clone(), new_features, std::move(resources), render_data.Clone(), cpu_timing->Clone(), std::move(input_timing_delta), - soft_navigation_count); + std::move(subresource_load_metrics), soft_navigation_count); } void SetUpSmoothnessReporting( @@ -133,6 +134,15 @@ page_timing_metrics_sender_->DidObserveLoadingBehavior(behavior); } +void MetricsRenderFrameObserver::DidObserveSubresourceLoad( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker) { + if (page_timing_metrics_sender_) + page_timing_metrics_sender_->DidObserveSubresourceLoad( + number_of_subresources_loaded, + number_of_subresource_loads_handled_by_service_worker); +} + void MetricsRenderFrameObserver::DidObserveNewFeatureUsage( const blink::UseCounterFeature& feature) { if (page_timing_metrics_sender_)
diff --git a/components/page_load_metrics/renderer/metrics_render_frame_observer.h b/components/page_load_metrics/renderer/metrics_render_frame_observer.h index 3d7ed3b..aaec2ba 100644 --- a/components/page_load_metrics/renderer/metrics_render_frame_observer.h +++ b/components/page_load_metrics/renderer/metrics_render_frame_observer.h
@@ -56,6 +56,9 @@ blink::UserInteractionType interaction_type) override; void DidChangeCpuTiming(base::TimeDelta time) override; void DidObserveLoadingBehavior(blink::LoadingBehaviorFlag behavior) override; + void DidObserveSubresourceLoad( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker) override; void DidObserveNewFeatureUsage( const blink::UseCounterFeature& feature) override; void DidObserveSoftNavigation(uint32_t count) override;
diff --git a/components/page_load_metrics/renderer/page_timing_metrics_sender.cc b/components/page_load_metrics/renderer/page_timing_metrics_sender.cc index d3610bb..4809eb9 100644 --- a/components/page_load_metrics/renderer/page_timing_metrics_sender.cc +++ b/components/page_load_metrics/renderer/page_timing_metrics_sender.cc
@@ -86,6 +86,27 @@ EnsureSendTimer(); } +void PageTimingMetricsSender::DidObserveSubresourceLoad( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker) { + if (!subresource_load_metrics_) { + subresource_load_metrics_ = mojom::SubresourceLoadMetrics::New(); + } + if (subresource_load_metrics_->number_of_subresources_loaded == + number_of_subresources_loaded && + subresource_load_metrics_ + ->number_of_subresource_loads_handled_by_service_worker == + number_of_subresource_loads_handled_by_service_worker) { + return; + } + subresource_load_metrics_->number_of_subresources_loaded = + number_of_subresources_loaded; + subresource_load_metrics_ + ->number_of_subresource_loads_handled_by_service_worker = + number_of_subresource_loads_handled_by_service_worker; + EnsureSendTimer(); +} + void PageTimingMetricsSender::DidObserveNewFeatureUsage( const blink::UseCounterFeature& feature) { if (feature_tracker_.TestAndSet(feature)) @@ -317,9 +338,10 @@ page_resource_data_use_.erase(resource->resource_id()); } } - sender_->SendTiming(last_timing_, metadata_, std::move(new_features_), - std::move(resources), render_data_, last_cpu_timing_, - std::move(input_timing_delta_), soft_navigation_count_); + sender_->SendTiming( + last_timing_, metadata_, std::move(new_features_), std::move(resources), + render_data_, last_cpu_timing_, std::move(input_timing_delta_), + subresource_load_metrics_.Clone(), soft_navigation_count_); input_timing_delta_ = mojom::InputTiming::New(); InitiateUserInteractionTiming(); new_features_.clear();
diff --git a/components/page_load_metrics/renderer/page_timing_metrics_sender.h b/components/page_load_metrics/renderer/page_timing_metrics_sender.h index f7398e8..3de1e39 100644 --- a/components/page_load_metrics/renderer/page_timing_metrics_sender.h +++ b/components/page_load_metrics/renderer/page_timing_metrics_sender.h
@@ -50,6 +50,9 @@ ~PageTimingMetricsSender(); void DidObserveLoadingBehavior(blink::LoadingBehaviorFlag behavior); + void DidObserveSubresourceLoad( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker); void DidObserveNewFeatureUsage(const blink::UseCounterFeature& feature); void DidObserveSoftNavigation(uint32_t count); void DidObserveLayoutShift(double score, bool after_input_or_scroll); @@ -110,6 +113,7 @@ mojom::PageLoadTimingPtr last_timing_; mojom::CpuTimingPtr last_cpu_timing_; mojom::InputTimingPtr input_timing_delta_; + mojom::SubresourceLoadMetricsPtr subresource_load_metrics_; // The the sender keep track of metadata as it comes in, because the sender is // scoped to a single committed load.
diff --git a/components/page_load_metrics/renderer/page_timing_metrics_sender_unittest.cc b/components/page_load_metrics/renderer/page_timing_metrics_sender_unittest.cc index 4db3f78e..a5f75b6f1 100644 --- a/components/page_load_metrics/renderer/page_timing_metrics_sender_unittest.cc +++ b/components/page_load_metrics/renderer/page_timing_metrics_sender_unittest.cc
@@ -163,6 +163,24 @@ validator_.VerifyExpectedInputTiming(); } +TEST_F(PageTimingMetricsSenderTest, SendSubresourceLoadMetrics) { + mojom::PageLoadTiming timing; + InitPageLoadTimingForTest(&timing); + metrics_sender_->Update(timing.Clone(), + PageTimingMetadataRecorder::MonotonicTiming()); + validator_.ExpectPageLoadTiming(timing); + + metrics_sender_->DidObserveSubresourceLoad(5, 2); + + mojom::SubresourceLoadMetricsPtr expected = + mojom::SubresourceLoadMetrics::New(); + expected->number_of_subresources_loaded = 5; + expected->number_of_subresource_loads_handled_by_service_worker = 2; + validator_.UpdateExpectedSubresourceLoadMetrics(*expected); + metrics_sender_->mock_timer()->Fire(); + validator_.VerifyExpectedSubresourceLoadMetrics(); +} + TEST_F(PageTimingMetricsSenderTest, SendSingleFeature) { mojom::PageLoadTiming timing; InitPageLoadTimingForTest(&timing);
diff --git a/components/page_load_metrics/renderer/page_timing_sender.h b/components/page_load_metrics/renderer/page_timing_sender.h index 6c32be03..d4d3a68a0 100644 --- a/components/page_load_metrics/renderer/page_timing_sender.h +++ b/components/page_load_metrics/renderer/page_timing_sender.h
@@ -22,6 +22,7 @@ const mojom::FrameRenderDataUpdate& render_data, const mojom::CpuTimingPtr& cpu_timing, mojom::InputTimingPtr input_timing_delta, + mojom::SubresourceLoadMetricsPtr subresource_load_metrics, uint32_t soft_navigation_count) = 0; virtual void SetUpSmoothnessReporting( base::ReadOnlySharedMemoryRegion shared_memory) = 0;
diff --git a/components/password_manager/content/common/BUILD.gn b/components/password_manager/content/common/BUILD.gn new file mode 100644 index 0000000..a083906d --- /dev/null +++ b/components/password_manager/content/common/BUILD.gn
@@ -0,0 +1,10 @@ +# 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. + +static_library("common") { + sources = [ + "web_ui_constants.cc", + "web_ui_constants.h", + ] +}
diff --git a/components/password_manager/content/common/web_ui_constants.cc b/components/password_manager/content/common/web_ui_constants.cc new file mode 100644 index 0000000..ba03df6 --- /dev/null +++ b/components/password_manager/content/common/web_ui_constants.cc
@@ -0,0 +1,11 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/password_manager/content/common/web_ui_constants.h" + +namespace password_manager { + +const char kChromeUIPasswordManagerHost[] = "password-manager"; + +} // namespace password_manager \ No newline at end of file
diff --git a/components/password_manager/content/common/web_ui_constants.h b/components/password_manager/content/common/web_ui_constants.h new file mode 100644 index 0000000..0fe611daf --- /dev/null +++ b/components/password_manager/content/common/web_ui_constants.h
@@ -0,0 +1,18 @@ +// 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. + +// Contains constants for WebUI UI/Host/SubPage constants. Anything else go in +// chrome/common/url_constants.h. + +#ifndef COMPONENTS_PASSWORD_MANAGER_CONTENT_COMMON_WEB_UI_CONSTANTS_H_ +#define COMPONENTS_PASSWORD_MANAGER_CONTENT_COMMON_WEB_UI_CONSTANTS_H_ + +namespace password_manager { + +// WebUI constants for Password Manager that are needed for other components. +extern const char kChromeUIPasswordManagerHost[]; + +} // namespace password_manager + +#endif // COMPONENTS_PASSWORD_MANAGER_CONTENT_COMMON_WEB_UI_CONSTANTS_H_
diff --git a/components/policy/resources/templates/policy_definitions/ChromeFrameContentTypes/ChromeFrameContentTypes.yaml b/components/policy/resources/templates/policy_definitions/ChromeFrameContentTypes/ChromeFrameContentTypes.yaml index 236eefb..7f7bcc88 100644 --- a/components/policy/resources/templates/policy_definitions/ChromeFrameContentTypes/ChromeFrameContentTypes.yaml +++ b/components/policy/resources/templates/policy_definitions/ChromeFrameContentTypes/ChromeFrameContentTypes.yaml
@@ -11,7 +11,7 @@ features: dynamic_refresh: false owners: -- tommi@chromium.org +- file://components/policy/OWNERS schema: items: type: string
diff --git a/components/policy/resources/templates/policy_definitions/ChromeFrameRendererSettings/ChromeFrameRendererSettings.yaml b/components/policy/resources/templates/policy_definitions/ChromeFrameRendererSettings/ChromeFrameRendererSettings.yaml index d96d9238..cc8f30f 100644 --- a/components/policy/resources/templates/policy_definitions/ChromeFrameRendererSettings/ChromeFrameRendererSettings.yaml +++ b/components/policy/resources/templates/policy_definitions/ChromeFrameRendererSettings/ChromeFrameRendererSettings.yaml
@@ -16,7 +16,7 @@ name: RenderInChromeFrame value: 1 owners: -- tommi@chromium.org +- file://components/policy/OWNERS schema: enum: - 0
diff --git a/components/policy/resources/webui/policy_base.js b/components/policy/resources/webui/policy_base.js index 7487d68..72599b4 100644 --- a/components/policy/resources/webui/policy_base.js +++ b/components/policy/resources/webui/policy_base.js
@@ -11,7 +11,7 @@ import './status_box.js'; import './policy_table.js'; -import {addWebUIListener, sendWithPromise} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener, sendWithPromise} from 'chrome://resources/js/cr.js'; import {FocusOutlineManager} from 'chrome://resources/js/focus_outline_manager.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {$} from 'chrome://resources/js/util.js'; @@ -117,11 +117,11 @@ }; chrome.send('listenPoliciesUpdates'); - addWebUIListener('status-updated', status => this.setStatus(status)); - addWebUIListener( + addWebUiListener('status-updated', status => this.setStatus(status)); + addWebUiListener( 'policies-updated', (names, values) => this.onPoliciesReceived_(names, values)); - addWebUIListener('download-json', json => this.downloadJson(json)); + addWebUiListener('download-json', json => this.downloadJson(json)); } /**
diff --git a/components/safe_browsing/content/browser/web_ui/resources/safe_browsing.js b/components/safe_browsing/content/browser/web_ui/resources/safe_browsing.js index 5f505121..efb4e8f64 100644 --- a/components/safe_browsing/content/browser/web_ui/resources/safe_browsing.js +++ b/components/safe_browsing/content/browser/web_ui/resources/safe_browsing.js
@@ -4,7 +4,7 @@ import 'chrome://resources/cr_elements/cr_tab_box/cr_tab_box.js'; -import {addWebUIListener, sendWithPromise} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener, sendWithPromise} from 'chrome://resources/js/cr.js'; import {$} from 'chrome://resources/js/util.js'; /** @@ -32,7 +32,7 @@ addDownloadUrlChecked(url_and_result); }); }); - addWebUIListener('download-url-checked-update', function(url_and_result) { + addWebUiListener('download-url-checked-update', function(url_and_result) { addDownloadUrlChecked(url_and_result); }); @@ -42,7 +42,7 @@ addSentClientDownloadRequestsInfo(cdr); }); }); - addWebUIListener('sent-client-download-requests-update', function(result) { + addWebUiListener('sent-client-download-requests-update', function(result) { addSentClientDownloadRequestsInfo(result); }); @@ -52,7 +52,7 @@ addReceivedClientDownloadResponseInfo(cdr); }); }); - addWebUIListener( + addWebUiListener( 'received-client-download-responses-update', function(result) { addReceivedClientDownloadResponseInfo(result); }); @@ -63,7 +63,7 @@ addSentClientPhishingRequestsInfo(cpr); }); }); - addWebUIListener('sent-client-phishing-requests-update', function(result) { + addWebUiListener('sent-client-phishing-requests-update', function(result) { addSentClientPhishingRequestsInfo(result); }); @@ -73,7 +73,7 @@ addReceivedClientPhishingResponseInfo(cpr); }); }); - addWebUIListener( + addWebUiListener( 'received-client-phishing-responses-update', function(result) { addReceivedClientPhishingResponseInfo(result); }); @@ -83,7 +83,7 @@ addSentCSBRRsInfo(csbrr); }); }); - addWebUIListener('sent-csbrr-update', function(result) { + addWebUiListener('sent-csbrr-update', function(result) { addSentCSBRRsInfo(result); }); @@ -92,7 +92,7 @@ addSentHitReportsInfo(hitReports); }); }); - addWebUIListener('sent-hit-report-list', function(result) { + addWebUiListener('sent-hit-report-list', function(result) { addSentHitReportsInfo(result); }); @@ -101,7 +101,7 @@ addPGEvent(pgEvent); }); }); - addWebUIListener('sent-pg-event', function(result) { + addWebUiListener('sent-pg-event', function(result) { addPGEvent(result); }); @@ -110,7 +110,7 @@ addSecurityEvent(securityEvent); }); }); - addWebUIListener('sent-security-event', function(result) { + addWebUiListener('sent-security-event', function(result) { addSecurityEvent(result); }); @@ -119,7 +119,7 @@ addPGPing(pgPing); }); }); - addWebUIListener('pg-pings-update', function(result) { + addWebUiListener('pg-pings-update', function(result) { addPGPing(result); }); @@ -128,7 +128,7 @@ addPGResponse(pgResponse); }); }); - addWebUIListener('pg-responses-update', function(result) { + addWebUiListener('pg-responses-update', function(result) { addPGResponse(result); }); @@ -137,7 +137,7 @@ addRTLookupPing(rtLookupPing); }); }); - addWebUIListener('rt-lookup-pings-update', function(result) { + addWebUiListener('rt-lookup-pings-update', function(result) { addRTLookupPing(result); }); @@ -146,7 +146,7 @@ addRTLookupResponse(rtLookupResponse); }); }); - addWebUIListener('rt-lookup-responses-update', function(result) { + addWebUiListener('rt-lookup-responses-update', function(result) { addRTLookupResponse(result); }); @@ -155,7 +155,7 @@ addLogMessage(message); }); }); - addWebUIListener('log-messages-update', function(message) { + addWebUiListener('log-messages-update', function(message) { addLogMessage(message); }); @@ -164,7 +164,7 @@ addReportingEvent(reportingEvent); }); }); - addWebUIListener('reporting-events-update', function(reportingEvent) { + addWebUiListener('reporting-events-update', function(reportingEvent) { addReportingEvent(reportingEvent); }); @@ -173,7 +173,7 @@ addDeepScan(request); }); }); - addWebUIListener('deep-scan-request-update', function(result) { + addWebUiListener('deep-scan-request-update', function(result) { addDeepScan(result); });
diff --git a/components/services/storage/service_worker/service_worker_storage.cc b/components/services/storage/service_worker/service_worker_storage.cc index 20e90d4c..dda0a9d 100644 --- a/components/services/storage/service_worker/service_worker_storage.cc +++ b/components/services/storage/service_worker/service_worker_storage.cc
@@ -19,7 +19,6 @@ #include "base/task/sequenced_task_runner.h" #include "base/task/task_runner_util.h" #include "base/task/thread_pool.h" -#include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "components/services/storage/public/cpp/constants.h" @@ -36,7 +35,8 @@ namespace { void RunSoon(const base::Location& from_here, base::OnceClosure closure) { - base::ThreadTaskRunnerHandle::Get()->PostTask(from_here, std::move(closure)); + base::SequencedTaskRunner::GetCurrentDefault()->PostTask(from_here, + std::move(closure)); } const base::FilePath::CharType kDatabaseName[] = FILE_PATH_LITERAL("Database"); @@ -148,8 +148,8 @@ database_task_runner_->PostTask( FROM_HERE, base::BindOnce(&FindForClientUrlInDB, database_.get(), - base::ThreadTaskRunnerHandle::Get(), client_url, - key, std::move(callback))); + base::SequencedTaskRunner::GetCurrentDefault(), + client_url, key, std::move(callback))); } void ServiceWorkerStorage::FindRegistrationForScope( @@ -185,8 +185,8 @@ database_task_runner_->PostTask( FROM_HERE, base::BindOnce(&FindForScopeInDB, database_.get(), - base::ThreadTaskRunnerHandle::Get(), scope, key, - std::move(callback))); + base::SequencedTaskRunner::GetCurrentDefault(), + scope, key, std::move(callback))); } void ServiceWorkerStorage::FindRegistrationForId( @@ -221,7 +221,7 @@ database_task_runner_->PostTask( FROM_HERE, base::BindOnce(&FindForIdInDB, database_.get(), - base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunner::GetCurrentDefault(), registration_id, key, std::move(callback))); } @@ -247,7 +247,7 @@ database_task_runner_->PostTask( FROM_HERE, base::BindOnce(&FindForIdOnlyInDB, database_.get(), - base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunner::GetCurrentDefault(), registration_id, std::move(callback))); } @@ -312,7 +312,8 @@ database_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ServiceWorkerStorage::GetUsageForStorageKeyInDB, - database_.get(), base::ThreadTaskRunnerHandle::Get(), key, + database_.get(), + base::SequencedTaskRunner::GetCurrentDefault(), key, std::move(callback))); } @@ -381,8 +382,8 @@ FROM_HERE, base::BindOnce( &WriteRegistrationInDB, database_.get(), - base::ThreadTaskRunnerHandle::Get(), std::move(registration_data), - std::move(resources), + base::SequencedTaskRunner::GetCurrentDefault(), + std::move(registration_data), std::move(resources), base::BindOnce(&ServiceWorkerStorage::DidStoreRegistrationData, weak_factory_.GetWeakPtr(), std::move(callback), resources_total_size_bytes))); @@ -564,7 +565,7 @@ FROM_HERE, base::BindOnce( &DeleteRegistrationFromDB, database_.get(), - base::ThreadTaskRunnerHandle::Get(), registration_id, key, + base::SequencedTaskRunner::GetCurrentDefault(), registration_id, key, base::BindOnce(&ServiceWorkerStorage::DidDeleteRegistration, weak_factory_.GetWeakPtr(), std::move(params)))); } @@ -820,8 +821,8 @@ database_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ServiceWorkerStorage::GetUserDataInDB, database_.get(), - base::ThreadTaskRunnerHandle::Get(), registration_id, keys, - std::move(callback))); + base::SequencedTaskRunner::GetCurrentDefault(), + registration_id, keys, std::move(callback))); } void ServiceWorkerStorage::GetUserDataByKeyPrefix( @@ -859,7 +860,8 @@ database_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ServiceWorkerStorage::GetUserDataByKeyPrefixInDB, - database_.get(), base::ThreadTaskRunnerHandle::Get(), + database_.get(), + base::SequencedTaskRunner::GetCurrentDefault(), registration_id, key_prefix, std::move(callback))); } @@ -898,7 +900,8 @@ database_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ServiceWorkerStorage::GetUserKeysAndDataByKeyPrefixInDB, - database_.get(), base::ThreadTaskRunnerHandle::Get(), + database_.get(), + base::SequencedTaskRunner::GetCurrentDefault(), registration_id, key_prefix, std::move(callback))); } @@ -1025,7 +1028,8 @@ database_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ServiceWorkerStorage::GetUserDataForAllRegistrationsInDB, - database_.get(), base::ThreadTaskRunnerHandle::Get(), key, + database_.get(), + base::SequencedTaskRunner::GetCurrentDefault(), key, std::move(callback))); } @@ -1062,8 +1066,8 @@ FROM_HERE, base::BindOnce( &ServiceWorkerStorage::GetUserDataForAllRegistrationsByKeyPrefixInDB, - database_.get(), base::ThreadTaskRunnerHandle::Get(), key_prefix, - std::move(callback))); + database_.get(), base::SequencedTaskRunner::GetCurrentDefault(), + key_prefix, std::move(callback))); } void ServiceWorkerStorage::ClearUserDataForAllRegistrationsByKeyPrefix( @@ -1292,9 +1296,9 @@ void ServiceWorkerStorage::GetPurgeableResourceIdsForTest( ResourceIdsCallback callback) { database_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&GetPurgeableResourceIdsFromDB, database_.get(), - base::ThreadTaskRunnerHandle::Get(), std::move(callback))); + FROM_HERE, base::BindOnce(&GetPurgeableResourceIdsFromDB, database_.get(), + base::SequencedTaskRunner::GetCurrentDefault(), + std::move(callback))); } void ServiceWorkerStorage::GetUncommittedResourceIdsForTest( @@ -1302,7 +1306,8 @@ database_task_runner_->PostTask( FROM_HERE, base::BindOnce(&GetUncommittedResourceIdsFromDB, database_.get(), - base::ThreadTaskRunnerHandle::Get(), std::move(callback))); + base::SequencedTaskRunner::GetCurrentDefault(), + std::move(callback))); } void ServiceWorkerStorage::LazyInitialize(base::OnceClosure callback) { @@ -1318,7 +1323,7 @@ database_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ReadInitialDataFromDB, database_.get(), - base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunner::GetCurrentDefault(), base::BindOnce(&ServiceWorkerStorage::DidReadInitialData, weak_factory_.GetWeakPtr()))); } @@ -1532,7 +1537,7 @@ FROM_HERE, base::BindOnce( &ServiceWorkerStorage::CollectStaleResourcesFromDB, database_.get(), - base::ThreadTaskRunnerHandle::Get(), + base::SequencedTaskRunner::GetCurrentDefault(), base::BindOnce(&ServiceWorkerStorage::DidCollectStaleResources, weak_factory_.GetWeakPtr()))); }
diff --git a/components/services/storage/service_worker/service_worker_storage_control_impl.cc b/components/services/storage/service_worker/service_worker_storage_control_impl.cc index 0453938..40d163b 100644 --- a/components/services/storage/service_worker/service_worker_storage_control_impl.cc +++ b/components/services/storage/service_worker/service_worker_storage_control_impl.cc
@@ -80,6 +80,25 @@ mojo::ReceiverSet<mojom::ServiceWorkerLiveVersionRef> receivers_; }; +// static +mojo::SelfOwnedReceiverRef<mojom::ServiceWorkerStorageControl> +ServiceWorkerStorageControlImpl::Create( + mojo::PendingReceiver<mojom::ServiceWorkerStorageControl> receiver, + const base::FilePath& user_data_directory, + scoped_refptr<base::SequencedTaskRunner> database_task_runner) { + return mojo::MakeSelfOwnedReceiver( + base::WrapUnique(new ServiceWorkerStorageControlImpl( + user_data_directory, std::move(database_task_runner))), + std::move(receiver)); +} + +ServiceWorkerStorageControlImpl::ServiceWorkerStorageControlImpl( + const base::FilePath& user_data_directory, + scoped_refptr<base::SequencedTaskRunner> database_task_runner) + : storage_(ServiceWorkerStorage::Create(user_data_directory, + std::move(database_task_runner))), + receiver_(this) {} + ServiceWorkerStorageControlImpl::ServiceWorkerStorageControlImpl( const base::FilePath& user_data_directory, scoped_refptr<base::SequencedTaskRunner> database_task_runner,
diff --git a/components/services/storage/service_worker/service_worker_storage_control_impl.h b/components/services/storage/service_worker/service_worker_storage_control_impl.h index 31574d8..5e552ce 100644 --- a/components/services/storage/service_worker/service_worker_storage_control_impl.h +++ b/components/services/storage/service_worker/service_worker_storage_control_impl.h
@@ -15,6 +15,7 @@ #include "components/services/storage/service_worker/service_worker_storage.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" namespace blink { class StorageKey; @@ -26,11 +27,24 @@ // This class wraps ServiceWorkerStorage to implement mojo interface defined by // the storage service, i.e., ServiceWorkerStorageControl. +// If kServiceWorkerStorageControlOnThreadPool is enabled, +// ServiceWorkerStorageControlImpl is created on database_task_runner (thread +// pool) and retained by mojo::SelfOwnedReceiver. If +// kServiceWorkerStorageControlOnIOThread is enabled on Android, +// ServiceWorkerStorageControlImpl is created on the IO thread and owned by +// PartitionImpl. Otherwise, this is created on the UI thread and owned by +// ServiceWorkerContextWrapper. In the near future, +// kServiceWorkerStorageControlOnThreadPool will be the default for all +// platforms. // TODO(crbug.com/1055677): Merge this implementation into ServiceWorkerStorage // and move the merged class to components/services/storage. class ServiceWorkerStorageControlImpl : public mojom::ServiceWorkerStorageControl { public: + static mojo::SelfOwnedReceiverRef<mojom::ServiceWorkerStorageControl> Create( + mojo::PendingReceiver<mojom::ServiceWorkerStorageControl> receiver, + const base::FilePath& user_data_directory, + scoped_refptr<base::SequencedTaskRunner> database_task_runner); ServiceWorkerStorageControlImpl( const base::FilePath& user_data_directory, scoped_refptr<base::SequencedTaskRunner> database_task_runner, @@ -48,6 +62,9 @@ void LazyInitializeForTest(); private: + ServiceWorkerStorageControlImpl( + const base::FilePath& user_data_directory, + scoped_refptr<base::SequencedTaskRunner> database_task_runner); // mojom::ServiceWorkerStorageControl implementations: void Disable(DisableCallback callback) override; void Delete(DeleteCallback callback) override;
diff --git a/components/signin/core/browser/account_reconcilor.h b/components/signin/core/browser/account_reconcilor.h index 8011060c..bfa3907 100644 --- a/components/signin/core/browser/account_reconcilor.h +++ b/components/signin/core/browser/account_reconcilor.h
@@ -214,6 +214,8 @@ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorMiceTest, AccountReconcilorStateScheduled); FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceTest, + ClearPrimaryAccountNotAllowed); + FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceTest, DiceTokenServiceRegistration); FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceTest, DiceReconcileWithoutSignin);
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc index 81d946c..0f89758 100644 --- a/components/signin/core/browser/account_reconcilor_unittest.cc +++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -177,7 +177,7 @@ case signin::AccountConsistencyMethod::kDice: #if BUILDFLAG(ENABLE_DICE_SUPPORT) return std::make_unique<signin::DiceAccountReconcilorDelegate>( - identity_manager); + identity_manager, client); #else NOTREACHED(); return nullptr; @@ -1084,6 +1084,32 @@ delete; }; +TEST_F(AccountReconcilorDiceTest, ClearPrimaryAccountNotAllowed) { + EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()).Times(1); + EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(testing::_)) + .Times(0); + + test_signin_client()->set_is_clear_primary_account_allowed( + SigninClient::SignoutDecision::CLEAR_PRIMARY_ACCOUNT_DISALLOWED); + signin::SetListAccountsResponseOneAccount(kFakeEmail, kFakeGaiaId, + &test_url_loader_factory_); + identity_test_env()->MakePrimaryAccountAvailable( + kFakeEmail, signin::ConsentLevel::kSignin); + identity_test_env()->SetInvalidRefreshTokenForPrimaryAccount(); + EXPECT_TRUE(identity_test_env()->identity_manager()->HasPrimaryAccount( + signin::ConsentLevel::kSignin)); + + AccountReconcilor* reconcilor = GetMockReconcilor(); + reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange); + ASSERT_TRUE(reconcilor->is_reconcile_started_); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(reconcilor->is_reconcile_started_); + testing::Mock::VerifyAndClearExpectations(GetMockReconcilor()); + + EXPECT_TRUE(identity_test_env()->identity_manager()->HasPrimaryAccount( + signin::ConsentLevel::kSignin)); +} + // Tests that the AccountReconcilor is always registered. TEST_F(AccountReconcilorDiceTest, DiceTokenServiceRegistration) { AccountReconcilor* reconcilor = GetMockReconcilor();
diff --git a/components/signin/core/browser/dice_account_reconcilor_delegate.cc b/components/signin/core/browser/dice_account_reconcilor_delegate.cc index acba02fdc..6a74a8a 100644 --- a/components/signin/core/browser/dice_account_reconcilor_delegate.cc +++ b/components/signin/core/browser/dice_account_reconcilor_delegate.cc
@@ -11,22 +11,46 @@ #include "base/metrics/histogram_macros.h" #include "base/ranges/algorithm.h" #include "components/prefs/pref_service.h" +#include "components/signin/public/base/consent_level.h" #include "components/signin/public/base/signin_client.h" +#include "components/signin/public/base/signin_metrics.h" #include "components/signin/public/base/signin_pref_names.h" #include "components/signin/public/identity_manager/accounts_mutator.h" #include "components/signin/public/identity_manager/identity_manager.h" +#include "components/signin/public/identity_manager/primary_account_mutator.h" namespace signin { // Revokes tokens for all accounts in chrome_accounts but the primary account. void RevokeAllSecondaryTokens( IdentityManager* identity_manager, + ConsentLevel consent_level, signin_metrics::SourceForRefreshTokenOperation source, + signin_metrics::ProfileSignout maybe_signout_source, bool revoke_only_if_in_error) { + // If |consent_level| is sync but there is only a primary account with Signin + // consent, it must be revoked. + bool should_revoke_primary_account = + consent_level == ConsentLevel::kSync && + !identity_manager->HasPrimaryAccount(ConsentLevel::kSync) && + identity_manager->HasPrimaryAccount(ConsentLevel::kSignin) && + (!revoke_only_if_in_error || + identity_manager->HasAccountWithRefreshTokenInPersistentErrorState( + identity_manager->GetPrimaryAccountId(ConsentLevel::kSignin))); + + if (should_revoke_primary_account) { + // The primary account should be revoked by calling |ClearPrimaryAccount|. + identity_manager->GetPrimaryAccountMutator()->ClearPrimaryAccount( + maybe_signout_source, signin_metrics::SignoutDelete::kIgnoreMetric); + DCHECK(identity_manager->GetAccountsWithRefreshTokens().empty()); + return; + } // The sync account should not be removed but put in a paused state, therefore - // this function excludes only the primary account with sync consent. + // this function excludes the primary account with sync consent. In some + // cases, removing the primary account regardless of the consent level is not + // allowed (e.g. cloud-managed enterprise profiles). CoreAccountId primary_account = - identity_manager->GetPrimaryAccountId(ConsentLevel::kSync); + identity_manager->GetPrimaryAccountId(consent_level); auto* accounts_mutator = identity_manager->GetAccountsMutator(); for (const CoreAccountInfo& account_info : @@ -50,8 +74,9 @@ } DiceAccountReconcilorDelegate::DiceAccountReconcilorDelegate( - IdentityManager* identity_manager) - : identity_manager_(identity_manager) {} + IdentityManager* identity_manager, + SigninClient* signin_client) + : identity_manager_(identity_manager), signin_client_(signin_client) {} DiceAccountReconcilorDelegate::~DiceAccountReconcilorDelegate() = default; bool DiceAccountReconcilorDelegate::IsReconcileEnabled() const { @@ -155,19 +180,31 @@ return false; } - RevokeAllSecondaryTokens(identity_manager_, - signin_metrics::SourceForRefreshTokenOperation:: - kAccountReconcilor_Reconcile, - /*revoke_only_if_in_error=*/false); + RevokeAllSecondaryTokens( + identity_manager_, GetConsentLevelForPrimaryAccount(), + signin_metrics::SourceForRefreshTokenOperation:: + kAccountReconcilor_Reconcile, + signin_metrics::ProfileSignout::ACCOUNT_RECONCILOR_RECONCILE, + /*revoke_only_if_in_error=*/false); return true; } +ConsentLevel DiceAccountReconcilorDelegate::GetConsentLevelForPrimaryAccount() + const { + // In some cases, clearing the primary account is not allowed regardless of + // the consent level (e.g. cloud-managed profiles). In these cases, the dice + // account reconcilor delegate should never remove the primary account + // regardless of the consent. + return signin_client_->IsClearPrimaryAccountAllowed() ? ConsentLevel::kSync + : ConsentLevel::kSignin; +} + bool DiceAccountReconcilorDelegate::ShouldRevokeTokensBeforeMultilogin( const std::vector<CoreAccountId>& chrome_accounts, const std::vector<gaia::ListedAccount>& gaia_accounts, bool first_execution) const { - CoreAccountId primary_account = - identity_manager_->GetPrimaryAccountId(ConsentLevel::kSync); + CoreAccountId primary_account = identity_manager_->GetPrimaryAccountId( + GetConsentLevelForPrimaryAccount()); bool primary_has_error = identity_manager_->HasAccountWithRefreshTokenInPersistentErrorState( @@ -179,8 +216,8 @@ return false; // On first execution, it's generally OK to reorder accounts. Only logout if - // the Sync account needs to be removed from the first position in cookies (it - // would be unacceptable to swap another account there). + // the primary account needs to be removed from the first position in cookies + // (it would be unacceptable to swap another account there). if (first_execution) { return !primary_account.empty() && primary_has_error && gaia_accounts[0].id == primary_account && gaia_accounts[0].valid; @@ -265,39 +302,46 @@ void DiceAccountReconcilorDelegate:: RevokeSecondaryTokensBeforeReconcileIfNeeded() { RevokeAllSecondaryTokens(identity_manager_, + GetConsentLevelForPrimaryAccount(), signin_metrics::SourceForRefreshTokenOperation:: kAccountReconcilor_GaiaCookiesUpdated, + signin_metrics::ProfileSignout::GAIA_COOKIE_UPDATED, /*revoke_only_if_in_error=*/true); } void DiceAccountReconcilorDelegate::OnAccountsCookieDeletedByUserAction( bool synced_data_deletion_in_progress) { + ConsentLevel consent_level = GetConsentLevelForPrimaryAccount(); // Revoke secondary tokens to avoid reconcilor rebuilding cookies. - RevokeAllSecondaryTokens(identity_manager_, - signin_metrics::SourceForRefreshTokenOperation:: - kAccountReconcilor_GaiaCookiesDeletedByUser, - /*revoke_only_if_in_error=*/false); + RevokeAllSecondaryTokens( + identity_manager_, consent_level, + signin_metrics::SourceForRefreshTokenOperation:: + kAccountReconcilor_GaiaCookiesDeletedByUser, + signin_metrics::ProfileSignout::USER_DELETED_ACCOUNT_COOKIES, + /*revoke_only_if_in_error=*/false); - if (!identity_manager_->HasPrimaryAccount(ConsentLevel::kSync)) + if (!identity_manager_->HasPrimaryAccount(consent_level)) return; - DCHECK_EQ(GetConsentLevelForPrimaryAccount(), ConsentLevel::kSync); - CoreAccountId primary_sync_account = - identity_manager_->GetPrimaryAccountId(ConsentLevel::kSync); - - // Sync account should be paused if the account cookie is deleted by user - // action. If sync data deletion in progress, avoid invalidating the sync - // account unless it is already in a persistent error state. This is needed to - // ensure the data gets deleted from the google account. - if (!synced_data_deletion_in_progress || - identity_manager_->HasAccountWithRefreshTokenInPersistentErrorState( - primary_sync_account)) { - // Invalidate the primary token, but do not revoke it. - auto* accounts_mutator = identity_manager_->GetAccountsMutator(); - accounts_mutator->InvalidateRefreshTokenForPrimaryAccount( - signin_metrics::SourceForRefreshTokenOperation:: - kAccountReconcilor_GaiaCookiesDeletedByUser); + if (synced_data_deletion_in_progress && + identity_manager_->HasPrimaryAccount(ConsentLevel::kSync)) { + // If sync data deletion in progress, avoid invalidating the sync + // account unless it is already in a persistent error state. This is needed + // to ensure the data gets deleted from the google account. + CoreAccountId primary_sync_account = + identity_manager_->GetPrimaryAccountId(ConsentLevel::kSync); + if (!identity_manager_->HasAccountWithRefreshTokenInPersistentErrorState( + primary_sync_account)) { + return; + } } + + // The primary account should be paused if the account cookie is deleted by + // user action. + auto* accounts_mutator = identity_manager_->GetAccountsMutator(); + accounts_mutator->InvalidateRefreshTokenForPrimaryAccount( + signin_metrics::SourceForRefreshTokenOperation:: + kAccountReconcilor_GaiaCookiesDeletedByUser); } void DiceAccountReconcilorDelegate::OnReconcileFinished(
diff --git a/components/signin/core/browser/dice_account_reconcilor_delegate.h b/components/signin/core/browser/dice_account_reconcilor_delegate.h index 253d90c0..33ac57a 100644 --- a/components/signin/core/browser/dice_account_reconcilor_delegate.h +++ b/components/signin/core/browser/dice_account_reconcilor_delegate.h
@@ -5,8 +5,10 @@ #ifndef COMPONENTS_SIGNIN_CORE_BROWSER_DICE_ACCOUNT_RECONCILOR_DELEGATE_H_ #define COMPONENTS_SIGNIN_CORE_BROWSER_DICE_ACCOUNT_RECONCILOR_DELEGATE_H_ +#include "base/memory/raw_ptr.h" #include "components/signin/core/browser/account_reconcilor_delegate.h" -#include "components/signin/public/base/account_consistency_method.h" +#include "components/signin/public/base/consent_level.h" +#include "components/signin/public/base/signin_client.h" namespace signin { @@ -15,7 +17,8 @@ // AccountReconcilorDelegate specialized for Dice. class DiceAccountReconcilorDelegate : public AccountReconcilorDelegate { public: - explicit DiceAccountReconcilorDelegate(IdentityManager* identity_manager); + DiceAccountReconcilorDelegate(IdentityManager* identity_manager, + SigninClient* signin_client); DiceAccountReconcilorDelegate(const DiceAccountReconcilorDelegate&) = delete; DiceAccountReconcilorDelegate& operator=( @@ -34,6 +37,7 @@ const std::vector<CoreAccountId>& chrome_accounts, const std::vector<gaia::ListedAccount>& gaia_accounts, bool first_execution) override; + ConsentLevel GetConsentLevelForPrimaryAccount() const override; private: // Possible inconsistency reasons between tokens and gaia cookies. @@ -110,6 +114,7 @@ bool first_execution) const; const raw_ptr<IdentityManager> identity_manager_; + const raw_ptr<SigninClient> signin_client_; // Last known "first account". Used when cookies are lost as a best guess. CoreAccountId last_known_first_account_;
diff --git a/components/signin/core/browser/resources/signin_internals.js b/components/signin/core/browser/resources/signin_internals.js index 0eba1fe..aafd1f3 100644 --- a/components/signin/core/browser/resources/signin_internals.js +++ b/components/signin/core/browser/resources/signin_internals.js
@@ -8,7 +8,7 @@ import 'chrome://resources/js/jstemplate_compiled.js'; import './strings.m.js'; -import {addWebUIListener, sendWithPromise} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener, sendWithPromise} from 'chrome://resources/js/cr.js'; import {$} from 'chrome://resources/js/util.js'; // TODO(vishwath): This function is identical to the one in sync_internals.js @@ -80,8 +80,8 @@ // On load, do an initial refresh and register refreshSigninInfo to be invoked // whenever we get new signin information from SigninInternalsUI. function onLoad() { - addWebUIListener('signin-info-changed', refreshSigninInfo); - addWebUIListener('update-cookie-accounts', updateCookieAccounts); + addWebUiListener('signin-info-changed', refreshSigninInfo); + addWebUiListener('update-cookie-accounts', updateCookieAccounts); sendWithPromise('getSigninInfo').then(refreshSigninInfo); }
diff --git a/components/signin/internal/identity_manager/accounts_mutator_impl.cc b/components/signin/internal/identity_manager/accounts_mutator_impl.cc index d468f3d..1fd8a0ea 100644 --- a/components/signin/internal/identity_manager/accounts_mutator_impl.cc +++ b/components/signin/internal/identity_manager/accounts_mutator_impl.cc
@@ -100,9 +100,9 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) NOTREACHED(); #endif - DCHECK(primary_account_manager_->HasPrimaryAccount(ConsentLevel::kSync)); + DCHECK(primary_account_manager_->HasPrimaryAccount(ConsentLevel::kSignin)); CoreAccountInfo primary_account_info = - primary_account_manager_->GetPrimaryAccountInfo(ConsentLevel::kSync); + primary_account_manager_->GetPrimaryAccountInfo(ConsentLevel::kSignin); AddOrUpdateAccount(primary_account_info.gaia, primary_account_info.email, GaiaConstants::kInvalidRefreshToken, primary_account_info.is_under_advanced_protection, source);
diff --git a/components/signin/public/base/signin_client.cc b/components/signin/public/base/signin_client.cc index 337a161..50f9b3a 100644 --- a/components/signin/public/base/signin_client.cc +++ b/components/signin/public/base/signin_client.cc
@@ -10,3 +10,7 @@ // Allow sign out to continue. std::move(on_signout_decision_reached).Run(SignoutDecision::ALLOW); } + +bool SigninClient::IsClearPrimaryAccountAllowed() const { + return true; +}
diff --git a/components/signin/public/base/signin_client.h b/components/signin/public/base/signin_client.h index 9b9cb74..c694cc46 100644 --- a/components/signin/public/base/signin_client.h +++ b/components/signin/public/base/signin_client.h
@@ -13,6 +13,7 @@ #include "build/chromeos_buildflags.h" #include "components/keyed_service/core/keyed_service.h" #include "components/signin/public/base/account_consistency_method.h" +#include "components/signin/public/base/consent_level.h" #include "components/signin/public/base/signin_metrics.h" #include "google_apis/gaia/core_account_id.h" #include "google_apis/gaia/gaia_auth_fetcher.h" @@ -68,6 +69,10 @@ // Returns the CookieManager for the client. virtual network::mojom::CookieManager* GetCookieManager() = 0; + // Returns true if clearing the primary account is allowed regardless of the + // consent level. + virtual bool IsClearPrimaryAccountAllowed() const; + // Called before Google sign-out started. Implementers must run the // |on_signout_decision_reached|, passing a SignoutDecision to allow/disallow // sign-out to continue. When to disallow sign-out is implementation specific.
diff --git a/components/signin/public/base/signin_metrics.h b/components/signin/public/base/signin_metrics.h index 19ed752..2dd330a 100644 --- a/components/signin/public/base/signin_metrics.h +++ b/components/signin/public/base/signin_metrics.h
@@ -77,6 +77,10 @@ ACCOUNT_EMAIL_UPDATED = 20, // User clicked on sign-out from the clear browsing data page. USER_CLICKED_SIGNOUT_FROM_CLEAR_BROWSING_DATA_PAGE = 21, + // Profile Signout during reconciliation triggered by a Gaia cookie update. + GAIA_COOKIE_UPDATED = 22, + // Profile Signout during reconciliation. + ACCOUNT_RECONCILOR_RECONCILE = 23, // Keep this as the last enum. NUM_PROFILE_SIGNOUT_METRICS, };
diff --git a/components/signin/public/base/test_signin_client.cc b/components/signin/public/base/test_signin_client.cc index 3d2a12d..ffbec7f 100644 --- a/components/signin/public/base/test_signin_client.cc +++ b/components/signin/public/base/test_signin_client.cc
@@ -34,6 +34,10 @@ return pref_service_; } +bool TestSigninClient::IsClearPrimaryAccountAllowed() const { + return is_clear_primary_account_allowed_ == SignoutDecision::ALLOW; +} + void TestSigninClient::PreSignOut( base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached, signin_metrics::ProfileSignout signout_source_metric) {
diff --git a/components/signin/public/base/test_signin_client.h b/components/signin/public/base/test_signin_client.h index b27b577..fab5da91 100644 --- a/components/signin/public/base/test_signin_client.h +++ b/components/signin/public/base/test_signin_client.h
@@ -51,6 +51,10 @@ // once there is a unit test that requires it. PrefService* GetPrefs() override; + // Returns true if clear primary account is allowed regardless of the consent + // level. + bool IsClearPrimaryAccountAllowed() const override; + // Allow or disallow continuation of sign-out depending on value of // |is_clear_primary_account_allowed_|; void PreSignOut(
diff --git a/components/signin/public/identity_manager/identity_test_utils.cc b/components/signin/public/identity_manager/identity_test_utils.cc index 385afe72..b03963b1 100644 --- a/components/signin/public/identity_manager/identity_test_utils.cc +++ b/components/signin/public/identity_manager/identity_test_utils.cc
@@ -197,9 +197,9 @@ void SetInvalidRefreshTokenForPrimaryAccount( IdentityManager* identity_manager) { - DCHECK(identity_manager->HasPrimaryAccount(ConsentLevel::kSync)); + DCHECK(identity_manager->HasPrimaryAccount(ConsentLevel::kSignin)); CoreAccountId account_id = - identity_manager->GetPrimaryAccountId(ConsentLevel::kSync); + identity_manager->GetPrimaryAccountId(ConsentLevel::kSignin); SetInvalidRefreshTokenForAccount(identity_manager, account_id); }
diff --git a/components/translate/translate_internals/translate_internals.js b/components/translate/translate_internals/translate_internals.js index ff05ea4..9c248385 100644 --- a/components/translate/translate_internals/translate_internals.js +++ b/components/translate/translate_internals/translate_internals.js
@@ -9,7 +9,7 @@ import './strings.m.js'; import 'chrome://resources/cr_elements/cr_tab_box/cr_tab_box.js'; -import {addWebUIListener} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener} from 'chrome://resources/js/cr.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {$} from 'chrome://resources/js/util.js'; @@ -550,13 +550,13 @@ } function addMessageHandlers() { - addWebUIListener('languageDetectionInfoAdded', onLanguageDetectionInfoAdded); - addWebUIListener('prefsUpdated', onPrefsUpdated); - addWebUIListener('supportedLanguagesUpdated', onSupportedLanguagesUpdated); - addWebUIListener('countryUpdated', onCountryUpdated); - addWebUIListener('translateErrorDetailsAdded', onTranslateErrorDetailsAdded); - addWebUIListener('translateEventDetailsAdded', onTranslateEventDetailsAdded); - addWebUIListener('translateInitDetailsAdded', onTranslateInitDetailsAdded); + addWebUiListener('languageDetectionInfoAdded', onLanguageDetectionInfoAdded); + addWebUiListener('prefsUpdated', onPrefsUpdated); + addWebUiListener('supportedLanguagesUpdated', onSupportedLanguagesUpdated); + addWebUiListener('countryUpdated', onCountryUpdated); + addWebUiListener('translateErrorDetailsAdded', onTranslateErrorDetailsAdded); + addWebUiListener('translateEventDetailsAdded', onTranslateEventDetailsAdded); + addWebUiListener('translateInitDetailsAdded', onTranslateInitDetailsAdded); } /**
diff --git a/components/user_actions_ui/resources/user_actions.js b/components/user_actions_ui/resources/user_actions.js index 11089436e..3ae4537 100644 --- a/components/user_actions_ui/resources/user_actions.js +++ b/components/user_actions_ui/resources/user_actions.js
@@ -12,7 +12,7 @@ * callbacks from the C++ code saying that a new user action was seen. */ -import {addWebUIListener} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener} from 'chrome://resources/js/cr.js'; import {$} from 'chrome://resources/js/util.js'; /** @@ -33,7 +33,7 @@ } document.addEventListener('DOMContentLoaded', function() { - addWebUIListener('user-action', observeUserAction); + addWebUiListener('user-action', observeUserAction); // <if expr="not is_ios"> chrome.send('pageLoaded'); // </if>
diff --git a/components/version_ui/resources/about_version.js b/components/version_ui/resources/about_version.js index 8826aaa..5d7f315 100644 --- a/components/version_ui/resources/about_version.js +++ b/components/version_ui/resources/about_version.js
@@ -11,7 +11,7 @@ // </if> import './strings.m.js'; -import {addWebUIListener, sendWithPromise} from 'chrome://resources/js/cr.m.js'; +import {addWebUIListener, sendWithPromise} from 'chrome://resources/js/cr.js'; import {$} from 'chrome://resources/js/util.js'; /**
diff --git a/components/webapps/browser/BUILD.gn b/components/webapps/browser/BUILD.gn index b1229ca..9707614 100644 --- a/components/webapps/browser/BUILD.gn +++ b/components/webapps/browser/BUILD.gn
@@ -46,6 +46,7 @@ "//base", "//components/back_forward_cache", "//components/content_settings/core/browser", + "//components/password_manager/content/common", "//components/permissions", "//components/security_state/core", "//components/site_engagement/content",
diff --git a/components/webapps/browser/DEPS b/components/webapps/browser/DEPS index 81d1c429..0cecda19 100644 --- a/components/webapps/browser/DEPS +++ b/components/webapps/browser/DEPS
@@ -3,6 +3,7 @@ "+components/content_settings", "+components/infobars", "+components/messages", + "+components/password_manager", "+components/permissions", "+components/prefs", "+components/security_state/core",
diff --git a/components/webapps/browser/banners/app_banner_manager.cc b/components/webapps/browser/banners/app_banner_manager.cc index d6029d7b..91039e4 100644 --- a/components/webapps/browser/banners/app_banner_manager.cc +++ b/components/webapps/browser/banners/app_banner_manager.cc
@@ -20,6 +20,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "components/back_forward_cache/back_forward_cache_disable.h" +#include "components/password_manager/content/common/web_ui_constants.h" #include "components/site_engagement/content/site_engagement_service.h" #include "components/webapps/browser/banners/app_banner_metrics.h" #include "components/webapps/browser/banners/app_banner_settings_helper.h" @@ -263,9 +264,12 @@ if (render_frame_host && !render_frame_host->IsInPrimaryMainFrame()) return true; - // There is never a need to trigger a banner for a WebUI page. - if (content::HasWebUIScheme(url)) + // There is never a need to trigger a banner for a WebUI page, except + // for PasswordManager WebUI. + if (content::HasWebUIScheme(url) && + (url.host() != password_manager::kChromeUIPasswordManagerHost)) { return true; + } return false; } @@ -381,6 +385,23 @@ manifest_ = data.manifest->Clone(); manifest_id_ = blink::GetIdFromManifest(manifest()); + // Skip checks for PasswordManager WebUI page. + if (content::HasWebUIScheme(validated_url_) && + (validated_url_.host() == + password_manager::kChromeUIPasswordManagerHost)) { + if (IsWebAppConsideredInstalled()) { + TrackDisplayEvent(DISPLAY_EVENT_INSTALLED_PREVIOUSLY); + SetInstallableWebAppCheckResult( + InstallableWebAppCheckResult::kNo_AlreadyInstalled); + Stop(ALREADY_INSTALLED); + } else { + SetInstallableWebAppCheckResult( + InstallableWebAppCheckResult::kYes_ByUserRequest); + Stop(NO_ERROR_DETECTED); + } + return; + } + PerformInstallableChecks(); }
diff --git a/content/browser/cross_origin_opener_policy_browsertest.cc b/content/browser/cross_origin_opener_policy_browsertest.cc index b2e80c32..efbdd0f 100644 --- a/content/browser/cross_origin_opener_policy_browsertest.cc +++ b/content/browser/cross_origin_opener_policy_browsertest.cc
@@ -120,6 +120,30 @@ return http_response; } +std::unique_ptr<net::test_server::HttpResponse> +RedirectToTargetOnSecondNavigation( + unsigned int& navigation_counter, + const net::test_server::HttpRequest& request) { + ++navigation_counter; + if (navigation_counter == 1) { + auto http_response = + std::make_unique<net::test_server::BasicHttpResponse>(); + http_response->set_code(net::HttpStatusCode::HTTP_OK); + return http_response; + } + + GURL request_url = request.GetURL(); + std::string dest = + base::UnescapeBinaryURLComponent(request_url.query_piece()); + net::test_server::RequestQuery query = + net::test_server::ParseQuery(request_url); + + auto http_response = std::make_unique<net::test_server::BasicHttpResponse>(); + http_response->set_code(net::HttpStatusCode::HTTP_FOUND); + http_response->AddCustomHeader("Location", dest); + return http_response; +} + class CrossOriginOpenerPolicyBrowserTest : public ContentBrowserTest, public ::testing::WithParamInterface<std::tuple<std::string, bool>> { @@ -184,6 +208,13 @@ "/redirect-with-coop-coep-headers", base::BindRepeating(CrossOriginIsolatedCrossOriginRedirectHandler))); + unsigned int navigation_counter = 0; + https_server_.RegisterDefaultHandler(base::BindRepeating( + &net::test_server::HandlePrefixedRequest, + "/redirect-to-target-on-second-navigation", + base::BindRepeating(&RedirectToTargetOnSecondNavigation, + base::OwnedRef(navigation_counter)))); + ASSERT_TRUE(https_server()->Start()); } @@ -3276,6 +3307,33 @@ EXPECT_FALSE(WaitForLoadStop(web_contents())); } +// Regression test for https://crbug.com/1374705. +IN_PROC_BROWSER_TEST_P(CrossOriginOpenerPolicyBrowserTest, + ReloadRedirectsToCoopPage) { + GURL coop_page( + https_server()->GetURL("a.test", + "/set-header?" + "Cross-Origin-Opener-Policy: same-origin")); + GURL redirect_page(https_server()->GetURL( + "a.test", + "/redirect-to-target-on-second-navigation?" + coop_page.spec())); + + // Navigate to the redirect page. On the first navigation, this is a simple + // empty page with no headers. + EXPECT_TRUE(NavigateToURL(shell(), redirect_page)); + scoped_refptr<SiteInstanceImpl> main_si = + current_frame_host()->GetSiteInstance(); + EXPECT_EQ(current_frame_host()->GetLastCommittedURL(), redirect_page); + + // Reload. This time we should be redirected to a COOP: same-origin page. + ReloadBlockUntilNavigationsComplete(shell(), 1); + EXPECT_EQ(current_frame_host()->GetLastCommittedURL(), coop_page); + + // We should have swapped BrowsingInstance. + EXPECT_FALSE( + main_si->IsRelatedSiteInstance(current_frame_host()->GetSiteInstance())); +} + IN_PROC_BROWSER_TEST_P(CrossOriginOpenerPolicyBrowserTest, CrossOriginRedirectHasProperCrossOriginIsolatedState) { GURL non_isolated_page(
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc index 61c67e9..f20b649a 100644 --- a/content/browser/renderer_host/render_frame_host_manager.cc +++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -1654,25 +1654,6 @@ if (is_same_document) return ShouldSwapBrowsingInstance::kNo_SameDocumentNavigation; - // If new_entry already has a SiteInstance, assume it is correct. We only - // need to force a swap if it is in a different BrowsingInstance. - if (destination_instance) { - // If we are doing an history navigation/reload and end up failing, it might - // not be suitable to host the error page in the original SiteInstance. - // Error pages have a Cross-Origin-Opener-Policy of 'unsafe-none' and might - // end up in a different BrowsingInstance. - if (is_failure && cross_origin_opener_policy_mismatch) - return ShouldSwapBrowsingInstance::kYes_ForceSwap; - - bool should_swap = !destination_instance->IsRelatedSiteInstance( - render_frame_host_->GetSiteInstance()); - if (should_swap) { - return ShouldSwapBrowsingInstance::kYes_ForceSwap; - } else { - return ShouldSwapBrowsingInstance::kNo_AlreadyHasMatchingBrowsingInstance; - } - } - // Check for reasons to swap processes even if we are in a process model that // doesn't usually swap (e.g., process-per-tab). Any time we return true, // the new URL will be rendered in a new SiteInstance AND BrowsingInstance. @@ -1771,26 +1752,6 @@ return ShouldSwapBrowsingInstance::kYes_ForceSwap; } - // If this is a cross-site navigation, we may be able to force a - // BrowsingInstance swap to avoid unneeded process sharing. This is done for - // certain main frame browser-initiated navigations where we can't use - // |source_instance| and we don't need to preserve scripting - // relationship for it (for isolated error pages). - // See https://crbug.com/803367. - bool is_for_isolated_error_page = - is_failure && frame_tree_node_->IsErrorPageIsolationEnabled(); - - if (current_instance->HasSite() && - !render_frame_host_->IsNavigationSameSite(destination_url_info) && - !CanUseSourceSiteInstance(destination_url_info, source_instance, - was_server_redirect, is_failure) && - !is_for_isolated_error_page && - IsBrowsingInstanceSwapAllowedForPageTransition(transition, - destination_url) && - render_frame_host_->has_committed_any_navigation()) { - return ShouldSwapBrowsingInstance::kYes_ForceSwap; - } - // If the navigation should end up in a different StoragePartition, create a // new BrowsingInstance, as we can only have one StoragePartition per // BrowsingInstance. @@ -1807,6 +1768,53 @@ return ShouldSwapBrowsingInstance::kYes_ForceSwap; } + // When doing a history navigation, we cannot assume that the page will behave + // in the same way as it did previously. It could change headers, lead to an + // error page, etc. We only check the destination_instance once we're done + // verifying that up-to-date security reasons do not require a + // BrowsingInstance swap. On the other hand we should use the + // destination_instance if suitable instead of swapping to a new + // BrowsingInstance. This is why this block is after security checks, but + // before proactive BrowsingInstance swap. + if (destination_instance) { + // TODO(ahemery): We should not have to specify here if we are going to swap + // BrowsingInstance. DetermineSiteInstanceForURL will reuse the + // destination_instance unless it is unfit because of a security concern + // flagged by above blocks. This is only used by BackForwardCache metrics to + // know if we have swapped BrowsingInstance, and it would be more + // appropriate to get this information in DetermineSiteInstanceForURL. + bool should_swap = + !destination_instance->IsRelatedSiteInstance(current_instance); + if (should_swap) { + return ShouldSwapBrowsingInstance::kYes_ForceSwap; + } else { + return ShouldSwapBrowsingInstance::kNo_AlreadyHasMatchingBrowsingInstance; + } + } + + // If this is a cross-site navigation, we may be able to force a + // BrowsingInstance swap to avoid unneeded process sharing. This is done for + // certain main frame browser-initiated navigations where we can't use + // |source_instance| and we don't need to preserve scripting + // relationship for it (for isolated error pages). + // See https://crbug.com/803367. + // TODO(https://crbug.com/1366827): This should probably be considered a + // a speculative BrowsingInstance swap. It is not required for security and + // needs to be treated after the history navigation block + bool is_for_isolated_error_page = + is_failure && frame_tree_node_->IsErrorPageIsolationEnabled(); + + if (current_instance->HasSite() && + !render_frame_host_->IsNavigationSameSite(destination_url_info) && + !CanUseSourceSiteInstance(destination_url_info, source_instance, + was_server_redirect, is_failure) && + !is_for_isolated_error_page && + IsBrowsingInstanceSwapAllowedForPageTransition(transition, + destination_url) && + render_frame_host_->has_committed_any_navigation()) { + return ShouldSwapBrowsingInstance::kYes_ForceSwap; + } + // Experimental mode to swap BrowsingInstances on most navigations when there // are no other windows in the BrowsingInstance. return ShouldProactivelySwapBrowsingInstance(destination_url_info, is_reload, @@ -2246,35 +2254,42 @@ // If the entry has an instance already we should usually use it, unless it is // no longer suitable. if (dest_instance) { - // Note: The later call to IsSuitableForUrlInfo does not have context about - // error page navigations, so we cannot rely on it to return correct value - // when error pages are involved. - if (IsSiteInstanceCompatibleWithErrorIsolation( - dest_instance, *frame_tree_node_, is_failure)) { - if (IsSiteInstanceCompatibleWithWebExposedIsolation( - dest_instance, dest_url_info.web_exposed_isolation_info)) { - // TODO(nasko,creis): The check whether data: or about: URLs are allowed - // to commit in the current process should be in IsSuitableForUrlInfo. - // However, making this change has further implications and needs more - // investigation of what behavior changes. For now, use a conservative - // approach and explicitly check before calling IsSuitableForUrlInfo. - SiteInstanceImpl* dest_instance_impl = - static_cast<SiteInstanceImpl*>(dest_instance); - // Make sure that if the destination frame is sandboxed that we don't - // skip the IsSuitableForUrlInfo() check. Note that it's impossible to - // have a sandboxed parent but unsandboxed child. - bool is_data_or_about_and_not_sandboxed = - IsDataOrAbout(dest_url_info.url) && !dest_url_info.is_sandboxed; - if (is_data_or_about_and_not_sandboxed || - dest_instance_impl->IsSuitableForUrlInfo(dest_url_info)) { - // If we are forcing a swap, this should be in a different - // BrowsingInstance. - if (force_browsing_instance_swap) { - CHECK(!dest_instance->IsRelatedSiteInstance( - render_frame_host_->GetSiteInstance())); + // If we've decided that the target SiteInstance cannot be in the same + // BrowsingInstance, and that the dest_instance is, we should not reuse it. + if (!force_browsing_instance_swap || + !dest_instance->IsRelatedSiteInstance(current_instance)) { + // Note: The later call to IsSuitableForUrlInfo does not have context + // about error page navigations, so we cannot rely on it to return correct + // value when error pages are involved. + if (IsSiteInstanceCompatibleWithErrorIsolation( + dest_instance, *frame_tree_node_, is_failure)) { + if (IsSiteInstanceCompatibleWithWebExposedIsolation( + dest_instance, dest_url_info.web_exposed_isolation_info)) { + // TODO(nasko,creis): The check whether data: or about: URLs are + // allowed to commit in the current process should be in + // IsSuitableForUrlInfo. However, making this change has further + // implications and needs more investigation of what behavior changes. + // For now, use a conservative approach and explicitly check before + // calling IsSuitableForUrlInfo. + SiteInstanceImpl* dest_instance_impl = + static_cast<SiteInstanceImpl*>(dest_instance); + // Make sure that if the destination frame is sandboxed that we don't + // skip the IsSuitableForUrlInfo() check. Note that it's impossible to + // have a sandboxed parent but unsandboxed child. + bool is_data_or_about_and_not_sandboxed = + IsDataOrAbout(dest_url_info.url) && !dest_url_info.is_sandboxed; + if (is_data_or_about_and_not_sandboxed || + dest_instance_impl->IsSuitableForUrlInfo(dest_url_info)) { + // If we are forcing a swap, this should be in a different + // BrowsingInstance. + if (force_browsing_instance_swap) { + CHECK(!dest_instance->IsRelatedSiteInstance( + render_frame_host_->GetSiteInstance())); + } + AppendReason(reason, + "DetermineSiteInstanceForURL => dest_instance"); + return SiteInstanceDescriptor(dest_instance); } - AppendReason(reason, "DetermineSiteInstanceForURL => dest_instance"); - return SiteInstanceDescriptor(dest_instance); } } }
diff --git a/content/browser/resources/service_worker/serviceworker_internals.js b/content/browser/resources/service_worker/serviceworker_internals.js index d44d5e0..2b4b1cb 100644 --- a/content/browser/resources/service_worker/serviceworker_internals.js +++ b/content/browser/resources/service_worker/serviceworker_internals.js
@@ -4,17 +4,17 @@ import 'chrome://resources/js/jstemplate_compiled.js'; -import {addWebUIListener, sendWithPromise} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener, sendWithPromise} from 'chrome://resources/js/cr.js'; import {$} from 'chrome://resources/js/util.js'; function initialize() { - addWebUIListener('partition-data', onPartitionData); - addWebUIListener('running-state-changed', onRunningStateChanged); - addWebUIListener('error-reported', onErrorReported); - addWebUIListener('console-message-reported', onConsoleMessageReported); - addWebUIListener('version-state-changed', onVersionStateChanged); - addWebUIListener('registration-completed', onRegistrationCompleted); - addWebUIListener('registration-deleted', onRegistrationDeleted); + addWebUiListener('partition-data', onPartitionData); + addWebUiListener('running-state-changed', onRunningStateChanged); + addWebUiListener('error-reported', onErrorReported); + addWebUiListener('console-message-reported', onConsoleMessageReported); + addWebUiListener('version-state-changed', onVersionStateChanged); + addWebUiListener('registration-completed', onRegistrationCompleted); + addWebUiListener('registration-deleted', onRegistrationDeleted); update(); }
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc index 4a5e2f20..1d4d5a1 100644 --- a/content/browser/service_worker/service_worker_browsertest.cc +++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -394,12 +394,7 @@ void SetUpOnMainThread() override { ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); - StoragePartition* partition = shell() - ->web_contents() - ->GetBrowserContext() - ->GetDefaultStoragePartition(); - wrapper_ = static_cast<ServiceWorkerContextWrapper*>( - partition->GetServiceWorkerContext()); + SetServiceWorkerContextWrapper(); ShellContentBrowserClient::Get() ->browser_context() ->set_client_hints_controller_delegate( @@ -417,6 +412,15 @@ wrapper_ = nullptr; } + void SetServiceWorkerContextWrapper() { + StoragePartition* partition = shell() + ->web_contents() + ->GetBrowserContext() + ->GetDefaultStoragePartition(); + wrapper_ = static_cast<ServiceWorkerContextWrapper*>( + partition->GetServiceWorkerContext()); + } + // Starts the test server and navigates the renderer to an empty page. Call // this after adding all request handlers to the test server. Adding handlers // after the test server has started is not allowed. @@ -4235,4 +4239,119 @@ static_cast<int>(blink::ServiceWorkerStatusCode::kOk), 1); } +enum class ServiceWorkerBypassFetchHandlerBypassedOriginType { + kBypassed, + kNotBypassed +}; + +class ServiceWorkerBypassFetchHandlerTest + : public ServiceWorkerBrowserTest, + public testing::WithParamInterface< + ServiceWorkerBypassFetchHandlerBypassedOriginType> { + public: + ServiceWorkerBypassFetchHandlerTest() { + feature_list_.InitWithFeaturesAndParameters( + {{features::kServiceWorkerBypassFetchHandler, + {{"origins_to_bypass", "https://a.test"}}}}, + {}); + } + ~ServiceWorkerBypassFetchHandlerTest() override = default; + + void SetUpOnMainThread() override { + SetServiceWorkerContextWrapper(); + host_resolver()->AddRule("*", "127.0.0.1"); + https_server_.ServeFilesFromSourceDirectory(GetTestDataFilePath()); + https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES); + net::test_server::RegisterDefaultHandlers(&https_server_); + ASSERT_TRUE(https_server()->Start()); + } + + net::EmbeddedTestServer* https_server() { return &https_server_; } + + WebContents* web_contents() const { return shell()->web_contents(); } + + RenderFrameHost* GetPrimaryMainFrame() { + return web_contents()->GetPrimaryMainFrame(); + } + + private: + base::test::ScopedFeatureList feature_list_; + net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS}; +}; + +INSTANTIATE_TEST_SUITE_P( + All, + ServiceWorkerBypassFetchHandlerTest, + testing::Values( + ServiceWorkerBypassFetchHandlerBypassedOriginType::kBypassed, + ServiceWorkerBypassFetchHandlerBypassedOriginType::kNotBypassed)); + +IN_PROC_BROWSER_TEST_P(ServiceWorkerBypassFetchHandlerTest, UrlInAllowList) { + std::string origin; + switch (GetParam()) { + case ServiceWorkerBypassFetchHandlerBypassedOriginType::kBypassed: + origin = "a.test"; + break; + case ServiceWorkerBypassFetchHandlerBypassedOriginType::kNotBypassed: + origin = "b.test"; + break; + } + + const GURL create_service_worker_url(https_server()->GetURL( + origin, "/service_worker/create_service_worker.html")); + const GURL out_scope_url(https_server()->GetURL(origin, "/empty.html")); + const GURL in_scope_url( + https_server()->GetURL(origin, "/service_worker/empty.html")); + + // Register a service worker. + WorkerRunningStatusObserver observer1(public_context()); + EXPECT_TRUE(NavigateToURL(shell(), create_service_worker_url)); + EXPECT_EQ("DONE", + EvalJs(GetPrimaryMainFrame(), + "register('/service_worker/fetch_event_pass_through.js')")); + observer1.WaitUntilRunning(); + scoped_refptr<ServiceWorkerVersion> version = + wrapper()->GetLiveVersion(observer1.version_id()); + EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status()); + + // Stop the current running service worker. + StopServiceWorker(version.get()); + EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status()); + + // Navigate away from the service worker's scope. + EXPECT_TRUE(NavigateToURL(shell(), out_scope_url)); + EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status()); + + // This script asks the service worker what fetch events it saw. + const std::string script = R"( + (async () => { + const saw_message = new Promise(resolve => { + navigator.serviceWorker.onmessage = event => { + resolve(event.data); + }; + }); + const registration = await navigator.serviceWorker.ready; + registration.active.postMessage(''); + const message = await saw_message; + return message.length; + })(); + )"; + + // Navigate to the service worker's scope. + EXPECT_TRUE(NavigateToURL(shell(), in_scope_url)); + + switch (GetParam()) { + case ServiceWorkerBypassFetchHandlerBypassedOriginType::kBypassed: + // If bypassing is allowed, the service worker was bypassed and the + // navigation request shouldn't be handled by the fetch handler. + EXPECT_EQ(0, EvalJs(GetPrimaryMainFrame(), script)); + break; + case ServiceWorkerBypassFetchHandlerBypassedOriginType::kNotBypassed: + // If bypassing is not allowed, the navigation request should be handled + // by the fetch handler. + EXPECT_EQ(1, EvalJs(GetPrimaryMainFrame(), script)); + break; + } +} + } // namespace content
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc index ebaf9405..9b05133 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.cc +++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -81,6 +81,10 @@ base::FEATURE_ENABLED_BY_DEFAULT); #endif +BASE_FEATURE(kServiceWorkerStorageControlOnThreadPool, + "ServiceWorkerStorageControlOnThreadPool", + base::FEATURE_DISABLED_BY_DEFAULT); + void DidFindRegistrationForStartActiveWorker( ServiceWorkerContextWrapper::StatusCallback callback, blink::ServiceWorkerStatusCode status, @@ -1554,6 +1558,24 @@ if (storage_control_binder_for_test_) { storage_control_binder_for_test_.Run(std::move(receiver)); + } else if (base::FeatureList::IsEnabled( + kServiceWorkerStorageControlOnThreadPool)) { + // The database task runner is BLOCK_SHUTDOWN in order to support + // ClearSessionOnlyOrigins() (called due to the "clear on browser exit" + // content setting). + // The ServiceWorkerStorageControl receiver runs on thread pool by using + // |database_task_runner| SequencedTaskRunner. + // TODO(falken): Only block shutdown for that particular task, when someday + // task runners support mixing task shutdown behaviors. + scoped_refptr<base::SequencedTaskRunner> database_task_runner = + base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN}); + database_task_runner->PostTask( + FROM_HERE, + base::BindOnce(base::IgnoreResult( + &storage::ServiceWorkerStorageControlImpl::Create), + std::move(receiver), user_data_directory_, + database_task_runner)); } else if (run_storage_control_on_ui_thread) { // TODO(crbug.com/1055677): Use storage_partition() to bind the control when // ServiceWorkerStorageControl is sandboxed in the Storage Service.
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.cc b/content/browser/service_worker/service_worker_controllee_request_handler.cc index a2e9bba..16dd466 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler.cc +++ b/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" +#include "base/no_destructor.h" #include "base/strings/string_split.h" #include "base/trace_event/trace_event.h" #include "components/offline_pages/buildflags/buildflags.h" @@ -84,12 +85,11 @@ } } -// Returns the list of origins in which fetch handlers are allowed to be -// bypassed. -const std::vector<url::Origin> BypassingFetchHandlerAllowedOrigins() { +// Returns the list of origins in which fetch handlers are bypassed. +const std::vector<url::Origin> FetchHandlerBypassedOrigins() { std::vector<url::Origin> origins; std::vector<std::string> parsed_params = base::SplitString( - features::kServiceWorkerBypassFetchHandlerAllowedOrigins.Get(), ",", + features::kServiceWorkerBypassFetchHandlerBypassedOrigins.Get(), ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); for (const auto& it : parsed_params) { const GURL url = GURL(it); @@ -110,12 +110,13 @@ features::ServiceWorkerBypassFetchHandlerTarget::kMainResource) { // When the url is in the allowlist, fetch handlers for the main resource // are bypassed. - // TODO(crbug.com/1371756) Consider using `static`. Since having `static` - // led some test failures, we tentatively removed it. - const std::vector<url::Origin> allowed_origins( - BypassingFetchHandlerAllowedOrigins()); - for (const auto& it : allowed_origins) { - if (it.IsSameOriginWith(stripped_url)) + const static base::NoDestructor<std::vector<url::Origin>> bypassed_origins( + FetchHandlerBypassedOrigins()); + for (const auto& it : *bypassed_origins) { + // Skip comparing port numbers because some tests run the mock HTTP server + // with a random port number. + if (it.scheme() == stripped_url.scheme() && + it.host() == stripped_url.host()) return true; } }
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc index 32c1d0c5..269df27 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc +++ b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -715,111 +715,6 @@ test_resources.ResetHandler(); } -class ServiceWorkerBypassMainResourceWithAllowListTest - : public ServiceWorkerControlleeRequestHandlerTest { - public: - ServiceWorkerBypassMainResourceWithAllowListTest() { - scoped_feature_list_.InitWithFeaturesAndParameters( - {{features::kServiceWorkerBypassFetchHandler, - {{"allowed_origins", "https://host"}}}}, - {}); - } - ~ServiceWorkerBypassMainResourceWithAllowListTest() override = default; - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - -TEST_F(ServiceWorkerBypassMainResourceWithAllowListTest, UrlInAllowList) { - // Store an activated worker. - version_->set_fetch_handler_type( - ServiceWorkerVersion::FetchHandlerType::kNotSkippable); - version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - registration_->SetActiveVersion(version_); - base::RunLoop loop; - context()->registry()->StoreRegistration( - registration_.get(), version_.get(), - base::BindLambdaForTesting( - [&loop](blink::ServiceWorkerStatusCode status) { loop.Quit(); })); - loop.Run(); - - // Conduct a main resource load. - ServiceWorkerRequestTestResources test_resources( - this, GURL("https://host/scope/doc"), - network::mojom::RequestDestination::kDocument); - test_resources.MaybeCreateLoader(); - - EXPECT_FALSE(test_resources.loader()); - EXPECT_FALSE(version_->HasControllee()); - - test_resources.WaitLoader(); - - // If the url is in the allowlist, ServiceWorker the interceptor doesn't - // handle the main resource request. - EXPECT_FALSE(test_resources.loader()); - EXPECT_TRUE(version_->HasControllee()); - - // Use RunUntilIdle() to wait for the ServiceWorker to start. - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(version_->running_status(), EmbeddedWorkerStatus::RUNNING); - - test_resources.ResetHandler(); -} - -class ServiceWorkerBypassMainResourceWithAnotherAllowListTest - : public ServiceWorkerControlleeRequestHandlerTest { - public: - ServiceWorkerBypassMainResourceWithAnotherAllowListTest() { - scoped_feature_list_.InitWithFeaturesAndParameters( - {{features::kServiceWorkerBypassFetchHandler, - {{"allowed_origins", "https://another-host"}}}}, - {}); - } - ~ServiceWorkerBypassMainResourceWithAnotherAllowListTest() override = default; - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - -TEST_F(ServiceWorkerBypassMainResourceWithAnotherAllowListTest, - UrlNotInAllowList) { - // Prepare a valid version and registration. - version_->set_fetch_handler_type( - ServiceWorkerVersion::FetchHandlerType::kNotSkippable); - version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - registration_->SetActiveVersion(version_); - { - base::RunLoop loop; - context()->registry()->StoreRegistration( - registration_.get(), version_.get(), - base::BindOnce( - [](base::OnceClosure closure, - blink::ServiceWorkerStatusCode status) { - ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status); - std::move(closure).Run(); - }, - loop.QuitClosure())); - loop.Run(); - } - - // Conduct a main resource load. - ServiceWorkerRequestTestResources test_resources( - this, GURL("https://host/scope/doc"), - network::mojom::RequestDestination::kDocument); - test_resources.MaybeCreateLoader(); - - EXPECT_FALSE(test_resources.loader()); - EXPECT_FALSE(version_->HasControllee()); - - test_resources.WaitLoader(); - - // If the url is not in the allowlist, ServiceWorker handles fetch handler. - EXPECT_TRUE(test_resources.loader()); - EXPECT_TRUE(version_->HasControllee()); - - test_resources.ResetHandler(); -} - #if BUILDFLAG(ENABLE_OFFLINE_PAGES) TEST_F(ServiceWorkerControlleeRequestHandlerTest, FallbackWithOfflineHeader) { version_->set_fetch_handler_type(
diff --git a/content/browser/webrtc/resources/candidate_grid.js b/content/browser/webrtc/resources/candidate_grid.js index ca51edb..68c108e 100644 --- a/content/browser/webrtc/resources/candidate_grid.js +++ b/content/browser/webrtc/resources/candidate_grid.js
@@ -137,9 +137,12 @@ localRow.children[index].innerText = localCandidate[stat]; } }); - // Network type is only for the local candidate - // so put it into the pair row above the address. + // Network type is only for the local candidate so put it into the pair + // row above the address. Also highlight VPN adapters. pairRow.children[2].innerText = localCandidate.networkType; + if (localCandidate['vpn*'] === true) { + pairRow.children[2].innerText += ' (VPN)'; + } // protocol must always be the same for the pair // so put it into the pair row above the candidate type. // Add tcpType for local candidates.
diff --git a/content/browser/webrtc/resources/webrtc_internals.js b/content/browser/webrtc/resources/webrtc_internals.js index 1b81d895..6c1988a 100644 --- a/content/browser/webrtc/resources/webrtc_internals.js +++ b/content/browser/webrtc/resources/webrtc_internals.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {addWebUIListener, sendWithPromise} from 'chrome://resources/js/cr.m.js'; +import {addWebUiListener, sendWithPromise} from 'chrome://resources/js/cr.js'; import {$} from 'chrome://resources/js/util.js'; import {MAX_STATS_DATA_POINT_BUFFER_SIZE} from './data_series.js'; @@ -115,20 +115,20 @@ statsTable = new StatsTable(ssrcInfoManager); // Add listeners for all the updates that get sent from webrtc_internals.cc. - addWebUIListener('add-peer-connection', addPeerConnection); - addWebUIListener('update-peer-connection', updatePeerConnection); - addWebUIListener('update-all-peer-connections', updateAllPeerConnections); - addWebUIListener('remove-peer-connection', removePeerConnection); - addWebUIListener('add-standard-stats', addStandardStats); - addWebUIListener('add-legacy-stats', addLegacyStats); - addWebUIListener('add-get-user-media', addGetUserMedia); - addWebUIListener('update-get-user-media', updateGetUserMedia); - addWebUIListener( + addWebUiListener('add-peer-connection', addPeerConnection); + addWebUiListener('update-peer-connection', updatePeerConnection); + addWebUiListener('update-all-peer-connections', updateAllPeerConnections); + addWebUiListener('remove-peer-connection', removePeerConnection); + addWebUiListener('add-standard-stats', addStandardStats); + addWebUiListener('add-legacy-stats', addLegacyStats); + addWebUiListener('add-get-user-media', addGetUserMedia); + addWebUiListener('update-get-user-media', updateGetUserMedia); + addWebUiListener( 'remove-get-user-media-for-renderer', removeGetUserMediaForRenderer); - addWebUIListener( + addWebUiListener( 'event-log-recordings-file-selection-cancelled', eventLogRecordingsFileSelectionCancelled); - addWebUIListener( + addWebUiListener( 'audio-debug-recordings-file-selection-cancelled', audioDebugRecordingsFileSelectionCancelled);
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 8aa38ed..4eaab73 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -897,12 +897,11 @@ ServiceWorkerBypassFetchHandlerTarget::kMainResource, &service_worker_bypass_fetch_handler_target_options}; -// Define the allowed websites to bypass ServiceWorker. Allowed origins are -// expected to be passed as a comma separated string. -// e.g. https://example1.test,https://example2.test +// Define origins to bypass ServiceWorker. Origins are expected to be passed as +// a comma separated string. e.g. https://example1.test,https://example2.test const base::FeatureParam<std::string> - kServiceWorkerBypassFetchHandlerAllowedOrigins{ - &kServiceWorkerBypassFetchHandler, "allowed_origins", ""}; + kServiceWorkerBypassFetchHandlerBypassedOrigins{ + &kServiceWorkerBypassFetchHandler, "origins_to_bypass", ""}; // Enables skipping the service worker fetch handler if the fetch handler is // identified as ignorable.
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index d8d6ee8..8879148e 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -220,7 +220,7 @@ ServiceWorkerBypassFetchHandlerTarget> kServiceWorkerBypassFetchHandlerTarget; CONTENT_EXPORT extern const base::FeatureParam<std::string> - kServiceWorkerBypassFetchHandlerAllowedOrigins; + kServiceWorkerBypassFetchHandlerBypassedOrigins; CONTENT_EXPORT BASE_DECLARE_FEATURE(kServiceWorkerSkipIgnorableFetchHandler); CONTENT_EXPORT extern const base::FeatureParam<bool> kSkipEmptyFetchHandler; CONTENT_EXPORT BASE_DECLARE_FEATURE(kUserMediaCaptureOnFocus);
diff --git a/content/public/renderer/render_frame_observer.h b/content/public/renderer/render_frame_observer.h index 0af40eb..7308301 100644 --- a/content/public/renderer/render_frame_observer.h +++ b/content/public/renderer/render_frame_observer.h
@@ -212,6 +212,13 @@ // load. This is used for metrics collection. virtual void DidObserveLoadingBehavior(blink::LoadingBehaviorFlag behavior) {} + // Notification when the renderer uses subresources. + // It is called when there is a subresouce load. The reported values via + // arguments are cumulative. They are NOT a difference from the previous call. + virtual void DidObserveSubresourceLoad( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker) {} + // Notification when the renderer observes a new use counter usage during a // page load. This is used for UseCounter metrics. virtual void DidObserveNewFeatureUsage(
diff --git a/content/public/test/browser_task_environment_unittest.cc b/content/public/test/browser_task_environment_unittest.cc index b860e067..acc230c 100644 --- a/content/public/test/browser_task_environment_unittest.cc +++ b/content/public/test/browser_task_environment_unittest.cc
@@ -14,6 +14,7 @@ #include "base/task/current_thread.h" #include "base/task/thread_pool.h" #include "base/test/bind.h" +#include "base/test/gtest_util.h" #include "build/build_config.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -32,13 +33,7 @@ constexpr int kNumHops = 13; constexpr int kNumTasks = 8; -#if DCHECK_IS_ON() && !BUILDFLAG(IS_ANDROID) -// Expect that in builds with working DCHECK messages the failure message -// includes a hint towards using the BrowserTaskEnvironment class. const char kDeathMatcher[] = "Check failed:.*\n*.*BrowserTaskEnvironment"; -#else -const char kDeathMatcher[] = ""; -#endif void PostTaskToUIThread(int iteration, base::subtle::Atomic32* tasks_run); @@ -121,12 +116,10 @@ } TEST(BrowserTaskEnvironmentTest, MessageLoopTypeMismatch) { - testing::FLAGS_gtest_death_test_style = "threadsafe"; - base::test::TaskEnvironment task_environment( base::test::TaskEnvironment::MainThreadType::UI); - EXPECT_DEATH_IF_SUPPORTED( + BASE_EXPECT_DEATH( { BrowserTaskEnvironment second_task_environment( BrowserTaskEnvironment::IO_MAINLOOP); @@ -135,9 +128,7 @@ } TEST(BrowserTaskEnvironmentTest, MultipleBrowserTaskEnvironment) { - testing::FLAGS_gtest_death_test_style = "threadsafe"; - - EXPECT_DEATH_IF_SUPPORTED( + BASE_EXPECT_DEATH( { BrowserTaskEnvironment task_environment; BrowserTaskEnvironment other_task_environment; @@ -192,30 +183,28 @@ // Verify that posting tasks to the UI thread without having the // BrowserTaskEnvironment instance cause a crash. TEST(BrowserTaskEnvironmentTest, NotInitializedUIThread) { - testing::FLAGS_gtest_death_test_style = "threadsafe"; base::test::TaskEnvironment task_environment( base::test::TaskEnvironment::MainThreadType::UI); - EXPECT_DEATH_IF_SUPPORTED( - { GetUIThreadTaskRunner({})->PostTask(FROM_HERE, base::DoNothing()); }, + EXPECT_DCHECK_DEATH_WITH( + GetUIThreadTaskRunner({})->PostTask(FROM_HERE, base::DoNothing()), kDeathMatcher); - EXPECT_DEATH_IF_SUPPORTED( - { GetUIThreadTaskRunner({})->PostTask(FROM_HERE, base::DoNothing()); }, + EXPECT_DCHECK_DEATH_WITH( + GetUIThreadTaskRunner({})->PostTask(FROM_HERE, base::DoNothing()), kDeathMatcher); } // Verify that posting tasks to the IO thread without having the // BrowserTaskEnvironment instance cause a crash. TEST(BrowserTaskEnvironmentTest, NotInitializedIOThread) { - testing::FLAGS_gtest_death_test_style = "threadsafe"; base::test::TaskEnvironment task_environment( base::test::TaskEnvironment::MainThreadType::IO); - EXPECT_DEATH_IF_SUPPORTED( - { GetIOThreadTaskRunner({})->PostTask(FROM_HERE, base::DoNothing()); }, + EXPECT_DCHECK_DEATH_WITH( + GetIOThreadTaskRunner({})->PostTask(FROM_HERE, base::DoNothing()), kDeathMatcher); - EXPECT_DEATH_IF_SUPPORTED( - { GetIOThreadTaskRunner({})->PostTask(FROM_HERE, base::DoNothing()); }, + EXPECT_DCHECK_DEATH_WITH( + GetIOThreadTaskRunner({})->PostTask(FROM_HERE, base::DoNothing()), kDeathMatcher); }
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 36bfded..e8ba73bd 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -4319,6 +4319,15 @@ observer.DidObserveLoadingBehavior(behavior); } +void RenderFrameImpl::DidObserveSubresourceLoad( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker) { + for (auto& observer : observers_) + observer.DidObserveSubresourceLoad( + number_of_subresources_loaded, + number_of_subresource_loads_handled_by_service_worker); +} + void RenderFrameImpl::DidObserveNewFeatureUsage( const blink::UseCounterFeature& feature) { for (auto& observer : observers_)
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 33dea08e..15f67fb 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -591,6 +591,9 @@ blink::UserInteractionType interaction_type) override; void DidChangeCpuTiming(base::TimeDelta time) override; void DidObserveLoadingBehavior(blink::LoadingBehaviorFlag behavior) override; + void DidObserveSubresourceLoad( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker) override; void DidObserveNewFeatureUsage( const blink::UseCounterFeature& feature) override; void DidObserveSoftNavigation(uint32_t count) override;
diff --git a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt index 0cf731c3..d73a206 100644 --- a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
@@ -157,7 +157,6 @@ # Failing on android N5 # Flaking on Linux FYI Release -crbug.com/1340081 [ linux release amd-0x7340 ] ContextLost_WorkerWebGLRAFAfterGPUCrash [ RetryOnFailure ] ####################################################################### # Automated Entries After This Point - Do Not Manually Add Below Here #
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index 725cbe85..d633872 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -325,7 +325,6 @@ crbug.com/1288134 [ win10 amd-0x7340 renderer-skia-gl ] Pixel_DirectComposition_Video_VP9_YUY2 [ Failure ] # Pixel 4 Flaky Failures - Passthrough, WebView and Validating -crbug.com/1273033 [ android android-pixel-4 ] Pixel_OffscreenCanvasWebGLPaintAfterResize [ Failure ] # Pixel 4 Flaky Failures - Passthrough and Validating on Chromium
diff --git a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt index 41cee7c..cf906d4b 100644 --- a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
@@ -229,7 +229,6 @@ crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] TraceTest_Canvas2DRedBox [ RetryOnFailure ] crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] TraceTest_ScissorTestWithPreserveDrawingBuffer [ RetryOnFailure ] crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] TraceTest_Video_MP4_FourColors_Aspect_4x3 [ RetryOnFailure ] -crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] TraceTest_Video_MP4_Rounded_Corner [ RetryOnFailure ] crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] TraceTest_WebGLGreenTriangle_* [ RetryOnFailure ] crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] TraceTest_WebGLPreservedAfterTabSwitch [ RetryOnFailure ] crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] WebGLCanvasCaptureTraceTest_VideoStreamFromWebGLAlphaCanvas [ RetryOnFailure ]
diff --git a/docs/webui_build_configuration.md b/docs/webui_build_configuration.md index e24a1558..28cb586 100644 --- a/docs/webui_build_configuration.md +++ b/docs/webui_build_configuration.md
@@ -244,7 +244,7 @@ targets generating shared resources that are expected to be bundled in the UI, e.g. //ui/webui/resources:preprocess. excludes: Paths of files that are not bundled. Often used for large mojo files - that would otherwise be in many bundles, and for cr.m.js which relies + that would otherwise be in many bundles, and for cr.js which relies on global variables. ``` @@ -269,7 +269,7 @@ "//ui/webui/resources:preprocess", ] excludes = [ - "chrome://resources/js/cr.m.js", + "chrome://resources/js/cr.js", "chrome://resources/mojo/mojo/public/js/bindings.js", ] }
diff --git a/docs/webui_explainer.md b/docs/webui_explainer.md index 64c6f4d..aa52588 100644 --- a/docs/webui_explainer.md +++ b/docs/webui_explainer.md
@@ -513,7 +513,7 @@ * [`FireWebUIListener()`](#FireWebUIListener) allows easily notifying the page when an event occurs in C++ and is more loosely coupled (nothing blows up if the event dispatch is ignored). JS subscribes to notifications via - [`addWebUIListener`](#addWebUIListener). + [`addWebUiListener`](#addWebUiListener). * [`ResolveJavascriptCallback`](#ResolveJavascriptCallback) and [`RejectJavascriptCallback`](#RejectJavascriptCallback) are useful when Javascript requires a response to an inquiry about C++-canonical state @@ -529,7 +529,7 @@ Here's some example to detect a change to Chrome's theme: ```js -addWebUIListener("theme-changed", refreshThemeStyles); +addWebUiListener("theme-changed", refreshThemeStyles); ``` This Javascript event listener can be triggered in C++ via: @@ -734,23 +734,23 @@ message_callbacks_.find(message)->second.Run(&args); ``` -### addWebUIListener() +### addWebUiListener() WebUI listeners are a convenient way for C++ to inform JavaScript of events. Older WebUI code exposed public methods for event notification, similar to how responses to [chrome.send()](#chrome_send) used to work. They both resulted in global namespace pollution, but it was additionally hard to stop -listening for events in some cases. **cr.addWebUIListener** is preferred in new +listening for events in some cases. **addWebUiListener** is preferred in new code. Adding WebUI listeners creates and inserts a unique ID into a map in JavaScript, just like [sendWithPromise()](#sendWithPromise). -addWebUIListener can be imported from 'chrome://resources/js/cr.m.js'. +addWebUiListener can be imported from 'chrome://resources/js/cr.m.js'. ```js -// addWebUIListener(): +// addWebUiListener(): webUIListenerMap[eventName] = webUIListenerMap[eventName] || {}; webUIListenerMap[eventName][createUid()] = callback; ``` @@ -780,7 +780,7 @@ ```js let donutsReady: number = 0; -addWebUIListener('donuts-baked', function(numFreshlyBakedDonuts: number) { +addWebUiListener('donuts-baked', function(numFreshlyBakedDonuts: number) { donutsReady += numFreshlyBakedDonuts; }); ``` @@ -806,7 +806,7 @@ }); ``` -Note that sendWithPromise can be imported from 'chrome://resources/js/cr.m.js'; +Note that sendWithPromise can be imported from 'chrome://resources/js/cr.js'; On the C++ side, the message registration is similar to [`chrome.send()`](#chrome_send) except that the first argument in the
diff --git a/extensions/common/api/_permission_features.json b/extensions/common/api/_permission_features.json index ac9d414b..f6988f3 100644 --- a/extensions/common/api/_permission_features.json +++ b/extensions/common/api/_permission_features.json
@@ -601,6 +601,11 @@ "allowlist": ["B44D08FD98F1523ED5837D78D0A606EA9D6206E5"] // Web Store }, { + "channel": "stable", + "extension_types": ["extension"], + "allowlist": ["DD87C93131FF8D3DE4E483DC1EB298D73C7223A6"] // http://crbug.com/1328114 + }, + { "channel": "dev", "extension_types": ["extension"] }
diff --git a/infra/config/generated/builders/try/win-swangle-try-x86/properties.json b/infra/config/generated/builders/try/win-swangle-try-x86/properties.json index f394223..e984210 100644 --- a/infra/config/generated/builders/try/win-swangle-try-x86/properties.json +++ b/infra/config/generated/builders/try/win-swangle-try-x86/properties.json
@@ -39,11 +39,6 @@ "retry_failed_shards": false } }, - "$build/goma": { - "enable_ats": false, - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" - }, "$build/reclient": { "instance": "rbe-chromium-untrusted", "jobs": 150,
diff --git "a/infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI Android Tests \050dbg\051 \050M Nexus5X\051/properties.json" "b/infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI Android Tests \050dbg\051 \050M Nexus5X\051/properties.json" deleted file mode 100644 index 7883bfd5..0000000 --- "a/infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI Android Tests \050dbg\051 \050M Nexus5X\051/properties.json" +++ /dev/null
@@ -1,11 +0,0 @@ -{ - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "chromium.webrtc.fyi", - "recipe": "chromium" -} \ No newline at end of file
diff --git "a/infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI Android Tests \050dbg\051 \050N Nexus5X\051/properties.json" "b/infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI Android Tests \050dbg\051 \050N Nexus5X\051/properties.json" deleted file mode 100644 index 7883bfd5..0000000 --- "a/infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI Android Tests \050dbg\051 \050N Nexus5X\051/properties.json" +++ /dev/null
@@ -1,11 +0,0 @@ -{ - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "chromium.webrtc.fyi", - "recipe": "chromium" -} \ No newline at end of file
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 7013297..0838cc62 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -90086,12 +90086,6 @@ ' "retry_failed_shards": false' ' }' ' },' - ' "$build/goma": {' - ' "enable_ats": false,' - ' "jobs": 150,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "instance": "rbe-chromium-untrusted",' ' "jobs": 300,' @@ -94861,108 +94855,6 @@ } } builders { - name: "WebRTC Chromium FYI Android Tests (dbg) (M Nexus5X)" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-18.04" - dimensions: "pool:luci.chromium.webrtc.fyi" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI Android Tests (dbg) (M Nexus5X)/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "chromium.webrtc.fyi",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium"' - '}' - execution_timeout_secs: 7200 - build_numbers: YES - service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.buildbucket.omit_python2" - value: 100 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - resultdb { - enable: true - } - } - builders { - name: "WebRTC Chromium FYI Android Tests (dbg) (N Nexus5X)" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-18.04" - dimensions: "pool:luci.chromium.webrtc.fyi" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI Android Tests (dbg) (N Nexus5X)/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "chromium.webrtc.fyi",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium"' - '}' - execution_timeout_secs: 7200 - build_numbers: YES - service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.buildbucket.omit_python2" - value: 100 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - resultdb { - enable: true - } - } - builders { name: "WebRTC Chromium FYI Android Tests ARM64 (dbg)" swarming_host: "chromium-swarm.appspot.com" dimensions: "cpu:x86-64"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg index 742841d8..a4d9c2a 100644 --- a/infra/config/generated/luci/luci-milo.cfg +++ b/infra/config/generated/luci/luci-milo.cfg
@@ -14697,24 +14697,14 @@ short_name: "64" } builders { - name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI Android Tests (dbg) (M Nexus5X)" - category: "android|debug|tester" - short_name: "M" - } - builders { - name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI Android Tests (dbg) (N Nexus5X)" - category: "android|debug|tester" - short_name: "N" - } - builders { name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI Android Tests (dbg)" category: "android|debug|tester" - short_name: "P" + short_name: "32" } builders { name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI Android Tests ARM64 (dbg)" category: "android|debug|tester" - short_name: "P" + short_name: "64" } builders { name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI Android Builder"
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg index 2c91e4b..c09d7b8cc 100644 --- a/infra/config/generated/luci/luci-scheduler.cfg +++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -2792,24 +2792,6 @@ } } job { - id: "WebRTC Chromium FYI Android Tests (dbg) (M Nexus5X)" - realm: "webrtc.fyi" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "webrtc.fyi" - builder: "WebRTC Chromium FYI Android Tests (dbg) (M Nexus5X)" - } -} -job { - id: "WebRTC Chromium FYI Android Tests (dbg) (N Nexus5X)" - realm: "webrtc.fyi" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "webrtc.fyi" - builder: "WebRTC Chromium FYI Android Tests (dbg) (N Nexus5X)" - } -} -job { id: "WebRTC Chromium FYI Android Tests ARM64 (dbg)" realm: "webrtc.fyi" buildbucket {
diff --git a/infra/config/generated/luci/realms.cfg b/infra/config/generated/luci/realms.cfg index cc90fa36..c62f970b1e 100644 --- a/infra/config/generated/luci/realms.cfg +++ b/infra/config/generated/luci/realms.cfg
@@ -607,8 +607,6 @@ restrict { attribute: "scheduler.job.name" values: "WebRTC Chromium FYI Android Tests (dbg)" - values: "WebRTC Chromium FYI Android Tests (dbg) (M Nexus5X)" - values: "WebRTC Chromium FYI Android Tests (dbg) (N Nexus5X)" values: "WebRTC Chromium FYI Android Tests ARM64 (dbg)" values: "WebRTC Chromium FYI Linux Tester" values: "WebRTC Chromium FYI Mac Tester"
diff --git a/infra/config/subprojects/chromium/swangle.try.star b/infra/config/subprojects/chromium/swangle.try.star index 86df446..d998b5f2 100644 --- a/infra/config/subprojects/chromium/swangle.try.star +++ b/infra/config/subprojects/chromium/swangle.try.star
@@ -162,4 +162,5 @@ try_settings = builder_config.try_settings( retry_failed_shards = False, ), + goma_backend = None, )
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.angle.star b/infra/config/subprojects/chromium/try/tryserver.chromium.angle.star index 902ba0d0..7b00f99 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.angle.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.angle.star
@@ -93,6 +93,7 @@ try_settings = builder_config.try_settings( retry_failed_shards = False, ), + goma_backend = None, ) try_.builder(
diff --git a/infra/config/subprojects/webrtc/consoles/chromium.webrtc.fyi.star b/infra/config/subprojects/webrtc/consoles/chromium.webrtc.fyi.star index 2795e12..7febc59 100644 --- a/infra/config/subprojects/webrtc/consoles/chromium.webrtc.fyi.star +++ b/infra/config/subprojects/webrtc/consoles/chromium.webrtc.fyi.star
@@ -21,24 +21,14 @@ short_name = "64", ), luci.console_view_entry( - builder = "webrtc.fyi/WebRTC Chromium FYI Android Tests (dbg) (M Nexus5X)", - category = "android|debug|tester", - short_name = "M", - ), - luci.console_view_entry( - builder = "webrtc.fyi/WebRTC Chromium FYI Android Tests (dbg) (N Nexus5X)", - category = "android|debug|tester", - short_name = "N", - ), - luci.console_view_entry( builder = "webrtc.fyi/WebRTC Chromium FYI Android Tests (dbg)", category = "android|debug|tester", - short_name = "P", + short_name = "32", ), luci.console_view_entry( builder = "webrtc.fyi/WebRTC Chromium FYI Android Tests ARM64 (dbg)", category = "android|debug|tester", - short_name = "P", + short_name = "64", ), luci.console_view_entry( builder = "webrtc.fyi/WebRTC Chromium FYI Android Builder",
diff --git a/infra/config/subprojects/webrtc/webrtc.fyi.star b/infra/config/subprojects/webrtc/webrtc.fyi.star index 06ff617..074e565 100644 --- a/infra/config/subprojects/webrtc/webrtc.fyi.star +++ b/infra/config/subprojects/webrtc/webrtc.fyi.star
@@ -63,16 +63,6 @@ ) builder( - name = "WebRTC Chromium FYI Android Tests (dbg) (M Nexus5X)", - triggered_by = ["WebRTC Chromium FYI Android Builder ARM64 (dbg)"], -) - -builder( - name = "WebRTC Chromium FYI Android Tests (dbg) (N Nexus5X)", - triggered_by = ["WebRTC Chromium FYI Android Builder (dbg)"], -) - -builder( name = "WebRTC Chromium FYI Android Tests (dbg)", triggered_by = ["WebRTC Chromium FYI Android Builder (dbg)"], )
diff --git a/ios/chrome/browser/ui/page_info/BUILD.gn b/ios/chrome/browser/ui/page_info/BUILD.gn index f958bbd..be98654 100644 --- a/ios/chrome/browser/ui/page_info/BUILD.gn +++ b/ios/chrome/browser/ui/page_info/BUILD.gn
@@ -27,6 +27,7 @@ "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/fancy_ui", "//ios/chrome/browser/ui/icons:symbols", + "//ios/chrome/browser/ui/keyboard", "//ios/chrome/browser/ui/page_info/requirements", "//ios/chrome/browser/ui/permissions", "//ios/chrome/browser/ui/permissions:constants",
diff --git a/ios/chrome/browser/ui/page_info/page_info_view_controller.mm b/ios/chrome/browser/ui/page_info/page_info_view_controller.mm index b6900cb..2ffbbe55 100644 --- a/ios/chrome/browser/ui/page_info/page_info_view_controller.mm +++ b/ios/chrome/browser/ui/page_info/page_info_view_controller.mm
@@ -5,11 +5,14 @@ #import "ios/chrome/browser/ui/page_info/page_info_view_controller.h" #import "base/mac/foundation_util.h" +#import "base/metrics/user_metrics.h" +#import "base/metrics/user_metrics_action.h" #import "base/notreached.h" #import "base/strings/sys_string_conversions.h" #import "ios/chrome/browser/net/crurl.h" #import "ios/chrome/browser/ui/commands/page_info_commands.h" #import "ios/chrome/browser/ui/icons/symbols.h" +#import "ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.h" #import "ios/chrome/browser/ui/page_info/page_info_constants.h" #import "ios/chrome/browser/ui/permissions/permission_info.h" #import "ios/chrome/browser/ui/permissions/permissions_constants.h" @@ -257,6 +260,23 @@ [self.pageInfoCommandsHandler hidePageInfo]; } +#pragma mark - UIResponder + +// To always be able to register key commands via -keyCommands, the VC must be +// able to become first responder. +- (BOOL)canBecomeFirstResponder { + return YES; +} + +- (NSArray*)keyCommands { + return @[ UIKeyCommand.cr_close ]; +} + +- (void)keyCommand_close { + base::RecordAction(base::UserMetricsAction("MobileKeyCommandClose")); + [self.pageInfoCommandsHandler hidePageInfo]; +} + #pragma mark - Private // Returns the navigationItem titleView for `siteURL`.
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm index 9f3a621..ee9712e 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm
@@ -17,6 +17,7 @@ #import "ios/chrome/browser/drag_and_drop/table_view_url_drag_drop_handler.h" #import "ios/chrome/browser/main/browser.h" #import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h" +#import "ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.h" #import "ios/chrome/browser/ui/list_model/list_item+Controller.h" #import "ios/chrome/browser/ui/list_model/list_item.h" #import "ios/chrome/browser/ui/reading_list/reading_list_constants.h" @@ -345,6 +346,23 @@ } } +#pragma mark - UIResponder + +// To always be able to register key commands via -keyCommands, the VC must be +// able to become first responder. +- (BOOL)canBecomeFirstResponder { + return YES; +} + +- (NSArray*)keyCommands { + return @[ UIKeyCommand.cr_close ]; +} + +- (void)keyCommand_close { + base::RecordAction(base::UserMetricsAction("MobileKeyCommandClose")); + [self.delegate dismissReadingListListViewController:self]; +} + #pragma mark - ReadingListDataSink - (void)dataSourceReady:(id<ReadingListDataSource>)dataSource {
diff --git a/ios/chrome/browser/ui/recent_tabs/synced_sessions.h b/ios/chrome/browser/ui/recent_tabs/synced_sessions.h index 5a32e19d..0b778e39 100644 --- a/ios/chrome/browser/ui/recent_tabs/synced_sessions.h +++ b/ios/chrome/browser/ui/recent_tabs/synced_sessions.h
@@ -84,7 +84,6 @@ std::string tag; std::string name; base::Time modified_time; - sync_pb::SyncEnums::DeviceType device_type; std::vector<std::unique_ptr<DistantTab>> tabs; };
diff --git a/ios/chrome/browser/ui/recent_tabs/synced_sessions.mm b/ios/chrome/browser/ui/recent_tabs/synced_sessions.mm index da393df80..07e1753b 100644 --- a/ios/chrome/browser/ui/recent_tabs/synced_sessions.mm +++ b/ios/chrome/browser/ui/recent_tabs/synced_sessions.mm
@@ -98,7 +98,6 @@ tag = synced_session->session_tag; name = synced_session->session_name; modified_time = synced_session->modified_time; - device_type = synced_session->device_type; std::vector<const sessions::SessionTab*> open_tabs; open_tabs_delegate->GetForeignSessionTabs(tag, &open_tabs);
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn b/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn index 71873cd..b8f80b75a 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn
@@ -56,6 +56,7 @@ "//ios/chrome/browser/ui/elements:elements_internal", "//ios/chrome/browser/ui/icons", "//ios/chrome/browser/ui/icons:symbols", + "//ios/chrome/browser/ui/keyboard", "//ios/chrome/browser/ui/list_model", "//ios/chrome/browser/ui/resources:legacy_password_key", "//ios/chrome/browser/ui/resources:password_key",
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm index 68b4859..3a88245 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.mm
@@ -27,6 +27,7 @@ #import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/browsing_data_commands.h" #import "ios/chrome/browser/ui/elements/chrome_activity_overlay_coordinator.h" +#import "ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.h" #import "ios/chrome/browser/ui/settings/cells/clear_browsing_data_constants.h" #import "ios/chrome/browser/ui/settings/cells/table_view_clear_browsing_data_item.h" #import "ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_consumer.h" @@ -326,6 +327,23 @@ [self updateToolbarButtons]; } +#pragma mark - UIResponder + +// To always be able to register key commands via -keyCommands, the VC must be +// able to become first responder. +- (BOOL)canBecomeFirstResponder { + return YES; +} + +- (NSArray*)keyCommands { + return @[ UIKeyCommand.cr_close ]; +} + +- (void)keyCommand_close { + base::RecordAction(base::UserMetricsAction("MobileKeyCommandClose")); + [self dismiss]; +} + #pragma mark - TableViewLinkHeaderFooterItemDelegate - (void)view:(TableViewLinkHeaderFooterView*)view didTapLinkURL:(CrURL*)url {
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_page_control.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_page_control.mm index a61743c..4d8a3d4 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_page_control.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_page_control.mm
@@ -12,6 +12,7 @@ #import "ios/chrome/browser/ui/icons/symbols.h" #import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_constants.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" +#import "ios/chrome/common/ui/colors/semantic_color_names.h" #import "ios/chrome/grit/ios_strings.h" #import "ui/base/l10n/l10n_util.h" @@ -34,7 +35,8 @@ // This control is built out of several views. From the (z-axis) bottom up, they // are: // -// * The background view, a grey roundrect with vertical transparent bars. +// * The background view, a grey roundrect. +// * The separators between the segment. // * The background image views. // * The numeric label on the regular tab icon. // * The hover views, which allow for pointer interactions. @@ -63,32 +65,52 @@ // Height and width of the slider. const CGFloat kSliderHeight = 40.0; -const CGFloat kSliderWidth = 78.0; +const CGFloat kLegacySliderWidth = 78.0; +const CGFloat kSliderWidth = 65.0; // Height and width of each segment. -const CGFloat kSegmentHeight = 36.0; -const CGFloat kSegmentWidth = 64.0; +const CGFloat kLegacySegmentHeight = 36.0; +const CGFloat kLegacySegmentWidth = 64.0; +const CGFloat kSegmentHeight = 44.0; +const CGFloat kSegmentWidth = 65.0; // Points that the slider overhangs a segment on each side, or 0 if the slider // is narrower than a segment. -const CGFloat kSliderOverhang = - std::max((kSliderWidth - kSegmentWidth) / 2.0, 0.0); +const CGFloat kLegacySliderOverhang = + std::max((kLegacySliderWidth - kLegacySegmentWidth) / 2.0, 0.0); +// Margin between the slider and the leading/trailing segments. +const CGFloat kSliderMargin = 2.0; -// Width of the separator bars between segments. +// Vertical margin between the slider and the segment on each side. +const CGFloat kSliderVerticalMargin = + std::max((kSegmentHeight - kSliderHeight) / 2.0, 0.0); + +// Width and height of the separator bars between segments. const CGFloat kSeparatorWidth = 1.0; +const CGFloat kSeparatorHeight = 22.0; // Width of the background -- three segments plus two separators. -const CGFloat kBackgroundWidth = 3 * kSegmentWidth + 2 * kSeparatorWidth; +const CGFloat kLegacyBackgroundWidth = + 3 * kLegacySegmentWidth + 2 * kSeparatorWidth; // Overall height of the control -- the larger of the slider and segment // heights. +const CGFloat kLegacyOverallHeight = + std::max(kSliderHeight, kLegacySegmentHeight); const CGFloat kOverallHeight = std::max(kSliderHeight, kSegmentHeight); // Overall width of the control -- the background width plus twice the slider // overhang. -const CGFloat kOverallWidth = kBackgroundWidth + 2 * kSliderOverhang; +const CGFloat kLegacyOverallWidth = + kLegacyBackgroundWidth + 2 * kLegacySliderOverhang; +// Overall width -- three segments plus two separators plus two margins between +// leading/trailing segments and the slider. +const CGFloat kOverallWidth = + 3 * kSegmentWidth + 2 * kSeparatorWidth + 2 * kSliderMargin; // Radius used to draw the background and the slider. -const CGFloat kCornerRadius = 13.0; +const CGFloat kSliderCornerRadius = 13.0; +const CGFloat kBackgroundCornerRadius = 15.0; +const CGFloat kLegacyBackgroundCornerRadius = 13.0; // Sizes for the labels and their selected counterparts. const CGFloat kLabelSize = 20.0; @@ -98,16 +120,16 @@ const NSTimeInterval kSliderMoveDuration = 0.2; // Color for the slider -const int kSliderColor = 0xF8F9FA; -// Color for the background view. -const int kBackgroundColor = 0xFFFFFF; +const int kLegacySliderColor = 0xF8F9FA; // Alpha for the background view. -const CGFloat kBackgroundAlpha = 0.3; +const CGFloat kLegacyBackgroundAlpha = 0.3; +const CGFloat kBackgroundAlpha = 0.15; // Color for the regular tab count label and icons. -const CGFloat kSelectedColor = 0x3C4043; +const CGFloat kLegacySelectedColor = 0x3C4043; -// The size of the symbol image. -const CGFloat kSymbolTabGridPageControlPointSize = 24.; +// The sizes of the symbol images. +const CGFloat kUnselectedSymbolSize = 22.; +const CGFloat kSelectedSymbolSize = 24.; // Returns the point that's at the center of `rect`. CGPoint RectCenter(CGRect rect) { @@ -134,11 +156,11 @@ imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]]; } -// Returns an UIImageView for the given symbolName. -UIImageView* ImageViewForSymbolNamed(NSString* symbolName) { +// Returns an UIImageView for the given `symbolName` and `selected` state. +UIImageView* ImageViewForSymbol(NSString* symbolName, bool selected) { + CGFloat size = selected ? kSelectedSymbolSize : kUnselectedSymbolSize; return [[UIImageView alloc] - initWithImage:CustomSymbolTemplateWithPointSize( - symbolName, kSymbolTabGridPageControlPointSize)]; + initWithImage:CustomSymbolTemplateWithPointSize(symbolName, size)]; } } // namespace @@ -159,6 +181,10 @@ @property(nonatomic, weak) UILayoutGuide* incognitoGuide; @property(nonatomic, weak) UILayoutGuide* regularGuide; @property(nonatomic, weak) UILayoutGuide* remoteGuide; +// The separator between incognito and regular tabs. +@property(nonatomic, weak) UIView* firstSeparator; +// The separator between the regular and remote tabs. +@property(nonatomic, weak) UIView* secondSeparator; // The view for the slider. @property(nonatomic, weak) UIView* sliderView; // The view for the selected images and labels (a subview of `sliderView). @@ -208,7 +234,12 @@ } - (instancetype)init { - CGRect frame = CGRectMake(0, 0, kOverallWidth, kOverallHeight); + CGRect frame; + if (UseSymbols()) { + frame = CGRectMake(0, 0, kOverallWidth, kOverallHeight); + } else { + frame = CGRectMake(0, 0, kLegacyOverallWidth, kLegacyOverallHeight); + } if (self = [super initWithFrame:frame]) { // Default to the regular tab page as the selected page. _selectedPage = TabGridPageRegularTabs; @@ -275,6 +306,12 @@ else _selectedPage = TabGridPageRemoteTabs; + // Hide/show the separator based on the slider position. Add a delta for the + // comparison to avoid issues when the regular tabs are selected. + const CGFloat kDelta = 0.001; + self.firstSeparator.hidden = sliderPosition < 0.5 + kDelta; + self.secondSeparator.hidden = sliderPosition > 0.5 - kDelta; + if (_selectedPage != previousSelectedPage) [self updateSelectedPageAccessibility]; } @@ -385,7 +422,10 @@ #pragma mark - UIView - (CGSize)intrinsicContentSize { - return CGSizeMake(kOverallWidth, kOverallHeight); + if (UseSymbols()) { + return CGSizeMake(kOverallWidth, kOverallHeight); + } + return CGSizeMake(kLegacyOverallWidth, kLegacyOverallHeight); } - (void)willMoveToSuperview:(UIView*)newSuperview { @@ -489,8 +529,8 @@ switch (tab) { case TabGridPageRegularTabs: { if (UseSymbols()) { - iconSelected = ImageViewForSymbolNamed(kSquareNumberSymbol); - iconNotSelected = ImageViewForSymbolNamed(kSquareNumberSymbol); + iconSelected = ImageViewForSymbol(kSquareNumberSymbol, true); + iconNotSelected = ImageViewForSymbol(kSquareNumberSymbol, false); } else { iconSelected = ImageViewForImageNamed(kImagePageControlRegularSelected); iconNotSelected = @@ -502,8 +542,8 @@ } case TabGridPageIncognitoTabs: { if (UseSymbols()) { - iconSelected = ImageViewForSymbolNamed(kIncognitoSymbol); - iconNotSelected = ImageViewForSymbolNamed(kIncognitoSymbol); + iconSelected = ImageViewForSymbol(kIncognitoSymbol, true); + iconNotSelected = ImageViewForSymbol(kIncognitoSymbol, false); } else { iconSelected = ImageViewForImageNamed(kImagePageControlIncognitoSelected); @@ -516,8 +556,8 @@ } case TabGridPageRemoteTabs: { if (UseSymbols()) { - iconSelected = ImageViewForSymbolNamed(kRecentTabsSymbol); - iconNotSelected = ImageViewForSymbolNamed(kRecentTabsSymbol); + iconSelected = ImageViewForSymbol(kRecentTabsSymbol, true); + iconNotSelected = ImageViewForSymbol(kRecentTabsSymbol, false); } else { iconSelected = ImageViewForImageNamed(kImagePageControlRemoteSelected); iconNotSelected = @@ -529,8 +569,13 @@ } } - iconNotSelected.tintColor = UIColorFromRGB(kSliderColor); - iconSelected.tintColor = UIColorFromRGB(kSelectedColor); + if (UseSymbols()) { + iconNotSelected.tintColor = [UIColor colorNamed:kGrey300Color]; + iconSelected.tintColor = UIColor.blackColor; + } else { + iconNotSelected.tintColor = UIColorFromRGB(kLegacySliderColor); + iconSelected.tintColor = UIColorFromRGB(kLegacySelectedColor); + } [self insertSubview:iconNotSelected belowSubview:self.sliderView]; [self.selectedImageView addSubview:iconSelected]; @@ -539,13 +584,31 @@ // Sets up all of the subviews for this control, as well as the layout guides // used to position the section content. - (void)setupViews { - UIView* backgroundView = [[TabGridPageControlBackground alloc] init]; + UIView* backgroundView = nil; + if (UseSymbols()) { + backgroundView = [[UIView alloc] + initWithFrame:CGRectMake(0, 0, kOverallWidth, kSegmentHeight)]; + backgroundView.backgroundColor = [UIColor colorWithWhite:1 + alpha:kBackgroundAlpha]; + + } else { + backgroundView = [[TabGridPageControlBackground alloc] init]; + } backgroundView.userInteractionEnabled = NO; - backgroundView.layer.cornerRadius = kCornerRadius; + if (UseSymbols()) { + backgroundView.layer.cornerRadius = kBackgroundCornerRadius; + } else { + backgroundView.layer.cornerRadius = kLegacyBackgroundCornerRadius; + } backgroundView.layer.masksToBounds = YES; [self addSubview:backgroundView]; - backgroundView.center = - CGPointMake(kOverallWidth / 2.0, kOverallHeight / 2.0); + if (UseSymbols()) { + backgroundView.center = + CGPointMake(kOverallWidth / 2.0, kOverallHeight / 2.0); + } else { + backgroundView.center = + CGPointMake(kLegacyOverallWidth / 2.0, kLegacyOverallHeight / 2.0); + } // Set up the layout guides for the segments. UILayoutGuide* incognitoGuide = [[UILayoutGuide alloc] init]; @@ -561,41 +624,94 @@ // All of the guides are of the same height, and vertically centered in the // control. for (UILayoutGuide* guide in @[ incognitoGuide, regularGuide, remoteGuide ]) { - [guide.heightAnchor constraintEqualToConstant:kOverallHeight].active = YES; + if (UseSymbols()) { + [guide.heightAnchor constraintEqualToConstant:kOverallHeight].active = + YES; + // Guides are all the same width. The regular guide is centered in the + // control, and the incognito and remote guides are on the leading and + // trailing sides of it, with separators in between. + [guide.widthAnchor constraintEqualToConstant:kSegmentWidth].active = YES; + } else { + [guide.heightAnchor constraintEqualToConstant:kLegacyOverallHeight] + .active = YES; + } [guide.centerYAnchor constraintEqualToAnchor:self.centerYAnchor].active = YES; } - // Guides are all the same width (except the regular guide is wider to include - // the separators on either side of it. The regular guide is centered in the - // control, and the incognito and remote guides are on the leading and - // trailing sides of it. - [NSLayoutConstraint activateConstraints:@[ - [incognitoGuide.widthAnchor constraintEqualToConstant:kSegmentWidth], - [regularGuide.widthAnchor - constraintEqualToConstant:kSegmentWidth + 2 * kSeparatorWidth], - [remoteGuide.widthAnchor constraintEqualToConstant:kSegmentWidth], - [regularGuide.centerXAnchor constraintEqualToAnchor:self.centerXAnchor], - [incognitoGuide.trailingAnchor - constraintEqualToAnchor:regularGuide.leadingAnchor], - [remoteGuide.leadingAnchor - constraintEqualToAnchor:regularGuide.trailingAnchor] - ]]; + if (UseSymbols()) { + UIView* firstSeparator = [self newSeparator]; + [self addSubview:firstSeparator]; + self.firstSeparator = firstSeparator; + UIView* secondSeparator = [self newSeparator]; + [self addSubview:secondSeparator]; + self.secondSeparator = secondSeparator; + + [NSLayoutConstraint activateConstraints:@[ + [incognitoGuide.trailingAnchor + constraintEqualToAnchor:firstSeparator.leadingAnchor], + [firstSeparator.trailingAnchor + constraintEqualToAnchor:regularGuide.leadingAnchor], + [regularGuide.centerXAnchor constraintEqualToAnchor:self.centerXAnchor], + [regularGuide.trailingAnchor + constraintEqualToAnchor:secondSeparator.leadingAnchor], + [secondSeparator.trailingAnchor + constraintEqualToAnchor:remoteGuide.leadingAnchor], + + [firstSeparator.centerYAnchor constraintEqualToAnchor:self.centerYAnchor], + [secondSeparator.centerYAnchor + constraintEqualToAnchor:self.centerYAnchor], + ]]; + + } else { + // Guides are all the same width (except the regular guide is wider to + // include the separators on either side of it). The regular guide is + // centered in the control, and the incognito and remote guides are on the + // leading and trailing sides of it. + [NSLayoutConstraint activateConstraints:@[ + [incognitoGuide.widthAnchor + constraintEqualToConstant:kLegacySegmentWidth], + [regularGuide.widthAnchor + constraintEqualToConstant:kLegacySegmentWidth + 2 * kSeparatorWidth], + [remoteGuide.widthAnchor constraintEqualToConstant:kLegacySegmentWidth], + [regularGuide.centerXAnchor constraintEqualToAnchor:self.centerXAnchor], + [incognitoGuide.trailingAnchor + constraintEqualToAnchor:regularGuide.leadingAnchor], + [remoteGuide.leadingAnchor + constraintEqualToAnchor:regularGuide.trailingAnchor] + ]]; + } // Add the slider above the section images and labels. - CGRect sliderFrame = CGRectMake(0, 0, kSliderWidth, kSliderHeight); + CGRect sliderFrame; + if (UseSymbols()) { + sliderFrame = + CGRectMake(0, kSliderVerticalMargin, kSliderWidth, kSliderHeight); + } else { + sliderFrame = CGRectMake(0, 0, kLegacySliderWidth, kSliderHeight); + } UIView* slider = [[UIView alloc] initWithFrame:sliderFrame]; - slider.layer.cornerRadius = kCornerRadius; + slider.layer.cornerRadius = kSliderCornerRadius; slider.layer.masksToBounds = YES; - slider.backgroundColor = UIColorFromRGB(kSliderColor); + if (UseSymbols()) { + slider.backgroundColor = UIColor.whiteColor; + } else { + slider.backgroundColor = UIColorFromRGB(kLegacySliderColor); + } [self addSubview:slider]; self.sliderView = slider; // Selected images and labels are added to the selected image view so they // will be clipped by the slider. - UIView* selectedImageView = [[UIView alloc] - initWithFrame:(CGRectMake(0, 0, kOverallWidth, kOverallHeight))]; + CGRect selectedImageFrame; + if (UseSymbols()) { + selectedImageFrame = CGRectMake(0, 0, kOverallWidth, kOverallHeight); + } else { + selectedImageFrame = + CGRectMake(0, 0, kLegacyOverallWidth, kLegacyOverallHeight); + } + UIView* selectedImageView = [[UIView alloc] initWithFrame:selectedImageFrame]; selectedImageView.userInteractionEnabled = NO; [self.sliderView addSubview:selectedImageView]; self.selectedImageView = selectedImageView; @@ -611,7 +727,12 @@ [self.selectedImageView addSubview:regularSelectedLabel]; self.regularSelectedLabel = regularSelectedLabel; - CGRect segmentRect = CGRectMake(0, 0, kSegmentWidth, kOverallHeight); + CGRect segmentRect; + if (UseSymbols()) { + segmentRect = CGRectMake(0, 0, kSegmentWidth, kOverallHeight); + } else { + segmentRect = CGRectMake(0, 0, kLegacySegmentWidth, kLegacyOverallHeight); + } UIView* incognitoHoverView = [[UIView alloc] initWithFrame:segmentRect]; UIView* regularHoverView = [[UIView alloc] initWithFrame:segmentRect]; UIView* remoteHoverView = [[UIView alloc] initWithFrame:segmentRect]; @@ -654,13 +775,26 @@ // Selected labels use a different size and are black. - (UILabel*)labelSelected:(BOOL)selected { CGFloat size = selected ? kSelectedLabelSize : kLabelSize; - UIColor* color = - selected ? UIColorFromRGB(kSelectedColor) : UIColorFromRGB(kSliderColor); + UIColor* color; + if (UseSymbols()) { + color = selected ? UIColor.blackColor : [UIColor colorNamed:kGrey300Color]; + } else { + color = selected ? UIColorFromRGB(kLegacySelectedColor) + : UIColorFromRGB(kLegacySliderColor); + } UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, size, size)]; label.backgroundColor = UIColor.clearColor; label.textAlignment = NSTextAlignmentCenter; label.textColor = color; - label.font = [UIFont systemFontOfSize:size * .6 weight:UIFontWeightBold]; + if (UseSymbols()) { + CGFloat fontSize = size * .6; + UIFont* font = [UIFont systemFontOfSize:fontSize weight:UIFontWeightBold]; + UIFontDescriptor* descriptor = [font.fontDescriptor + fontDescriptorWithDesign:UIFontDescriptorSystemDesignRounded]; + label.font = [UIFont fontWithDescriptor:descriptor size:fontSize]; + } else { + label.font = [UIFont systemFontOfSize:size * .6 weight:UIFontWeightBold]; + } return label; } @@ -699,6 +833,19 @@ } } +// Creates and returns a new separator, with constraints on its height/width. +- (UIView*)newSeparator { + UIView* separator = [[UIView alloc] init]; + separator.backgroundColor = [UIColor colorNamed:kGrey700Color]; + separator.layer.cornerRadius = kSeparatorWidth / 2.0; + separator.translatesAutoresizingMaskIntoConstraints = NO; + [separator.heightAnchor constraintEqualToConstant:kSeparatorHeight].active = + YES; + [separator.widthAnchor constraintEqualToConstant:kSeparatorWidth].active = + YES; + return separator; +} + #pragma mark UIPointerInteractionDelegate - (UIPointerRegion*)pointerInteraction:(UIPointerInteraction*)interaction @@ -716,7 +863,7 @@ initWithView:interaction.view]]; UIPointerShape* shape = [UIPointerShape shapeWithRoundedRect:interaction.view.frame - cornerRadius:kCornerRadius]; + cornerRadius:kSliderCornerRadius]; return [UIPointerStyle styleWithEffect:effect shape:shape]; } @@ -725,8 +872,9 @@ @implementation TabGridPageControlBackground - (instancetype)init { - self = - [super initWithFrame:CGRectMake(0, 0, kBackgroundWidth, kSegmentHeight)]; + DCHECK(!UseSymbols()); + CGRect frame = CGRectMake(0, 0, kLegacyBackgroundWidth, kLegacySegmentHeight); + self = [super initWithFrame:frame]; if (self) { self.backgroundColor = UIColor.clearColor; } @@ -734,12 +882,13 @@ } - (CGSize)intrinsicContentsSize { - return CGSizeMake(kBackgroundWidth, kSegmentHeight); + return CGSizeMake(kLegacyBackgroundWidth, kLegacySegmentHeight); } - (void)drawRect:(CGRect)rect { CGContextRef drawing = UIGraphicsGetCurrentContext(); - UIColor* backgroundColor = UIColorFromRGB(kBackgroundColor, kBackgroundAlpha); + UIColor* backgroundColor = [UIColor colorWithWhite:1 + alpha:kLegacyBackgroundAlpha]; CGContextSetFillColorWithColor(drawing, backgroundColor.CGColor); CGRect fillRect = CGRectMake(0, 0, kSegmentWidth, kSegmentHeight); CGContextFillRect(drawing, fillRect);
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 index 89213d5..78b795e 100644 --- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -997a5beb33a8e83c09b39712180e890ff02b359a \ No newline at end of file +47bb49160c55208b4af1ff0f026d5fe18ed1af56 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 index 29260a1..dc096b5 100644 --- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -8b419238ee65422d55855bcd3933f3a227045070 \ No newline at end of file +7f25830968619aad88f9dc5ce3545f84d4069522 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 index 45e155e9..8ef6697 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -ff118e39f07f18020c8f60de85cae4b933f89eb7 \ No newline at end of file +7107da3eb1ec2b35121f06840c9566cb3fb48d0b \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 index 2180bf2..65b7606fca 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -54c1b98462c8b44a97c03bcf3850bb1329e5029d \ No newline at end of file +27ddf93ba8c5ef580e1c8ff1675006f424531b2d \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 index 6e1af0e..80bbd63f 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -295f34910b160ccf8caf15b801ebb5a8e5dba0f7 \ No newline at end of file +3346c7d419df0e292e764999b355f47e3a5c77c0 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 index 3c267ae..8ca74d2 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -63239915aa5059d10efe22b312d9c40cfd3fbb34 \ No newline at end of file +61e5d96ae8d90481ee230c2ac1219a4298ca9ddf \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 index a5385fa..96119c8c 100644 --- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -a1ccf0dabed13ec71301c719a8ccfa4cf466f5bb \ No newline at end of file +2d667bcb1954a89586b58a04dbf8d38ca902d4a7 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 index 5549013..c618a0c 100644 --- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -65ffad4c7e4f485a9f1b68affe14499c7519df0f \ No newline at end of file +3e2007c07d506e2ccfe534cd999a569bb99b0709 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 index 19a666c..e92ae41 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -b6e8a718854ee023e180ecb1749093598ec8f7c1 \ No newline at end of file +0422e7b8268197e7588ed1343a091b1cb60b52e9 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 index ce010af0..a5e2f137 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -17265817754bd422944d50df309373eee4e0be78 \ No newline at end of file +0e568a4fdee7c7af36606910766bff827309ae5e \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 index d22df79..67426b0 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -ce7e0faa409004f090fb9cd5f919f361383a1c7c \ No newline at end of file +912be2b58ee353fa897d6a1e7d76e33842ad4c0b \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 index 91b6d54c..02355bf8 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -778eac85d7f0bc3222f56d8cca21a4b76ab4258e \ No newline at end of file +e38a111fbd973344e599c99749ea78ca74aefbd9 \ No newline at end of file
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn index 35d8bce..7dcd29a 100644 --- a/media/gpu/BUILD.gn +++ b/media/gpu/BUILD.gn
@@ -99,6 +99,9 @@ libs = [] ldflags = [] + # V4L2 and VAAPI for video acceleration should not be enabled simultaneously. + assert(!(use_v4l2_codec && use_vaapi)) + # TODO(crbug.com/1006266): consider using |use_chromeos_video_acceleration|. if (use_v4l2_codec || use_vaapi) { public_deps += [
diff --git a/media/gpu/chromeos/BUILD.gn b/media/gpu/chromeos/BUILD.gn index 2b1f70c..7cfe1cf 100644 --- a/media/gpu/chromeos/BUILD.gn +++ b/media/gpu/chromeos/BUILD.gn
@@ -7,6 +7,9 @@ import("//testing/test.gni") import("//third_party/protobuf/proto_library.gni") +# V4L2 and VAAPI for video acceleration should not be enabled simultaneously. +assert(!(use_v4l2_codec && use_vaapi)) + assert(use_v4l2_codec || use_vaapi) # V4L2 or Vaapi imply the OS is Linux or ChromeOS
diff --git a/media/gpu/chromeos/fourcc.cc b/media/gpu/chromeos/fourcc.cc index cf76edf2..cc30a89 100644 --- a/media/gpu/chromeos/fourcc.cc +++ b/media/gpu/chromeos/fourcc.cc
@@ -10,9 +10,7 @@ #if BUILDFLAG(USE_V4L2_CODEC) #include <linux/videodev2.h> -#endif // BUILDFLAG(USE_V4L2_CODEC) - -#if BUILDFLAG(USE_VAAPI) +#elif BUILDFLAG(USE_VAAPI) #include <va/va.h> #endif // BUILDFLAG(USE_VAAPI) @@ -201,9 +199,7 @@ // Fourcc as V4L2. return static_cast<uint32_t>(value_); } -#endif // BUILDFLAG(USE_V4L2_CODEC) - -#if BUILDFLAG(USE_VAAPI) +#elif BUILDFLAG(USE_VAAPI) // static absl::optional<Fourcc> Fourcc::FromVAFourCC(uint32_t va_fourcc) { switch (va_fourcc) {
diff --git a/media/gpu/chromeos/fourcc.h b/media/gpu/chromeos/fourcc.h index 89195916..f61e7362 100644 --- a/media/gpu/chromeos/fourcc.h +++ b/media/gpu/chromeos/fourcc.h
@@ -115,8 +115,7 @@ // Converts a V4L2PixFmt to Fourcc. // Returns nullopt for invalid input. static absl::optional<Fourcc> FromV4L2PixFmt(uint32_t v4l2_pix_fmt); -#endif // BUILDFLAG(USE_V4L2_CODEC) -#if BUILDFLAG(USE_VAAPI) +#elif BUILDFLAG(USE_VAAPI) // Converts a VAFourCC to Fourcc. // Returns nullopt for invalid input. static absl::optional<Fourcc> FromVAFourCC(uint32_t va_fourcc); @@ -130,8 +129,7 @@ // Returns the V4L2PixFmt counterpart of the value. // Returns 0 if no mapping is found. uint32_t ToV4L2PixFmt() const; -#endif // BUILDFLAG(USE_V4L2_CODEC) -#if BUILDFLAG(USE_VAAPI) +#elif BUILDFLAG(USE_VAAPI) // Returns the VAFourCC counterpart of the value. // Returns nullopt if no mapping is found. absl::optional<uint32_t> ToVAFourCC() const;
diff --git a/media/gpu/chromeos/fourcc_unittests.cc b/media/gpu/chromeos/fourcc_unittests.cc index 96947ebb..128d73c 100644 --- a/media/gpu/chromeos/fourcc_unittests.cc +++ b/media/gpu/chromeos/fourcc_unittests.cc
@@ -10,8 +10,7 @@ #if BUILDFLAG(USE_V4L2_CODEC) #include <linux/videodev2.h> -#endif // BUILDFLAG(USE_V4L2_CODEC) -#if BUILDFLAG(USE_VAAPI) +#elif BUILDFLAG(USE_VAAPI) #include <va/va.h> #endif // BUILDFLAG(USE_VAAPI) @@ -104,9 +103,9 @@ V4L2_PIX_FMT_YUV422M, Fourcc::FromVideoPixelFormat(PIXEL_FORMAT_I422, false)->ToV4L2PixFmt()); } -#endif // BUILDFLAG(USE_V4L2_CODEC) -#if BUILDFLAG(USE_VAAPI) +#elif BUILDFLAG(USE_VAAPI) + // Checks that converting a VaFourCC to Fourcc and back to VaFourCC // yields the same format as the original one. static void CheckFromVAFourCCAndBack(uint32_t va_fourcc) { @@ -155,7 +154,7 @@ EXPECT_EQ(static_cast<uint32_t>(VA_FOURCC_P010), *Fourcc::FromVideoPixelFormat(PIXEL_FORMAT_P016LE)->ToVAFourCC()); } -#endif // BUILDFLAG(USE_VAAPI) +#endif TEST(FourccTest, FourccToSinglePlanar) { EXPECT_EQ(Fourcc(Fourcc::YU12).ToSinglePlanar(), Fourcc(Fourcc::YU12));
diff --git a/media/gpu/chromeos/image_processor_factory.cc b/media/gpu/chromeos/image_processor_factory.cc index cc1379fb..96b9eb5e 100644 --- a/media/gpu/chromeos/image_processor_factory.cc +++ b/media/gpu/chromeos/image_processor_factory.cc
@@ -22,13 +22,11 @@ #if BUILDFLAG(USE_VAAPI) #include "media/gpu/vaapi/vaapi_image_processor_backend.h" #include "media/gpu/vaapi/vaapi_wrapper.h" -#endif // BUILDFLAG(USE_VAAPI) - -#if BUILDFLAG(USE_V4L2_CODEC) +#elif BUILDFLAG(USE_V4L2_CODEC) #include "media/gpu/v4l2/v4l2_device.h" #include "media/gpu/v4l2/v4l2_image_processor_backend.h" #include "media/gpu/v4l2/v4l2_vda_helpers.h" -#endif // BUILDFLAG(USE_V4L2_CODEC) +#endif namespace media { @@ -82,9 +80,9 @@ output_config, ImageProcessor::OutputMode::IMPORT, VIDEO_ROTATION_0, std::move(error_cb), std::move(client_task_runner)); } -#endif // BUILDFLAG(USE_VAAPI) -#if BUILDFLAG(USE_V4L2_CODEC) && !BUILDFLAG(USE_VAAPI) +#elif BUILDFLAG(USE_V4L2_CODEC) + std::unique_ptr<ImageProcessor> CreateV4L2ImageProcessorWithInputCandidates( const std::vector<PixelLayoutCandidate>& input_candidates, const gfx::Rect& visible_rect, @@ -227,7 +225,7 @@ output_config, ImageProcessor::OutputMode::IMPORT, VIDEO_ROTATION_0, std::move(error_cb), std::move(client_task_runner)); } -#endif // BUILDFLAG(USE_V4L2_CODEC) && !BUILDFLAG(USE_VAAPI) +#endif } // namespace @@ -247,7 +245,7 @@ #elif BUILDFLAG(USE_V4L2_CODEC) create_funcs.push_back(base::BindRepeating( &V4L2ImageProcessorBackend::Create, V4L2Device::Create(), num_buffers)); -#endif // BUILDFLAG(USE_V4L2_CODEC) +#endif create_funcs.push_back( base::BindRepeating(&LibYUVImageProcessorBackend::Create)); @@ -299,7 +297,7 @@ if (processor) return processor; -#endif // BUILDFLAG(USE_V4L2_CODEC) +#endif // TODO(crbug.com/1004727): Implement LibYUVImageProcessorBackend. When doing // so, we must keep in mind that it might not be desirable to fallback to
diff --git a/media/gpu/gpu_video_encode_accelerator_factory.cc b/media/gpu/gpu_video_encode_accelerator_factory.cc index 9264f446..484fe741 100644 --- a/media/gpu/gpu_video_encode_accelerator_factory.cc +++ b/media/gpu/gpu_video_encode_accelerator_factory.cc
@@ -21,9 +21,6 @@ #include "media/gpu/macros.h" #include "media/video/video_encode_accelerator.h" -#if BUILDFLAG(USE_V4L2_CODEC) -#include "media/gpu/v4l2/v4l2_video_encode_accelerator.h" -#endif #if BUILDFLAG(IS_ANDROID) #include "media/gpu/android/android_video_encode_accelerator.h" #include "media/gpu/android/ndk_video_encode_accelerator.h" @@ -34,7 +31,9 @@ #if BUILDFLAG(IS_WIN) #include "media/gpu/windows/media_foundation_video_encode_accelerator_win.h" #endif -#if BUILDFLAG(USE_VAAPI) +#if BUILDFLAG(USE_V4L2_CODEC) +#include "media/gpu/v4l2/v4l2_video_encode_accelerator.h" +#elif BUILDFLAG(USE_VAAPI) #include "media/gpu/vaapi/vaapi_video_encode_accelerator.h" #endif #if BUILDFLAG(IS_FUCHSIA) @@ -58,9 +57,7 @@ return nullptr; #endif } -#endif - -#if BUILDFLAG(USE_VAAPI) +#elif BUILDFLAG(USE_VAAPI) std::unique_ptr<VideoEncodeAccelerator> CreateVaapiVEA() { return base::WrapUnique<VideoEncodeAccelerator>( new VaapiVideoEncodeAccelerator()); @@ -129,10 +126,10 @@ #else vea_factory_functions.push_back(base::BindRepeating(&CreateVaapiVEA)); #endif -#endif -#if BUILDFLAG(USE_V4L2_CODEC) +#elif BUILDFLAG(USE_V4L2_CODEC) vea_factory_functions.push_back(base::BindRepeating(&CreateV4L2VEA)); #endif + #if BUILDFLAG(IS_ANDROID) vea_factory_functions.push_back(base::BindRepeating(&CreateAndroidVEA)); #endif
diff --git a/media/gpu/sandbox/hardware_video_decoding_sandbox_hook_linux.cc b/media/gpu/sandbox/hardware_video_decoding_sandbox_hook_linux.cc index 25e31b6..b8fd522b 100644 --- a/media/gpu/sandbox/hardware_video_decoding_sandbox_hook_linux.cc +++ b/media/gpu/sandbox/hardware_video_decoding_sandbox_hook_linux.cc
@@ -72,7 +72,7 @@ BrokerFilePermission::ReadOnlyRecursive(path + "/")); } } -#endif // BUILDFLAG(USE_V4L2_CODEC) +#endif // TODO(b/195769334): consider using the type of client to decide if we should // allow access to the render node: @@ -125,7 +125,7 @@ #else dlopen("/usr/lib/libv4l2.so", RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE); #endif // defined(__aarch64__) -#endif // BUILDFLAG(USE_VAAPI) +#endif return true; }
diff --git a/sandbox/win/src/policy_engine_opcodes.cc b/sandbox/win/src/policy_engine_opcodes.cc index b9b856a..51c3befa 100644 --- a/sandbox/win/src/policy_engine_opcodes.cc +++ b/sandbox/win/src/policy_engine_opcodes.cc
@@ -44,7 +44,7 @@ size_t OpcodeFactory::memory_size() const { DCHECK_GE(memory_bottom_, memory_top_); - return memory_bottom_ - memory_top_; + return static_cast<size_t>(memory_bottom_ - memory_top_); } template <int> @@ -57,7 +57,7 @@ // Does not require input parameter. PolicyOpcode* OpcodeFactory::MakeOpAlwaysFalse(uint32_t options) { - return MakeBase(OP_ALWAYS_FALSE, options, -1); + return MakeBase(OP_ALWAYS_FALSE, options); } template <> @@ -72,7 +72,7 @@ // Does not require input parameter. PolicyOpcode* OpcodeFactory::MakeOpAlwaysTrue(uint32_t options) { - return MakeBase(OP_ALWAYS_TRUE, options, -1); + return MakeBase(OP_ALWAYS_TRUE, options); } template <> @@ -110,7 +110,7 @@ // Argument 0 is the stored number to match. // Argument 1 is the C++ type of the 0th argument. -PolicyOpcode* OpcodeFactory::MakeOpNumberMatch(int16_t selected_param, +PolicyOpcode* OpcodeFactory::MakeOpNumberMatch(uint8_t selected_param, uint32_t match, uint32_t options) { PolicyOpcode* opcode = MakeBase(OP_NUMBER_MATCH, options, selected_param); @@ -121,7 +121,7 @@ return opcode; } -PolicyOpcode* OpcodeFactory::MakeOpVoidPtrMatch(int16_t selected_param, +PolicyOpcode* OpcodeFactory::MakeOpVoidPtrMatch(uint8_t selected_param, const void* match, uint32_t options) { PolicyOpcode* opcode = MakeBase(OP_NUMBER_MATCH, options, selected_param); @@ -158,7 +158,7 @@ // Argument 0 is the stored lower bound to match. // Argument 1 is the stored upper bound to match. -PolicyOpcode* OpcodeFactory::MakeOpNumberMatchRange(int16_t selected_param, +PolicyOpcode* OpcodeFactory::MakeOpNumberMatchRange(uint8_t selected_param, uint32_t lower_bound, uint32_t upper_bound, uint32_t options) { @@ -195,7 +195,7 @@ // Requires a uint32_t in selected_param. // Argument 0 is the stored number to match. -PolicyOpcode* OpcodeFactory::MakeOpNumberAndMatch(int16_t selected_param, +PolicyOpcode* OpcodeFactory::MakeOpNumberAndMatch(uint8_t selected_param, uint32_t match, uint32_t options) { PolicyOpcode* opcode = MakeBase(OP_NUMBER_AND_MATCH, options, selected_param); @@ -227,7 +227,7 @@ // as noted in the header file. // Argument 3 is the string matching options. -PolicyOpcode* OpcodeFactory::MakeOpWStringMatch(int16_t selected_param, +PolicyOpcode* OpcodeFactory::MakeOpWStringMatch(uint8_t selected_param, const wchar_t* match_str, int start_position, StringMatchOptions match_opts, @@ -237,12 +237,12 @@ if ('\0' == match_str[0]) return nullptr; - int length = lstrlenW(match_str); + size_t length = wcslen(match_str); PolicyOpcode* opcode = MakeBase(OP_WSTRING_MATCH, options, selected_param); if (!opcode) return nullptr; - ptrdiff_t delta_str = AllocRelative(opcode, match_str, wcslen(match_str) + 1); + ptrdiff_t delta_str = AllocRelative(opcode, match_str, length + 1); if (0 == delta_str) return nullptr; opcode->SetArgument(0, delta_str); @@ -268,7 +268,7 @@ return EVAL_FALSE; int start_position = 0; - int match_len = 0; + size_t match_len = 0; unsigned int match_opts = 0; opcode->GetArgument(1, &match_len); opcode->GetArgument(2, &start_position); @@ -278,7 +278,7 @@ // Advance the source string to the last successfully evaluated position // according to the match context. source_str = &source_str[context->position]; - int source_len = static_cast<int>(GetNtExports()->wcslen(source_str)); + size_t source_len = GetNtExports()->wcslen(source_str); if (0 == source_len) { // If we reached the end of the source string there is nothing we can @@ -298,22 +298,23 @@ // Case 2: We skip to the end and compare once. // Case 3: We match the first substring (if we find any). if (start_position >= 0) { + size_t start_offset = static_cast<size_t>(start_position); if (kSeekToEnd == start_position) { - start_position = source_len - match_len; + start_offset = static_cast<size_t>(source_len - match_len); } else if (match_opts & EXACT_LENGTH) { // A sub-case of case 3 is when the EXACT_LENGTH flag is on // the match needs to be not just substring but full match. - if ((match_len + start_position) != source_len) { + if ((match_len + start_offset) != source_len) { return EVAL_FALSE; } } // Advance start_pos characters. Warning! this does not consider // utf16 encodings (surrogate pairs) or other Unicode 'features'. - source_str += start_position; + source_str += start_offset; // Since we skipped, lets reevaluate just the lengths again. - if ((match_len + start_position) > source_len) { + if ((match_len + start_offset) > source_len) { return EVAL_FALSE; } @@ -326,7 +327,7 @@ if (0 == GetNtExports()->RtlCompareUnicodeString(&match_ustr, &source_ustr, case_sensitive)) { // Match! update the match context. - context->position += start_position + match_len; + context->position += start_offset + match_len; return EVAL_TRUE; } else { return EVAL_FALSE; @@ -342,7 +343,8 @@ if (0 == GetNtExports()->RtlCompareUnicodeString( &match_ustr, &source_ustr, case_sensitive)) { // Match! update the match context. - context->position += (source_ustr.Buffer - source_str) + match_len; + context->position += + static_cast<size_t>(source_ustr.Buffer - source_str) + match_len; return EVAL_TRUE; } ++source_ustr.Buffer; @@ -355,9 +357,7 @@ ////////////////////////////////////////////////////////////////////////////// // OpcodeMaker (other member functions). -PolicyOpcode* OpcodeFactory::MakeBase(OpcodeID opcode_id, - uint32_t options, - int16_t selected_param) { +PolicyOpcode* OpcodeFactory::MakeBase(OpcodeID opcode_id, uint32_t options) { if (memory_size() < sizeof(PolicyOpcode)) return nullptr; @@ -368,6 +368,18 @@ memory_top_ += sizeof(PolicyOpcode); opcode->opcode_id_ = opcode_id; opcode->SetOptions(options); + opcode->has_param_ = 0; + opcode->parameter_ = 0; + return opcode; +} + +PolicyOpcode* OpcodeFactory::MakeBase(OpcodeID opcode_id, + uint32_t options, + uint8_t selected_param) { + PolicyOpcode* opcode = MakeBase(opcode_id, options); + if (!opcode) + return nullptr; + opcode->has_param_ = 1; opcode->parameter_ = selected_param; return opcode; } @@ -404,8 +416,8 @@ if (!call_params) return EVAL_ERROR; const ParameterSet* selected_param = nullptr; - if (parameter_ >= 0) { - if (static_cast<size_t>(parameter_) >= param_count) { + if (has_param_) { + if (parameter_ >= param_count) { return EVAL_ERROR; } selected_param = &call_params[parameter_];
diff --git a/sandbox/win/src/policy_engine_opcodes.h b/sandbox/win/src/policy_engine_opcodes.h index fbaeecd..a457fee 100644 --- a/sandbox/win/src/policy_engine_opcodes.h +++ b/sandbox/win/src/policy_engine_opcodes.h
@@ -73,8 +73,8 @@ TERMINATE_PROCESS, // Destroy target process. Do IPC as well. }; -// The following are the implemented opcodes. -enum OpcodeID { +// The following are the implemented opcodes. uint16_t purely to pack nicely. +enum OpcodeID : uint16_t { OP_ALWAYS_FALSE, // Evaluates to false (EVAL_FALSE). OP_ALWAYS_TRUE, // Evaluates to true (EVAL_TRUE). OP_NUMBER_MATCH, // Match a 32-bit integer as n == a. @@ -195,7 +195,7 @@ void SetOptions(uint32_t options) { options_ = options; } // Returns the parameter of the function the opcode concerns. - uint16_t GetParameter() const { return parameter_; } + uint8_t GetParameter() const { return parameter_; } private: static const size_t kArgumentCount = 4; // The number of supported argument. @@ -213,7 +213,10 @@ EvalResult EvaluateHelper(const ParameterSet* parameters, MatchContext* match); OpcodeID opcode_id_; - int16_t parameter_; + // Used a boolean field but provided as a uint8_t to maintain packing. + uint8_t has_param_; + // Not used if has_param_ is false. + uint8_t parameter_; uint32_t options_; OpcodeArgument arguments_[PolicyOpcode::kArgumentCount]; }; @@ -301,7 +304,7 @@ // selected_param: index of the input argument. It must be a uint32_t or the // evaluation result will generate a EVAL_ERROR. // match: the number to compare against the selected_param. - PolicyOpcode* MakeOpNumberMatch(int16_t selected_param, + PolicyOpcode* MakeOpNumberMatch(uint8_t selected_param, uint32_t match, uint32_t options); @@ -309,7 +312,7 @@ // selected_param: index of the input argument. It must be an void* or the // evaluation result will generate a EVAL_ERROR. // match: the pointer numeric value to compare against selected_param. - PolicyOpcode* MakeOpVoidPtrMatch(int16_t selected_param, + PolicyOpcode* MakeOpVoidPtrMatch(uint8_t selected_param, const void* match, uint32_t options); @@ -317,7 +320,7 @@ // selected_param: index of the input argument. It must be a uint32_t or the // evaluation result will generate a EVAL_ERROR. // lower_bound, upper_bound: the range to compare against selected_param. - PolicyOpcode* MakeOpNumberMatchRange(int16_t selected_param, + PolicyOpcode* MakeOpNumberMatchRange(uint8_t selected_param, uint32_t lower_bound, uint32_t upper_bound, uint32_t options); @@ -335,7 +338,7 @@ // current implementation. // match_opts: Indicates additional matching flags. Currently CaseInsensitive // is supported. - PolicyOpcode* MakeOpWStringMatch(int16_t selected_param, + PolicyOpcode* MakeOpWStringMatch(uint8_t selected_param, const wchar_t* match_str, int start_position, StringMatchOptions match_opts, @@ -345,17 +348,17 @@ // selected_param: index of the input argument. It must be uint32_t or the // evaluation result will generate a EVAL_ERROR. // match: the value to bitwise AND against selected_param. - PolicyOpcode* MakeOpNumberAndMatch(int16_t selected_param, + PolicyOpcode* MakeOpNumberAndMatch(uint8_t selected_param, uint32_t match, uint32_t options); private: // Constructs the common part of every opcode. selected_param is the index - // of the input param to use when evaluating the opcode. Pass -1 in - // selected_param to indicate that no input parameter is required. + // of the input param to use when evaluating the opcode. + PolicyOpcode* MakeBase(OpcodeID opcode_id, uint32_t options); PolicyOpcode* MakeBase(OpcodeID opcode_id, uint32_t options, - int16_t selected_param); + uint8_t selected_param); // Allocates (and copies) a string (of size length) inside the buffer and // returns the displacement with respect to start.
diff --git a/sandbox/win/src/policy_low_level.cc b/sandbox/win/src/policy_low_level.cc index e67077c..0f47c96 100644 --- a/sandbox/win/src/policy_low_level.cc +++ b/sandbox/win/src/policy_low_level.cc
@@ -157,7 +157,7 @@ // to zero. bool PolicyRule::GenStringOpcode(RuleType rule_type, StringMatchOptions match_opts, - uint16_t parameter, + uint8_t parameter, int state, bool last_call, int* skip_count, @@ -221,7 +221,7 @@ } bool PolicyRule::AddStringMatch(RuleType rule_type, - int16_t parameter, + uint8_t parameter, const wchar_t* string, StringMatchOptions match_opts) { if (done_) { @@ -283,7 +283,7 @@ } bool PolicyRule::AddNumberMatch(RuleType rule_type, - int16_t parameter, + uint8_t parameter, uint32_t number, RuleOp comparison_op) { if (done_) {
diff --git a/sandbox/win/src/policy_low_level.h b/sandbox/win/src/policy_low_level.h index c2828a1c..fd7d1396 100644 --- a/sandbox/win/src/policy_low_level.h +++ b/sandbox/win/src/policy_low_level.h
@@ -140,7 +140,7 @@ // string: is the desired matching pattern. // match_opts: if the pattern matching is case sensitive or not. bool AddStringMatch(RuleType rule_type, - int16_t parameter, + uint8_t parameter, const wchar_t* string, StringMatchOptions match_opts); @@ -150,7 +150,7 @@ // number: the value to compare the input to. // comparison_op: the comparison kind (equal, logical and, etc). bool AddNumberMatch(RuleType rule_type, - int16_t parameter, + uint8_t parameter, uint32_t number, RuleOp comparison_op); @@ -168,7 +168,7 @@ // in AddStringMatch. bool GenStringOpcode(RuleType rule_type, StringMatchOptions match_opts, - uint16_t parameter, + uint8_t parameter, int state, bool last_call, int* skip_count,
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 2f5742b..b534164f 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -5922,9 +5922,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "isolate_profile_data": true, "merge": { "args": [], @@ -5936,8 +5936,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "dimension_sets": [ @@ -6088,9 +6088,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "isolate_profile_data": true, "merge": { "args": [], @@ -6102,8 +6102,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "dimension_sets": [ @@ -6239,9 +6239,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "isolate_profile_data": true, "merge": { "args": [], @@ -6253,8 +6253,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index aeeb737..5c33ac2 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -87396,9 +87396,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "isolate_profile_data": true, "merge": { "args": [], @@ -87410,8 +87410,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -87532,9 +87532,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "isolate_profile_data": true, "merge": { "args": [], @@ -87546,8 +87546,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -87658,9 +87658,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "isolate_profile_data": true, "merge": { "args": [], @@ -87672,8 +87672,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -89013,9 +89013,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -89026,8 +89026,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "dimension_sets": [ @@ -89179,9 +89179,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -89192,8 +89192,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "dimension_sets": [ @@ -89330,9 +89330,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -89343,8 +89343,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "dimension_sets": [ @@ -90865,9 +90865,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -90878,8 +90878,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "dimension_sets": [ @@ -91031,9 +91031,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -91044,8 +91044,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "dimension_sets": [ @@ -91182,9 +91182,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -91195,8 +91195,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "dimension_sets": [ @@ -91994,9 +91994,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -92007,8 +92007,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index bddee2b..cc717ab 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -18559,10 +18559,10 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome", "--test-launcher-print-test-stdio=always" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "isolate_profile_data": true, "merge": { "args": [], @@ -18574,8 +18574,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "dimension_sets": [ @@ -18733,10 +18733,10 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome", "--test-launcher-print-test-stdio=always" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "isolate_profile_data": true, "merge": { "args": [], @@ -18748,8 +18748,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "dimension_sets": [ @@ -18889,10 +18889,10 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome", "--test-launcher-print-test-stdio=always" ], - "description": "Run with ash-chrome version 110.0.5424.0", + "description": "Run with ash-chrome version 110.0.5425.0", "isolate_profile_data": true, "merge": { "args": [], @@ -18904,8 +18904,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5424.0", - "revision": "version:110.0.5424.0" + "location": "lacros_version_skew_tests_v110.0.5425.0", + "revision": "version:110.0.5425.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/chromium.webrtc.fyi.json b/testing/buildbot/chromium.webrtc.fyi.json index b2fb128..17b5018 100644 --- a/testing/buildbot/chromium.webrtc.fyi.json +++ b/testing/buildbot/chromium.webrtc.fyi.json
@@ -55,96 +55,6 @@ } ] }, - "WebRTC Chromium FYI Android Tests (dbg) (M Nexus5X)": { - "gtest_tests": [ - { - "args": [ - "--gtest_filter=WebRtc*", - "--gs-results-bucket=chromium-result-details", - "--recover-devices", - "--test-launcher-filter-file=../../testing/buildbot/filters/chromium.webrtc.fyi.android.tests.dbg.content_browsertests.filter" - ], - "merge": { - "args": [ - "--bucket", - "chromium-result-details", - "--test-name", - "content_browsertests" - ], - "script": "//build/android/pylib/results/presentation/test_results_presentation.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "device_os": "MMB29Q", - "device_os_type": "userdebug", - "device_type": "bullhead", - "os": "Android" - } - ], - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "content_browsertests", - "test_id_prefix": "ninja://content/test:content_browsertests/" - } - ] - }, - "WebRTC Chromium FYI Android Tests (dbg) (N Nexus5X)": { - "gtest_tests": [ - { - "args": [ - "--gtest_filter=WebRtc*", - "--gs-results-bucket=chromium-result-details", - "--recover-devices", - "--test-launcher-filter-file=../../testing/buildbot/filters/chromium.webrtc.fyi.android.tests.dbg.content_browsertests.filter" - ], - "merge": { - "args": [ - "--bucket", - "chromium-result-details", - "--test-name", - "content_browsertests" - ], - "script": "//build/android/pylib/results/presentation/test_results_presentation.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "device_os": "N", - "device_os_type": "userdebug", - "device_type": "bullhead", - "os": "Android" - } - ], - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "content_browsertests", - "test_id_prefix": "ninja://content/test:content_browsertests/" - } - ] - }, "WebRTC Chromium FYI Android Tests ARM64 (dbg)": { "gtest_tests": [ {
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl index 74bceff..e23031b 100644 --- a/testing/buildbot/mixins.pyl +++ b/testing/buildbot/mixins.pyl
@@ -1050,13 +1050,6 @@ ] }, }, - 'nougat_generic': { - 'swarming': { - 'dimensions': { - 'device_os': 'N', - }, - }, - }, 'oreo-x86-emulator': { '$mixin_append': { 'args': [
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index cc940c4..787e116c 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1676,16 +1676,6 @@ '--test-launcher-filter-file=../../testing/buildbot/filters/chromium.webrtc.fyi.android.tests.dbg.content_browsertests.filter', ], }, - 'WebRTC Chromium FYI Android Tests (dbg) (M Nexus5X)': { - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/chromium.webrtc.fyi.android.tests.dbg.content_browsertests.filter', - ], - }, - 'WebRTC Chromium FYI Android Tests (dbg) (N Nexus5X)': { - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/chromium.webrtc.fyi.android.tests.dbg.content_browsertests.filter', - ], - }, 'WebRTC Chromium FYI Android Tests ARM64 (dbg)': { 'args': [ '--test-launcher-filter-file=../../testing/buildbot/filters/chromium.webrtc.fyi.android.tests.dbg.content_browsertests.filter',
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index cbe9b05..c746f59 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -590,7 +590,6 @@ 'flame', 'marshmallow', 'mdarcy', - 'nougat_generic', 'oreo_fleet', 'pie_fleet', 'walleye', @@ -1598,7 +1597,6 @@ 'flame', 'marshmallow', 'mdarcy', - 'nougat_generic', 'oreo_fleet', 'pie_fleet', 'walleye', @@ -4291,7 +4289,6 @@ 'flame', 'marshmallow', 'mdarcy', - 'nougat_generic', 'oreo_fleet', 'pie_fleet', 'walleye',
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 35e81fbc..25836ad4 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -22,16 +22,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5424.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5425.0/test_ash_chrome', ], - 'description': 'Run with ash-chrome version 110.0.5424.0', + 'description': 'Run with ash-chrome version 110.0.5425.0', 'identifier': 'Lacros version skew testing ash canary', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v110.0.5424.0', - 'revision': 'version:110.0.5424.0', + 'location': 'lacros_version_skew_tests_v110.0.5425.0', + 'revision': 'version:110.0.5425.0', }, ], },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index fcef396e..45b1bad 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -5944,26 +5944,6 @@ 'gtest_tests': 'webrtc_chromium_simple_gtests', }, }, - 'WebRTC Chromium FYI Android Tests (dbg) (M Nexus5X)': { - 'os_type': 'android', - 'mixins': [ - 'marshmallow', - 'bullhead', - ], - 'test_suites': { - 'gtest_tests': 'webrtc_chromium_simple_gtests', - }, - }, - 'WebRTC Chromium FYI Android Tests (dbg) (N Nexus5X)': { - 'os_type': 'android', - 'mixins': [ - 'nougat_generic', - 'bullhead', - ], - 'test_suites': { - 'gtest_tests': 'webrtc_chromium_simple_gtests', - }, - }, 'WebRTC Chromium FYI Android Tests ARM64 (dbg)': { 'os_type': 'android', 'mixins': [
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 9652c2c..d7f723582 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -2769,7 +2769,104 @@ ], "experiments": [ { - "name": "Shopping_Launch", + "name": "Dogfood", + "params": { + "allow_bookmark_type_swapping": "true", + "autodismiss_enabled": "true", + "bookmark_compact_visuals_enabled": "true", + "bookmark_in_app_menu": "true", + "bookmark_visuals_enabled": "true", + "enable_persisted_tab_data_maintenance": "true", + "enable_price_notification": "true", + "enable_price_tracking": "true", + "price_tracking_with_optimization_guide": "true", + "use_root_bookmark_as_default": "true" + }, + "enable_features": [ + "BookmarksImprovedSaveFlow", + "BookmarksRefresh", + "CommercePriceTracking", + "OptimizationGuidePushNotifications", + "ReadLater", + "ShoppingList" + ] + }, + { + "name": "Default_1__M100_C_v5", + "params": { + "use_root_bookmark_as_default": "true" + }, + "enable_features": [ + "ReadLater" + ] + }, + { + "name": "ReadLater_CCT_non_US__NoCustomTab_M100_C_v5", + "params": { + "use_cct": "false", + "use_root_bookmark_as_default": "true" + }, + "enable_features": [ + "ReadLater" + ] + }, + { + "name": "ReadLater_SaveFlow_non_US__SemiIntegratedRedux_M100_C_v5", + "params": { + "allow_bookmark_type_swapping": "true", + "autodismiss_enabled": "true", + "use_root_bookmark_as_default": "true" + }, + "enable_features": [ + "BookmarksImprovedSaveFlow", + "ReadLater" + ] + }, + { + "name": "Default_1__M100_A_v5", + "params": { + "enable_persisted_tab_data_maintenance": "true", + "enable_price_tracking": "true", + "price_tracking_with_optimization_guide": "true", + "use_root_bookmark_as_default": "true" + }, + "enable_features": [ + "CommercePriceTracking", + "ReadLater" + ] + }, + { + "name": "ReadLater_CCT_US__NoCustomTab_M100_A_v5", + "params": { + "enable_persisted_tab_data_maintenance": "true", + "enable_price_tracking": "true", + "price_tracking_with_optimization_guide": "true", + "use_cct": "false", + "use_root_bookmark_as_default": "true" + }, + "enable_features": [ + "CommercePriceTracking", + "ReadLater" + ] + }, + { + "name": "ReadLater_SaveFlow_US__SemiIntegratedRedux_M100_A_v5", + "params": { + "allow_bookmark_type_swapping": "true", + "autodismiss_enabled": "true", + "enable_persisted_tab_data_maintenance": "true", + "enable_price_tracking": "true", + "price_tracking_with_optimization_guide": "true", + "use_root_bookmark_as_default": "true" + }, + "enable_features": [ + "BookmarksImprovedSaveFlow", + "CommercePriceTracking", + "ReadLater" + ] + }, + { + "name": "WallE_US__ShoppingCompact_M100_A_v5", "params": { "autodismiss_enabled": "true", "bookmark_compact_visuals_enabled": "true", @@ -2778,13 +2875,75 @@ "enable_persisted_tab_data_maintenance": "true", "enable_price_notification": "true", "enable_price_tracking": "true", - "price_tracking_with_optimization_guide": "true" + "price_tracking_with_optimization_guide": "true", + "use_root_bookmark_as_default": "true" }, "enable_features": [ "BookmarksImprovedSaveFlow", "BookmarksRefresh", "CommercePriceTracking", "OptimizationGuidePushNotifications", + "ReadLater", + "ShoppingList" + ] + }, + { + "name": "ReadLater_SaveFlow_non_US__SemiIntegrated_NoCCT_M100_C_v7", + "params": { + "allow_bookmark_type_swapping": "true", + "autodismiss_enabled": "true", + "use_cct": "false", + "use_root_bookmark_as_default": "true" + }, + "enable_features": [ + "BookmarksImprovedSaveFlow", + "ReadLater" + ] + }, + { + "name": "WallE_US__ShoppingCompact_WithRL_M100_A_v7", + "params": { + "allow_bookmark_type_swapping": "true", + "autodismiss_enabled": "true", + "bookmark_compact_visuals_enabled": "true", + "bookmark_in_app_menu": "true", + "bookmark_visuals_enabled": "true", + "enable_persisted_tab_data_maintenance": "true", + "enable_price_notification": "true", + "enable_price_tracking": "true", + "price_tracking_with_optimization_guide": "true", + "use_root_bookmark_as_default": "true" + }, + "enable_features": [ + "BookmarksImprovedSaveFlow", + "BookmarksRefresh", + "CommercePriceTracking", + "OptimizationGuidePushNotifications", + "ReadLater", + "ShoppingList" + ] + }, + { + "name": "WallE_US__ShoppingCompact_WithRL_NoCCT_M100_A_v7", + "params": { + "allow_bookmark_type_swapping": "true", + "autodismiss_enabled": "true", + "bookmark_compact_visuals_enabled": "true", + "bookmark_in_app_menu": "true", + "bookmark_visuals_enabled": "true", + "enable_persisted_tab_data_maintenance": "true", + "enable_price_notification": "true", + "enable_price_tracking": "true", + "price_tracking_with_optimization_guide": "true", + "use_cct": "false", + "use_root_bookmark_as_default": "true" + }, + "enable_features": [ + "BookmarksImprovedSaveFlow", + "BookmarksRefresh", + "CommercePriceTracking", + "OptimizationGuidePushNotifications", + "ReadLater", "ShoppingList" ] } @@ -9156,25 +9315,6 @@ ] } ], - "ReadLaterUSOnly": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled", - "params": { - "allow_bookmark_type_swapping": "true", - "use_cct": "false" - }, - "enable_features": [ - "ReadLater" - ] - } - ] - } - ], "RecordPermissionExpirationTimestamps": [ { "platforms": [
diff --git a/third_party/blink/public/common/loader/loading_behavior_flag.h b/third_party/blink/public/common/loader/loading_behavior_flag.h index 8d1308f..2807058 100644 --- a/third_party/blink/public/common/loader/loading_behavior_flag.h +++ b/third_party/blink/public/common/loader/loading_behavior_flag.h
@@ -69,6 +69,9 @@ // Indicates that the page is controlled by a Service Worker, but // the fetch handler is considered skippable. kLoadingBehaviorServiceWorkerFetchHandlerSkippable = 1 << 20, + // Indicates that the main resource fetch for the page controlled by + // a service worker at the navigation time fallback to network. + kLoadingBehaviorServiceWorkerMainResourceFetchFallback = 1 << 21, }; } // namespace blink
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h index 92fc4db..b536eea 100644 --- a/third_party/blink/public/web/web_local_frame_client.h +++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -552,6 +552,13 @@ // use for segregated histograms. virtual void DidObserveLoadingBehavior(LoadingBehaviorFlag) {} + // A subresource load is observed. + // It is called when there is a subresouce load. The reported values via + // arguments are cumulative. They are NOT a difference from the previous call. + virtual void DidObserveSubresourceLoad( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker) {} + // Blink hits the code path for a certain UseCounterFeature for the first time // on this frame. As a performance optimization, features already hit on other // frames associated with the same page in the renderer are not currently
diff --git a/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc b/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc index 781c5cd8..8be0c6b 100644 --- a/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc +++ b/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc
@@ -245,7 +245,7 @@ // style stored for a shadow root child against a non shadow root child, we // would end up with an incorrect match. if (IsAtShadowBoundary(&state.GetElement()) && - state.Style()->UserModify() != parent_style.UserModify()) { + state.StyleBuilder().UserModify() != parent_style.UserModify()) { return false; }
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc index eec6b37..56092062 100644 --- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc +++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -269,8 +269,7 @@ } void StyleAdjuster::AdjustStyleForEditing(ComputedStyleBuilder& builder) { - const ComputedStyle& style = *builder.InternalStyle(); - if (style.UserModify() != EUserModify::kReadWritePlaintextOnly) + if (builder.UserModify() != EUserModify::kReadWritePlaintextOnly) return; // Collapsing whitespace is harmful in plain-text editing. if (builder.WhiteSpace() == EWhiteSpace::kNormal) @@ -589,8 +588,8 @@ } bool StyleAdjuster::IsEditableElement(Element* element, - const ComputedStyle& style) { - if (style.UserModify() != EUserModify::kReadOnly) + const ComputedStyleBuilder& builder) { + if (builder.UserModify() != EUserModify::kReadOnly) return true; if (!element) @@ -685,7 +684,7 @@ if (element->GetDocument().IsVerticalScrollEnforced()) enforced_by_policy = TouchAction::kPanY; if (::features::IsSwipeToMoveCursorEnabled() && - IsEditableElement(element, style)) { + IsEditableElement(element, builder)) { element_touch_action &= ~TouchAction::kInternalPanXScrolls; } @@ -694,7 +693,7 @@ if (base::FeatureList::IsEnabled(blink::features::kStylusWritingToInput) && RuntimeEnabledFeatures::StylusHandwritingEnabled() && (element_touch_action & TouchAction::kPan) == TouchAction::kPan && - IsEditableElement(element, style) && + IsEditableElement(element, builder) && !IsPasswordFieldWithUnrevealedPassword(element)) { element_touch_action &= ~TouchAction::kInternalNotWritable; }
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.h b/third_party/blink/renderer/core/css/resolver/style_adjuster.h index 089a292..0693a5d 100644 --- a/third_party/blink/renderer/core/css/resolver/style_adjuster.h +++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.h
@@ -47,7 +47,7 @@ static void AdjustStyleForTextCombine(ComputedStyleBuilder&); private: - static bool IsEditableElement(Element*, const ComputedStyle&); + static bool IsEditableElement(Element*, const ComputedStyleBuilder&); static bool IsPasswordFieldWithUnrevealedPassword(Element*); static void AdjustEffectiveTouchAction(ComputedStyle&, ComputedStyleBuilder&,
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h index 248df0e..68ddcc62 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client.h +++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -211,6 +211,11 @@ // propogates renderer loading behavior to the browser process for histograms. virtual void DidObserveLoadingBehavior(LoadingBehaviorFlag) {} + // Will be called when a sub resource load happens. + virtual void DidObserveSubresourceLoad( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker) {} + // Will be called when a new UseCounterFeature has been observed in a frame. // This propagates feature usage to the browser process for histograms. virtual void DidObserveNewFeatureUsage(const UseCounterFeature&) {}
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc index 860023bd..b2f8a26a 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc +++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
@@ -740,6 +740,16 @@ web_frame_->Client()->DidObserveLoadingBehavior(behavior); } +void LocalFrameClientImpl::DidObserveSubresourceLoad( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker) { + if (web_frame_->Client()) { + web_frame_->Client()->DidObserveSubresourceLoad( + number_of_subresources_loaded, + number_of_subresource_loads_handled_by_service_worker); + } +} + void LocalFrameClientImpl::DidObserveNewFeatureUsage( const UseCounterFeature& feature) { if (web_frame_->Client())
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.h b/third_party/blink/renderer/core/frame/local_frame_client_impl.h index 8e634ec..c1d35e9 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client_impl.h +++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
@@ -151,6 +151,9 @@ UserInteractionType interaction_type) override; void DidChangeCpuTiming(base::TimeDelta) override; void DidObserveLoadingBehavior(LoadingBehaviorFlag) override; + void DidObserveSubresourceLoad( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker) override; void DidObserveNewFeatureUsage(const UseCounterFeature&) override; void DidObserveSoftNavigation(uint32_t count) override; void DidObserveLayoutShift(double score, bool after_input_or_scroll) override;
diff --git a/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc b/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc index 45766fd..3fce465 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc
@@ -20,6 +20,8 @@ LayoutUnit LayoutBoxUtils::AvailableLogicalWidth(const LayoutBox& box, const LayoutBlock* cb) { + // SVG <text> and <foreignObject> should not refer to its containing block. + DCHECK(!box.IsSVGChild()); auto writing_mode = box.StyleRef().GetWritingMode(); bool parallel_containing_block = IsParallelWritingMode( cb ? cb->StyleRef().GetWritingMode() : writing_mode, writing_mode); @@ -45,6 +47,8 @@ LayoutUnit LayoutBoxUtils::AvailableLogicalHeight(const LayoutBox& box, const LayoutBlock* cb) { + // SVG <text> and <foreignObject> should not refer to its containing block. + DCHECK(!box.IsSVGChild()); auto writing_mode = box.StyleRef().GetWritingMode(); bool parallel_containing_block = IsParallelWritingMode( cb ? cb->StyleRef().GetWritingMode() : writing_mode, writing_mode);
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc index 629ccc9..d5361116 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc
@@ -276,7 +276,8 @@ } LayoutNGMixin<Base>::UpdateInFlowBlockLayout(); - LayoutNGMixin<Base>::UpdateMargins(); + if (!Base::IsSVGChild()) + LayoutNGMixin<Base>::UpdateMargins(); } template <typename Base>
diff --git a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.cc b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.cc index 0e6b76bb..09c5807 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.cc
@@ -44,7 +44,9 @@ LogicalSize available_size; bool is_fixed_inline_size = false; bool is_fixed_block_size = false; - if (cb) { + if (block.IsSVGChild()) { + // SVG <text> and <foreignObject> should not refer to its containing block. + } else if (cb) { available_size.inline_size = LayoutBoxUtils::AvailableLogicalWidth(block, cb); available_size.block_size =
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index 2aec75c..c214ea01d 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -2697,6 +2697,11 @@ loading_behavior | kLoadingBehaviorServiceWorkerFetchHandlerSkippable); } + if (!response_.WasFetchedViaServiceWorker()) { + loading_behavior = static_cast<LoadingBehaviorFlag>( + loading_behavior | + kLoadingBehaviorServiceWorkerMainResourceFetchFallback); + } GetLocalFrameClient().DidObserveLoadingBehavior(loading_behavior); } @@ -3207,6 +3212,14 @@ GetDisableCodeCacheForTesting() = true; } +void DocumentLoader::UpdateSubresourceLoadMetrics( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker) { + GetLocalFrameClient().DidObserveSubresourceLoad( + number_of_subresources_loaded, + number_of_subresource_loads_handled_by_service_worker); +} + DEFINE_WEAK_IDENTIFIER_MAP(DocumentLoader) } // namespace blink
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h index 9e53223a..01e862c 100644 --- a/third_party/blink/renderer/core/loader/document_loader.h +++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -452,6 +452,10 @@ return navigation_delivery_type_; } + void UpdateSubresourceLoadMetrics( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker); + protected: // Based on its MIME type, if the main document's response corresponds to an // MHTML archive, then every resources will be loaded from this archive.
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc index 5dee8a50..978d792 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -888,4 +888,12 @@ return probe::ToCoreProbeSink(GetFrame()->GetDocument()); } +void FrameFetchContext::UpdateSubresourceLoadMetrics( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker) { + document_loader_->UpdateSubresourceLoadMetrics( + number_of_subresources_loaded, + number_of_subresource_loads_handled_by_service_worker); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.h b/third_party/blink/renderer/core/loader/frame_fetch_context.h index 15209ba..df474419 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context.h +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -138,6 +138,10 @@ ExecutionContext* GetExecutionContext() const override; + void UpdateSubresourceLoadMetrics( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker) override; + private: friend class FrameFetchContextTest;
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index be64f48..6ab95da1 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2592,6 +2592,12 @@ STACK_ALLOCATED(); public: + friend class ColorPropertyFunctions; + friend class StyleAdjuster; + friend class StyleResolverState; + // Access to UserModify(). + friend class MatchedPropertiesCache; + explicit ComputedStyleBuilder(const ComputedStyle& style) { SetStyle(ComputedStyle::Clone(style)); } @@ -3087,10 +3093,6 @@ } private: - friend class ColorPropertyFunctions; - friend class StyleAdjuster; - friend class StyleResolverState; - ComputedStyleBuilder() = default; CORE_EXPORT void ClearVariableNamesCache();
diff --git a/third_party/blink/renderer/platform/graphics/color_space_gamut.cc b/third_party/blink/renderer/platform/graphics/color_space_gamut.cc index 6413935..37c9a43a 100644 --- a/third_party/blink/renderer/platform/graphics/color_space_gamut.cc +++ b/third_party/blink/renderer/platform/graphics/color_space_gamut.cc
@@ -18,10 +18,10 @@ if (!color_space.IsValid()) return ColorSpaceGamut::kUnknown; - // TODO(crbug.com/1049334): Change this function to operate on a - // gfx::DisplayColorSpaces structure. + // TODO(crbug.com/1385853): Perform a better computation, using the available + // SkColorSpacePrimaries. if (color_space.IsHDR()) - return ColorSpaceGamut::BT2020; + return ColorSpaceGamut::P3; sk_sp<SkColorSpace> sk_color_space = color_space.ToSkColorSpace(); if (!sk_color_space)
diff --git a/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder.cc index 5c793ee..fb3ce1b 100644 --- a/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder.cc +++ b/third_party/blink/renderer/platform/image-decoders/jxl/jxl_image_decoder.cc
@@ -158,7 +158,8 @@ // Frame already complete return; } - if ((index < num_decoded_frames_) && dec_) { + if ((index < num_decoded_frames_) && dec_ && + frame_buffer_cache_[index].GetStatus() != ImageFrame::kFramePartial) { // An animation frame that already has been decoded, but does not have // status ImageFrame::kFrameComplete, was requested. // This can mean two things:
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h index 36d1127..b0b9afb0 100644 --- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h +++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
@@ -176,6 +176,11 @@ // Returns if the request context is for prerendering or not. virtual bool IsPrerendering() const { return false; } + + // Update SubresourceLoad metrics. + virtual void UpdateSubresourceLoadMetrics( + uint32_t number_of_subresources_loaded, + uint32_t number_of_subresource_loads_handled_by_service_worker) {} }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc index 56c0d8f6..b1d12e1 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -1966,6 +1966,17 @@ bool should_report_corb_blocking) { DCHECK(resource); + // kRaw might not be subresource, and we do not need them. + if (resource->GetType() != ResourceType::kRaw) { + ++number_of_subresources_loaded_; + if (resource->GetResponse().WasFetchedViaServiceWorker()) { + ++number_of_subresource_loads_handled_by_service_worker_; + } + } + context_->UpdateSubresourceLoadMetrics( + number_of_subresources_loaded_, + number_of_subresource_loads_handled_by_service_worker_); + DCHECK_LE(inflight_keepalive_bytes, inflight_keepalive_bytes_); inflight_keepalive_bytes_ -= inflight_keepalive_bytes;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h index e4c1e23..d8271ea 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -521,6 +521,12 @@ std::unique_ptr<ukm::MojoUkmRecorder> ukm_recorder_; + // The total number of sub resource loads except for ResourceType::kRaw. + uint32_t number_of_subresources_loaded_ = 0; + // The number of sub resource loads that a service worker fetch handler + // called respondWith. i.e. no fallback to network. + uint32_t number_of_subresource_loads_handled_by_service_worker_ = 0; + // NOTE: This must be the last member. base::WeakPtrFactory<ResourceFetcher> weak_ptr_factory_{this}; };
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index ebf233cb..61f7abb3 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -368,7 +368,7 @@ status: "experimental", origin_trial_feature_name: "BackForwardCacheNotRestoredReasons", base_feature: "BackForwardCacheSendNotRestoredReasons", - base_feature_status: "enabled", + base_feature_status: "disabled", copied_from_base_feature_if: "overridden", public: true, },
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests index c495002..2d6e58b 100644 --- a/third_party/blink/web_tests/SlowTests +++ b/third_party/blink/web_tests/SlowTests
@@ -214,7 +214,6 @@ crbug.com/1243943 [ Mac ] virtual/oopr-canvas2d/fast/canvas/canvas-blending-gradient-over-gradient.html [ Slow ] crbug.com/1243943 [ Mac ] virtual/gpu/fast/canvas/canvas-blending-transforms.html [ Slow ] crbug.com/1243943 [ Mac ] virtual/oopr-canvas2d/fast/canvas/canvas-composite-canvas.html [ Slow ] -crbug.com/1243943 [ Mac ] virtual/gpu/fast/canvas/canvas-blending-fill-style.html [ Slow ] crbug.com/1312081 [ Mac ] virtual/gpu/fast/canvas/canvas-blend-solid.html [ Slow ] crbug.com/1312081 [ Linux ] virtual/gpu/fast/canvas/canvas-blend-solid.html [ Slow ] @@ -757,7 +756,6 @@ crbug.com/1195814 [ Mac11 ] external/wpt/IndexedDB/idbtransaction_objectStoreNames.html [ Slow ] crbug.com/1195814 [ Mac11 ] external/wpt/IndexedDB/keygenerator-explicit.html [ Slow ] crbug.com/1195814 [ Mac11 ] external/wpt/IndexedDB/keypath-special-identifiers.htm [ Slow ] -crbug.com/1195814 [ Mac11 ] storage/indexeddb/key-generator.html [ Slow ] crbug.com/1263580 editing/deleting/delete-many-lines-of-text.html [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index b92fbe5..7c59426 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -211,6 +211,9 @@ # ====== Popover and Anchor Positioning failures to here ====== +# Disabled to revert devtools-frontend change: +crbug.com/1383296 http/tests/devtools/elements/elements-tab-stops.js [ Failure Pass ] + # Sheriff on 2020-09-03 crbug.com/1124352 media/picture-in-picture/clear-after-request.html [ Crash Pass ] crbug.com/1124352 media/picture-in-picture/controls/picture-in-picture-button.html [ Crash Pass ] @@ -313,7 +316,6 @@ external/wpt/editing/run/inserttext.html?2001-last [ Failure ] external/wpt/editing/run/forecolor.html?1-1000 [ Failure ] external/wpt/editing/run/forecolor.html?2001-last [ Failure ] -external/wpt/editing/run/insertlinebreak.html [ Failure ] # WPT editing test failures crbug.com/1168974 external/wpt/editing/run/forwarddelete.html?6001-last [ Failure ] @@ -1965,7 +1967,6 @@ # Flaky tests on Mac after enabling scroll animations in web_tests crbug.com/944583 [ Mac ] fast/events/platform-wheelevent-paging-xy-in-scrolling-div.html [ Failure Pass ] -crbug.com/944583 [ Mac ] fast/events/platform-wheelevent-paging-xy-in-scrolling-page.html [ Failure Pass ] crbug.com/944583 [ Mac ] fast/events/space-scroll-textinput-canceled.html [ Failure Pass ] crbug.com/944583 [ Mac ] fast/scrolling/percentage-mousewheel-scroll-on-iframe.html [ Failure Pass ] crbug.com/944583 [ Mac ] fast/scrolling/percentage-mousewheel-scroll.html [ Failure Pass ] @@ -3000,7 +3001,6 @@ crbug.com/958381 [ Mac ] external/wpt/css/CSS2/tables/table-anonymous-objects-016.xht [ Failure ] crbug.com/958381 [ Mac ] external/wpt/css/CSS2/tables/table-anonymous-objects-020.xht [ Failure ] crbug.com/958381 [ Mac ] external/wpt/css/CSS2/tables/table-anonymous-objects-179.xht [ Failure ] -crbug.com/958381 [ Mac ] external/wpt/css/CSS2/tables/table-anonymous-objects-189.xht [ Failure ] crbug.com/958381 [ Mac ] external/wpt/css/CSS2/tables/table-anonymous-objects-192.xht [ Failure ] crbug.com/958381 [ Mac ] external/wpt/css/CSS2/tables/table-anonymous-objects-193.xht [ Failure ] crbug.com/958381 [ Mac ] external/wpt/css/CSS2/tables/table-anonymous-objects-194.xht [ Failure ] @@ -3221,7 +3221,6 @@ crbug.com/626703 [ Mac10.14 ] external/wpt/pointerevents/pointerevent_pointercapture_in_frame.html?pen [ Timeout ] crbug.com/626703 [ Mac11 ] external/wpt/pointerevents/pointerevent_pointercapture_in_frame.html?pen [ Timeout ] crbug.com/626703 [ Win ] external/wpt/websockets/stream/tentative/constructor.any.serviceworker.html?wss [ Failure Timeout ] -crbug.com/626703 [ Win ] external/wpt/websockets/constructor/010.html?wss [ Failure Timeout ] crbug.com/626703 [ Win ] external/wpt/websockets/opening-handshake/005.html [ Failure Timeout ] crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc/RTCPeerConnection-ondatachannel.html [ Skip Timeout ] crbug.com/626703 [ Mac11 ] external/wpt/webrtc/RTCPeerConnection-ondatachannel.html [ Skip Timeout ] @@ -4439,8 +4438,6 @@ crbug.com/1048149 external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-screeny.html [ Crash Timeout ] crbug.com/1048149 external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-width.html [ Crash Timeout ] crbug.com/1048149 [ Mac ] fast/forms/calendar-picker/month-picker-appearance.html [ Crash Pass ] -crbug.com/1048149 [ Mac ] fast/forms/calendar-picker/month-picker-appearance-step.html [ Crash Pass ] -crbug.com/1048149 crbug.com/1050121 [ Mac ] fast/forms/month/month-picker-appearance-zoom150.html [ Crash Failure Pass ] # SwANGLE issues crbug.com/1204234 css3/blending/background-blend-mode-single-accelerated-element.html [ Failure ] @@ -5159,7 +5156,6 @@ crbug.com/1048761 [ Mac12 ] external/wpt/websockets/Send-0byte-data.any.html?wpt_flags=h2 [ Failure ] crbug.com/1048761 [ Mac12-arm64 ] external/wpt/websockets/Send-0byte-data.any.html?wpt_flags=h2 [ Failure ] crbug.com/1048761 [ Win ] external/wpt/websockets/Send-0byte-data.any.html?wpt_flags=h2 [ Failure ] -crbug.com/1048761 [ Win ] external/wpt/websockets/Send-0byte-data.any.worker.html?wpt_flags=h2 [ Failure ] crbug.com/1048761 [ Linux ] external/wpt/websockets/Send-65K-data.any.html?wpt_flags=h2 [ Failure ] crbug.com/1048761 [ Mac10.15 ] external/wpt/websockets/Send-65K-data.any.html?wpt_flags=h2 [ Failure ] crbug.com/1048761 [ Mac11 ] external/wpt/websockets/Send-65K-data.any.html?wpt_flags=h2 [ Failure ] @@ -6925,3 +6921,8 @@ crbug.com/1372166 fast/spatial-navigation/snav-div-scrollable-but-without-focusable-content.html [ Failure Pass ] crbug.com/1385497 http/tests/inspector-protocol/tracing/page-load-metrics.js [ Failure Pass ] crbug.com/1349215 external/wpt/fullscreen/api/document-fullscreen-enabled-cross-origin.sub.html [ Skip Timeout ] + +# To be removed after cherry picking +crbug.com/1386017 external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache-reasons-stay.window.html [ Failure Pass ] +crbug.com/1386017 external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-cross-origin-bfcache.window.html [ Failure Pass ] +crbug.com/1386017 external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-not-bfcached.window.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 9e71efc..fa494ec 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -481,6 +481,12 @@ "args": ["--enable-features=PlzDedicatedWorker"] }, { + "prefix": "service-worker-storage-control-on-thread-pool", + "platforms": ["Linux", "Mac", "Win"], + "bases": ["external/wpt/service-workers/service-worker/fetch-event.https.html"], + "args": ["--enable-features=ServiceWorkerStorageControlOnThreadPool"] + }, + { "prefix": "direct-sockets", "platforms": ["Linux", "Mac", "Win"], "bases": ["external/wpt/direct-sockets",
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 044d3bd..b0f78b4e 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -3556,13 +3556,6 @@ null, {} ] - ], - "uncontained-transition-crash.html": [ - "98632508aedc849999c760625f45ad2b54a829d0", - [ - null, - {} - ] ] }, "css-writing-modes": { @@ -217161,7 +217154,7 @@ ] ], "new-content-element-writing-modes.html": [ - "4c2268ffc0de78dbd82a253443789ff3b50b5d52", + "0c50e22fc0dea2d2f1a4325895086f83ebeabafc", [ null, [ @@ -217234,7 +217227,7 @@ ] ], "new-content-object-fit-fill.html": [ - "47c7f77cd0f31232c60041abd57e5db3e9237c02", + "5b1941aa3e6f7e6bce6b54ae4bcf823a76d581c7", [ null, [ @@ -217267,7 +217260,7 @@ ] ], "new-content-object-fit-none.html": [ - "be477691013fd76c0959848372c4d4a03ac07149", + "d3e4d2dc3def3527de5fd10a3a2540c9a16ab64d", [ null, [ @@ -217689,7 +217682,7 @@ ] ], "old-content-object-fit-fill.html": [ - "587c05c0cb189e03d6966f7f7ed0080a282434f5", + "75dc628f944d49e19c98a95e5fc03f57c2434a39", [ null, [ @@ -217722,7 +217715,7 @@ ] ], "old-content-object-fit-none.html": [ - "71f3f5474876e533c297f08b454fe8a9635f4a42", + "c40ad13435a773cb48b3454705ea8955cdcadbee", [ null, [ @@ -276223,6 +276216,10 @@ "06f866c02dd04724a35cf5032b1d40e6783c3389", [] ], + "nested-color-mix-with-currentcolor-expected.txt": [ + "13c385b073f45c5648976704d28d8284392f8049", + [] + ], "oklab-004-ref.html": [ "d947445321da29d5658fb957cb45c83e8cca2424", [] @@ -352188,7 +352185,7 @@ [] ], "util.js": [ - "d6f54bcfc7ebd16caf1414e828e3b7b8ecfc3f9e", + "1b3c82d7d68da9b2f94159db850d1951dadd33f6", [] ] } @@ -361581,7 +361578,7 @@ [] ], "META.yml": [ - "b8c0b9741d4a22ac42a995ca04b3df2c96cfc16f", + "633c917b0e60783c41db597695e22c499080a95d", [] ], "active-lock-expected.txt": [ @@ -417527,6 +417524,13 @@ {} ] ], + "nested-color-mix-with-currentcolor.html": [ + "a4dd687dd5814af2e4660586a2c97c09ba34ffe4", + [ + null, + {} + ] + ], "parsing": { "color-computed-color-contrast-function.html": [ "74be5ced3748dcaa9b86d99938390cd7de122de0", @@ -441797,8 +441801,15 @@ ] }, "css-view-transitions": { - "duplicate_tag_rejects.html": [ - "c7aef2aa1a45183a8ddfa5d0ca19647f3d81d838", + "duplicate-tag-rejects-capture.html": [ + "517502b6741818d84e9faeb81a9ce69bb5c0b6cc", + [ + null, + {} + ] + ], + "duplicate-tag-rejects-start.html": [ + "2d99717df446b210fcc47f4992d980e0c8ce8e73", [ null, {} @@ -441834,6 +441845,27 @@ {} ] ], + "no-containment-on-new-element-mid-transition.html": [ + "869fd24f42c34740809aa075be96a73b6ee465ef", + [ + null, + {} + ] + ], + "no-containment-on-new-element.html": [ + "ecb05373b3e653686a3d724fc5418aa28ffb2979", + [ + null, + {} + ] + ], + "no-containment-on-old-element.html": [ + "22cad098c76c21b424fef72db5e4db2d8b8dbf7f", + [ + null, + {} + ] + ], "no-crash-set-exception.html": [ "035d050e4487b1443f518b425a0b6a301d83b093", [ @@ -441875,6 +441907,13 @@ ] ] }, + "pseudo-computed-style-stays-in-sync-with-new-element.html": [ + "b1ed783b0af4875abb2d381986797059c054b192", + [ + null, + {} + ] + ], "pseudo-get-computed-style.html": [ "e837d52a5709eb71e80a1dfc5c0a35f6a17a14c4", [ @@ -441895,6 +441934,48 @@ null, {} ] + ], + "synchronous-callback-skipped-before-run.html": [ + "1bda243449c564134bf8fb1d1d93f7858460a533", + [ + null, + {} + ] + ], + "transition-skipped-after-animation-started.html": [ + "78f32def3e58b59a5568d2e25806d77ad8ee84a2", + [ + null, + {} + ] + ], + "transition-skipped-from-invalid-callback.html": [ + "4a56f81efe0f9c8512db85230b7da6713be33223", + [ + null, + {} + ] + ], + "unset-and-initial-view-transition-name.html": [ + "93c8eb64d79ac8c24995a8a54442d71b31ae6fe6", + [ + null, + {} + ] + ], + "view-transition-name-on-added-element.html": [ + "cd957973b7d9a9c67574c5ced363cf4e18e4eaa3", + [ + null, + {} + ] + ], + "view-transition-name-on-removed-element.html": [ + "4a26a8154f5dbaa407eec0a074cf8f56bb53c94e", + [ + null, + {} + ] ] }, "css-will-change": { @@ -538419,7 +538500,7 @@ ] ], "simple-block-movement.html": [ - "837b438ef6b87e177c65ebbcd381d378d372ba24", + "10261f7d81d0f04eedc4fa1f7998bcf09d866d2a", [ null, {}
diff --git a/third_party/blink/web_tests/external/wpt/cookies/samesite/get_all_cookies-default-samesite.html b/third_party/blink/web_tests/external/wpt/cookies/samesite/get_all_cookies-default-samesite.html index 099ac511..3b1606b 100644 --- a/third_party/blink/web_tests/external/wpt/cookies/samesite/get_all_cookies-default-samesite.html +++ b/third_party/blink/web_tests/external/wpt/cookies/samesite/get_all_cookies-default-samesite.html
@@ -7,6 +7,8 @@ <script src="/resources/testdriver-vendor.js"></script> <script> promise_test(async t => { + await test_driver.delete_all_cookies(); + t.add_cleanup(test_driver.delete_all_cookies); document.cookie = "test0=0"; const cookies = await test_driver.get_all_cookies(); assert_equals(cookies.length, 1);
diff --git a/third_party/blink/web_tests/external/wpt/cookies/samesite/get_all_cookies-default-samesite.html.ini b/third_party/blink/web_tests/external/wpt/cookies/samesite/get_all_cookies-default-samesite.html.ini deleted file mode 100644 index 6219d6e..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/samesite/get_all_cookies-default-samesite.html.ini +++ /dev/null
@@ -1,3 +0,0 @@ -[get_all_cookies-default-samesite.html] - [Get all cookies w/ default SameSite] - expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/cookies/samesite/get_named_cookie-default-samesite.html b/third_party/blink/web_tests/external/wpt/cookies/samesite/get_named_cookie-default-samesite.html index 405473c..2ee5d0f 100644 --- a/third_party/blink/web_tests/external/wpt/cookies/samesite/get_named_cookie-default-samesite.html +++ b/third_party/blink/web_tests/external/wpt/cookies/samesite/get_named_cookie-default-samesite.html
@@ -7,6 +7,8 @@ <script src="/resources/testdriver-vendor.js"></script> <script> promise_test(async t => { + await test_driver.delete_all_cookies(); + t.add_cleanup(test_driver.delete_all_cookies); document.cookie = "test0=0"; const cookie = await test_driver.get_named_cookie("test0"); assert_equals(cookie["name"], "test0");
diff --git a/third_party/blink/web_tests/external/wpt/cookies/samesite/get_named_cookie-default-samesite.html.ini b/third_party/blink/web_tests/external/wpt/cookies/samesite/get_named_cookie-default-samesite.html.ini deleted file mode 100644 index a08ca555..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/samesite/get_named_cookie-default-samesite.html.ini +++ /dev/null
@@ -1,3 +0,0 @@ -[get_named_cookie-default-samesite.html] - [Get Named cookie w/ default SameSite] - expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/transition-style-change-event-002-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/transition-style-change-event-002-expected.txt new file mode 100644 index 0000000..3b126fc --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/transition-style-change-event-002-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL #inner color change to red triggers a step transition starting at green assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/transition-style-change-event-002.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/transition-style-change-event-002.html new file mode 100644 index 0000000..dc92970 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/transition-style-change-event-002.html
@@ -0,0 +1,45 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Container Queries - Style Change Event for transitions</title> +<link rel="help" href="https://drafts.csswg.org/css-transitions/#starting"> +<link rel="help" href="https://drafts.csswg.org/css-contain-3/#animated-containers"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/cq-testcommon.js"></script> +<style> + .container { + container-type: inline-size; + } + #outer { + width: 100px; + color: green; + } + #target { + transition: color 100s step-end; + } + + @container (min-width: 200px) { + #inner { color: red; } + } + @container (min-width: 200px) { + #target { + /* This rule exists just to have a container query dependency between + target and #inner */ + background-color: orange; + } + } +</style> +<div id="outer" class="container"> + <div id="inner" class="container"> + <div id="target">Green</div> + </div> +</div> +<script> + setup(() => assert_implements_container_queries()); + + test(() => { + outer.offsetTop; + outer.style.width = "200px"; + assert_equals(getComputedStyle(target).color, "rgb(0, 128, 0)"); + }, "#inner color change to red triggers a step transition starting at green"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.html b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.html index a145e52..84f93af0 100644 --- a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.html +++ b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.html
@@ -7,6 +7,7 @@ <script src="/resources/testdriver-vendor.js"></script> <script> promise_test(async t => { + t.add_cleanup(test_driver.delete_all_cookies); const kTenDaysFromNow = new Date(Date.now() + 10 * 24 * 60 * 60 * 1000); document.cookie = "test0=0"; document.cookie = `test1=1; Expires=${kTenDaysFromNow.toUTCString()}`;
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.https.html b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.https.html index e3402780..e941671 100644 --- a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.https.html +++ b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_all_cookies.sub.https.html
@@ -7,6 +7,7 @@ <script src="/resources/testdriver-vendor.js"></script> <script> promise_test(async t => { + t.add_cleanup(test_driver.delete_all_cookies); const kTenDaysFromNow = new Date(Date.now() + 10 * 24 * 60 * 60 * 1000); document.cookie = "test0=0"; document.cookie = `test1=1; Expires=${kTenDaysFromNow.toUTCString()}`;
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.html b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.html index 3cbc784..28950e2 100644 --- a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.html +++ b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.html
@@ -7,6 +7,7 @@ <script src="/resources/testdriver-vendor.js"></script> <script> promise_test(async t => { + t.add_cleanup(test_driver.delete_all_cookies); const kTenDaysFromNow = new Date(Date.now() + 10 * 24 * 60 * 60 * 1000); document.cookie = "test0=0"; document.cookie = `test1=1; Expires=${kTenDaysFromNow.toUTCString()}`;
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.https.html b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.https.html index d0d8612a..8e8f4433 100644 --- a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.https.html +++ b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/get_named_cookie.sub.https.html
@@ -7,6 +7,7 @@ <script src="/resources/testdriver-vendor.js"></script> <script> promise_test(async t => { + t.add_cleanup(test_driver.delete_all_cookies); const kTenDaysFromNow = new Date(Date.now() + 10 * 24 * 60 * 60 * 1000); document.cookie = "test0=0"; document.cookie = `test1=1; Expires=${kTenDaysFromNow.toUTCString()}`;
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-streams/parallel-capture-requests.https.html b/third_party/blink/web_tests/external/wpt/mediacapture-streams/parallel-capture-requests.https.html index 01b7f32..301515d 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-streams/parallel-capture-requests.https.html +++ b/third_party/blink/web_tests/external/wpt/mediacapture-streams/parallel-capture-requests.https.html
@@ -4,38 +4,52 @@ <title>Parallel capture requests</title> </head> <body> +<button id="button">User gesture</button> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> <script> +async function getDisplayMedia(constraints) { + const p = new Promise(r => button.onclick = r); + await test_driver.click(button); + await p; + return navigator.mediaDevices.getDisplayMedia(constraints); +} + promise_test(function() { const getUserMediaPromise = navigator.mediaDevices.getUserMedia({audio: true, video:true}); const getDisplayMediaPromise = - navigator.mediaDevices.getDisplayMedia({video: true, audio: true}); + getDisplayMedia({video: true, audio: true}); return Promise.all([getUserMediaPromise, getDisplayMediaPromise]) .then(function(s) { - assert_equals(s[0].getTracks().length, 2); - assert_equals(s[0].getAudioTracks().length, 1); + assert_greater_than_equal(s[0].getTracks().length, 1); + assert_less_than_equal(s[0].getTracks().length, 2); assert_equals(s[0].getVideoTracks().length, 1); - assert_equals(s[1].getTracks().length, 2); - assert_equals(s[1].getAudioTracks().length, 1); + assert_less_than_equal(s[0].getAudioTracks().length, 1); + assert_greater_than_equal(s[1].getTracks().length, 1); + assert_less_than_equal(s[1].getTracks().length, 2); assert_equals(s[1].getVideoTracks().length, 1); + assert_less_than_equal(s[1].getAudioTracks().length, 1); }); }, 'getDisplayMedia() and parallel getUserMedia()'); promise_test(function() { const getDisplayMediaPromise = - navigator.mediaDevices.getDisplayMedia({video: true, audio: true}); + getDisplayMedia({video: true, audio: true}); const getUserMediaPromise = navigator.mediaDevices.getUserMedia({audio: true, video:true}); return Promise.all([getDisplayMediaPromise, getUserMediaPromise]) .then(function(s) { - assert_equals(s[0].getTracks().length, 2); - assert_equals(s[0].getAudioTracks().length, 1); + assert_greater_than_equal(s[0].getTracks().length, 1); + assert_less_than_equal(s[0].getTracks().length, 2); assert_equals(s[0].getVideoTracks().length, 1); - assert_equals(s[1].getTracks().length, 2); - assert_equals(s[1].getAudioTracks().length, 1); + assert_less_than_equal(s[0].getAudioTracks().length, 1); + assert_greater_than_equal(s[1].getTracks().length, 1); + assert_less_than_equal(s[1].getTracks().length, 2); assert_equals(s[1].getVideoTracks().length, 1); + assert_less_than_equal(s[1].getAudioTracks().length, 1); }); }, 'getUserMedia() and parallel getDisplayMedia()'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/screen-orientation/META.yml b/third_party/blink/web_tests/external/wpt/screen-orientation/META.yml index b8c0b97..633c917b0 100644 --- a/third_party/blink/web_tests/external/wpt/screen-orientation/META.yml +++ b/third_party/blink/web_tests/external/wpt/screen-orientation/META.yml
@@ -3,3 +3,4 @@ - marcoscaceres - cdumez - michaelwasserman + - makotokato
diff --git a/third_party/blink/web_tests/external/wpt/svg/struct/reftests/currentScale-change-repaint.html b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/currentScale-change-repaint.html index bd2773b59..aa3939c1 100644 --- a/third_party/blink/web_tests/external/wpt/svg/struct/reftests/currentScale-change-repaint.html +++ b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/currentScale-change-repaint.html
@@ -1,16 +1,14 @@ <!doctype HTML> -<head> - <meta charset="utf-8"> - <title>Testcase for changing currentScale on SVG embedded in HTML</title> - <link rel="help" href="https://www.w3.org/TR/SVG/struct.html#__svg__SVGSVGElement__currentScale"> - <link rel="match" href="reference/green-100x100.svg"/> - <script> - function go() { - var mySVG = document.getElementById("mySVG"); - mySVG.currentScale = 0.5; - } - </script> -</head> +<meta charset="utf-8"> +<title>Testcase for changing currentScale on SVG embedded in HTML</title> +<link rel="help" href="https://www.w3.org/TR/SVG/struct.html#__svg__SVGSVGElement__currentScale"> +<link rel="match" href="reference/green-100x100.html"> +<script> + function go() { + const mySVG = document.getElementById("mySVG"); + mySVG.currentScale = 0.5; + } +</script> <body onload="go()"> <svg id="mySVG"> <rect width="100" height="100" fill="green"></rect>
diff --git a/third_party/blink/web_tests/external/wpt/svg/struct/reftests/currentScale.svg b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/currentScale.svg new file mode 100644 index 0000000..926117b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/currentScale.svg
@@ -0,0 +1,11 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml" onload="scaleDown()"> + <title>Testcase for changing currentScale on SVG embedded in HTML</title> + <h:link rel="help" href="https://www.w3.org/TR/SVG/struct.html#__svg__SVGSVGElement__currentScale"/> + <h:link rel="match" href="reference/green-100x100.svg"/> + <script> + function scaleDown() { + document.documentElement.currentScale = 0.5; + } + </script> + <rect width="200" height="200" fill="green"/> +</svg>
diff --git a/third_party/blink/web_tests/virtual/service-worker-storage-control-on-thread-pool/README.md b/third_party/blink/web_tests/virtual/service-worker-storage-control-on-thread-pool/README.md new file mode 100644 index 0000000..24be641 --- /dev/null +++ b/third_party/blink/web_tests/virtual/service-worker-storage-control-on-thread-pool/README.md
@@ -0,0 +1 @@ +This directory is for testing ServiceWorkerStorageControlOnThreadPool (https://crbug.com/1375174).
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 9bd4eb9..1410e0e 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -1030,7 +1030,7 @@ 'ios-angle-try-intel': 'angle_deqp_release_trybot_ios', 'linux-angle-chromium-try': 'gpu_tests_release_trybot_reclient', 'mac-angle-chromium-try': 'gpu_tests_release_trybot', - 'win-angle-chromium-x64-try': 'gpu_tests_release_trybot', + 'win-angle-chromium-x64-try': 'gpu_tests_release_trybot_reclient', 'win-angle-chromium-x86-try': 'gpu_tests_release_trybot_x86', }, @@ -1292,7 +1292,7 @@ 'win-swangle-try-tot-swiftshader-x64': 'angle_deqp_release_trybot', 'win-swangle-try-tot-swiftshader-x86': 'angle_deqp_release_trybot_x86', 'win-swangle-try-x64': 'angle_deqp_release_trybot', - 'win-swangle-try-x86': 'angle_deqp_release_trybot_x86', + 'win-swangle-try-x86': 'angle_deqp_release_trybot_x86_reclient', }, 'tryserver.chromium.tricium': { @@ -1791,6 +1791,10 @@ 'angle_deqp_tests', 'shared_release_trybot', 'x86', ], + 'angle_deqp_release_trybot_x86_reclient': [ + 'angle_deqp_tests', 'shared_release_trybot_reclient', 'x86', + ], + 'asan_clang_fuzzer_static_v8_heap_minimal_symbols_release_reclient': [ 'asan', 'fuzzer', 'static', 'v8_heap', 'minimal_symbols', 'release_bot_reclient', ],
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.angle.json b/tools/mb/mb_config_expectations/tryserver.chromium.angle.json index 9876678..d2fbe36 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.angle.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.angle.json
@@ -71,7 +71,7 @@ "is_debug": false, "proprietary_codecs": true, "symbol_level": 0, - "use_goma": true + "use_remoteexec": true } }, "win-angle-chromium-x86-try": {
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.swangle.json b/tools/mb/mb_config_expectations/tryserver.chromium.swangle.json index 36ea9fc4..b08613706 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.swangle.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.swangle.json
@@ -93,7 +93,7 @@ "is_debug": false, "symbol_level": 0, "target_cpu": "x86", - "use_goma": true + "use_remoteexec": true } } } \ No newline at end of file
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 7901c6c3..4418e97 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -54149,6 +54149,19 @@ <int value="2" label="Subresource"/> </enum> +<enum name="IsolatedWebAppReadIntegrityBlockAndMetadataStatus"> + <int value="0" label="Success"/> + <int value="1" label="Error: Integrity Block parsing: Internal error"/> + <int value="2" label="Error: Integrity Block parsing: Format error"/> + <int value="3" label="Error: Integrity Block parsing: Version error"/> + <int value="4" label="Error: Integrity Block validation error"/> + <int value="5" label="Error: Signature verification error"/> + <int value="6" label="Error: Metadata parsing: Internal error"/> + <int value="7" label="Error: Metadata parsing: Format error"/> + <int value="8" label="Error: Metadata parsing: Version error"/> + <int value="9" label="Error: Metadata validation error"/> +</enum> + <enum name="IsolatedWebAppResponseReaderCacheState"> <int value="0" label="Not cached"/> <int value="1" label="Cached and ready"/> @@ -91817,6 +91830,31 @@ <int value="1" label="Received on uninstalled service worker."/> </enum> +<enum name="ServiceWorkerResourceLoadStatus"> + <int value="0" + label="falled back for loading both main resource and sub resource."/> + <int value="1" + label="falled back for loading main resource, but did not fallback for + sub resource."/> + <int value="2" + label="falled back for loading main resource, and some sub resource + fallbacks and the others are not."/> + <int value="3" + label="falled back for loading main resource, and no sub resource are + loaded."/> + <int value="4" + label="not falled back for loading main resource, but falled back for + sub resource."/> + <int value="5" + label="not falled back for both main resource and sub resource."/> + <int value="6" + label="not falled back for main resource, but sub resource has both + fallback case and non-fallback cases."/> + <int value="7" + label="not falled back for main resource, and no sub resource are + loaded."/> +</enum> + <enum name="ServiceWorkerResponseError"> <obsolete> No longer recorded since NetS13nSW shipped on Dec 2018. @@ -93826,6 +93864,12 @@ <int value="21" label="User clicked signout from clear browsing data page"> User clicked sign-out in the clear browsing data page. </int> + <int value="22" label="AccountReconcilor GaiaCookiesUpdated"> + The reconcilor cleared the signin primary account on a Gaia cookie update. + </int> + <int value="23" label="AccountReconcilor Reconcile"> + The reconcilor cleared the signin primary account during reconcilation. + </int> </enum> <enum name="SigninSource">
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml index 09dcca6..0e9660b 100644 --- a/tools/metrics/histograms/metadata/autofill/histograms.xml +++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -3019,7 +3019,7 @@ </histogram> <histogram name="Autofill.ProfileImport.SilentUpdatesProfileImportType" - enum="AutofillSilentUpdatesProfileImportType" expires_after="M110"> + enum="AutofillSilentUpdatesProfileImportType" expires_after="2023-04-30"> <owner>koerber@google.com</owner> <owner>src/components/autofill/OWNERS</owner> <summary> @@ -3045,7 +3045,7 @@ </histogram> <histogram name="Autofill.ProfileImport.UpdateProfileAffectedType.{Decision}" - enum="AutofillSettingsVisibleTypes" expires_after="M110"> + enum="AutofillSettingsVisibleTypes" expires_after="2023-04-30"> <owner>koerber@google.com</owner> <owner>src/components/autofill/OWNERS</owner> <summary> @@ -3126,7 +3126,7 @@ <histogram name="Autofill.ProfileImport.UpdateProfileNumberOfAffectedFields.{Decision}" - units="fields" expires_after="M110"> + units="fields" expires_after="2023-04-30"> <owner>koerber@google.com</owner> <owner>src/components/autofill/OWNERS</owner> <summary> @@ -3225,7 +3225,7 @@ </histogram> <histogram name="Autofill.ProfileSuggestionsMadeWithFormatter" - enum="BooleanCreated" expires_after="M110"> + enum="BooleanCreated" expires_after="2023-04-30"> <owner>battre@chromium.org</owner> <owner>src/components/autofill/OWNERS</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml index 8e8b412..0de8887 100644 --- a/tools/metrics/histograms/metadata/password/histograms.xml +++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -2425,8 +2425,8 @@ <histogram name="PasswordManager.PasswordStore.OnLoginsChanged" enum="Boolean" expires_after="2023-03-19"> - <owner>fhorschig@chromium.org</owner> <owner>vsemeniuk@google.com</owner> + <owner>fhorschig@chromium.org</owner> <summary> Recorded whenever PasswordStore notifies consumers about changes to logins. Changes can be made locally (in settings, in bubbles etc.) or remotely (via @@ -2436,8 +2436,8 @@ <histogram name="PasswordManager.PasswordStore.OnLoginsRetained" enum="LoginsChangedTrigger" expires_after="2023-03-19"> - <owner>fhorschig@chromium.org</owner> <owner>vsemeniuk@google.com</owner> + <owner>fhorschig@chromium.org</owner> <summary> Android only. |OnLoginsRetained| replaces |OnLoginsChanged| and this metric records potential calls of |OnLoginsRetained| to measure differences in @@ -2478,9 +2478,9 @@ <histogram name="PasswordManager.PasswordStore.WasEnrolledInUPMWhenBackendWasCreated" enum="Boolean" expires_after="2023-03-19"> - <owner>fhorschig@chromium.org</owner> <owner>kazinova@google.com</owner> <owner>ioanap@chromium.org</owner> + <owner>fhorschig@chromium.org</owner> <summary> Recorded on Android when the password store backend is created. This happens on startup and once per profile. It logs whether the user is enrolled in @@ -2510,8 +2510,8 @@ <histogram name="PasswordManager.PasswordStoreAndroidBackend.ClearAllLocalPasswords.LoginsToRemove" units="count" expires_after="M114"> - <owner>fhorschig@chromium.org</owner> <owner>vsemeniuk@google.com</owner> + <owner>fhorschig@chromium.org</owner> <summary> Total number of logins to be removed by ClearAllLocalPasswords. </summary> @@ -2520,8 +2520,8 @@ <histogram name="PasswordManager.PasswordStoreAndroidBackend.ClearAllLocalPasswords.SuccessRate" units="%" expires_after="M114"> - <owner>fhorschig@chromium.org</owner> <owner>vsemeniuk@google.com</owner> + <owner>fhorschig@chromium.org</owner> <summary> Ratio between successfully removed logins and total number of logins in the GMS's local storage. Removal is considered successful when change list is @@ -2617,8 +2617,10 @@ <histogram name="PasswordManager.PasswordStoreAndroidBackend{Function}.APIError" enum="PasswordStoreAndroidBackendAPIError" expires_after="M114"> - <owner>fhorschig@chromium.org</owner> + <owner>maxan@chromium.org</owner> + <owner>ioanap@chromium.org</owner> <owner>vasilii@chromium.org</owner> + <owner>fhorschig@chromium.org</owner> <summary> The error codes returned by the GMS Core ChromeSync 1P API{Function}. Recorded when the asynchronous job has returned. @@ -2660,8 +2662,10 @@ <histogram name="PasswordManager.PasswordStoreAndroidBackend{Function}.ErrorCode" enum="PasswordStoreAndroidBackendError" expires_after="M114"> - <owner>fhorschig@chromium.org</owner> + <owner>maxan@chromium.org</owner> + <owner>ioanap@chromium.org</owner> <owner>vasilii@chromium.org</owner> + <owner>fhorschig@chromium.org</owner> <summary> This metric reports the error observed when {Function} the PasswordStore Android backend. Recorded when the asynchronous job has returned. @@ -2736,8 +2740,10 @@ <histogram name="PasswordManager.PasswordStoreProxyBackend.{Function}.{Metric}.{Measurement}" units="count" expires_after="M114"> - <owner>fhorschig@chromium.org</owner> + <owner>maxan@chromium.org</owner> + <owner>ioanap@chromium.org</owner> <owner>vasilii@chromium.org</owner> + <owner>fhorschig@chromium.org</owner> <summary> Records the number of logins {Metric}{Measurement} Recorded when the asynchronous job for {Function} has returned. @@ -2773,8 +2779,10 @@ <histogram name="PasswordManager.PasswordStoreProxyBackend.{ModifyingFunction}.{Metric}.{Measurement}" units="count" expires_after="M114"> - <owner>fhorschig@chromium.org</owner> + <owner>maxan@chromium.org</owner> + <owner>ioanap@chromium.org</owner> <owner>vasilii@chromium.org</owner> + <owner>fhorschig@chromium.org</owner> <summary> Records the number of password store changes {Metric}{Measurement} Recorded when the asynchronous job for {ModifyingFunction} has returned. Recorded @@ -2812,8 +2820,10 @@ <histogram name="PasswordManager.PasswordStore{Backend}{Function}" enum="PasswordStoreAndroidBackendRequestStatus" expires_after="M114"> - <owner>fhorschig@chromium.org</owner> + <owner>maxan@chromium.org</owner> + <owner>ioanap@chromium.org</owner> <owner>vasilii@chromium.org</owner> + <owner>fhorschig@chromium.org</owner> <summary> Records each {Function} call by the PasswordStore {Backend}. Recorded twice: 1) when the store issues the request, and 2) as the asynchronous job has @@ -2847,8 +2857,10 @@ <histogram name="PasswordManager.PasswordStore{Backend}{Function}.Latency" units="ms" expires_after="M114"> - <owner>fhorschig@chromium.org</owner> + <owner>maxan@chromium.org</owner> + <owner>ioanap@chromium.org</owner> <owner>vasilii@chromium.org</owner> + <owner>fhorschig@chromium.org</owner> <summary> Real-time duration of the asynchronous call to {Function} the PasswordStore {Backend}. Recorded when the asynchronous job has returned. @@ -2882,8 +2894,10 @@ <histogram name="PasswordManager.PasswordStore{Backend}{Function}.Success" enum="BooleanSuccess" expires_after="M114"> - <owner>fhorschig@chromium.org</owner> + <owner>maxan@chromium.org</owner> + <owner>ioanap@chromium.org</owner> <owner>vasilii@chromium.org</owner> + <owner>fhorschig@chromium.org</owner> <summary> Records whether {Function} the PasswordStore {Backend}. Recorded when the asynchronous job has returned. False is emitted if an error occurs; @@ -3509,9 +3523,9 @@ <histogram name="PasswordManager.UnenrolledFromUPMDueToErrors" enum="Boolean" expires_after="M114"> - <owner>fhorschig@chromium.org</owner> <owner>kazinova@google.com</owner> <owner>ioanap@chromium.org</owner> + <owner>fhorschig@chromium.org</owner> <summary> Records true when a client's profile is being unenrolled from UPM. This happens when a password store request to GMS Core fails with an error that @@ -3525,9 +3539,9 @@ Obsolete in M110 after PasswordStore is no longer created for non-regular, guest, system and incognito profiles. </obsolete> - <owner>fhorschig@chromium.org</owner> <owner>kazinova@google.com</owner> <owner>ioanap@chromium.org</owner> + <owner>fhorschig@chromium.org</owner> <summary> Recorded on profile open after the sync service is initialized and once per profile. It is recorded for clients that have UPM enabled and logs whether @@ -3541,9 +3555,9 @@ <histogram name="PasswordManager.UnifiedPasswordManager.ActiveStatus2" enum="UnifiedPasswordManagerActiveStatus" expires_after="M114"> - <owner>fhorschig@chromium.org</owner> <owner>kazinova@google.com</owner> <owner>ioanap@chromium.org</owner> + <owner>fhorschig@chromium.org</owner> <summary> Recorded on profile open after the sync service is initialized and once per regular profile. It is recorded for clients that have UPM enabled and logs @@ -3557,8 +3571,8 @@ <histogram name="PasswordManager.UnifiedPasswordManager.WasMigrationDone" enum="BooleanSuccess" expires_after="M114"> - <owner>fhorschig@chromium.org</owner> <owner>vsemeniuk@google.com</owner> + <owner>fhorschig@chromium.org</owner> <summary> Records whether passwords were successfully migrated from built in backed to android backed and the current migration version stored in pref is @@ -3569,8 +3583,8 @@ <histogram name="PasswordManager.UnifiedPasswordManager.{UPMMigrationType}.Latency" units="ms" expires_after="M114"> - <owner>fhorschig@chromium.org</owner> <owner>vsemeniuk@google.com</owner> + <owner>fhorschig@chromium.org</owner> <summary> Real-time duration of {UPMMigrationType}. Recorded when all operations are completed and migration is finished. @@ -3581,8 +3595,8 @@ <histogram name="PasswordManager.UnifiedPasswordManager.{UPMMigrationType}.Success" enum="BooleanSuccess" expires_after="M114"> - <owner>fhorschig@chromium.org</owner> <owner>vsemeniuk@google.com</owner> + <owner>fhorschig@chromium.org</owner> <summary> Records success of {UPMMigrationType}. Recorded when the migration is finished.
diff --git a/tools/metrics/histograms/metadata/webapps/histograms.xml b/tools/metrics/histograms/metadata/webapps/histograms.xml index 432390f7..f9c5e24 100644 --- a/tools/metrics/histograms/metadata/webapps/histograms.xml +++ b/tools/metrics/histograms/metadata/webapps/histograms.xml
@@ -755,6 +755,23 @@ <summary>Records the result code of Web App installs.</summary> </histogram> +<histogram name="WebApp.Isolated.ReadIntegrityBlockAndMetadataStatus" + enum="IsolatedWebAppReadIntegrityBlockAndMetadataStatus" + expires_after="2023-11-08"> + <owner>cmfcmf@chromium.org</owner> + <owner>peletskyi@chromium.org</owner> + <summary> + Records whether reading integrity block and metadata from a Signed Web + Bundle via the isolated-app: scheme was successful or resulted in an error. + This is logged every time the integrity block and metadata of an Isolated + Web App are parsed, which happens whenever the reader for an Isolated Web + App is not yet cached. Readers are evicted from the cache after + approximately 10 minutes of not reading any responses from their + corresponding Signed Web Bundle. Isolated Web Apps are parsed for any + resources loading for the web app, so any usage could trigger this UMA. + </summary> +</histogram> + <histogram name="WebApp.Isolated.ResponseReaderCacheState" enum="IsolatedWebAppResponseReaderCacheState" expires_after="2023-11-08"> <owner>cmfcmf@chromium.org</owner>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index deb06e4..9ac7aff 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -19583,6 +19583,40 @@ </metric> </event> +<event name="ServiceWorker.OnLoad"> + <owner>yyanagisawa@chromium.org</owner> + <owner>chrome-worker@google.com</owner> + <summary> + Events taken at the end of the loading pages controlled by the service + workers. + </summary> + <metric name="MainAndSubResourceLoadLocation" + enum="ServiceWorkerResourceLoadStatus"> + <summary> + Enum value to represent how main / sub resource are loaded. + </summary> + </metric> + <metric name="SubResourceFallbackRatio"> + <summary> + An integer ratio (0 - 100) to represent the ratio of network fallbacks + from the total subresource load. + </summary> + </metric> + <metric name="TotalSubResourceFallback"> + <summary> + The number of network fallbacks during sub resource load. This is rounded + down to the nearest exponential bucket (with a bucket ratio on 1.15). + </summary> + </metric> + <metric name="TotalSubResourceLoad"> + <summary> + The number of all sub resource load of the page controlled by the service + worker. This is rounded down to the nearest exponential bucket (with a + bucket ratio on 1.15). + </summary> + </metric> +</event> + <event name="SharedHighlights.LinkGenerated"> <owner>jeffreycohen@chromium.org</owner> <owner>chrome-creation@google.com</owner>
diff --git a/tools/perf/contrib/power/cpu_powerups.sql b/tools/perf/contrib/power/cpu_powerups.sql index a6705f5..5b00b15 100644 --- a/tools/perf/contrib/power/cpu_powerups.sql +++ b/tools/perf/contrib/power/cpu_powerups.sql
@@ -123,6 +123,24 @@ -- per CPU power up. ORDER BY ts ASC; +-- A view with counts of power-ups grouped by Linux process & thread. +-- +-- Schema: +-- process_name : The Linux process that ran after a power up. +-- thread_name : The thread in the Linux process that powered up. +-- powerup_count : The counts for the (process, thread) pair. +DROP VIEW IF EXISTS cpu_power_powerup_count_by_process_and_thread; +CREATE VIEW cpu_power_powerup_count_by_process_and_thread AS + SELECT + process.name AS process_name, + thread.name AS thread_name, + count() AS powerup_count + FROM cpu_power_first_sched_slice_after_powerup + JOIN thread using (utid) + JOIN process using (upid) + GROUP BY process_name, thread_name + ORDER BY powerup_count DESC; + -- A view joining thread tracks and top-level slices. -- -- This view is intended to be intersected by time with the scheduler
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index f6fc2b6..6cb3cb6b 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -6,7 +6,7 @@ }, "win": { "hash": "bb2cc045bbee68ad3cd3daed827075285572fe49", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/3c036ab6b21b9d9ddf91dc6b7fe7f50142f28758/trace_processor_shell.exe" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/6f7678ba37a925e02df652a13c50be9daaeb484e/trace_processor_shell.exe" }, "linux_arm": { "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893", @@ -22,7 +22,7 @@ }, "linux": { "hash": "7e4cc10d0a4b47b170771988b6800e9438ad73cf", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/6f7678ba37a925e02df652a13c50be9daaeb484e/trace_processor_shell" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/6c5c80b3c694219abfaa0a1fe814522e70c0dc65/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/perf/core/tbmv3/metrics/power_rails_metric.sql b/tools/perf/core/tbmv3/metrics/power_rails_metric.sql index 161d6e3..0b2eb11 100644 --- a/tools/perf/core/tbmv3/metrics/power_rails_metric.sql +++ b/tools/perf/core/tbmv3/metrics/power_rails_metric.sql
@@ -16,14 +16,22 @@ -- Compute cumulative power drain over the duration of the run_story event. CREATE VIEW story_drain AS -SELECT - subsystem, - sum(dur * drain_w / 1e9) as drain_j, - sum(dur / 1e6) as dur_ms -FROM run_story_span_join_drain -JOIN power_counters USING (name) +WITH + drain_per_rail AS ( + SELECT + name, + sum(dur * drain_w / 1e9) AS drain_j, + sum(dur / 1e6) AS dur_ms + FROM run_story_span_join_drain + GROUP BY name + ) +SELECT subsystem, sum(drain_j) AS drain_j, max(dur_ms) AS dur_ms +FROM drain_per_rail +JOIN power_counters + USING (name) GROUP BY subsystem; + CREATE VIEW interaction_events AS SELECT ts, dur FROM slice @@ -34,12 +42,19 @@ -- Compute cumulative power drain over the total duration of interaction events. CREATE VIEW interaction_drain AS -SELECT - subsystem, - sum(dur * drain_w / 1e9) as drain_j, - sum(dur / 1e6) as dur_ms -FROM interactions_span_join_drain -JOIN power_counters USING (name) +WITH + drain_per_rail AS ( + SELECT + name, + sum(dur * drain_w / 1e9) AS drain_j, + sum(dur / 1e6) AS dur_ms + FROM interactions_span_join_drain + GROUP BY name + ) +SELECT subsystem, sum(drain_j) AS drain_j, max(dur_ms) AS dur_ms +FROM drain_per_rail +JOIN power_counters + USING (name) GROUP BY subsystem; -- Output power consumption as measured by several ODPMs, over the following
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index f502833b..44ad1e3 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -302,7 +302,6 @@ <item id="tachyon_ice_config_fetcher" added_in_milestone="98" content_hash_code="01e878b0" os_list="chromeos" file_path="chrome/browser/nearby_sharing/tachyon_ice_config_fetcher.cc" /> <item id="supervised_users_denylist" added_in_milestone="98" content_hash_code="01cebaff" os_list="chromeos,android" file_path="chrome/browser/supervised_user/supervised_user_service.cc" /> <item id="app_suggestion_get_favicon" added_in_milestone="98" content_hash_code="07fca800" os_list="chromeos" file_path="chrome/browser/ui/app_list/search/app_service_app_result.cc" /> - <item id="url_icon_source_fetch" added_in_milestone="98" content_hash_code="0297f30b" os_list="chromeos" file_path="chrome/browser/ui/app_list/search/common/url_icon_source.cc" /> <item id="launcher_item_suggest" added_in_milestone="98" content_hash_code="04a4041e" os_list="chromeos" file_path="chrome/browser/ui/app_list/search/files/item_suggest_cache.cc" /> <item id="ambient_client" added_in_milestone="98" content_hash_code="062d821f" os_list="chromeos" file_path="chrome/browser/ui/ash/ambient/ambient_client_impl.cc" /> <item id="calendar_get_events" added_in_milestone="98" content_hash_code="0603f52a" os_list="chromeos" file_path="chrome/browser/ui/ash/calendar/calendar_keyed_service.cc" />
diff --git a/tools/traffic_annotation/summary/grouping.xml b/tools/traffic_annotation/summary/grouping.xml index b2e3885..825ac767 100644 --- a/tools/traffic_annotation/summary/grouping.xml +++ b/tools/traffic_annotation/summary/grouping.xml
@@ -88,7 +88,6 @@ <annotation id="tachyon_ice_config_fetcher"/> <annotation id="terms_of_service_fetch"/> <annotation id="timezone_lookup"/> - <annotation id="url_icon_source_fetch"/> <annotation id="wallpaper_backdrop_collection_names"/> <annotation id="wallpaper_backdrop_images_info"/> <annotation id="wallpaper_backdrop_surprise_me_image"/>
diff --git a/ui/ozone/platform/wayland/common/wayland_object.cc b/ui/ozone/platform/wayland/common/wayland_object.cc index 12ae52b2..1c621e2 100644 --- a/ui/ozone/platform/wayland/common/wayland_object.cc +++ b/ui/ozone/platform/wayland/common/wayland_object.cc
@@ -46,7 +46,12 @@ namespace { void delete_gtk_surface1(gtk_surface1* surface) { - gtk_surface1_release(surface); + if (wl::get_version_of_object(surface) >= + GTK_SURFACE1_RELEASE_SINCE_VERSION) { + gtk_surface1_release(surface); + } else { + gtk_surface1_destroy(surface); + } } void delete_data_device(wl_data_device* data_device) {
diff --git a/ui/ozone/platform/wayland/host/wayland_cursor_factory_unittest.cc b/ui/ozone/platform/wayland/host/wayland_cursor_factory_unittest.cc index b6ce41b..78abcde8 100644 --- a/ui/ozone/platform/wayland/host/wayland_cursor_factory_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_cursor_factory_unittest.cc
@@ -7,7 +7,6 @@ #include <wayland-cursor.h> #include "base/containers/flat_map.h" -#include "base/gtest_prod_util.h" #include "base/memory/scoped_refptr.h" #include "ui/base/cursor/platform_cursor.h" #include "ui/ozone/common/bitmap_cursor.h" @@ -53,11 +52,9 @@ } // namespace -class WaylandCursorFactoryTest : public WaylandTest, +class WaylandCursorFactoryTest : public WaylandTestSimple, public CursorFactoryObserver { public: - WaylandCursorFactoryTest() = default; - // CursorFactoryObserver: void OnThemeLoaded() override { ASSERT_TRUE(loop_quit_closure_); @@ -87,7 +84,7 @@ // Tests that the factory holds the cursor theme until a buffer taken from it // released. // TODO(1357512): fails on Linux (not used on LaCros). -TEST_P(WaylandCursorFactoryTest, +TEST_F(WaylandCursorFactoryTest, DISABLED_RetainOldThemeUntilNewBufferIsAttached) { std::unique_ptr<WaylandCursorFactory> cursor_factory = std::make_unique<DryRunningWaylandCursorFactory>(connection_.get()); @@ -167,7 +164,7 @@ // Tests that the factory keeps the caches when either cursor size or buffer // scale are changed, and only resets them when the theme is changed. // TODO(1357512): fails on Linux (not used on LaCros). -TEST_P(WaylandCursorFactoryTest, DISABLED_CachesSizesUntilThemeNameIsChanged) { +TEST_F(WaylandCursorFactoryTest, DISABLED_CachesSizesUntilThemeNameIsChanged) { std::unique_ptr<WaylandCursorFactory> cursor_factory = std::make_unique<DryRunningWaylandCursorFactory>(connection_.get()); cursor_factory->AddObserver(this); @@ -259,8 +256,4 @@ } } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandCursorFactoryTest, - Values(wl::ServerConfig{})); - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc index afb4371..4f196ad1 100644 --- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
@@ -266,7 +266,7 @@ std::unique_ptr<MockDragFinishedCallback> drag_finished_callback_; }; -TEST_P(WaylandDataDragControllerTest, StartDrag) { +TEST_F(WaylandDataDragControllerTest, StartDrag) { FocusAndPressLeftPointerButton(window_.get(), &delegate_); auto test = [](WaylandDataDragControllerTest* self) { @@ -287,7 +287,7 @@ EXPECT_FALSE(data_device()->drag_delegate_); } -TEST_P(WaylandDataDragControllerTest, StartDragWithWrongMimeType) { +TEST_F(WaylandDataDragControllerTest, StartDragWithWrongMimeType) { FocusAndPressLeftPointerButton(window_.get(), &delegate_); // The client starts dragging offering data with |kMimeTypeHTML| @@ -307,7 +307,7 @@ // - https://crbug.com/1236708 // - https://crbug.com/1207607 // - https://crbug.com/1247063 -TEST_P(WaylandDataDragControllerTest, StartDragWithCustomFormats) { +TEST_F(WaylandDataDragControllerTest, StartDragWithCustomFormats) { FocusAndPressLeftPointerButton(window_.get(), &delegate_); OSExchangeData data(OSExchangeDataProviderFactory::CreateProvider()); ClipboardFormatType kCustomFormats[] = { @@ -333,7 +333,7 @@ }); } -TEST_P(WaylandDataDragControllerTest, StartDragWithText) { +TEST_F(WaylandDataDragControllerTest, StartDragWithText) { FocusAndPressLeftPointerButton(window_.get(), &delegate_); // The client starts dragging offering text mime type. @@ -349,7 +349,7 @@ ReadAndCheckData(kMimeTypeText, kSampleTextForDragAndDrop); } -TEST_P(WaylandDataDragControllerTest, StartDragWithFileContents) { +TEST_F(WaylandDataDragControllerTest, StartDragWithFileContents) { FocusAndPressLeftPointerButton(window_.get(), &delegate_); // The client starts dragging offering text mime type. @@ -375,7 +375,7 @@ return arg.IsWithinDistance(n, 0.01f); } -TEST_P(WaylandDataDragControllerTest, ReceiveDrag) { +TEST_F(WaylandDataDragControllerTest, ReceiveDrag) { const uint32_t surface_id = window_->root_surface()->get_surface_id(); // Consume the move event from pointer enter. @@ -428,7 +428,7 @@ ASSERT_FALSE(data_device()->drag_delegate_); } -TEST_P(WaylandDataDragControllerTest, ReceiveDragPixelSurface) { +TEST_F(WaylandDataDragControllerTest, ReceiveDragPixelSurface) { constexpr int32_t kTripleScale = 3; // Set connection to use pixel coordinates. @@ -495,7 +495,7 @@ SendMotionEvent(top_left); } -TEST_P(WaylandDataDragControllerTest, DropSeveralMimeTypes) { +TEST_F(WaylandDataDragControllerTest, DropSeveralMimeTypes) { EXPECT_CALL(*drop_handler_, MockOnDragEnter()).Times(1); const uint32_t surface_id = window_->root_surface()->get_surface_id(); PostToServerAndWait([surface_id](wl::TestWaylandServerThread* server) { @@ -539,7 +539,7 @@ // Tests URI validation for text/uri-list MIME type. Log warnings rendered in // the console when this test is running are the expected and valid side effect. -TEST_P(WaylandDataDragControllerTest, ValidateDroppedUriList) { +TEST_F(WaylandDataDragControllerTest, ValidateDroppedUriList) { const struct { std::string content; base::flat_set<std::string> expected_uris; @@ -600,7 +600,7 @@ // Tests URI validation for text/x-moz-url MIME type. Log warnings rendered in // the console when this test is running are the expected and valid side effect. -TEST_P(WaylandDataDragControllerTest, ValidateDroppedXMozUrl) { +TEST_F(WaylandDataDragControllerTest, ValidateDroppedXMozUrl) { const struct { std::u16string content; std::string expected_url; @@ -663,7 +663,7 @@ // Verifies the correct delegate functions are called when a drag session is // started and cancelled within the same surface. -TEST_P(WaylandDataDragControllerTest, StartAndCancel) { +TEST_F(WaylandDataDragControllerTest, StartAndCancel) { FocusAndPressLeftPointerButton(window_.get(), &delegate_); ScheduleDataDeviceAction(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE); @@ -674,7 +674,7 @@ RunMouseDragWithSampleData(window_.get(), DragDropTypes::DRAG_COPY); } -TEST_P(WaylandDataDragControllerTest, ForeignDragHandleAskAction) { +TEST_F(WaylandDataDragControllerTest, ForeignDragHandleAskAction) { const uint32_t surface_id = window_->root_surface()->get_surface_id(); PostToServerAndWait([surface_id](wl::TestWaylandServerThread* server) { auto* data_offer = @@ -721,7 +721,7 @@ // Verifies entered surface destruction is properly handled. // Regression test for https://crbug.com/1143707. -TEST_P(WaylandDataDragControllerTest, DestroyEnteredSurface) { +TEST_F(WaylandDataDragControllerTest, DestroyEnteredSurface) { auto* window_1 = window_.get(); FocusAndPressLeftPointerButton(window_1, &delegate_); @@ -758,7 +758,7 @@ // Verifies that early origin surface destruction is properly handled. // Regression test for https://crbug.com/1143707. -TEST_P(WaylandDataDragControllerTest, DestroyOriginSurface) { +TEST_F(WaylandDataDragControllerTest, DestroyOriginSurface) { auto* window_1 = window_.get(); SetPointerFocusedWindow(nullptr); @@ -802,7 +802,7 @@ } // Ensures drag/drop events are properly propagated to non-toplevel windows. -TEST_P(WaylandDataDragControllerTest, DragToNonToplevelWindows) { +TEST_F(WaylandDataDragControllerTest, DragToNonToplevelWindows) { auto* origin_window = window_.get(); FocusAndPressLeftPointerButton(origin_window, &delegate_); @@ -860,7 +860,7 @@ // Ensures that requests to create a |PlatformWindowType::kPopup| during drag // sessions return xdg_popup-backed windows. -TEST_P(WaylandDataDragControllerTest, PopupRequestCreatesPopupWindow) { +TEST_F(WaylandDataDragControllerTest, PopupRequestCreatesPopupWindow) { auto* origin_window = window_.get(); FocusAndPressLeftPointerButton(origin_window, &delegate_); @@ -892,7 +892,7 @@ // Ensures that requests to create a |PlatformWindowType::kMenu| during drag // sessions return xdg_popup-backed windows. -TEST_P(WaylandDataDragControllerTest, MenuRequestCreatesPopupWindow) { +TEST_F(WaylandDataDragControllerTest, MenuRequestCreatesPopupWindow) { auto* origin_window = window_.get(); FocusAndPressLeftPointerButton(origin_window, &delegate_); @@ -933,7 +933,7 @@ // browser <=> renderer IPC, etc. In both cases, drag controller is expected to // gracefully reset state and quit drag loop as if the drag session was // cancelled as usual. -TEST_P(WaylandDataDragControllerTest, AsyncNoopStartDrag) { +TEST_F(WaylandDataDragControllerTest, AsyncNoopStartDrag) { OSExchangeData os_exchange_data; os_exchange_data.SetString(sample_text_for_dnd()); @@ -988,7 +988,7 @@ } // Regression test for https://crbug.com/1175083. -TEST_P(WaylandDataDragControllerTest, StartDragWithCorrectSerial) { +TEST_F(WaylandDataDragControllerTest, StartDragWithCorrectSerial) { FocusAndPressLeftPointerButton(window_.get(), &delegate_); absl::optional<wl::Serial> mouse_press_serial = connection()->serial_tracker().GetSerial(wl::SerialType::kMousePress); @@ -1038,7 +1038,7 @@ // Check drag session is correctly started when there are both mouse button and // a touch point pressed. -TEST_P(WaylandDataDragControllerTest, StartDragWithCorrectSerialForDragSource) { +TEST_F(WaylandDataDragControllerTest, StartDragWithCorrectSerialForDragSource) { OSExchangeData os_exchange_data; os_exchange_data.SetString(sample_text_for_dnd()); @@ -1093,8 +1093,4 @@ }); } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandDataDragControllerTest, - Values(wl::ServerConfig{})); - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_event_source_unittest.cc b/ui/ozone/platform/wayland/host/wayland_event_source_unittest.cc index 3a3c834..06020a1 100644 --- a/ui/ozone/platform/wayland/host/wayland_event_source_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_event_source_unittest.cc
@@ -7,6 +7,7 @@ #include "base/memory/raw_ptr.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/ozone/platform/wayland/host/wayland_event_source.h" +#include "ui/ozone/platform/wayland/host/wayland_seat.h" #include "ui/ozone/platform/wayland/test/mock_pointer.h" #include "ui/ozone/platform/wayland/test/mock_surface.h" #include "ui/ozone/platform/wayland/test/test_keyboard.h" @@ -25,45 +26,27 @@ } // namespace -class WaylandEventSourceTest : public WaylandTest { +class WaylandEventSourceTest : public WaylandTestSimple { public: - WaylandEventSourceTest() {} - - WaylandEventSourceTest(const WaylandEventSourceTest&) = delete; - WaylandEventSourceTest& operator=(const WaylandEventSourceTest&) = delete; - void SetUp() override { - WaylandTest::SetUp(); + WaylandTestSimple::SetUp(); pointer_delegate_ = connection_->event_source(); ASSERT_TRUE(pointer_delegate_); } protected: - std::unique_ptr<WaylandWindow> CreateWaylandWindowWithParams( - PlatformWindowType type, - const gfx::Rect bounds, - MockPlatformWindowDelegate* delegate) { - PlatformWindowInitProperties properties; - properties.bounds = bounds; - properties.type = type; - auto window = WaylandWindow::Create(delegate, connection_.get(), - std::move(properties)); - if (window) - window->Show(false); - return window; - } - raw_ptr<WaylandPointer::Delegate> pointer_delegate_ = nullptr; }; // Verify WaylandEventSource properly manages its internal state as pointer // button events are sent. More specifically - pointer flags. -TEST_P(WaylandEventSourceTest, CheckPointerButtonHandling) { - MockPlatformWindowDelegate delegate; - wl_seat_send_capabilities(server_.seat()->resource(), - WL_SEAT_CAPABILITY_POINTER); - Sync(); +TEST_F(WaylandEventSourceTest, CheckPointerButtonHandling) { + PostToServerAndWait([](wl::TestWaylandServerThread* server) { + wl_seat_send_capabilities(server->seat()->resource(), + WL_SEAT_CAPABILITY_POINTER); + }); + ASSERT_TRUE(connection_->seat()->pointer()); EXPECT_FALSE(pointer_delegate_->IsPointerButtonPressed(EF_LEFT_MOUSE_BUTTON)); EXPECT_FALSE( @@ -74,46 +57,51 @@ EXPECT_FALSE( pointer_delegate_->IsPointerButtonPressed(EF_FORWARD_MOUSE_BUTTON)); - auto window1 = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, - kDefaultBounds, &delegate); - Sync(); + EXPECT_CALL(delegate_, DispatchEvent(_)).Times(2); - ASSERT_TRUE(server_.seat()->pointer()); + PostToServerAndWait([surface_id = window_->root_surface()->get_surface_id()]( + wl::TestWaylandServerThread* server) { + auto* const surface = + server->GetObject<wl::MockSurface>(surface_id)->resource(); + auto* const pointer = server->seat()->pointer()->resource(); - uint32_t serial = 0; - uint32_t tstamp = 0; - wl_resource* surface_res = - server_ - .GetObject<wl::MockSurface>(window1->root_surface()->get_surface_id()) - ->resource(); - wl_resource* pointer_res = server_.seat()->pointer()->resource(); - - wl_pointer_send_enter(pointer_res, serial++, surface_res, 0, 0); - wl_pointer_send_frame(pointer_res); - wl_pointer_send_button(pointer_res, serial++, tstamp++, BTN_LEFT, - WL_POINTER_BUTTON_STATE_PRESSED); - wl_pointer_send_frame(pointer_res); - EXPECT_CALL(delegate, DispatchEvent(_)).Times(2); - Sync(); + wl_pointer_send_enter(pointer, server->GetNextSerial(), surface, 0, 0); + wl_pointer_send_frame(pointer); + wl_pointer_send_button(pointer, server->GetNextSerial(), + server->GetNextTime(), BTN_LEFT, + WL_POINTER_BUTTON_STATE_PRESSED); + wl_pointer_send_frame(pointer); + }); EXPECT_TRUE(pointer_delegate_->IsPointerButtonPressed(EF_LEFT_MOUSE_BUTTON)); - wl_pointer_send_button(pointer_res, serial++, tstamp++, BTN_RIGHT, - WL_POINTER_BUTTON_STATE_PRESSED); - wl_pointer_send_frame(pointer_res); - EXPECT_CALL(delegate, DispatchEvent(_)).Times(1); - Sync(); + EXPECT_CALL(delegate_, DispatchEvent(_)).Times(1); + + PostToServerAndWait([](wl::TestWaylandServerThread* server) { + auto* const pointer = server->seat()->pointer()->resource(); + + wl_pointer_send_button(pointer, server->GetNextSerial(), + server->GetNextTime(), BTN_RIGHT, + WL_POINTER_BUTTON_STATE_PRESSED); + wl_pointer_send_frame(pointer); + }); EXPECT_TRUE(pointer_delegate_->IsPointerButtonPressed(EF_RIGHT_MOUSE_BUTTON)); - wl_pointer_send_button(pointer_res, serial++, tstamp++, BTN_LEFT, - WL_POINTER_BUTTON_STATE_RELEASED); - wl_pointer_send_frame(pointer_res); - wl_pointer_send_button(pointer_res, serial++, tstamp++, BTN_RIGHT, - WL_POINTER_BUTTON_STATE_RELEASED); - wl_pointer_send_frame(pointer_res); - EXPECT_CALL(delegate, DispatchEvent(_)).Times(2); - Sync(); + EXPECT_CALL(delegate_, DispatchEvent(_)).Times(2); + PostToServerAndWait([surface_id = window_->root_surface()->get_surface_id()]( + wl::TestWaylandServerThread* server) { + auto* const pointer = server->seat()->pointer()->resource(); + + wl_pointer_send_button(pointer, server->GetNextSerial(), + server->GetNextTime(), BTN_LEFT, + WL_POINTER_BUTTON_STATE_RELEASED); + wl_pointer_send_frame(pointer); + wl_pointer_send_button(pointer, server->GetNextSerial(), + server->GetNextTime(), BTN_RIGHT, + WL_POINTER_BUTTON_STATE_RELEASED); + wl_pointer_send_frame(pointer); + }); EXPECT_FALSE(pointer_delegate_->IsPointerButtonPressed(EF_LEFT_MOUSE_BUTTON)); EXPECT_FALSE( @@ -122,76 +110,67 @@ // Verify WaylandEventSource properly manages its internal state as pointer // button events are sent. More specifically - pointer flags. -TEST_P(WaylandEventSourceTest, DeleteBeforeTouchFrame) { - MockPlatformWindowDelegate delegate; - wl_seat_send_capabilities(server_.seat()->resource(), - WL_SEAT_CAPABILITY_TOUCH); +TEST_F(WaylandEventSourceTest, DeleteBeforeTouchFrame) { + PostToServerAndWait([](wl::TestWaylandServerThread* server) { + wl_seat_send_capabilities(server->seat()->resource(), + WL_SEAT_CAPABILITY_TOUCH); + }); + ASSERT_TRUE(connection_->seat()->touch()); + MockWaylandPlatformWindowDelegate delegate; auto window1 = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, kDefaultBounds, &delegate); - Sync(); - ASSERT_TRUE(server_.seat()->touch()); + PostToServerAndWait([surface_id = window1->root_surface()->get_surface_id()]( + wl::TestWaylandServerThread* server) { + auto* const surface = + server->GetObject<wl::MockSurface>(surface_id)->resource(); + auto* const touch = server->seat()->touch()->resource(); - uint32_t serial = 0; - uint32_t tstamp = 0; - wl_resource* surface_res = - server_ - .GetObject<wl::MockSurface>(window1->root_surface()->get_surface_id()) - ->resource(); - wl_resource* touch_res = server_.seat()->touch()->resource(); - - wl_touch_send_down(touch_res, serial++, tstamp++, surface_res, /*id=*/0, 0, - 0); - wl_touch_send_down(touch_res, serial++, tstamp++, surface_res, /*id=*/1, 0, - 0); - - Sync(); + wl_touch_send_down(touch, server->GetNextSerial(), server->GetNextTime(), + surface, /*id=*/0, 0, 0); + wl_touch_send_down(touch, server->GetNextSerial(), server->GetNextTime(), + surface, /*id=*/1, 0, 0); + }); // Removing the target during touch event sequence should not cause crash. window1.reset(); - wl_touch_send_frame(touch_res); EXPECT_CALL(delegate, DispatchEvent(_)).Times(0); - Sync(); + PostToServerAndWait([](wl::TestWaylandServerThread* server) { + auto* const touch = server->seat()->touch()->resource(); + + wl_touch_send_frame(touch); + }); } // Verify WaylandEventSource ignores release events for mouse buttons that // aren't pressed. Regression test for crbug.com/1376393. -TEST_P(WaylandEventSourceTest, IgnoreReleaseWithoutPress) { - MockPlatformWindowDelegate delegate; - wl_seat_send_capabilities(server_.seat()->resource(), - WL_SEAT_CAPABILITY_POINTER); +TEST_F(WaylandEventSourceTest, IgnoreReleaseWithoutPress) { + PostToServerAndWait([](wl::TestWaylandServerThread* server) { + wl_seat_send_capabilities(server->seat()->resource(), + WL_SEAT_CAPABILITY_POINTER); + }); + ASSERT_TRUE(connection_->seat()->pointer()); - auto window1 = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, - kDefaultBounds, &delegate); - Sync(); + // The only event the delegate should capture is when the pointer enters the + // surface. + EXPECT_CALL(delegate_, DispatchEvent(_)).Times(1); + PostToServerAndWait([surface_id = window_->root_surface()->get_surface_id()]( + wl::TestWaylandServerThread* server) { + auto* const surface = + server->GetObject<wl::MockSurface>(surface_id)->resource(); + auto* const pointer = server->seat()->pointer()->resource(); - ASSERT_TRUE(server_.seat()->pointer()); + wl_pointer_send_enter(pointer, server->GetNextSerial(), surface, 0, 0); + wl_pointer_send_frame(pointer); - uint32_t serial = 0; - uint32_t tstamp = 0; - wl_resource* surface_res = - server_ - .GetObject<wl::MockSurface>(window1->root_surface()->get_surface_id()) - ->resource(); - wl_resource* pointer_res = server_.seat()->pointer()->resource(); - - wl_pointer_send_enter(pointer_res, serial++, surface_res, 0, 0); - wl_pointer_send_frame(pointer_res); - EXPECT_CALL(delegate, DispatchEvent(_)).Times(1); - Sync(); - - wl_pointer_send_button(pointer_res, serial++, tstamp++, BTN_LEFT, - WL_POINTER_BUTTON_STATE_RELEASED); - wl_pointer_send_frame(pointer_res); - EXPECT_CALL(delegate, DispatchEvent(_)).Times(0); - Sync(); + wl_pointer_send_button(pointer, server->GetNextSerial(), + server->GetNextTime(), BTN_LEFT, + WL_POINTER_BUTTON_STATE_RELEASED); + wl_pointer_send_frame(pointer); + }); } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandEventSourceTest, - Values(wl::ServerConfig{})); - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_event_watcher_unittest.cc b/ui/ozone/platform/wayland/host/wayland_event_watcher_unittest.cc index 5454edf..9d528cb 100644 --- a/ui/ozone/platform/wayland/host/wayland_event_watcher_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_event_watcher_unittest.cc
@@ -38,24 +38,18 @@ // the sync on the test tear down. To ensure that the error message is caught // by the crash reporter, we wait until idle in the end of each test before // checking the crash key value. -class WaylandEventWatcherTest : public WaylandTest { - public: - WaylandEventWatcherTest() : WaylandTest(TestServerMode::kAsync) {} - WaylandEventWatcherTest(const WaylandEventWatcherTest&) = delete; - WaylandEventWatcherTest& operator=(const WaylandEventWatcherTest&) = delete; - ~WaylandEventWatcherTest() override = default; - +class WaylandEventWatcherTest : public WaylandTestSimple { protected: void TearDown() override { // All tests in this suite terminate the client-server connection by posting // various errors. We cannot sync the connection on tear down. DisableSyncOnTearDown(); - WaylandTest::TearDown(); + WaylandTestSimple::TearDown(); } }; -TEST_P(WaylandEventWatcherTest, CrashKeyResourceError) { +TEST_F(WaylandEventWatcherTest, CrashKeyResourceError) { const std::string kTestErrorString = "This is a nice error."; std::string text; @@ -88,7 +82,7 @@ EXPECT_EQ(text, crash_reporter::GetCrashKeyValue("wayland_error")); } -TEST_P(WaylandEventWatcherTest, CrashKeyResourceNoMemory) { +TEST_F(WaylandEventWatcherTest, CrashKeyResourceNoMemory) { // Prepare the expectation error string. const std::string expected_error_code = base::StrCat( {"wl_display: error ", @@ -111,7 +105,7 @@ crash_reporter::GetCrashKeyValue("wayland_error")); } -TEST_P(WaylandEventWatcherTest, CrashKeyClientNoMemoryError) { +TEST_F(WaylandEventWatcherTest, CrashKeyClientNoMemoryError) { const std::string expected_error_code = base::StrCat( {"wl_display: error ", NumberToString(static_cast<uint32_t>(WL_DISPLAY_ERROR_NO_MEMORY)), @@ -128,7 +122,7 @@ crash_reporter::GetCrashKeyValue("wayland_error")); } -TEST_P(WaylandEventWatcherTest, CrashKeyClientImplementationError) { +TEST_F(WaylandEventWatcherTest, CrashKeyClientImplementationError) { const std::string kError = "A nice error."; const std::string expected_error_code = base::StrCat( {"wl_display: error ", @@ -147,7 +141,7 @@ crash_reporter::GetCrashKeyValue("wayland_error")); } -TEST_P(WaylandEventWatcherTest, CrashKeyCompositorNameSet) { +TEST_F(WaylandEventWatcherTest, CrashKeyCompositorNameSet) { const std::string kTestWaylandCompositor = "OzoneWaylandTestCompositor"; base::Environment::Create()->SetVar(base::nix::kXdgCurrentDesktopEnvVar, kTestWaylandCompositor); @@ -164,7 +158,7 @@ crash_reporter::GetCrashKeyValue("wayland_compositor")); } -TEST_P(WaylandEventWatcherTest, CrashKeyCompositorNameUnset) { +TEST_F(WaylandEventWatcherTest, CrashKeyCompositorNameUnset) { base::Environment::Create()->UnSetVar(base::nix::kXdgCurrentDesktopEnvVar); server_.RunAndWait( @@ -178,8 +172,4 @@ EXPECT_EQ("Unknown", crash_reporter::GetCrashKeyValue("wayland_compositor")); } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandEventWatcherTest, - Values(wl::ServerConfig{})); - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc b/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc index 10d8f80..9304d56 100644 --- a/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
@@ -20,6 +20,7 @@ #include "ui/gfx/range/range.h" #include "ui/ozone/platform/wayland/host/wayland_event_source.h" #include "ui/ozone/platform/wayland/host/wayland_input_method_context.h" +#include "ui/ozone/platform/wayland/host/wayland_seat.h" #include "ui/ozone/platform/wayland/host/wayland_window.h" #include "ui/ozone/platform/wayland/test/mock_surface.h" #include "ui/ozone/platform/wayland/test/mock_zcr_extended_text_input.h" @@ -35,7 +36,6 @@ using ::testing::Values; namespace ui { -namespace { // Returns the number of grapheme clusters in the text. absl::optional<size_t> CountGraphemeCluster(base::StringPiece16 text) { @@ -229,19 +229,10 @@ absl::optional<gfx::Rect> virtual_keyboard_bounds_; }; -class WaylandInputMethodContextTest : public WaylandTest { +class WaylandInputMethodContextTest : public WaylandTestSimple { public: - // TODO(crbug.com/1365887): TestServerMode::kAsync must be removed once all - // tests switch to asynchronous mode. - WaylandInputMethodContextTest() - : WaylandTest(WaylandTest::TestServerMode::kAsync) {} - ~WaylandInputMethodContextTest() override = default; - WaylandInputMethodContextTest(const WaylandInputMethodContextTest&) = delete; - WaylandInputMethodContextTest& operator=( - const WaylandInputMethodContextTest&) = delete; - void SetUp() override { - WaylandTest::SetUp(); + WaylandTestSimple::SetUp(); surface_id_ = window_->root_surface()->get_surface_id(); @@ -251,6 +242,7 @@ wl_seat_send_capabilities(server->seat()->resource(), WL_SEAT_CAPABILITY_KEYBOARD); }); + ASSERT_TRUE(connection_->seat()->keyboard()); SetUpInternal(); } @@ -288,7 +280,7 @@ uint32_t surface_id_ = 0u; }; -TEST_P(WaylandInputMethodContextTest, ActivateDeactivate) { +TEST_F(WaylandInputMethodContextTest, ActivateDeactivate) { // Activate is called only when both InputMethod's TextInputClient focus and // Wayland's keyboard focus is met. @@ -403,7 +395,7 @@ }); } -TEST_P(WaylandInputMethodContextTest, Reset) { +TEST_F(WaylandInputMethodContextTest, Reset) { PostToServerAndWait([](wl::TestWaylandServerThread* server) { EXPECT_CALL(*server->text_input_manager_v1()->text_input(), Reset()); }); @@ -411,7 +403,7 @@ connection_->Flush(); } -TEST_P(WaylandInputMethodContextTest, SetCursorLocation) { +TEST_F(WaylandInputMethodContextTest, SetCursorLocation) { constexpr gfx::Rect cursor_location(50, 0, 1, 1); PostToServerAndWait([cursor_location](wl::TestWaylandServerThread* server) { EXPECT_CALL( @@ -423,7 +415,7 @@ connection_->Flush(); } -TEST_P(WaylandInputMethodContextTest, SetSurroundingTextForShortText) { +TEST_F(WaylandInputMethodContextTest, SetSurroundingTextForShortText) { const std::u16string text(50, u'あ'); constexpr gfx::Range range(20, 30); @@ -458,7 +450,7 @@ (std::pair<size_t, size_t>(0, 0))); } -TEST_P(WaylandInputMethodContextTest, SetSurroundingTextForLongText) { +TEST_F(WaylandInputMethodContextTest, SetSurroundingTextForLongText) { const std::u16string text(5000, u'あ'); constexpr gfx::Range range(2800, 3200); @@ -495,7 +487,7 @@ (std::pair<size_t, size_t>(0, 0))); } -TEST_P(WaylandInputMethodContextTest, SetSurroundingTextForLongTextInLeftEdge) { +TEST_F(WaylandInputMethodContextTest, SetSurroundingTextForLongTextInLeftEdge) { const std::u16string text(5000, u'あ'); constexpr gfx::Range range(0, 500); @@ -532,7 +524,7 @@ (std::pair<size_t, size_t>(0, 0))); } -TEST_P(WaylandInputMethodContextTest, +TEST_F(WaylandInputMethodContextTest, SetSurroundingTextForLongTextInRightEdge) { const std::u16string text(5000, u'あ'); constexpr gfx::Range range(4500, 5000); @@ -570,7 +562,7 @@ (std::pair<size_t, size_t>(0, 0))); } -TEST_P(WaylandInputMethodContextTest, SetSurroundingTextForLongRange) { +TEST_F(WaylandInputMethodContextTest, SetSurroundingTextForLongRange) { const std::u16string text(5000, u'あ'); constexpr gfx::Range range(1000, 4000); @@ -591,7 +583,7 @@ }); } -TEST_P(WaylandInputMethodContextTest, DeleteSurroundingTextWithExtendedRange) { +TEST_F(WaylandInputMethodContextTest, DeleteSurroundingTextWithExtendedRange) { const std::u16string text(50, u'あ'); const gfx::Range range(20, 30); @@ -626,7 +618,7 @@ (std::pair<size_t, size_t>(1, 1))); } -TEST_P(WaylandInputMethodContextTest, SetContentType) { +TEST_F(WaylandInputMethodContextTest, SetContentType) { PostToServerAndWait([](wl::TestWaylandServerThread* server) { EXPECT_CALL( *server->text_input_extension_v1()->extended_text_input(), @@ -648,7 +640,7 @@ }); } -TEST_P(WaylandInputMethodContextTest, SetContentTypeWithoutLearning) { +TEST_F(WaylandInputMethodContextTest, SetContentTypeWithoutLearning) { PostToServerAndWait([](wl::TestWaylandServerThread* server) { EXPECT_CALL( *server->text_input_extension_v1()->extended_text_input(), @@ -670,7 +662,7 @@ }); } -TEST_P(WaylandInputMethodContextTest, OnPreeditChanged) { +TEST_F(WaylandInputMethodContextTest, OnPreeditChanged) { PostToServerAndWait([](wl::TestWaylandServerThread* server) { zwp_text_input_v1_send_preedit_string( server->text_input_manager_v1()->text_input()->resource(), @@ -679,7 +671,7 @@ EXPECT_TRUE(input_method_context_delegate_->was_on_preedit_changed_called()); } -TEST_P(WaylandInputMethodContextTest, OnCommit) { +TEST_F(WaylandInputMethodContextTest, OnCommit) { PostToServerAndWait([](wl::TestWaylandServerThread* server) { zwp_text_input_v1_send_commit_string( server->text_input_manager_v1()->text_input()->resource(), @@ -697,7 +689,7 @@ #define MAYBE(x) DISABLED_##x #endif -TEST_P(WaylandInputMethodContextTest, MAYBE(OnConfirmCompositionText)) { +TEST_F(WaylandInputMethodContextTest, MAYBE(OnConfirmCompositionText)) { constexpr char16_t text[] = u"ab😀cあdef"; constexpr gfx::Range range(5, 6); // あ is selected. @@ -722,7 +714,7 @@ input_method_context_delegate_->was_on_confirm_composition_text_called()); } -TEST_P(WaylandInputMethodContextTest, OnSetPreeditRegion_Success) { +TEST_F(WaylandInputMethodContextTest, OnSetPreeditRegion_Success) { constexpr char16_t text[] = u"abcあdef"; const gfx::Range range(3, 4); // あ is selected. @@ -749,7 +741,7 @@ input_method_context_delegate_->was_on_set_preedit_region_called()); } -TEST_P(WaylandInputMethodContextTest, OnSetPreeditRegion_NoSurroundingText) { +TEST_F(WaylandInputMethodContextTest, OnSetPreeditRegion_NoSurroundingText) { // If no surrounding text is set yet, set_preedit_region would fail. PostToServerAndWait([](wl::TestWaylandServerThread* server) { zcr_extended_text_input_v1_send_set_preedit_region( @@ -762,7 +754,7 @@ // The range is represented in UTF-16 code points, so it is independent from // grapheme clusters. -TEST_P(WaylandInputMethodContextTest, +TEST_F(WaylandInputMethodContextTest, OnSetPreeditRegion_GraphemeClusterIndependeceSimple) { // Single code point representation of é. constexpr char16_t u16_text[] = u"\u00E9"; @@ -797,7 +789,7 @@ input_method_context_delegate_->was_on_set_preedit_region_called()); } -TEST_P(WaylandInputMethodContextTest, +TEST_F(WaylandInputMethodContextTest, OnSetPreeditRegion_GraphemeClusterIndependeceCombined) { // Decomposed code point representation of é. constexpr char16_t u16_text[] = u"\u0065\u0301"; @@ -832,14 +824,14 @@ input_method_context_delegate_->was_on_set_preedit_region_called()); } -TEST_P(WaylandInputMethodContextTest, OnClearGrammarFragments) { +TEST_F(WaylandInputMethodContextTest, OnClearGrammarFragments) { input_method_context_->OnClearGrammarFragments(gfx::Range(1, 5)); SyncDisplay(); EXPECT_TRUE( input_method_context_delegate_->was_on_clear_grammar_fragments_called()); } -TEST_P(WaylandInputMethodContextTest, OnAddGrammarFragments) { +TEST_F(WaylandInputMethodContextTest, OnAddGrammarFragments) { input_method_context_->OnAddGrammarFragment( ui::GrammarFragment(gfx::Range(1, 5), "test")); SyncDisplay(); @@ -847,21 +839,21 @@ input_method_context_delegate_->was_on_add_grammar_fragment_called()); } -TEST_P(WaylandInputMethodContextTest, OnSetAutocorrectRange) { +TEST_F(WaylandInputMethodContextTest, OnSetAutocorrectRange) { input_method_context_->OnSetAutocorrectRange(gfx::Range(1, 5)); SyncDisplay(); EXPECT_TRUE( input_method_context_delegate_->was_on_set_autocorrect_range_called()); } -TEST_P(WaylandInputMethodContextTest, OnSetVirtualKeyboardOccludedBounds) { +TEST_F(WaylandInputMethodContextTest, OnSetVirtualKeyboardOccludedBounds) { constexpr gfx::Rect kBounds(10, 20, 300, 400); input_method_context_->OnSetVirtualKeyboardOccludedBounds(kBounds); SyncDisplay(); EXPECT_EQ(input_method_context_delegate_->virtual_keyboard_bounds(), kBounds); } -TEST_P(WaylandInputMethodContextTest, +TEST_F(WaylandInputMethodContextTest, OnSetVirtualKeyboardOccludedBoundsUpdatesPastTextInputClients) { auto client1 = std::make_unique<MockTextInputClient>(TEXT_INPUT_TYPE_TEXT); auto client2 = std::make_unique<MockTextInputClient>(TEXT_INPUT_TYPE_URL); @@ -901,7 +893,7 @@ Mock::VerifyAndClearExpectations(client2.get()); } -TEST_P(WaylandInputMethodContextTest, +TEST_F(WaylandInputMethodContextTest, OnSetVirtualKeyboardOccludedBoundsWithDeletedPastTextInputClient) { auto client = std::make_unique<MockTextInputClient>(TEXT_INPUT_TYPE_TEXT); @@ -920,7 +912,7 @@ SyncDisplay(); } -TEST_P(WaylandInputMethodContextTest, DisplayVirtualKeyboard) { +TEST_F(WaylandInputMethodContextTest, DisplayVirtualKeyboard) { PostToServerAndWait([](wl::TestWaylandServerThread* server) { EXPECT_CALL(*server->text_input_manager_v1()->text_input(), ShowInputPanel()) @@ -931,7 +923,7 @@ SyncDisplay(); } -TEST_P(WaylandInputMethodContextTest, DismissVirtualKeyboard) { +TEST_F(WaylandInputMethodContextTest, DismissVirtualKeyboard) { PostToServerAndWait([](wl::TestWaylandServerThread* server) { EXPECT_CALL(*server->text_input_manager_v1()->text_input(), HideInputPanel()); @@ -941,7 +933,7 @@ SyncDisplay(); } -TEST_P(WaylandInputMethodContextTest, UpdateVirtualKeyboardState) { +TEST_F(WaylandInputMethodContextTest, UpdateVirtualKeyboardState) { EXPECT_FALSE(input_method_context_->IsKeyboardVisible()); PostToServerAndWait([](wl::TestWaylandServerThread* server) { zwp_text_input_v1_send_input_panel_state( @@ -961,16 +953,17 @@ class WaylandInputMethodContextNoKeyboardTest : public WaylandInputMethodContextTest { public: - WaylandInputMethodContextNoKeyboardTest() = default; - ~WaylandInputMethodContextNoKeyboardTest() override = default; - void SetUp() override { - WaylandTest::SetUp(); + // Call the skip base implementation to avoid setting up the keyboard. + WaylandTestSimple::SetUp(); + + ASSERT_FALSE(connection_->seat()->keyboard()); + SetUpInternal(); } }; -TEST_P(WaylandInputMethodContextNoKeyboardTest, ActivateDeactivate) { +TEST_F(WaylandInputMethodContextNoKeyboardTest, ActivateDeactivate) { const uint32_t surface_id = window_->root_surface()->get_surface_id(); // Because there is no keyboard, Activate is called as soon as InputMethod's @@ -1005,7 +998,7 @@ }); } -TEST_P(WaylandInputMethodContextNoKeyboardTest, UpdateFocusBetweenTextFields) { +TEST_F(WaylandInputMethodContextNoKeyboardTest, UpdateFocusBetweenTextFields) { const uint32_t surface_id = window_->root_surface()->get_surface_id(); // Because there is no keyboard, Activate is called as soon as InputMethod's @@ -1045,13 +1038,4 @@ }); } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandInputMethodContextTest, - Values(wl::ServerConfig{})); - -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandInputMethodContextNoKeyboardTest, - Values(wl::ServerConfig{})); - -} // namespace } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_keyboard_unittest.cc b/ui/ozone/platform/wayland/host/wayland_keyboard_unittest.cc index 70b1fe6..7d079e7 100644 --- a/ui/ozone/platform/wayland/host/wayland_keyboard_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_keyboard_unittest.cc
@@ -34,15 +34,10 @@ namespace ui { -class WaylandKeyboardTest : public WaylandTest { +class WaylandKeyboardTest : public WaylandTestSimple { public: - WaylandKeyboardTest() : WaylandTest(TestServerMode::kAsync) {} - WaylandKeyboardTest(const WaylandKeyboardTest&) = delete; - WaylandKeyboardTest& operator=(const WaylandKeyboardTest&) = delete; - ~WaylandKeyboardTest() override = default; - void SetUp() override { - WaylandTest::SetUp(); + WaylandTestSimple::SetUp(); PostToServerAndWait([](wl::TestWaylandServerThread* server) { wl_seat_send_capabilities(server->seat()->resource(), @@ -96,7 +91,7 @@ closure.Run(); } -TEST_P(WaylandKeyboardTest, Keypress) { +TEST_F(WaylandKeyboardTest, Keypress) { SendEnter(); std::unique_ptr<Event> event; @@ -135,7 +130,7 @@ }); } -TEST_P(WaylandKeyboardTest, ControlShiftModifiers) { +TEST_F(WaylandKeyboardTest, ControlShiftModifiers) { SendEnter(); std::vector<std::unique_ptr<Event>> events; @@ -183,7 +178,7 @@ } #if BUILDFLAG(USE_XKBCOMMON) -TEST_P(WaylandKeyboardTest, CapsLockModifier) { +TEST_F(WaylandKeyboardTest, CapsLockModifier) { SendEnter(); std::vector<std::unique_ptr<Event>> events; @@ -231,7 +226,7 @@ } #endif -TEST_P(WaylandKeyboardTest, EventAutoRepeat) { +TEST_F(WaylandKeyboardTest, EventAutoRepeat) { constexpr int32_t rate = 5; // num key events per second. constexpr int32_t delay = 60; // in milliseconds. @@ -288,7 +283,7 @@ EXPECT_EQ(second_repeat_delay.InMilliseconds(), 1000 / rate); } -TEST_P(WaylandKeyboardTest, NoEventAutoRepeatOnLeave) { +TEST_F(WaylandKeyboardTest, NoEventAutoRepeatOnLeave) { constexpr int32_t rate = 5; // num key events per second. constexpr int32_t delay = 60; // in milliseconds. @@ -343,8 +338,4 @@ }); } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandKeyboardTest, - Values(wl::ServerConfig{})); - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_output_unittest.cc b/ui/ozone/platform/wayland/host/wayland_output_unittest.cc index 2c6506b8..c5137ec 100644 --- a/ui/ozone/platform/wayland/host/wayland_output_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_output_unittest.cc
@@ -13,19 +13,11 @@ namespace ui { -// TODO(crbug.com/1365887): revert this to using WaylandOutputTest = WaylandTest -// once the default mode becomes asynchronous. -class WaylandOutputTest : public WaylandTest { - public: - WaylandOutputTest() : WaylandTest(TestServerMode::kAsync) {} - WaylandOutputTest(const WaylandOutputTest&) = delete; - WaylandOutputTest& operator=(const WaylandOutputTest&) = delete; - ~WaylandOutputTest() override = default; -}; +using WaylandOutputTest = WaylandTestSimple; // Tests that name and description fall back to ones in the WaylandOutput if // XDGOutput is not created. -TEST_P(WaylandOutputTest, NameAndDescriptionFallback) { +TEST_F(WaylandOutputTest, NameAndDescriptionFallback) { constexpr char kWlOutputName[] = "kWlOutputName"; constexpr char kWlOutputDescription[] = "kWlOutputDescription"; constexpr char kXDGOutputName[] = "kXDGOutputName"; @@ -55,8 +47,4 @@ EXPECT_EQ(wl_output->description(), kWlOutputDescription); } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandOutputTest, - Values(wl::ServerConfig{})); - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_pointer_unittest.cc b/ui/ozone/platform/wayland/host/wayland_pointer_unittest.cc index 9659930..183387717 100644 --- a/ui/ozone/platform/wayland/host/wayland_pointer_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_pointer_unittest.cc
@@ -37,15 +37,10 @@ namespace ui { -class WaylandPointerTest : public WaylandTest { +class WaylandPointerTest : public WaylandTestSimple { public: - WaylandPointerTest() : WaylandTest(TestServerMode::kAsync) {} - WaylandPointerTest(const WaylandPointerTest&) = delete; - WaylandPointerTest& operator=(const WaylandPointerTest&) = delete; - ~WaylandPointerTest() override = default; - void SetUp() override { - WaylandTest::SetUp(); + WaylandTestSimple::SetUp(); PostToServerAndWait([](wl::TestWaylandServerThread* server) { wl_seat_send_capabilities(server->seat()->resource(), @@ -172,7 +167,7 @@ *ptr = arg0->Clone(); } -TEST_P(WaylandPointerTest, Enter) { +TEST_F(WaylandPointerTest, Enter) { std::unique_ptr<Event> event; EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); @@ -187,7 +182,7 @@ EXPECT_EQ(gfx::PointF(0, 0), mouse_event->location_f()); } -TEST_P(WaylandPointerTest, Leave) { +TEST_F(WaylandPointerTest, Leave) { MockPlatformWindowDelegate other_delegate; gfx::AcceleratedWidget other_widget = gfx::kNullAcceleratedWidget; EXPECT_CALL(other_delegate, OnAcceleratedWidgetAvailable(_)) @@ -233,7 +228,7 @@ *ptr = arg0->Clone(); } -TEST_P(WaylandPointerTest, Motion) { +TEST_F(WaylandPointerTest, Motion) { SendEnter(); std::unique_ptr<Event> event; @@ -257,7 +252,7 @@ EXPECT_EQ(gfx::PointF(10.75, 20.375), mouse_event->root_location_f()); } -TEST_P(WaylandPointerTest, MotionDragged) { +TEST_F(WaylandPointerTest, MotionDragged) { SendEnter(); PostToServerAndWait([](wl::TestWaylandServerThread* server) { @@ -290,7 +285,7 @@ EXPECT_EQ(gfx::PointF(400, 500), mouse_event->root_location_f()); } -TEST_P(WaylandPointerTest, MotionDraggedWithStylus) { +TEST_F(WaylandPointerTest, MotionDraggedWithStylus) { SendEnter(); std::unique_ptr<Event> event; @@ -339,7 +334,7 @@ // Verifies whether the platform event source handles all types of axis sources. // The actual behaviour of each axis source is not tested here. -TEST_P(WaylandPointerTest, AxisSourceTypes) { +TEST_F(WaylandPointerTest, AxisSourceTypes) { SendEnter(); std::unique_ptr<Event> event1, event2, event3, event4; @@ -377,7 +372,7 @@ // to a pointer clicking event. // In practice, this might happen with specific compositors, eg Exo, when a // device wakes up from sleeping. -TEST_P(WaylandPointerTest, SpuriousAxisSourceAndStylusToolEvents) { +TEST_F(WaylandPointerTest, SpuriousAxisSourceAndStylusToolEvents) { SendEnter(); PostToServerAndWait([](wl::TestWaylandServerThread* server) { @@ -409,7 +404,7 @@ // Do not validate anything, this test only ensures that no crash occurred. } -TEST_P(WaylandPointerTest, Axis) { +TEST_F(WaylandPointerTest, Axis) { SendEnter(); for (uint32_t axis : @@ -446,7 +441,7 @@ } } -TEST_P(WaylandPointerTest, SetBitmap) { +TEST_F(WaylandPointerTest, SetBitmap) { SendEnter(); PostToServerAndWait([](wl::TestWaylandServerThread* server) { @@ -485,7 +480,7 @@ // Tests that bitmap is set on pointer focus and the pointer surface respects // provided scale of the surface image. -TEST_P(WaylandPointerTest, SetBitmapAndScaleOnPointerFocus) { +TEST_F(WaylandPointerTest, SetBitmapAndScaleOnPointerFocus) { for (int32_t scale = 1; scale < 5; scale++) { gfx::Size size = {10 * scale, 10 * scale}; SkBitmap dummy_cursor; @@ -551,7 +546,7 @@ } #if BUILDFLAG(IS_CHROMEOS_LACROS) -TEST_P(WaylandPointerTest, FlingVertical) { +TEST_F(WaylandPointerTest, FlingVertical) { SendEnter(50, 75); SendRightButtonPress(); @@ -602,7 +597,7 @@ EXPECT_GT(0.0f, scroll_event->y_offset_ordinal()); } -TEST_P(WaylandPointerTest, FlingHorizontal) { +TEST_F(WaylandPointerTest, FlingHorizontal) { SendEnter(50, 75); SendRightButtonPress(); @@ -653,7 +648,7 @@ EXPECT_GT(0.0f, scroll_event->x_offset_ordinal()); } -TEST_P(WaylandPointerTest, FlingCancel) { +TEST_F(WaylandPointerTest, FlingCancel) { SendEnter(50, 75); SendRightButtonPress(); @@ -722,7 +717,7 @@ EXPECT_EQ(0.0f, scroll_event->y_offset_ordinal()); } -TEST_P(WaylandPointerTest, FlingDiagonal) { +TEST_F(WaylandPointerTest, FlingDiagonal) { SendEnter(50, 75); SendRightButtonPress(); @@ -777,8 +772,4 @@ } #endif -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandPointerTest, - Values(wl::ServerConfig{})); - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc b/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc index 4bfbb77a5..504cdcb 100644 --- a/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc
@@ -92,19 +92,10 @@ } // namespace -class WaylandScreenTest : public WaylandTest { +class WaylandScreenTest : public WaylandTestSimple { public: - // TODO(crbug.com/1365887): TestServerMode::kAsync must be removed once all - // tests switch to asynchronous mode. - WaylandScreenTest() : WaylandTest(WaylandTest::TestServerMode::kAsync) {} - - WaylandScreenTest(const WaylandScreenTest&) = delete; - WaylandScreenTest& operator=(const WaylandScreenTest&) = delete; - - ~WaylandScreenTest() override = default; - void SetUp() override { - WaylandTest::SetUp(); + WaylandTestSimple::SetUp(); PostToServerAndWait([](wl::TestWaylandServerThread* server) { auto* output = server->output(); @@ -150,7 +141,7 @@ // Tests whether a primary output has been initialized before PlatformScreen is // created. -TEST_P(WaylandScreenTest, OutputBaseTest) { +TEST_F(WaylandScreenTest, OutputBaseTest) { // IsPrimaryOutputReady and PlatformScreen creation is done in the // initialization part of the tests. @@ -165,7 +156,7 @@ // In multi-monitor setup, the `entered_outputs_` list should be updated when // the display is unplugged or switched off. -TEST_P(WaylandScreenTest, EnteredOutputListAfterDisplayRemoval) { +TEST_F(WaylandScreenTest, EnteredOutputListAfterDisplayRemoval) { // These have to be stored on the client thread, but must be used only on the // server thread. wl::TestOutput* output1 = nullptr; @@ -275,7 +266,7 @@ EXPECT_EQ(2u, entered_outputs.size()); } -TEST_P(WaylandScreenTest, MultipleOutputsAddedAndRemoved) { +TEST_F(WaylandScreenTest, MultipleOutputsAddedAndRemoved) { // This has to be stored on the client thread, but must be used only on the // server thread. wl::TestOutput* output2 = nullptr; @@ -369,7 +360,7 @@ platform_screen_->RemoveObserver(&observer); } -TEST_P(WaylandScreenTest, OutputPropertyChangesMissingLogicalSize) { +TEST_F(WaylandScreenTest, OutputPropertyChangesMissingLogicalSize) { TestDisplayObserver observer; platform_screen_->AddObserver(&observer); @@ -404,7 +395,7 @@ platform_screen_->RemoveObserver(&observer); } -TEST_P(WaylandScreenTest, OutputPropertyChangesPrimaryDisplayChanged) { +TEST_F(WaylandScreenTest, OutputPropertyChangesPrimaryDisplayChanged) { TestDisplayObserver observer; platform_screen_->AddObserver(&observer); @@ -446,7 +437,7 @@ platform_screen_->RemoveObserver(&observer); } -TEST_P(WaylandScreenTest, GetAcceleratedWidgetAtScreenPoint) { +TEST_F(WaylandScreenTest, GetAcceleratedWidgetAtScreenPoint) { const uint32_t surface_id = window_->root_surface()->get_surface_id(); PostToServerAndWait([surface_id](wl::TestWaylandServerThread* server) { // Now, send enter event for the surface, which was created before. @@ -520,7 +511,7 @@ EXPECT_EQ(widget_at_screen_point, menu_window->GetWidget()); } -TEST_P(WaylandScreenTest, GetLocalProcessWidgetAtPoint) { +TEST_F(WaylandScreenTest, GetLocalProcessWidgetAtPoint) { gfx::Point point(10, 10); EXPECT_EQ(platform_screen_->GetLocalProcessWidgetAtPoint(point, {}), gfx::kNullAcceleratedWidget); @@ -538,7 +529,7 @@ gfx::kNullAcceleratedWidget); } -TEST_P(WaylandScreenTest, GetDisplayMatching) { +TEST_F(WaylandScreenTest, GetDisplayMatching) { TestDisplayObserver observer; platform_screen_->AddObserver(&observer); @@ -625,7 +616,7 @@ } // Regression test for https://crbug.com/1362872. -TEST_P(WaylandScreenTest, GetPrimaryDisplayAfterRemoval) { +TEST_F(WaylandScreenTest, GetPrimaryDisplayAfterRemoval) { TestDisplayObserver observer; platform_screen_->AddObserver(&observer); @@ -649,7 +640,7 @@ platform_screen_->RemoveObserver(&observer); } -TEST_P(WaylandScreenTest, GetDisplayForAcceleratedWidget) { +TEST_F(WaylandScreenTest, GetDisplayForAcceleratedWidget) { TestDisplayObserver observer; platform_screen_->AddObserver(&observer); @@ -732,7 +723,7 @@ }); } -TEST_P(WaylandScreenTest, GetCursorScreenPoint) { +TEST_F(WaylandScreenTest, GetCursorScreenPoint) { MockWaylandPlatformWindowDelegate delegate; std::unique_ptr<WaylandWindow> second_window = CreateWaylandWindowWithProperties(gfx::Rect(0, 0, 1920, 1080), @@ -928,7 +919,7 @@ // Checks that the surface that backs the window receives new scale of the // output that it is in. -TEST_P(WaylandScreenTest, SetWindowScale) { +TEST_F(WaylandScreenTest, SetWindowScale) { constexpr int32_t kTripleScale = 3; const uint32_t surface_id = window_->root_surface()->get_surface_id(); @@ -980,7 +971,7 @@ // which implies in its scale being set to the primary output's scale at its // initialization, any primary output scale update (or other properties that // lead to scale change) must be propagated to the window. -TEST_P(WaylandScreenTest, SetWindowScaleWithoutEnteredOutput) { +TEST_F(WaylandScreenTest, SetWindowScaleWithoutEnteredOutput) { // Test pre-conditions: single output setup whereas |output_| is the primary // output managed by |output_manager_|, with initial scale == 1. ASSERT_EQ(1u, output_manager_->GetAllOutputs().size()); @@ -1012,7 +1003,7 @@ // Checks that output transform is properly translated into Display orientation. // The first one is counter-clockwise, while the latter is clockwise. -TEST_P(WaylandScreenTest, Transform) { +TEST_F(WaylandScreenTest, Transform) { constexpr std::pair<wl_output_transform, display::Display::Rotation> kTestData[] = { {WL_OUTPUT_TRANSFORM_NORMAL, display::Display::ROTATE_0}, @@ -1041,30 +1032,21 @@ namespace { class LazilyConfiguredScreenTest - : public WaylandTest, + : public WaylandTestSimple, public wl::TestWaylandServerThread::OutputDelegate { public: - // TODO(crbug.com/1365887): TestServerMode::kAsync must be removed once all - // tests switch to asynchronous mode. - LazilyConfiguredScreenTest() - : WaylandTest(WaylandTest::TestServerMode::kAsync) {} - LazilyConfiguredScreenTest(const LazilyConfiguredScreenTest&) = delete; - LazilyConfiguredScreenTest& operator=(const LazilyConfiguredScreenTest&) = - delete; - ~LazilyConfiguredScreenTest() override = default; - void SetUp() override { // This can be set on the client thread as the server is not running yet. ASSERT_FALSE(server_.IsRunning()); server_.set_output_delegate(this); - WaylandTest::SetUp(); + WaylandTestSimple::SetUp(); output_manager_ = connection_->wayland_output_manager(); ASSERT_TRUE(output_manager_); } void TearDown() override { - WaylandTest::TearDown(); + WaylandTestSimple::TearDown(); PostToServerAndWait( [output = aux_output_](wl::TestWaylandServerThread* server) { @@ -1105,7 +1087,7 @@ // Ensures WaylandOutputManager and WaylandScreen properly handle scenarios // where multiple wl_output objects are announced but not "configured" (ie: // size, position, mode, etc sent to client) at bind time. -TEST_P(LazilyConfiguredScreenTest, DualOutput) { +TEST_F(LazilyConfiguredScreenTest, DualOutput) { // Ensure WaylandScreen got properly created and fed with a single display // object, ie: |aux_output_| at server side. EXPECT_TRUE(output_manager_->IsOutputReady()); @@ -1128,7 +1110,7 @@ using WaylandAuraShellScreenTest = WaylandScreenTest; -TEST_P(WaylandAuraShellScreenTest, OutputPropertyChanges) { +TEST_F(WaylandAuraShellScreenTest, OutputPropertyChanges) { TestDisplayObserver observer; platform_screen_->AddObserver(&observer); @@ -1221,7 +1203,7 @@ // in landscape orientation. Thus their physical bounds are in portrait // orientation along with an offset transform, which differs from the usual // landscape oriented bounds. -TEST_P(WaylandAuraShellScreenTest, +TEST_F(WaylandAuraShellScreenTest, OutputPropertyChangesWithPortraitPanelRotation) { TestDisplayObserver observer; platform_screen_->AddObserver(&observer); @@ -1308,16 +1290,4 @@ platform_screen_->RemoveObserver(&observer); } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandScreenTest, - Values(wl::ServerConfig{})); - -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandAuraShellScreenTest, - Values(wl::ServerConfig{})); - -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - LazilyConfiguredScreenTest, - Values(wl::ServerConfig{})); - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_surface_unittest.cc b/ui/ozone/platform/wayland/host/wayland_surface_unittest.cc index 9577ab0..2520339 100644 --- a/ui/ozone/platform/wayland/host/wayland_surface_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_surface_unittest.cc
@@ -15,19 +15,12 @@ #include "ui/ozone/platform/wayland/test/wayland_test.h" namespace ui { -namespace { using ::testing::ElementsAre; -class WaylandSurfaceTest : public WaylandTest { - public: - WaylandSurfaceTest() : WaylandTest(WaylandTest::TestServerMode::kAsync) {} - WaylandSurfaceTest(const WaylandSurfaceTest&) = delete; - WaylandSurfaceTest& operator=(const WaylandSurfaceTest&) = delete; - ~WaylandSurfaceTest() override = default; -}; +using WaylandSurfaceTest = WaylandTestSimple; -TEST_P(WaylandSurfaceTest, SurfaceReenterOutput) { +TEST_F(WaylandSurfaceTest, SurfaceReenterOutput) { WaylandSurface* wayland_surface = window_->root_surface(); EXPECT_TRUE(wayland_surface->entered_outputs().empty()); @@ -58,9 +51,4 @@ EXPECT_THAT(wayland_surface->entered_outputs(), ElementsAre(output_id)); } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandSurfaceTest, - ::testing::Values(wl::ServerConfig{})); - -} // namespace } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_touch_unittest.cc b/ui/ozone/platform/wayland/host/wayland_touch_unittest.cc index 83f175c..2dc92f0 100644 --- a/ui/ozone/platform/wayland/host/wayland_touch_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_touch_unittest.cc
@@ -46,15 +46,10 @@ } // namespace -class WaylandTouchTest : public WaylandTest { +class WaylandTouchTest : public WaylandTestSimple { public: - WaylandTouchTest() : WaylandTest(TestServerMode::kAsync) {} - WaylandTouchTest(const WaylandTouchTest&) = delete; - WaylandTouchTest& operator=(const WaylandTouchTest&) = delete; - ~WaylandTouchTest() override = default; - void SetUp() override { - WaylandTest::SetUp(); + WaylandTestSimple::SetUp(); PostToServerAndWait([](wl::TestWaylandServerThread* server) { wl_seat_send_capabilities( @@ -98,7 +93,7 @@ } }; -TEST_P(WaylandTouchTest, TouchPressAndMotion) { +TEST_F(WaylandTouchTest, TouchPressAndMotion) { std::unique_ptr<Event> event; EXPECT_CALL(delegate_, DispatchEvent(_)).WillRepeatedly(CloneEvent(&event)); @@ -138,7 +133,7 @@ } // Tests that touch events with stylus pen work. -TEST_P(WaylandTouchTest, TouchPressAndMotionWithStylus) { +TEST_F(WaylandTouchTest, TouchPressAndMotionWithStylus) { std::unique_ptr<Event> event; EXPECT_CALL(delegate_, DispatchEvent(_)).WillRepeatedly(CloneEvent(&event)); @@ -185,7 +180,7 @@ // Tests that touch events with stylus pen work. This variant of the test sends // the tool information after the touch down event, and ensures that // wl_touch::frame event handles it correctly. -TEST_P(WaylandTouchTest, TouchPressAndMotionWithStylus2) { +TEST_F(WaylandTouchTest, TouchPressAndMotionWithStylus2) { std::unique_ptr<Event> event; EXPECT_CALL(delegate_, DispatchEvent(_)).WillRepeatedly(CloneEvent(&event)); @@ -236,7 +231,7 @@ } // Tests that touch focus is correctly set and released. -TEST_P(WaylandTouchTest, CheckTouchFocus) { +TEST_F(WaylandTouchTest, CheckTouchFocus) { constexpr uint32_t touch_id1 = 1; constexpr uint32_t touch_id2 = 2; constexpr uint32_t touch_id3 = 3; @@ -365,7 +360,7 @@ // Verifies keyboard modifier flags are set in touch events while modifier keys // are pressed. Regression test for https://crbug.com/1298604. -TEST_P(WaylandTouchTest, KeyboardFlagsSet) { +TEST_F(WaylandTouchTest, KeyboardFlagsSet) { std::unique_ptr<Event> event; MaybeSetUpXkb(); @@ -468,8 +463,4 @@ EXPECT_FALSE(event->flags() & ui::EF_CONTROL_DOWN); } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandTouchTest, - Values(wl::ServerConfig{})); - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc index bdc1056..6b34826 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
@@ -153,7 +153,7 @@ // 1. With a single 1 window open, // 2. Move pointer into it, press left button, move cursor a bit (drag), // 3. Run move loop, drag it within the window bounds and drop. -TEST_P(WaylandWindowDragControllerTest, DragInsideWindowAndDrop) { +TEST_F(WaylandWindowDragControllerTest, DragInsideWindowAndDrop) { // Ensure there is no window currently focused EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(gfx::kNullAcceleratedWidget, @@ -244,7 +244,7 @@ // 1. With a single window open, // 2. Touch down and move the touch point a bit (drag), // 3. Run move loop, drag it within the window bounds and drop. -TEST_P(WaylandWindowDragControllerTest, DragInsideWindowAndDrop_TOUCH) { +TEST_F(WaylandWindowDragControllerTest, DragInsideWindowAndDrop_TOUCH) { ASSERT_TRUE(GetWmMoveLoopHandler(*window_)); ASSERT_TRUE(GetWaylandExtension(*window_)); @@ -333,7 +333,7 @@ // // NOTE: This bug isn't noticed on DUT, but seems to be frequent on ash/chrome // linux desktop builds (with ozone/x11 underneath). -TEST_P(WaylandWindowDragControllerTest, +TEST_F(WaylandWindowDragControllerTest, DragAndDropWithExtraneousPointerEnterEvent_TOUCH) { // Init and open |target_window|. PlatformWindowInitProperties properties{gfx::Rect{80, 80}}; @@ -384,7 +384,7 @@ // 4. Drag pointer to outside the window and release the mouse button, and make // sure RELEASE and EXIT mouse events are delivered even when the drop // happens outside the bounds of any surface. -TEST_P(WaylandWindowDragControllerTest, DragExitWindowAndDrop) { +TEST_F(WaylandWindowDragControllerTest, DragExitWindowAndDrop) { // Ensure there is no window currently focused EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(gfx::kNullAcceleratedWidget, @@ -480,7 +480,7 @@ // 5. Drag it a bit more (within window 2) and then calls EndMoveLoop(), // emulating a window snap), and then // 6. With the window in "snapped" state, drag it further and then drop. -TEST_P(WaylandWindowDragControllerTest, DragToOtherWindowSnapDragDrop) { +TEST_F(WaylandWindowDragControllerTest, DragToOtherWindowSnapDragDrop) { // Init and open |target_window|. PlatformWindowInitProperties properties{gfx::Rect{80, 80}}; properties.type = PlatformWindowType::kWindow; @@ -635,7 +635,7 @@ // 5. Drag it a bit more (within window 2) and then calls EndMoveLoop(), // emulating a window snap), and then // 6. With the window in "snapped" state, drag it further and then drop. -TEST_P(WaylandWindowDragControllerTest, DragToOtherWindowSnapDragDrop_TOUCH) { +TEST_F(WaylandWindowDragControllerTest, DragToOtherWindowSnapDragDrop_TOUCH) { // Init and open |target_window|. PlatformWindowInitProperties properties{gfx::Rect{80, 80}}; properties.type = PlatformWindowType::kWindow; @@ -760,7 +760,7 @@ // Verifies wl_data_device::leave events are properly handled and propagated // while in window dragging "attached" mode. -TEST_P(WaylandWindowDragControllerTest, DragExitAttached) { +TEST_F(WaylandWindowDragControllerTest, DragExitAttached) { // Ensure there is no window currently focused EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(gfx::kNullAcceleratedWidget, @@ -804,7 +804,7 @@ // Verifies wl_data_device::leave events are properly handled and propagated // while in window dragging "attached" mode. -TEST_P(WaylandWindowDragControllerTest, DragExitAttached_TOUCH) { +TEST_F(WaylandWindowDragControllerTest, DragExitAttached_TOUCH) { // Ensure there is no window currently focused EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(gfx::kNullAcceleratedWidget, @@ -839,7 +839,7 @@ using BoundsChange = PlatformWindowDelegate::BoundsChange; -TEST_P(WaylandWindowDragControllerTest, RestoreDuringWindowDragSession) { +TEST_F(WaylandWindowDragControllerTest, RestoreDuringWindowDragSession) { const gfx::Rect original_bounds = window_->GetBoundsInDIP(); wl::ScopedWlArray states({XDG_TOPLEVEL_STATE_ACTIVATED}); @@ -885,7 +885,7 @@ // // Verifies window drag controller is resistant to issues such as // https://crbug.com/1148021. -TEST_P(WaylandWindowDragControllerTest, IgnorePointerEventsUntilDrop) { +TEST_F(WaylandWindowDragControllerTest, IgnorePointerEventsUntilDrop) { // Ensure there is no window currently focused EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(gfx::kNullAcceleratedWidget, @@ -1018,7 +1018,7 @@ } // Regression test for https://crbug.com/1169446. -TEST_P(WaylandWindowDragControllerTest, MotionEventsSkippedWhileReattaching) { +TEST_F(WaylandWindowDragControllerTest, MotionEventsSkippedWhileReattaching) { auto* dragged_window = window_.get(); EXPECT_TRUE(dragged_window); @@ -1084,7 +1084,7 @@ // Test that cursor position is using DIP coordinates and is updated correctly // on DragMotion event. -TEST_P(WaylandWindowDragControllerTest, CursorPositionIsUpdatedOnMotion) { +TEST_F(WaylandWindowDragControllerTest, CursorPositionIsUpdatedOnMotion) { const gfx::Rect output_bounds(0, 0, 1920, 1080); PostToServerAndWait([output_bounds](wl::TestWaylandServerThread* server) { // Configure the first output with scale 1. @@ -1202,7 +1202,7 @@ // after quitting the move loop. Regression test for crbug.com/1267791 and // should be caught in both regular and ASAN builds, where more details about // the actual memory issue is provided. -TEST_P(WaylandWindowDragControllerTest, +TEST_F(WaylandWindowDragControllerTest, HandleDraggedWindowDestructionAfterMoveLoop) { // 1. Ensure there is no window currently focused EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); @@ -1247,7 +1247,7 @@ // Ensure no memory issues happen when the dragged and/or events grabber windows // get destroyed while the move loop is running. -TEST_P(WaylandWindowDragControllerTest, +TEST_F(WaylandWindowDragControllerTest, HandleWindowsDestructionDuringMoveLoop) { // 1. Send some initial pointer events to |window_|. ASSERT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); @@ -1332,7 +1332,7 @@ // Wayland Compositor. // // Regression test for https://crbug.com/1366504. -TEST_P(WaylandWindowDragControllerTest, ExtendedDragUnavailable) { +TEST_F(WaylandWindowDragControllerTest, ExtendedDragUnavailable) { ASSERT_TRUE(GetWmMoveLoopHandler(*window_)); ASSERT_TRUE(GetWaylandExtension(*window_)); drag_controller()->set_extended_drag_available_for_testing(false); @@ -1391,8 +1391,4 @@ window_manager()->GetCurrentPointerOrTouchFocusedWindow()); } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandWindowDragControllerTest, - Values(wl::ServerConfig{})); - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc b/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc index 96c044df..6fdd811 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc
@@ -22,40 +22,21 @@ } // namespace -class WaylandWindowManagerTest : public WaylandTest { +class WaylandWindowManagerTest : public WaylandTestSimple { public: - WaylandWindowManagerTest() : WaylandTest(TestServerMode::kAsync) {} - WaylandWindowManagerTest(const WaylandWindowManagerTest&) = delete; - WaylandWindowManagerTest& operator=(const WaylandWindowManagerTest&) = delete; - ~WaylandWindowManagerTest() override = default; - void SetUp() override { - WaylandTest::SetUp(); + WaylandTestSimple::SetUp(); manager_ = connection_->wayland_window_manager(); ASSERT_TRUE(manager_); } protected: - std::unique_ptr<WaylandWindow> CreateWaylandWindowWithParams( - PlatformWindowType type, - const gfx::Rect bounds, - MockPlatformWindowDelegate* delegate) { - PlatformWindowInitProperties properties; - properties.bounds = bounds; - properties.type = type; - auto window = WaylandWindow::Create(delegate, connection_.get(), - std::move(properties)); - if (window) - window->Show(false); - return window; - } - raw_ptr<WaylandWindowManager> manager_ = nullptr; }; -TEST_P(WaylandWindowManagerTest, GetWindow) { - MockPlatformWindowDelegate delegate; +TEST_F(WaylandWindowManagerTest, GetWindow) { + MockWaylandPlatformWindowDelegate delegate; auto window1 = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, kDefaultBounds, &delegate); @@ -72,8 +53,8 @@ EXPECT_FALSE(manager_->GetWindow(window1_widget)); } -TEST_P(WaylandWindowManagerTest, GetWindowWithLargestBounds) { - MockPlatformWindowDelegate delegate; +TEST_F(WaylandWindowManagerTest, GetWindowWithLargestBounds) { + MockWaylandPlatformWindowDelegate delegate; auto window1 = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, kDefaultBounds, &delegate); @@ -85,8 +66,8 @@ EXPECT_TRUE(window2.get() == manager_->GetWindowWithLargestBounds()); } -TEST_P(WaylandWindowManagerTest, GetCurrentFocusedWindow) { - MockPlatformWindowDelegate delegate; +TEST_F(WaylandWindowManagerTest, GetCurrentFocusedWindow) { + MockWaylandPlatformWindowDelegate delegate; PostToServerAndWait([](wl::TestWaylandServerThread* server) { wl_seat_send_capabilities(server->seat()->resource(), @@ -136,8 +117,8 @@ EXPECT_FALSE(manager_->GetCurrentPointerFocusedWindow()); } -TEST_P(WaylandWindowManagerTest, GetCurrentKeyboardFocusedWindow) { - MockPlatformWindowDelegate delegate; +TEST_F(WaylandWindowManagerTest, GetCurrentKeyboardFocusedWindow) { + MockWaylandPlatformWindowDelegate delegate; PostToServerAndWait([](wl::TestWaylandServerThread* server) { wl_seat_send_capabilities(server->seat()->resource(), @@ -181,8 +162,8 @@ EXPECT_FALSE(manager_->GetCurrentKeyboardFocusedWindow()); } -TEST_P(WaylandWindowManagerTest, GetAllWindows) { - MockPlatformWindowDelegate delegate; +TEST_F(WaylandWindowManagerTest, GetAllWindows) { + MockWaylandPlatformWindowDelegate delegate; // There is a default window created by WaylandTest. auto windows = manager_->GetAllWindows(); @@ -200,8 +181,4 @@ EXPECT_EQ(2u, windows.size()); } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandWindowManagerTest, - Values(wl::ServerConfig{})); - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc index e86931e..e6f4fcf1 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
@@ -151,11 +151,10 @@ } // namespace -class WaylandWindowTest : public WaylandTest { +class WaylandWindowTest : public WaylandTestSimple { public: WaylandWindowTest() - : WaylandTest(WaylandTest::TestServerMode::kAsync), - test_mouse_event_(ET_MOUSE_PRESSED, + : test_mouse_event_(ET_MOUSE_PRESSED, gfx::Point(10, 15), gfx::Point(10, 15), ui::EventTimeStampFromSeconds(123456), @@ -164,9 +163,10 @@ WaylandWindowTest(const WaylandWindowTest&) = delete; WaylandWindowTest& operator=(const WaylandWindowTest&) = delete; + ~WaylandWindowTest() override = default; void SetUp() override { - WaylandTest::SetUp(); + WaylandTestSimple::SetUp(); surface_id_ = window_->root_surface()->get_surface_id(); PostToServerAndWait( @@ -189,25 +189,6 @@ }); } - std::unique_ptr<WaylandWindow> CreateWaylandWindowWithParams( - PlatformWindowType type, - gfx::AcceleratedWidget parent_widget, - const gfx::Rect& bounds, - MockWaylandPlatformWindowDelegate* delegate) { - PlatformWindowInitProperties properties; - // TODO(msisov): use a fancy method to calculate position of a popup window. - properties.bounds = bounds; - properties.type = type; - properties.parent_widget = parent_widget; - - auto window = delegate->CreateWaylandWindow( - connection_.get(), std::move(properties), true, true); - - if (window) - window->Show(false); - return window; - } - void InitializeWithSupportedHitTestValues(std::vector<int>* hit_tests) { hit_tests->push_back(static_cast<int>(HTBOTTOM)); hit_tests->push_back(static_cast<int>(HTBOTTOMLEFT)); @@ -329,7 +310,7 @@ MouseEvent test_mouse_event_; }; -TEST_P(WaylandWindowTest, SetTitle) { +TEST_F(WaylandWindowTest, SetTitle) { window_->SetTitle(u"hello"); PostToServerAndWait([id = surface_id_](wl::TestWaylandServerThread* server) { auto* surface = server->GetObject<wl::MockSurface>(id); @@ -338,7 +319,7 @@ }); } -TEST_P(WaylandWindowTest, UpdateVisualSizeConfiguresWaylandWindow) { +TEST_F(WaylandWindowTest, UpdateVisualSizeConfiguresWaylandWindow) { constexpr gfx::Rect kNormalBounds{500, 300}; window_->set_update_visual_size_immediately_for_testing(false); @@ -378,7 +359,7 @@ // WaylandSurface state changes are sent to wayland compositor when // ApplyPendingState() is called. -TEST_P(WaylandWindowTest, ApplyPendingStatesAndCommit) { +TEST_F(WaylandWindowTest, ApplyPendingStatesAndCommit) { window_->set_update_visual_size_immediately_for_testing(false); window_->set_apply_pending_state_on_update_visual_size_for_testing(false); @@ -416,7 +397,7 @@ // Checks that decoration insets do not change final bounds and that // WaylandToplevelWindow::HandleToplevelConfigure does correct rounding when // some sides of insets divides by 2 with remainder. -TEST_P(WaylandWindowTest, SetDecorationInsets) { +TEST_F(WaylandWindowTest, SetDecorationInsets) { constexpr gfx::Rect kNormalBounds{956, 556}; constexpr auto kHiDpiScale = 2; const gfx::Size kHiDpiSize = @@ -519,7 +500,7 @@ // Checks that when the window gets some of its edges tiled, it notifies the // delegate appropriately. -TEST_P(WaylandWindowTest, HandleTiledEdges) { +TEST_F(WaylandWindowTest, HandleTiledEdges) { constexpr gfx::Rect kWindowBounds{800, 600}; struct { @@ -559,7 +540,7 @@ } } -TEST_P(WaylandWindowTest, DisregardUnpassedWindowConfigure) { +TEST_F(WaylandWindowTest, DisregardUnpassedWindowConfigure) { constexpr gfx::Rect kNormalBounds1{500, 300}; constexpr gfx::Rect kNormalBounds2{800, 600}; constexpr gfx::Rect kNormalBounds3{700, 400}; @@ -599,7 +580,7 @@ window_->UpdateVisualSize(kNormalBounds3.size()); } -TEST_P(WaylandWindowTest, MismatchUpdateVisualSize) { +TEST_F(WaylandWindowTest, MismatchUpdateVisualSize) { constexpr gfx::Rect kNormalBounds1{500, 300}; constexpr gfx::Rect kNormalBounds2{800, 600}; constexpr gfx::Rect kNormalBounds3{700, 400}; @@ -629,7 +610,7 @@ window_->UpdateVisualSize({100, 100}); } -TEST_P(WaylandWindowTest, UpdateVisualSizeClearsPreviousUnackedConfigures) { +TEST_F(WaylandWindowTest, UpdateVisualSizeClearsPreviousUnackedConfigures) { constexpr gfx::Rect kNormalBounds1{500, 300}; constexpr gfx::Rect kNormalBounds2{800, 600}; constexpr gfx::Rect kNormalBounds3{700, 400}; @@ -680,7 +661,7 @@ window_->UpdateVisualSize(kNormalBounds3.size()); } -TEST_P(WaylandWindowTest, MaximizeAndRestore) { +TEST_F(WaylandWindowTest, MaximizeAndRestore) { constexpr gfx::Rect kNormalBounds{500, 300}; constexpr gfx::Rect kMaximizedBounds{800, 600}; @@ -777,7 +758,7 @@ #if BUILDFLAG(IS_CHROMEOS_LACROS) // Tests the event sequence where a minimize request is initiated by the client. -TEST_P(WaylandWindowTest, ClientInitiatedMinimize) { +TEST_F(WaylandWindowTest, ClientInitiatedMinimize) { wl::ScopedWlArray states({}); // Make sure the window is initialized to normal state from the beginning. @@ -805,7 +786,7 @@ // Tests the event sequence where a minimize event is initiated by the server // and the client's window is in a non-minimized state. -TEST_P(WaylandWindowTest, ServerInitiatedMinimize) { +TEST_F(WaylandWindowTest, ServerInitiatedMinimize) { wl::ScopedWlArray states({}); // Make sure the window is initialized to normal state from the beginning. @@ -823,7 +804,7 @@ #else -TEST_P(WaylandWindowTest, Minimize) { +TEST_F(WaylandWindowTest, Minimize) { wl::ScopedWlArray states({}); // Make sure the window is initialized to normal state from the beginning. @@ -868,7 +849,7 @@ #endif // BUILDFLAG(IS_CHROMEOS_LACROS) -TEST_P(WaylandWindowTest, SetFullscreenAndRestore) { +TEST_F(WaylandWindowTest, SetFullscreenAndRestore) { // Make sure the window is initialized to normal state from the beginning. EXPECT_EQ(PlatformWindowState::kNormal, window_->GetPlatformWindowState()); @@ -907,7 +888,7 @@ EXPECT_EQ(window_->GetPlatformWindowState(), PlatformWindowState::kNormal); } -TEST_P(WaylandWindowTest, StartWithFullscreen) { +TEST_F(WaylandWindowTest, StartWithFullscreen) { MockWaylandPlatformWindowDelegate delegate; PlatformWindowInitProperties properties; properties.bounds = gfx::Rect(100, 100); @@ -965,7 +946,7 @@ Mock::VerifyAndClearExpectations(&delegate); } -TEST_P(WaylandWindowTest, StartMaximized) { +TEST_F(WaylandWindowTest, StartMaximized) { MockWaylandPlatformWindowDelegate delegate; PlatformWindowInitProperties properties; properties.bounds = gfx::Rect(100, 100); @@ -1026,7 +1007,7 @@ Mock::VerifyAndClearExpectations(&delegate); } -TEST_P(WaylandWindowTest, CompositorSideStateChanges) { +TEST_F(WaylandWindowTest, CompositorSideStateChanges) { // Real insets used by default on HiDPI. const auto kInsets = gfx::Insets::TLBR(38, 44, 55, 44); const auto kNormalBounds = window_->GetBoundsInDIP(); @@ -1150,7 +1131,7 @@ SendConfigureEvent(surface_id_, {0, 0}, states); } -TEST_P(WaylandWindowTest, SetMaximizedFullscreenAndRestore) { +TEST_F(WaylandWindowTest, SetMaximizedFullscreenAndRestore) { constexpr gfx::Rect kNormalBounds{500, 300}; constexpr gfx::Rect kMaximizedBounds{800, 600}; @@ -1224,7 +1205,7 @@ EXPECT_EQ(PlatformWindowState::kNormal, window_->GetPlatformWindowState()); } -TEST_P(WaylandWindowTest, RestoreBoundsAfterMaximize) { +TEST_F(WaylandWindowTest, RestoreBoundsAfterMaximize) { const gfx::Rect current_bounds = window_->GetBoundsInDIP(); wl::ScopedWlArray states = InitializeWlArrayWithActivatedState(); @@ -1263,7 +1244,7 @@ EXPECT_EQ(restored_bounds, gfx::Rect()); } -TEST_P(WaylandWindowTest, RestoreBoundsAfterFullscreen) { +TEST_F(WaylandWindowTest, RestoreBoundsAfterFullscreen) { const gfx::Rect current_bounds = window_->GetBoundsInDIP(); wl::ScopedWlArray states = InitializeWlArrayWithActivatedState(); @@ -1303,7 +1284,7 @@ EXPECT_EQ(restored_bounds, gfx::Rect()); } -TEST_P(WaylandWindowTest, RestoreBoundsAfterMaximizeAndFullscreen) { +TEST_F(WaylandWindowTest, RestoreBoundsAfterMaximizeAndFullscreen) { const gfx::Rect current_bounds = window_->GetBoundsInDIP(); wl::ScopedWlArray states = InitializeWlArrayWithActivatedState(); @@ -1359,7 +1340,7 @@ EXPECT_EQ(restored_bounds, gfx::Rect()); } -TEST_P(WaylandWindowTest, SendsBoundsOnRequest) { +TEST_F(WaylandWindowTest, SendsBoundsOnRequest) { const gfx::Rect initial_bounds = window_->GetBoundsInDIP(); const gfx::Rect new_bounds = @@ -1395,7 +1376,7 @@ EXPECT_EQ(restored_bounds, gfx::Rect()); } -TEST_P(WaylandWindowTest, UpdateWindowRegion) { +TEST_F(WaylandWindowTest, UpdateWindowRegion) { // Change bounds. const gfx::Rect initial_bounds = window_->GetBoundsInDIP(); const gfx::Rect new_bounds = @@ -1460,7 +1441,7 @@ }); } -TEST_P(WaylandWindowTest, CanDispatchMouseEventFocus) { +TEST_F(WaylandWindowTest, CanDispatchMouseEventFocus) { // SetPointerFocusedWindow requires a WaylandPointer. PostToServerAndWait([](wl::TestWaylandServerThread* server) { wl_seat_send_capabilities(server->seat()->resource(), @@ -1472,7 +1453,7 @@ EXPECT_TRUE(window_->CanDispatchEvent(&test_mouse_event_)); } -TEST_P(WaylandWindowTest, SetCursorUsesZcrCursorShapesForCommonTypes) { +TEST_F(WaylandWindowTest, SetCursorUsesZcrCursorShapesForCommonTypes) { MockZcrCursorShapes* mock_cursor_shapes = InstallMockZcrCursorShapes(); // Verify some commonly-used cursors. @@ -1495,7 +1476,7 @@ window_->SetCursor(ibeam_cursor.get()); } -TEST_P(WaylandWindowTest, SetCursorCallsZcrCursorShapesOncePerCursor) { +TEST_F(WaylandWindowTest, SetCursorCallsZcrCursorShapesOncePerCursor) { MockZcrCursorShapes* mock_cursor_shapes = InstallMockZcrCursorShapes(); auto hand_cursor = base::MakeRefCounted<BitmapCursor>( mojom::CursorType::kHand, kDefaultCursorScale); @@ -1505,7 +1486,7 @@ window_->SetCursor(hand_cursor.get()); } -TEST_P(WaylandWindowTest, SetCursorDoesNotUseZcrCursorShapesForNoneCursor) { +TEST_F(WaylandWindowTest, SetCursorDoesNotUseZcrCursorShapesForNoneCursor) { MockZcrCursorShapes* mock_cursor_shapes = InstallMockZcrCursorShapes(); EXPECT_CALL(*mock_cursor_shapes, SetCursorShape(_)).Times(0); auto none_cursor = base::MakeRefCounted<BitmapCursor>( @@ -1513,7 +1494,7 @@ window_->SetCursor(none_cursor.get()); } -TEST_P(WaylandWindowTest, SetCursorDoesNotUseZcrCursorShapesForCustomCursors) { +TEST_F(WaylandWindowTest, SetCursorDoesNotUseZcrCursorShapesForCustomCursors) { MockZcrCursorShapes* mock_cursor_shapes = InstallMockZcrCursorShapes(); // Custom cursors require bitmaps, so they do not use server-side cursors. @@ -1528,7 +1509,7 @@ *ptr = arg0->Clone(); } -TEST_P(WaylandWindowTest, DispatchEvent) { +TEST_F(WaylandWindowTest, DispatchEvent) { std::unique_ptr<Event> event; EXPECT_CALL(delegate_, DispatchEvent(_)).WillOnce(CloneEvent(&event)); window_->DispatchEvent(&test_mouse_event_); @@ -1544,7 +1525,7 @@ test_mouse_event_.changed_button_flags()); } -TEST_P(WaylandWindowTest, ConfigureEvent) { +TEST_F(WaylandWindowTest, ConfigureEvent) { wl::ScopedWlArray states({}); // The surface must react on each configure event and send bounds to its @@ -1582,7 +1563,7 @@ SendConfigureEvent(surface_id_, kNewSize, states, ++serial); } -TEST_P(WaylandWindowTest, ConfigureEventWithNulledSize) { +TEST_F(WaylandWindowTest, ConfigureEventWithNulledSize) { wl::ScopedWlArray states({}); // |xdg_surface| must receive the following calls in both xdg_shell_v5 and @@ -1602,7 +1583,7 @@ SendConfigureEvent(surface_id_, {0, 0}, states, 14u); } -TEST_P(WaylandWindowTest, OnActivationChanged) { +TEST_F(WaylandWindowTest, OnActivationChanged) { uint32_t serial = 0; // Deactivate the surface. @@ -1620,11 +1601,11 @@ SendConfigureEvent(surface_id_, {0, 0}, states, ++serial); } -TEST_P(WaylandWindowTest, OnAcceleratedWidgetDestroy) { +TEST_F(WaylandWindowTest, OnAcceleratedWidgetDestroy) { window_.reset(); } -TEST_P(WaylandWindowTest, CanCreateMenuWindow) { +TEST_F(WaylandWindowTest, CanCreateMenuWindow) { MockWaylandPlatformWindowDelegate menu_window_delegate; EXPECT_CALL(menu_window_delegate, GetMenuType()) .WillRepeatedly(Return(MenuType::kRootContextMenu)); @@ -1640,8 +1621,7 @@ SetPointerFocusedWindow(window_.get()); std::unique_ptr<WaylandWindow> menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, gfx::kNullAcceleratedWidget, gfx::Rect(10, 10), - &menu_window_delegate); + PlatformWindowType::kMenu, gfx::Rect(10, 10), &menu_window_delegate); EXPECT_TRUE(menu_window); SetPointerFocusedWindow(window_.get()); @@ -1650,19 +1630,17 @@ // Given that there is no parent passed and we don't have any focused windows, // Wayland must still create a window. menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, gfx::kNullAcceleratedWidget, gfx::Rect(10, 10), - &menu_window_delegate); + PlatformWindowType::kMenu, gfx::Rect(10, 10), &menu_window_delegate); EXPECT_TRUE(menu_window); window_->set_touch_focus(true); menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, gfx::kNullAcceleratedWidget, gfx::Rect(10, 10), - &menu_window_delegate); + PlatformWindowType::kMenu, gfx::Rect(10, 10), &menu_window_delegate); EXPECT_TRUE(menu_window); } -TEST_P(WaylandWindowTest, CreateAndDestroyNestedMenuWindow) { +TEST_F(WaylandWindowTest, CreateAndDestroyNestedMenuWindow) { MockWaylandPlatformWindowDelegate menu_window_delegate; gfx::AcceleratedWidget menu_window_widget; EXPECT_CALL(menu_window_delegate, OnAcceleratedWidgetAvailable(_)) @@ -1670,27 +1648,27 @@ EXPECT_CALL(menu_window_delegate, GetMenuType()) .WillRepeatedly(Return(MenuType::kRootContextMenu)); - std::unique_ptr<WaylandWindow> menu_window = - CreateWaylandWindowWithParams(PlatformWindowType::kMenu, widget_, - gfx::Rect(10, 10), &menu_window_delegate); + std::unique_ptr<WaylandWindow> menu_window = CreateWaylandWindowWithParams( + PlatformWindowType::kMenu, gfx::Rect(10, 10), &menu_window_delegate, + widget_); EXPECT_TRUE(menu_window); ASSERT_NE(menu_window_widget, gfx::kNullAcceleratedWidget); MockWaylandPlatformWindowDelegate nested_menu_window_delegate; std::unique_ptr<WaylandWindow> nested_menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, menu_window_widget, - gfx::Rect(20, 0, 10, 10), &nested_menu_window_delegate); + PlatformWindowType::kMenu, gfx::Rect(20, 0, 10, 10), + &nested_menu_window_delegate, menu_window_widget); EXPECT_TRUE(nested_menu_window); } -TEST_P(WaylandWindowTest, DispatchesLocatedEventsToCapturedWindow) { +TEST_F(WaylandWindowTest, DispatchesLocatedEventsToCapturedWindow) { MockWaylandPlatformWindowDelegate menu_window_delegate; EXPECT_CALL(menu_window_delegate, GetMenuType()) .WillOnce(Return(MenuType::kRootContextMenu)); std::unique_ptr<WaylandWindow> menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, widget_, gfx::Rect(10, 10, 10, 10), - &menu_window_delegate); + PlatformWindowType::kMenu, gfx::Rect(10, 10, 10, 10), + &menu_window_delegate, widget_); EXPECT_TRUE(menu_window); PostToServerAndWait([](wl::TestWaylandServerThread* server) { @@ -1766,8 +1744,8 @@ .WillOnce(Return(MenuType::kRootContextMenu)); std::unique_ptr<WaylandWindow> nested_menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, menu_window->GetWidget(), - gfx::Rect(15, 18, 10, 10), &nested_menu_window_delegate); + PlatformWindowType::kMenu, gfx::Rect(15, 18, 10, 10), + &nested_menu_window_delegate, menu_window->GetWidget()); EXPECT_TRUE(nested_menu_window); SetPointerFocusedWindow(nested_menu_window.get()); @@ -1802,7 +1780,7 @@ // Verify that located events are translated correctly when the windows have // geometry with non-zero offset. // See https://crbug.com/1292486. -TEST_P(WaylandWindowTest, ConvertEventToTarget) { +TEST_F(WaylandWindowTest, ConvertEventToTarget) { // This first section repeats a part of SetDecorationInsets that sets // decoration insets and ensures that they have been applied. constexpr gfx::Rect kMainWindowBounds{956, 556}; @@ -1831,7 +1809,7 @@ EXPECT_CALL(menu_window_delegate, GetMenuType()) .WillOnce(Return(MenuType::kRootContextMenu)); std::unique_ptr<WaylandWindow> menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, widget_, kMenuBounds, &menu_window_delegate); + PlatformWindowType::kMenu, kMenuBounds, &menu_window_delegate, widget_); EXPECT_TRUE(menu_window); // Now translate the event located at (0, 0) in the parent window into the @@ -1854,22 +1832,22 @@ // Tests that the event grabber gets the events processed by its toplevel parent // window iff they belong to the same "family". Otherwise, events mustn't be // rerouted from another toplevel window to the event grabber. -TEST_P(WaylandWindowTest, +TEST_F(WaylandWindowTest, DispatchesLocatedEventsToCapturedWindowInTheSameStack) { MockWaylandPlatformWindowDelegate menu_window_delegate; EXPECT_CALL(menu_window_delegate, GetMenuType()) .WillOnce(Return(MenuType::kRootContextMenu)); std::unique_ptr<WaylandWindow> menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, widget_, gfx::Rect(30, 40, 20, 50), - &menu_window_delegate); + PlatformWindowType::kMenu, gfx::Rect(30, 40, 20, 50), + &menu_window_delegate, widget_); EXPECT_TRUE(menu_window); // Second toplevel window has the same bounds as the |window_|. MockWaylandPlatformWindowDelegate toplevel_window2_delegate; std::unique_ptr<WaylandWindow> toplevel_window2 = - CreateWaylandWindowWithParams( - PlatformWindowType::kWindow, gfx::kNullAcceleratedWidget, - window_->GetBoundsInDIP(), &toplevel_window2_delegate); + CreateWaylandWindowWithParams(PlatformWindowType::kWindow, + window_->GetBoundsInDIP(), + &toplevel_window2_delegate); EXPECT_TRUE(toplevel_window2); PostToServerAndWait([](wl::TestWaylandServerThread* server) { @@ -1930,13 +1908,13 @@ EXPECT_EQ(event->AsLocatedEvent()->location(), gfx::Point(10, 20)); } -TEST_P(WaylandWindowTest, DispatchesKeyboardEventToToplevelWindow) { +TEST_F(WaylandWindowTest, DispatchesKeyboardEventToToplevelWindow) { MockWaylandPlatformWindowDelegate menu_window_delegate; EXPECT_CALL(menu_window_delegate, GetMenuType()) .WillOnce(Return(MenuType::kRootContextMenu)); std::unique_ptr<WaylandWindow> menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, widget_, gfx::Rect(10, 10, 10, 10), - &menu_window_delegate); + PlatformWindowType::kMenu, gfx::Rect(10, 10, 10, 10), + &menu_window_delegate, widget_); EXPECT_TRUE(menu_window); PostToServerAndWait([](wl::TestWaylandServerThread* server) { @@ -2001,7 +1979,7 @@ // Tests that event is processed by the surface that has the focus. More // extensive tests are located in wayland touch/keyboard/pointer unittests. -TEST_P(WaylandWindowTest, CanDispatchEvent) { +TEST_F(WaylandWindowTest, CanDispatchEvent) { MockWaylandPlatformWindowDelegate menu_window_delegate; gfx::AcceleratedWidget menu_window_widget; EXPECT_CALL(menu_window_delegate, OnAcceleratedWidgetAvailable(_)) @@ -2009,9 +1987,9 @@ EXPECT_CALL(menu_window_delegate, GetMenuType()) .WillOnce(Return(MenuType::kRootContextMenu)); - std::unique_ptr<WaylandWindow> menu_window = - CreateWaylandWindowWithParams(PlatformWindowType::kMenu, widget_, - gfx::Rect(10, 10), &menu_window_delegate); + std::unique_ptr<WaylandWindow> menu_window = CreateWaylandWindowWithParams( + PlatformWindowType::kMenu, gfx::Rect(10, 10), &menu_window_delegate, + widget_); EXPECT_TRUE(menu_window); MockWaylandPlatformWindowDelegate nested_menu_window_delegate; @@ -2019,8 +1997,8 @@ .WillOnce(Return(MenuType::kRootContextMenu)); std::unique_ptr<WaylandWindow> nested_menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, menu_window_widget, - gfx::Rect(20, 0, 10, 10), &nested_menu_window_delegate); + PlatformWindowType::kMenu, gfx::Rect(20, 0, 10, 10), + &nested_menu_window_delegate, menu_window_widget); EXPECT_TRUE(nested_menu_window); PostToServerAndWait([](wl::TestWaylandServerThread* server) { @@ -2140,7 +2118,7 @@ {}, {window_.get(), menu_window.get(), nested_menu_window.get()}); } -TEST_P(WaylandWindowTest, DispatchWindowMove) { +TEST_F(WaylandWindowTest, DispatchWindowMove) { PostToServerAndWait([](wl::TestWaylandServerThread* server) { wl_seat_send_capabilities(server->seat()->resource(), WL_SEAT_CAPABILITY_POINTER); @@ -2168,7 +2146,7 @@ } // Makes sure hit tests are converted into right edges. -TEST_P(WaylandWindowTest, DispatchWindowResize) { +TEST_F(WaylandWindowTest, DispatchWindowResize) { std::vector<int> hit_test_values; InitializeWithSupportedHitTestValues(&hit_test_values); @@ -2206,7 +2184,7 @@ } } -TEST_P(WaylandWindowTest, ToplevelWindowUpdateWindowScale) { +TEST_F(WaylandWindowTest, ToplevelWindowUpdateWindowScale) { VerifyAndClearExpectations(); // Surface scale must be 1 when no output has been entered by the window. @@ -2268,7 +2246,7 @@ EXPECT_EQ(gfx::Rect(800, 600), window_->GetBoundsInDIP()); } -TEST_P(WaylandWindowTest, WaylandPopupSurfaceScale) { +TEST_F(WaylandWindowTest, WaylandPopupSurfaceScale) { VerifyAndClearExpectations(); PostToServerAndWait([](wl::TestWaylandServerThread* server) { @@ -2307,7 +2285,7 @@ SetPointerFocusedWindow(window_.get()); gfx::Rect wayland_popup_bounds(15, 15, 10, 10); auto wayland_popup = CreateWaylandWindowWithParams( - type, window_->GetWidget(), wayland_popup_bounds, &delegate_); + type, wayland_popup_bounds, &delegate_, window_->GetWidget()); EXPECT_TRUE(wayland_popup); wayland_popup->Show(false); @@ -2359,7 +2337,7 @@ // PlatformWindowProperties using buffer scale it's going to use that the client // is not able to determine before PlatformWindow is created. See // WaylandPopup::OnInitialize for more details. -TEST_P(WaylandWindowTest, WaylandPopupInitialBufferScale) { +TEST_F(WaylandWindowTest, WaylandPopupInitialBufferScale) { VerifyAndClearExpectations(); PostToServerAndWait([](wl::TestWaylandServerThread* server) { @@ -2431,9 +2409,8 @@ gfx::Rect wayland_popup_bounds = transform.MapRect(bounds_dip); std::unique_ptr<WaylandWindow> wayland_popup = - CreateWaylandWindowWithParams(PlatformWindowType::kMenu, - window_->GetWidget(), bounds_dip, - &delegate_); + CreateWaylandWindowWithParams(PlatformWindowType::kMenu, bounds_dip, + &delegate_, window_->GetWidget()); EXPECT_TRUE(wayland_popup); wayland_popup->Show(false); @@ -2462,7 +2439,7 @@ } } -TEST_P(WaylandWindowTest, WaylandPopupInitialBufferUsesParentScale) { +TEST_F(WaylandWindowTest, WaylandPopupInitialBufferUsesParentScale) { VerifyAndClearExpectations(); PostToServerAndWait([](wl::TestWaylandServerThread* server) { @@ -2499,7 +2476,7 @@ gfx::ScaleToCeiledSize(kBoundsDip.size(), 2); std::unique_ptr<WaylandWindow> wayland_popup = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, window_->GetWidget(), kBoundsDip, &delegate_); + PlatformWindowType::kMenu, kBoundsDip, &delegate_, window_->GetWidget()); EXPECT_TRUE(wayland_popup); wayland_popup->Show(false); @@ -2519,7 +2496,7 @@ // Tests that a WaylandWindow uses the entered output with largest scale // factor as the preferred output. If scale factors are equal, the very first // entered display is used. -TEST_P(WaylandWindowTest, GetPreferredOutput) { +TEST_F(WaylandWindowTest, GetPreferredOutput) { VerifyAndClearExpectations(); // Buffer scale must be 1 when no output has been entered by the window. @@ -2649,7 +2626,7 @@ EXPECT_EQ(window_->GetPreferredEnteredOutputId(), output1_id); } -TEST_P(WaylandWindowTest, GetChildrenPreferredOutput) { +TEST_F(WaylandWindowTest, GetChildrenPreferredOutput) { VerifyAndClearExpectations(); // Buffer scale must be 1 when no output has been entered by the window. @@ -2657,8 +2634,8 @@ MockWaylandPlatformWindowDelegate menu_window_delegate; std::unique_ptr<WaylandWindow> menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, window_->GetWidget(), - gfx::Rect(10, 10, 10, 10), &menu_window_delegate); + PlatformWindowType::kMenu, gfx::Rect(10, 10, 10, 10), + &menu_window_delegate, window_->GetWidget()); menu_window->Show(false); @@ -2764,7 +2741,7 @@ // Tests that xdg_popup is configured with default anchor properties and bounds // if delegate doesn't have anchor properties set. -TEST_P(WaylandWindowTest, PopupPassesDefaultAnchorInformation) { +TEST_F(WaylandWindowTest, PopupPassesDefaultAnchorInformation) { PopupPosition menu_window_positioner, nested_menu_window_positioner; menu_window_positioner = {gfx::Rect(439, 46, 1, 1), gfx::Size(287, 409), @@ -2790,8 +2767,8 @@ gfx::Rect menu_window_bounds(gfx::Point(439, 46), menu_window_positioner.size); std::unique_ptr<WaylandWindow> menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, toplevel_window->GetWidget(), - menu_window_bounds, &menu_window_delegate); + PlatformWindowType::kMenu, menu_window_bounds, &menu_window_delegate, + toplevel_window->GetWidget()); EXPECT_TRUE(menu_window); VerifyXdgPopupPosition(menu_window.get(), menu_window_positioner); @@ -2809,8 +2786,8 @@ nested_menu_window_positioner.size); std::unique_ptr<WaylandWindow> nested_menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, menu_window->GetWidget(), - nested_menu_window_bounds, &nested_menu_window_delegate); + PlatformWindowType::kMenu, nested_menu_window_bounds, + &nested_menu_window_delegate, menu_window->GetWidget()); EXPECT_TRUE(nested_menu_window); VerifyXdgPopupPosition(nested_menu_window.get(), @@ -2819,7 +2796,7 @@ // Tests that xdg_popup is configured with anchor properties received from // delegate. -TEST_P(WaylandWindowTest, PopupPassesSetAnchorInformation) { +TEST_F(WaylandWindowTest, PopupPassesSetAnchorInformation) { PopupPosition menu_window_positioner, nested_menu_window_positioner; menu_window_positioner = {gfx::Rect(468, 46, 28, 28), gfx::Size(320, 404), @@ -2848,8 +2825,8 @@ gfx::Rect menu_window_bounds(gfx::Point(176, 74), menu_window_positioner.size); std::unique_ptr<WaylandWindow> menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, toplevel_window->GetWidget(), - menu_window_bounds, &menu_window_delegate); + PlatformWindowType::kMenu, menu_window_bounds, &menu_window_delegate, + toplevel_window->GetWidget()); EXPECT_TRUE(menu_window); VerifyXdgPopupPosition(menu_window.get(), menu_window_positioner); @@ -2868,15 +2845,15 @@ nested_menu_window_positioner.size); std::unique_ptr<WaylandWindow> nested_menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, menu_window->GetWidget(), - nested_menu_window_bounds, &nested_menu_window_delegate); + PlatformWindowType::kMenu, nested_menu_window_bounds, + &nested_menu_window_delegate, menu_window->GetWidget()); EXPECT_TRUE(nested_menu_window); VerifyXdgPopupPosition(nested_menu_window.get(), nested_menu_window_positioner); } -TEST_P(WaylandWindowTest, SetOpaqueRegion) { +TEST_F(WaylandWindowTest, SetOpaqueRegion) { gfx::Rect new_bounds(500, 600); SkIRect rect = SkIRect::MakeXYWH(0, 0, new_bounds.width(), new_bounds.height()); @@ -2904,7 +2881,7 @@ }); } -TEST_P(WaylandWindowTest, OnCloseRequest) { +TEST_F(WaylandWindowTest, OnCloseRequest) { EXPECT_CALL(delegate_, OnCloseRequest()); PostToServerAndWait([id = surface_id_](wl::TestWaylandServerThread* server) { @@ -2915,7 +2892,7 @@ }); } -TEST_P(WaylandWindowTest, WaylandPopupSimpleParent) { +TEST_F(WaylandWindowTest, WaylandPopupSimpleParent) { VerifyAndClearExpectations(); EXPECT_CALL(delegate_, GetMenuType()) @@ -2924,8 +2901,8 @@ // use focused window instead. gfx::Rect wayland_popup_bounds(gfx::Point(15, 15), gfx::Size(10, 10)); std::unique_ptr<WaylandWindow> wayland_popup = CreateWaylandWindowWithParams( - PlatformWindowType::kTooltip, window_->GetWidget(), wayland_popup_bounds, - &delegate_); + PlatformWindowType::kTooltip, wayland_popup_bounds, &delegate_, + window_->GetWidget()); EXPECT_TRUE(wayland_popup); wayland_popup->Show(false); @@ -2945,13 +2922,13 @@ wayland_popup->Hide(); } -TEST_P(WaylandWindowTest, WaylandPopupNestedParent) { +TEST_F(WaylandWindowTest, WaylandPopupNestedParent) { VerifyAndClearExpectations(); gfx::Rect menu_window_bounds(gfx::Point(10, 10), gfx::Size(100, 100)); auto menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, window_->GetWidget(), menu_window_bounds, - &delegate_); + PlatformWindowType::kMenu, menu_window_bounds, &delegate_, + window_->GetWidget()); EXPECT_TRUE(menu_window); VerifyAndClearExpectations(); @@ -2963,8 +2940,8 @@ gfx::Rect nested_wayland_popup_bounds(gfx::Point(15, 15), gfx::Size(10, 10)); auto nested_wayland_popup = - CreateWaylandWindowWithParams(type, menu_window->GetWidget(), - nested_wayland_popup_bounds, &delegate_); + CreateWaylandWindowWithParams(type, nested_wayland_popup_bounds, + &delegate_, menu_window->GetWidget()); EXPECT_TRUE(nested_wayland_popup); VerifyAndClearExpectations(); @@ -2994,7 +2971,7 @@ // Tests that size constraints returned by the `ui::PlatformWindowDelegate` are // obeyed by the window when its bounds are set internally via its // SetBoundsInDIP() implementation. -TEST_P(WaylandWindowTest, SizeConstraintsInternal) { +TEST_F(WaylandWindowTest, SizeConstraintsInternal) { constexpr gfx::Size kMinSize{100, 100}; constexpr gfx::Size kMaxSize{300, 300}; @@ -3024,7 +3001,7 @@ // Tests that size constraints returned by the `ui::PlatformWindowDelegate` are // obeyed by the window when its bounds are set externally via the configure // event sent by the compositor. -TEST_P(WaylandWindowTest, SizeConstraintsExternal) { +TEST_F(WaylandWindowTest, SizeConstraintsExternal) { constexpr gfx::Size kMinSize{100, 100}; constexpr gfx::Size kMaxSize{300, 300}; @@ -3060,7 +3037,7 @@ SendConfigureEvent(surface_id_, even_greater_bounds.size(), state); } -TEST_P(WaylandWindowTest, OnSizeConstraintsChanged) { +TEST_F(WaylandWindowTest, OnSizeConstraintsChanged) { const bool kBooleans[] = {false, true}; for (bool has_min_size : kBooleans) { for (bool has_max_size : kBooleans) { @@ -3091,10 +3068,9 @@ } } -TEST_P(WaylandWindowTest, DestroysCreatesSurfaceOnHideShow) { +TEST_F(WaylandWindowTest, DestroysCreatesSurfaceOnHideShow) { MockWaylandPlatformWindowDelegate delegate; auto window = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, - gfx::kNullAcceleratedWidget, gfx::Rect(100, 100), &delegate); ASSERT_TRUE(window); @@ -3121,13 +3097,13 @@ }); } -TEST_P(WaylandWindowTest, DestroysCreatesPopupsOnHideShow) { +TEST_F(WaylandWindowTest, DestroysCreatesPopupsOnHideShow) { MockWaylandPlatformWindowDelegate delegate; EXPECT_CALL(delegate, GetMenuType()) .WillRepeatedly(Return(MenuType::kRootContextMenu)); auto window = CreateWaylandWindowWithParams(PlatformWindowType::kMenu, - window_->GetWidget(), - gfx::Rect(50, 50), &delegate); + gfx::Rect(50, 50), &delegate, + window_->GetWidget()); ASSERT_TRUE(window); const uint32_t surface_id = window->root_surface()->get_surface_id(); @@ -3153,7 +3129,7 @@ }); } -TEST_P(WaylandWindowTest, ReattachesBackgroundOnShow) { +TEST_F(WaylandWindowTest, ReattachesBackgroundOnShow) { EXPECT_TRUE(connection_->buffer_manager_host()); auto interface_ptr = connection_->buffer_manager_host()->BindInterface(); @@ -3175,7 +3151,6 @@ // Create window. MockWaylandPlatformWindowDelegate delegate; auto window = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, - gfx::kNullAcceleratedWidget, gfx::Rect(100, 100), &delegate); ASSERT_TRUE(window); auto states = InitializeWlArrayWithActivatedState(); @@ -3245,7 +3220,7 @@ // Tests that if the window gets hidden and shown again, the title, app id and // size constraints remain the same. -TEST_P(WaylandWindowTest, SetsPropertiesOnShow) { +TEST_F(WaylandWindowTest, SetsPropertiesOnShow) { constexpr char kAppId[] = "wayland_test"; const std::u16string kTitle(u"WaylandWindowTest"); @@ -3322,7 +3297,7 @@ // Tests that a popup window is created using the serial of button press // events as required by the Wayland protocol spec. -TEST_P(WaylandWindowTest, CreatesPopupOnButtonPressSerial) { +TEST_F(WaylandWindowTest, CreatesPopupOnButtonPressSerial) { for (bool use_explicit_grab : {false, true}) { base::test::ScopedCommandLine command_line_; if (use_explicit_grab) { @@ -3368,28 +3343,28 @@ EXPECT_CALL(delegate, GetMenuType()) .WillOnce(Return(MenuType::kRootContextMenu)); auto popup = CreateWaylandWindowWithParams(PlatformWindowType::kMenu, - window_->GetWidget(), - gfx::Rect(50, 50), &delegate); + gfx::Rect(50, 50), &delegate, + window_->GetWidget()); ASSERT_TRUE(popup); const uint32_t surface_id = popup->root_surface()->get_surface_id(); // Unfortunately, everything has to be captured as |use_explicit_grab| may // not be used and |maybe_unused| doesn't work with lambda captures. PostToServerAndWait([&](wl::TestWaylandServerThread* server) { - auto* test_popup = GetTestXdgPopupByWindow(server, surface_id); - ASSERT_TRUE(test_popup); + auto* TEST_Fopup = GetTestXdgPopupByWindow(server, surface_id); + ASSERT_TRUE(TEST_Fopup); #if !BUILDFLAG(IS_CHROMEOS_LACROS) if (use_explicit_grab) { - EXPECT_NE(test_popup->grab_serial(), button_release_serial); - EXPECT_EQ(test_popup->grab_serial(), button_press_serial); + EXPECT_NE(TEST_Fopup->grab_serial(), button_release_serial); + EXPECT_EQ(TEST_Fopup->grab_serial(), button_press_serial); } else { - EXPECT_EQ(test_popup->grab_serial(), 0U); + EXPECT_EQ(TEST_Fopup->grab_serial(), 0U); } #else // crbug.com/1320528: Lacros uses explicit grab always. - EXPECT_NE(test_popup->grab_serial(), button_release_serial); - EXPECT_EQ(test_popup->grab_serial(), button_press_serial); + EXPECT_NE(TEST_Fopup->grab_serial(), button_release_serial); + EXPECT_EQ(TEST_Fopup->grab_serial(), button_press_serial); #endif // !BUILDFLAG(IS_CHROMEOS_LACROS) }); } @@ -3397,7 +3372,7 @@ // Tests that a popup window is created using the serial of touch down events // as required by the Wayland protocol spec. -TEST_P(WaylandWindowTest, CreatesPopupOnTouchDownSerial) { +TEST_F(WaylandWindowTest, CreatesPopupOnTouchDownSerial) { for (bool use_explicit_grab : {false, true}) { base::test::ScopedCommandLine command_line_; if (use_explicit_grab) { @@ -3439,16 +3414,16 @@ EXPECT_CALL(delegate, GetMenuType()) .WillRepeatedly(Return(MenuType::kRootContextMenu)); auto popup = CreateWaylandWindowWithParams(PlatformWindowType::kMenu, - window_->GetWidget(), - gfx::Rect(50, 50), &delegate); + gfx::Rect(50, 50), &delegate, + window_->GetWidget()); ASSERT_TRUE(popup); const uint32_t surface_id = popup->root_surface()->get_surface_id(); // Unfortunately, everything has to be captured as |use_explicit_grab| may // not be used and |maybe_unused| doesn't work with lambda captures. PostToServerAndWait([&](wl::TestWaylandServerThread* server) { - auto* test_popup = GetTestXdgPopupByWindow(server, surface_id); - ASSERT_TRUE(test_popup); + auto* TEST_Fopup = GetTestXdgPopupByWindow(server, surface_id); + ASSERT_TRUE(TEST_Fopup); // crbug.com/1320528: Lacros uses explicit grab always. #if !BUILDFLAG(IS_CHROMEOS_LACROS) // Unless the use-wayland-explicit-grab switch is set, touch events @@ -3456,7 +3431,7 @@ // (latest) cannot be used, otherwise, some compositors may dismiss // popups. if (!use_explicit_grab) - EXPECT_EQ(test_popup->grab_serial(), 0U); + EXPECT_EQ(TEST_Fopup->grab_serial(), 0U); #endif }); @@ -3478,8 +3453,8 @@ // Unfortunately, everything has to be captured as |use_explicit_grab| may // not be used and |maybe_unused| doesn't work with lambda captures. PostToServerAndWait([&](wl::TestWaylandServerThread* server) { - auto* test_popup = GetTestXdgPopupByWindow(server, surface_id); - ASSERT_TRUE(test_popup); + auto* TEST_Fopup = GetTestXdgPopupByWindow(server, surface_id); + ASSERT_TRUE(TEST_Fopup); #if !BUILDFLAG(IS_CHROMEOS_LACROS) uint32_t expected_serial = touch_down_serial; @@ -3490,13 +3465,13 @@ expected_serial = 0u; } if (use_explicit_grab) { - EXPECT_EQ(test_popup->grab_serial(), expected_serial); + EXPECT_EQ(TEST_Fopup->grab_serial(), expected_serial); } else { - EXPECT_EQ(test_popup->grab_serial(), 0U); + EXPECT_EQ(TEST_Fopup->grab_serial(), 0U); } #else // crbug.com/1320528: Lacros uses explicit grab always. - EXPECT_EQ(test_popup->grab_serial(), touch_down_serial); + EXPECT_EQ(TEST_Fopup->grab_serial(), touch_down_serial); #endif // !BUILDFLAG(IS_CHROMEOS_LACROS) }); } @@ -3504,62 +3479,62 @@ // Tests nested menu windows get the topmost window in the stack of windows // within the same family/tree. -TEST_P(WaylandWindowTest, NestedPopupWindowsGetCorrectParent) { +TEST_F(WaylandWindowTest, NestedPopupWindowsGetCorrectParent) { VerifyAndClearExpectations(); gfx::Rect menu_window_bounds(gfx::Rect(10, 20, 20, 20)); std::unique_ptr<WaylandWindow> menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, window_->GetWidget(), menu_window_bounds, - &delegate_); + PlatformWindowType::kMenu, menu_window_bounds, &delegate_, + window_->GetWidget()); EXPECT_TRUE(menu_window); EXPECT_TRUE(menu_window->parent_window() == window_.get()); gfx::Rect menu_window_bounds2(gfx::Rect(20, 40, 30, 20)); std::unique_ptr<WaylandWindow> menu_window2 = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, menu_window->GetWidget(), menu_window_bounds2, - &delegate_); + PlatformWindowType::kMenu, menu_window_bounds2, &delegate_, + menu_window->GetWidget()); EXPECT_TRUE(menu_window2); EXPECT_TRUE(menu_window2->parent_window() == menu_window.get()); gfx::Rect menu_window_bounds3(gfx::Rect(30, 40, 30, 20)); std::unique_ptr<WaylandWindow> menu_window3 = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, menu_window2->GetWidget(), menu_window_bounds3, - &delegate_); + PlatformWindowType::kMenu, menu_window_bounds3, &delegate_, + menu_window2->GetWidget()); EXPECT_TRUE(menu_window3); EXPECT_TRUE(menu_window3->parent_window() == menu_window2.get()); gfx::Rect menu_window_bounds4(gfx::Rect(40, 40, 30, 20)); std::unique_ptr<WaylandWindow> menu_window4 = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, menu_window3->GetWidget(), menu_window_bounds4, - &delegate_); + PlatformWindowType::kMenu, menu_window_bounds4, &delegate_, + menu_window3->GetWidget()); EXPECT_TRUE(menu_window4); EXPECT_TRUE(menu_window4->parent_window() == menu_window3.get()); } -TEST_P(WaylandWindowTest, DoesNotGrabPopupIfNoSeat) { +TEST_F(WaylandWindowTest, DoesNotGrabPopupIfNoSeat) { // Create a popup window and verify the grab serial is not set. MockWaylandPlatformWindowDelegate delegate; EXPECT_CALL(delegate, GetMenuType()) .WillOnce(Return(MenuType::kRootContextMenu)); auto popup = CreateWaylandWindowWithParams(PlatformWindowType::kMenu, - window_->GetWidget(), - gfx::Rect(50, 50), &delegate); + gfx::Rect(50, 50), &delegate, + window_->GetWidget()); ASSERT_TRUE(popup); PostToServerAndWait([surface_id = popup->root_surface()->get_surface_id()]( wl::TestWaylandServerThread* server) { - auto* test_popup = GetTestXdgPopupByWindow(server, surface_id); - ASSERT_TRUE(test_popup); - EXPECT_EQ(test_popup->grab_serial(), 0u); + auto* TEST_Fopup = GetTestXdgPopupByWindow(server, surface_id); + ASSERT_TRUE(TEST_Fopup); + EXPECT_EQ(TEST_Fopup->grab_serial(), 0u); }); } // Regression test for https://crbug.com/1247799. -TEST_P(WaylandWindowTest, DoesNotGrabPopupUnlessParentHasGrab) { +TEST_F(WaylandWindowTest, DoesNotGrabPopupUnlessParentHasGrab) { PostToServerAndWait([](wl::TestWaylandServerThread* server) { wl_seat_send_capabilities(server->seat()->resource(), WL_SEAT_CAPABILITY_POINTER); @@ -3575,8 +3550,8 @@ std::unique_ptr<WaylandWindow> root_menu; EXPECT_CALL(delegate, GetMenuType()).WillOnce(Return(MenuType::kRootMenu)); root_menu = CreateWaylandWindowWithParams(PlatformWindowType::kMenu, - window_->GetWidget(), - gfx::Rect(50, 50), &delegate); + gfx::Rect(50, 50), &delegate, + window_->GetWidget()); VerifyAndClearExpectations(); Mock::VerifyAndClearExpectations(&delegate); ASSERT_TRUE(root_menu); @@ -3613,8 +3588,8 @@ std::unique_ptr<WaylandWindow> child_menu; EXPECT_CALL(delegate_2, GetMenuType()).WillOnce(Return(MenuType::kChildMenu)); child_menu = CreateWaylandWindowWithParams(PlatformWindowType::kMenu, - root_menu->GetWidget(), - gfx::Rect(10, 10), &delegate_2); + gfx::Rect(10, 10), &delegate_2, + root_menu->GetWidget()); VerifyAndClearExpectations(); Mock::VerifyAndClearExpectations(&delegate_2); ASSERT_TRUE(child_menu); @@ -3636,20 +3611,20 @@ }); } -TEST_P(WaylandWindowTest, InitialBounds) { +TEST_F(WaylandWindowTest, InitialBounds) { testing::NiceMock<MockWaylandPlatformWindowDelegate> delegate_2; auto toplevel = CreateWaylandWindowWithParams( - PlatformWindowType::kWindow, 0, gfx::Rect(10, 10, 200, 200), &delegate_2); + PlatformWindowType::kWindow, gfx::Rect(10, 10, 200, 200), &delegate_2); toplevel->HandleAuraToplevelConfigure(0, 0, 0, 0, {false, false, true}); toplevel->HandleSurfaceConfigure(2); static_cast<WaylandToplevelWindow*>(toplevel.get())->ApplyPendingBounds(); EXPECT_EQ(gfx::Rect(10, 10, 200, 200), toplevel->GetBoundsInDIP()); } -TEST_P(WaylandWindowTest, PrimarySnappedState) { +TEST_F(WaylandWindowTest, PrimarySnappedState) { testing::NiceMock<MockWaylandPlatformWindowDelegate> delegate_2; auto toplevel = CreateWaylandWindowWithParams( - PlatformWindowType::kWindow, 0, gfx::Rect(0, 0, 200, 200), &delegate_2); + PlatformWindowType::kWindow, gfx::Rect(0, 0, 200, 200), &delegate_2); toplevel->HandleAuraToplevelConfigure(0, 0, 100, 200, {.is_maximized = false, .is_fullscreen = false, @@ -3660,10 +3635,10 @@ EXPECT_EQ(gfx::Rect(0, 0, 100, 200), toplevel->GetBoundsInDIP()); } -TEST_P(WaylandWindowTest, SecondarySnappedState) { +TEST_F(WaylandWindowTest, SecondarySnappedState) { testing::NiceMock<MockWaylandPlatformWindowDelegate> delegate_2; auto toplevel = CreateWaylandWindowWithParams( - PlatformWindowType::kWindow, 0, gfx::Rect(0, 0, 200, 200), &delegate_2); + PlatformWindowType::kWindow, gfx::Rect(0, 0, 200, 200), &delegate_2); toplevel->HandleAuraToplevelConfigure(100, 0, 100, 200, {.is_maximized = false, .is_fullscreen = false, @@ -3688,8 +3663,7 @@ VerifyAndClearExpectations(); std::unique_ptr<WaylandWindow> window = CreateWaylandWindowWithParams( - PlatformWindowType::kWindow, gfx::kNullAcceleratedWidget, - gfx::Rect(640, 480), &delegate_); + PlatformWindowType::kWindow, gfx::Rect(640, 480), &delegate_); EXPECT_TRUE(window); bool result = window->RequestSubsurface(); @@ -3756,7 +3730,7 @@ // Tests integer and non integer size/position support with and without surface // augmenter. -TEST_P(WaylandSubsurfaceTest, OneWaylandSubsurfaceInteger) { +TEST_F(WaylandSubsurfaceTest, OneWaylandSubsurfaceInteger) { ASSERT_FALSE(connection_->surface_augmenter()); constexpr gfx::RectF test_data[2][2] = { @@ -3775,7 +3749,7 @@ }; } -TEST_P(WaylandSubsurfaceTest, OneWaylandSubsurfaceNonInteger) { +TEST_F(WaylandSubsurfaceTest, OneWaylandSubsurfaceNonInteger) { ASSERT_FALSE(connection_->surface_augmenter()); constexpr gfx::RectF test_data[2][2] = { @@ -3792,7 +3766,7 @@ } } -TEST_P(WaylandSubsurfaceTest, NoDuplicateSubsurfaceRequests) { +TEST_F(WaylandSubsurfaceTest, NoDuplicateSubsurfaceRequests) { auto subsurfaces = RequestWaylandSubsurface(3); for (auto* subsurface : subsurfaces) { subsurface->ConfigureAndShowSurface(gfx::RectF(1.f, 2.f, 10.f, 20.f), @@ -3838,7 +3812,7 @@ VerifyAndClearExpectations(); } -TEST_P(WaylandWindowTest, NoDuplicateViewporterRequests) { +TEST_F(WaylandWindowTest, NoDuplicateViewporterRequests) { EXPECT_TRUE(connection_->buffer_manager_host()); auto interface_ptr = connection_->buffer_manager_host()->BindInterface(); @@ -3940,15 +3914,15 @@ } // Tests that WaylandPopups can be repositioned. -TEST_P(WaylandWindowTest, RepositionPopups) { +TEST_F(WaylandWindowTest, RepositionPopups) { VerifyAndClearExpectations(); EXPECT_CALL(delegate_, GetMenuType()) .WillRepeatedly(Return(MenuType::kRootContextMenu)); gfx::Rect menu_window_bounds(gfx::Rect(6, 20, 8, 20)); std::unique_ptr<WaylandWindow> menu_window = CreateWaylandWindowWithParams( - PlatformWindowType::kMenu, window_->GetWidget(), menu_window_bounds, - &delegate_); + PlatformWindowType::kMenu, menu_window_bounds, &delegate_, + window_->GetWidget()); EXPECT_TRUE(menu_window); EXPECT_TRUE(menu_window->IsVisible()); @@ -3999,13 +3973,13 @@ // If buffers are not attached (aka WaylandBufferManagerHost is not used for // buffer management), WaylandSurface::Commit mustn't result in creation of // surface sync. -TEST_P(WaylandWindowTest, DoesNotCreateSurfaceSyncOnCommitWithoutBuffers) { +TEST_F(WaylandWindowTest, DoesNotCreateSurfaceSyncOnCommitWithoutBuffers) { EXPECT_THAT(window_->root_surface()->surface_sync_, nullptr); window_->root_surface()->Commit(); EXPECT_THAT(window_->root_surface()->surface_sync_, nullptr); } -TEST_P(WaylandWindowTest, StartWithMinimized) { +TEST_F(WaylandWindowTest, StartWithMinimized) { // Make sure the window is initialized to normal state from the beginning. EXPECT_EQ(PlatformWindowState::kNormal, window_->GetPlatformWindowState()); @@ -4101,7 +4075,7 @@ // the first touch down/up action, and blocks the original flow, before it gets // handled completely. // The test is flaky. https://crbug.com/1305272. -TEST_P(WaylandWindowTest, DISABLED_BlockingTouchDownUp_NoCrash) { +TEST_F(WaylandWindowTest, DISABLED_BlockingTouchDownUp_NoCrash) { window_.reset(); MockWaylandPlatformWindowDelegate delegate; @@ -4162,7 +4136,7 @@ #else #define MAYBE_ChangeFocusDuringDispatch ChangeFocusDuringDispatch #endif -TEST_P(WaylandWindowTest, MAYBE_ChangeFocusDuringDispatch) { +TEST_F(WaylandWindowTest, MAYBE_ChangeFocusDuringDispatch) { MockPlatformWindowDelegate other_delegate; gfx::AcceleratedWidget other_widget = gfx::kNullAcceleratedWidget; EXPECT_CALL(other_delegate, OnAcceleratedWidgetAvailable(_)) @@ -4223,7 +4197,7 @@ EXPECT_EQ(count, 3); } -TEST_P(WaylandWindowTest, WindowMovedResized) { +TEST_F(WaylandWindowTest, WindowMovedResized) { const gfx::Rect initial_bounds = window_->GetBoundsInDIP(); gfx::Rect new_bounds(initial_bounds); @@ -4267,7 +4241,7 @@ // Make sure that creating a window with DIP bounds creates a window with // the same DIP bounds with various fractional scales. -TEST_P(WaylandWindowTest, NoRoundingErrorInDIP) { +TEST_F(WaylandWindowTest, NoRoundingErrorInDIP) { VerifyAndClearExpectations(); auto* primary_output = connection_->wayland_output_manager()->GetPrimaryOutput(); @@ -4281,7 +4255,6 @@ testing::NiceMock<MockWaylandPlatformWindowDelegate> delegate; std::unique_ptr<WaylandWindow> wayland_window = CreateWaylandWindowWithParams(PlatformWindowType::kWindow, - gfx::kNullAcceleratedWidget, gfx::Rect(20, 0, 100, 100), &delegate); for (int i = 100; i < 3000; i++) { const gfx::Rect kBoundsDip{20, 0, i, 3000 - i}; @@ -4294,12 +4267,4 @@ VerifyAndClearExpectations(); } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandWindowTest, - Values(wl::ServerConfig{})); - -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandSubsurfaceTest, - Values(wl::ServerConfig{})); - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_output_unittest.cc b/ui/ozone/platform/wayland/host/wayland_zaura_output_unittest.cc index 2c6afbf..6f506b9 100644 --- a/ui/ozone/platform/wayland/host/wayland_zaura_output_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_zaura_output_unittest.cc
@@ -15,17 +15,10 @@ namespace ui { -using ::testing::Values; -namespace { -class WaylandZAuraOutputTest : public WaylandTest { +class WaylandZAuraOutputTest : public WaylandTestSimple { public: - WaylandZAuraOutputTest() : WaylandTest(TestServerMode::kAsync) {} - WaylandZAuraOutputTest(const WaylandZAuraOutputTest&) = delete; - WaylandZAuraOutputTest& operator=(const WaylandZAuraOutputTest&) = delete; - ~WaylandZAuraOutputTest() override = default; - void SetUp() override { - WaylandTest::SetUp(); + WaylandTestSimple::SetUp(); // Set default values for the output. PostToServerAndWait([](wl::TestWaylandServerThread* server) { @@ -50,9 +43,7 @@ std::unique_ptr<WaylandScreen> platform_screen_; }; -} // namespace - -TEST_P(WaylandZAuraOutputTest, HandleInsets) { +TEST_F(WaylandZAuraOutputTest, HandleInsets) { WaylandOutput* wayland_output = output_manager_->GetPrimaryOutput(); ASSERT_TRUE(wayland_output); EXPECT_TRUE(wayland_output->IsReady()); @@ -79,7 +70,7 @@ EXPECT_EQ(wayland_output->insets(), insets); } -TEST_P(WaylandZAuraOutputTest, HandleLogicalTransform) { +TEST_F(WaylandZAuraOutputTest, HandleLogicalTransform) { WaylandOutput* wayland_output = output_manager_->GetPrimaryOutput(); ASSERT_TRUE(wayland_output); EXPECT_TRUE(wayland_output->IsReady()); @@ -98,7 +89,7 @@ } // Test edge case display ids are converted correctly. -TEST_P(WaylandZAuraOutputTest, DisplayIdConversions) { +TEST_F(WaylandZAuraOutputTest, DisplayIdConversions) { const int64_t kTestIds[] = { std::numeric_limits<int64_t>::min(), std::numeric_limits<int64_t>::min() + 1, @@ -122,8 +113,4 @@ } } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandZAuraOutputTest, - Values(wl::ServerConfig{})); - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_shell_unittest.cc b/ui/ozone/platform/wayland/host/wayland_zaura_shell_unittest.cc index 625d94af..7c627f95 100644 --- a/ui/ozone/platform/wayland/host/wayland_zaura_shell_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_zaura_shell_unittest.cc
@@ -13,18 +13,9 @@ namespace ui { -// TODO(crbug.com/1365887): change this to -// `using WaylandZAuraShellTest = WaylandTest` -// once the default mode becomes asynchronous. -class WaylandZAuraShellTest : public WaylandTest { - public: - WaylandZAuraShellTest() : WaylandTest(TestServerMode::kAsync) {} - WaylandZAuraShellTest(const WaylandZAuraShellTest&) = delete; - WaylandZAuraShellTest& operator=(const WaylandZAuraShellTest&) = delete; - ~WaylandZAuraShellTest() override = default; -}; +using WaylandZAuraShellTest = WaylandTestSimple; -TEST_P(WaylandZAuraShellTest, BugFix) { +TEST_F(WaylandZAuraShellTest, BugFix) { PostToServerAndWait([](wl::TestWaylandServerThread* server) { auto* const zaura_shell = server->zaura_shell()->resource(); zaura_shell_send_bug_fix(zaura_shell, 1); @@ -36,8 +27,4 @@ ASSERT_FALSE(connection_->zaura_shell()->HasBugFix(2)); } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandZAuraShellTest, - Values(wl::ServerConfig{})); - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures_unittest.cc b/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures_unittest.cc index f845ad87..5cd9c0ee 100644 --- a/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures_unittest.cc
@@ -56,16 +56,10 @@ } // namespace -class WaylandPointerGesturesTest : public WaylandTest { +class WaylandPointerGesturesTest : public WaylandTestSimple { public: - WaylandPointerGesturesTest() : WaylandTest(TestServerMode::kAsync) {} - WaylandPointerGesturesTest(const WaylandPointerGesturesTest&) = delete; - WaylandPointerGesturesTest& operator=(const WaylandPointerGesturesTest&) = - delete; - ~WaylandPointerGesturesTest() override = default; - void SetUp() override { - WaylandTest::SetUp(); + WaylandTestSimple::SetUp(); // Pointer capability is required for gesture objects to be initialised. PostToServerAndWait([](wl::TestWaylandServerThread* server) { @@ -89,7 +83,7 @@ // WaylandZwpPointerGestures methods. // // See https://crbug.com/1283652 -TEST_P(WaylandPointerGesturesTest, PinchZoomScale) { +TEST_F(WaylandPointerGesturesTest, PinchZoomScale) { PostToServerAndWait([surface_id = window_->root_surface()->get_surface_id()]( wl::TestWaylandServerThread* server) { auto* const pointer = server->seat()->pointer()->resource(); @@ -140,8 +134,4 @@ } } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - WaylandPointerGesturesTest, - testing::Values(wl::ServerConfig{})); - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1_unittest.cc b/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1_unittest.cc index b18e51a..159489b 100644 --- a/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1_unittest.cc +++ b/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1_unittest.cc
@@ -4,12 +4,9 @@ #include "ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.h" -#include "base/run_loop.h" -#include "base/test/task_environment.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h" -#include "ui/ozone/platform/wayland/host/wayland_event_source.h" #include "ui/ozone/platform/wayland/test/mock_zcr_extended_text_input.h" #include "ui/ozone/platform/wayland/test/mock_zwp_text_input.h" #include "ui/ozone/platform/wayland/test/test_wayland_server_thread.h" @@ -17,99 +14,89 @@ #include "ui/ozone/platform/wayland/test/wayland_test.h" using ::testing::InSequence; -using ::testing::Values; +using ::testing::Mock; namespace ui { -namespace { -class ZWPTextInputWrapperV1Test : public WaylandTest { +class ZWPTextInputWrapperV1Test : public WaylandTestSimple { public: - ZWPTextInputWrapperV1Test() = default; - ZWPTextInputWrapperV1Test(const ZWPTextInputWrapperV1Test&) = delete; - ZWPTextInputWrapperV1Test& operator=(const ZWPTextInputWrapperV1Test&) = - delete; - ~ZWPTextInputWrapperV1Test() override = default; - void SetUp() override { - WaylandTest::SetUp(); + WaylandTestSimple::SetUp(); wrapper_ = std::make_unique<ZWPTextInputWrapperV1>( connection_.get(), nullptr, connection_->text_input_manager_v1(), connection_->text_input_extension_v1()); - - connection_->Flush(); - Sync(); - - mock_text_input_ = server_.text_input_manager_v1()->text_input(); - ASSERT_TRUE(mock_text_input_); - mock_ext_text_input_ = - server_.text_input_extension_v1()->extended_text_input(); - ASSERT_TRUE(mock_ext_text_input_); } protected: std::unique_ptr<ZWPTextInputWrapperV1> wrapper_; - wl::MockZwpTextInput* mock_text_input_ = nullptr; - wl::MockZcrExtendedTextInput* mock_ext_text_input_ = nullptr; }; -TEST_P(ZWPTextInputWrapperV1Test, +TEST_F(ZWPTextInputWrapperV1Test, FinalizeVirtualKeyboardChangesShowInputPanel) { - InSequence s; - EXPECT_CALL(*mock_text_input_, ShowInputPanel()); - EXPECT_CALL(*mock_ext_text_input_, FinalizeVirtualKeyboardChanges()); - wrapper_->ShowInputPanel(); - connection_->Flush(); - Sync(); + PostToServerAndWait([](wl::TestWaylandServerThread* server) { + InSequence s; + EXPECT_CALL(*server->text_input_manager_v1()->text_input(), + ShowInputPanel()); + EXPECT_CALL(*server->text_input_extension_v1()->extended_text_input(), + FinalizeVirtualKeyboardChanges()); + }); - // Flush again after sync, so the scheduled finalize request is processed. - connection_->Flush(); - Sync(); + wrapper_->ShowInputPanel(); + + PostToServerAndWait([](wl::TestWaylandServerThread* server) { + Mock::VerifyAndClearExpectations( + server->text_input_manager_v1()->text_input()); + Mock::VerifyAndClearExpectations(server->text_input_extension_v1()); + }); } -TEST_P(ZWPTextInputWrapperV1Test, +TEST_F(ZWPTextInputWrapperV1Test, FinalizeVirtualKeyboardChangesHideInputPanel) { - InSequence s; - EXPECT_CALL(*mock_text_input_, HideInputPanel()); - EXPECT_CALL(*mock_ext_text_input_, FinalizeVirtualKeyboardChanges()); - wrapper_->HideInputPanel(); - connection_->Flush(); - Sync(); + PostToServerAndWait([](wl::TestWaylandServerThread* server) { + InSequence s; + EXPECT_CALL(*server->text_input_manager_v1()->text_input(), + HideInputPanel()); + EXPECT_CALL(*server->text_input_extension_v1()->extended_text_input(), + FinalizeVirtualKeyboardChanges()); + }); - // Flush again after sync, so the scheduled finalize request is processed. - connection_->Flush(); - Sync(); + wrapper_->HideInputPanel(); + + PostToServerAndWait([](wl::TestWaylandServerThread* server) { + Mock::VerifyAndClearExpectations( + server->text_input_manager_v1()->text_input()); + Mock::VerifyAndClearExpectations( + server->text_input_extension_v1()->extended_text_input()); + }); } -TEST_P(ZWPTextInputWrapperV1Test, +TEST_F(ZWPTextInputWrapperV1Test, FinalizeVirtualKeyboardChangesMultipleInputPanelChanges) { - InSequence s; - EXPECT_CALL(*mock_text_input_, ShowInputPanel()); - EXPECT_CALL(*mock_text_input_, HideInputPanel()); - EXPECT_CALL(*mock_text_input_, ShowInputPanel()); - EXPECT_CALL(*mock_text_input_, HideInputPanel()); - EXPECT_CALL(*mock_text_input_, ShowInputPanel()); - EXPECT_CALL(*mock_ext_text_input_, FinalizeVirtualKeyboardChanges()); + PostToServerAndWait([](wl::TestWaylandServerThread* server) { + auto* const mock_text_input = server->text_input_manager_v1()->text_input(); + InSequence s; + EXPECT_CALL(*mock_text_input, ShowInputPanel()); + EXPECT_CALL(*mock_text_input, HideInputPanel()); + EXPECT_CALL(*mock_text_input, ShowInputPanel()); + EXPECT_CALL(*mock_text_input, HideInputPanel()); + EXPECT_CALL(*mock_text_input, ShowInputPanel()); + EXPECT_CALL(*server->text_input_extension_v1()->extended_text_input(), + FinalizeVirtualKeyboardChanges()); + }); + wrapper_->ShowInputPanel(); wrapper_->HideInputPanel(); wrapper_->ShowInputPanel(); wrapper_->HideInputPanel(); wrapper_->ShowInputPanel(); - connection_->Flush(); - Sync(); - // Flush again after sync, so the scheduled finalize request is processed. - connection_->Flush(); - Sync(); - - // Flush and sync again to make sure no extra finalize request. - connection_->Flush(); - Sync(); + PostToServerAndWait([](wl::TestWaylandServerThread* server) { + Mock::VerifyAndClearExpectations( + server->text_input_manager_v1()->text_input()); + Mock::VerifyAndClearExpectations( + server->text_input_extension_v1()->extended_text_input()); + }); } -INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, - ZWPTextInputWrapperV1Test, - Values(wl::ServerConfig{})); - -} // namespace } // namespace ui
diff --git a/ui/ozone/platform/wayland/test/wayland_drag_drop_test.cc b/ui/ozone/platform/wayland/test/wayland_drag_drop_test.cc index e0baa3b..a525a6c 100644 --- a/ui/ozone/platform/wayland/test/wayland_drag_drop_test.cc +++ b/ui/ozone/platform/wayland/test/wayland_drag_drop_test.cc
@@ -43,9 +43,7 @@ return std::make_unique<WaylandExchangeDataProvider>(); } -WaylandDragDropTest::WaylandDragDropTest() - : WaylandTest(WaylandTest::TestServerMode::kAsync) {} - +WaylandDragDropTest::WaylandDragDropTest() = default; WaylandDragDropTest::~WaylandDragDropTest() = default; void WaylandDragDropTest::SendDndEnter(WaylandWindow* window, @@ -214,7 +212,7 @@ } void WaylandDragDropTest::SetUp() { - WaylandTest::SetUp(); + WaylandTestSimple::SetUp(); PostToServerAndWait([](wl::TestWaylandServerThread* server) { wl_seat_send_capabilities(server->seat()->resource(),
diff --git a/ui/ozone/platform/wayland/test/wayland_drag_drop_test.h b/ui/ozone/platform/wayland/test/wayland_drag_drop_test.h index 8591d78b..61d078b 100644 --- a/ui/ozone/platform/wayland/test/wayland_drag_drop_test.h +++ b/ui/ozone/platform/wayland/test/wayland_drag_drop_test.h
@@ -33,7 +33,7 @@ // Base class for Wayland drag-and-drop tests. Public methods allow test code to // emulate dnd-related events from the test compositor and can be used in both // data and window dragging test cases. -class WaylandDragDropTest : public WaylandTest { +class WaylandDragDropTest : public WaylandTestSimple { public: WaylandDragDropTest(); WaylandDragDropTest(const WaylandDragDropTest&) = delete;
diff --git a/ui/ozone/platform/wayland/test/wayland_test.cc b/ui/ozone/platform/wayland/test/wayland_test.cc index 338d443..f63748f 100644 --- a/ui/ozone/platform/wayland/test/wayland_test.cc +++ b/ui/ozone/platform/wayland/test/wayland_test.cc
@@ -32,10 +32,12 @@ namespace ui { -WaylandTest::WaylandTest(TestServerMode server_mode) +WaylandTestBase::WaylandTestBase(wl::ServerConfig config, + TestServerMode server_mode) : task_environment_(base::test::TaskEnvironment::MainThreadType::UI, base::test::TaskEnvironment::TimeSource::MOCK_TIME), - server_mode_(server_mode) { + server_mode_(server_mode), + config_(config) { #if BUILDFLAG(USE_XKBCOMMON) auto keyboard_layout_engine = std::make_unique<XkbKeyboardLayoutEngine>(xkb_evdev_code_converter_); @@ -50,9 +52,9 @@ connection_.get(), buffer_manager_gpu_.get()); } -WaylandTest::~WaylandTest() {} +WaylandTestBase::~WaylandTestBase() = default; -void WaylandTest::SetUp() { +void WaylandTestBase::SetUp() { disabled_features_.push_back(ui::kWaylandSurfaceSubmissionInPixelCoordinates); disabled_features_.push_back(features::kWaylandScreenCoordinatesEnabled); @@ -65,7 +67,7 @@ DeviceDataManager::CreateInstance(); } - ASSERT_TRUE(server_.Start(GetParam())); + ASSERT_TRUE(server_.Start(config_)); ASSERT_TRUE(connection_->Initialize()); screen_ = connection_->wayland_output_manager()->CreateWaylandScreen(); connection_->wayland_output_manager()->InitWaylandScreen(screen_.get()); @@ -109,7 +111,7 @@ server_.SetServerAsync(); } -void WaylandTest::TearDown() { +void WaylandTestBase::TearDown() { if (initialized_) { if (server_mode_ != TestServerMode::kAsync) Sync(); @@ -118,7 +120,7 @@ } } -void WaylandTest::Sync() { +void WaylandTestBase::Sync() { // Resume the server, flushing its pending events. server_.Resume(); @@ -130,7 +132,7 @@ server_.Pause(); } -void WaylandTest::PostToServerAndWait( +void WaylandTestBase::PostToServerAndWait( base::OnceCallback<void(wl::TestWaylandServerThread* server)> callback) { // Sync with the display to ensure client's requests are processed. SyncDisplay(); @@ -141,7 +143,7 @@ SyncDisplay(); } -void WaylandTest::PostToServerAndWait(base::OnceClosure closure) { +void WaylandTestBase::PostToServerAndWait(base::OnceClosure closure) { // Sync with the display to ensure client's requests are processed. SyncDisplay(); @@ -151,22 +153,22 @@ SyncDisplay(); } -void WaylandTest::DisableSyncOnTearDown() { +void WaylandTestBase::DisableSyncOnTearDown() { initialized_ = false; } -void WaylandTest::SetPointerFocusedWindow(WaylandWindow* window) { +void WaylandTestBase::SetPointerFocusedWindow(WaylandWindow* window) { connection_->wayland_window_manager()->SetPointerFocusedWindow(window); } -void WaylandTest::SetKeyboardFocusedWindow(WaylandWindow* window) { +void WaylandTestBase::SetKeyboardFocusedWindow(WaylandWindow* window) { connection_->wayland_window_manager()->SetKeyboardFocusedWindow(window); } -void WaylandTest::SendConfigureEvent(wl::MockXdgSurface* xdg_surface, - const gfx::Size& size, - uint32_t serial, - struct wl_array* states) { +void WaylandTestBase::SendConfigureEvent(wl::MockXdgSurface* xdg_surface, + const gfx::Size& size, + uint32_t serial, + struct wl_array* states) { const int32_t width = size.width(); const int32_t height = size.height(); // Please note that toplevel surfaces may not exist if the surface was created @@ -182,10 +184,10 @@ xdg_surface_send_configure(xdg_surface->resource(), serial); } -void WaylandTest::SendConfigureEvent(uint32_t surface_id, - const gfx::Size& size, - const wl::ScopedWlArray& states, - absl::optional<uint32_t> serial) { +void WaylandTestBase::SendConfigureEvent(uint32_t surface_id, + const gfx::Size& size, + const wl::ScopedWlArray& states, + absl::optional<uint32_t> serial) { ASSERT_EQ(server_mode_, TestServerMode::kAsync); PostToServerAndWait([size, surface_id, states, serial](wl::TestWaylandServerThread* server) { @@ -215,18 +217,18 @@ }); } -void WaylandTest::ActivateSurface(wl::MockXdgSurface* xdg_surface) { +void WaylandTestBase::ActivateSurface(wl::MockXdgSurface* xdg_surface) { wl::ScopedWlArray state({XDG_TOPLEVEL_STATE_ACTIVATED}); SendConfigureEvent(xdg_surface, {0, 0}, 1, state.get()); } -void WaylandTest::ActivateSurface(uint32_t surface_id) { +void WaylandTestBase::ActivateSurface(uint32_t surface_id) { ASSERT_EQ(server_mode_, TestServerMode::kAsync); wl::ScopedWlArray state({XDG_TOPLEVEL_STATE_ACTIVATED}); SendConfigureEvent(surface_id, {0, 0}, state); } -void WaylandTest::InitializeSurfaceAugmenter() { +void WaylandTestBase::InitializeSurfaceAugmenter() { if (server_mode_ == TestServerMode::kAsync) { PostToServerAndWait([](wl::TestWaylandServerThread* server) { server->EnsureSurfaceAugmenter(); @@ -237,7 +239,7 @@ } } -void WaylandTest::SyncDisplay() { +void WaylandTestBase::SyncDisplay() { ASSERT_EQ(server_mode_, TestServerMode::kAsync); DCHECK(initialized_); base::RunLoop run_loop; @@ -252,7 +254,7 @@ run_loop.Run(); } -void WaylandTest::MaybeSetUpXkb() { +void WaylandTestBase::MaybeSetUpXkb() { #if BUILDFLAG(USE_XKBCOMMON) PostToServerAndWait([](wl::TestWaylandServerThread* server) { // Set up XKB bits and set the keymap to the client. @@ -290,4 +292,48 @@ #endif } +std::unique_ptr<WaylandWindow> WaylandTestBase::CreateWaylandWindowWithParams( + PlatformWindowType type, + const gfx::Rect bounds, + MockWaylandPlatformWindowDelegate* delegate, + gfx::AcceleratedWidget parent_widget) { + PlatformWindowInitProperties properties; + properties.bounds = bounds; + properties.type = type; + properties.parent_widget = parent_widget; + + auto window = delegate->CreateWaylandWindow( + connection_.get(), std::move(properties), true, true); + if (window) + window->Show(false); + return window; +} + +WaylandTest::WaylandTest(WaylandTestBase::TestServerMode server_mode) + : WaylandTestBase(GetParam(), server_mode) {} + +WaylandTest::~WaylandTest() = default; + +void WaylandTest::SetUp() { + WaylandTestBase::SetUp(); +} + +void WaylandTest::TearDown() { + WaylandTestBase::TearDown(); +} + +WaylandTestSimple::WaylandTestSimple( + WaylandTestBase::TestServerMode server_mode) + : WaylandTestBase({}, server_mode) {} + +WaylandTestSimple::~WaylandTestSimple() = default; + +void WaylandTestSimple::SetUp() { + WaylandTestBase::SetUp(); +} + +void WaylandTestSimple::TearDown() { + WaylandTestBase::TearDown(); +} + } // namespace ui
diff --git a/ui/ozone/platform/wayland/test/wayland_test.h b/ui/ozone/platform/wayland/test/wayland_test.h index fed9a7d..ed24458 100644 --- a/ui/ozone/platform/wayland/test/wayland_test.h +++ b/ui/ozone/platform/wayland/test/wayland_test.h
@@ -40,7 +40,7 @@ // WaylandTest is a base class that sets up a display, window, and test server, // and allows easy synchronization between them. -class WaylandTest : public ::testing::TestWithParam<wl::ServerConfig> { +class WaylandTestBase { public: // Specifies how the server should run. // TODO(crbug.com/1365887): this must be removed once all tests switch to @@ -54,15 +54,13 @@ kSync }; - explicit WaylandTest(TestServerMode server_mode = TestServerMode::kSync); + WaylandTestBase(wl::ServerConfig config, TestServerMode server_mode); + WaylandTestBase(const WaylandTestBase&) = delete; + WaylandTestBase& operator=(const WaylandTestBase&) = delete; + ~WaylandTestBase(); - WaylandTest(const WaylandTest&) = delete; - WaylandTest& operator=(const WaylandTest&) = delete; - - ~WaylandTest() override; - - void SetUp() override; - void TearDown() override; + void SetUp(); + void TearDown(); void Sync(); @@ -125,6 +123,13 @@ // Does nothing if XkbCommon is not used. void MaybeSetUpXkb(); + // Creates a Wayland window with the specified delegate, type, and bounds. + std::unique_ptr<WaylandWindow> CreateWaylandWindowWithParams( + PlatformWindowType type, + const gfx::Rect bounds, + MockWaylandPlatformWindowDelegate* delegate, + gfx::AcceleratedWidget parent_widget = gfx::kNullAcceleratedWidget); + base::test::TaskEnvironment task_environment_; wl::TestWaylandServerThread server_; @@ -154,6 +159,33 @@ // The server will be set to asynchronous mode once started. const TestServerMode server_mode_; + const wl::ServerConfig config_; +}; + +// Version of WaylandTestBase that uses parametrised tests (TEST_P). +class WaylandTest : public WaylandTestBase, + public ::testing::TestWithParam<wl::ServerConfig> { + public: + explicit WaylandTest(TestServerMode server_mode = TestServerMode::kSync); + WaylandTest(const WaylandTest&) = delete; + WaylandTest& operator=(const WaylandTest&) = delete; + ~WaylandTest() override; + + void SetUp() override; + void TearDown() override; +}; + +// Version of WaylandTest that uses simple test fixtures (TEST_F). +class WaylandTestSimple : public WaylandTestBase, public ::testing::Test { + public: + explicit WaylandTestSimple(WaylandTestBase::TestServerMode server_mode = + WaylandTestBase::TestServerMode::kAsync); + WaylandTestSimple(const WaylandTestSimple&) = delete; + WaylandTestSimple& operator=(const WaylandTestSimple&) = delete; + ~WaylandTestSimple() override; + + void SetUp() override; + void TearDown() override; }; } // namespace ui